From 544d618f878ac56762d729b5cf322c1eaac80029 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=CE=9ET=CE=9ERNAL?= Date: Tue, 23 Dec 2025 17:09:18 +0530 Subject: [PATCH] Major Update! This features a new bypass, new theme, etc --- .gitignore | 12 +- app/build.gradle.kts | 140 +- .../libs/ManifestEditor-1.0.2.jar | Bin {manager => app}/libs/apkzlib.jar | Bin app/proguard-rules.pro | 6 +- app/src/main/AndroidManifest.xml | 14 +- app/src/main/assets/lspatch/dexes/loader.dex | Bin 0 -> 1208924 bytes .../main/assets/lspatch/dexes/metaloader.dex | Bin 0 -> 11196 bytes .../src/main/assets/lspatch/keystore.jks | Bin .../assets/lspatch/so/arm64-v8a/liblspatch.so | Bin 0 -> 473496 bytes .../lspatch/so/armeabi-v7a/liblspatch.so | Bin 0 -> 319144 bytes app/src/main/assets/lspatch/version.txt | 1 + .../purrfectsnap}/LogManager.kt | 63 +- .../purrfectsnap}/RemoteAccountStorage.kt | 6 +- .../purrfectsnap}/RemoteFileHandleManager.kt | 17 +- .../purrfectsnap}/RemoteLocationManager.kt | 6 +- .../purrfectsnap}/RemoteSideContext.kt | 72 +- .../purrfectsnap}/RemoteTracker.kt | 20 +- .../purrfectsnap}/SharedContextHolder.kt | 2 +- .../purrfectsnap}/StreaksReminder.kt | 12 +- .../purrfectsnap}/action/EnumQuickActions.kt | 4 +- .../bridge/BiometricPromptActivity.kt | 4 +- .../purrfectsnap}/bridge/BridgeService.kt | 32 +- .../bridge/ForceStartActivity.kt | 6 +- .../download/DownloadProcessor.kt | 110 +- .../purrfectsnap}/download/FFMpegProcessor.kt | 14 +- .../purrfectsnap}/e2ee/E2EEImplementation.kt | 18 +- .../scripting/AutoReloadHandler.kt | 2 +- .../scripting/RemoteScriptManager.kt | 36 +- .../scripting/impl/ManagerIPC.kt | 8 +- .../scripting/impl/ManagerScriptConfig.kt | 6 +- .../security/AppIntegrityVerifier.kt | 10 + .../purrfectsnap/security/KeystoreAesGcm.kt | 60 + .../purrfectsnap/security/SecurityAbort.kt | 12 + .../security/SigningCertSha256.kt | 31 + .../purrfectsnap/setup/patch/APKMirror.kt | 97 + .../setup/patch}/ApkSignatureHelper.kt | 42 +- .../setup/patch/AutoPatchServer.kt | 62 + .../purrfectsnap/setup/patch/Constants.kt | 7 + .../purrfectsnap/setup/patch}/DexLibExt.kt | 28 +- .../purrfectsnap/setup}/patch/LSPatch.kt | 149 +- .../setup/patch/LSPatchObfuscation.kt | 62 + .../purrfectsnap/setup/patch}/PatchConfig.kt | 4 +- .../purrfectsnap}/storage/AppDatabase.kt | 12 +- .../purrfectsnap}/storage/Location.kt | 10 +- .../purrfectsnap}/storage/Messaging.kt | 18 +- .../purrfectsnap}/storage/QuickTiles.kt | 4 +- .../purrfectsnap}/storage/Repositories.kt | 5 +- .../purrfectsnap}/storage/ScopeNotes.kt | 2 +- .../purrfectsnap}/storage/Scripting.kt | 2 +- .../purrfectsnap}/storage/Tracker.kt | 28 +- .../storage/TrackerDataManagerImpl.kt | 14 +- .../purrfectsnap}/task/PendingTask.kt | 7 +- .../purrfectsnap/task/RemoteTaskInterface.kt | 66 + .../purrfectsnap}/task/TaskManager.kt | 10 +- .../purrfectsnap}/task/UpdateCheckWorker.kt | 14 +- .../purrfectsnap}/ui/manager/MainActivity.kt | 130 +- .../purrfectsnap/ui/manager/Navigation.kt | 808 ++++ .../purrfectsnap}/ui/manager/Routes.kt | 87 +- .../ui/manager/components/AestheticDialog.kt | 173 + .../manager/components/AestheticEmptyState.kt | 92 + .../ui/manager/components/FloatingTopBar.kt | 126 + .../ui/manager/data/InstallationSummary.kt | 2 +- .../ui/manager/data/UpdateDownloader.kt | 21 +- .../purrfectsnap}/ui/manager/data/Updater.kt | 6 +- .../ui/manager/pages/FileImportsRoot.kt | 285 ++ .../ui/manager/pages/LoggerHistoryRoot.kt | 516 +++ .../ui/manager/pages/ManageReposSection.kt | 20 +- .../ui/manager/pages/TasksRootSection.kt | 1045 +++++ .../manager/pages/features/CallbackAlias.kt | 2 +- .../features/ConfigExportSummaryScreen.kt | 381 ++ .../ConfigImportConfirmationScreen.kt | 417 ++ .../pages/features/FeaturesRootSection.kt | 1637 ++++++++ .../pages/features/ManageRuleFeature.kt | 402 ++ .../ui/manager/pages/home/HomeLogs.kt | 565 +++ .../ui/manager/pages/home/HomeRootSection.kt | 1127 ++++++ .../ui/manager/pages/home/HomeSettings.kt | 755 ++++ .../manager/pages/home/QuickActionsDialog.kt | 206 + .../pages/location/AddCoordinatesDialog.kt | 8 +- .../pages/location/BetterLocationRoot.kt | 431 ++- .../scripting/ManageScriptReposSection.kt | 409 ++ .../manager/pages/scripting/ScriptCatalog.kt | 198 +- .../ui/manager/pages/scripting/ScriptRepos.md | 0 .../pages/scripting/ScriptingRootSection.kt | 945 +++++ .../manager/pages/social/AddFriendDialog.kt | 370 ++ .../ui/manager/pages/social/LoggedStories.kt | 26 +- .../ui/manager/pages/social/ManageScope.kt | 246 +- .../manager/pages/social/MessagingPreview.kt | 960 +++++ .../manager/pages/social/SocialRootSection.kt | 562 +++ .../ui/manager/pages/tracker/EditRule.kt | 781 ++++ .../pages/tracker/FriendTrackerCatalog.kt | 223 +- .../FriendTrackerConfigExportScreen.kt | 63 +- .../FriendTrackerConfigImportScreen.kt | 6 +- .../pages/tracker/FriendTrackerManagerRoot.kt | 907 +++++ .../pages/tracker/FriendTrackerRepos.md | 4 +- .../ui/manager/pages/tracker/LogsTab.kt | 808 ++++ .../ManageFriendTrackerReposSection.kt | 400 ++ .../pages/tracker/TrackerConfigParser.kt | 6 +- .../ui/manager/theme/PurrfectPalette.kt | 39 + .../purrfectsnap}/ui/overlay/RemoteOverlay.kt | 64 +- .../purrfectsnap}/ui/setup/Requirements.kt | 2 +- .../purrfectsnap/ui/setup/SetupActivity.kt | 801 ++++ .../ui/setup/screens/SetupScreen.kt | 130 + .../setup/screens/impl/InstallModeScreen.kt | 206 + .../ui/setup/screens/impl/MappingsScreen.kt | 85 +- .../setup/screens/impl/PatchSnapchatScreen.kt | 584 +++ .../setup/screens/impl/PermissionsScreen.kt | 317 ++ .../setup/screens/impl/PickLanguageScreen.kt | 266 ++ .../ui/setup/screens/impl/SaveFolderScreen.kt | 241 ++ .../purrfectsnap}/ui/util/Accompagnist.kt | 2 +- .../ui/util/ActivityLauncherHelper.kt | 64 +- .../purrfectsnap/ui/util/AlertDialogs.kt | 1404 +++++++ .../ui/util/AndroidDialogCustom.kt | 2 +- .../purrfectsnap}/ui/util/Animations.kt | 2 +- .../purrfectsnap}/ui/util/ColorPicker.kt | 2 +- .../purrfectsnap/ui/util/GlobalDialogs.kt | 25 + .../purrfectsnap}/ui/util/LifecycleHelper.kt | 2 +- .../ui/util/ObservableMutableState.kt | 2 +- .../purrfectsnap/ui/util/PurrfectSwitch.kt | 21 + .../ui/util/coil/CoilPreviewDecoder.kt | 14 +- .../ui/util/coil/ComposeImageHelper.kt | 8 +- .../ui/util/pullrefresh/PullRefresh.kt | 2 +- .../util/pullrefresh/PullRefreshIndicator.kt | 2 +- .../PullRefreshIndicatorTransform.kt | 2 +- .../ui/util/pullrefresh/PullRefreshState.kt | 2 +- .../snapenhance/ui/manager/Navigation.kt | 580 --- .../ui/manager/components/AestheticDialog.kt | 83 - .../ui/manager/pages/FileImportsRoot.kt | 156 - .../ui/manager/pages/LoggerHistoryRoot.kt | 415 -- .../ui/manager/pages/TasksRootSection.kt | 519 --- .../features/ConfigExportSummaryScreen.kt | 244 -- .../ConfigImportConfirmationScreen.kt | 331 -- .../pages/features/FeaturesRootSection.kt | 758 ---- .../pages/features/ManageRuleFeature.kt | 231 -- .../ui/manager/pages/home/HomeLogs.kt | 250 -- .../ui/manager/pages/home/HomeRootSection.kt | 849 ---- .../ui/manager/pages/home/HomeSettings.kt | 594 --- .../manager/pages/home/QuickActionsDialog.kt | 103 - .../scripting/ManageScriptReposSection.kt | 247 -- .../pages/scripting/ScriptingRootSection.kt | 616 --- .../manager/pages/social/AddFriendDialog.kt | 299 -- .../manager/pages/social/MessagingPreview.kt | 535 --- .../manager/pages/social/SocialRootSection.kt | 297 -- .../ui/manager/pages/tracker/EditRule.kt | 562 --- .../pages/tracker/FriendTrackerManagerRoot.kt | 503 --- .../ui/manager/pages/tracker/LogsTab.kt | 601 --- .../ManageFriendTrackerReposSection.kt | 239 -- .../snapenhance/ui/setup/SetupActivity.kt | 192 - .../ui/setup/screens/SetupScreen.kt | 35 - .../setup/screens/impl/PermissionsScreen.kt | 201 - .../setup/screens/impl/PickLanguageScreen.kt | 148 - .../ui/setup/screens/impl/SaveFolderScreen.kt | 40 - .../rhunk/snapenhance/ui/util/AlertDialogs.kt | 705 ---- app/src/main/res/drawable/howtomen_logo.jpg | Bin 0 -> 11102 bytes .../res/mipmap-anydpi-v26/ic_launcher.xml | 5 + .../mipmap-anydpi-v26/ic_launcher_round.xml | 5 + .../res/mipmap-anydpi-v26/launcher_icon.xml | 5 - .../mipmap-anydpi-v26/launcher_icon_round.xml | 5 - app/src/main/res/mipmap-hdpi/ic_launcher.png | Bin 6624 -> 8691 bytes .../mipmap-hdpi/ic_launcher_foreground.png | Bin 0 -> 26759 bytes .../mipmap-hdpi/ic_launcher_monochrome.png | Bin 0 -> 33344 bytes .../res/mipmap-hdpi/ic_launcher_round.png | Bin 0 -> 10478 bytes .../mipmap-hdpi/launcher_icon_foreground.png | Bin 21795 -> 0 bytes .../res/mipmap-hdpi/launcher_icon_round.png | Bin 8597 -> 0 bytes app/src/main/res/mipmap-ldpi/ic_launcher.png | Bin 0 -> 2513 bytes .../res/mipmap-ldpi/ic_launcher_round.png | Bin 0 -> 3111 bytes app/src/main/res/mipmap-mdpi/ic_launcher.png | Bin 0 -> 4215 bytes .../mipmap-mdpi/ic_launcher_foreground.png | Bin 0 -> 12896 bytes .../mipmap-mdpi/ic_launcher_monochrome.png | Bin 0 -> 15698 bytes .../res/mipmap-mdpi/ic_launcher_round.png | Bin 0 -> 5144 bytes .../main/res/mipmap-mdpi/launcher_icon.png | Bin 3476 -> 0 bytes .../mipmap-mdpi/launcher_icon_foreground.png | Bin 10861 -> 0 bytes .../res/mipmap-mdpi/launcher_icon_round.png | Bin 4603 -> 0 bytes app/src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 0 -> 14474 bytes .../mipmap-xhdpi/ic_launcher_foreground.png | Bin 0 -> 44388 bytes .../mipmap-xhdpi/ic_launcher_monochrome.png | Bin 0 -> 54009 bytes .../res/mipmap-xhdpi/ic_launcher_round.png | Bin 0 -> 17669 bytes .../main/res/mipmap-xhdpi/launcher_icon.png | Bin 9548 -> 0 bytes .../mipmap-xhdpi/launcher_icon_foreground.png | Bin 30846 -> 0 bytes .../res/mipmap-xhdpi/launcher_icon_round.png | Bin 12209 -> 0 bytes .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin 0 -> 29777 bytes .../mipmap-xxhdpi/ic_launcher_foreground.png | Bin 0 -> 92076 bytes .../mipmap-xxhdpi/ic_launcher_monochrome.png | Bin 0 -> 104991 bytes .../res/mipmap-xxhdpi/ic_launcher_round.png | Bin 0 -> 35778 bytes .../main/res/mipmap-xxhdpi/launcher_icon.png | Bin 19043 -> 0 bytes .../launcher_icon_foreground.png | Bin 72083 -> 0 bytes .../res/mipmap-xxhdpi/launcher_icon_round.png | Bin 23520 -> 0 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin 0 -> 49645 bytes .../mipmap-xxxhdpi/ic_launcher_foreground.png | Bin 0 -> 153606 bytes .../mipmap-xxxhdpi/ic_launcher_monochrome.png | Bin 0 -> 165585 bytes .../res/mipmap-xxxhdpi/ic_launcher_round.png | Bin 0 -> 60148 bytes .../main/res/mipmap-xxxhdpi/launcher_icon.png | Bin 28575 -> 0 bytes .../launcher_icon_foreground.png | Bin 117897 -> 0 bytes .../mipmap-xxxhdpi/launcher_icon_round.png | Bin 34381 -> 0 bytes .../res/values/ic_launcher_background.xml | 4 +- .../res/values/launcher_icon_background.xml | 4 + build-wsl.sh | 89 + build.gradle.kts | 10 +- common/build.gradle.kts | 3 +- .../purrfectsnap}/bridge/AccountStorage.aidl | 2 +- .../purrfectsnap}/bridge/BridgeInterface.aidl | 31 +- .../bridge/ConfigStateListener.aidl | 2 +- .../bridge/DownloadCallback.aidl | 2 +- .../purrfectsnap}/bridge/SyncCallback.aidl | 2 +- .../bridge/e2ee/E2eeInterface.aidl | 4 +- .../bridge/e2ee/EncryptionResult.aidl | 2 +- .../bridge/location/FriendLocation.aidl | 2 +- .../bridge/location/LocationCoordinates.aidl | 2 +- .../bridge/location/LocationManager.aidl | 7 + .../bridge/logger/BridgeLoggedMessage.aidl | 2 +- .../bridge/logger/LoggedChatEdit.aidl | 2 +- .../bridge/logger/LoggerInterface.aidl | 6 +- .../bridge/logger/TrackerInterface.aidl | 2 +- .../bridge/scripting/AutoReloadListener.aidl | 2 +- .../bridge/scripting/IPCListener.aidl | 2 +- .../bridge/scripting/IScripting.aidl | 6 +- .../bridge/snapclient/MessagingBridge.aidl | 6 +- .../snapclient/SessionStartListener.aidl | 2 +- .../bridge/snapclient/types/Message.aidl | 2 +- .../bridge/storage/FileHandle.aidl | 2 +- .../bridge/storage/FileHandleManager.aidl | 7 + .../bridge/task/TaskInterface.aidl | 14 + .../bridge/task/TaskListener.aidl | 9 + .../bridge/location/LocationManager.aidl | 7 - .../bridge/storage/FileHandleManager.aidl | 7 - common/src/main/assets/lang/ar.json | 2022 ---------- common/src/main/assets/lang/ar_AE.json | 2487 ++++++++++++ common/src/main/assets/lang/bn.json | 3399 +++++++---------- common/src/main/assets/lang/cs.json | 2022 ---------- common/src/main/assets/lang/da.json | 2440 +++++------- common/src/main/assets/lang/de_DE.json | 2426 +++++------- common/src/main/assets/lang/el.json | 2022 ---------- common/src/main/assets/lang/en_UK.json | 1559 ++++++++ common/src/main/assets/lang/en_US.json | 1927 ++++++++-- common/src/main/assets/lang/es_ES.json | 1656 ++++++++ common/src/main/assets/lang/fi.json | 2042 +++------- common/src/main/assets/lang/fr_FR.json | 2470 ++++++------ common/src/main/assets/lang/gsw.json | 441 +++ common/src/main/assets/lang/gu_IN.json | 2020 +--------- common/src/main/assets/lang/gwi.json | 1389 +++++++ common/src/main/assets/lang/hi_IN.json | 2172 ++--------- common/src/main/assets/lang/hr_HR.json | 71 + common/src/main/assets/lang/hu_HU.json | 1517 ++++++++ common/src/main/assets/lang/id.json | 2203 ++--------- common/src/main/assets/lang/it_IT.json | 2075 +--------- common/src/main/assets/lang/ja.json | 2022 ---------- common/src/main/assets/lang/ja_JP.json | 29 + common/src/main/assets/lang/kn.json | 2022 ---------- common/src/main/assets/lang/ko_KR.json | 2021 +--------- common/src/main/assets/lang/la.json | 2063 +--------- common/src/main/assets/lang/lv_LV.json | 44 + common/src/main/assets/lang/ml_IN.json | 937 +++++ common/src/main/assets/lang/mr.json | 2022 ---------- common/src/main/assets/lang/ms.json | 2022 ---------- common/src/main/assets/lang/nb_NO.json | 211 + common/src/main/assets/lang/nl.json | 2087 ++-------- common/src/main/assets/lang/no.json | 2022 ---------- common/src/main/assets/lang/or.json | 1826 --------- common/src/main/assets/lang/pa.json | 2016 ---------- common/src/main/assets/lang/pl.json | 2160 +---------- common/src/main/assets/lang/pt.json | 2025 +--------- common/src/main/assets/lang/ro.json | 2685 +++++-------- common/src/main/assets/lang/ru.json | 2735 +++++-------- common/src/main/assets/lang/sl_SI.json | 87 + common/src/main/assets/lang/sv.json | 839 ++++ common/src/main/assets/lang/sw.json | 2022 ---------- common/src/main/assets/lang/swg.json | 1 + common/src/main/assets/lang/ta_IN.json | 1705 +++++++++ common/src/main/assets/lang/te.json | 2022 ---------- common/src/main/assets/lang/th.json | 2022 ---------- common/src/main/assets/lang/tr_TR.json | 1658 ++++++++ common/src/main/assets/lang/uk_UA.json | 1732 +++++++++ common/src/main/assets/lang/ur.json | 2022 ---------- common/src/main/assets/lang/vi.json | 2022 ---------- common/src/main/assets/lang/wep.json | 1389 +++++++ common/src/main/assets/lang/zh_CN.json | 2026 ---------- .../src/main/assets/lang/zh_SIMPLIFIED.json | 416 ++ .../purrfectsnap}/common/Constants.kt | 2 +- .../purrfectsnap}/common/ReceiversConfig.kt | 4 +- .../purrfectsnap}/common/action/EnumAction.kt | 2 +- .../common/bridge/BridgeFiles.kt | 12 +- .../common/bridge/InternalFileWrapper.kt | 8 +- .../common/bridge/wrapper/LocaleWrapper.kt | 18 +- .../common/bridge/wrapper/LoggerWrapper.kt | 28 +- .../common/bridge/wrapper/MappingsWrapper.kt | 22 +- .../common/config/ConfigConstants.kt | 2 +- .../common/config/ConfigContainer.kt | 8 +- .../common/config/ConfigObjects.kt | 5 +- .../common/config/DataProcessors.kt | 2 +- .../purrfectsnap}/common/config/ModConfig.kt | 18 +- .../common/config/impl/Camera.kt | 8 +- .../common/config/impl/DownloaderConfig.kt | 8 +- .../common/config/impl/Experimental.kt | 13 +- .../common/config/impl/FriendTrackerConfig.kt | 10 +- .../common/config/impl/Global.kt | 9 +- .../common/config/impl/MessagingTweaks.kt | 288 ++ .../common/config/impl/RootConfig.kt | 6 +- .../purrfectsnap}/common/config/impl/Rules.kt | 10 +- .../common/config/impl/Scripting.kt | 6 +- .../purrfectsnap/common/config/impl/Spoof.kt | 26 + .../config/impl/StreaksReminderConfig.kt | 4 +- .../common/config/impl/UserInterfaceTweaks.kt | 10 +- .../purrfectsnap}/common/data/ExportType.kt | 2 +- .../common/data/ExportedTrackerData.kt | 4 +- .../purrfectsnap}/common/data/FileType.kt | 2 +- .../common/data/MessagingCoreObjects.kt | 22 +- .../common/data/SessionEventsData.kt | 4 +- .../purrfectsnap}/common/data/SnapEnums.kt | 25 +- .../common/data/ThemingObjects.kt | 2 +- .../common/data/TrackerDataManager.kt | 4 +- .../common/data/download/DownloadMediaType.kt | 2 +- .../common/data/download/DownloadMetadata.kt | 2 +- .../common/data/download/DownloadRequest.kt | 4 +- .../common/data/download/DownloadStage.kt | 2 +- .../data/download/MediaDownloadSource.kt | 4 +- .../data/download/MediaEncryptionKeyPair.kt | 2 +- .../data/download/SplitMediaAssetType.kt | 2 +- .../common/database/DatabaseObject.kt | 2 +- .../database/impl/ConversationMessage.kt | 14 +- .../common/database/impl/FriendFeedEntry.kt | 12 +- .../common/database/impl/FriendInfo.kt | 12 +- .../common/database/impl/StoryEntry.kt | 8 +- .../common/database/impl/StorySnapEntry.kt | 6 +- .../database/impl/UserConversationLink.kt | 8 +- .../common/logger/AbstractLogger.kt | 6 +- .../purrfectsnap}/common/logger/LogChannel.kt | 10 +- .../purrfectsnap}/common/logger/LogLevel.kt | 2 +- .../common/messaging/MessagingTask.kt | 8 +- .../common/scripting/JSModule.kt | 26 +- .../common/scripting/PrimitiveUtil.kt | 2 +- .../common/scripting/ScriptRuntime.kt | 14 +- .../common/scripting/ScriptingLogger.kt | 6 +- .../scripting/bindings/AbstractBinding.kt | 2 +- .../common/scripting/bindings/BindingSide.kt | 2 +- .../scripting/bindings/BindingsContext.kt | 11 + .../common/scripting/impl/ConfigInterface.kt | 6 +- .../common/scripting/impl/IPCInterface.kt | 6 +- .../common/scripting/impl/JavaInterfaces.kt | 12 +- .../common/scripting/impl/Networking.kt | 8 +- .../common/scripting/impl/Protobuf.kt | 12 +- .../common/scripting/ktx/RhinoKtx.kt | 2 +- .../common/scripting/type/ModuleInfo.kt | 2 +- .../common/scripting/type/Permissions.kt | 2 +- .../scripting/ui/EnumScriptInterface.kt | 4 +- .../common/scripting/ui/InterfaceManager.kt | 24 +- .../common/scripting/ui/ScriptInterface.kt | 12 +- .../common/scripting/ui/components/Node.kt | 2 +- .../scripting/ui/components/NodeType.kt | 2 +- .../ui/components/impl/ActionNode.kt | 15 + .../ui/components/impl/RowColumnNode.kt | 6 +- .../ui/components/impl/TextInputNode.kt | 6 +- .../common/ui/AsyncMutableState.kt | 2 +- .../purrfectsnap}/common/ui/Components.kt | 6 +- .../common/ui/ComposeViewFactory.kt | 12 +- .../purrfectsnap}/common/ui/Keyboard.kt | 2 +- .../purrfectsnap}/common/ui/OverlayType.kt | 2 +- .../common/ui/TextFieldColors.kt | 2 +- .../purrfectsnap}/common/ui/Theme.kt | 2 +- .../common/ui/ThemeChooserDialog.kt | 2 +- .../purrfectsnap}/common/ui/ThemeMode.kt | 2 +- .../common/ui/ThemePreferences.kt | 2 +- .../purrfectsnap}/common/util/LazyBridge.kt | 2 +- .../common/util/ParcelableExt.kt | 2 +- .../purrfectsnap}/common/util/Purge.kt | 2 +- .../common/util/SQLiteDatabaseHelper.kt | 6 +- .../util/ktx/AndroidCompatExtensions.kt | 2 +- .../common/util/ktx/DbCursorExt.kt | 2 +- .../purrfectsnap}/common/util/ktx/JavaExt.kt | 2 +- .../purrfectsnap}/common/util/ktx/OkHttp.kt | 2 +- .../common/util/protobuf/GrpcReader.kt | 2 +- .../common/util/protobuf/GrpcWriter.kt | 2 +- .../common/util/protobuf/ProtoEditor.kt | 2 +- .../common/util/protobuf/ProtoReader.kt | 2 +- .../common/util/protobuf/ProtoWriter.kt | 2 +- .../common/util/protobuf/WireType.kt | 2 +- .../common/util/snap/BitmojiSelfie.kt | 2 +- .../common/util/snap/MediaDownloaderHelper.kt | 6 +- .../common/util/snap/RemoteMediaResolver.kt | 6 +- .../snap/SnapWidgetBroadcastReceiverHelper.kt | 4 +- .../common/config/impl/MessagingTweaks.kt | 104 - .../snapenhance/common/config/impl/Spoof.kt | 10 - .../scripting/bindings/BindingsContext.kt | 11 - .../ui/components/impl/ActionNode.kt | 15 - compare_translations.ipynb | 10 - composer/build.gradle.kts | 16 +- composer/src/main/ts/imports.ts | 19 +- config/config.json | 23 + core/build.gradle.kts | 7 +- core/src/main/assets/xposed_init | 2 +- .../core/DownloadManagerClient.kt | 10 +- .../purrfectsnap}/core/ModContext.kt | 53 +- .../purrfectsnap/core/PurrfectSnap.kt} | 135 +- .../purrfectsnap}/core/SecurityFeatures.kt | 119 +- .../purrfectsnap}/core/XposedLoader.kt | 14 +- .../core/action/AbstractAction.kt | 4 +- .../core/action/ActionManager.kt | 16 +- .../core/action/impl/BulkMessagingAction.kt | 1392 +++++++ .../core/action/impl/CleanCache.kt | 4 +- .../core/action/impl/ExportChatMessages.kt | 840 ++++ .../core/action/impl/ExportMemories.kt | 823 ++++ .../core/action/impl/ManageFriendList.kt | 685 ++++ .../purrfectsnap}/core/bridge/BridgeClient.kt | 49 +- .../purrfectsnap}/core/data/SnapClassCache.kt | 13 +- .../core/database/DatabaseAccess.kt | 48 +- .../purrfectsnap}/core/event/EventBus.kt | 4 +- .../core/event/EventDispatcher.kt | 60 +- .../core/event/events/AbstractHookEvent.kt | 6 +- .../event/events/impl/ActivityResultEvent.kt | 4 +- .../core/event/events/impl/AddViewEvent.kt | 4 +- .../core/event/events/impl/BindViewEvent.kt | 6 +- .../event/events/impl/BuildMessageEvent.kt | 8 + .../events/impl/ConversationUpdateEvent.kt | 10 + .../event/events/impl/LayoutInflateEvent.kt | 4 +- .../event/events/impl/MediaUploadEvent.kt | 8 +- .../event/events/impl/NativeUnaryCallEvent.kt | 8 + .../events/impl/NetworkApiRequestEvent.kt | 10 +- .../events/impl/OnSnapInteractionEvent.kt | 10 + .../impl/SendMessageWithContentEvent.kt | 12 +- .../impl/SnapWidgetBroadcastReceiveEvent.kt | 4 +- .../core/event/events/impl/UnaryCallEvent.kt | 4 +- .../core/features/BridgeFileFeature.kt | 12 +- .../purrfectsnap}/core/features/Feature.kt | 4 +- .../core/features/FeatureLoadParams.kt | 2 +- .../core/features/FeatureManager.kt | 39 +- .../core/features/MessagingRuleFeature.kt | 9 +- .../core/features/impl/COFOverride.kt | 14 +- .../features/impl/ConfigurationOverride.kt | 16 +- .../purrfectsnap}/core/features/impl/Debug.kt | 6 +- .../features/impl/FriendMutationObserver.kt | 12 +- .../core/features/impl/MixerStories.kt | 12 +- .../impl/OperaViewerParamsOverride.kt | 12 +- .../core/features/impl/ScopeSync.kt | 10 +- .../impl/downloader/MediaDownloader.kt | 71 +- .../downloader/ProfilePictureDownloader.kt | 223 ++ .../impl/downloader/decoder/AttachmentInfo.kt | 4 +- .../impl/downloader/decoder/AttachmentType.kt | 2 +- .../impl/downloader/decoder/MessageDecoder.kt | 16 +- .../impl/experiments/AccountSwitcher.kt | 182 +- .../impl/experiments/AddFriendSourceSpoof.kt | 74 + .../core/features/impl/experiments/AppLock.kt | 24 +- .../impl/experiments/AutoOpenSnaps.kt | 662 ++++ .../impl/experiments/BestFriendPinning.kt | 14 +- .../impl/experiments/BetterLocation.kt | 42 +- .../impl/experiments/BetterTranscript.kt | 20 +- .../features/impl/experiments/CallRecorder.kt | 22 +- .../impl/experiments/ComposerHooks.kt | 35 +- .../impl/experiments/ContextMenuFix.kt | 6 +- .../impl/experiments/ConvertMessageLocally.kt | 20 +- .../impl/experiments/CustomEmojiFont.kt | 53 + .../impl/experiments/DeviceSpooferHook.kt | 447 +++ .../impl/experiments/EndToEndEncryption.kt | 56 +- .../impl/experiments/InfiniteStoryBoost.kt | 10 +- .../impl/experiments/MediaFilePicker.kt | 112 +- .../impl/experiments/MeoPasscodeBypass.kt | 10 +- .../impl/experiments/NoFriendScoreDelay.kt | 10 +- .../impl/experiments/PreventForcedLogout.kt | 8 +- .../impl/experiments/SnapScoreChanges.kt | 18 +- .../global/BypassVideoLengthRestriction.kt | 27 +- .../features/impl/global/DisableCustomTabs.kt | 8 +- .../impl/global/DisableMemoriesSnapFeed.kt | 10 +- .../features/impl/global/DisableMetrics.kt | 10 +- .../impl/global/DisableTelecomFramework.kt | 8 +- .../features/impl/global/EndpointsBlocker.kt | 194 + .../impl/global/GooglePlayServicesDialogs.kt | 8 +- .../impl/global/MediaUploadQualityOverride.kt | 27 +- .../core/features/impl/global/SnapchatPlus.kt | 14 +- .../impl/messaging/AutoDeleteSentMessages.kt | 402 ++ .../features/impl/messaging/AutoMarkAsRead.kt | 28 +- .../core/features/impl/messaging/AutoRead.kt | 92 + .../core/features/impl/messaging/AutoReply.kt | 1092 ++++++ .../core/features/impl/messaging/AutoSave.kt | 31 +- .../BypassMessageActionRestrictions.kt | 6 +- .../impl/messaging/CallButtonsOverride.kt | 18 +- .../impl/messaging/DisableReplayInFF.kt | 12 +- .../impl/messaging/HideTypingIndicator.kt | 12 +- .../impl/messaging/MessageTranslator.kt | 146 + .../core/features/impl/messaging/Messaging.kt | 36 +- .../features/impl/messaging/Notifications.kt | 73 +- .../impl/messaging/PreventMessageSending.kt | 16 +- .../features/impl/messaging/SendOverride.kt | 765 ++++ .../impl/messaging/TranslationManager.kt | 203 + .../features/impl/messaging/TranslationUI.kt | 180 + .../impl/messaging/UnlimitedSnapViewTime.kt | 14 +- .../features/impl/spying/FriendTracker.kt | 209 +- .../features/impl/spying/HalfSwipeNotifier.kt | 29 +- .../features/impl/spying/MessageLogger.kt | 38 +- .../core/features/impl/spying/StealthMode.kt | 17 +- .../impl/tweaks/BypassScreenshotDetection.kt | 8 +- .../core/features/impl/tweaks/CameraTweaks.kt | 10 +- .../impl/tweaks/DisablePermissionRequests.kt | 10 +- .../tweaks/DisableSnapModeRestrictions.kt | 10 +- .../impl/tweaks/DoubleTapChatAction.kt | 24 +- .../features/impl/tweaks/HideActiveMusic.kt | 8 +- .../impl/tweaks/PreventForcedKeyboard.kt | 8 +- .../tweaks/PreventMessageListAutoScroll.kt | 14 +- .../impl/tweaks/RemoveGroupsLockedStatus.kt | 10 +- .../features/impl/tweaks/RequerySqlite.kt | 10 +- .../impl/tweaks/UnsaveableMessages.kt | 130 + .../features/impl/tweaks/VoiceNoteOverride.kt | 30 +- .../impl/ui/ClientBootstrapOverride.kt | 10 +- .../features/impl/ui/ConversationToolbox.kt | 214 ++ .../impl/ui/CustomStreaksExpirationFormat.kt | 16 +- .../core/features/impl/ui/CustomTheming.kt | 86 + .../features/impl/ui/DefaultVolumeControls.kt | 8 +- .../impl/ui/DisableConfirmationDialogs.kt | 14 +- .../core/features/impl/ui/EditTextOverride.kt | 10 +- .../impl/ui/FriendFeedMessagePreview.kt | 36 +- .../core/features/impl/ui/FriendNotes.kt | 20 +- .../features/impl/ui/HideFriendFeedEntry.kt | 20 +- .../features/impl/ui/HideStreakRestore.kt | 20 +- .../features/impl/ui/MessageIndicators.kt | 16 +- .../core/features/impl/ui/OldBitmojiSelfie.kt | 8 +- .../core/features/impl/ui/PinConversations.kt | 22 +- .../core/features/impl/ui/SnapPreview.kt | 28 +- .../impl/ui/SpotlightCommentsUsername.kt | 134 + .../features/impl/ui/StealthModeIndicator.kt | 22 +- .../core/features/impl/ui/UITweaks.kt | 26 +- .../purrfectsnap}/core/logger/CoreLogger.kt | 16 +- .../core/messaging/ConversationExporter.kt | 24 +- .../core/messaging/CoreMessagingBridge.kt | 18 +- .../core/messaging/EnumBulkAction.kt | 2 +- .../core/messaging/ExportFormat.kt | 2 +- .../core/messaging/ExportParams.kt | 4 +- .../core/messaging/MessageSender.kt | 37 +- .../core/scripting/CoreScriptRuntime.kt | 16 +- .../core/scripting/impl/CoreEvents.kt | 14 +- .../core/scripting/impl/CoreIPC.kt | 8 +- .../core/scripting/impl/CoreMessaging.kt | 20 +- .../core/scripting/impl/CoreScriptConfig.kt | 6 +- .../core/scripting/impl/CoreScriptHooker.kt | 20 +- .../purrfectsnap}/core/ui/ComposeIcons.kt | 2 +- .../purrfectsnap}/core/ui/DebugComponents.kt | 2 +- .../purrfectsnap/core/ui/InAppOverlay.kt | 373 ++ .../core/ui/PurrfectOverlayTheme.kt | 181 + .../purrfectsnap}/core/ui/UserInterface.kt | 12 +- .../core/ui/ViewAppearanceHelper.kt | 41 +- .../purrfectsnap}/core/ui/ViewTagState.kt | 2 +- .../core/ui/menu/AbstractMenu.kt | 6 +- .../core/ui/menu/MenuViewInjector.kt | 14 +- .../core/ui/menu/impl/ChatActionMenu.kt | 28 +- .../core/ui/menu/impl/FriendFeedInfoMenu.kt | 796 ++++ .../core/ui/menu/impl/NewChatActionMenu.kt | 77 +- .../ui/menu/impl/OperaContextActionMenu.kt | 22 +- .../core/ui/menu/impl/OperaViewerIcons.kt | 20 +- .../core/ui/menu/impl/SettingsGearInjector.kt | 12 +- .../core/ui/menu/impl/SettingsMenu.kt | 14 +- .../core/util/CallbackBuilder.kt | 8 +- .../core/util/DataClassBuilder.kt | 2 +- .../purrfectsnap}/core/util/EvictingMap.kt | 2 +- .../purrfectsnap}/core/util/LSPatchUpdater.kt | 8 +- .../purrfectsnap}/core/util/RandomWalking.kt | 2 +- .../core/util/hook/HookAdapter.kt | 2 +- .../purrfectsnap}/core/util/hook/HookStage.kt | 2 +- .../purrfectsnap}/core/util/hook/Hooker.kt | 4 +- .../purrfectsnap}/core/util/ktx/AndroidExt.kt | 6 +- .../core/util/ktx/FileHandleManagerKtx.kt | 10 +- .../core/util/ktx/XposedHelperExt.kt | 2 +- .../core/util/media/HttpServer.kt | 4 +- .../core/util/media/PreviewUtils.kt | 4 +- .../core/wrapper/AbstractWrapper.kt | 6 +- .../core/wrapper/impl/ConversationManager.kt | 18 +- .../core/wrapper/impl/Message.kt | 45 +- .../core/wrapper/impl/MessageContent.kt | 6 +- .../core/wrapper/impl/MessageDescriptor.kt | 4 +- .../core/wrapper/impl/MessageDestinations.kt | 7 +- .../core/wrapper/impl/MessageMetadata.kt | 6 +- .../core/wrapper/impl/QuotedMessage.kt | 6 +- .../core/wrapper/impl/QuotedMessageContent.kt | 4 +- .../purrfectsnap}/core/wrapper/impl/ScSize.kt | 4 +- .../core/wrapper/impl/SnapUUID.kt | 16 +- .../core/wrapper/impl/Snapchatter.kt | 4 +- .../core/wrapper/impl/UserIdToReaction.kt | 8 +- .../wrapper/impl/composer/ComposerContext.kt | 13 +- .../impl/composer/ComposerMarshaller.kt | 4 +- .../wrapper/impl/composer/ComposerViewNode.kt | 62 + .../wrapper/impl/media/EncryptionWrapper.kt | 6 +- .../core/wrapper/impl/media/MediaInfo.kt | 6 +- .../media/dash/LongformVideoPlaylistItem.kt | 4 +- .../wrapper/impl/media/dash/SnapChapter.kt | 4 +- .../impl/media/dash/SnapPlaylistItem.kt | 4 +- .../core/wrapper/impl/media/opera/Layer.kt | 6 +- .../core/wrapper/impl/media/opera/ParamMap.kt | 8 +- .../core/action/impl/BulkMessagingAction.kt | 650 ---- .../core/action/impl/ExportChatMessages.kt | 425 --- .../core/action/impl/ExportMemories.kt | 387 -- .../core/action/impl/ManageFriendList.kt | 268 -- .../event/events/impl/BuildMessageEvent.kt | 8 - .../events/impl/ConversationUpdateEvent.kt | 10 - .../event/events/impl/NativeUnaryCallEvent.kt | 8 - .../events/impl/OnSnapInteractionEvent.kt | 10 - .../downloader/ProfilePictureDownloader.kt | 71 - .../impl/experiments/AddFriendSourceSpoof.kt | 72 - .../impl/experiments/AutoOpenSnaps.kt | 121 - .../impl/experiments/CustomEmojiFont.kt | 29 - .../impl/experiments/DeviceSpooferHook.kt | 57 - .../features/impl/messaging/SendOverride.kt | 379 -- .../impl/tweaks/UnsaveableMessages.kt | 44 - .../features/impl/ui/ConversationToolbox.kt | 172 - .../core/features/impl/ui/CustomTheming.kt | 42 - .../impl/ui/SpotlightCommentsUsername.kt | 59 - .../rhunk/snapenhance/core/ui/InAppOverlay.kt | 294 -- .../core/ui/menu/impl/FriendFeedInfoMenu.kt | 595 --- .../wrapper/impl/composer/ComposerViewNode.kt | 58 - gradle.properties | 10 +- logo.png | Bin 194897 -> 0 bytes manager/.gitignore | 1 - manager/build.gradle.kts | 86 - manager/proguard-rules.pro | 5 - manager/src/main/AndroidManifest.xml | 37 - .../src/main/assets/lspatch/dexes/loader.dex | Bin 1083544 -> 0 bytes .../main/assets/lspatch/dexes/metaloader.dex | Bin 10392 -> 0 bytes .../assets/lspatch/so/arm64-v8a/liblspatch.so | Bin 219456 -> 0 bytes .../lspatch/so/armeabi-v7a/liblspatch.so | Bin 168056 -> 0 bytes manager/src/main/assets/lspatch/version.txt | 1 - .../snapenhance/manager/data/APKMirror.kt | 80 - .../snapenhance/manager/data/SharedConfig.kt | 30 - .../manager/data/download/InstallStage.kt | 9 - .../manager/data/download/SEArtifact.kt | 11 - .../manager/data/download/SEVersion.kt | 7 - .../manager/patch/LSPatchObfuscation.kt | 58 - .../snapenhance/manager/patch/Repackager.kt | 89 - .../manager/patch/config/Constants.kt | 7 - .../snapenhance/manager/ui/MainActivity.kt | 81 - .../snapenhance/manager/ui/Navigation.kt | 124 - .../manager/ui/components/Dialogs.kt | 69 - .../rhunk/snapenhance/manager/ui/tab/Tab.kt | 57 - .../manager/ui/tab/impl/HomeTab.kt | 147 - .../manager/ui/tab/impl/SettingsTab.kt | 166 - .../ui/tab/impl/download/InstallPackageTab.kt | 231 -- .../ui/tab/impl/download/LSPatchTab.kt | 230 -- .../ui/tab/impl/download/RepackageTab.kt | 86 - .../ui/tab/impl/download/SEDownloadTab.kt | 262 -- .../ui/tab/impl/download/SnapchatPatchTab.kt | 326 -- manager/src/main/res/drawable/sclogo.xml | 15 - manager/src/main/res/values/themes.xml | 8 - manager/src/main/res/xml/provider_paths.xml | 4 - mapper/build.gradle.kts | 2 +- .../mapper/AbstractClassMapper.kt | 11 +- .../purrfectsnap}/mapper/ClassMapper.kt | 4 +- .../purrfectsnap}/mapper/MapperContext.kt | 2 +- .../purrfectsnap}/mapper/ext/DexClassDef.kt | 2 +- .../purrfectsnap}/mapper/ext/DexMethod.kt | 2 +- .../mapper/impl/BCryptClassMapper.kt | 10 +- .../mapper/impl/COFObservableMapper.kt | 6 +- .../mapper/impl/CallbackMapper.kt | 10 +- .../mapper/impl/ChatEventDispatcherMapper.kt | 6 +- .../CompositeConfigurationProviderMapper.kt | 12 +- .../mapper/impl/DefaultMediaItemMapper.kt | 12 +- .../mapper/impl/FoldingLayoutMapper.kt | 4 +- .../impl/FriendRelationshipChangerMapper.kt | 12 +- .../impl/FriendsFeedEventDispatcherMapper.kt | 10 +- .../impl/MediaQualityLevelProviderMapper.kt | 12 +- .../mapper/impl/MemoriesPresenterMapper.kt | 8 +- .../impl/OperaPageViewControllerMapper.kt | 14 +- .../mapper/impl/OperaViewerParamsMapper.kt | 8 +- .../impl/PlatformClientAttestationMapper.kt | 8 +- .../mapper/impl/PlusSubscriptionMapper.kt | 10 +- .../mapper/impl/ScoreUpdateMapper.kt | 8 +- .../mapper/impl/StoryBoostStateMapper.kt | 8 +- .../mapper/impl/StreaksExpirationMapper.kt | 8 +- .../mapper/impl/ViewBinderMapper.kt | 10 +- .../mapper/tests/TestMappings.kt | 4 +- native/build-native.sh | 297 ++ native/build.gradle.kts | 266 +- native/obfuscation.yml | 18 + native/omvll_config.py | 83 + native/rust/.cargo/config.toml | 7 +- native/rust/Cargo.lock | 608 ++- native/rust/Cargo.toml | 21 +- native/rust/build.rs | 15 +- native/rust/secure/secure_strings.c | 133 + native/rust/secure/secure_strings.h | 10 + native/rust/src/config.rs | 30 +- native/rust/src/lib.rs | 629 ++- native/rust/src/modules/composer_hook.rs | 41 +- native/rust/src/modules/unary_call_hook.rs | 4 +- native/rust/src/secstrings.rs | 47 + native/rust/src/security.rs | 96 + .../purrfectsnap}/nativelib/NativeConfig.kt | 2 +- .../purrfectsnap/nativelib/NativeDecision.kt | 8 + .../purrfectsnap/nativelib/NativeLib.kt | 138 + .../nativelib/NativeRequestData.kt | 2 +- .../rhunk/snapenhance/nativelib/NativeLib.kt | 76 - settings.gradle.kts | 19 +- translation_report.md | 32 - 685 files changed, 63893 insertions(+), 81215 deletions(-) rename {manager => app}/libs/ManifestEditor-1.0.2.jar (100%) rename {manager => app}/libs/apkzlib.jar (100%) create mode 100644 app/src/main/assets/lspatch/dexes/loader.dex create mode 100644 app/src/main/assets/lspatch/dexes/metaloader.dex rename {manager => app}/src/main/assets/lspatch/keystore.jks (100%) create mode 100644 app/src/main/assets/lspatch/so/arm64-v8a/liblspatch.so create mode 100644 app/src/main/assets/lspatch/so/armeabi-v7a/liblspatch.so create mode 100644 app/src/main/assets/lspatch/version.txt rename app/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/LogManager.kt (84%) rename app/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/RemoteAccountStorage.kt (91%) rename app/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/RemoteFileHandleManager.kt (90%) rename app/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/RemoteLocationManager.kt (68%) rename app/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/RemoteSideContext.kt (79%) rename app/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/RemoteTracker.kt (56%) rename app/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/SharedContextHolder.kt (95%) rename app/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/StreaksReminder.kt (94%) rename app/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/action/EnumQuickActions.kt (89%) rename app/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/bridge/BiometricPromptActivity.kt (95%) rename app/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/bridge/BridgeService.kt (92%) rename app/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/bridge/ForceStartActivity.kt (81%) rename app/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/download/DownloadProcessor.kt (83%) rename app/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/download/FFMpegProcessor.kt (96%) rename app/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/e2ee/E2EEImplementation.kt (88%) rename app/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/scripting/AutoReloadHandler.kt (97%) rename app/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/scripting/RemoteScriptManager.kt (89%) rename app/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/scripting/impl/ManagerIPC.kt (89%) rename app/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/scripting/impl/ManagerScriptConfig.kt (90%) create mode 100644 app/src/main/kotlin/me/eternal/purrfectsnap/security/AppIntegrityVerifier.kt create mode 100644 app/src/main/kotlin/me/eternal/purrfectsnap/security/KeystoreAesGcm.kt create mode 100644 app/src/main/kotlin/me/eternal/purrfectsnap/security/SecurityAbort.kt create mode 100644 app/src/main/kotlin/me/eternal/purrfectsnap/security/SigningCertSha256.kt create mode 100644 app/src/main/kotlin/me/eternal/purrfectsnap/setup/patch/APKMirror.kt rename {manager/src/main/kotlin/me/rhunk/snapenhance/manager/patch/util => app/src/main/kotlin/me/eternal/purrfectsnap/setup/patch}/ApkSignatureHelper.kt (83%) create mode 100644 app/src/main/kotlin/me/eternal/purrfectsnap/setup/patch/AutoPatchServer.kt create mode 100644 app/src/main/kotlin/me/eternal/purrfectsnap/setup/patch/Constants.kt rename {manager/src/main/kotlin/me/rhunk/snapenhance/manager/patch/util => app/src/main/kotlin/me/eternal/purrfectsnap/setup/patch}/DexLibExt.kt (69%) rename {manager/src/main/kotlin/me/rhunk/snapenhance/manager => app/src/main/kotlin/me/eternal/purrfectsnap/setup}/patch/LSPatch.kt (60%) create mode 100644 app/src/main/kotlin/me/eternal/purrfectsnap/setup/patch/LSPatchObfuscation.kt rename {manager/src/main/kotlin/me/rhunk/snapenhance/manager/patch/config => app/src/main/kotlin/me/eternal/purrfectsnap/setup/patch}/PatchConfig.kt (91%) rename app/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/storage/AppDatabase.kt (93%) rename app/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/storage/Location.kt (88%) rename app/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/storage/Messaging.kt (93%) rename app/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/storage/QuickTiles.kt (87%) rename app/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/storage/Repositories.kt (90%) rename app/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/storage/ScopeNotes.kt (97%) rename app/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/storage/Scripting.kt (94%) rename app/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/storage/Tracker.kt (92%) rename app/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/storage/TrackerDataManagerImpl.kt (80%) rename app/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/task/PendingTask.kt (96%) create mode 100644 app/src/main/kotlin/me/eternal/purrfectsnap/task/RemoteTaskInterface.kt rename app/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/task/TaskManager.kt (95%) rename app/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/task/UpdateCheckWorker.kt (89%) rename app/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/ui/manager/MainActivity.kt (61%) create mode 100644 app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/Navigation.kt rename app/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/ui/manager/Routes.kt (66%) create mode 100644 app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/components/AestheticDialog.kt create mode 100644 app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/components/AestheticEmptyState.kt create mode 100644 app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/components/FloatingTopBar.kt rename app/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/ui/manager/data/InstallationSummary.kt (93%) rename app/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/ui/manager/data/UpdateDownloader.kt (88%) rename app/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/ui/manager/data/Updater.kt (94%) create mode 100644 app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/FileImportsRoot.kt create mode 100644 app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/LoggerHistoryRoot.kt rename app/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/ui/manager/pages/ManageReposSection.kt (93%) create mode 100644 app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/TasksRootSection.kt rename app/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/ui/manager/pages/features/CallbackAlias.kt (65%) create mode 100644 app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/features/ConfigExportSummaryScreen.kt create mode 100644 app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/features/ConfigImportConfirmationScreen.kt create mode 100644 app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/features/FeaturesRootSection.kt create mode 100644 app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/features/ManageRuleFeature.kt create mode 100644 app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/home/HomeLogs.kt create mode 100644 app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/home/HomeRootSection.kt create mode 100644 app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/home/HomeSettings.kt create mode 100644 app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/home/QuickActionsDialog.kt rename app/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/ui/manager/pages/location/AddCoordinatesDialog.kt (93%) rename app/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/ui/manager/pages/location/BetterLocationRoot.kt (50%) create mode 100644 app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/scripting/ManageScriptReposSection.kt rename app/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/ui/manager/pages/scripting/ScriptCatalog.kt (62%) rename app/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/ui/manager/pages/scripting/ScriptRepos.md (100%) create mode 100644 app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/scripting/ScriptingRootSection.kt create mode 100644 app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/social/AddFriendDialog.kt rename app/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/ui/manager/pages/social/LoggedStories.kt (94%) rename app/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/ui/manager/pages/social/ManageScope.kt (70%) create mode 100644 app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/social/MessagingPreview.kt create mode 100644 app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/social/SocialRootSection.kt create mode 100644 app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/tracker/EditRule.kt rename app/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/ui/manager/pages/tracker/FriendTrackerCatalog.kt (53%) rename app/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/ui/manager/pages/tracker/FriendTrackerConfigExportScreen.kt (74%) rename app/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/ui/manager/pages/tracker/FriendTrackerConfigImportScreen.kt (97%) create mode 100644 app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/tracker/FriendTrackerManagerRoot.kt rename app/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/ui/manager/pages/tracker/FriendTrackerRepos.md (85%) create mode 100644 app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/tracker/LogsTab.kt create mode 100644 app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/tracker/ManageFriendTrackerReposSection.kt rename app/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/ui/manager/pages/tracker/TrackerConfigParser.kt (90%) create mode 100644 app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/theme/PurrfectPalette.kt rename app/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/ui/overlay/RemoteOverlay.kt (61%) rename app/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/ui/setup/Requirements.kt (85%) create mode 100644 app/src/main/kotlin/me/eternal/purrfectsnap/ui/setup/SetupActivity.kt create mode 100644 app/src/main/kotlin/me/eternal/purrfectsnap/ui/setup/screens/SetupScreen.kt create mode 100644 app/src/main/kotlin/me/eternal/purrfectsnap/ui/setup/screens/impl/InstallModeScreen.kt rename app/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/ui/setup/screens/impl/MappingsScreen.kt (52%) create mode 100644 app/src/main/kotlin/me/eternal/purrfectsnap/ui/setup/screens/impl/PatchSnapchatScreen.kt create mode 100644 app/src/main/kotlin/me/eternal/purrfectsnap/ui/setup/screens/impl/PermissionsScreen.kt create mode 100644 app/src/main/kotlin/me/eternal/purrfectsnap/ui/setup/screens/impl/PickLanguageScreen.kt create mode 100644 app/src/main/kotlin/me/eternal/purrfectsnap/ui/setup/screens/impl/SaveFolderScreen.kt rename app/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/ui/util/Accompagnist.kt (98%) rename app/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/ui/util/ActivityLauncherHelper.kt (65%) create mode 100644 app/src/main/kotlin/me/eternal/purrfectsnap/ui/util/AlertDialogs.kt rename app/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/ui/util/AndroidDialogCustom.kt (99%) rename app/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/ui/util/Animations.kt (98%) rename app/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/ui/util/ColorPicker.kt (95%) create mode 100644 app/src/main/kotlin/me/eternal/purrfectsnap/ui/util/GlobalDialogs.kt rename app/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/ui/util/LifecycleHelper.kt (96%) rename app/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/ui/util/ObservableMutableState.kt (92%) create mode 100644 app/src/main/kotlin/me/eternal/purrfectsnap/ui/util/PurrfectSwitch.kt rename app/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/ui/util/coil/CoilPreviewDecoder.kt (82%) rename app/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/ui/util/coil/ComposeImageHelper.kt (91%) rename app/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/ui/util/pullrefresh/PullRefresh.kt (98%) rename app/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/ui/util/pullrefresh/PullRefreshIndicator.kt (99%) rename app/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/ui/util/pullrefresh/PullRefreshIndicatorTransform.kt (98%) rename app/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/ui/util/pullrefresh/PullRefreshState.kt (99%) delete mode 100644 app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/Navigation.kt delete mode 100644 app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/components/AestheticDialog.kt delete mode 100644 app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/FileImportsRoot.kt delete mode 100644 app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/LoggerHistoryRoot.kt delete mode 100644 app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/TasksRootSection.kt delete mode 100644 app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/features/ConfigExportSummaryScreen.kt delete mode 100644 app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/features/ConfigImportConfirmationScreen.kt delete mode 100644 app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/features/FeaturesRootSection.kt delete mode 100644 app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/features/ManageRuleFeature.kt delete mode 100644 app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/home/HomeLogs.kt delete mode 100644 app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/home/HomeRootSection.kt delete mode 100644 app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/home/HomeSettings.kt delete mode 100644 app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/home/QuickActionsDialog.kt delete mode 100644 app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/scripting/ManageScriptReposSection.kt delete mode 100644 app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/scripting/ScriptingRootSection.kt delete mode 100644 app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/social/AddFriendDialog.kt delete mode 100644 app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/social/MessagingPreview.kt delete mode 100644 app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/social/SocialRootSection.kt delete mode 100644 app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/tracker/EditRule.kt delete mode 100644 app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/tracker/FriendTrackerManagerRoot.kt delete mode 100644 app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/tracker/LogsTab.kt delete mode 100644 app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/tracker/ManageFriendTrackerReposSection.kt delete mode 100644 app/src/main/kotlin/me/rhunk/snapenhance/ui/setup/SetupActivity.kt delete mode 100644 app/src/main/kotlin/me/rhunk/snapenhance/ui/setup/screens/SetupScreen.kt delete mode 100644 app/src/main/kotlin/me/rhunk/snapenhance/ui/setup/screens/impl/PermissionsScreen.kt delete mode 100644 app/src/main/kotlin/me/rhunk/snapenhance/ui/setup/screens/impl/PickLanguageScreen.kt delete mode 100644 app/src/main/kotlin/me/rhunk/snapenhance/ui/setup/screens/impl/SaveFolderScreen.kt delete mode 100644 app/src/main/kotlin/me/rhunk/snapenhance/ui/util/AlertDialogs.kt create mode 100644 app/src/main/res/drawable/howtomen_logo.jpg create mode 100644 app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml create mode 100644 app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml delete mode 100644 app/src/main/res/mipmap-anydpi-v26/launcher_icon.xml delete mode 100644 app/src/main/res/mipmap-anydpi-v26/launcher_icon_round.xml create mode 100644 app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png create mode 100644 app/src/main/res/mipmap-hdpi/ic_launcher_monochrome.png create mode 100644 app/src/main/res/mipmap-hdpi/ic_launcher_round.png delete mode 100644 app/src/main/res/mipmap-hdpi/launcher_icon_foreground.png delete mode 100644 app/src/main/res/mipmap-hdpi/launcher_icon_round.png create mode 100644 app/src/main/res/mipmap-ldpi/ic_launcher.png create mode 100644 app/src/main/res/mipmap-ldpi/ic_launcher_round.png create mode 100644 app/src/main/res/mipmap-mdpi/ic_launcher.png create mode 100644 app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png create mode 100644 app/src/main/res/mipmap-mdpi/ic_launcher_monochrome.png create mode 100644 app/src/main/res/mipmap-mdpi/ic_launcher_round.png delete mode 100644 app/src/main/res/mipmap-mdpi/launcher_icon.png delete mode 100644 app/src/main/res/mipmap-mdpi/launcher_icon_foreground.png delete mode 100644 app/src/main/res/mipmap-mdpi/launcher_icon_round.png create mode 100644 app/src/main/res/mipmap-xhdpi/ic_launcher.png create mode 100644 app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png create mode 100644 app/src/main/res/mipmap-xhdpi/ic_launcher_monochrome.png create mode 100644 app/src/main/res/mipmap-xhdpi/ic_launcher_round.png delete mode 100644 app/src/main/res/mipmap-xhdpi/launcher_icon.png delete mode 100644 app/src/main/res/mipmap-xhdpi/launcher_icon_foreground.png delete mode 100644 app/src/main/res/mipmap-xhdpi/launcher_icon_round.png create mode 100644 app/src/main/res/mipmap-xxhdpi/ic_launcher.png create mode 100644 app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png create mode 100644 app/src/main/res/mipmap-xxhdpi/ic_launcher_monochrome.png create mode 100644 app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png delete mode 100644 app/src/main/res/mipmap-xxhdpi/launcher_icon.png delete mode 100644 app/src/main/res/mipmap-xxhdpi/launcher_icon_foreground.png delete mode 100644 app/src/main/res/mipmap-xxhdpi/launcher_icon_round.png create mode 100644 app/src/main/res/mipmap-xxxhdpi/ic_launcher.png create mode 100644 app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png create mode 100644 app/src/main/res/mipmap-xxxhdpi/ic_launcher_monochrome.png create mode 100644 app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png delete mode 100644 app/src/main/res/mipmap-xxxhdpi/launcher_icon.png delete mode 100644 app/src/main/res/mipmap-xxxhdpi/launcher_icon_foreground.png delete mode 100644 app/src/main/res/mipmap-xxxhdpi/launcher_icon_round.png create mode 100644 app/src/main/res/values/launcher_icon_background.xml create mode 100644 build-wsl.sh rename common/src/main/aidl/me/{rhunk/snapenhance => eternal/purrfectsnap}/bridge/AccountStorage.aidl (88%) rename common/src/main/aidl/me/{rhunk/snapenhance => eternal/purrfectsnap}/bridge/BridgeInterface.aidl (72%) rename common/src/main/aidl/me/{rhunk/snapenhance => eternal/purrfectsnap}/bridge/ConfigStateListener.aidl (76%) rename common/src/main/aidl/me/{rhunk/snapenhance => eternal/purrfectsnap}/bridge/DownloadCallback.aidl (81%) rename common/src/main/aidl/me/{rhunk/snapenhance => eternal/purrfectsnap}/bridge/SyncCallback.aidl (91%) rename common/src/main/aidl/me/{rhunk/snapenhance => eternal/purrfectsnap}/bridge/e2ee/E2eeInterface.aidl (92%) rename common/src/main/aidl/me/{rhunk/snapenhance => eternal/purrfectsnap}/bridge/e2ee/EncryptionResult.aidl (60%) rename common/src/main/aidl/me/{rhunk/snapenhance => eternal/purrfectsnap}/bridge/location/FriendLocation.aidl (84%) rename common/src/main/aidl/me/{rhunk/snapenhance => eternal/purrfectsnap}/bridge/location/LocationCoordinates.aidl (72%) create mode 100644 common/src/main/aidl/me/eternal/purrfectsnap/bridge/location/LocationManager.aidl rename common/src/main/aidl/me/{rhunk/snapenhance => eternal/purrfectsnap}/bridge/logger/BridgeLoggedMessage.aidl (81%) rename common/src/main/aidl/me/{rhunk/snapenhance => eternal/purrfectsnap}/bridge/logger/LoggedChatEdit.aidl (59%) rename common/src/main/aidl/me/{rhunk/snapenhance => eternal/purrfectsnap}/bridge/logger/LoggerInterface.aidl (86%) rename common/src/main/aidl/me/{rhunk/snapenhance => eternal/purrfectsnap}/bridge/logger/TrackerInterface.aidl (82%) rename common/src/main/aidl/me/{rhunk/snapenhance => eternal/purrfectsnap}/bridge/scripting/AutoReloadListener.aidl (55%) rename common/src/main/aidl/me/{rhunk/snapenhance => eternal/purrfectsnap}/bridge/scripting/IPCListener.aidl (56%) rename common/src/main/aidl/me/{rhunk/snapenhance => eternal/purrfectsnap}/bridge/scripting/IScripting.aidl (74%) rename common/src/main/aidl/me/{rhunk/snapenhance => eternal/purrfectsnap}/bridge/snapclient/MessagingBridge.aidl (77%) rename common/src/main/aidl/me/{rhunk/snapenhance => eternal/purrfectsnap}/bridge/snapclient/SessionStartListener.aidl (56%) rename common/src/main/aidl/me/{rhunk/snapenhance => eternal/purrfectsnap}/bridge/snapclient/types/Message.aidl (77%) rename common/src/main/aidl/me/{rhunk/snapenhance => eternal/purrfectsnap}/bridge/storage/FileHandle.aidl (74%) create mode 100644 common/src/main/aidl/me/eternal/purrfectsnap/bridge/storage/FileHandleManager.aidl create mode 100644 common/src/main/aidl/me/eternal/purrfectsnap/bridge/task/TaskInterface.aidl create mode 100644 common/src/main/aidl/me/eternal/purrfectsnap/bridge/task/TaskListener.aidl delete mode 100644 common/src/main/aidl/me/rhunk/snapenhance/bridge/location/LocationManager.aidl delete mode 100644 common/src/main/aidl/me/rhunk/snapenhance/bridge/storage/FileHandleManager.aidl delete mode 100644 common/src/main/assets/lang/ar.json create mode 100644 common/src/main/assets/lang/ar_AE.json delete mode 100644 common/src/main/assets/lang/cs.json delete mode 100644 common/src/main/assets/lang/el.json create mode 100644 common/src/main/assets/lang/en_UK.json create mode 100644 common/src/main/assets/lang/es_ES.json create mode 100644 common/src/main/assets/lang/gsw.json create mode 100644 common/src/main/assets/lang/gwi.json create mode 100644 common/src/main/assets/lang/hr_HR.json create mode 100644 common/src/main/assets/lang/hu_HU.json delete mode 100644 common/src/main/assets/lang/ja.json create mode 100644 common/src/main/assets/lang/ja_JP.json delete mode 100644 common/src/main/assets/lang/kn.json create mode 100644 common/src/main/assets/lang/lv_LV.json create mode 100644 common/src/main/assets/lang/ml_IN.json delete mode 100644 common/src/main/assets/lang/mr.json delete mode 100644 common/src/main/assets/lang/ms.json create mode 100644 common/src/main/assets/lang/nb_NO.json delete mode 100644 common/src/main/assets/lang/no.json delete mode 100644 common/src/main/assets/lang/or.json delete mode 100644 common/src/main/assets/lang/pa.json create mode 100644 common/src/main/assets/lang/sl_SI.json create mode 100644 common/src/main/assets/lang/sv.json delete mode 100644 common/src/main/assets/lang/sw.json create mode 100644 common/src/main/assets/lang/swg.json create mode 100644 common/src/main/assets/lang/ta_IN.json delete mode 100644 common/src/main/assets/lang/te.json delete mode 100644 common/src/main/assets/lang/th.json create mode 100644 common/src/main/assets/lang/tr_TR.json create mode 100644 common/src/main/assets/lang/uk_UA.json delete mode 100644 common/src/main/assets/lang/ur.json delete mode 100644 common/src/main/assets/lang/vi.json create mode 100644 common/src/main/assets/lang/wep.json delete mode 100644 common/src/main/assets/lang/zh_CN.json create mode 100644 common/src/main/assets/lang/zh_SIMPLIFIED.json rename common/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/common/Constants.kt (87%) rename common/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/common/ReceiversConfig.kt (61%) rename common/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/common/action/EnumAction.kt (95%) rename common/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/common/bridge/BridgeFiles.kt (87%) rename common/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/common/bridge/InternalFileWrapper.kt (71%) rename common/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/common/bridge/wrapper/LocaleWrapper.kt (86%) rename common/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/common/bridge/wrapper/LoggerWrapper.kt (96%) rename common/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/common/bridge/wrapper/MappingsWrapper.kt (82%) rename common/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/common/config/ConfigConstants.kt (89%) rename common/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/common/config/ConfigContainer.kt (95%) rename common/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/common/config/ConfigObjects.kt (97%) rename common/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/common/config/DataProcessors.kt (98%) rename common/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/common/config/ModConfig.kt (90%) rename common/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/common/config/impl/Camera.kt (94%) rename common/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/common/config/impl/DownloaderConfig.kt (91%) rename common/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/common/config/impl/Experimental.kt (94%) rename common/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/common/config/impl/FriendTrackerConfig.kt (59%) rename common/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/common/config/impl/Global.kt (93%) create mode 100644 common/src/main/kotlin/me/eternal/purrfectsnap/common/config/impl/MessagingTweaks.kt rename common/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/common/config/impl/RootConfig.kt (88%) rename common/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/common/config/impl/Rules.kt (72%) rename common/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/common/config/impl/Scripting.kt (77%) create mode 100644 common/src/main/kotlin/me/eternal/purrfectsnap/common/config/impl/Spoof.kt rename common/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/common/config/impl/StreaksReminderConfig.kt (68%) rename common/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/common/config/impl/UserInterfaceTweaks.kt (92%) rename common/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/common/data/ExportType.kt (52%) rename common/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/common/data/ExportedTrackerData.kt (67%) rename common/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/common/data/FileType.kt (98%) rename common/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/common/data/MessagingCoreObjects.kt (84%) rename common/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/common/data/SessionEventsData.kt (97%) rename common/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/common/data/SnapEnums.kt (88%) rename common/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/common/data/ThemingObjects.kt (98%) rename common/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/common/data/TrackerDataManager.kt (82%) rename common/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/common/data/download/DownloadMediaType.kt (90%) rename common/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/common/data/download/DownloadMetadata.kt (77%) rename common/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/common/data/download/DownloadRequest.kt (96%) rename common/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/common/data/download/DownloadStage.kt (81%) rename common/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/common/data/download/MediaDownloadSource.kt (90%) rename common/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/common/data/download/MediaEncryptionKeyPair.kt (95%) rename common/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/common/data/download/SplitMediaAssetType.kt (52%) rename common/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/common/database/DatabaseObject.kt (65%) rename common/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/common/database/impl/ConversationMessage.kt (76%) rename common/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/common/database/impl/FriendFeedEntry.kt (87%) rename common/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/common/database/impl/FriendInfo.kt (89%) rename common/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/common/database/impl/StoryEntry.kt (72%) rename common/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/common/database/impl/StorySnapEntry.kt (75%) rename common/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/common/database/impl/UserConversationLink.kt (69%) rename common/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/common/logger/AbstractLogger.kt (91%) rename common/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/common/logger/LogChannel.kt (58%) rename common/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/common/logger/LogLevel.kt (94%) rename common/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/common/messaging/MessagingTask.kt (94%) rename common/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/common/scripting/JSModule.kt (93%) rename common/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/common/scripting/PrimitiveUtil.kt (96%) rename common/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/common/scripting/ScriptRuntime.kt (83%) rename common/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/common/scripting/ScriptingLogger.kt (83%) rename common/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/common/scripting/bindings/AbstractBinding.kt (88%) rename common/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/common/scripting/bindings/BindingSide.kt (82%) create mode 100644 common/src/main/kotlin/me/eternal/purrfectsnap/common/scripting/bindings/BindingsContext.kt rename common/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/common/scripting/impl/ConfigInterface.kt (94%) rename common/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/common/scripting/impl/IPCInterface.kt (81%) rename common/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/common/scripting/impl/JavaInterfaces.kt (82%) rename common/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/common/scripting/impl/Networking.kt (96%) rename common/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/common/scripting/impl/Protobuf.kt (82%) rename common/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/common/scripting/ktx/RhinoKtx.kt (97%) rename common/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/common/scripting/type/ModuleInfo.kt (97%) rename common/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/common/scripting/type/Permissions.kt (64%) rename common/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/common/scripting/ui/EnumScriptInterface.kt (69%) rename common/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/common/scripting/ui/InterfaceManager.kt (84%) rename common/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/common/scripting/ui/ScriptInterface.kt (95%) rename common/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/common/scripting/ui/components/Node.kt (95%) rename common/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/common/scripting/ui/components/NodeType.kt (67%) create mode 100644 common/src/main/kotlin/me/eternal/purrfectsnap/common/scripting/ui/components/impl/ActionNode.kt rename common/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/common/scripting/ui/components/impl/RowColumnNode.kt (87%) rename common/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/common/scripting/ui/components/impl/TextInputNode.kt (78%) rename common/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/common/ui/AsyncMutableState.kt (98%) rename common/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/common/ui/Components.kt (95%) rename common/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/common/ui/ComposeViewFactory.kt (94%) rename common/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/common/ui/Keyboard.kt (97%) rename common/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/common/ui/OverlayType.kt (85%) rename common/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/common/ui/TextFieldColors.kt (93%) rename common/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/common/ui/Theme.kt (99%) rename common/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/common/ui/ThemeChooserDialog.kt (98%) rename common/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/common/ui/ThemeMode.kt (76%) rename common/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/common/ui/ThemePreferences.kt (95%) rename common/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/common/util/LazyBridge.kt (96%) rename common/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/common/util/ParcelableExt.kt (95%) rename common/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/common/util/Purge.kt (94%) rename common/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/common/util/SQLiteDatabaseHelper.kt (92%) rename common/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/common/util/ktx/AndroidCompatExtensions.kt (97%) rename common/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/common/util/ktx/DbCursorExt.kt (96%) rename common/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/common/util/ktx/JavaExt.kt (96%) rename common/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/common/util/ktx/OkHttp.kt (94%) rename common/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/common/util/protobuf/GrpcReader.kt (97%) rename common/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/common/util/protobuf/GrpcWriter.kt (95%) rename common/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/common/util/protobuf/ProtoEditor.kt (98%) rename common/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/common/util/protobuf/ProtoReader.kt (99%) rename common/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/common/util/protobuf/ProtoWriter.kt (98%) rename common/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/common/util/protobuf/WireType.kt (82%) rename common/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/common/util/snap/BitmojiSelfie.kt (94%) rename common/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/common/util/snap/MediaDownloaderHelper.kt (88%) rename common/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/common/util/snap/RemoteMediaResolver.kt (93%) rename common/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/common/util/snap/SnapWidgetBroadcastReceiverHelper.kt (88%) delete mode 100644 common/src/main/kotlin/me/rhunk/snapenhance/common/config/impl/MessagingTweaks.kt delete mode 100644 common/src/main/kotlin/me/rhunk/snapenhance/common/config/impl/Spoof.kt delete mode 100644 common/src/main/kotlin/me/rhunk/snapenhance/common/scripting/bindings/BindingsContext.kt delete mode 100644 common/src/main/kotlin/me/rhunk/snapenhance/common/scripting/ui/components/impl/ActionNode.kt delete mode 100644 compare_translations.ipynb create mode 100644 config/config.json rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/DownloadManagerClient.kt (90%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/ModContext.kt (77%) rename core/src/main/kotlin/me/{rhunk/snapenhance/core/SnapEnhance.kt => eternal/purrfectsnap/core/PurrfectSnap.kt} (74%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/SecurityFeatures.kt (67%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/XposedLoader.kt (56%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/action/AbstractAction.kt (85%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/action/ActionManager.kt (71%) create mode 100644 core/src/main/kotlin/me/eternal/purrfectsnap/core/action/impl/BulkMessagingAction.kt rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/action/impl/CleanCache.kt (92%) create mode 100644 core/src/main/kotlin/me/eternal/purrfectsnap/core/action/impl/ExportChatMessages.kt create mode 100644 core/src/main/kotlin/me/eternal/purrfectsnap/core/action/impl/ExportMemories.kt create mode 100644 core/src/main/kotlin/me/eternal/purrfectsnap/core/action/impl/ManageFriendList.kt rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/bridge/BridgeClient.kt (87%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/data/SnapClassCache.kt (77%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/database/DatabaseAccess.kt (94%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/event/EventBus.kt (96%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/event/EventDispatcher.kt (87%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/event/events/AbstractHookEvent.kt (79%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/event/events/impl/ActivityResultEvent.kt (63%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/event/events/impl/AddViewEvent.kt (68%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/event/events/impl/BindViewEvent.kt (87%) create mode 100644 core/src/main/kotlin/me/eternal/purrfectsnap/core/event/events/impl/BuildMessageEvent.kt create mode 100644 core/src/main/kotlin/me/eternal/purrfectsnap/core/event/events/impl/ConversationUpdateEvent.kt rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/event/events/impl/LayoutInflateEvent.kt (59%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/event/events/impl/MediaUploadEvent.kt (62%) create mode 100644 core/src/main/kotlin/me/eternal/purrfectsnap/core/event/events/impl/NativeUnaryCallEvent.kt rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/event/events/impl/NetworkApiRequestEvent.kt (92%) create mode 100644 core/src/main/kotlin/me/eternal/purrfectsnap/core/event/events/impl/OnSnapInteractionEvent.kt rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/event/events/impl/SendMessageWithContentEvent.kt (55%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/event/events/impl/SnapWidgetBroadcastReceiveEvent.kt (62%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/event/events/impl/UnaryCallEvent.kt (69%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/features/BridgeFileFeature.kt (84%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/features/Feature.kt (91%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/features/FeatureLoadParams.kt (82%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/features/FeatureManager.kt (82%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/features/MessagingRuleFeature.kt (84%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/features/impl/COFOverride.kt (74%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/features/impl/ConfigurationOverride.kt (94%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/features/impl/Debug.kt (74%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/features/impl/FriendMutationObserver.kt (95%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/features/impl/MixerStories.kt (94%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/features/impl/OperaViewerParamsOverride.kt (90%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/features/impl/ScopeSync.kt (81%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/features/impl/downloader/MediaDownloader.kt (93%) create mode 100644 core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/downloader/ProfilePictureDownloader.kt rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/features/impl/downloader/decoder/AttachmentInfo.kt (70%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/features/impl/downloader/decoder/AttachmentType.kt (74%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/features/impl/downloader/decoder/MessageDecoder.kt (95%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/features/impl/experiments/AccountSwitcher.kt (77%) create mode 100644 core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/experiments/AddFriendSourceSpoof.kt rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/features/impl/experiments/AppLock.kt (89%) create mode 100644 core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/experiments/AutoOpenSnaps.kt rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/features/impl/experiments/BestFriendPinning.kt (88%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/features/impl/experiments/BetterLocation.kt (91%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/features/impl/experiments/BetterTranscript.kt (82%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/features/impl/experiments/CallRecorder.kt (90%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/features/impl/experiments/ComposerHooks.kt (87%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/features/impl/experiments/ContextMenuFix.kt (81%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/features/impl/experiments/ConvertMessageLocally.kt (81%) create mode 100644 core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/experiments/CustomEmojiFont.kt create mode 100644 core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/experiments/DeviceSpooferHook.kt rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/features/impl/experiments/EndToEndEncryption.kt (93%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/features/impl/experiments/InfiniteStoryBoost.kt (70%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/features/impl/experiments/MediaFilePicker.kt (63%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/features/impl/experiments/MeoPasscodeBypass.kt (67%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/features/impl/experiments/NoFriendScoreDelay.kt (74%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/features/impl/experiments/PreventForcedLogout.kt (72%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/features/impl/experiments/SnapScoreChanges.kt (84%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/features/impl/global/BypassVideoLengthRestriction.kt (83%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/features/impl/global/DisableCustomTabs.kt (71%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/features/impl/global/DisableMemoriesSnapFeed.kt (73%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/features/impl/global/DisableMetrics.kt (72%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/features/impl/global/DisableTelecomFramework.kt (64%) create mode 100644 core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/global/EndpointsBlocker.kt rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/features/impl/global/GooglePlayServicesDialogs.kt (77%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/features/impl/global/MediaUploadQualityOverride.kt (62%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/features/impl/global/SnapchatPlus.kt (86%) create mode 100644 core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/messaging/AutoDeleteSentMessages.kt rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/features/impl/messaging/AutoMarkAsRead.kt (88%) create mode 100644 core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/messaging/AutoRead.kt create mode 100644 core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/messaging/AutoReply.kt rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/features/impl/messaging/AutoSave.kt (80%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/features/impl/messaging/BypassMessageActionRestrictions.kt (72%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/features/impl/messaging/CallButtonsOverride.kt (88%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/features/impl/messaging/DisableReplayInFF.kt (65%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/features/impl/messaging/HideTypingIndicator.kt (61%) create mode 100644 core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/messaging/MessageTranslator.kt rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/features/impl/messaging/Messaging.kt (89%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/features/impl/messaging/Notifications.kt (90%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/features/impl/messaging/PreventMessageSending.kt (77%) create mode 100644 core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/messaging/SendOverride.kt create mode 100644 core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/messaging/TranslationManager.kt create mode 100644 core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/messaging/TranslationUI.kt rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/features/impl/messaging/UnlimitedSnapViewTime.kt (70%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/features/impl/spying/FriendTracker.kt (71%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/features/impl/spying/HalfSwipeNotifier.kt (85%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/features/impl/spying/MessageLogger.kt (89%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/features/impl/spying/StealthMode.kt (74%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/features/impl/tweaks/BypassScreenshotDetection.kt (80%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/features/impl/tweaks/CameraTweaks.kt (95%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/features/impl/tweaks/DisablePermissionRequests.kt (71%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/features/impl/tweaks/DisableSnapModeRestrictions.kt (60%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/features/impl/tweaks/DoubleTapChatAction.kt (78%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/features/impl/tweaks/HideActiveMusic.kt (62%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/features/impl/tweaks/PreventForcedKeyboard.kt (71%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/features/impl/tweaks/PreventMessageListAutoScroll.kt (85%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/features/impl/tweaks/RemoveGroupsLockedStatus.kt (62%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/features/impl/tweaks/RequerySqlite.kt (86%) create mode 100644 core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/tweaks/UnsaveableMessages.kt rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/features/impl/tweaks/VoiceNoteOverride.kt (88%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/features/impl/ui/ClientBootstrapOverride.kt (84%) create mode 100644 core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/ui/ConversationToolbox.kt rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/features/impl/ui/CustomStreaksExpirationFormat.kt (88%) create mode 100644 core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/ui/CustomTheming.kt rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/features/impl/ui/DefaultVolumeControls.kt (72%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/features/impl/ui/DisableConfirmationDialogs.kt (88%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/features/impl/ui/EditTextOverride.kt (82%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/features/impl/ui/FriendFeedMessagePreview.kt (85%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/features/impl/ui/FriendNotes.kt (85%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/features/impl/ui/HideFriendFeedEntry.kt (82%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/features/impl/ui/HideStreakRestore.kt (72%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/features/impl/ui/MessageIndicators.kt (94%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/features/impl/ui/OldBitmojiSelfie.kt (85%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/features/impl/ui/PinConversations.kt (75%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/features/impl/ui/SnapPreview.kt (84%) create mode 100644 core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/ui/SpotlightCommentsUsername.kt rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/features/impl/ui/StealthModeIndicator.kt (85%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/features/impl/ui/UITweaks.kt (91%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/logger/CoreLogger.kt (85%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/messaging/ConversationExporter.kt (95%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/messaging/CoreMessagingBridge.kt (87%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/messaging/EnumBulkAction.kt (74%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/messaging/ExportFormat.kt (69%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/messaging/ExportParams.kt (67%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/messaging/MessageSender.kt (78%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/scripting/CoreScriptRuntime.kt (81%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/scripting/impl/CoreEvents.kt (87%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/scripting/impl/CoreIPC.kt (79%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/scripting/impl/CoreMessaging.kt (88%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/scripting/impl/CoreScriptConfig.kt (83%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/scripting/impl/CoreScriptHooker.kt (90%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/ui/ComposeIcons.kt (99%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/ui/DebugComponents.kt (94%) create mode 100644 core/src/main/kotlin/me/eternal/purrfectsnap/core/ui/InAppOverlay.kt create mode 100644 core/src/main/kotlin/me/eternal/purrfectsnap/core/ui/PurrfectOverlayTheme.kt rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/ui/UserInterface.kt (91%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/ui/ViewAppearanceHelper.kt (77%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/ui/ViewTagState.kt (91%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/ui/menu/AbstractMenu.kt (67%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/ui/menu/MenuViewInjector.kt (90%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/ui/menu/impl/ChatActionMenu.kt (89%) create mode 100644 core/src/main/kotlin/me/eternal/purrfectsnap/core/ui/menu/impl/FriendFeedInfoMenu.kt rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/ui/menu/impl/NewChatActionMenu.kt (85%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/ui/menu/impl/OperaContextActionMenu.kt (92%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/ui/menu/impl/OperaViewerIcons.kt (92%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/ui/menu/impl/SettingsGearInjector.kt (92%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/ui/menu/impl/SettingsMenu.kt (72%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/util/CallbackBuilder.kt (94%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/util/DataClassBuilder.kt (98%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/util/EvictingMap.kt (81%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/util/LSPatchUpdater.kt (95%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/util/RandomWalking.kt (98%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/util/hook/HookAdapter.kt (97%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/util/hook/HookStage.kt (50%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/util/hook/Hooker.kt (98%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/util/ktx/AndroidExt.kt (92%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/util/ktx/FileHandleManagerKtx.kt (76%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/util/ktx/XposedHelperExt.kt (93%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/util/media/HttpServer.kt (98%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/util/media/PreviewUtils.kt (97%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/wrapper/AbstractWrapper.kt (94%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/wrapper/impl/ConversationManager.kt (95%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/wrapper/impl/Message.kt (57%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/wrapper/impl/MessageContent.kt (76%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/wrapper/impl/MessageDescriptor.kt (73%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/wrapper/impl/MessageDestinations.kt (59%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/wrapper/impl/MessageMetadata.kt (90%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/wrapper/impl/QuotedMessage.kt (65%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/wrapper/impl/QuotedMessageContent.kt (69%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/wrapper/impl/ScSize.kt (86%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/wrapper/impl/SnapUUID.kt (66%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/wrapper/impl/Snapchatter.kt (88%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/wrapper/impl/UserIdToReaction.kt (73%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/wrapper/impl/composer/ComposerContext.kt (56%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/wrapper/impl/composer/ComposerMarshaller.kt (84%) create mode 100644 core/src/main/kotlin/me/eternal/purrfectsnap/core/wrapper/impl/composer/ComposerViewNode.kt rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/wrapper/impl/media/EncryptionWrapper.kt (92%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/wrapper/impl/media/MediaInfo.kt (84%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/wrapper/impl/media/dash/LongformVideoPlaylistItem.kt (73%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/wrapper/impl/media/dash/SnapChapter.kt (76%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/wrapper/impl/media/dash/SnapPlaylistItem.kt (65%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/wrapper/impl/media/opera/Layer.kt (79%) rename core/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/core/wrapper/impl/media/opera/ParamMap.kt (83%) delete mode 100644 core/src/main/kotlin/me/rhunk/snapenhance/core/action/impl/BulkMessagingAction.kt delete mode 100644 core/src/main/kotlin/me/rhunk/snapenhance/core/action/impl/ExportChatMessages.kt delete mode 100644 core/src/main/kotlin/me/rhunk/snapenhance/core/action/impl/ExportMemories.kt delete mode 100644 core/src/main/kotlin/me/rhunk/snapenhance/core/action/impl/ManageFriendList.kt delete mode 100644 core/src/main/kotlin/me/rhunk/snapenhance/core/event/events/impl/BuildMessageEvent.kt delete mode 100644 core/src/main/kotlin/me/rhunk/snapenhance/core/event/events/impl/ConversationUpdateEvent.kt delete mode 100644 core/src/main/kotlin/me/rhunk/snapenhance/core/event/events/impl/NativeUnaryCallEvent.kt delete mode 100644 core/src/main/kotlin/me/rhunk/snapenhance/core/event/events/impl/OnSnapInteractionEvent.kt delete mode 100644 core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/downloader/ProfilePictureDownloader.kt delete mode 100644 core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/experiments/AddFriendSourceSpoof.kt delete mode 100644 core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/experiments/AutoOpenSnaps.kt delete mode 100644 core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/experiments/CustomEmojiFont.kt delete mode 100644 core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/experiments/DeviceSpooferHook.kt delete mode 100644 core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/messaging/SendOverride.kt delete mode 100644 core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/tweaks/UnsaveableMessages.kt delete mode 100644 core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/ui/ConversationToolbox.kt delete mode 100644 core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/ui/CustomTheming.kt delete mode 100644 core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/ui/SpotlightCommentsUsername.kt delete mode 100644 core/src/main/kotlin/me/rhunk/snapenhance/core/ui/InAppOverlay.kt delete mode 100644 core/src/main/kotlin/me/rhunk/snapenhance/core/ui/menu/impl/FriendFeedInfoMenu.kt delete mode 100644 core/src/main/kotlin/me/rhunk/snapenhance/core/wrapper/impl/composer/ComposerViewNode.kt delete mode 100644 logo.png delete mode 100644 manager/.gitignore delete mode 100644 manager/build.gradle.kts delete mode 100644 manager/proguard-rules.pro delete mode 100644 manager/src/main/AndroidManifest.xml delete mode 100644 manager/src/main/assets/lspatch/dexes/loader.dex delete mode 100644 manager/src/main/assets/lspatch/dexes/metaloader.dex delete mode 100644 manager/src/main/assets/lspatch/so/arm64-v8a/liblspatch.so delete mode 100644 manager/src/main/assets/lspatch/so/armeabi-v7a/liblspatch.so delete mode 100644 manager/src/main/assets/lspatch/version.txt delete mode 100644 manager/src/main/kotlin/me/rhunk/snapenhance/manager/data/APKMirror.kt delete mode 100644 manager/src/main/kotlin/me/rhunk/snapenhance/manager/data/SharedConfig.kt delete mode 100644 manager/src/main/kotlin/me/rhunk/snapenhance/manager/data/download/InstallStage.kt delete mode 100644 manager/src/main/kotlin/me/rhunk/snapenhance/manager/data/download/SEArtifact.kt delete mode 100644 manager/src/main/kotlin/me/rhunk/snapenhance/manager/data/download/SEVersion.kt delete mode 100644 manager/src/main/kotlin/me/rhunk/snapenhance/manager/patch/LSPatchObfuscation.kt delete mode 100644 manager/src/main/kotlin/me/rhunk/snapenhance/manager/patch/Repackager.kt delete mode 100644 manager/src/main/kotlin/me/rhunk/snapenhance/manager/patch/config/Constants.kt delete mode 100644 manager/src/main/kotlin/me/rhunk/snapenhance/manager/ui/MainActivity.kt delete mode 100644 manager/src/main/kotlin/me/rhunk/snapenhance/manager/ui/Navigation.kt delete mode 100644 manager/src/main/kotlin/me/rhunk/snapenhance/manager/ui/components/Dialogs.kt delete mode 100644 manager/src/main/kotlin/me/rhunk/snapenhance/manager/ui/tab/Tab.kt delete mode 100644 manager/src/main/kotlin/me/rhunk/snapenhance/manager/ui/tab/impl/HomeTab.kt delete mode 100644 manager/src/main/kotlin/me/rhunk/snapenhance/manager/ui/tab/impl/SettingsTab.kt delete mode 100644 manager/src/main/kotlin/me/rhunk/snapenhance/manager/ui/tab/impl/download/InstallPackageTab.kt delete mode 100644 manager/src/main/kotlin/me/rhunk/snapenhance/manager/ui/tab/impl/download/LSPatchTab.kt delete mode 100644 manager/src/main/kotlin/me/rhunk/snapenhance/manager/ui/tab/impl/download/RepackageTab.kt delete mode 100644 manager/src/main/kotlin/me/rhunk/snapenhance/manager/ui/tab/impl/download/SEDownloadTab.kt delete mode 100644 manager/src/main/kotlin/me/rhunk/snapenhance/manager/ui/tab/impl/download/SnapchatPatchTab.kt delete mode 100644 manager/src/main/res/drawable/sclogo.xml delete mode 100644 manager/src/main/res/values/themes.xml delete mode 100644 manager/src/main/res/xml/provider_paths.xml rename mapper/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/mapper/AbstractClassMapper.kt (86%) rename mapper/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/mapper/ClassMapper.kt (97%) rename mapper/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/mapper/MapperContext.kt (92%) rename mapper/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/mapper/ext/DexClassDef.kt (95%) rename mapper/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/mapper/ext/DexMethod.kt (97%) rename mapper/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/mapper/impl/BCryptClassMapper.kt (82%) rename mapper/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/mapper/impl/COFObservableMapper.kt (89%) rename mapper/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/mapper/impl/CallbackMapper.kt (85%) rename mapper/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/mapper/impl/ChatEventDispatcherMapper.kt (72%) rename mapper/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/mapper/impl/CompositeConfigurationProviderMapper.kt (94%) rename mapper/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/mapper/impl/DefaultMediaItemMapper.kt (83%) rename mapper/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/mapper/impl/FoldingLayoutMapper.kt (94%) rename mapper/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/mapper/impl/FriendRelationshipChangerMapper.kt (86%) rename mapper/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/mapper/impl/FriendsFeedEventDispatcherMapper.kt (84%) rename mapper/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/mapper/impl/MediaQualityLevelProviderMapper.kt (79%) rename mapper/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/mapper/impl/MemoriesPresenterMapper.kt (79%) rename mapper/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/mapper/impl/OperaPageViewControllerMapper.kt (86%) rename mapper/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/mapper/impl/OperaViewerParamsMapper.kt (86%) rename mapper/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/mapper/impl/PlatformClientAttestationMapper.kt (89%) rename mapper/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/mapper/impl/PlusSubscriptionMapper.kt (84%) rename mapper/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/mapper/impl/ScoreUpdateMapper.kt (77%) rename mapper/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/mapper/impl/StoryBoostStateMapper.kt (77%) rename mapper/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/mapper/impl/StreaksExpirationMapper.kt (87%) rename mapper/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/mapper/impl/ViewBinderMapper.kt (84%) rename mapper/src/test/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/mapper/tests/TestMappings.kt (88%) create mode 100644 native/build-native.sh create mode 100644 native/obfuscation.yml create mode 100644 native/omvll_config.py create mode 100644 native/rust/secure/secure_strings.c create mode 100644 native/rust/secure/secure_strings.h create mode 100644 native/rust/src/secstrings.rs create mode 100644 native/rust/src/security.rs rename native/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/nativelib/NativeConfig.kt (85%) create mode 100644 native/src/main/kotlin/me/eternal/purrfectsnap/nativelib/NativeDecision.kt create mode 100644 native/src/main/kotlin/me/eternal/purrfectsnap/nativelib/NativeLib.kt rename native/src/main/kotlin/me/{rhunk/snapenhance => eternal/purrfectsnap}/nativelib/NativeRequestData.kt (72%) delete mode 100644 native/src/main/kotlin/me/rhunk/snapenhance/nativelib/NativeLib.kt delete mode 100644 translation_report.md diff --git a/.gitignore b/.gitignore index d2666ebf..02cb567e 100644 --- a/.gitignore +++ b/.gitignore @@ -6,4 +6,14 @@ local.properties /build /captures .externalNativeBuild -.cxx \ No newline at end of file +.cxx +native/.omvll/ +cloudflare/**/.wrangler/ +cloudflare/**/node_modules/ +cloudflare/**/dist/ +cloudflare/**/.env +cloudflare/**/.env.* +cloudflare/**/allowed-codes.local.* +cloudflare/**/allowed_codes.local.* +security/allowed-codes.local.* +security/allowed_codes.local.* diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 3f52a226..db1bad3b 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -2,8 +2,20 @@ import com.android.build.gradle.internal.api.BaseVariantOutputImpl import kotlinx.coroutines.delay import kotlinx.coroutines.launch import kotlinx.coroutines.runBlocking -import org.gradle.configurationcache.extensions.capitalized +import com.android.build.api.artifact.MultipleArtifact +import org.gradle.api.file.ConfigurableFileCollection +import org.gradle.api.file.DirectoryProperty +import org.gradle.api.provider.Property +import org.gradle.api.tasks.InputFiles +import org.gradle.api.tasks.Input +import org.gradle.api.tasks.OutputDirectory +import org.gradle.api.tasks.PathSensitive +import org.gradle.api.tasks.PathSensitivity +import org.gradle.api.tasks.TaskAction import java.io.ByteArrayOutputStream +import java.security.MessageDigest +import java.security.KeyStore +import java.io.File plugins { alias(libs.plugins.androidApplication) @@ -12,21 +24,111 @@ plugins { id("com.google.devtools.ksp") version "2.2.20-2.0.3" } +abstract class GenerateDexIntegrityAsset : org.gradle.api.DefaultTask() { + @get:InputFiles + @get:PathSensitive(PathSensitivity.RELATIVE) + abstract val dexFiles: ConfigurableFileCollection + + @get:Input + abstract val variantName: Property + + @get:Input + abstract val pinnedSha256: Property + + @get:org.gradle.api.tasks.InputDirectory + @get:PathSensitive(PathSensitivity.RELATIVE) + abstract val r8DexDir: DirectoryProperty + + @get:org.gradle.api.tasks.InputDirectory + @get:PathSensitive(PathSensitivity.RELATIVE) + abstract val assetsDir: DirectoryProperty + + @get:OutputDirectory + abstract val outputDir: DirectoryProperty + + @TaskAction + fun writeIntegrityAsset() { + val pinned = pinnedSha256.orNull?.trim().orEmpty() + if (pinned.isNotBlank()) { + val assetDir = outputDir.get().asFile.apply { mkdirs() } + assetDir.resolve("ps_integrity.bin").writeText(pinned.lowercase()) + return + } + + fun mapToApkEntry(file: java.io.File): String { + val segments = file.invariantSeparatorsPath.split("/") + val idx = segments.indexOfLast { it == "assets" } + return if (idx != -1 && idx + 1 < segments.size) { + ("assets/" + segments.drop(idx + 1).joinToString("/")) + } else { + file.name + } + } + + val digest = MessageDigest.getInstance("SHA-256") + val allFiles = mutableListOf() + allFiles += r8DexDir.asFileTree.files.filter { it.extension == "dex" } + allFiles += assetsDir.get().asFile.walkTopDown().filter { it.isFile && it.extension == "dex" }.toList() + + allFiles + .map { mapToApkEntry(it) to it } + .sortedBy { it.first } + .forEach { (_, file) -> + file.inputStream().use { input -> + val buffer = ByteArray(DEFAULT_BUFFER_SIZE) + while (true) { + val read = input.read(buffer) + if (read <= 0) break + digest.update(buffer, 0, read) + } + } + } + val expectedHash = digest.digest().joinToString("") { "%02x".format(it) } + val assetDir = outputDir.get().asFile.apply { mkdirs() } + assetDir.resolve("ps_integrity.bin").writeText(expectedHash) + } +} + +fun computeKeystoreCertSha256(storeFile: File, storePass: String, keyAlias: String, keyPass: String = storePass): String? { + if (!storeFile.exists()) return null + return runCatching { + val ks = KeyStore.getInstance(KeyStore.getDefaultType()) + storeFile.inputStream().use { ks.load(it, storePass.toCharArray()) } + val cert = ks.getCertificate(keyAlias) ?: return null + val digest = MessageDigest.getInstance("SHA-256") + digest.digest(cert.encoded).joinToString("") { "%02x".format(it) } + }.getOrNull() +} + android { namespace = rootProject.ext["applicationId"].toString() compileSdk = 36 + ndkVersion = "28.2.13676358" buildFeatures { aidl = true compose = true + buildConfig = true } defaultConfig { + val autoCertSha = providers.provider { + computeKeystoreCertSha256( + File(System.getProperty("user.home"), ".android/debug.keystore"), + storePass = "android", + keyAlias = "androiddebugkey" + ).orEmpty() + } + val expectedCertSha256 = providers.gradleProperty("EXPECTED_CERT_SHA256") + .orElse(providers.gradleProperty("psExpectedCertSha256")) + .orElse(autoCertSha) + .orElse("") applicationId = rootProject.ext["applicationId"].toString() versionCode = rootProject.ext["appVersionCode"].toString().toInt() versionName = rootProject.ext["appVersionName"].toString() minSdk = 28 targetSdk = 36 multiDexEnabled = true + buildConfigField("String", "EXPECTED_CERT_SHA256", "\"${expectedCertSha256.get()}\"") } buildTypes { @@ -100,18 +202,28 @@ androidComponents { variantOutput.outputFileName.set( when { variant.name.startsWith("core") -> "core.apk" - else -> "snapenhance_${rootProject.ext["appVersionName"]}-${variant.name}.apk" + else -> "purrfectsnap_${rootProject.ext["appVersionName"]}-${variant.name}.apk" } ) } + + val integrityTaskName = "generate${variant.name.replaceFirstChar { if (it.isLowerCase()) it.titlecase() else it.toString() }}DexIntegrity" + val capitalizedVariant = variant.name.replaceFirstChar { if (it.isLowerCase()) it.titlecase() else it.toString() } + val dexOutput = layout.buildDirectory.dir("intermediates/dex/${variant.name}") + val integrityTask = tasks.register(integrityTaskName, GenerateDexIntegrityAsset::class.java) { + tasks.findByName("minify${capitalizedVariant}WithR8")?.let { dependsOn(it) } + dexFiles.from( + fileTree(dexOutput) { include("**/*.dex") } + ) + variantName.set(variant.name) + r8DexDir.set(layout.buildDirectory.dir("intermediates/dex/${variant.name}/minify${capitalizedVariant}WithR8")) + assetsDir.set(layout.projectDirectory.dir("src/main/assets")) + outputDir.set(layout.buildDirectory.dir("generated/integrity/${variant.name}/assets")) + pinnedSha256.set(providers.gradleProperty("psIntegrityPinnedSha256").orElse("")) + } + variant.sources.assets?.addGeneratedSourceDirectory(integrityTask, GenerateDexIntegrityAsset::outputDir) } - onVariants(selector().withFlavor("abi", "core")) { - it.packaging.jniLibs.apply { - pickFirsts.set(listOf("**/lib${rootProject.ext["buildHash"]}.so")) - excludes.set(listOf("**/*.so")) - } - } } dependencies { @@ -124,7 +236,9 @@ dependencies { implementation(project(":core")) implementation(project(":common")) + implementation(project(":native")) implementation(libs.androidx.documentfile) + implementation("androidx.browser:browser:1.8.0") implementation(libs.gson) implementation(libs.smart.exception.java) implementation(files("libs/ffmpeg-kit-full-gpl-6.0-2.LTS.aar")) @@ -149,6 +263,16 @@ dependencies { implementation("com.google.android.material:material:1.13.0") implementation(libs.androidx.material3) implementation(libs.androidx.work.runtime.ktx) + // Patching pipeline dependencies + implementation(files("libs/apkzlib.jar")) + implementation(files("libs/ManifestEditor-1.0.2.jar")) + implementation(libs.apksig) + implementation(libs.dexlib2) + implementation(libs.jsoup) + implementation("com.google.auto.value:auto-value-annotations:1.10.4") + implementation("com.squareup.okhttp3:okhttp:4.12.0") + implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.8.0") + implementation("org.json:json:20240303") implementation(libs.fetch) { exclude(group = "androidx.room", module = "room-runtime") } diff --git a/manager/libs/ManifestEditor-1.0.2.jar b/app/libs/ManifestEditor-1.0.2.jar similarity index 100% rename from manager/libs/ManifestEditor-1.0.2.jar rename to app/libs/ManifestEditor-1.0.2.jar diff --git a/manager/libs/apkzlib.jar b/app/libs/apkzlib.jar similarity index 100% rename from manager/libs/apkzlib.jar rename to app/libs/apkzlib.jar diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro index 145e4714..2d60e596 100644 --- a/app/proguard-rules.pro +++ b/app/proguard-rules.pro @@ -1,3 +1,4 @@ + -dontwarn de.robv.android.xposed.** -dontwarn org.mozilla.javascript.** @@ -12,7 +13,7 @@ -keep class androidx.compose.material3.R$* { *; } -keep class androidx.compose.ui.R$* { *; } -keep class androidx.navigation.** { *; } --keep class me.rhunk.snapenhance.** { *; } +-keep class me.eternal.purrfectsnap.** { *; } -keep class androidx.core.content.res.ResourcesCompat { *; } -keepclassmembers class * implements android.os.Parcelable { @@ -21,4 +22,5 @@ # Prevent WorkManager from stripping generated Room database constructor -keep class androidx.work.impl.WorkDatabase_Impl { *; } - +-keep class android.support.annotation.** { *; } +-dontwarn android.support.annotation.** diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 1790135c..07e5cf66 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -19,7 +19,8 @@ android:allowBackup="true" android:hasFragileUserData="true" android:enableOnBackInvokedCallback="true" - android:icon="@mipmap/launcher_icon"> + android:icon="@mipmap/ic_launcher" + android:roundIcon="@mipmap/ic_launcher_round"> @@ -52,21 +53,20 @@ + android:exported="false" + android:theme="@style/AppTheme" /> + android:exported="false" /> + android:exported="false" /> F#d+XZ^1AEEwkA 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

nlvP9qPDp!T;=zk(A&rig6)%k}Yh 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%0Dgp@pDhEw3;DeOu8;J$K05Dv5A+Xt`WHn{ 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⁣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±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¡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

dyncUO71;TG6>kw&fe$-cd=Rb(3-qg` zxe~s0kI9-Vjb_I|_k;Y9G1#26IqJ%Ihu5e5{=x&SY^%&yfwaQDI!^b4xUj3@1Ll6_ zzfRMyv~w)jH^?sD&au*6Ai=!8hw>c_ywA?-Mos|L#sI&6LA-DWZ5^vE-k18ho?d|8 z8E;*^bP+`plrJdv*X445Q7RYT0=8VY{{N16*Pg~!w@$mcK@tl;*`Ne-uN=la9VtvZ z8I|=IWoqAyer@;PO0qfWu~hQ~{e|C__<|wzja2qV+7Q(D)F##U`;qJ0NZG^sN4lWC zziv`}kBwa4hv?r+n^fPQ%k>HGb)T7=8{1XQjqOUd%8oY^EtRag*Idoq_&T~}*Tj26 z*T!4AcZvn_j$n=`t;*{)Ut^BUFU^si>>SaU>-PrjlnzS{&L`v5Ge^+9>3)#2^HtQ4 zGo6Hx>Max*|2MwP0zNt+4MDLQ!tle z*lerb{?c3;j$?l0iM$F?d1jz0Y;OC9-I7eG;E!7*?gUq2!CMNb$!tWO?es-}srpI)o z@TuC=ft_G_YA3DJ=`wO5+q#8FL|p3@cYiy+c-A-LKg?n`Yrf04)Ea%~|5;gw7EwpL z?duKn^{esD)aLZ{M)nCm7k}kxXR$i_qtbq$fDGvuv_tFZoyc1LXz?TRYyR(oy4?6z*A>{?A3`}4 z&iMZyxL1p}96V0pSv=h2+N84u{p%;4*1QSUXVP7v6v1kTe(#j-6Gg(#`Ph2k;qGKq z+>xbrR^s|nb)px1>{v(Lvs~LyE^rK##1&Kt_^ERE5AR*6~ggr7-WvL$vTh--m2vm0A6L_lEz7vRcmKC(`&Z*V{Wrvm{WoHhT8I``JKWaZ zmAkB5gO|uGjaJdo6u+)%_#t-ioJ#q3X_7>RwT* zdj)l`aCI;4rJjSRXO`-b?zZX~z>>UFPYmc9S5J&Pu>-pHOX{&Uu9hBs9eUJOrcIrx z%_?PHEossWPoGrwZUQGPz9PUR?y>&xJ0G)&VIY9C*PtcUyt`t zig*QwzkjD5i@&9MguffleN8F1tNZ8W-d5<~8Sz^WFLr?8%4w*%+ECUG>VwP*M-U zYnAy9BYqmvlMoAA!W=>ys^uEuUBl!FP7wameL?tbrEnLMUo(6! z8o=iAl3b$K+-mbkvM9K0puOS=Wf360C?6d#EowEgnw;4QIji528)XrXWOBn_#YYb&+-;MScxm1#5OKvWW9~1}2RFXTXoCe|qd&zfqM!tIs^LHmn zoYZb_70_|~yWrMDTIsR$r{)8Z9`C!zcW)y;7>CC{5sbr~<+hRB=nibvRZM+PnP`b_nJFwc%ZYkCG|@mAe};b%IUu6Bg;)&yFl(3`Ce8&6{XpyF)L`y zbZTgJj&c)IYoS>2)zwKk!u^b?hWqkd0QX=Fke70=#MD-IBXMO69xmg~?WO*>{Zut9 zKL#vs2bMcq>D`o8N$>6eR@(EZpF7Y77&c(JzlG(U!1DX}*7-pdJYOl_H*nV=xMj+4 z`>_oV@M&&oeEL#d!T@;pkAXk#UN*t`*>g(s!F&uno<0bV_aLw26T-GZoHwZRdE|cYjl(m_I2_=k?uykuHe(KJ4)DIwdlovgLkV*$uzu{!0N;OP z`x@ZLV%qEQz1i#ntbYXD0($z59|!b9cv`{VWhM9o_PJ$S_D0CC=Q@4gXSsK+%WFd4_gQu(#a5*DP}#@p z&|VEmdhPUnb;roEQrr`YL(6-xWZR9a>bRUXNxsnNbz>{Luob-`>pL~j**TFmOgnl+VN-+5Wch&zEt7(03tjrx$2K_sh zka{4g^g!x0?Za%VwQlHJrw+GU`ITFfZswkM&6gmLdT7^}!a)t_0zu^*PHJx4#a$l} zn|6t%0l}KDI1jmli(6Wb3-+RC(O1cWNHxs!woGJ?c{+AC+uW^w;&x<=JUjiSJ^C3-Xycm1cU@}{QJu1dYn)8I&8V(<23KqSH~4P(H$PcEsL(bZxJW_ zY+8`^rsF$(jvw)gv(>K-EI{QkD*v{l0WSTlhpX$EKB%5|2Gz5jttZf#mj728Tp8EG z_H|RyhSr!C7}EfLKLYgCXd1zKuTw$*5PXN<6b(QlKW|#V^T@(`W>bUMXb@=lx!+SI0MuzvSpnVqJ zK|PJ64{*X+mbkhCc(qm6mEC<1ytb;!>tNvGg-_x?j%B?SJ`oF@y>wf6Eut#%CzNiE@CqwD+9w090OT|ys z1J+NK?UP@?zWv zRXTYRO>yn3r@v}nkN4}6@2-mMPkJp$;_%&Vd4gW=USzd_&eB+Wh8e(CZBaQnGY4I_ zFI&15w55Y_(b`#&s>|Cx-`;G}uBGjL*{`+A16)N;_$GbV9tXedwr;ikPu8B=wOwPi zJ>^>dFPpJ;)xp|)7&OO*7dB7oY+hKZ@1275-3{oayZxxj8Py%Y;5Tu60mL;1!9HO& zd1QxicxnsTLuY>zPmkHh`yJM-5A*v2uzdv(DZFTYiv&-ST7`(FyD~hJ?Q?SgyXzs|>9MQkP{z7n(V+}<=E)_p{=l}ASRV)Vu^qOn-cETXK# zYx)Z_5~&zk;`WX((Xe*f;(2F8rt+?l5iYIUIhd!PK=yQVN%rLWbTsXD_N@M7`QFZl zG`d;rSO0(nEeb#K-`(~;9B6)(D;3$nTic=dFrT$p9 zedn_rUQ9h&=354bKVriZKv(?uiL`TTo}#JTu{rOL@#4~#;`5@>SkJsi;!R&_KG^W~ zXgnQlx^()H8B^T#QQAL0`nVVM=lC@`YxU-MHQu~XJlYsK&+lJ+ck6=meEfAh8jX7S zzX>OYwz-&k%(kJ19;grJ(gvN2s0|U*)Zc8VeZgZ`{Wjqzb}T-J9z*}F7@dPH;FIuzsegLK+KhzU?LYk=I9{))wjjcb@d%~k{f6&*ef!IZZFpuQbv?V0@aJr}eDevmKcWrON^Mwd zigRBCQ|18od69_enf^??IQJ!N#490KRjf>Bw~tITO)GDXG%tz7dZs@YFY;?zI6Wmx z`j_H!eDZ@0^U;b$XB&^jcuolSOnYv`_W#wkC!o>4qCNHufw4|;`#U~X{J)Nv?{7Ar zR#5fhccrl|!P4PFsK@);hUeOiygh3zd4bwSnxn6dSYI*q+D5|HZzTMcjfB6vk?-HMCB8}V@rd;6O?_R3P^%A)jN9Q17 zK_jj8_lpMQLU(@;TUUr&FIVMynOqB_^K7o)4$76DL2dC^qA@{zSKYd%nG2J89>iqn zl;RWX<4xYUE9u6T%`t687dq5)r&;`g6jGu(yyK`o_i{Ix_k*INkZC z*7f2q>269k)g}9s{E9946-vH!jVpV>CYAlG>aw3sFHqTCa8T*qd43G-t!eb4G5%UK zwq;`ic(1v2MYDM~+VkM6aqo-8Ctr;>{bYJ=8$H=Q`nX@~d(CtFc<9kErU%pKgyP|O z^rtcMT67-$X$+@hv4yd@G25pf+Is71b?0OL$>x(>ndyF4e;ezNM)%g<=G=y8&+lG~ z7y03@v}-doj`xT@9!`eXsQmuIPg)m;=ZE|n?#HyNUh_%hfABTt7FIca z5Gfbyx{L~-CL_0NV~$^;+*|rd&=y+ z=4uz+@BJ6BkZMoDVI?QkwZrSmj>s$BJEwNfvz&m!b@zs)rS|Ul9`AL| zW8MIYfjnCKJgwoy?CaPaz7cN>jm0MF`PP*68{^i&fG_Lu-eez^&T9t|?1_W@Ns*fk zRu@`K2KT!bf4qI-ah9S zXOe!5((jR6NJ)RSr#`A{0qY%cOWuxefsG_rh%<_+mHjO38)s`J%<4E4XOS}Zc03na z3V-@s>uk9F>*_j8{)I`AN%*pIc$DP5JtEjIW+aL{CjpHkcxuOVBu}^ZJj#5o{ObKFOnK__veR@xK}ax8GJTJ`U&W$kpfv?bE$v zTH&pJsXqow2PY2^Pv+q9reAD&i#^UZ?5iqgp2EA~<-AlbC-8|l2rk?khb2Q5T(Bj! zUMsoaz|^AOmny?$9`M|Xc4|G8@5z6&7n;i^wFmg-yeIg&8f@%o0vo(#NDBVO3HIv3 zGwrj1cP6||PS}WdH*g4BMKEzT=TwcM=fLkhk_9_|G_K$W^=R)~%z}Y*-A7s!5sXwe^|Uf5!F3H^eiEchF(E zKXwCFmU>Ra#<($2YgQ%vL?+>HR*EBRyvfuq!%O@9u{%v&ZDVcD^w#-_KJ>d}L7Pb) z%RSt;#Gf>E$=oQ<&y61K_tqSN#$J2;DKuZ#*SyR9;Jb24_G%5B%cueKeL!3{dUf`J zn)bYpW>Eo($~D%+L!%S>lxVf%NnNoZf>PN&=kMH3NfMisIjq3&F?l# zC+FA1k^|X`xMiX)nu~RYir3e(4|q9wrfUg$*7Ec78ot2mM)jqhPL49QqxuRLCtes` zSCbiavXvOTV07>JjijurS)E-|%iZLBze1kA)MSOmdakRldLLu^)|b7hwcYv>K$DBU zVynit(k4vvBRTqaR_)Qm&xlPinb@^a*WZEE__iqVEySO0@5Z$%|kq; zgOD(fh0KE?b5F?J5kg93F7V9@{)sn*uMQD$SIGRz?b&FK`5Yod(Wn8lfxij-cU^Uc zXTF;n>#f<}Gxk;wv?l@^Qc*`>!r8o)&01aw%0Xy|{(l1+w;Ks6GUC3}M5LjtB&kVy z*6McN$z}&{Q95bONq^P-tGBf^|mVwk)?fz;Yb*0;9rT(dW+|G1!VF%-5cgo3YI3FvH#g9nDY?v1g zM{Xmc9ckXag?-+9KUOo4 zJ)`yrpmQB@UMbyH<#Yq7FV;p(ZEQTVXlf)DpAng4RKK$-%*1Z0SG`BrdTl$b#iRRn z?Qm_FjL+hr9bJ(D-u+Tthf-dGd9@k7{44i+XKFIGq%$p5w`wa%RTTGp3lxr z$w?r>4Mw>2yo+&_QVX zhWLQ_7wIJTSDG_fbuurA59@5mt;@QVMm`jC{=v}vE!%u_I&=O(yf^Yb zkoq@e4bXQ=#2bpvN$SGIIjq2uf$n$Prnd~3|F!`u|4i24Nw#eIkTT@W_@mPzZH0?bAoU~WJ|xZ zI1Y<(R+kjaCm1dm%hI+tB3{RapGEu>*!i=b)~=UNqF7onmjccR6~z&QJ+lGC{~(iMoP{%oX;l^*Tqk>X(Z)#K}QhJ4dVeM>1LothS|0n3wZA^wiyZ#p|I zygUBbI~k!yS|@MVFXOksax$y{g6-xCXV>bunT+>EyAp`A!HN@}`Zep-K)j}I@)oZt z-J*==c+F}KNW2Gj;;triE3atRSS6`j;qW9-u7|KUZ)dL{9ib`od=H*Z#=E;&VBg&t zqVPg{pav*U&fAX}?6);B3!66|C>#*Wq7^3?Dy?s}ChZKqISWekdJ~xa`?D7hx1~c3 zp$W8f2e__xWA%PR=;NX{@PChpZrQz;?k+|1JC+P(yz4Rpg=Q~BE~R@3efp8pU0+J4 zHi$oxe5l1fk#d}PPq<|gf4VvtOUXP!W+&Qr8}Y^diSS0O`8=Cwag?_VAvf^c3~n$6 zCO%V^XQbIPn#2r$7F_RBgv!U~PC$1H^3~z_{3K*DttRT>1ODJqaM^L%{AN>M_78AT zby58BaN|!Su+yEWn|a$2)*I1&XlCL7Jm2mLL~m$iPvz~=%sDJ?bv{tQBKHQ{yRp&U zDDA-`cNB`cmnj|zhwW`w-xbBii1((0caGv?N}L4T>3GXYs9ksmu(w?={+Lof+Lrcj3gS>@7R}?z>shwkS)^JyDyO|%0 zf?eXv+?qC*r=%o{cv_uRf8w%hy=9?$>lV5fJ3_|n{#hqWY4ol@8!_Dmj@$Vj%;~)t zLkKtYM>Fh9&ZK+2Bhk~5FJ`3?ogZAr*kNU?pbV`E)%gS3{VC$y+`brYt}^EjEr$m* z#K}SqCtNZ~*Z^EuN6}rFXmHxvvMAR5vtg_@PELtGHOg)#O6SPf&hb`fEuAx=-%hOf2U#SZ z*FVov%vQ^fI{vdC-Z^D?I`Ub6@=j`6(HkzN5((EX*V>9cN?^%321ts2#LYFdB}-E? z=3Qj1-)fhSewPYq(@zud1sP}%HbDMc%>OCSmO8H~ts7#ew`}0V&V!4$w}|Sz_&>VW zb9z+L1;s)T#Z{-$crrQ<>XqE z2XUBjv+jka3OGdwa2rXtWA6$36Gw8>q$xSDyLQEdi(t}JJs5RR+$@W>yQq) zRYuYwrH$L?E6Ezu+%*=gzo_;H;guK?^+2Y zD9cGij;QI1=q96P?I4oLq`m#YeMPW{Wrf@VIesp(hB^G1c1~NDpPT4edI5asc5U=O z+Ou>`qIhqDwc?JtrA8+tlTC6%GO1OzMyqVO4A$Oc#ycyj{Xq&zkz}LVt1sl)0j8hI zb1C1C@f3CY8&7dC>+Q47yuoubzMXIO(d?Jqnj692>Sew;&o?i6=5^0pRHA{JP5<6A z;C*W0ed@}*k7$DC*ssB5oo&0l!fRtR3c9zUmi~PQexVM&VRBmsA;OM*&~~ZNgFld0 zbj#&^oxGcu^2&N`GF*B^7p;?hyZDD{U!A(EUHtclp$S>+gFb4SAehOf zQ0;MTm0z|B4RCG#aaEfgy?6pxymy|TROJ!m-9N2UJ>F=zO05C96T>r4QP$mji%(@Q z1a-kHZK{cwoOX4gU79oDna%x$@umX~uG!L;jK8W`k`CrRcM9Z;Y~6DH20zUy#ooyd zc+QpZU~O$b!}lh;!e|$}yGh-&1U+PI(my6Eg?Frtv$u#>I_^R7=sWrkaW|Nw0YPqNQ^7s)oqEI()mR{a`S#7KV zx!incMMEO3XQ(%^S13J&x7vopER){Ry)D9zq2BuNWOjO-xmuH^tZeNgl+_qp#47y` zClz&}mSySK%mZ~okgfd#`=T|RVWTtE-IMGXE4iIraV6pR*N5?-my~zOq?fPZ7v&e` z=O>}f_l+AUZ0l`}e7Y}H@Q^Gg=R?sO*xMVv`m!GPkhQ}n8}l_F??vtnf6Kc)e3SQ& z@D1Kw;p@C}qSt~f8hzo+e#2z;isK(bBuNo-=F`xRPI!P-CYPx9_BG4BEqLC_U7p!Q z#=8(5h$g-p80`-dJhf&f_&{Bj62JHAtR@l%w?3 zlfE?3Q-4XKXWW+(&PPjWPr~WTLkTx#&PHi>dyl!ZQL55pi;3!plCJhN?<70W+>vcK zQckL5xt1}TwhX=AO@0xq52pA}ja>q*=7+IY?0hkS>Vn`oXgqb_ps5hG( z#2t0pBX8^kD$SIT-zJG~FDDb`E0VNOXl7@Y#5Oirx|Q`4780^hdr&U?>ROdU|J%xPjEi-cDol(>9f4CA>&_3X$ONFk||Nz3xeV}lYdTr)dWYo zyNz^(92`jzVXq4|P3L~lWXaF4!zR)L!@0Ce@In@f7d3}XbK!?$v|Igx@kiDU9@zeR z)(@y~sk;;(0+;5%g+cD0sQbwLtkb6*l#ZDZ@S+O0d2N{9+&@>|$bS2V^U+H8 zzvQ)4%U0~#QqjRv;0F&I-WInz8{D^%!iK{|{u8uf4$eDLx=jrmsl1WGhL^XoaT^N1 zjinn37iZ@`sBhrG@V1PBk_^YSfR+tiC#rElEfb$nUFLg*jg;4|cCM8{-jUM%|07Jg zk)rwgLTkEc(tvrMzv!mBCu{ud=DzG3MpW-@)6L)4k!k7g3hpkRlBkbN;C}YiOP_+% z>r4Hel6u1vSk->oHWP}_$UEy8q58|NHH^Hh>bo7;p3dF`kwSS6ucj@+&|+$e-A_u_ zNo_oe@NEg-cpHn0Xb~3r>G0~}Q>G(mk^eEoNlBdpu;vX@Zz)c5SS8Co!MPnp(I@A0NZAKX1pcx$bK{^$@V zJXPOp%xvE$*uGCL_x&5xuXXGF;EwOyL47aPY*(7}*y@@_hlfI4Fdu8{ZKGb-@7t)i z@SgPwC#BgmC6Vs^@V!>u<89rN!MVEc{UCKO`l#x5xc0~KhpW!NxhqnUz0yV z{1P|KK8E_mhi;sXRj+Ywb;DxFU%jZZx|L`e_tA3_l^#UX{E^nSjHN4EL04QGmeGdJ zO=ttVp~Bs53&O?e(6-fD%|@i>L#gVJ)z!_jiM9<>%Jlq@O&tG8AKCc3z8~`;;Gg-( z;P2-8IkZ9N)*HtG$3twrk-iTZ@ez3kw~k?r1l)ypmv3U7<37SVZ`{N>(X<+Ij(@Oz zy79e}I^TbO2Rx*kUt4TsdBWJxMd#g4R@~!FK^`3J84e-t zz2|>rzf$jSGXy`X;le4`2sjbU|6pv6rM_GhPGmf{S4R$L_v+#y?hy~6QHi9-)cbj} zdf`*1Wr6CF9K&%eSSg1k4Uvwj2lRvT&!qhK#<}7A(q_Zxd1bVN`T}V{JC#=UUcxyy z&n|mkIJ)s(;M*Nt^iM>n@_pgsh0OF9(lTgt+; zvD~-YKVaWlK6Kw4Ebn{Y`l@9ITm26>>FRsr1JyV6f3ENO4^&_7f3EKzAE>^L|GB={ zo9|CkB$0EnpX7(GPcuLGr#JBvHE^$pgv7hcA1`%w8$4e|@Q!NvYF<7kN5)l$Yu&+}?)$ z5TS39Pq;V_9qLugrBdqbRU^dfM$Ye`3ph02e8O$%c7I0c*&mR~l|9*fY*_4_Rk7O= zd-(`uHWMDSc_3byPPhboY`xu z;=fJ}gJJsps{UL|?Aj6fbJp-$T`6dnyYcVq{%+gsWkG+nQq4o_<1-t}7wIe9MSq5l zc#-;lJVN~+FT-;0UANkiCw$!q^#$MSabuv+qcWe8-y0saMTb0d=9KZxy(IX>FjMihQH z4EFimf|OXZ4Vy9f9V@Y49v-_@U+ODW{prj8A8^Sx1-%JyNuHHOyRI43PGNAqwlDS7 zK_v*XXd7{|4LLNQ=g-0Xdid?ZZ)bjaeiQlW%p>@X;v1WV^0&g@X@GJ7`<~NOB13!`Xw|M-O-yit>oL^9vp5Ntn4ZpSgWNUFezX5(L z`6+%mzuoxh9!H(Q$QE7vjn1-Zs!6@&d^FAQvDCq{x7Lc)**_B}zdLc0^$w4A;UlBb z93GX|q|czMyRt27*BNovs$(K$NFTL7^;<$zLSNyMHt7sjbkupZYtlgW=h9KP`2*d_ zM)K>NU8CeQM`LIS{2ToY>AmVSS?#Ty+==HMDBO!qtMsvkhTmtywJr*L?Ub$bj_()G z@6vBYxb!7vgkvWCme#M?v{yHZpy+JZGvtJLxg(65MaJ3_sNJdczP9Fw)e(5JqFcH> zWyv-`S`2B{uGgt~b>Y9P>3H0*G7D*<3Kp(SvK`hrdl5~@Y8@~K56}7;5mY*vNT;@tj9J(q|9$Yx|Gk^ip|y^68&-umuOBV2H`=C#S9$v-oc(epd=DD<3-Z&fJ@ZhTX2Dr_ zsXO82V?{E-CY~Ba-(*jmKR!#0n*)1Mzs9(jt&C~fTU~hCWZ|h+nfxp(!1NuJm{iv6o z+Td^L>#f&Y97@k3)=w|8e|z<}!8;+^;A8t$=x%R{Hb*JTJnhdnlx2>mJ$Ul+Z=R@@ zr+OQrM@Acf3c9Q4ckR+1g(3vw1$YLHqwrOH_o*5$1~g|XwlgcyLt6}F&^->lG9eRg z$+av@$7VOx`3;eTY3b&Dp)_%ta}C%e>wED5;Q7ktrF+I2Vq5wRHOu^l_-HhJ*H6gQ zUY2WFo{oM0%sSaH#-cSg1+mKa{Ywd*NN7CW4h&-Hj`?BwKZl-&Gv0T%XhI zkoVrr6V$OcF^N^tgA)zj{@Aha70M)EpO6{#aFa?~|I<3JzAkB+AJ{XN8THbnhSAHc z-{1A4>qgBVB|GoK+GS6?9vg7JNor}aiIyV0Q#>~#Zb5BECD&71y&o@y|DO%dgx;_%ba9DN+*QP3g%WzHDz3H^ z_qEobyv=QSbvAre-KP@GC+`_s<$XHQdY+&iP5{rS-OCiPU zPT7@q7gvjKwUE~s#wMrmt=Pq}x^O-@FG5IUnNJKm4r03Rj9v1%I(B89)mE?3nv8Vs zv|}mhlEDv`tX)%$d8{*1YY-A)HCnRO?aPRMtR#F27EWjil6$(<7`)MXNEZd0ZLAd` zx_6>iOYAILRi10|FQRp4b&AW7;UA=vH;~%QQbEVdum%Fh7Sd$QHzTW4C*Vh|&d1}8 z?|Y5VroejLBj0RTH{`0c!pT?NeeAvFEa;(+ecqgW7HTN^*<@SLTyDou8ZG`u_1{L_ zGi=>|9zOsKM5Aw~!O}{+!#-D;LleFHGTxdt(OYp!b0_wChbANyJ2Rfeqi%zDGWXz2 zZxf~Q{9bbiwk~n-;t;6Ep=jAhER`13Uk%mImZ-jH&Q`XC9d^A4))L2K^r5>hZ~cLu zxne7R@0O$vONe*TI#V59Ont`c@C2~^3H=*Of&r6;x8RQDCd$pe$(o?C*pl01&?5F` z`2AUYWTADevg&M`k{fB0N^@<}TBQuPmBzTo>tnV544S-$m38(5np=Utv(I$?M&OG} z?JE}ktTAViZiGi?=K@odFn{9Pdb?x=8-+%$^Dm_F6<&#M=R#57y7qJ8J71054=ei}wv$ zBFX#1)b|M*l`*?UGTu4KjDLPo^9Jh{>vL-1^W;RnREr^sXZlhh1(b&q#%i36QzYeSN`B=a^?dJ5@8DUu#+Zb}#oY8!3 zCiXY1=z?_kO^uw>mWllf?(6>8XDK67^I!XZs-=Bf`qp{}nlYIXyEK8#il2$2G0cp; z(9YaT6Q}42)zM5=JAE^wCJMJ+M=wUf*H2;<59bE5cg32m7VUV;%LIJPrHOuEs{Dej zo3WL=4fHuBIs<3IxTXGM??KXiQVXH}jo$Or{O^(-WTnoWhpn>jY?Yf#&$!M|&-iJf zp3R(1GLXXGXCbuD*p5(Fcw$h4KVbfeF-%=lr7wy~)6JERZZ#TMqNU@lW;(V$zyte~ zl&~|n-SR98lPrBGrm=%2T<;nGv*mE{Y~40&aXGA*rcJ=rrJY|DUMPnTh7I@H)Sw@4 zj^%cjn)brS2U6|OfdFDj=;q;;B3)%1F1b-iLh*!Ib@&u&2b10Yb2)f=67SO0yOO8Q zB=6vP4A1SrTlop_&27HR)FJtHtvQ`E>DSWOc0~Q+MTJnYQ~qfFTZ4s1=uY;f zJLQ|X`~7xS;9OqoXb1S7orbR`ys9;Z95q1pX!0%DX?S!Ba}P^s86&wbYY=|$#(7Jp z&z1G)+{9wAxxS`gwmX{DsAh)Q?#zUFJQ__r8jC%+?#M?Y5ikFew;~g2rk=~GC*kGe zPFp<_IuCvLEG?<`_c7aL!|XlqQN!pAq!zL&6xU1*<-FstHyFjJ_WFB;#64-Ji$9Ht znGhaZy1yO^rCqwu)2meb1*RpHj3z4HjkVuXI5bG_aHM`E4&fTdoMzDc4w86Jt}r`(Q|E&RmVVTY`dP= z8Jm8KyDRvT-uv-_sX3edg`URj0_-F|5#6MB)?Y$8G`$|L@tBfj=WgkD;fb^{yrmzT zCBN(WHyw3vFrBG{wbE@cXVb?ouol$;i3!mA^0(<^Pp~?5v`UT+q%N^-LWYTD1Xj>5 zx^Y%3Dr>g52<^6quZhksS8I^Qe0SPCjrWZC+k}kwO1*Y#;9Lo=%;v%L3cAvhnif*& zJ*lZ^U#IzBA8x{~Q#;*_npTf#jP>0Xh6^^rvP~Tk)qyB^o{Eia#&p z`Hi8~*yqTev@wExITAcC+UT|TJ)x5*u?P>6@US{(411y{Cwh{nB=VVgUJ~!WCnuU7 zx_M^vm~^biJ0;;YH9d0kuG0sgpRrRCkJfnJym+!^emv%RC+FX6NS=bl`1$QSV=1NF z^O9V`I$=gEW11eB5u0F&$&>Nec1mKPa8diiq#1(^rMSrECirf`9`x#xjmZ^$d$I|? zTFl{m(?mRpC8n?KGV|hIO=J9&=%UMyOw6dQHO0%0z}7TdyDF+(Q>-SRRETCiSc7F4 zF<7B0W=Z_?L{}V-I`TbPpN#j`o`uEY?7S>e2eLEsUuK5v*1p2* z(_>w6&Yt7z@N>Q_7RUN)ITq`AKelQ~k`&1X*Q44}k7}_GqofB-el-0G(XX8A*TcT+ z7jui)n?Jro%{=D*Tt-P2WxMLBQL1SS(Z3x(NB?R}v6FG97Y9c3TXpUZy!o!~-GR0F ztitBi#%e?p*Ohur_}FA9=%aQI>f;W~D^UX5I(9X?BfX-p8}dKsigUV^+KYabT9TZR zoK$XI7kcl=%1Oh_L<%{Oy|8^>OC8uV#dFEYNI<)>`umRcU^yn)4)gU%@KZG+wmZg8;*#vhM#x8CzbAiX>XP!9~NvdR0$YsIdW}d=*`L2Ie>kM;eONdOuWTzg( zU0?|lo7(6d13hhIM$}=ShcpKNh(OToUg>X7^HFx~4CJNqiAe%Dfuj@hP1u)hrT3B% zYTi3Ob?Ds*M^l1pmuJ3Jnv*%R7x$(dm*_A29eS4?A$;*6}w&kFwLHRzu zR>f~x`KULaF;d_nqA(Kbetm*68>)vL4qGA=#$&hIYc!a&Kry(=^Q+H+^n{K?)Hm zUU#l7Wwqt}*8m-*ER2I&M+&6SsCiTT@R#-0eA0`3{v5?Tkq#qcv;`+9ucz6c)Az zcgQM6aV^Bfc-CY6s(2q?xmtsQyc-VRc-}2Hn%9*b_-)RaC7jwk-kN273d)t7$hGOB za+~B2Qeg$k-HIoEL}YPYUTtTX(Y&|mREW5V@@M7^EV;NnG_y`O?BWs8dKEPLTIwzR zm`evqC`IR|S$#X#z8Tab9~OP77qlKx_IcuZfWt+=VGL`KYfm@nWH+F6wr=KdH@s;V z=LpIpN>OT;ZBKpon6TE&ijP6HL>eBM$f0&N$^)CiERBOk=&9Dpm(_4Np8T|EuMptB z#$RIxU8j{!b}3GMciJhrYcVUlc-r27XS*=yYps zqMmnAA%$f^cy@!%p?~=Y?ZdQ>QQaP#&xdcvt%KTe#{bw3@nhm~B$w3LzRv69^@fpb zI>ypkNoX^kqqTZhFAJ=n>LnNn&nN$NbMgiDUZSH8zmMzwpUMMj1w4)mUi$Bum5i6Y zGd6o(yb0LW`;KPt&e%(K{3873PZ$ftBK(uw$Mfz*mKe|zv`>RF@RA`~^g+r9?w&cC zGTJCJXPl30&CHAN2V56zIw0*&PiHt|iGocHq7e49U9_V<>{>iKqVtPu>k96? z;`xe=b1=7-q)y+6O#M{L>kgfZ#nj0g2|r~c;iqjR{3ILhDE&z1$-)$4e!#skS_68# zQxm!oWvJa~8X7Y0iwMw2SmUs_E%8`U>1e zG1qHOx1}dc4_##D)r<-?#9tu&X0>bCwb$bzrYpWZQfv4?R<0Uw?zU?>uc7Ck<9_%S zyxYhlb-d~F&g1Hk9K`*G+CP!IHF2j&#BaMeA8ER*3$EB}=|Uqsc3OUnYvD_FWl#&< z_ZWQUx)wLYpD)+m#XTo8BJ$^FYmVG@ZRfSrd;~SOYG10FdlUPC^{t5;RNp1#_I$bH z*jm$cY3HYaO0?-qIu-C*^ND#;S{QrMw(v;&jo-GiD?+$S zjBwIOTPuL|vT};dsADEbekRQw`P+G#ljMAUMx^`|k=|EhE$bp)$tU5xw+@-texZ&@ zJ+$+E!y{tG?-JP1N&Xje&2(MWEVcIa>=uZ zncx2FQDc(1XcUWOaSwMm1&^Q;V|_$2&*t*2+B^*kF_$>^Ff7wlOewDUfuq~?w2@BPdR@hfSt{wPk} zzqq+zC+fQjd6hfE3Uo(ER{p0MtNAsQW*vzB$Vlggz2=1Xq(K2~QUzgtPA({^pQAj# zrJdsA`m)P8>vVn(hsX7l;{ut;?@M$iXU=7}voHKhUv_^a2afk~wCQou2p-L2=ES5^ z7PO_}@37+6kYx6sa!QLzaL`X_MWb@&9O_v{J*&*wz)$c|{8Q8+UdQn=X|p`_MPemC zQZK^hIpPoEyD#+|>Ex~DMLoUrtW4JH-loBe6&l(~8AcHJ?vj#I%` zNsU*<*iNQD`x|a|X=k7KGGUx8^?m`#r!Cdys0aQW{dc%I@LtWbzrvQu~GL`&ysyTf1qhmp1Swb-;uFW9*GaUS#I06Ra< zdC&QAUe)}lF_Wq9*Oc?#^W%mf{sYYqfcn)gUZ}Po;6b0w^yg`^)G_c zKA3}3o$_83?de@Ja;~oo&ZRq{f?VTGPw)97=Q_DMS6^zqr3wS7hZ$c{hYRg|*V+DI z8>&-&&>8Ri3=f_2n){0xH$4yGDXcxc^t`GRemhS`6K+HDBCgMvy%}%a=OE~5zn+F? zc%7YSu}RXNw|QIC#7LCFBsEl6v1tuEvro0xhlRJLx0VZu{TGtnQdw~CuTtg(;Ii_g z$IiF3e1rLVD0Ms9@!2wc7#?>-IWCyX{p1rLnlsLCoM^|1Lukjo-0kkxnt6k0$EZUG z&*7lVBPsKP(}!aQ(T8v2yRmvr4RoE4r|b`->wIkca9!s!DQi<`ji`rc&1;JSU1u~d zvL~>)bN4U@`_?s-H-&T+`toZ|MJ7UDe(kSLt+Lu;lB9wg$V{}qze!>6QYW-KT9to& z<5bD5*`iB=yQ51NK$iwAUAm}>E?q`Ds@Ls(QWsazrKq`*_{%7#G|PF8v~C{}#BTy! z>h*U4Z=U7sK(q7Gk>~WY)ibp(^-O7{zhvap4~(4pOCzVgZE$MG7j(%EAk8V1zfbSQ z0f%r^b;|#ZUPzDWW57{#VoB-w8J^NzI+drR4=0!D!#%)#E5e7<2c-UmBSisPfJXKo z%E*a!-d6a|OTeo$!K=RP*+XbSh40*T z5H0v{eCNf~bF#(XwN?20yCL|yJat(W{{H`l?+iG}%SOhpA$(`RrG7cUs{hyd&PBjT zSRxMe%e;vL6~2fc+8Ey%@M6P#o{Gx2e{Rnpxscwf!ZzaPd(+aXyy0~O?HTU-&ZWJ5 zp<9QFsmtxYOco>3Ier9unM%`!`%{_Q?EJ132pC8V4`vvOX`u*z0u!d|-OBtLw!l8dAGT zJ79Wjz0UT&wG6uzFFSakd)utNVPL!dkN0hl@I&^xKxNio4-w)5ks)z5R;ho?Fz*nq zJrzF<4h}V3m?Zl4KI1UN_eigQ4*2>k+6Ou_tEzRFcL=R{&Obnl-Ir-{P$Mu@8&iSw!iyo z$^P!EQQ6;p1*y=r<@LqMMORRU_|d@rju~87*S<0PyB}x`8?-lFN&XMcd;ZY!p5o%g z=jxw$&w;{^2JxgPpD{8|dKh(n7@qV;Bk-h0Q`V;Nq?MLRo(0c2B0c^fbbHh3ap0Td z6xu4Cyy5eGUWx9C&UAyD{}Q#Cc6B1%I@B-A&d}h;+h>B6jbTz&&;R%I%Mz>~$K4XF z30K=SA)tYm(6*7+gzC152GXjI!8EWpqLtzCc6rIMR_xWS+6XNix+Z*s`nP;f*c2C0 zbNyhtRI(Z!L{b0QXyfrh8xIxQh#Sj58@p4*YTxE=w97p|J)(;WzSWHi&M4YKdRNdH z3Rwd+6QEIx(*l?Wi{3sIyJRlSbYp`KZu%eS;1{S1ev5ary05{LGP;!S|2rC$#7%Usrct2O z`Zf>xbkVK<#P`)sOpfv8GRBknde$Xz{#3zvJ>NpV9`Ny9wqMevQ#QIkNU zzEjgdqn3O8{d(RdOz9IiB4{=|A{q|=nMMs2Zh+^PG^9fTPxmpg{6CC|!w`Qo;K!Ml z|HYW-IRf;}2c##^tP#07_l{T>!Rm8%9eN^8$?4k=NS~=4l$^(pL-{@N_tbsxce#td z%LRX1fWIH@gTJRDkM8)3mM{9e6Mug>*ChM26E83e{&Fpmg|#%LT>39L@BJG7P{$_u z#}X+gPL}fwWV@W}BfbaSc|+67FyP)lFMpbgJCO+wdi?wFlS#VG`|SVIEyF!|`Q&^R zL%BtO=a)E}ESIZ0&Q~b?7d*SHBzkd=@juPqav>xMV3Sip* zIO+})=XZS{clU7wDF4sL(Y1i5`#5?K<4Ef!8EQVlhIVVeL57BrnlRs?WoZ&pS@#SD zbg6(Zf95$KsGM;e(ZmjUQ4cndcEKFoPJ?AM!(0CLv{c$pX;ifC_ z_PF8n7xP#0-V#Wrb0NQi^fxVd;y!$L@EE)y8{C&04<7E0ag1#l>sZ0coi4qq$C<$s z&kY{v(gcM68g1wm{B_#!JnGw%Hk`H(ZFtC~4G#%zcmTBF+kI%mE6AfeZ9q>I8Nnov z|4Z8NYva2+eb{$=Z-e|;kMBo&%o$&}{Nf;Wy5M?}M!yD_y5rWPz%A-FbB(zHVSJ}G zIW`9wrwc9MtIIQr4hW7jB1b(6?GwMBw|EZ2`rgGSv@va%HUyvaJ#6|`cR?l?`{L7k zDC;oz6Tbf*pSsij3$bRz%Y?y`lRR}`0C0zTrAhk!1OiuhYIk9^Ly8EmG94vk$v^hSVDGNd@;^r~QER|9k%ApkVhs#ImRN&!3q8{_psc zBwkS$rzfAI*Rz?(CrJ2#2ci!t7^UB6OO<{X;KY;py)SBhFk_?QL6yw2EKYj!7%ZFbd;8Y4I&M=hyDBLrAD?NPO zJaSJPB+y{qsYhWNLyyk+GxGmDvk0S^`b0x;|3$SggQo!SDtIHpY!B{0z-vsim48@u z(Z!yNQ+dWQm~u*bDo)uh?>h_H4qA^Aw*w74B_mZ{>`Op*J}2V{q+h7t;RdFz?xv|< z9k?GU`(%vH7z+H|4s9X60f;waJKyO$rFW`eIdr~~Zve`hfYin(##0Xw^sjF(mF<3m zw~0IzK6ueb-t|6L9h!#MxN#bCP`ZB6XEx3u>U>W@jhPR1f(NCU*daL~cna>4i+AAN zVtH?Tbg!8me1V;>LY|B@Sq4tY^hur6>v%|R{6@s&DvlgucB(%!8!d{B28;(o4ac_x zeN*MSFT^7*?pLfWA+5}7uWUObW<qo33@qur|=rYPs26@m(pcQZI;dOcS zL^kDRXeHyxZ0h>@uxs23sc92z)QH_JJwf|4Uj^@qfb1_BRxK~SGOVj4)>Du62`HT*VVh%y3rRPPoALyuY>go_1mdm z%a^c9dv%>+LTh*F02{=W(}TR%Q$x!>HH@=+k>>F4L9A<8jiD-#PC0E7{y(5B)~D;8 zz-kSzoL#RDe4H7;IGqXlq0a`8cPCCvLpt*AJ?p))_nA`vV}j6fhX&;ej#<2bg+0k$ zLA0oLR|i(g`5FJnp#_Je$MZJuR82tm5sY~v>tv9%Bw?p zGkq@uFS(EWHhPD5R}|qq_Dbxj<%9Ok3~aZ#wtK~XfOk{Sl4%6vZg)bq_0Mt!-BkDZC&5lD%(iTDQFtB6lrQYI=pM%Nc!Vl zc=6|4!Twu>_6*`XNEHRJ%9qjD^%AUT$#&M0xSTKJob^=u)blL2o{q5!{A2Qr#}edE zUI*t?GkiFMr&|zj%o=T;SV}8mlHTwH0nS+>E_FzzkNa&#WVXE4=i3Rr&)CUm`*fW$ zUCFID120s%?M35z5^s0|Ot>kE_kXbMLAlZPqmqoSGnr{1xRqQmDPJKR} zC0vQJ9hQx=3uzby$s3U|HYkYEXIt>yi6mGTII>pU~)4`~Of75tFbI-EPh zaWR?iIWLp%T%qgL#{FT zN;Kio(*M^HNASF8kU_qfc@m%R|E=qfcU*awN;3ZRjmh|Uw-)h}Wo_C|S%VFI&tEdF z^?5SwkREB@-A~%UK52J!!kOPA?Wg-mTi~Wm${P3lG7ert%*SnndhAk$@jc>DuWyiQ z8#>4+#VNx~)SKs+-o>oXK7b}~O1A8w>bYPIa6_-X*dHB8&-L9PwQ<-CACAjN+8lg6 z>H|cpR8QgT=!Rbjds4=4vj3~0Bh-_p)^qx1$XGyFP=*2i?l3u%!;^u!fAl%z)F1R3 zlyP_(Q1_`$@97?fvy$D@?Rv3$x)XY&yA^t$q;rxdPR4XkcZ=OEtmxz(=~B<`78W?I zN4j;8yLRS@nU-)S`)g~p*3F()v^I!yEx1eL*|do7X`IV052l#=yL$*>zB@pEyYk3F zU3o`gGLJ#3tbk`0ilCo4It4RY%5%u`8QfOzEb@&>zC5c(TqXVwaN8HyGss(Lm2%aKm^K;!a3j7e>ft@r&ooB{;&jHt7J=BE>A*m|X|9Q`>v^BDx zA^wtgISP5P9+9HwKp*<5$cX1X)Mbr~d;w=zSL1eqd-|BhG~Y|I;?%kUY@1_|j&q&g zcO>pz!>yXe7)T9y!s8Hf+E`m0!gHG`BS+GANUvAYA}73#dndsMp7XkAbgw?}rH$}S z08gt^^Tdkgu3my(FUMvifK-6p4?0}!I~%C)!THo7xGT0x&U~U?z><0QOpd@(xJ#TUZuG^4ELvvsXalmuo!@ zSbYp`nHWSpYFt>FeP4OfdnHgZxrt{gS8k7~ocmMX&yPi@Oxg|qTm;L>#ZGmxIR zSnaz=&R}jbI@BifDx8q_@+Ph;by^8a*>q%wT9uNO!nHDW!?+ec2k9@B^iyyzhDQO; z@2Y)&pdD?_uj@j~i!WwHeuw7nP8-@UH{G9R{Nd;Uov||PjMQ}8++zg4Sy6O!|I^e- zDXD2Iz=2K7ELNL_;%2avVW4}L1#u&!m>%ROC8saUNJqSjGZ$bbH#(!2=2X5Zz+H^h zz6($yUxk0R-}LA>Pt&L%?tQxyd3eByb%tYJm7IFNlagW%@;oDP<73J)dZoRUmSzN> z$VP=pkJ(34QE#q=r-OUJY8W@KY>=^lGc|(0vk?B8w9B+0&oNOil55@^v*SvC3hy}W zI`Ie`%m&8cZX-$}M&+YQaJP=7~qO$AGIu6uSJE96Cz zC$JpvP`{G)Rz@$QeAYiaky)?fW`^y3u-n^vNN?P*)SI_$d4Db zg3n5yS@cn#v(nFbd4p$k`q79t5u?SEKB)Jz{i*|JdKP0Af>H&(UGiC2S$g?=sF5JI>_w?wzutAvm(DlxI3i83m2e zZN1ZdxCs9$rB>a~{1?KfH`d~`p=_)Pzs;Dgwxy?wA4}-Un_)#N{~X*&khZ!7mRjT*OL-qB z13&OY{O=Y0q;bjd^CaR^hBV#xBIthCiZtfi0$yCN1CWRBUDPoN!;5YikpObd ze;+Wc1q?jld3g}B$j-SS*{`o6{&6TH64;74gy+O-aB?;h*dq5n5EHt3i1y?O4u3}ub0r7P6`UX0MsEWiEsOXo+Gw`4 z(MGh9-f$kle1ZA*Jr{>LGb!~k@&-U?$-g1* zIPxwx-^S|e9o!GKwHuzKA)oI3%RK*bH3e<^O`$66Gm?HRFAtSn3_+%nM3+fYfQ5X%5Un118~c5Kf>?NP2n6_445Me_k!;J0nCjD^W>2}-0alNryTLK%mOt5 z>%LKFoI~AE9LYue3AgU{96c`0h}^34;4L(5M@1HE7w>x*IqaV*C+#Z3f9S}I+VNJ$ zmw=^5Zi{qWQvLEpUwR^)?k*cc{=MH2{{@HPyhP;Yy`F_QPRki`Bz9KnRL``(p6l1$ za%CxB^>F8==Hd+fk;fnD<~LdH0BajjzUXr|Uef2${PIP6_T#r}KYri4eizF9NwGy= zc#Ijr;rq79LTpR1K6vZ)tl*IUwm#pudH+EmEnoDt$A3IqXT_P!%LHGyCAC-Tqn8am zWp`Sv;aiVC?dVgoRHX4+Pozor17*NAZex+zelPn~r{y`E)DF65_+|ttuZ`XMou_B` zS3mowlm02p6dW#hzUgc9G^DTV+_zqVSM(pt%nG0?ya06mNXCtsaI1bDWo36U+OoSi@}Sg9yh8TjZ$kJdj#L&P*OvkJs_2gUl;k<5k8w$7{rg z_=u+07dn0f@k#%a<2yOFk0s~b8DHOAN@1%El~f!e9(w6NBw}@l5IQPt)nixK)nI!R2^25G2f3;Ciid1 zKg>qFXCOd}JzB-p%yXA7TTZ*jPaZAK;IBEWaXJqbZ6}eaE zOghXN9&a`pI(@xBd363EI={ezpdTEtgazi)o~G?L!tP1e_M2$W(DpwuPH%Eqsai_8 zDgF4v)CCHl__RH>TnJ z705sI{wU>&#M}FjZwbB=&NMS8TwrEC>KlX8&5<)Z(C@E%A{XGx^-SP2?B4JehQko1 zGX2?plPhM!2QE4g`Mt^Hj*bm)NihSD9RiM=rtl5}hA*0()ga zw$Rlk&!5wipJC0}o+|(&rtD5$S!Kq|4o`WCnVEctLa8SaXB6T@id1HG;BiuR6@xue z)PeTO1+_IZ{d-5|W4%=LL@*U6+F}R^LK3^$jfj=1gBEaU7WG@~qgi z$xiaDIH9^R?X48UD9`^H?cNfcpo|g0&m!accFU))n@?ZlBQk|ttktc^@oC8WdEAfO zM{?#aAJ_imhT(^tH=#}sAxDq7B7pVE$$c|9h++}VzJzroiJxp+H9WP$OOd7i(GebChwAA%*ech0paA}MJkqRWKOv5 zkW9{w!U?3N!hL9_zyHXK@Pf=CBQMHOBYEThL9wFr%-{jBqCT0y{;{Hr%wW!u=ixR0 zhG}Rj>3=G5it7 zlj{Sz2V#B3S)$zNEjX53mu3B=$3e2Kia_D}W|sTC(q5z>IAel1vyox0G9g#y$`m(% zPAAUwz?ES-WWw~`z$(V^?{?$P$jsylc|!I-JjoUEKoyzc$)peC41`>Y{G_%=X6U?0 zZ~v5C9hi>r$c&6k&<6vfH$T{GLiW!d?&@@frf2?oSfBqPOplyy*qxG-IuN_m8K5`K zNi4@r>l@P|$ABWGq5QO9FWM(uqG6w`BFA)iy1Ou{)4&xR157|1)EFaVTIOUm;h2=n zt*L1PS4HSP4cfM#4JU&(K&luyGBtBZ$}4FTj?}r1R>8*uClAAI#E{;nOu(FfPH*si zkpBXL6w*ZIfmqFw%SpT$8*``R(s?^JQc0X!bR6E3eNzYRd=CQelR(Nk-g7eM%h9}l z1#xj^UtQ5H#)EhpqGyaCVod4K<={;T-;Z*CBiFys#B<9#OvO5=9kL#NhpBTqA~Qe} zi~{s=s*68pVcfC95(laYGrWQ?1CyAA*j;$RIKP#UAaG!Rv`DYayJ*p0g4bYWo@=CZ zmc=|yb92|Vj0i@iVx_8EoA?ZDR7n@+0N^`s3Neh8sSO}Z$$8^Ucf2HJEI!N|*_q`j zSr{)o?@AgLL!58$o$hPH?ySf>GiLbC2l?YGMw)-ihdmeCvZVggu#%x^0Ez>k$59P# z%%k4L!kc%-zipbSJj0utVqk}z@kXc>0nk@SwK~%TW?^O@8sMH|HS)<-R~b5I<~aZ( zbuFcfNl9^MN`^e&T}}bo?&~&dXiOp>r=bjfUZ9eEUSwu2Qg4OarVmbcXZF?K2jKR| z81jETI^_t-3n3UmI}mG&oBFVFt}rKgo+dZh5`*yK5ko~FHm8kA z>xWy_H{-_7SD+>E4(}($yEA$oNnj3pBzW$CnSpovT%;lw`7mn^l9}c$yb;5hiu^V2 zZ{~MUdc#2OI*fvyv(Qm0h7`uxOh>NcbgpkEQ}((o@z$h z7ohEv=kFrEewZtt?Gr%n6k{}Vj*Aq$jyYcC*Zd3e z9Edz|rvYB($ySl$!Eug6KLtMM13n)5ETHssLoQB<@M>9iXQw9b#8{2=V~7t$uj5{2 zt%rsc3AB@lH(UjcHV<-LHNoxB%$1^&n@XW(0)HegM7A9}=5e$X{a5J}fwLq4LL zf&EHo=0FPTA2B`fA>?a-hn*Gr|wTKy>mZu z>CX^f%cbwwM=rgyhg|wYtdf)R&##dtgfb$55C4N)_%%?hYh1}PO7BUVJMYZkJTk=S zDMQxpY@i>1)^d~r^%~moYPO@f9dh0skRfk_>=+P8zmqpij+?$nLw5vs#*GH15Ca3i zO76#My|rwU{5jh^2XV{r^<(ujDD!9^?_-;of;ZoQ%SZRlC*O}Z6E0NnGd6)AIJ&n_ zjfRdteX0Y`adhY#s5|wCu>!_>8LuK#UU0&$puVwFr`733^*&QgE4n+#lW62~3VOYj zHlb)xCQFNqI52bixTk|B`?7I^E@e>US&6UtfR%fYTuVHK-eMiuC#**!_V>B|>%v;U z!CXcPZZHMvz5Hg5PccsukWDPwO+ z&)C6B0t>-a{%ZU^`^Fz1Shxiefqa#|aERKH#@=>IF(;(xbq;5Zh&nivFSLyW-V8Fo zmRv9k3sx8^csTakGky)mul6l7m%aYWx_r4$Ji!g$F};~8(#mqZ-2haJ)J74!Z#sJqLzcLQ? zu=GL3mpR@0SL5=%z-5h(T6*UoPtxd!FCSwN+&K2G0&)klmU$*+Jm>$)-rsbjCr&2$ z(tO})9~Vz&Bdjm;p2WO8Dt$)!HO4K*()6~j{XLEu&H+~;E^%JN!PggF0uAYs3tqo( zIOJgggeT{k1^b3WY8L>{lN^&bBb@ZJKxJT!>qARd`wGy59%E>>)|jKuQ21mU$uzei z4dE~7-0#LqQzF-s{aTspl6Uyti@4NP>l)VuhG7ps;TQeJAkVZcRT=I8V#SarbT- zxB!NZq}(|f-j1@kA1UG4zYKr1dw72LaI9~U?hS+!293|<#-X6S2WOU>hXAkBM1qO^ zQp6!H`E!mOnI-&LFf-!Euis&r6Yw&}jB#%TC!}H@5xt*Wzio5#jp3E(n0XjhZokRo zT??!~@r{3@ATOn?B;p&M$vSbboNfLw(p~{KVZwVQ`qn7r-*codP2mNaKMV(KBAo(H z1nt%fhG$MM+7j%a&ea!X8Am~bJ9se9rGcWSyQirP_iHB4!jH<2{9dO#2AU~f04AEa z*9Q4@<+Qy6TA}H|5q;AKrM%;(Y@H`^_!iqR$RC>^59*T|xmc&*UL!e8`VHzueG45< zKgu+d+~*8v7N$^pw6jdyg4)eRJ<^c0hoMfzH^^4Gvh0+T)JcF(x84z#_M}5>6Sh6^ zDz(Fv#g2Oq*rMNW<~-X6{_IEhL>^?AM?;oc9e5{rHrJNmSB7cn_}5%x>%4N1X1Ju; z34BQ2HP;{OqX+t+zF5aXn&kVCVP-$9oR5a46IX^9e;66>28Yci-41@jJAx1g?XwGC zp5)}KVY@K;I36_5laI0vLs^l)@XRsjyPj`Mb6w4J-1ldDKQHU)>8PW5qPup(n^)A| zC@|i|i)$N$`QvyRGY3B8yEWY{uIwqNPRj1rVGoHsOm$#8c#xiVsCI?z>y}{s!|tuG9Y`@lVF*{i8bmo8nI_Wc!`$#;-2=O5O-h;(8eVoR5bX zwyGZYh2VR#ui>rp0v*wGN7tD;G`h}TqKuw>-4*tAXIQeYZ+CS+3e*ni>+kmI>n+%4 z)O~$=kG?)US*K1oH2oudYzy9%o2>sSh^t}ysk3~BF$K?)NSMAmN#^5ZU-2$0-B&xh z_0{*tqpPn7hwiKG=&L=_S4Vd1tFt@%q-S3>;tad)lW&nj_Xi380nW31uxMPq|I8xD!w!lgjh-e8AK z@4TpOKW*D_=L|a>wbXFJy1xKvg#85!7kt=Xi1cx?*_79c4!3tVTh8$Mv5D;{N^;yb zxUmveL*ZU;7A?4vR~1!wq=mQun{La}*aE9AS`ruxV@OF!Gf;&IN}It0Bi^d0%Frp6 zXPvK?b+Zk4lK2kWFBNy^^Rjc4R~ z+crFIIcE$`#GDf3hZ>BvoU>jk8^3-%@poAQa42v5_Heu|UfUK2hBAwiP`$Mt74C$p zN{~o{&Z4v%DTkZ=jQ(D85FQj|!Vqge*cxoP4QIgu;W5TfRoKYRtuy?&R)e+5Y7H!nxSLXTNA&cW|W{0@i1QU}wkfS{;Rv>qi^o7U6BdI7D!6YESd z7fRkYvfg>>L2)eCjv%O2A(BhmtD~9KZ8WCRm_*|W8jENoXrN|h=2CTnB(S2<`SU{|b8hi9>J>0h z-b963%dc8b3@j|OEx4tG9d7Ve3I1FMN5?j(tvY-@b|#rT!7of0x28%Sa7Ye!N=UQB zQ+H~=d-UgF33`HN)NPTk2nF@_A3Y+EdXJTX{G6x-{6Es$1SD9x~xZTE$EFB9)2VqQbOxr)ZKt! zvZ_Uo{=OJ=FSJ_C_nJ5bDV@nN-VV4C<9+?vOwglGE{k6NP_)Fz z$*L?l-}EguXH7Qe8UwvCwM4q@9cig(EKy_}(Esjp)pbl|m#BMLWE>+b@`AkbS3jI@`;^9_g zXRC+BqW-2o3;8LHs`WC{sa^WB22wqss9MF!*QnQ%l?T(|RktJTe75^fu#}m7U$pId zvudk)z@)!)>$F4@92zYF9cvY|Mu-Hp>Z?WzL<$ z)|g77yMdwJL`;3i3KiC=yRl0|3qYx>V4{5zTrJ^D@vM-t``O35^&f)?<*B9O`%ez8 zZ)u!@+*=KQ))MG_c-6-e`WYfNw&3Y0CTJAery3dgc^dD~c#Ijo%y2fTnoqxG8Y^kM zOTT*<Pmn#T%E^ARgzi?+D2;}zgua!S_i=PBD2^)V+H)2u+#&e zd$sF%{i$b!FPP{D8p}~+v?*#;s_hKeL!*PnWc>2krZQis;~04men;Xr2EPD)LHxc0 zOoi%Em|nGv#s;xICFa@mI0hvc{j<~u;`OqaSF?ya8M=!`J&lm^j>5rM7I_)_P+cje zBPJ)JLiHQQ<4lFQjn);C*)lQj5_3MxLOWbB{ubi^pCyw>)ZYETELFkyA^FsvF>REW1VBBNnH@X;iDl3WCfaXFX&CNKypDQWIc~RmY0`Br(z4CAgVp))XA% z_fBmwYv-vG84!;u3tu%Cze7;95uK{TWU^T3aKDlW{{pqFGHAP zsTuIOg-rwdLPmegbv!}Gde`wb9dFP$k_Mi$e*jbU{bqD29*btC(^1HfIs6}(0}ToI z|2s6j5xArBU?}ebtu|R*BAoD>nBM^(TXAqq4sAs!y5U6sJN>`H_e_o1B8L8>n7HzAH}xKk*J9L zghWo5*^_N`3n`v$W=%Hw^{+K@`l;zmrRIn!or$qSz<(C=7OC&;G|k*~X6@t}uo~uN zi))mOLZ>-gYYfN+-Xa1V^>j3{hZMz+o{cI0~Qm3zA7TfAa{n;fEbu+}G4?w-tTStC23L!d-3k8VEhKdFi1{BdyRB+2y zBLDz?6K!j_qdpMMV<(xAPiVYDV*@=gf5?>YsMYj)41R^`X;@>m4WZ_S79-cEmNVqf zH149Y0Nd=So)wE52V^@=!j8w)eKP+q?}gxpVb~ygPKmmc?xtSAoF6qKSauwyx+#fs zZj3r1bK2r-m2lBs&`|VmX*d@BT`06|8+yW?7z%BmA&v@s)z|E=XsB6j7M|69NeNf$ zGD_hRyT~qyIvdJL?5d_#wNsjs1V$C>aZ(Ap9Wwg)Fi#tPm@RflJw(j0<7%~_WF@HB zURik*JD5DO48nCf|I+xWBpL+Vac#2MExdTFL{N>qJ{ged@HiT``(@@yn z=ztvvhod38rT&gT{0{6~7;K$gLBs4j8CM$I6{q_(QB5>hYA7Prs7de{fS-eF0#LitVLb`I3-H6- zT3aVV)5GAh7<(AfSVB$_ECURY)K>QK4jNmDAnH>wchQ`(T5Vy#TjKQ-tv9fX>!tT^ z5wl6m>$Eq*t`;{jO1%IhR8?<}z8J`c?9Rbt^9KCN;-O1bJ$<4fNkgWyP!#tmoB}f-hEhyghcTTF3@qc=(91p^0G86nVLx zKD8{Fv#z>?#!(SWrA2`gteHBM|{*!m;Ds_0Pp{6d`URX*4n_)O%=6U|zqpSMJ& z;gu(V@$ZL;drp2=Xi2Z8LlE zg}6P^tIni`J8C!mbDC|dqusVl|74mV1CV5>!HkI31>POX{O#8H zc72Ei%G8vYh$XcXE(s?ZpG>%v%mRucYTN%JV31gs7wXmJT7BDP4zTu#< zz#6bAK!^>GmHbW!@wx zKfcMb2me+WD6hT4DT8K!##iLrBE(INK{=!1@hif0iRzk?8VE>R?B@Dt^nNu|GNPoW zR2?SvLy-D@!3V2kYWVxh?Iq4|HJ(BCd`C@liA6ovYGw6NbHL(8V5Ip6;{b2vgC%3l z>~+F|dDW>XQ%yp;JZxoo=SyRwX~C{*Qhj;2vZA8OuCiB`*){Xex5H!S>S1N%4zR|` zczMrWp+YR#@a0$+SzwppD69hkPdIh;j%DO#g~Rv^%xY*UGcN`Rs!+GjW8^vJ0A#fV zU__g-z=sd!m|W*nO0(>-SRRM!O5(MZ5Cd9v2&}f{l+aPvAnP2v0pt|3X)}5Y6Q5

~_bOsVB5LU(lI8)%)K+7tY5+^VG zA&Z008;FQvmy0mVj4i>UPx2X4l>Z|H7EUDRNa< z;n?fJ(8&TCezL+)1*mz>91b;ePWct;dt_68ojMC2G;^huD6#EIEL7oE304i5(SU!k zN-$8ewzTbub<(xYl+(a&hb;%~Py?wjP+Si#$c>N#kqp|HM6dCJSFJ5)G&X<}YlZ+W z*AL`qXsASLC%#73mm~>Muq3g>@203bBzfbldYl5sM@V)df<+-Iq&OsuQ5gcZ;qQ;? z|8OZQ7ZUPisWT-(K+G{T8`KFp;dFeu21?i}vnJ}HBD1BD+kc{rlv`%$A?gkk;Ya`o zj+n4w4@t$&01+Lp{)i0u?kvOx0ycyRP>*o`z;bBzED=RtkgNZbOqmHZ>{%Dbu@)zA zwmoHBtS)3@m!kgmsAet`6YVm~vFpMUtcx#EJIQ7ijxWIgJ>xvpCQK)I3*k$^4Kou< zJ)(JGbuUm+E!R_XNIlN^;c;P-uII#$*`#qzyLsu##x>?_63x#T;e8m<=7xsW=GF%F z1by0dZlmWmm5p_*?Ng&A$VFFwul_Wr;eX4j+VCjiHdLk7le(~Cj0w(5lD8rujA7~3A7 zX3pI@v!m(uMl@kZqgtUEU2mf?(7&Bc8bz&IoEm$TQ_*Uv)4I4XG>|2*Jt)omL7mN& zvT7Inent1z>-zJY_&ui`ZSt{=1GClul{H#hYqndE%Vr}_NGQVUdL30LC^+H zH`;5}*&2#D>LhOK;?HZ&C^mibz#kz8PMKc2-YIKW6wTPyo$5k(6(&?bT9{oc;+2pS z4$ZHqAF1Ub>IIHTES~MgDhjrrWk)|N9j!L&{*Je)os5*2*rMsD+RFeeym9QE-Sm@$ zRzO+|M?%o*jP-CyU;`O8EZ=3}3lmZ9ktks}B*ud}hCTmg(!=F+iR?-}!SGVpCE5!T zu!bfm23VjMnAZzBP<8~o>P?CB4$VY`mNmS|Sa0fBpXkpQ5^GQQSYI&K7drSV!F?

Xne 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

VIW*g`U^aiIF_8JX3!p9)zZAseB6@m!G<{O}h%E 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 z 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⁣cPXjeax7nq89H?Fz@ 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 literal 0 HcmV?d00001 diff --git a/app/src/main/assets/lspatch/dexes/metaloader.dex b/app/src/main/assets/lspatch/dexes/metaloader.dex new file mode 100644 index 0000000000000000000000000000000000000000..d60a75973e5355a24fb4b07cf58a3afccea94857 GIT binary patch literal 11196 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 TWeI7%SNvZ)Y`7i#8{Gc~=c15r literal 0 HcmV?d00001 diff --git a/manager/src/main/assets/lspatch/keystore.jks b/app/src/main/assets/lspatch/keystore.jks similarity index 100% rename from manager/src/main/assets/lspatch/keystore.jks rename to app/src/main/assets/lspatch/keystore.jks diff --git a/app/src/main/assets/lspatch/so/arm64-v8a/liblspatch.so b/app/src/main/assets/lspatch/so/arm64-v8a/liblspatch.so new file mode 100644 index 0000000000000000000000000000000000000000..851d2333dac18d7c971c92a64609d528b3511da4 GIT binary patch literal 473496 zcmc$n4}4oy{r6AObj`M|%SM3?Hn`x%GT6GLf3ttkZQbagY>^EpV~}P|x`d@oOwug_ z#DG()4ylS-ar#t$Q;VWh!5FsAL6rb1g zdIH(aecyA>J?C@2=bZ2Plk{Di8aLZ*Ho>m~@vxXU6QWLE=&mT@AjEuPCjGlmoFirs zb`N{W5ET30)u?k;y^W@`@&L1B+e^3@@SvgUq$UuTUXcy!E@ zk&@RmFwF>$#^tG_8>&EV%3V> z;dIbTpZ}AWx6 z&ab|YE=~E8`ItF9^dqAB>wDY(qo>Egd)3jX#fcz6mPn}VmN;I~e}@0fzWcM5)Z z3jSH*+EnS&#Op!&csd>Wr{Duq@TaEWLsRhQrrh) zf`4=h{>3Tyx2E7vPr-jO1^@XJ{C89EzfZwuQO9&T{Y$6d3#Z_3n}V;Jf^VCG2d3b? zX1i1(obOOQKKK7Z*!6!lI?DH3`>$Y9__u!l>7FLzBy*>?O>|Ix4EiklYkB@|eNLyM zWsdYX3&icjw_@{t0u_?|!_8EsF?OR;b}T-u+Ero*Bw+}6^T z5N*L&EZ!no&G4-vxI3Oqi`HaVJ~efK9@9oq#S`IV`aob$I4y$dc$A_Ig_B8f#nvr> zZS9TmU`VvJ1ru}!(e}7}Dt(A2MO#O^*rF`?IM+G3AVS2 zRuv==kT6goTIqo)nT~X_y(MuV&=T2OAyO@oa42vf8jjIZDQW3&OIn0tsRL~ka$l-l zWkiNmcT)b%6Us~rJyXbIoE|1mDC6%)$qWZWv2e1oLZ-20ugqsU+7=dxbcE6w3bb{Q z^rULbUO*k~CX`Yp4oF4Y;`@}c5z2hHEk%NHit?%iWKpFyi+!y5zF>;g*9A!T1ER+q%4I3p)e^GKahti-AK)#spuXuu6#(7?M_ljwggk@ z$#{Q|td5@}OC%9)iMB>t@{Ce@3fmi|;v(_L&{~zfwI({!bWc1L%}}n$>?j5KDB|rc z6LQOYL*ZDM?xn{CJ2LwyrKSy#;k35KI#QARjmiCHiS18LDjiLA@q}UlGWaB=C6I`O zl6Y@2WZoN#?heJuQ*qI_Wy3~6XD#xCjwG}Gbc;T=@s(5}m~M&4GxgHruL2&x@OTmU zm_9E99{Z+j8K`XmzPw*?H}I1WD((TE*75j&cWPb-{J7=~z>6PJ@izf?)~NAmGjL9S z1o$qU{si!}jz0r@RP!uwPJbtGPJb8hgF2ob-~;-+7kErMWc2C-p4Pk{xc_k#p5x^>kbv+%(BU({oAh}n@F9KP1-we9vm5v!&3k|!)w~Zl+f_gCK^=YoxS{QN5IEa8 zrx$e?hVVbtI*b5k9masWv^|UiXB~vT&d=SY)9D1xI&gd(p3AEY!vAlbP6IgS(*xYE z&wao-oprzu>2x*#=X7#>n9e2$|4*IHX5gGoE@zA<0pVxArrMtja4wfDaMrC8`1v}X zF5nT}?sWs_czS@>>3Dj9b2|EgbG!q<2jsw*UW34gH6H>#sQEDPAu8N890|O+Y!gZ<(+`=ojRT@@DY9930%mD33_z_FV?&p zc$wxsz!z)Y3w*ieeZY%L)pPrSmufx$+`mH&9tVLh*5QYMvp&PXtNvzYSFj$er%Q($ zh42m?ehfH2PpndY3diHu=T6|PvkN%uTn3zVHh{CvZr~oRg9kY4>;uj^*8yjp8-Vwo zsmhD<$N6R5njrixty?p2)-3^iK%ZxTvu;`7tXn5=)~yRT>(&iCTc+~W1Dtj11zx&9 zh3^B-y7dEJtiyBuP`5z{|8cF`5OCIQ1h{9lvcFN_tlJoH)@>X(>n3!3oKDuw3EZRe zujaGk~*hZs4JFl+K(#P7m9g55j*}>sAMxb@K!7(dSLTk9*W}n}PeiibsGy zt9b%=Q-unj0e-*cS>Pu%?*z`ebpdDHx`8)Vs^@b4P`6$P|0k_mA8^)f0QkLf;fG#B zz%SJkl_S7EcT9yJ1HSVy#l@P*?I&{=@aq3j;SJ!oJgK+`IESwT{)6KxydU^Cey(^k z@CKc)1n}o{JXzoiURLpR0ss2174HFF^8>~EfPY2nHURumt-}!TKgfkNdW`^I^{C=w zz}ucyT&$g}|AjjJF5u7oQH3{vhkvKI2l$QOQM?ZL)ml$K@RVHGqgONV&ue>203Z6T z3ZDgj`}2x-0S{?=>jB=Ut6%Ub8IDR>X?F@4?(oc)JB;Osy2184tX066;(gTN1_ zR6jKYoc)Jk;M@<60Ox*i6nIxg#n1V}esCPZm;YVqFD{#G58MyBfH&*>^M60i1Pn z183blz*#pR@LdN~zUqLpZVkX$H$QOJtqJ(rTUGp=Kh!M(;cwKsC4jSTS>*b>6FBSE z1)O#32F|+m0B7BLfj8)U^#Nzy`hl}<1Hf6gLE!FpYI_Fm(&NTq;D@wsBfwd=G2nG| z$}Y!&vu;9P=kj9RoWNN(7jV|C40x5!mjRr0a|37HJiu8uAMit2ZO_12w+7%xwQhdk ztXnhiK7Aem&blRlvu+vStXmd1>(&XpTj#3_IP2C8oOSB~&bsviKlW~=8|RP9optMn z@PE;|4FG4|hJYLEmAwrEXWd4Cvu>lnS+_CZtlK#7A)POwpU?SX-JHN#Hy3c$tqi#5 zeM&dZAIHzSxgq?8aswH?JiuAEI^bRUya71t<_FHYH34Vcnt`)!5#X`+t9&JZvu+vS ztXmd1>(&Xp{(~xh&L8U54dJiSy7d5O-THuw4a(m7k?Z-x0pP6LAaK@g2srCD4BW5t zH3FP<8wJj~jR9xf#(}2~Dcv}KsGC#goB3^8Hy3c$%>bUz=WgI^Zyw;Rn-4haRtKDQ zYXF|r`SJs2-I{>2Zq2}1w+Qg24{3V_&h<0{yjSa%1;@A4?LvvH2|D-8wAd}4FPA}hJiajs&wQ0v0brlqY(b*TDLLatee<4*&p`nb0=`t z%>|rwD+A8D8NgXLH}F!OFAs3m%?F%ys{_uuH6Z`E(v9(&RHb?XOS->r1x{Go1x5Ppr;Z3sB) zHUivJuk3FWIO{eBoOK%q&bkR5AE%Rba{_lAQTcKKXWhzxvu*}(*3Aw4(&jt zPsh*sL*05Ie2>;>K0Nk}n+1ns+)@=wl>oyFWbsGWBx{U%qs`E7loOK%q&bkSm zUejdujr|K8FfU|Brz{m7?FL2ha4>;@A51e%y0M5D%0)I{C zYX~^&HVm9~8v)L`jUxZ5(v9=S_Q|@9L-@5?H?euLzrnh>fH&*>^M60i1Pn183bl zz*#pR@Lf7zb--D-2H>olA2{pQ1U&M9(v9+??FtXmgw)~y>j z>(&FDb?XJ*@QBJ+A8^*KA2{na0GxFj1l}dTa6+#k;B0Thz`vk%8v)L`jRCK_T-oI~ zaMn%e>s(%}n-e(e<^s;Tl>uLSROQP6&bqmQvu+;XteX#b7vu-26S+`N(tlJoH)@>YkLg!29=d(R598mdn0%zS^z*)C4 z;0JX)oIj4Ab#p`b?OHbvaMrC3c$YqJ0M5GkfwOK+z*)Cu;H+B&c$dys0(j$hlx`W| ztXmd1>(&YUn2v|@hq`q`_-?IR4{+A454hN(?5!U;&%Xg@-3EcPZbQIXw_)HzI$tBe zU-_=mZ4@}`HU^w^8wXx|OvS_bL*1M@-^_oab#nn{-3;IfeeMR%_T~Z3y7_>!Zgs#} zw+7&4I$wU^y_z=xXWg2Cvu+XKM|C`$Kh}rqX$HcdaZUW&7w{2%-VK~}>jBQX z^#W(z`hc@;{lEuxz6OAEe>w=9bsGZCx(x$2o>2D2`9s}CA^cTZw=v+Xo48`KKkV1% zPT;JY3pndm2Ap*>fU|CH;D?@4`SJi~-F(1Vw>sdgTLbXU@2mJZf2dm%gug@U)(o6= zO8_6x=NaIvTNXI$)(M<->jKWYbpyXg=c@-e>(&dLb?XDpy7dD;c3kPk`9s|XA$*_K zZ3sB)HUivprLwX(>n3!1SqIk53B2!lZO_12w=&?DYTXRrteXdTR-gNTvu<_3S+@q@teYP=>(&JP zsLoe2aMmpXoOMe8XWcTuoj+5$asF6m)~yr5AJDpW0cYKMfRE|(Uf`@-A8^*KA2{na z0GxFj1YWB1H3Xb>8wSq0jR0reMuBHuP`YvcP`7ai->Y>KS55XeST`5&W_?};oOLsR zvu*fP~Q0J=-IP2B`oOSa9XWg2BcmG1^#`#0tA`t!sty=;(>y|~X&pUy$ zZe74xw{GC9TMuy7trz$aov%LNtXn^D)@=Yd>oy4d{uh;QL%_M74g;U_y6P83fU|C6 z!0WauyBr73x(R)q%Zqh$0%zS^z*)C4;QcyZ25{ER4V-oJ0B7BN!0-Q+(v9=S>1W*< zApAD1n;$sq)(pH)pGSbRZVBM5TLw7mmIcnbbpr3#`RW4Bx^)9*-FkqtZoR;t{k77K z^M|_iL-==V-3EZOZbQJ0ZOYz;fwOKSz*)CZ;H=viaMo=c_=wJz(9h?5v2IS_teXos z>sAK* zTLw7mmIcnbbpmf1Rq=EFP`7Rf{|BvG4{+A454i9vd+SHe^KZaew?W{n+YoTpZ5Vh+ z=W7Hw>oy9UbsGcDx{U*m{a)$D`9s~DI^WFC%c*|B1)Oy=fG7018#vpW2RQ5I1J1hD z0cYJBfM;~R{J>eaCg7}FGjP@|0(|ThZO_2Do@RjiwQgD9tXmiG5q;hboOSB~&bsvi zXWjaMvu^#sPwIRP0B79>fwOKyz*)Cp;LblN-8g@2SFGD8gzwb4jR9xf#M>wP!+w44 z1kSp-fU|C8z*#o~IP2yHUaIru0nWPlfU|COz*)Bj;IHWTIe(~I6NG<6>(&gMbxQyr z(B~Q8tXmd1>(&XJb?XAox^)8=e^&O;1Dtj11@8EZ3f~8ub?XOSro(goP`5z{|68rw z5OCIQ1i0sFWq+f*fZ&T>ela zy*PiI9jl0^>(&RHbsGTg+OF(v5IE~L1e|pn2F|*T0B7Asfg3tsW58Lr zap0_*(CKCSVcnd-#Xqz?183dJfM>OC25{ER13atGeZX0_I^e8Z18~;O51e&t0$!~1 z)r?&K9!LcEvpReNIO~=HKB~iW{#a+$trNmOq;=~8&bsvgckWR3)(f0<>jTcZ^#f^V<*nm`$aB066D&5cseT&-p_;8HVs7 zZEqvM+1|#0*IlFP={RuKP3Y_VT-MDAoON>nXWhzxpV0X-fU|CH;M^~GfU|Bs;DdIh zGv|-f&-JST!hclj<_FHYH3RR{=MmtnTLL)imI2PXWr4G9oxpt#m9H+~tXns5)~yFP z>(&dru299#`9t0MA^Z=uZUewsw;|xhwaVUxfwOKSz*)CZ;H=viaMo=cc%#mj(9h?5 zv2IS_jWd)EF5s+N8SrKup7Y1?v%R??{Oejb4{+A44tSS7Zvf7^`GK=;O~6^VX5g$_ z1b9s6D*>E!%K$%Eq;$&yXWcr1ckA$+Kh&)o!mqU3%<)AJaMrC4xVTQ)TR(E1e*@0C z4FYG~hJdqf!@!T|e2oBS-9~};I+bo?z*)C(;74_M&L8UL)cIx}(Ym>Svu+0Pgg$oz zXM6JiXWe|jS+_ditXl){E#E`x-|jk_N^H>>lOh%G+V{b`D1;!o@OBYC$w%^ z;H+C0@DY994g3ZD+#cW!#VS3$z#r1Q54bT$h3^L*(|iDUzvhF$S+^nJtlKbfM~Qka z=MQxoh49C;Zeze%H_@c(CCB5}=T6{kZ!X|$Z)L#Q-VESuZ*Jf&oi7h?wl^Pe)~yaW z>(&5V%vHK^{y4vEZ%q*XZ(6rz;H+B$_<%mo0B7B@z*)CW;H+C0aMrCGc(Kk`4{|*| z?FBxd!}kGa-THw)tHX2tP`5z{zqCO03q!zJw-Ml;>y`bD0%zUEfU|Dnz*#q;{D8AE$@y%?II|wQhC5SvNoM9(~>foONpk&bmc_ zvu+9CtXl^7xXxD=IP2C4oOSC0&boC2Z+5AA%K1axdLjHLwQhaDS+@b;uAR!>27$9~ zL%>H3MheBEVU<1aQ_Z1H5j&(v91W*WqK93;R&rJYl-7>(B>hM|M ztXn7WK^?vecw>diZ#Qt(tp_;k)(d>3TH7;l)~z3Tq3Ra~fU|Bxz>OQV-2!KO8v)L` zjRI$T8w1X|jRSv0=S%44vpulAIf1ioF5s+N8StiBr5opu<7eI65PrSZ%>$fus{`Jp z&l`ZVZhqjbTN7~Btr&gw=8hhtrPf=PwB?_L*2R|d`j!q1Dtj1 z11@e-_SO&l1^wIs;KlL}F4Aid_*%_}fU|DHz+*c62=EiDRs5sCS+_CZtlK#7aUBom z4|Q|ud^5jK>*fN^x*5O|`rHki?ac$6?ac?A?X3(&6=u}10R2hR4^1e|qi2F|)g zfG5_f_&I;957*NSg#U@wEeo7=>jFNa&%1%MZau(Rw_f0^TOV-NtsnSpI$s08S+_yp ztlJQ9)@>O0j&({m&L8SF3gKtYQ2oLfaMn!(RK4VQ{QBGpoON>nXWhzxvu*}(*3AvP zS?9|GoOSa7XWi<6vu+K*>*};U17~|{0=`=7)(o6=O8_6x=NaIvTNXI$)(M<->jKWY zbpvnI`RW1Ay7dBQ-THvDZvDW=bo`t@wiDKE5W+{bZbQIXw-Ml;W@Ue)z*)C3;H=v? zaMn%e_&A-cn-h5b24xQ};H+C2aMsNL&bqmQhc>GCIe(lU*3AduKc{u81J1hnf%oY1 zCg7}FGjP@|0-SYA0B7AYz!N%OS>UW&CveuS3pnf64g6TW(v9lnOB$fu^8xqk z`0IdoZBzMe0M5GkfwOK+z)$#9Je)t&Edt>`uXRfRXWg>M^?4`oG5y>w;H+CWaMrB{ zIP2C6+<3dnS08ZScE$UFvu*>xS+_ypP5SQx4gu$SIt=_LTDKA4tlK#7k&H^GXqjxE zqnbN`k7@1#UUfjlQwDtDEs7h!9k(j(241GQ2e?~vA8?=Mb-bVKv&UY!^2|PWZco*=D=H0;i`&IZJ;4d6iychWRgNpY7e@%xU zMDACA(0mB^xaPyaPij5_yzK2No>Ab7H6H`+)_ffJa?M?#$@aNJ^D^K~nj64(Y3>G| z(cA<4pyoc{otoDHKcsmR@Z(o29h!mn>hKZZ_iLU2KB##H__La4fe&lm3H$}kdw_E~ zdw~z>^!EXOR`Y(~W10^DKdJd3aIsz68*qo_qrmy^S&so9|Ch4!ap3&-tVMXT{ru(+ z<}{lq1OA$}X9Kv=rqbyKzF2b)@OsUCz;|d~2fRu12H?9iZwAig6#;%whfe_S)I0;c zSMx0Je$6|9AJx1I_<-iUz>mE{>DC8)Nb`Q+RY?_o0Ju-{LEuMURpmGY+^PTG*(h)> z-!b6zjzTk{ao`P_i`L2Z6VluXJfXP@cv|x^;2F(5z`1;Vz?Bj>5~7{C`-DDDP6uuSnf;2gdIIEQZr z&d<#NU%Onz-vylG?*_h5r?U@uq)Npz2;9F)@gd;H7b!jr{Fv5f4EXZ-GgSQro;X8s z5t*#>IO`8QTdTqwz}?p=?gsAD+yi`v=04!Nde!_x9daGM0eHg~Rd_#ekLFFl5AIR@ zU^DRkn-z}$Kk_xj6TrK^u6PFcu;y9dhW0Z%fk!m&0^X;2H}EmtkMscdx2t}k7x?0L z>HY}mjbR@>nq@Jv+OCveAJZJ)q*X+8pcRP#~bhhr+9G2ret#m9jU zX)dCZ?K%Ap72XNFEUCB)_z}&^fO}FZya9Ynb2sovT7~xjcXTN31AapDI^b!|8-VZH zr{eJgAJ@DI_`&@ud^7NI%_G1&Gb(%n_({z(z|#j*_$=^I%{zfdZc*X8fRAe44LtKs z6}|_!>vqL^fqQxs?*ndpPw{@>%b!tv0Qs=ugTN2Hr1%i<*M6n=FmTte6(0d!bwcq` z;Lev79|PX|TgAtL9~@O&+&tO-i(ggT34GU|6?Xw2{FrLbNB2&S=b z*yQj{HR{|6Jgd12c(3MVz+JT}9s_vQG4)(GaK8@k0nXulz(@6S>wvp;JPp9Rt5tgZ zz+(@q^fUn<(BUJ%JrAgO62RS>XMhj?Nrle>_vrL@0)O^(|xi07s!)p(~Fc+YD} zx5yMcf&8Qjp8+1#e}_E_{OM8k+)m(Y!>XU{0$%ov3f~RT%&lvCx zI-YUhho4jNh(1+5Y!9QqRPi{0e`r{RcLA^OSG){(--wFG0RGssD!dzbtB%J5d{D>Z z1ODAdR6KRS>wl$q1Mu5kQt9yn|FqV#3HU#?{WJrQ>3AZ*>-FESPXIskJ(Zpe@WEG9 zda}SjbwY*j1pcu>#k+vNpyTNV{){f)9^mVKsp9Dc{+f=b54iDT6}}(%{aUvH;GIJC zgM+}opz}2Zyjs`aVc@SgRXiiWAJlq|0zaYcY7F?;92L(v@b!A$Mtp6u{lBd3$_dcan+Kmi$fN!e&Ip! zVGCD1h~gs_PEqAwqZY1Gs4k6J_>6pLA;v9SDX1^DsWX{QrzO18!e?5z%fe?_c$tOI zws6D3i!I!3;d3n9W8ozh?z3>0h1Xg5JPU8I@c9<*x9~G8yvf2#Exg&n&$RG}g`Z{N z2@5~l!ZQ|LX5m>2Utr;#7JiO}cUkzk7T#^)3oX3I!WUV1uZ5py;e8fQ&xMAS~ z7Jh++4_f$z7CvO*Z?o`W3tw#EBNo2I!bdIqA`2h0@TC?$ZsBeV7wr@Fzs$m&7JjjX zyDaP zud(omh1Xhm!oqzPp0V&%7M`{6)fV1q;cG0s%fi=Mc(;YGv+y1ZztqBeE&MVI@3Zha z3-7n^^%g#0;TtS`(84!b_>hIyTllbrZ?fGK<1 zD;9(Azm=7su>Q`hz6L?Ua&fTSdKdkXKwBAo8n-#< zkLyub`uvdHNq@lWXg<$I$aRRq?lASCPoxh;O#0C0lRDq$MqHzIk-3K+c*yP?mf4nB zdDe`Cba~V3G1n`0ahtrq%kHG#wI4EL8P4C|EdO{_>>ynqvpK1FdhO0WyXboh*C|o4 zu2Te&1xx8W(^Gn|KqQJg3&cJ4;%os4eVZ&ceT_h@m;!X!i|Mz|4qL7*mp?)nk@S$g z_%*xewrBXha|B7Yqm+_)*tV9EJYp-p-%j>IqMPyR>%_WkYbn$Vwqh#VQOk8d{ia9h z5xcm@wwA68+lqVa;)Jb9-(M`K5%oFNinZjFP#(?@)M(VZ$R>9b)67$IKV??(IU*(~ z`DC~m`k>g^^h`l-7pc-~#`};>)&Ld0QHaLk!#2?r;qYged2w~xMW}elCK43C8TM?t zThLpUUcarFa(T>ld~!TJ6i@!S#bUV-%UwIfS~}(qpJ|&Z(n6$-BQ{H8Fg0IfD-j7H z5{vt6wtH;GWcQikn`bKw8C{d(IvtboP&s85AGO&IOB0q!&cDnytJty7k|Z;3$LU%A z=jvnxZ}HyKJp#;tP?7vu$GqBcio2aAusN#3JC*4Q=N`osV zn%E|r9D_F7E;6(UvoPbK#=>2k5mh9)c`i-SnGqRP|4KxI5DmVpO=N9E%rGv|NpW=A zoTOZrq;y}2S(nx_(cuOt+yJ%JHtK~`Us5b&{dYErCUu{)%(+V#RF!gvFR+z1mmam- z(iGyDt(ZOy*(N1dKF4VkH;Uy|X8hLAN)KnfsF(2`UT57=%vQQ?r~Dm0llqb3o-@U|$vy}@9 zOYhMHCva1ZlPY&jCc8L9H@>q=en{4sqba`zTk{t+o8z<~k z;>DwO8#%<}xQyA!x3itJQw_4jtjc({zNa{Aw?;?WUSqr5^hF$LYJ44?4q3|%Iz-mq zkadU`?2E?=M7Dr>#_j?KeLP%1c5;6~DSdpQpp-%!ayYsjWP9+?9F;+tySU44tD?3v z=AaJ=YS~9@@{=WXru~^^;E33KlWn4-J(UQzL|dcbkdZo&N{8D5Ex~knPds_R2q%;A zq_}p+4x=@mG(OoS?GM6|s%F5Hbb2loY6#)9p8R_=%-j$=qob!~j8>w;U2l!5KHec?pY+gVxHT4T zNw3_L3Ac2l)zf#rSqMw=w(Y)|ZeMf5smS_d9ZGDyrm<1PqPv6bp=3N7YTaL+ii>1; ze=?d5H?_sC4!4Gr;r5nrYHKhZ-4_-u!B}i}uw}2&7EVXvAtRbH+T&>>*lvXL=@nOO z-O><_QQ=smh_**5STe0|6cZ|6OV1T_Wpgwf3t8@Hjkbr32^Gpo%&oz;u&`u|i(*O2 zXw8eB49CL3RM=?iNQX0GNow_y&}w5zN|@yy2(-rH!L+x+C%^)XXj^bkv^|(SAob{I z-%pR1_ZchbpIM^*y1=G}fPYh2&?on+;{T%Z+4s4>dt?V|R4VEV9O0YT~Me$6HZZ zRb5l-TeW_}#`;a0g=)N3MB8KK5g`+2%1N@MuMNgJ!eaMh& z8gx5gD%}!nm&Um}Y=qkq=>t;u)0X1DYj0_q$a?w3A{D(Q9B(y*aRU_@wTOXe>*_bm zGPS&ccx!8l+SgNa?Oqb=SZ2gK(gwvzcDyG%YnDi~P>GWUB1ARcD?d@)tn`YFTQ(W{ z!pW4ZV7f8$8dNVTMcW2h57#FWv8bwmRJPX&sxRB4do~pdyM8xSJ+gImd6U_%UKLF4y*8SP?v5SULiLCm11c8Pghb-h zLWHbM?*?TKYeWmRPkRHDJ((W&#>Q54Tc{F6_mMdTWTlneaCr;)4cxt7l>fALZT{nJ`A?T#Dh?#l?R&-Q z)vd{Bm1w(0?D(>f@v%M3DDD!gPk-H~j6LwnOz zERbqFjlJb-*+w(E-DW3Zq{6{uOT-|v+80blrBxfTaQmKgMD-XXtZc2z$tuYhD?OH? zBQ1><5LReLy--n7q> z470~hYCD@SR<8O6*-u*{9;1H6a+BG2S$b{hd*$6Z^VVn!`g4bukPX!G3HJtTb1u;udI-0D-Muf6J1wv6$ z!SA5jkYb0)5~B=94wI_8)b>cfX~Lgk2XZ~TRHt52u9md;7AdFS^o@*=>5U4qy|zS* z+?KpA{f1RTHNye29;$j~r!;jhR4F#sZ!#jmlyOTqNe!G?A4Gdc+ivN|q`1ElZ5x&O zPo#WHEEe7qjIGxNxhc~UPDrOnq$70Sx^;%E<)^C`7JtNScGoQ1NiNsk@Rs&Sn4DZ$ zFGVOA+ZWxtQjIoNf>VJ7gqPhrsaGJ|NgnV^k8pD`-nK^Aa!La>GW_S6OWhVr6|MCbrnD_0$VJduzOFgt7N1f?T(0mT_M z#U&SzJYBPo?}&wWQ=K9gpE5ov;5kwB}o-asUj#h1`~;u>sx4y5ltVUaTocvP%K;8l}B73&X@(MJW%OhSCCsL zR!AR)+M*S0!ORNs$ipi-s1Hl6^N4tIPkAhrh^N9Kc?^|PYqu}j5-t}@VzJDMB^PIm zB~>ZIJYFo1A!A8Jb#=;GbX=!Ym0M$}ZL+NQP&vDoZMRU}I|}y|jhsR9cBzJ>SCWD& zo2ccDcOV3stPJ;lxKQG-UqZNc`S)ML9{lz`-3zrY*hoBK%gZP z4D9I$CPM)|h@&>BCD^eik~ZCW=^3czR*qcqc1;adASffEfh*NORrOTwaFHOR4`&Xv z$5X3(UXN_j^0pdGw$)TgH(8Abte2>as4h^4ogaG9^YS4{wH>nE*d#0ccJh%#OGlDM z$t2Ds`)%CrmqsU4GZ!!?FUYr}W=_s4kh|G#tY~eIuTb@kWTCd64A-paRDh`z329uo zBz2*n-arnvZ+)j!SbC|lu`5pWG@>}*AP;>w>ub8%D1Njs&SY`axC$4 zEtnXTTa3VTfhWvEnT+MSX(SW#Aj=vjx4LG*BmCiNJioHX78acED<1 zrhB_axqC8`=Ab!m9~VtH4>#PHrxUKE(H`D!xp3P$QC?myrw3?8ASQhYYDr{IlWz}G zr?!VQ6x-$xB%P<=;R+krP|i|fOg%`|_=GaS%T=PQq#B-2Af z_cE+IlO0br=36!)ISrfSREugj+3~(TUs9LSbc8v|l#QsGW6jS_s5yr~f;_u$1-Vx| zL2(+#;Z2)abAE23vCULa)v3l#T>3`ka(o<4mQ! zC6L`}13A?uEY6&2-_{5{P1j*I*0E?Cb!X(f$Y)P#gimcc*HG6kEjGNZmD&Xw($Fj` zeN=7%`NT9IMGd@IBdEeqTVzgF=L>`Cho1Xhk^iJBW+)z3Q?e8z&9+LX(OAlXmkRCU zTimya($dpO+|Qjl(yd?z-7+0YlLY2``Q zG!3J5M#s`C>7J%hj{YVOov;GvN+jOUk4d$VS~L!8FSRn5p5XY#J)FpC;?vcwpTDS`&ga*12XASegs zeD9=%3pEdYiknPh6q@nhos5R|kgrUw;wBy>)6@~Qkb!;C@cz}SQyp?D$x##ZMEQ`>RC$ns5+|@?YY%R%PDnbrf*pTzMCjG00-4OLHFCz2Yv#oht*V^7 z5|^5tr8%`A;_Y&*LuMrHX`7tYPMfaLWCx10w)P)e)%>A}R^}&mxsz8*4CY1YRmxdg zh4k_lIXo-nY{!Or$B+)ud%I4n?j_JQ><*8k6ZUn=OTKZ)v>s zoo_n&*&?>@jV8#SP?NA>(>1YJi!?IIletnt7HYN}ZegzcNauYo4=vtg&@IbyzgooN zd4-8Vx!9*>WzB+1L??=Do#|BxQcsVVRlP9CAEC+d7}f2x8KSa+<{sau#hn;epW5b5 zG`S%fId9pzSIRL-eN5xJt|!zXTDP9dfxGZbw+}xmKahZ<>Jq_ zWK^zwowE9~KAldUZuv*fqD<5{v(CysENRZNnRS2$8!dY~65`s4k((*tbp5(5)FDPY z+Um8RNB&(ZLaol;9dSA0%Fo@BbmSvn@P_ij4Aq-V;>MEXs{5qFu~N?($fI;8R+7gY zR8GfA<#cSMnX-60weOp0DxFsAwx>IGqpK1k=RHXc=!9I<2vb2&zZ|2Hr^wtw3pgzS z8eDLRntgWD&cKFiHU~Ccef74htzpz;H8tt`lX5ZJ^dK$}Gzn$#P4aW|?wuCOZRo`4 z&ANQ2t1Fc&4-mGu(|T4Uo))U^uJ>;d`FRPm{h_(!D^EX}?DbI|rR~r{YTE4Rw$yKG zo8%CwUc#CJOY0?lqsgsXzJnFyh0~(G*h%|EQxj_hYu8cx*wOZ8!v@+9U@l(=$m^l@ z!CYpbX|r}Y97hjEcC6d=Y_b~Ok+(@pZE}pF{3;r18uE+`#w(|3c&g{rxvVuZVYFfu zFqfmIG3q|eB)|r0Vp!-RHsHq~-e4xA{~A z6DDic@D_9Ur-wPZ^&xNB9G9ER&jC3xAI>+BD^`fLvNKz5nCmd|V}KS7Xjaa|mx@q_ z^dk&&*x)tDp-si94WiMUAs5+Ak1!RKGalr}nyc9~E0dsg?__wnL54*Q?|$le)%_JR zREPr0zAPWk+Adf}9+T%O)!gK2ng<}qk51(NfwWO&$i>f;9JtDr8uN+qc5W(%GGGy1f;qRZ}x%scpL5x!{5e zXa+@^2{yNFw)wRb!4QrdkJ%f<63ij#i=f|rLa%a zVK2MkbZv<>mN)5FEzz5{Bt1kPQY{I#$|+Q_bhmV!S742(r8n!2CLz&Io8pJLnCa{na%HH3g{h9N@FtB ziMe~($;tV0YW?NdO{%Q|>pdA}g)%#)VEX|Y=$Q*$`3+BMsY@=-Ow=sx|5%99=Zydt zkZKIAzRdsAE7TCWmu<0(j^)ClxrD2XN*ekGbJ%X_!A&v9qmi=?+PX!4G;Mk@=GZnI zqD6>cCfe4~X3)G0`Saz*4%y?Hqh;FJlZv;|Vub9rO$W4mit+O4=6%i4*^NxM%h7>pc(PDwD$-mcqE!Ix@J=jm(qscS-%Dur(wu!V?MQC$qfsAep?klYDiNW% zNRe-vWj`*PW~#<)mZq~!8#L9G4RU)Nb@-lq!>F3+{3bt{O1-ng92L_34cb;!PE|uL z#aJuiv`s)3r^U+nK8u@v!$!;XQ_NCZ?r9nZYtO;MadX<&*dL*`iL?ruI~OOGBXu*k z^wxJST`e+d%`_yZrp;9cH8;7vgSt~Q6}(adzB+Z@a(+wTRG7tL^PY^g2j`rVS(+OZ zXeDT(eyY6}swpD1$pFdnXpw~+&WTa2UKm&NE_t6wHZ0aLJX_DoiFKigMe-GwUM#f3 zn(xrGyZS~w+2vcW3AED=1vzD=ccx9tYj}e(gSG!6DNb>aq{eHg+6VQXz4FQ1KyTP0 zUB4a44%+P)q8b-XPZYBn(W#k3x%WwKG!be=aC0oU$GXqb^!)XlXsUzu^2og>=0B{=f1;fWQF7)zb4IF=*`xX=e*zE5pCHkCrij=X+v))EYx0`(|McZTBgm- zFx2wXx_XK#6gAe?>DAS=Q^`0G@1Ri-T?^(1i+V0r4nk>lZeoi;gjV4p3VMjNWE$K_ z2SSe6bT@Qa-bUBblmfRDOC~-V+8ttV$k-RBHb^#i=4vABF?>T4rro7sQv8kgOoeL9 zEvj4Ud1+YgoZ@w1bJvV%k+e^BFKzre-4+>|;|`lsa+Yx(xx<#dz`@-uloFbdZ$F)d zSPW~zW@ub%;c91-d%KnCHFYfMc1QEN`S6=}zCUV}^XF2GtIq>vhNjFO0E$jwuJ{tY5S14bG*%8lP1 zp@w}lpDf!Wl8<)isQDdo3TdV`*^x-+chH6CYdg|2G{e#qFEtw(u7~--h}cJ4IaKFh zY06FWKW%lQ>OkK6X?nSdFN?i zxy5K@Go-X5Ydm$sAX}H*2$L80wuv3qm#8^>+F0EoElzKPpq@UOG8Z_!HE*)OA;C4GF zJ3} zZDM4?-O}XkHI}9z9{~1KTB>YS&#&Wyqduxp5V3T-G7@>VEmfB{}E4 zKc3uMF6djUmhV~0@A~p@ftAV=emVGqu+!I}&6o8zy%eGEeA3JIwoQB9|K%UP`uYox zbnn|y;o{#wyHq zwmt3j#^QTu>eGytu6ir1TX{`jUDlJJlGbtM7oqe$HrrOOM^35BZ#wPsQb!p`MWSuy z_nc_wOKY5RIVnIb1(uWaQ--LZ=u**B15t8U$^DgPtipDSZNL3x+h^?i?f2Wq=(GG! zi2e3|(dTFE^#%LwwFU36|I)0T>gwcw;{~say9-v^es2G+*lGKk{c+phDTepkz98N! zK5xb+M6vzsg5~zD;vCzyf^u=Q*l#N^|NFW=7T9jkpM+3X3T#OmhhoCVUs2eTwx8HO zZ+nV9J!AVJ{j2VmMR>0n)2noUr|n~=-Q6!fVf%{hX4`LV|FnI_w%&fH?P3ado$WTd zI*{Q+16-VZokN`?zlqO z&ATh?e(^Ud!-~M=joUV?Zwv&s2B?_nizRaRLcX*0diB?9rIRPi{7u4FZKXl-G{RMQ zH`0R3wdPdhTYG{}rbK$+(|C&4qdb{uCcdI-b3D19cJc4f6LeRzmocqp(V7jpA#xY* zw1WGodyQtM8{A7<^3!i2yibo$cBg1JU?M%;$9QNUPTy&oX7Jjr;r-JL>h;u{8>Xij z+_#ZD%xQ-8R?)y(&tpyZmTJ014Q+$deGDZjHEkU$X*58CN1E-OZi=e(Tx6r#gf$Hl z^2zNo(~Z8ybPaXnTWJ1yOY5d-Ji~kHeWCyGzVNi}t5j1p(^tV;eNB5iH3=cvCQP@Y z*K9w~PU~+p-Nsej+<-gX+r9ExlkTji1^#KsSy`dxfP!-N>_3g9f*M(K=KDWMK}9v+ z#YZ#e(@cMbchX&cS~8vHo!;t=R3AE$X45@QoxPsMVB79caJn|`-9$U7-h$;+Zq}2h zrUcU{KHuheEHus3R8*L;%I{K2ndmP1VG0^APvbFO&jz^;J>4gHt5xu;Zn={0D8WeALxy7Dj%3P3=e$iXl*uxkR^jWq%=b;_o>iB};=6;fx0)sID(!_*p{CN& zG)>%0tEyJilFBrv77qPq_j^6-cSm;w_sBh`)5u@XfQ%||fa z3hv_8(-!n;eY`4)lCm4C& zn2-E7K={aW%0x(&$d6?{z(7+TKri2j-Kjwc#rs`__o+jzg>Bwt<}_t=XL*+<6`lD_g?}1g53Yje=%E$ zy^*Gdn8HMS8 zK9~E^1G(IdU#GBizU|>$uJZ@E9H-$yiu3>1yN{mzFr_v8U@rFy%BPpocP^#->|f?` zS5rD8#H)yfNQb@jIW$CCd_R}_G3Ccg`F@1%t)}Bi%JUY|rXXLy`*-367~ukhCg#I?Jwy8iO@ z;oZVGd(ph*tKPQkoQq0J)>Vs3&fve%B8{<*-rsuk`JcXc+s_}B_9)u~xx~V2IWkP{ z!2j}}QU7D}PjeV_KK9c8e2)%7lrOqqPR+)PuUv5X%rh@5+qu)bQ@zS|8f$kpm_g(} zJ9p0BIs5xNKlZhqJHOf6BZIhgKzaD2`FZxvoge@D{hxm1zR&7Q-#D^!=M(bty*qb` zo!>rN6wE9tESkqJv7EB8V&2m8&zH+j=0D=zPk!=~%XZy;r|itLjv zk^L(DLO87zWjR6bq7UcOTmJ1RwH8-LpL75-<1*Jm$OS0bCi1$WWb(6Iilm8q^EI(9 zqdsXY?DQ(oe;AIw?odgKw%!VI2;>fX`L*&Sb$#mVy9$zjv_&qi?Do@-zP*+3@&^41 z)9;zm51tBdjoL=C#ee12?SWdo{JLrDc5h&nUcQefw`{KtY@(On7r0psX8l*TsEGc< z`^}q`auaKU^89Z(wZ@0X!^EYIcr2q1L)su7$A)t`sXZQ>54@f$B#y^{N5^uqyzrQf z?#an=$D=rZ)<4bS$747!i+Ee4H_4quiydE#DGI}e$Ro-fE zjknh8^RBA!RCp^YDk>|gDyl1LDrzfy6{{*emEOvV%F4>B%IeCR%Gyd_<*F)AmA9&* zs50s%vU$YHNHo zt7<*9-r9=V%G#>h>e`yx+FD=jDxb&a^;P&PeO10{UyZNU=ku*vMM+#mk6%SmucF&l z5t2*truh~)=v7!)IAg|)B6>NU&Y3f3&Z5`s*|Up_i|5d*q@-l-+_^4#QO%q`fBqTt znzU|DI`fOyu|pb+%0i}>YpFW+yjNLI-3Ikn-LfC=Ru^9St1Mn2zJIU!^Ft?Q?=b7% z=)MMX4}k0Q&yLFLJ;|+QvY_g2as6c{9kWjyx&1ErknhC*{NA_G@dGzzHnq@0LSKCF zzemWu8GXOwZBKqc*a~DG3yNk?2ItLMID0{H=^R(doVgBH0p)1sS+=ta%j^pZ&M8`G zUt~M~ETiBOT18wjyWHj}@Y*YEU$oz6|B~a&&VSnfRrqhm>jk-)U&$Q!;9Z~dT-Wr$ zLtP6O{i0;q6nXK71bqe*CEyPrN)fXWphQp>X!#*N=Ytv7bCY_NRBh=YvPS@a@MQfAZ-c{p{xr z-H-n8iKlbp{tw;#wf}zjvF|+b%*_-w(sc} zd}`>K;h+ANR`O@qXnoXSC&lfv3TN9(94^~D`~1Q)=9Svcw4ZHXFlS-mBIjb;%>{ey zM```{+2Wtfe9r#7{b#n3!k6r$_CFe9j&b`x?4-G^cISwMGMZkaLJ{YJ^qBlc-xYT+?Br74OcY!w_kIul&iTV+`2cFdFQ)6aO6u5 z^bHJs^??J&+v6VyHrW8NM2mt?Wc2Mh1)D>!Gyo&PSlzUa)^XU{AxE-k)!#;h6V%(%YjlETfi zmeX&!+X}q1mpjgxF}ompKV7=uvPQ>>g0ypO!Q6tiMLy>xg?HxWl{r_=TTx)RE|{A= zDlKM>~vf|GyCqcg|p6@+33iAV8)k^6rb(ze%5iv&n_w|E-cJ` ze%>8zu8jNQ8Fck7NA}wV=N8PJbJK;l78X#tS_^C|%d>YbD)7!-=vX}SyuwQg>m4N* zXTLOKv175r?W~$@%XZySJM*kr&TRLpf)?jY&sl{R6r5XVtMfUoEL`cBRW!4x&RFUw zo>^0{y6~JLM{$vVOKs(x%A#`TtUE5cdaK)c@wE#}&z`x}ao*gGB@2pX&1i5go!K$_ zvh^3wSW`G_#@lDu3S9+-*$?hMufaJh`-Ph>+%$XEj5%klDwcRPan71Sq3)C^*Mqzaz1_ z(DojYeSTS^W0u4I?s@f%>$2ZnJHzI z&H6y%{r`SCcyQkS<6nMs!!0lWy|0|Knd=9$xUPrn4V@ zX6=jH?)pUg{CCfO{=X9IWf8^} z@$vGbpZgl!wQu#_*}u&9Z({fTkN-aN6_LH=?1wLUepqzf-(Hb<@B73<*Uh@@tjK-h zvwt}L^ts>tanHfhy5QTdKREdL1zq3#eEjpP=Nhjqz554Gzh~w>iAQ z=MD^1W+cJovX8 z=fzfkeD)dlK6GZ$Q@1|-iGd4#-tet+zWeCdUpwb~!~e;BAFuem|5ryYD?R%9l9$i< z(6$A?f2{ULL;cUZ`jM{|78EXh;>!=8^W?@S`X2uH%ZXjTyY=ac+wVT~mlNmQ`PhvQ z#yy|;?CzD-Be%}|))|LKN0)4S;pn$der7}}U-94!<(f zcK+itA9?2GAN_7?$p5xSANX#|Yv=v*vb(;2_u)@G{^eKyde>Qni(EI)+Hm~QFTL>T z_jO(W^39jta97C*=lIi~>b?7;iTZEecg2wdXNcea;w$%dFWuMD`>|CmznK5QCl+u2 znzm;uAIt0i5cf8KQB~L8_dYWTOojj>3?XP}!iSm!tN{ZgHI@lP3=lP9+NM|9M2Xiy zQVkm0P_YD|Z4|5-jg=xwwDh@23T5yn0~Oi&@{h@&Ej^`RboPGVQ@pFaPR^ zn;!YrP2YwkUVwNH9Z zE}#C5yZ_R>ddEXculT{q`9J>Q*a`7F9+}ql#_@t%9=$U4p4+dQ=x+V{ElGde{c88Z z#81`E8@oU8EyuF2FMI6N!@vIfo=d(~F~Pm?g_i8kzH86`fZmyj5=G*t|{k&4|fBKGVfAp-TUOjoqhTCdf>K~82 z{BZn#WLj>oF5aQsn|?DjZcnyz_Vc~Fyw*z*_$yX3Z&-SRe5R=>zJf`U3zPCbGewf! z^Z!T#_>e=($2hQ#NT)}Q^63AL)D~z5*-!ebTA&5^M*r8O?l-BX2ouJr%e70jJ*4gq zr}@9NG<7&xipKNh51Kd}{7)Jo#hlQiJ_bt^@hpePK$h{ZRb3>Wg;_rpS$go%ko;lo zO{TawA&EH#Y9l|<$7<5Wo^c+}r)H{opH5nul;rzD(xplI=To{hqswzAXk}U1f8=sM zXhkKrncu-md1dj^S=O6mpz;C*xi_+S=~t1!`aS%X8FpRoHtuXG=BAyTyY&Y_^Q(Ec zOz1Pb^2H&JX#LK0Ohwi$!KG%U*6~otU%b*k%T1IeI(Oe1>w1QmzHefU`(e~?iZS3^ z<<0$%xyGABxP64XOJ`ld<0l2T8uzqunWUJTXt~9fwYB{L+r=xcyKy!|dAQnqam(Tr zSF`gm+rIMwg*%eMpP2Q{qCUOmf?NNS*HPF%vC8M($g6jFjPIVisjX~oAy| zxz#Q7cMtB?omppyML}(WBFME4uWiK<|C~3a8 z&py)5VmqOOE*(07=ez5+7+3Z#iRT@kG*>eZ~-4?m?_ZIG$o1L3qaXT*oFf5^$)8ClP->#9N z5#hp>)NKpiWhnqc*h_8=N{W9#`C3o7#ZIs8^gxU0+6ZHbZ zqFK2F-0RJ^q3KVZb6a}!$XD|In=$%;H>#+y$qdlb#eF}ME9!p~;e zLioJ0+w})G!dC!HHBEb37Y=4+aT}KToc7hlOZ{J2#$|;eCf_S!O}f=?Eepa=An)}))uXcsP+G~K9SZ4)j#{T6|=9nQGfUE zH47J-Z~nc}c=7MT*%8is9W&^>YgR10`JTIPB_GKun{~y)JNf%0@(M`fW&oSHt@fQw ze!*;8PGpV0Xn&qHXK~~kHfNIz%X5Rq-)S;t_q*lg3WI$-hCZ{-Eq|8W+j>sv_PNv6 zpXZjJo%OjY9DAv4!$L z@2s3_@BAun>bRS~vu0T(THzb7un*;P$jiOv=DTj;Z%CNVsaF!A{yF$(7m$4Eel0g~ z#Izpvo$f6$&gRxYl%*7y@3v*s9&a)(~RENPJ~IlTJnuZY3sawCn59p3X{=J_S0 z`6@2XyrIUl*F5vJ_PN%((#y=0KkED}nMsyJyn;Kj3!=);&Z4|2TYqb}Bzfkrw(7Le zL-E4QEO=o|8!b(fb(xLKK6x?!K zu37l=*V@FI`VW?8MiKM8@aM2v=7z`!_H(c2)nt{<{WW>qrSq=(l$N9AvrVLF@2Zbf zmrBsGw8ipF@%YhhkK3J?q$Z3@9GjRpCOLJ=MY8eaxj1fo`shz5v(=C^ZH8NRmS$Dl zTI0^TVvfg=*RK)~FSXH*p-O@!te(LG84 zE^3r_QGU3nlusF-;h~|gTaD25$4=*o=go%$dqz;7iSg%&=gTLdauoH+JpqE&@o@2c z`8+C4O^nav8Tx3%&unzPj~E~F-z1$LjrgOD9^J3@@hRilK8~$%Zl}xrDR#PbEO%52 z-9k%_CEqG%VRSj`*eX8=qsE0bK4SY>c>F|`8%%eY<1040l|i=<`$U&#b5X{pBMQ$| zuXTQqylDC6@gRFd^g}oCFY?A> z=h$epe=K^&K5y`iHu(pm!8h9EAAJ67{AtRQKpavA#z$c^U2#9`L{}!Q$x@TR=0+C|PQ8`cY|4AJ6HgAfO0MGC|C*hfwiD(wNhKa z6fkXtQq|yYj@N<*z{8-68#p_`63+YYqCD6S9tAhv4KL@nfq7sTcTv`Xye~>MfiuCq zU@>@5&Vz|0k*B~kFzsvHMFv*YP##oks0(y~z2I`t#f@;juhR~}d*P{2ssStlyTHxR z)7GLlSPC8o`C~U~`ULa?bHE<30_+EC!18Y>wL{K>HOTR=gC9Iz3rczL0GP5KTY-6? zx)mNUISIRf1z_C$=nftSo4_7$FQ_)qUa$b{2g^Y(H`)0%(l5yA0(~48ev`U6?gw{( zDc@4+2$%6_>q&gX&KI9>}@a9j_zbKDNraC{it3?ARCR4W+w5bXog!G5p^oXLgj z63_=$f+gTKuom12Hh^*5U9k_$22X)LFz!Np3d{yOz;f^~SPjNKtW+bI4ITh<>S^0W z@PS^i5KIS)!91`Q^n7j_VpJE9XIo3 z2l#>&zoo5U-0x^l8nS;+Tfo9Y=neLP2f(J+C^H4Wex3G#uEW>`+zsvo8{edlz~cXb z2kZm0r^0uHJ^)MqfM0=ee?%X!4fIZ<-AAbt+z3{K^BKL<(qq^X>;qFShW~B+0o(@q!6tAmc=R3m0_*~hfTe%M z=GZIyB=uavd9WO8`X_A$kNhv^!Pe9C<)zf$ha9jSYy-ChIS&?m#CIh&25Z5hkLh3V zAlL^^@28I2X**a2?gP`)IS=mSxYnboJdS-AXsQP62iw4oahmD{+s1P~1AZ^(!R!f~ z2m8TZa9@(9vNNSmHB}ELPS?}{(0_@h(q?dcsisQ7wdtDL0_J6C>M-d2H0Ng`mwP*^ zK<{i#HGyqlC+NRIQ^}XnpV^u!23x_+;PN?|+6VT7{a{v}rV2mJF<1w>7HFyi^nyph z!(j5|$Su%R1=tSOfQ^eZ)e7ze_knRskOz7|PZoM!tEqCZ5Ud89iZ!(pYy;cD<4R?qwj3|1ngJ^Uzw(sb9@-A0{7lb zJzxjeF2}cMJUGKRTA`^NFs_1fU@MqdiJq0%jpL(WCs_9tO{HXG*DBd=ZF4&-{-5j@r zX>+mvH|cNC3s!<{;100!+mr`;z*As#9p&etH&_mKfz@Ec1Lz6%gI%EOLF@+Z1G92y z?o% z{RJk1`@p>KV)xHb59kHEz#{PQq_2 z9xxp|_$>ATkAgMe@iyuKPk|kv|7Yk0R)e0;!Us+VH-kA~#q-z$tOD!7uHBkC4%WOt zf6Zqc@5O##J-8O!26obJPdnu~-U03dTfrmX=9lnCA9e?`z?zroXK*7}2Nu0Td%$wA z6RZS#!L|F)Cm%ch8vg}7|BZYw1>6CazDjwp7VHH#gRTYW3uc3P`|&@p7_0@CgAJhX z0CoV2z@y+P(7OV%&U5&k7r(IydVe9}FzQK3|OTdF*J9r$N`6l&&TfoFc)C;D8S^q=( zz_nl@SO=!xfnAR<-Z|a~R)INxpx?nFumdawkAfB8DXkY86g>P#;w;z+ zHiEnVgg)Rtun#;4CKlpfU>ewU6n_JccM`Y2Q(!x|{B6pEelT${cIrYt*wu|6gAF~j z7xevuep^CZ0Da(=e_}^4=YP>3JPw`$>rXL$mtwc~s1K~~|z6=6zl~n!2@i-wSq^$ecn#2PUrmcDGt@e@jh@l$7xe32Nr;hU_F>tg&n42N1=nu zIWD}|p*lG}p6O6opU2)a9I6D|JCptf4_@X_2j%#3hf4keb_Mgm>@4gCc7WT!ey|m6 zn1vm{tZeKc=fSj6_`qy1eU3vFf~DYcunw#OYv@Q@|=P3#IZQy3G72LTP{{_>p!w9N; z$%mn%+f1GB+a(EpP-wGV6pkAPiZ57@RlUS;FoX?x;T1(*)D ziNAwgpnNJYk|Z{Qo^FSx8=jHe)RvgawslW|7bHqN)%>dfJ|gKrZw+?#<1 zPg-H(5gn4DmD49;2VI^` z2c{yG!}(Iq7lHcu^3ue~<&QcV;vO6EUDxC8Es5V7v(@v&xNY92lAcU$a6WE*Wk7K)(4HSsyd)$Ay=1IT#`7s*pjEW z(eu=}C%taRsl?Rc5=$zLGX#r_a%8lvK>u^eaC)%NU?JJa*ny1p3dTRbquS*%T2*0d zl~K2}=_q{3w}#s!v{TR$p_Pa%K4P~xC;bTRxDdo{zT(8mzEC?8pBnR|$I+IU>MIU4 z@h^XtqI`Yu_QI=%ZXbSNSgAd#fqyjZpALH+a!PJ9^wD*&`ERMsVWn&vWy^5zW(GQ}>IsIOZ>Zc#KN@+0Y80@jo3KIo4`yx{AHaDO(%G zUkz<7w2Bz~)lvM7lx?HzbScY6WVS(@zAD_W>Cif$B}2=SLQ&(t*d|lPTQ6l(D4S-L zwT*3&<&9@d4nvld^-;EN7-hweD=E8~vYq^n@?&C#c(P-+&5_>}CzJN>fG@i;++Lv( z+EqFct*eqy;F!HA8`e^`o_s1z%JLDOdT86A)eAxR zC5D-C+!nm_@hA1QQ@)?_GLH4~LyQ}d-9uSd75!zEHDnXBWtMQ1hi(6tKTG+Pk+hBS zl~#G1Y)8Z_V)RoHyk#4%V9h~>T9Qb&M@oip==&y6Gb*3sZTEcXG0rq zeOZ)WKFs=-Q?}ezpXgf!t#latQg+)g>k?acm~}}mqucG2gM=hvvfidoL!6e6*t{Q} zta~E+)Z@k{qG;2hCEIACTMo2DXi~SWpY)Mr?`J7nL0Qi*%4Soxp0Zxb_E>UjH9Y{B z4&Zj|NKA!fOvL8=DSRF9b-*V}S6!b*Eu!(?8}pRM*`tLfaB>vG??z$gubD9cRti>IbwixOVh@;if<7XlR8vYAD-5~XmEzM!vqprsalFY}9x)}F zJ>Nfu3_qL%i#~2=qGK?TfjOw4xOFshjAAiJ*dU5gwtm$Sbl&nbdY{!loNGzC2l+xJ z{K;d8k1fPY@<-iXL*@R?EwS=;w_|fuva8#}u`LEw@1HvA>)VOmRHxS$IlfG9#!5DA zMWp!2K6o2;(LWY%w4XT0DnqLt!%-wh>W8l%zU7vUVz1$h6`bP;hK^joiKIg06pUpI z{1_jzffLu@lV`OO&fD8ZQcv*NZa}8AhDnqzT)SQ$?qr|n|Zj~vDRi~BAp%! zq)xd%WG}p}gL%)|KYsYKe|G+SjqvS+kD(E*t65*IO;bZr(ens=Y0sZued5cWal{Sy z_F29hdrXA(HEQtcs9~Wm9x<_6jx5ifaK0t9Drl}K+D2$9inaw>-|p~yBD(E_)&s4R z-$V6Vz0DeWzq!dqLSx_PNztPZS+&&Z5?OqNCimD>LzCa~5tRFFs%*MR+{lLJhgM_R zC_3Iar(=~+rP3)8S_na8uSL$5pNH)uzF7~g9$F}FhhCCoEH=R@D9e`KurCor0 z#1G`Yph{?sLWrFAO#c}i8-*{~%RCBS!;pM~CtuN_7{07uMB1-CF{nnLwjsCczp?Y+_8EPuXQ83C=s`hpf*$xf zJBSTdjvRBI%Aww&ztjZ9jHp??CsZT5Wk^j7?8-%d;R(QuXDwl>3i=(sjv( zy#`s^4xXQ1N`JJ%7kB7i%M*IwZG`uHVyXD_^ofjv!(ks2J#wJsb+P{Bw{DAAwv;3& z%9O%e4R1TV46n2Bl8r|3N*}hu>pOu@#pVs={aYfq^}Ju-uax`S4#3}I@ej`HLi?4i zk#6}1Yrj%&e=>e>@?UH}yuJSduik!mYr4sIEd3+x9%_F>jP?uvDfp%F{|bL8tXY#- zE5g5#wX@#u#q1Ru>j*QR_G2|`qu3b9O)LVUNagWSq#VR;Mt1A_%)M5;khVpxQJnQo zd&BhMq_0mq;LQmVbIvxl9S7~q|6^$9i#gt9jHXw+7FF4*E9~;LIsdk5LEVEk8qih%&H4tP^ji^pJK@_on9rJb9rkS1>Nlyg z4&IcJF?r9L=eEOF4`1WpI)}_}3MtzMUmtwg>c4EMHJ^J;8BEqOj*ec%E7Yw;Nwp*hHNI|olD=UZxZ(g z4VGoK+u3i|Y^a7KOY~iiyu)00v-(BaUIpy{v`|bLroK(^^`?epNk8p{)&q^(LX18> z$6D<;y2o0p`CxaYu}?RJ`;)9bH?DP9+pf+!c+Cq)`evOhXza(*-XdgFObhEM?JbA4 z9NKhCZghJcz0uvH+inYdg)rG|w-cHVT1dxeS^6H!;J!W%U+2YPS^D^gb_CiEYn~V+ z%OCAGksfY@Jzdv=DU7wuuzayaDYS~q!ZaC^mC%+$3+)qy>kRo<>mdI!e5nau*X3b( z5;yij|sYAfBWF^EDX!>(X1oTYKxd-_^tQf;B}69SH_O0RZiINovm0J zx$9{r_ad(X-t^Ch^~{1M&j;0hk>>~at&fK&KR6uHR8Kc_y>`M=_#a_8qE|aKAGA;o z6z-FdUcL5FYSXJ9-t6UJc{1KS8T2!>Mt+~qI4y*)0luCg`SwQjsbT9{_zJ%i)nR%FGMu-(kO`IOyi z;w~}wuzi`>&>tzg1lmk!6+_B)F&muS!A0+F$SJ%%EL-}g6`Bv4cd#FtISVsHglNOg zUGSx>ij>t4%?nNLeT>=H&V$i5(ETub1~#pXlvM~#o}20&QdV1Zn{`?8$6>bI8I~nu zqXAkyv=pn2QDcLQIU+WRtvcYTsfv_y6j~Lu^O55rh?K4l%MpK^4y_nkv2&1}LjLHo zXUjH!EQhzEI#OOWwB^uTXOXwhZY`UtXge~SN%@npwG_;r2iOl{r%m;)0GSqi%b}u(=EioeH)AajVp6#*p ziH;F+cS*!p8x$h+wpJh~@xI78rpBaM?U#Ps46UY?T$JCj>`J=_`F%S)N8qvK_+UK@ z?I5(HL&%Am+hg{RJm=|OA1QYxv~p;jL&)70sb5UFRmkX%lDiRFFSL#!+zw>a z+#hMIbjZAz8Q6YN%DksrVsJK{mA8RsH7yy@e&O`nJxb4uQ{bzF zZ|_F4UmR`rn?rR!+06NxZ-#9yv8NGQ6|}sw_^%owRvZ=HZ}V)H*p-im?>B%qp4p5a_}VSL z$QU%_zM<4v1aB$N*1CqWjod>M5ig8B*$7|yrm+4Jd$vGJgQkX*)fy!$cI@dy&JpBz zr9FJ4FM3UyWp}C1bp+y1*DxN zq*?Vzo4cSDQLdHW@{#`Pht>scrx0S^8!&i3M#f||%*($Mb05Q+Q)1pfBX*YO$2;Kt zciX)iIU64i`;4^l0JOExD)}uRp>;w#97XGeHnTpmoNEs9pcUzy25$k-C&Z^F9)$`H)))EfHFq)DhF(EU6>LM{&flw5JsrYmwm<8GMAc&!pM=`v|mZ zTm4e52U?|#mL~${k_SQa%kOaPv*OJ;*Z4m8H``=pA*KY{MrfyE%XBc32F0*CczlmW z+G`uM9BBVep4Ewr12(y0hhAv=qG+yp^tFxVqg)EKHlbNDAu11#YR91YUi@9&N3gbm zb?)F?*IZ}G72SwV9~8($XL*l7)|Rk+aACCr?cb)#k`K#L8oxJ7{@y&MNI{fWPpW^NUNucL2V< z{{o-9+ac@w=T{$9sXX|0#O4ddL3;!>Q)@l;*1+rCaen&@Qm4FEVl8|zV)j|<6y6?q zd;SGpv2FTi@R=VFyR1A+`ZV(11U3-Ey(vkb#L{y3j{FyK)$-9uUoi5C5<91HTY{r! z5KXsREAkFE#caR1{TQF?-dEGFWX^)OmG;Dr+hpjG z!%Ww8IefmB^W)2+iU#<0!&hb5Ix_A!^T>DY0aW5c2Rywy!(&?H9EH{ct4LVA-?q8Lcm~%|9;!@w#Yd5~l+UBC z1}jcP>6cA>uV^0kSsXJjO3Y_I|7EyNX+s*cZP42I9px9HHq_aA)82;V z@Ood29J5u>vY@qVro5<_*AO*krEhn@vloWrmJX3Tj`kRRdjy`!m%?q4Sk?or0$P?; zcZ@mkXmnd5vQeXT(ib@k=%1Iv@`Y9e%?C|%mXFx49NKbdJ}br#uG1NDrNK0y58iF? zmjBA;i;?Yi%1(=YY`Y^5b-(OHM%Aw)_3VY_hi2(1y1Nz6n(d3;`{l5v96Mb8uRU)sR z-ywfYlXn&9Z@O^!!u=Q0LEbsl5v7B?f2s-DR@+2Zc^6e9wCN(7kBp@>Xzl1#C4|T| ztLgua!f=(wLxE`&ErqZAfNf7L-0ymxmO>eM$JG|f==Fuyo_b5tIlqnb+c;muZ@q4# z|Mm0sE19Bu2W1O>$8~Zk%SU*QLM#70_c2;)n)Y+tzqyx14P|28znO--nO75o4x4@x z*4MN>=P6T6ncb8jMKyE|J%jCbR^zYMW7zUQk&MY&%4fYv{IbfQecdHH?y+t|)bH&+ zfUG`b^;oieMWL5i$fC>R=FyRGMjliAI3ZQKfn$%fUK&5(j>1{DyE>JK^e+Uy{BBv9cCU~|vgh{{M zMfF0LXhWNtI+GII7fwU3quRxO}U2gKsl*fK0?cawl|6svaMU(fR_1b9S zkCo6of973gBFyGL+l;YGQeZ|8{hnd{88kbAab`P2#9rj>Mjo##GUTP9nPJkU7jV8G_mD$ljgJPv&G?vRUPMxDZ34sTdWuq`<_(8B})m2Q8%PYr%2q{ zf}EarxF%-#wp^!*@$A%cyxM-5N+vyN#}W9e{}%QMq4hxXN72+$;uJKd3jLGDzg}pY zp>+wx(S)Pg8Vo6oZw_UO|2}jXsc$)Dyj_v@tukqHUOs{wp~*W9Et=@E1zIAsUMUpy zEdDm5lkJ|OM-1EhQ4YTWMdWoNXE$;f4*ExEz0i7~CE92%0@QIEP5M0r+EHjTrJVS7 zXf9*CS`!(kB-R(2WqBo=Q8r?q$9T(-(@STCw}{ZtY`@ffGEyIT-{R3I+D>SPp{0p$ z@sT#QL+k8jJjHRK$CR_bhf7v3Q7)(3PGlusi$15=k8lr9*2aX`veIBLMONuY#5&Q{ z(L2b8WIeH#GJf6>>9K5Pb2E2UC~}BPyZw=ep&+Ke(ag>0Hp7fwSW+_kacSgX)LA;y zUO4J(JdBEgr4E38X3F4M3%fyGj0^`<+J+Ytg@U9c=BL3LXMAb39>ei z=G}@`yQ*SOm9k!_ikv9*+)4D=f{be3uc`aG*f?T5J#Joy?XZt0ed83z2#+u*BI`J^ z3dh>)eD)mESwZi`N-{-ORx$G}4(qqt))+hIFpaLS(I{fe2J{!-=`nsSvO0MuXg_jo zbEmnIiFCXu7uRFuUii0-<6V@(&&R{}AhcfIFPf-R4BByMJ<#-f-JqxQ?SnQwiT8F& zxuP*?ZijTlD7R!Gqui1~j$-;G58ylf2Ks}t66d5WX|Dc}`h1*gv(9lWv=V4XY&4PK zht>~mr`WAc8QRy2i}W`?j@ow5gb_M1Mcx6K#n0({dq)$;K-V;n{2A_n0r5o{ zr+O~s4o&|OcYKtSvaBieoZoe&jVBxvuAh*P0;pOh`8to&^Xz3ir;%j$8Dvhw#E zj*Hx-Ph`=plrV_p*@U;owrGxlFdl$6UjPS-i zzv6>U@D`^TIhX538*eBVk;q^rBL$;`=O{dR7S9#K9nVrv0X#m7=Zf*+ zemo0L4Lma~p7F!u*$GcFJjDw8y%)1R41=%@#78>e@l3^E#79PY!@9-JqvgJ$=rmf7 z(dlvIMbpeaAF$~g_7T%piPxc#DAB<189)5;w=xPv_pvrT>^>8jfhd})8sXalpHKL@ zZT0GV5k?H(N0|=FNT0j@WG@qbUo59|yPcw}{LO@pc*^d#l|Ab`?{=<@InlGnfZPIP zHR9lHs=6=I#*tBS>(3>Zo5Cp*ORo4%FLKM* zGCr_{>kBr0&yf!tx~LME+&GgM+XToqXvF1gBgYjCqD&8k0_58Ivw+&X^~hyBRsL z&m4{$>P!(&S;yu%K7_(P{OEv-Iq?)R--&HLJZrw-JcU-FFl8nT(w83A5Zn65+hxq{ zx5;Qc`)HIAjddqr-Nv4`Y(!6r96 z?^N681FnmNCkOZ?2a!L1S@0?2*#Orjn~Xtm{kY9wMqC$r`QR^~YCOm6x+x~VmFLB< z`QVF6EaUZc_mNq~eZ{VcHkpI(QMTSuqTgw3pSY}-loTNEI6Agn$KS>fzj(`*lf_y~ zIXB}O5lbh1Ehe^_Nn9>nY242ikp~X4)$T#I5D8CWj9q?`w-f4DT{W<|x2^_UXt;RJ4;n@vOBKLMo7aqI* zVc#ba3A=kX<$B<$gh$VFyT^oMr#%O$2}NwZbuvH6dmsJW`%x$M{-Iqz+q>oUr`~KE z6YvRdIlP_R!x1OE-yg&q%6Uo7BXV9?BR*x*oo}S3Ip6TzG1GJHGR-T;?as0{1%G*` z(vQn=jZ;q5q8zDjTIY^&EPQHUz$3Vza;7KWs9>8 zq!Fq?XagJ6p)>bt&1V*>0I~vUs&?70mT3*_N6hJ(;cHIteQ(*~yZ`Ghm67nonS1k_ zDIa(dKD~a*5h3=h9~fwzqVfVgELs0HFz~pgyHV#ao8KFyf>N*MQ-Sx;H@*L@4wrtZ zz4noRR;h+Y+V$QjU+~PmFE?4T{SIHybAd0|=^Wo;KPPP$`JK+x7SX||;}^{zd_imO zz22d>uZur(BK7n-wH8p#rHM zwWrgW)N;(}ZKg^o%AD9bj(&{S`!QXseMIcy(zN|$ ztPYx7s-(%`%WZc1f*(0Yw!G&Y(ej})zU2dS7kf5QzSkMo(lzkEr-M#sOU{JHw$2wm zE@yRowC?rADrwUaXYI22nyWi~ecjfC1m92Qe@VT&IR1gHsbH6*cG*R<9@t9w_Fjan zPUl4}ld%K$^tQC&qn*wad?UH#ZTgJoj2nImt=8$?bj*1nwDB!YXk8BPrd+41yOXrj z#kmLgzU`dUlBSK{q-hg3eS*A~@U{8N)w_)6l1}9P@^;m*5WW+66OfUU$Ae;xA0PUnOcLXT<7u#L-K3}ywev5Xb*xele~rQ>&L zyamAJQbDdrUnS#bYNN0DnA6qLw#A4sF3J{CR?fL7pP+ofDZzEv!qw7nyYj{wZ)Iuf zSs4@0I917ePDe`_ZF`2c`M;ieV_lNUd0kV_d9bP9?fc1M?63D1_MQ`8hyPD#*;lMJ z(62u^#@KuGe$`w@`;9T?)$RH$Hrsyt71(0%Sd{Vek{NS~er)OYLUWLq(^uxec24{$ zPWLBio5+37sbz{iQlC|;*Q4`e^hXDMPbl}+ec9KXM0-0%s6zt|SND{7Rr1zU^=$13 zRnm-4JcjR`z`s(pgziHA%uPaY-Rnv5DzKDxz2!*g&UmbDYbJhGM*D7$e{ie#*9m0j z%zAJuDW`Yhnf%vX3F-o|OBcF(p(X3SmW(gETGnHWW7yh@v(ri=^w9qUB=^f>|A$$?D3e)c$6`6C3cxI zQUyLh2N^qD7A+B3_ea%C zS>^_b`x7!{Y|EJU6K6WkjGSAIO(oX9b$d4ccQ$*DZ%GZ=^B2wUN|yb>K6L=?Z=hZiWk4;x8XZ`n?IzjAAG^VICJXbO#DRV z6Y-f(qpLsD*DP^-B{m&p^Pg4tPvYeK*QaQkXs_?|cXdBX!go~nE$G?g(DsY%-=S|D zTGFQD;9r^d|Hk!NLiscM|$FazIE%`S8rU@Ui` z7iqhI{8g}^-=U+7a*@_Jx-6r#jJw8lqS%rO#_WzQ;B}XKOllZ9^`%@S{($8Y= zDa=1F@u$6B<}0?GlDH_iz_Td$2xW{oKE9=x-x8~r-D%BLgJmY#WU}oYDbtJ0lT8>|*HFPll-h*%HHiBRJ(HcvKkiG8qIXSc~ zAmc>FNPn65OL&|}`M0p!BFak6A$D(kJ(wjnmgD(xzSZ3l=k#?**xo9>cA41f6?AAC z7^pvS?RS=yGZxgI_N(f!gX_MyfR^CfmEcor${n>=X)d)ZwNB+m_v5yKfr(O2?ZCh( zbtENVuXq1h>ivOP@8U7FM!k#mdh1>JlLyrsUFSNpPHAi5q02q<`{%Eg-x>TS{$);i zscx&~V*?8{)>)3`_b-xpfqZ0xtc5gkH{YIK+JCc?*K5$AS)?o{p(Koct6FD+2qGfrIC3Su24r5FY zI32VxuKB|mG9Qc}W{f0eX!@G3lew#x@6)5^H#cK*@zts12bQnC%@`10J>gV=xti}M zT~3u7%V+25K0C2x9x}S{S&6CdZy+W*tvTF?|7rN)Tlj3(3KeKvs1C{ady4t_7{{V> zL;t|zT`NrcV4Kc~hJF5Y8+LP=bSHG?1hLy2(4}u(AI$JHI^W8(;z{|4+N*l6zlJu; z+_8u;QP7MXLbj7JJBe{2b(uDtr^{#F6+OmayDnS(FPQbG4~(1}$9NSUz5FL5=Yk=9 zo~4}dfASS0$N#+3nvcU{OL&8{S;}c~j59qyFxJ>l-)5CJ)(mgsi|CpuZJhGLgr?`10Z_E>G#@rjOIe@k`ldfNHfU9MS+ zg6gHXz*X2zVw=0+PjT>(2yAl-t?)3Fl9do8;zRmYD z(4OI(zK69jH{fIcOUmc*ee_ywkZ-2%`sQm1RrkH_?k|7cb=xmar%~RO|L4;gQ&gbq zh4)TpXzt%++~;~?$uAcFX0ev=n{<9BoVoM$bj`ISV>D&&OSnjMNcidH9@k{wBUemv zZMu0J`%{&w!T-ryb?M{;a_md2T{hKIyUeLt#~nvcd@1v9e1C&Z(fyO~v61IT>-Mkc zwfIMdUg_xNxikB|vj(4I zmmxalKi60Fqfnk~)OBB!tf!-7JsWlYdr{|iMV${solj5m$@+fvG3LxEjOQOvo?LQ} zZpSKuRnjM17V+x-y)z}S0bTDyp2Q4pOu19Fe_Jkn?BWF+d>wq9yR7~mc*WQoes4Vc zw+mGu9a;KVWv(UP$lXnx_dn>{)1mt2mOo?cAHQkR$lc~8Xxi+R52`&~+#*nZi>B`{ z|IR$0x<=h~^T0rfHAM%UWFDD?f++$a{Px_Df%*#<34D4mmd@XbG8OvsYE$yc4=U39F=^UF6Bqk9GK< zYZSSv!?kG@{LyXxvejli-;7$b(soz>TP{ES!P+x(Ci3)o4?phe>Z=le_I+oTr)#7N zb`)t1zRYk@9v_=^tjsz%nd!t?$^v-E2ZU)?;*Q$zVa z%DbGOn$7w;SJs`98}!3RE;2E7r0iFylE;;6p2+*IAuqEK-(s(2kMM|0_24Ye4>{L~ zUkgv?$nETL6fnP7ds$qIu;r-a{q@Qf9}wR4Z}(MQ&)#RbtOY!m=(JMsqM3MN_*>*Y&K%SKC-iT3Nj;q#XL-JXj%f}xrwhZO@px&FoGHQ1$`HOP2k z4SU|tNx8z?jdEOaYbd{83wUo;4L)+#@+4o7ea?moo6IhMq)h8Nlv4BG)Z5+e3A_VO z8ZtO;RSjbTZ*hF1O-A9`SrK|gkLhC3!_@InQ^(G-VAgMij($BApr+=^@4xXoz5JW6 z`EPAH-PQ5x>AIC&rzNk^@Jq>uWS_Q+Kh>`5;u{&zp1dab0&@HgN1&Q@6S)KVTPnG3 zYKx4ON8yoi$Qq7yv^vP1+`Dh%PcCgy@NP%#R#`_UXi~=2lEF1CS*JCkODF5H6O_+J zzT{=D1S2PVhw(+-2f2HYm}%^RKSBMbPW38{x6r^N*Bl;$Zuo#P_ehxsuwllR#s(6e z92tC=7-2szeV6v7%RQea7q`!4(Ph-~%RLuIm9giUBFF#841He(pAB06V$U^YT)k(; zC@m_FUteMDN$UMS^Adf%Zuzp6V~8z9hFrt*l7GsYYyDLAoT*Rd{{LqGhy9b)w-O&~ zZ&8PCr(dNX?76_}W;~46>#vqxlKb1%MK_sxDeAMgX^>7_JBy{$Gf_HS9YZJPIDK9k zu1<4@(8<2n_3RMsxfEW@uJ-aj7^3_|W_cs0AJ^Rfgj`3l<@FozN%Hf zCzvI9`pxw7RN|!M>yp#kbM}VWi-H?ojte}nlzlPQ1+qRk!J1%#tO-~j%wt`!o0$Hy zFU)VQrQGha&xY0kdM;1SzX0C#obyr7z5JH4jVn~(nGM<@DId!FomcI;lJkwMt*-+0 z@wDSI#*>lv=Rtdhb9y{A^L{D+S-y`gG4`-lISd~aKd^j1mMw2~m}}K2U+P#9+xDNc z%5&|*?t6R9^2R=jxqq@j3%F$M#aFI5HO8^l)NSu*VZZgD>sr><#f!}AWttw7WbKzB zanGsRZXwpQC)g&ro=ep}GH^NjJm1%vC6_x!jOr@Wa;NdTb3iqB-n}uebHn|7H{^BQ zsP?!dCQUYCQrDHN{m9c~efTuvt&9B|SwU-3Q^G;3K zlBdtZ&bL4GJd;^A&QY&o#Oap;rVMzFU&lDXZ*`XZrO>Rl}3{f2eT4-#9)E7ztn z+Fs7}-wknn&%2a!f2uaVdj__Uc1@{JV>3jD?<=k|Xf4vNw;$G;KO}a@{^-D^_%Lf; ziI>tgxiyC>F~+g>ICim0J|Ogg8GHn=mG4OF~Nw{CuqA|GwLFbkv;ZzxSsnq z*Q8b^s5w%<*z#@mppH?e)Gc+2U8O#;t;mx#oZY^4$ak@CCu{H%*ZB6#$F}4PC0)!Z z%_G#D6W_lkU@8oys+e^~l11-^AI^{nLGQa+hu%a+m}>Hk9dLF^;;6B|i8EdLNYxv-D4 zyA#`5ZI?ESZKYk7UVg{+t-aSTrktzggD(`)*ViOHF6Z3c>p7R8GPv76-Ji_tYbPwf%?GqS)OEm!A;Es^epU~z&fgbphV7D<2+gqa;Or8ZsM0784uip@_${YPr^DGF=sD!i@eq# zdcNk)o(I{95LzZd!TtoV%DlX?OE%JI6bYRwNEN?(V! zlN-r3CfNfNzY%+hkLdeMbMuWgE57KTou9js^D7srJxy_H?&bL2tLSR=JNa~pU&e>& z2aO*Ol!)vdW<7d8Fm|La>v}|=?Rtdtj~{uWvxdL>=NjXv5xFbosy*Yy_sJWka4f#! zr#(D|!rF@8=(O^gYci^n6!ohMWL)|es68)XC;x22Uu4V}d>Yr-jq4%y`o)i|K8wCK zDt*R2cqZ4>^*)>KP;({stYs~ggzrmV7;!79E??|TU%n{)C+Fx(`K|b^x0ANtGt9PH_8Co`e(Wo9^3ln%Zzp!C#=f#9 z-af)u(;IeDd&EvdUtb;U+j5W8H}Q>BmC#*FKk0KIwvl{Lt}B0l-+zb=C8iv6Ca@Rn zZ0U2xXa25GYxpZZ{*HdVb7BkEjM)n%9<#SCxuKu6S_XC&z0$L_+;zy$$MzCS(zCSO zX7*_%rlesX8ROyu5>v?Oy_OC#4|kp!2*(6`{0B;ni{%UAi(KnpJ=LRv($)g6{Z^OQU)MxiM@~4t$dmbZpS@t}^noR6jPMhualyhKdU`_PQ>k@?xs_mmBc^c@;lIOfoMw41ozW?jcP#_z+d8+(}x z?;fYx3Rz#^D|_nEv!DHIiLD=Bqcxo1_iwnSFLUJwGvb;vpO$^@q?VIcs9>g+5SaV4 z3Y>hA-#5Dh^R)QD$)#E_Gk;Vd=jMdK$*=KyN@5`QC3oQDqx{APKlAh`eveq=CO5nC zrNlt0OTGKSP4Ug`j*+`MH++j+?Av_n@@hAHlkd0qew(ixKfw1vzMJ@N=KB!e@9=#% z@58r}nrofzUA4|pd=vSO<~xS(SiT;<7wqa=s0I73(SpQ*UCOEL3f`#&gLiAe+6@zS zeY8mne)O;w^l@%r#^~IWKh%N)E1Y`^aH#lS_Yim+80Tbc$T{J4 zUm!B%yiLYv*(cNj#I=SK(+ZmPu{c4MNWb9^<8GuMrQbSVSRAaSKe;vBD=|WGzp2a{ zsp_KcF7ziiE!j?gN;%)az;m6O@`LNvsb*)kgiT%3$hT-~0(&&v zsnXU@dq-(0-P|l)QpYvQ)IDl-e&0aJN!n1z*iO*qADaKG`Ons2!%ptWQR@C>Cofmc zUqp{uuWCDSxv%*oe%whLCFe_6OYX+nH{m4}DAZh=7RRgLtK2)Aar4YT!f358A>gYK zALXtDJ$G|YQMv9Wa;wo^_AA|)qb^Xvgn+6!aVh&4=z1NxKVY_@IjRjuSdVm$Rl!=9 zYCB0g5;XVz`E%5}?{E#cXX)nG7PCLH^afww=6~!uU0M0t(>*i(aeBU%*uC-}n_kQK z?XJ_W{`0q|SMKULU9K(uD4)Dz@f_}D!VSnlE?VecI}$iJgmcRY3HXb7Iev zwSTB)X|NcDfmkdekAgG zoTFN{GY6aiyIBt{(MGwskU!6=BLg|}=^NQkl0GCxwoW-1$GSiZyuCsNZe^cHtb53$C zA9iUJ-s?E`vO8eWo)FqpXtyMUXx|mucV(^1-m=LX5E}WYpKA|7L!T1+p3?)1G_UfnV0yQGx6_Qd})-7pUK+lTH^S+ z8?@EOh~s4m#OieJ>5TW~mMzv+Kjek>Iq+iei`r`bW=2Wbm$cQ5mxB*6_AbFE6O8*S z{OI-jMDFds#<A)c=_2+F7pb;muNdV&JKDH6U^aU${yXx6E9tj^6>81E zJoX{9g#82Ws9e{Xg^vzQ({g1@S$yMM248If_W;7@hmSVxKQYZ0Tta#A?^~F6R?*j$ z%ZTyB6tz&5d`0sGf4e}nC9YZ7w=37z{4jg3ztcwV9~k|eZpQ*ul7+ADT5~5$E>HJE zqgAk+I3+y)bb4AwGnXW;xub7azQN~l2w#2oL3mb>`@BV+Q;AWZ@Jbl5;fDFlY1nZ7 z#n=iP&c~MJ#PIpp@afMQHWPbE-^eS64#Gk&ED2R z#vtV<5XWWwm*d|u-$*=f<>+u8fYG&f)cmu#%O&H5FeV@r&`6gb{zK(PgS{G ztE+c?(-nAzvFP%l&*+3r{yVhb%Bj9)H*u~p*NmHch?~Dst6k_Z6W`l3W&c+2wM0+j z=_1v68rz=C&%qan>#tB|XXfVDGO^hV;`+@0+IjlGWd}|dZT`pUGWsC1X!C0i?%H|! z{u2#PuZ~rKQR}lI*F!!hMvNsCixgZCo4F@GG$m@0@A)h;}w!te)dl!`?Fd zwP-B$#cQiO$pOknYpd6fi?ruF*=xhs%CAsuB4Y}Azs-DlY&LlU{x31RcD9~#Qoc;V0&m&%#$Xu&-qL>o4(V>5Ffnhxoj`|GpyqC;ol8QHRV^lGnHy zV`VR?)vqwt%TB1()5wFC#A`Q{-Kti<%6XZyM4xseKhpJKZ!x5g3n~66=>mC0+Vu0{x6{$hiGHc5EN7+G?K3Z%*ZTgM7xq*O;>VAo5 zf^KF_NnX}cPrbFYHPtyu-xE6~y0EV6qx=Q*O&di_b(r?&VY`@#MMY&Fu+Eb&3= z&f{3dfW)z`Ka8CF5%!T-YQ+I!Vs05e^b&f1$hkhg8ORiS+=3lePR(z=2m5^VC)GTc z_&SfckVK44VIEA<+E3RFEPV9y#M>@%GpX+r@+Q&Kmq@(1Bfr`2bnV|xn`I8~nwFp2 z#J<29#%?;-8x!)4HG(yEmx;YEFvjjA#%>Tf`q*91{T@!&rju^+{gLLn;8=QSU0`1e zBqzxJI@cT+ud*JvcMQ1^drs@b?&$D!?7qf%;r=q`gzhOk^U+Sbr9W>o`?`^PlPmT9 z=Xn94jaF^zC@bZRXR9W)e2iW{=A1l}CH;^-u;9^))FjLoJ2Oj?|`W)c9pYLz@CeU{>zNP(g?OgW%rZ?y}$QnI%21yAyu{X~7wPkwjO|8DNjEZd{4mgAe{I8FuJn$oWU zG;+L@{EQXY z+SfA5+fS4GoLo;^L`NBWo3F#47OUs(=l*A*$$VW+tdsFsC%H;gyi1}V)T2g!d5L%8 zmsY&1HFA|!*RhNBXXzwob|q?ku6kch0@s^e(l==;cct84@zAHZzr&sBs#i6Ij5%_W zVb%Y^0_uNwc=hXbn)Qn=QaAT@)Mrf23=mg`Ro@?}uXfYFULS2em~q3Uft$#MhGXAf zO8e@DSKmIJhuF)h)|Vjdw8)Zhv}~k?VY83}b+Co>t2IKeb4| z&X&(PYaZ;(GV@k)=k@%SaYKyE97~Qb`-Hx7_1sT}+1^EB-!=bwdv$+06CVf+v%XBR z?>)n-ZzzA#$Lpl=DG3!qtUcN{kDf6P_pXG~Lhcc%wIiYSSlReTU#9)qPZM?n^KVq%&rD5v+ z0=hTeHay*9jYYlResD=(#4zjIPJL+=!>jKszH%_*)hj}_N+-6T9A@lWC-s*Pul^z0 zdn#k4Cm{1oCRXV^`)jP1cx<-P#=1XA6yW$HHROu$i38iqlrv4|x7a%BIZ= zm#v`e`WR)qt+Hc{{gS_P+=zcPjxl(jSz*+5^z+=WIYvFl-`)t-ceZ&q2iy3*@Ne1X zV8*lbi_JDo*k*%S|0q4T8`aG{Tfz1l+3&OEg$p@;mz?mQe2ek@(b@%@dYofgx}6ua z{1|_}6P^L`oL$7+)HLTCznkNE;&(5pL$dyO7df+DRyWMQM6F&;9T{?MlQnBbf;u!` z8`HglTx2maJ=&;E|9hp@Ec_45Nq8c`k+3Oak2)k{>bmRY8mPOwagI5bh{O5(7Cskz z(oe!8*L+;hsYBAg514i@zc##2rLHyisaWSeT_ke^_uSL>R-Xvpi`Oc)B8)zfxnu+T zw=$Qc9%65c-&Wo<>U#EOFJVt->W$5BaUK6@S>KrZ+_DZj?3l1$uJ5mBjVyMM{PbfV zYqRg-3#@St@LSf+FN2MRs_iX@wO%uxGnV!5Li${us~4U+*78ZpYp&%dw)mgo9`mWJ z<+svb=snKtN74C}tBw6q$>nDxXg93;gIZlUMU`wOAK0AX4Ln4?`kghaYIY@z+0<7#K+PQMpA>zuxj0vLx>_H8yzH6m#bB9;oS>x!n*`YXEhh4S|v;NDZ z{yAr@zkV1wdVNN2c+T&j{u*2TR=@n1=kxR&i1_v*ePSO^?W`?wSQAIb(`QVcM)q5* z*!v)5FSC_Bo8P@ZpZ0zF-)`TjjEoT>`=--ApRIjotN#tDKXZ8X58+RzGJ^3De($IL zv|-l&oYYV3Ig3As`ge%>4`#eOHlqGI##BO@)+~J`*V#X0&syG_qd&{MA^a?}6)R^8;S@m z%0#q4gwBMd% zqP0!LT0lJ#FU{}$+0WiH&rBu|u;=vm$MZ^_d7fwQwbx#2?X}ikYi+$Rz56NlK-&fo zD{9y6m(ky)tLr`V`dwbY|G&}L0_pvQd`o-L7rG7Yx$#`E7+#(v=GO74Z< zrP!cVzn_pG|7dsp~e_z78FHpSi#SvR?(60=y$!bjpIe(w#(y2#(YmYNIzgxuV>clY)N(u(kb1_ZG(N%K_Ta@A|$; z^N3zm{f0jm`hDx+-iE0bPqxp8ORJAeebZZ?-#f#~X4}5#M17o;MJv>IHngICMJv?< z)ASbNf6<$pGkyQ(GdO0_!p``2mR?YiAZN#{1Ll7D(8R>_{qEA`hb2sG7W2&W-KFOs zV*+FD4gRQw-{2VEe_y^?IXDH!?$Qs??fTHqv|vAfnv#&8QFLSa{mLnQYU8of(!BUG zaR@-bJM-U5zaVa}zmwDI?cd%JJH{*;i-%jp^0sMs<2 z52a^GPa0jFM_rXrO9Qb8^4T>FzHWAinsjY9-7x#5!Tt6XUl2-q1LG%;YU`Ku;@_O@ z#mU)>H_R?Qv$AUr@dr`hs=>$DcxquH-qLz52~?>ut6 zoi6uB;L~rb*cX?NwuAn|)LD}sxfcKWD!yGsEJOpb5Uuzt)sN(oVx6`!<~XvgVM=9J zd?NeAQ}FjsLC348>}s6CeFgUw+FRzn0yy|>Jbma}^+K3ZRVPY%TzpP{ravn6U-`_^x(0*?rIUrvJ{#TH_ zzPuz}Y?3$YO#I~Dap^UwiM}N3N@P3mf5#-``c&_vtI^-P(bG$(dW)|@e_uhIiuQu2 z|Fh#|_P92pzsJz~rH2=SSLx!>a&OBYPY!KR8`L~l_Rfg-U0*`~7Tiv@U5tOZDZgZ2 z+f-mUOuP`<6{iow3)mm(FT(qC_}%yo*t;(WzB$jaSHk}u;{-oloMT755w8pW+*x|m zP}BZP{3d_Z#<||}ZrtP-n_4;4F)uRs+V014314f#lW-O13A!%Oc`tUl8QeaBF2P0KJ4$q zO9k&Zv)4zRCbPfZgx;h5^$_?xZ>+aP@Lhn;AiYO6-6SJB@o9#}9WPsSBX}qtld7w*ch-F|u^l5*8!04vi!Hsm&TKx01><`r8oA-Sa<0@*|6To-9 zGcxPriCX5M4!v{=@W@{NpV`PZVli{=GheN~wa*NX2KT;~PaNUzdt)mXYk!k^Y9+{@ zPQ|$WwcF>(6GO{7^9x$q-{>~Hp#L>S_V0|IIvpIx*;fryJK$AtT5^fEtm*CU#qSLC zwrH(W{QL#H>*)VHY@51!7nyz3){v z&86aP1V?{zdEL7))(*F(w%d30j+=WEKfyR-wq}+4{dW1h{NFcMBa`kt)t4H{ z=&=3@#!7C9x5v;XV{C^HXA|=i&+|41`A#-iLx9FQ7^~KM#mrm*9PmsJ8>kbym#iM- z;OGABv(I52I-B)q0qfFPtWRfR*POxralh35vA!#SMsM?JbZ5A|G=YrkDn#yRuTgQK zEy$rHdyS&g7WNwPJ()emzcB9?0MDnmR`2e<{XG7L=wG^s@OPtPK^W(&pLKDWz0`}e z>!V@{tHG`0v*uwJva!BAw6MPa+7T{G@hW~@Q z;P!W@^8hW#eqUMaEsMd^E60<+gZy-KCi-~-yP*vlcXXzhAGcm@E_Sp}hHVWHP!zci!k8^m!RDNzMr_#i5uO2dDoddpE+T z!sUIe7vu@en$9={LvM8}UmvdLC6Iz2=j8ZI_;{3<63I#Jk1D4!m#lmmST(j>va;2u z!-vBgCnY2+%b`8Dmuh@Q(4h7+<>xM13{4_4dxKN^^RkB)V~=bYehP7lklg)VM zQv>T+D_eVmd-T5UQPtz-<#gg*1*06>u9zykTC69`3sNDBxUeS(w z^b9@DgKsqMJ84hvi58G4UEw@rIKOFq`4|3Hn|K6Mqr>PyevXu1M?h=%f0^$kXZ-K$ zkafk>CzdQ!>}PS4M}BauD~Y^|^z*u!=|g&RuKcYk+EN^XYF`Iyo)(+fiBL;(K>jIi zLh~W{H=XaIHg3Yjuf`QOfedSMv{QPdiCvw~I_qdhG-Ki;pr2~$*eOmzwBz+t9k!k| zP|r@`{m04ov6*w#nI2tRnVgqDddC>W3zO?H4?SVzkkHyuW(d`ksD`wM)R=a$>~7As^;@Sj(8B#hkmdcH`gY z-l}<3jGS!s_sQ=F){hR>j*h`kHrD6iQeu6ycah)m&N;7~yJ}H4c*}l{F7dF71$vj~ z``+9SP51L{rJ^|ViH$jjW#C8Hw{74+`7s-@Pvh`wEwT`QTUQcWv>BVTme{d6f&X4%kyia?wbE|o85_qb)7rz?)hxxwx zFzO!Wg%V9I@sqE3fm)Z~DBE@v46Hw0S22Gz6JuRhUKmQWVuQ}{ig&$)E$qXO4UGM1 z;GY8g6N!(*R^29>6Wh0L3isH;+pta5MqPzx@~vh63jS5V{}SJC!7AGOR`0Wx z82ID7_ZIKfOgt^A{uN_YecjJzZ^I7uLh+MpFU(6^d49j7>}=V`&VHBuD>wvi4RBPm zCP^-Qfws_@$bTp@G9ec~fA(X_Tgc7l2jp>^dlcmHkJD#UE*{_N^LPWXYc4*$4t$Hp z3(%#T*>jcN@+`J-7=D*79qt^IsDkIi$Ayyf&|4zpQ~GO0Po7_tqRairq#W=L`H1jd zEIH-F`*65%NT1=Ia)|K0I_sn1cc6uL9&#YOeSDwceebW1?+*^Yk9|aV9}MF6hN3>h z`>R8QckM@n_e|*6(!2?1{cQC8OAY9)@+BbCl%whU z6P{3vBz0ur_chqK$OIE3xsi3@3&;oa{qON1pf3i$ueRUs;#ie~PkKcpu3+3yR zj{?6-*!aAn=;mhti;KCu4;?#rznZl(6=z8srNmh(x9%j`P#f@Bb-m(H=mVbU<|MmEfU?zqP`T@;CH<06&tq#@}M`BfrB^iyyx| ze_X;ta2&5P?%@5?e3w10XVCwMeQa52;i;ytCBPHq?>q~S`kN0t5ypY8T_Ii8z@8sA z{~wB6eQoAP}Kn9E?C?Bl=;tr~sD<%pO#S@b>G3jSJf zgwd_Hi*K^y9`jfqB>%A&mg;|WzDSwQeCb&a^@RYOz3QYn$t>`|{CfKjIF2&7H^%vBE72Zq1Q86jPF3?T>b*4Xj}&P$Rn z_pV9Aoa4*=_G9m(7I z$i6w1zK>Ua9CBDv{(JKKDrBR-hJT^DKYkHwkIS}ld5*R3QCkBW>H8<4v+|DY@t}>g z1G%fcj^G|gD{@x0zzh1u#wcmeNxJWy`VG3vqL|> z$es$?QrTzmY~Iy<`#0(91}?4NPTueDf2{{@4G7BA;(;;adoi^-@JZBuFP5x^&c2O( zQxGa%D}2uf*Jb2w&tEmf=mViujd#g*q40#+bBW>`k^RKUWX86aPyG)(({EwgsKxHu zK%S0#xec@}--7bVl}FxiOFEByE4a-iXWchLm0xcBOqsG+wNFm9xX?H)9uxy%@-uWF zLS}yB99JhTQ=crSKDWkS=J~joTBCgYf?bV_yNYp_w-3R7LT>>Vm3Hil?AYbwtz(=W z@CSSM4_AG0FtIX`wK4V(=SO^aJ?y9mxl6*wZQwOb`$>Zba=O4xnZ-qO02iXOX8VrD zoT_hR=cj<0$!>1Sl~bQc=hSO%DzfG#IeGmewX=QG1D8i?%N`dj8?b>@d%4lhNf4G? z^YRWhe(-#8KDjTkIT#fzO3BQE%9bhxA8`?r|O zD)jO<^9QxC&)n5%;wne9JiBMfO!*ToJ-*;>`6=J#`HRFGl(dC{ij?LV()m!-F zWN+De&Ms11WjIu{V=3n@NxypvJ#HTDuB`C()J_ZEP5tb(VZIO3hvMU3-_`I!S%|t` z!(uDebSC#!m2KO*rgInhAqBfSb~G-EhUQ&Ujr@`ysu`TRJP_$5&If-h<41Qi^2Pa} zS_3{PbQ1jNlT-QAPAAd6PtlpIJIK$7S%>^Q5XlMoQ*-f3HXOA9IF8CD~MCs z@R?BJQPw>9d4u=A=l-tOefvOjGY5QVewx5*1#|*6?k3(p3Bf_*{3wQ zhE~l&+jD0 z8O^o+qXWw47sR)4oWeIaJ{X_hBJh(7z9MAmbo!TEkz9x(SBjAZk}*@M*)Q25nK}=A z)Md%k*_tEPw^rs!a>er^$W%Yp^#-2#GL?L&K)Z$s{$IILl;a`p5({_|xu(8qZ^uWj+y znh5+o2b|P_llhWmf%+hlW$&Ko&uj@)sHVH2cdHz}yTvvkc zNPay?-){YQb3qz^LD?leNwpx%o(Qyz&a$F@%}tAzP)~@tM0YB|9wj#p9VQI#l$=FQ z8ha=5zx#Eeyp}&J{~v#DIIwTJk$2>aRZR3z;I9Z7BRwY!&oqLE3TS@`b$B`gJgz+y zox5-qaQl8=ucedzT|BRJ7u8M_O>IL4mBACY5<}jI3@S$kHGtQp@N*q|d9|!Z;)kX9 zFMXScn&HX|(|$8KgJF0_KGa(6@qq)4kqSGb)l`)TDKhS-nHV_!0#{mFjlNByzM4m0P8Iz2T`OoGuD6~n;)R%fjU zLodQv4f)BY77IRK)l;d)2PtIeV{S31LIMQ`|hx!-aW{|n}c{EZU3so(WoH9q5T zRJqiVL@oD{anf6t;zM1EUsU^k*RbbzExz1hc;N7JRxQ%rpK67?PE3kqX`KGtK3>}x ze^2Qta$mJ>yiI=U$kE>B73}BDAs!*bI<*}BI*I**lKio|+S#XxLtEO%KUVNE59pp- zUV%=|ADRBHW@yjv*t;~}mD=xG$**|PtSOR7WykVt7!O37s_XQc*Qno zb2;);{-8I2eLd^OXq;lc9d*JcIgDZ_m0?FCm{#__$Szs7salPClSrd`F$8 zu62C3uK&p4_k@O;@2dEYZ~gDCl%HVa@#=3T{k@Jnsp9=A>LM)(!Q+g-ocG_wwlV#z z7|r`*&HF3xSGI>)|KT+&&IYI2Rk8Ii0({QophPoNJD}{mfAr z^P|0p5q7RGp`BQv+8NhluHWQY8}(<^x0~w~(6wqL)UtnI+TvdGEV>sxS9f;%{C7I` z8viSgUA$KgpVzXcxjgnxYN~0iHhJvG0{4B8AL8((uj70IUOye4KMmfWiwtmQ9;9Qf zl?UGrJ*h9*eClgFaUjm-lbr3)x?z1WVcM46cQj)J&pqru*|KdZUr{vCiA=1M&&B!) zA^|-?F_YRGEVBCqzd>&*q1_2w2lN~5 zCkyWG6Z+ueA}(V)a3=$BYd>7DH$ta<^>K{>e(5;=xne!fc_>0R)V^^H-!bjZnnQd* zJMu+moocU{eaNmh^y8$SO(SN9{~HT@zjB0Uas0&Ptcm65lXHlz&gWk1)jH0mk-oo{ zvyk4&AJ`)Q>`K;`b?v^sUp}qi?sD`;$*2eSE}6Lw-SHlD#|P^*%JJ< ziis?TJ_L{8lE3tH_&|N>Ua=l6z^Hcxqv`{N%g&tDLVE>#BfX`PcQilSL`#8r(K@4f zxs!QO%vG*^{TF?DdRThC=0$T+>(*H5py>E@T1W9aYHe+1KmLk|p`?5Zg3I}^^N|bE ztu@Xw_--Ju2|w$s9aJ@~@NSJqy0vig2J8I#fDP0LZuDHwnrT>B<*AKd&L+Lf*% z9@^g-7~vyq?l1aDIWce}z)2lADTBXC&_`=|E#=DxQSFWLeIj_sEgTa{R;KFz*#rrS*5wD z<+r9n6PNn7iA(kK%CNnVB_mtD2rPaq)##Su`cN0=Xl$9zZ{c%@-93|ULj^lj`%8L^ z&f2P?X4mV;r>di4$$Fl>Jb3M{3&GX7E3Vr27`W1V!dC+|J_;HtO>S!`|Lb?jenS`4 z1&Ma#uIeNFn{+&ITZx}Qb!&RV@r&f4%AeF9*w7z03+C>;k;e9N=bWe}@eMrJ8lkZ? zupU2_SG2ZyF!t+LklCy`;fq6EZy^iGXB&0oU%GGaIzD#{MVJ~6vS(Y-PmMk@44TmY z(1i4I@o5`#ExT{Y^VC&fY~oq*dMUq4C)HS`V_ii)!qg^}~6U;k9efSF73wnfeKh z*b=HmQpNslRbo~mLfoioN-9p)qjscxHw8!gen|11>c^CP=+`9)+R{PYU;5`C{_O0# zp0P9zXYyAVoJpsL28FXFtcAi^HTP4&)5;q{%bsR@D?3BWI?&lxZVW9G-CWFbJ&V%D z%0_Cn>2Cr&fzwA>GppeJmGEbXZzIi%l1}&6oW#NF3Fs$N_0CprSw8nGsr9v*xvA|> zKK~b~Ck?)Z!?oCc%uUf>`^RqyBOfFO-MofFgVy2`SbP+4-lKN-{~p@84>_@(cAiu_ zwD}z8DC{vbPkt%y7+R2A<^O^QfsHoRuEs51DH-H=rFNfioR%xO_x)Es03K*-4}zWVD-=WVRqmCGaRPtU?ydaoVHd6P?IOt`M^nd(rl<+(*HZ@#WHslVW%rLN`5fab#6q?P(11hw{A8dgBlc9uyHW-=yiQ|I%kBi^%!G* z|7Xg%M#goZL+Y&Vc4T((ZLGP}=?&()YP{-y4zTInHhjY#F;+vke~UghgKx=!eC{O& za^=2W&ojw3_kAOBK>4qcfswV5?-Cz^9EjZMbs=^KjbCfr>4t$ zU+#yF)gN8Uod=;>pZ*yKvL_|aUtNprMz5;otWW7?5n|{Y(EV;j_citm<23fy7+?3L z9+k1ZgdaWEnhSjteT+HNz1AS}{xp9L5)J8H#dSu(W1)EG7u2y6J-kLO8Qz!gcsIE; zGi*E4_`C8ve-A*rUVmy|7=62>ch;<{*icU8?Oqq{1`#nozB!=BB^^U^W)1t!LxI2UR(iJ#8f)4kcj^Su*9)83wW zt^KF>&G)5a5*2(eKGyg|>q}@S`0TUX-+q3jk&l91H1uU?M0!Va-l!dF|88vY zV%B!a5WTa6=lWfA{67WW<~yyOT?rlBk+QRWTTFDSb@n{qi(_Xa|F*0#?Sxtm=Qq}v zoHo>Vc_tf5-#8me_EQ6Ky=CYG4cKBcu%ARr;)fWu#?4y7TG`ItlyA@YG_5gp5TASp zxEI{-!kgh7HuS#Zz`xPAIBNqODo4lBMKLxs?d%S>k4Qw&MZOnEOx%Z=g@pY}F z)kB++ai2$K1n04Em1k;zeIFSqx^nfKM}+*^&D!e=(v;3?dEey7eggS&IyRimmCa9| z$w5xa4$Z?HVv0F8Fr|Z(>VM*k&9mQ9SB=_|%7xi=SlbI#rQ7eqzxFz@wu`X?7HVxw zl2BHAk&pFtb;dQ{QHP*%a zhFQ-(%Wqo87V@{+jHmaQ;hpCDe@x8q$+UGSct4Ww;=SNq`nzi03g^Rk58k+0epB&6 zBfO-#w;F!|^C3ASepmxPQOl#^R_wV(cq*6Qeokr*(zU2Z#ACC*s&loWTls86kKuvX zo^kZs$+1}##?O?utP~lF+%WsN<@}Yt8`Zfu<}8Y$mVCY?e{NaFk@t)p!MD&aXGmn8 zV|wd#-mDv_)#2l-k1&*DxA*sk!?&3*^zRJ@)>+n){lV~sgM|S-zx?Qeb9=zReoJmV z92kbVy})oTwbzAz&4ctI%>z0_*Ze{0zJ$kIxIHFEn?=m;blNm_BJE06)$)DB^T}$)1NDsehZ?CfSwLDXmbw z1nK-+@Dr&fsrsOfR+svDjAu_%OI3MDZ_wW+Y(MQCmaqq0dt%v8*#^%d$DgG3vvkOt zuy20#VdaZMh7Df38-1@NudrUVi>1^3jkV=Ce)}7B1iM4W)vud;(_NdU-E^1ioWHWa z{5SrN88&e3QTf8G4^ zg}9lLD0S9u#%D9=rWYFXVqGm~KD4)D-LLk(e%70NwHB@VmbZ8;@7#f&jt_rvgudpi zB43IB@0j8x#vb84e->j}c_;P}{jJ32M*mp65}mmc9oF~N>>u9+he_v=PiOz{9rk|r zC}Xc~#RdiTzI?Noq!`U*#rpN=^ab@EzQ1kER|#`92{>DL_TVM!(7gxN$4C43&kp*Q zxsOtlTsBRddJ1}fE`L{U$KK^{88|jMoWB4T_AvSa%cTWg(LUxtwRcOVdCT_gLZ7)& zb3m=6_ud&Q`YhPhJ#^}d+T~S|LSi)h8k8pvk&ZEg_b=?U2*wYTNm?pKDNlK z-G--T!bji3uT)1qhjP(4|93|-bUPiLxR!Q^sendCwtR>2X)meinx6S+SF_L40i9|O zp^a~9KO?<$WX3+0?`s>;@+A4fO)q!%IUlWxexu8C=cDZq&asaLm*NyeEBApL(Oun} zqPs|a_0is9{AxQ(-xzQ908VARKgH*T-HfeDoCrCcP2`z-|Bsp=TpyL^7tC)xd7cr?WS z>SG#qhWd@Yl~-wn1M@z04&nS!llWeW9t`=?|| zc`q`hDD3akkE-^41-K7esh)#xfU5><`jN*a~hxI^UllEGK>GTrwmEg zofw;u)5^lUq56Eu5Vv>j=dsC;_hX&~Wr*|?&G&z({+;;q$38BeQvEdOwDk%9{%3m5 zoX5CN;l}cVn|DVq&w`uQ57WH$1KU>hW8Isb+;zAbWaVwl;wpYlHm=6@z?I~T`~=dI zoS&c#KG8Tf&{uSGPh4p&%$fgt6f}2MZh3oI7Ov(zg3d9K^+ap)BmR0qE%^%7(hJJ4 zuL@V-vh4@msF3kRj*bLh2X^)OtO?7(Pw<-q$-N&S_w@beY}?+Zz&uzQ)pN~3N1^w` zDeSQch!(8{AH(n2G+MQ_{Piz;9{wAA7@9pTdmhI0X&#!&{CQYJUVGcW z^_+*^^03#@Z@e=1JPgX32aRPcc#s@vy5E;8MxL;T64X(yrp?wx_*PEzuOy%X(2 zCecykH)ueQ4o8t2H^-K{Jrbv*lzfnvvBy0C{0f%e_GgV}zP*XwmOOqFO-LR%InZcv zsv3XI_@&cz4#xGs=^bPIbu^p4oA8&auRl_cEc)FvUgaCQ3O}9d_51Yg%YsUK&cY1g zbw+Mk@EFgWEcgTZMC|}yey7&|J|%jrDDEuV!iIHP@(>^ZIJ@=1tZbe}{IdL}QjL;9@r z->27iFHWNOYM=Z2(4}m;HRu8><-5bCJ2Odrx-WE#SC;^BKe1cTeK~Xi&`Rh?e73H}6Kj9>D04I#+8%%h8%Ye(TQj zmVJA8{H~&*8}7ncUX-nOegzz9jS=lhzcA|xI*ijZ)YgmC$T;!?pZ`R!7x9hWSA85a zmp|{Hn#&LIDWQ+gFu%wAIX;lQeGhq?4Of-zgSr?e&FSau*%}8&z$qAmusL}D0E~af zmdtKvrfo;-g2u8Qy;^kQ?mx%!01*`P>_Ojf^ACZICY`ADBAvWng=CCGlmH zcOJ(^Y(+;2i^uR~D8A%zd>Lc#Wu(p?$y&3Xp?&tj&AyTIbsM{yHOudpF`r3=lKU$bCD%eTQ%8FI(r=}4^sR=29g#x}ZDC-tzH zzd6t2f7t8xVtiX|Hg=!lnH}!c_Hs zcCP`S)`~*(2K+oGrcC<{WyRhJiW@GFJz{+uUVPQ;-g5rqjOn1@xAs#I{*M7aGQ!YL z2K?AiDfrvx82F{%1mXX_g<7H-|TJMk}_-`~d#J z`wGFk!;T>i{ssFy#-ec+G6%xF8%v}}zJ}bj2`8k+@)P#yvSR%h&sfIuZvJ76r$4mR zk1^#_Lng0f9%Is3MiI-?8kh84jq5k%%!?h@SoR}jk3{drUj|>t+_-A;6Z09@Ga7^F z3jXe7Tw%r~ebmcuJ()S0bupLtd=+C<9;Tx+kD4rnZNAMLieEQdb2ji#^249Te9UFv z@l?j6{f=KWKS?a3VtZcwuY;tyz??ar`7UGIAI~%>Ub+1+Lvy@~F!2K6UqteqS%?o05y-!$i)a}*2mEo$lSTye?rzeR?wZL@xN?R(W>Z?q9ZQ;m#p zYp}<@hVyT1q#fxiT5H?q;(KPT{rhll!wL4R4z+OsZK&RJj2NkUY8L8!*$O&0xlMj0 zVAlU7w(dk7ZACo)ERrUkYfRxzzqa$K$S%R_`-j3N4p!$x57;M!bUFQ`~~uC?VEkmCl>z`;8a*wW`CkF{zj{ zNUhJajMxVBg_}zsKEc!^>&X7S?C6Ai9Is^lzO!`m35ngnps}1l8}m2=n0@4~lF6Kh z&3WEsoSj}s?8Hj;s#Y_G@D0QbQui*bXM=J-DO+=|&;6_!eXOjM{SD|o7p%?bW@YS!=X$nn56{XKYhJMHb=IhPoW~aBx3IPHvLY{E#!GaAg)R4nAWgKW$0}uaIQJ;X)aytVDwJEj+o+6mnz<>bcBgVl^k*L zR?kF;H_eKPi4Ys`A9h~u!QNd>EzMeT#@24rUPfVki2JfZKHQ>(R_3MARr5lza6pzEU68 zw|C#(!T<5U;IqeHPt46O?=Rhp&k#J&?#4gs99Tb|_XKoYwVR^Xc@>EZq089;x|B>P zZFuXPSHRJ7f;{v~%vFz)gxRBo~GJn6hG#W|V%kM|n-!+~|uK+)E zU4qYYYddEz(vQY+8Ztw2Cfc5^q2Jn;#$65nXUmzfoVPf}wLJ*i2YS#vEv5Z427c4b zRWs{ij2z%tso8(JxwI{0#;iWagS)2x8Zbk)hGdu8?-=1dK|2QjDLm~SlDLj{_F9_I z@8Dy1Y4qsCM1FrG@VmiBN4eqmKj-4@8-SDeCTd}}lr?&ZiVha~=E7G;g%O1RmFW2@_k(vuwUlJf3*tb4TJwCT23o7fsSz z(YsT8v2kP%z9`UnpV@ptobrgtq2xxpzmOrbPG^7kMSpH{@p|nGqTAeZpy7F*^&+#H zck-+knYHcLJnKbfb^MBFy~wPvp6y3wg`eYjFEXp_S)LJBlWUCgcJS=z+|O#C;n}p@ z&lKYzUCbt*$puN{~$z*ciYXb7i@ZYu*5)=7-V1WPleP`(v(-L{e9mSG5 zd1rnfJt6T5{3>3`C3owFdPS1mk_Fw!0ll}8b3G(q|AhbiXMgZ*lJ0yz-!)}R^1f=q zmxUBpPpl1V0Dj3mQRI>0hvy-a&OjzTJMboC(!lx#c&i$j)QY~QXFJUAh4mh~l(}Em zXk^z$e9ZHZHQKutEK$WRBiCK7(S5{gs2-POy{p5unpj`S`z82$3iyU`o4Q+93l7?n zA4qMb)-3jnv}Vm?P0{aqu4n3J$*0qC-#wlko%u{KN>>ZQ_X>KV@(Psyr*>DNlimRw z%15fAKfzaGY_uk1gNA93DA z|BC(68mGGN2aD@Bz;%59*KZu_CFSFH_-?0t;krHFhy8By2|Az~>GQ%v8{a!S>ceZP zw@fUYvkRX4eeZsSFg&dK`|>Bxfq(OzUpavug1n(6TmstaI9l;o-MA}{5gq5P3Q5w}#${f~$ZPsJEme?^#aiQX?4ZSaoZcX3N*o!;ul z7#ROv`*CJZupIf}Z2bs!v8#zO;vCt;k&2SIH|uV zC+priA`PRH3r5xfqkQXT?rWwS-}-iBL9V&4#;;J)!=Kx;ChDLRj6Khz5j>YjCr;5r zQOlQvbM9}$|NbN~Z5_~a8~oRthkU_a*S*${X7XL}r#oFEmwdc^5+86n_vC}i=7PUdk=g0| z6V>XFTMbgsL{{*4UUa%`A{3O@cncQL#2&j=q)y+KmEqZ@yb=B z|C>B>F${`{l%1>bY8=d)(X%SS$&)-2{mS-qdxXDZU%%GwceUZOQ7oR~Hi%)~dF`tw zCBB248VOCdul7uQUOBN{$<-y0JGHUlkr=)lvsSWJ)xc}6ef4`e`=Qlu`!=@rHuQcg z<2U-=EZ*mTy*~@N?BFcrx2d#k+FVFnGx|la&1&%0N?w}w4%KFJK&NwZ_{Wo=Wt)5N zWL&k?=ajEOUpvDaXBionWPGR5Ul;KQf-er9OyBc~C**(Ew{R*LZ^geTUa$73!2v#r zTWCq`V`i(r&a2R~leB77$;G@C9BzOc%Bd`e; z!RBhvRAN75*Pv-du1e0`M1SIuCUWCqz^;6s^Mng(8s(}}@;jcjslEu`1asqb=0({g zKgM`Exp9t8WB9}j4JkKnSNGzLtC#Ex;sn3d?aD3J+OFI<?EE&{;Mt;tZhbp8ltmN8X@K;Qv?FBEfmhrcQYXX<{G`r_2 zha#W4CH;_V{n?8;40$vFKYW<8zC6xjgPz&DhX-X->3e@I3>*Dc zYvO09_rLBK>JIUo9LmM-;ak6k+6fx_<@&HT*4UI7fyp~pZq^> zfzwXbylbGXTIl^s(K+<>HPL-&OvP2ik=KgG?)A?sX+oBC5IfMo?{5KDBjYzPU~>w7 z)#j)~uAd0(C86S7xABg~okUk~^+TS5f1NHc61cuioRl9QHqJkz%gU$ei8duhsM5jZeZOpMY0R zhi8;4I+yc@(rfjVzw5sJlfd%{F7emFo(FOq-$nB?<)YDrp;xO5?+lk7Yvkhm9JO=m z&~tnl>Bj~{(1~;9^PK^lhXP;t!0=IXfIL-jy*+?y;aD=NukcOk3w!~c(b*DhrOm50y|ZG7n&$c?4KA8=}4Kcyog6I_gGP*=>Z$MHYEJv5v?3d~+E znA3BxcU~Rx2^_=XQB)^T*!`A{|wS})2 z+k9sj`)oTneI}f?&%|4e;M4J!4=4O3JB@Y8kGaXLl`A{){s628Q&+PFIODzGQTnCR zZ_ePoI@XJSL|*KQLxgn(FhqNS)zT^PO#S>h#~kD;MD$Y^hke?Uv#f;+9vw%>#WgL{O{W+B^9fwZ{3FO*EHFl z6^$Rx&=)n!^=(A`;@{P8>i5GEZ$s<|zir8>tMPNb`%0;SOSlqD>LXls=j! zdd8**+7rT?^QS%l-tsr9mD0_xw5qA9BIq*e+joqVP?Vspk zPhl+I{e*8c?`mrsZHd1}+cw7F7mz=;h*}+{tYNxi9ErYSfwAMuP0`mba?x7x{VxYL*^}WMW1k}U?EZj@D{^BG zGj??EE@T`vQ%e)B2FA$G6aQ!D-OQiG!HLMBtLdvFfCq=;f%Fr%_M+3DT|XUGe;#LP z!kmW+O%%hA4!@BaFEI{0T+z>)k+Mmx3~+tCRRaIBFOW^gj)ukKqG5kL#2DHB46oB) zs;^4 z3N9p@#Uq`}|7g2LOXrb3rnCL1RZ}FJQ2mK6&ZAGQSL#!8Ay=Od(x+R~f^_Kmq^+Id zc0c#dth2UX!B8xJIDH!!Y^>A}Q|ejV81Z-XyKqiyneZ1oZz zGz#p*jDF0-jBO{b)va+Y)_=Fd>aub48|jTMW~>nXp|3HciT#YFEE;=4HLr#HhGE`x z*(UOPs0MyPykXJk^G2Q4t{7EM|Vp*tRY+dnT=Z5olFJ{hlC}12*@OjN=oh#2#Yx{6F zZu}9ZFJdy(hyFLb1rBbbzZ0Q5^_6P(0B1!UX4{QY-$`u+&x$ykXQq97RzxB2Hhd5N zgLETwh&ha{^i3Nh(B&=L%2~uWYD~0KCt6}mn%n)2>(3MX`D~+BlfH}CaSenH>$tyd zWUT9+(wX&Tw558KYnV&XWfk;U4=q*|uNk|fZf$*eA84_+xxadVcjDQ=eKE9H58M^# zPJ(+KG^x0%i=oLn=B1W-Dd$`_`6k_28$Yt}$C2ZLUt<<6%I5yRrpH??EbIsSxC9pQ zhNH)q^1SJXLg!z%?UJ*Uv)$hIK+x}2Z2#qr#59n<^+)2_;PKf&7mw|a*O%CS zy}We4@~vo05zAvQ;NvUjy)v#Nxu$SU<~o9F64ykoQm!S$zlD&s7oFtSQ2FrMo;8*F znv>C=_FAnC<8*^oE8p8#4~=}UneFc_hSTz$y%@7UhX#F;FUHGzc-22KZ+i zY(~aNo~oWwxOn8by}I-j;=u<%h6FFSFxs%aTL? zj5T_Jg{6sg(X207GErlFC%`W{x8gwOE6uWPw%Ymi`9AU`}j zwBZA;_qp6$pL|ero#wlLh7Q&R+(rkJO{X>6;`E;}zrVAv#D`|W;?}%Fq2H~p%|V%M z))o3XmuSSuj$&_k$ywgAygtZ2>A|_=%c1JQcUTy+dF-Dd@2<44^u}XZbI>Q8+4Gx#rKnOna&=t@Z`) zQgr00#eN?v@jcAP*3%ha<+o+pdLOra#PL50#=7sX?E!Bi^xlaMD!+!>)!Jz69c)S2 zIl^N2G`fQzQ%Pe*EL)#xD2mhEB@pJ z$7}mJ{}rAKy01&4)Ct|_#JVYFLNG8j5?4X5U283 zo_CVYg^Ls_#>S6j5M73$%gEX^-LE1JLh!~}f8?ufpe;Y%dUVS;cvbg@!>iv>KeSWK z860MQi$mv<&uDa`^!%pJ7Y))trjL+!0zSeu@KGahHV{)IIIG|z?9E-&?tP*WcxBHv z-k1sRLJO~a){Vd?-;rSM%s-s?BjP$}M=^I}YRiqUFr340nMs#vm>QtRwZJ4;@L3vN zW-YMv=Eo5Jj<)cCLxVrbght>PD<2{7-9s!Ym6%H!VVOKoknZ8hQJ5zNlM zi6G;g9Nr+Bga+jAaP%X+#Q8cD_mf?3*u9_DJ<_$F<@dOney`%XlIsdCr?>v-cqbEj z`T?8|!10)aCCFcyv>Z6I_7G(2HNd6$tlpn&z0gbi`tQWDX13oaz5hbnetbW=OLqK8 zIp35yd?EXm_JXf6&ixd=rbc5=L_J?`(cEh9LG&;++WXo(+reddB1IE{wORWo|A2Yu z6P`v}cqHS3G@4q=GjTu6jB`J7N_3xZ+swA(GS*Gz_JTv4+g+orTserj{UP5x!u2rM z54a3Zfb%`mdgqCrzOl5O@Xzp zW}Qp@ZTc|lagP1lmw6_fhVA~X+mpQ#{Z;L*WIf2>@hlr}rES~!of?U2b$iZnYu`m! zN1bgaKGsu?i)jnq^4qN(=zb~%6*ZJ5N^Jr@hd$H=P4qVit z_s`GTi#^x2N1e z5Pi~1_KrO88Xw&6Q{3wleDgThV_ZMt+QPM&>rt*Nng7!{*URt``?qf$`@h3SKc_G8 zQPlcI(tDuAErY;QkdF?e(N!#BY?eIV$*oQu!9E_+R{q(%Rc0fmOhi- z=MVZ^GjfVo`7y<1z%IK+xi0@*3>{mzU7lMUxWkpI1r&Qiak0(7>#-)30eggfFW!B3dmrGmagRYbHv?xh2b_xU zQyjPt&u9||KK~=cf&cmt;adlM@m}Cl45N#wzl!&md*V$ef8?{K?zgaZukJ@~+CcJb z29a+wn7o@IH*Fa8EAveas2YzoZUJYNbH@ErXgxv=62)a*2rc+II}7>d9KJo9 zHWtvs#5M^zYZ3d*qaVU$xHM*H9Nt>#+3cI(UcJ zhK#(nNm=*z;r|ey$=|Q{mCL68qnxE@@}I~V+savbijUWOdZ$7B2(5@8UF>NE_-#7Q zkEP7W4TMhOKAjK;I@$Qsf^nb`;uT#CDETfom(Tw==OOsHK^;7cL_K-yw<>OP8*PsEMy^$RZTVw!)__-SkSMf3 z9>}aELplZge{;FRyevGLZFWwMtmI5p1Gf^{s%r5!y+JXNS#c}igE}kjJS7Z4V zxU9`Tobwt-wCKza`L|D{=0n?neo5j_x70$jb)Ki^S@J{8yB27D24H0Sqx&;R;X-yH{j zl*6xj@z7313GG*dPr>@@ou;mR>O7)V;OZ*yk)3<5v5O8qW9JU}vxPJGiiD$5ev4s8 z=gP;w*Wk!MqbQiqsT}9*Gf#vI@kJZBH@PXQqi5#9&(VLAnh15s+O`|>lGKSZ`JIxR z6{3p(&dPG&>=uVJzLSqy?HC>e59WLNs^Nd}UrNR@W<3k$4y(3~YV3%X#rwe;P|6=> ze}pyM=X=Rq)zlGvs_x}3-d`6=^S|m|62p|10s5cs+o_xL%B!3+bDx*^(`qmA+T3(b z&o4MzLhWgd>706cvTR{x*VMCgMtk9oC4(Avl|e%tCt$x1DpyN8k|`VIPw_M$gfy@ov2GNaejeFVMcPR8%x3;GlKlGk`1FjiX_ zgSxFdD-Ai$np$q;_?jS$hnUxRX$sb!F}Gp-ADSP;o}p4I3bS^EZk@?9_1n2(CLOLu-7^?4v$Z{Khq-_@!IMZ3bwR`!^6p08qbilMI_uwrxU&zJS8ZBudP zuFZC2zTzs6VjTKSxb6Uc&F7PYy***piwrvz+#Cq@?XI63cIxn~IqfYDdmU}8%oUdZr)U>Z6!-hL5Hmi{}HR}0(zb85WVR~`nU1j&jl55aumsr2M_O|C| z`TOpoebG6WPv^+M@+&7K)J6gFvT9E#p}D9W)_B(|$g=W_lRI^{ zh1sulXlv%P28d5fN;w0D8fb-KXs>^K`1XSMaPe&g`g9(BpIY|u#Kq`Cm#}7CN)67h zP@{7hH9WsXoxLWm?rtyHO})L#sQKAV?TXTAzJ5XHxv39OlW6fL{*+Ki7m*qX?#nnGb*Q|SM zn58B5RXE45Nb)}Cyi`)NZUnj;^P>51b2F8B31OF3-S_c8E&A-Gw|{|_=hXE7%ed3F!?lX!1E^KvoI_3Z-Y zWnE}U;jui|`<2YauZ9gY&-0jvzlDbKd|2Ue{J(_f3!#%Yc&_&~ALl?be`5}+X>THJ zdtRte?+G6DsXi*9rN0gH-N8$1FUW6}pp8D)jiTYK8TIP@c z%A?Qmdt1Jj2r;MOt%F+XLXnpC0p6ynn(enz%b=zF!+9?jepvfr_`~HdR(<^|w^aS~ zf?LYR*WOY;e)%oo_Mt7i#-H=(yik~0WQAOjmWJ`wk9wgm|Lfb(%E8j-jeH|nl0l!q zCi>jTvrM_slRnP~(C7LJOP{M%BefsCivIX2LcZLfp0Uo5jXT`oQ|Cwo4J#D5xwl@?=t2@|35r!-PmLD z1{YRglZoHo95%Rc@OW=#4RyRKSdXHsVrNbq5W4Kh{@!KbL9rj^-ygoL-~HiZC-Zj- zf6p0u(WMKAe&LwYhJNAFxkE2HX3@|u9dqu`FJAhIpW$eWcMv1De;2=3dt-%~O(If?s8+&|BKJNGAWe**Vg zxqqJfx!lj?{t@oCa(^!O=W@T1`$xFHi2IAUPjJ7H`>%5U)smT!M9ECai>CaSXHUdu za_YbLBbT4LPAw`#WN^fQM*XMY{qJDttwL1(Aqr#cNkRay={!uMuPg)ZJI_v!4z zYt!*g<-~P}rpj1PrAto5FR~JPYDDL%VhvT!p6m{-tCg!7P3-A52NSwR9XebG-&I|I z~rs#O*q<{gc=Ch%3#GCAyez>K$HK*EU(abkEI){|4ai3*+~T;QuSY4_F944y3LX z{OH#@^?ilLrY>puDs>yM+gGfq_?D^L2QSuRAIO$pv1Y0Kfd%!%Z~6Dn`1jS+elpLE z|FEDwR&4JJST;c)vnV`s@1 z)j_SR4)(pvp`q> zKd#!;bSQ3_2@Ki`@bK|5_AO!VyLjJ?+103f{dwx{O`@I!V|4lM_}|U=wllsmd~78F zf9IP+@MV0=uUYAAGmT5Ng8!3xmGe#gmT`$^phfxeBSS*_BDcntci_*cU~DBXh00C6 z;7O|WK>g!ez2z(LH;sA#KM!?0H!@G}!3*c#Sh+8FK4aT(-@lT_IMh~@akY-{w!8p5 zS4_w;KNEVNpP%wgbb8u?~DNfJPM&?2I)*PM4So}E} zW9F#U)Hf+^`89C3Icgg2ZMjEdnV4fN6MG-a8op^gy7#d>kwt47OBr)g#++y@<;=r; zJC^bn{jroWCzZ^JqqkMeiN>M&c*Uu)j5cEdZv0-wE#EO?8P&oX-xX(GF6LgouM7Db zt;p>=ebu}(l6*{`PM!Z$zRnpK0pnY824POdY6pD=Ka;yf0g?vnOQ(#XKb+EEX9N$4Sg z-P*MeID4z55v7edH35P$!N~*bcX>EmQ{u~m0Gy4$SyUZL9%JDgELci}Pv>tf#{MiK zzS?W~mVvWx_>_FRV+VCbv4aJ()}^34bNJmm82l28wO_bPOMAeb6n=Boxi}Mfe+F{D z3i&^ubzmOr=_jexmY>@9(R}=de%p|FFXxT6e&zHy&r6Ndr?=kd=J(8p+Y5OYyGDB; z9qet?vCkoXy!OJ%WXCAvIr|~+;s1RZ`SaecP_k`xXwzHwdHl`WRLMFM-0RRci%pmcSdoI(S0n{F7uC=h*C9k_Z3gqi=CW7rOJ9JLY4PXP(O^ zIbWvQMz)?~8Dr9Zj`W*12SGa)k7KCqqJk=RsKVRqZ6&&t${9aAGbRG07egF0QZ+hXG=Qi!F zc<{NsE$iOci|)U#mSv{=c~al`facAct3Rg*tiZS{CXGh-Gy8=T+V*FZ;G>@ zvT_LworW^jDAA>OKy*2eHqZ$()~UGFw^Qru#v{x+CHNeF7r@)%@jB6};!5lud<5Mf zC(M@Ka-DaF57N{vD$&``?1{6tx(xk$aYMvAQD^pQo@(i*5x=;z0k<;-X9J2>vgzUz zjLXo)AaaHHR&=5DXU+9%7O76{p|*RRZMPM_dq%rIZ!|XMJTJaT^}%|yPptGx=qm*` zao4%vrXHPv8=ESleSAV|8>x{j_#-wByOzEL180PDLt{@sH`CFn7Iyq4?}v(U zXuk8#y;b;Ib{*>_j{5qxyDx=C=S=qYY>&e%*(2UtIq{!MIM&>E6`;@Z+Cb=*{ZD zx8n8-@PqDf^qb3P{nvp$tWoQ;?xYWNsvY8ua{4Jf&r3{aJeD_hh&OVb(<7Pj5N&PZ zdXVe;T!yZ(fB!n!(e=-gZy|>zd*x4;Um)t?tDT%>gFld&r}T5$5*>JHzxvJPHOFv9 zieTh>Xj*mGBC4?_89{r3^DX4&hu1!ps{8*<+VN#p+CMP@*{F3>v?-m!#rD-=kM1vD z$i4693l(wJKxV#>8~a0nvA=zG$jIp;`qbDPOrN=Plv-K$-SeD&3-katuf}hYC6}(Y zIIFgDDUwqzrD4|mostVbW)JXx2|vK}r5yM%a*ck4qcHU0<|K~H$44?NLcOp#p*&O5 zS$31U`WP|F7t;T1W;)4U=Yw983Yj2^Wr!0AG=GWK9n#~*+r|7CVKv$Y$ z_guQ1%dM=|I2l)(wldEQQ9Qp}Ge)NHmkERTOL!E2of!3HGv}*6aUfpnWK80D9gX!q zKj|D7?aS6mhj8O8&l+bkbDSI8IIZ4caQahfJX`s-bnx{i&bVNhx5CLV#lwebS8K!m z{F_^$pB$Z z_^O}z#SQ7TPqLbJa>?p(7B<1)cp*jitSJ|y;LWVH71Td9$5Y2=>7U>2sec}2Vbyx= z^iQqT$+Olidj0zKiyDu5@bZcWH(ef?<~^=_SVM=jE4Vp>Co^tg;(_(hp|-!K3_aA} zOaC;_O#AGmtNp&}q3;)1og+&R^=Ze-NMxYe6ukuF{0AT}pXB?Was8Cb&;)u)_asLX znK%x{g)~b}SUynhit<(tlv}dX!WtXp%b3PM?uyfyRZBtgt$@n8HK=}Ncg(-@jta0U9>+6{tV=I9}jj_HDH7~y8@R^kl6VaZN z#;KYY_-cOgw?oS(USQiNhSrB0*c2C3?&4o2pcfy6oc)+>&$DaS_WjJw2HHLt`5NRG z=}NieYw#V(s@Ef-4V_#aTz}#EGuLZef8r87URCbar?fuWLw-fFBMJ}##tzcw+qocSm@;g4B3qk}VP zD@eQlmpS3LT6kI`neaGTPt~9$mMo-rFY>#@r`Un}jUoHG8z(Z%%(La8q~jrEonpwK zjg&6jmpXc1w(SPjD9#E^j9{&hT*E(`lKTgW>B4bq=rd|*#`nAU>)m&GCb(UkUiR7~ zUK`Cjqqs(L6>}AF8QNit=Lcvf=!eS4#bF&(qFVl=8c-#`gaRwH~%wIIB;}q<8VP z)}w}}VzU%~DF2gW+?9&2hrTvJx8VWabgjE3gC<r%AQOT}27@Hz1t~Mi2Fsb~X9I$-D;o>lF%h~*&)kdFU zb1$)Nc*pcUo_UN-e)W#I__3k=M%I*$5uxQ}%1h(ipAO~C5HnaCI<(qXXF3=vGGQpU zbJ|xu=wr5>wkfuq96k@lzh=Z4Bg-`Z`|}$gVcTsw!f!Vyzl1-ZHx5o;A7a~VE$tmv zvnFF73BHUqIm_1iV1VUaTf-ukttEL;W^JuC@W@inJ82DkQovrf^unpOR)hST^P&BD zip|NY(eR4x$DEfT+W!aP_gUL+>zJPSEj~p2KIU-3_za&~SPdTFS?MLhgX$U8;IB^A zM?i)O-#KempnH|D7wKwN{HyJQxD(Td^mNrm2+D%K^3I(Hs&}TGzZ^2)>lTJ6d1njw zUu(N+NGw6dQ4{Qt##QTZXYGkx0+)9A!q$`3rkbP&ZCvL zDcNucZ60Uaj5{A!R-5u~YroB$c{(>8>n52l*>1*^qb5r0AG!nnytKb)Cpk13_{bHf z*43TU-@A>y(*HaxwBaSL-*Nqx>o;64a=pOyJl9UHUvvG6>p8Axxpr_p!)4ZE?BIb> zr(^$w*n?0qdoQ%@F9R-|}Z&^MxtTRmSqW+!sZD$RjUR?f|`WWk5O2)%~8L|$Z3)&xB z8I#e04)f`OI&DVxkuJYtEH*yh%ieajb`Yi@+);A-G{$VWbuMfQmIL^>{?)<)Jcj>s z$z92wF|@M+xp39LKLR;Hc!NMK0UNhdz<-+iE)141JK7v3zxH@L?2o+3+_+X z{}Fwt59bFxkc{cg-|N2HpTGA%`iD0Bg6rp8PjfjNs(&wZRsLXR>~010w1oJ9B>KTp z=?Cb>*?YFXr(N-<>c%)5Mc-*%Txw|wdu8UK&PNLO_!ctcM3$f8F$;$`(5I<_pZk6a z;otcwMBmPzYvzD9B|9WDoc!ob-Z{DA_H6oUuO}>A)dOGig+b8!qXiB>)9hj+GI9lk6l z`?RmMnzPUP+U6MBX58A*u1)#JWS{2Rt7+>O+VC=$!%t~1_;GT6YV_c1B)&!aW~|Of zY;~TXu6oEkc?de#uPr=H;Y>d0MX&3VE&F5JX7sSkHiKi7e%xSq{2=$;4`Gbow(z(; zFh>h+jJasx^L+C;uFrCPhRe_d`*YtJpPOfT_=}lW*>H_6wkC&+{tE4i7G$?L8Es-H zkjuJXb0M`}X-6{9*onxCXV7sD#YQ^M^=0=d{^PEvlJeD6e^>jm6f&O>L&@`q&jRO)*1@0443-MZoC%<-@3^Me61QtQyF7H1ywfDP*I_SCf(>0EUe$cVgHL%Y!);nzTpkDlbzU6O6`}f~q zWZ3or?4Q?`nZ0w>84S}-qox1g8rN6*tuOlAe_B|wWni7%kIO~(_wdcXa($QUJ6v~j z-Nof(;vWxp^uM3IlJYFtXYVdsKY4^UMf;}C1GKJ~GIDcouIehH22Esb6>$g2f&P9x zdl@Ux56u3F$v2|?|83kgTKKB7){ivqGWSvz^8PsvPwb1|@(;q(mwUsL;ub8P>TKM? zKLby54iZlTc>k~fp5~?Sl)1OvL!R~_e)Vt*i^qPplc!Y=t$U&3p@;TXob{`{Ef>GJ zSMjSxwzB?|*%;Oe);@El9Wq3GCEZ$bN%a%Ukt0E0Q@-sZp6zRLKDf;FsZZ7E-s*80NUl%Ih)>x(?S z-oja}^#Gh5VC;Qb=Pt8twq?l~x6b9-hnvASCvr{aI)UqWu4!DyaUIL$bd_b}oUG2| zt>QpEkwaPUQ)}S?d_*&W#mIQ_QG~DUH(+n$CldaRy^YS{{6vRj>$x@g=&Ut4E52={ zg~QRmS^M8PA+ePD`sFshZO!0xe4FG$8EtA^);`6S{+t&I?TJT3Cp+@Ujc0$j6o1*& zY5rO_A9-PX^^auAi+4jl4wM_CF()n085u;|((le=Us!#4v?n=44aBw55!BZlWRco7 zvM8(0MVoEgvwWld5bX_@!XIWY0oc@r^w8em`?YN&?(`LOT4dvzG?L=I4o+3ce*Ucr>1L!lc7b*L8CX2{Y_Ab!Zj4&~yDukhVvT$gfP!gVoM zJ=an$!xPl$d2p=H6WKK)daO6B1sVD~>p->+6Q^C#cN^=6TW?)(l?1NORJOu2l6VF@&6{AvxsyPDZb! z?E~qR8?k|cG3L2rkkY!L;*Xy3(qkW(8e`8ot;AIOXTRgy43oE3GAy*LiT_Ker?-)H zPPJE`eU_SD(Azsx&P{eu=k7`J1to`yZi{t|4)sqc|LoDcq8;~;vsgnec9dEP+9Ucc zFzEfZZzE^=ds`mhKG&JFZ#~yNO8q?W95v^_U$CEcU{OEejDEry{rn`*5BBz!wcIN& zaTR}C^S#YargABD7UT%(MtUuI%$MZ9gRhRdt zNgm;fwa>0!glLN{~EqCF71SuJ zYWMSEmFre8h&=cN`ET%RQHUH<^3F^iJo3rp!Bca$9GS1NNFLWR9^piAhE-F9`aw?_ zdK%GkHt}k**`UwO%8PD9&R5u4n1WL`3th!>FBr|r|$1hh?v zsNgL@Aph_0T$0H!T-5e`|MU5r&pC6>zO23W+H0@1_S$RjYoi}MpAXORINl6R9(g*k zKT@pi_1`I*?WJAT+(rLsj&{#4a%D5w=R^l*;)kbN2XSTX)2)L%01VbVfIR9m*k>`2 zy(2MuDz*=B<<|r;@ff#^+1(nSinqo1%v0RQjmQcCVj;f$#UW|Z6LuqSY-4WCWGvrm zcCUKnc)`B!rT3_MkMsdg@;u@p&NQLdcZs!>#`P|-huX}G=gk|wx_aZt)zydTt3%!% z(RaC5rKeQgLcVpx?pV)y-dxhBa+R2=^RoC~PCO^!%xB=+nPpTo^nhOuyD~4|Fb?<4 zyfROFS_7G>d6iv>lQb+fPhhp2D{4%+`-qjd&WV9h?~bWi{_w%LF|~rSdnXuE_kk;m$6aXixO&F944I2cWQ$xPN)Hp3s(#!A}a#wzhS zZTaMcu~s%d@iCV_)Hr)4L-4R{#aW~s%W21QU?1r4C%2A4)L}4Bovx1k)FFO)+B&jQ z>^g|=*1j*(@h|kld$cE0c=N%3L|6Gatn1PSJC5|k$j8>+;6mh|-?pzK=cnV-0{<){ zM%d01-NxM6#oq5CUiBm}ec#$I&Ym@JQ=0%cn@N+&_>AT8>SH(lH@JCFah)UJMsYM; zxc%%=?42O)!5^Vv!7EznGdwk~Z&qsFUf#X>RNKRUI4?Et^&zQwmkvIaFSKFB4jMuK zOa5x2?be=AWOvOY+Pi1T^u!Lz0Z$FYQGFKpL(Cxt{8RIT_Ew26zlhCQYmcSL=s!u& z1Y=)veRdLYaPe=5m9NAP7Ez8XJN|cnmnWRY{y02NMob{PhbdG1uQWzRM0S5~%8vu> zvb!IdRQ%BI$nWBlmYhiWXX1;WMNSOHv~%g%v=be*lPrwh8!roA=d?2v-_GHE+uK<@ z&9<`^Cp~tD^c26d$IEIfb^JTp+9jr~SDZ~-;VYfmia$zxTL(F9m7G~lUy0VHa9*nX za@*%MXzpz0wa?OjdyYHvnY&jic0NPz>E7PX#BmTLi)tK+@7Ck5Bc3@H{`c{aUg2>X z)9@X|pUou3fnpnIt)RanEA>l-H}%cv)rYYsej=G;0DO!6%(;EjY`#^7?5VO#k>inH z^YZ<+UZJrko+Nn>d-vJ`#_K|O(}%#KIVxLm7~EJE$kdYUR?$|CYw;#G27_d}KUqAc zPt=Wne7d*^Pd=Gg20BR>#~+|m-{WHt-}gTT9*t)MJB!=*b62mnbiQI_f)!W(tka$d z&Y<1O88_j4d`YBtr^3(RX`|$?BVFr5c)^xux`)?-_bl=I?nVW;nJJ#0#dphw^g|vNy%qgudqBp`N}G zzl!xAe~fQ>=W}8!BwGKeKVioJX#hSq2FS9D-?5#~3y$oaLmqzJoh`7w)Y8 z;BLEvJO1zSfjg7*(DBx(;4T^5%>#GXQRbC{yP#RTNOP|N?gT?@e2zqIoRed>F_|`6 za}9DpRzG*H>1;p!EcE%|F`GW?*aveu`joEj+9bqxMWdq6Z1EEO`Ao^{*gZ8aMGG3E z*jK8oxtD&(X3Zi#9_}BVx-~XBXu{t25oo6g+i$v(aiKmvfNa-p=e;}5zWQNjd);rG z@{tFv@-5oFdziJhnrYTe$l6;s-Y`QG%)O!UYCHbUTeDTBGxoBeam!x$asqqhRcW2< zV2`?OaqM8$IJ>H6dtEsV!4}o!Z!lUcTEE`L-`Uz8tDN#(d;G4mv^`!!zUf?7b4}yA zipw4&p{>$Knu718Wi2dg(X+qsy|nCwwa;dnzADkCOK;!l>(X0Ce1`RN4C^eDZTR)S z^a3^+*4aymi@%=uKFH9!*gun$e^II+I}(lyV-*M__GAjfpjuxv=)Z<57?5E_kb;;j9{Fe6GE2o6J3Msa|v$4|Yi>hF8pe`zHiv?$Y{CPv#LDU2$0ca&yvoT4eaF}WD)eslv4CeVD}Fa z?1^>Co7&;;jAMT(J~)hJ`HD-1+0Hy%?yPINI@@yQ2id(WxdFXRvY@+%;wsu?(H4Bw zo}c>IdK%|{>wga8p?j+hbAY;H}=FtN#}^+H=l; zqpyM^jl+OpHZw2Hgg4{`IJZoCfG^8!7+FSI%}oa7>aH~*-Ser> z=u=s3J#$9D@q0V-&rWkx49~aZBlO+9t=O^>%u%w%Nq2V7y8AWh{5t3GUvSo4(?)l$ z>a2g9bbd_?yyC;s&wm0OK?hzpMskf~JFK(qs>Gxn6y60-FUB_E+72}*`I(z6-9z&# z^U_@SmNhSBo5XDF9J56D+!h08tZeyzYc1oyXsh_||I2Z54KTR#(L=rLF_Aq8U8)Ob zcStWA5ZvmAKZ`HQcB(l4ndk%9eDd5lTC+sg%&lpPp@rR3=_O<25A)_&>v8xnA?N1` z=ZuSr`t#Ri=vnoiRbAQ09$h%s7rm>!E^N|guFI&X@Bb<5l8km?^0l4nLU#D9bp_*a zSRRW*;jDY&vauCd{2&%bXDmzm0u$i>GnFMjvon+>*|{q;lSn^1W&ALBW2dwCQ6+-cX9n5U zcVcx>hji-j-)#L<`hsL-*)uhs6YZ-$->I|oEOpX%KQ`9B!zJ8nTwQ!NZO6uOCi`+1 z2M%PM_O`n|MSkkZo&R&o*5S0-in}A3U-r8*$*}7!*}ubQNIc!8*$%nCZaHe>d);H#Xv6Y|&35d$UUv?r4@Qq_iby$_xyoT_c1rHuc-el~kd znNxnyiO1lUpCcQH%BHVs@E2(BAIGP;vJm^K*XY|8O;t;dPckbIME z!z*X~_EVP1mo1>k>+7gvcw8NEI^bxx4#yW5yX~f&QP zzwuL^TTiw(?X2rL$L$mLy{b>FdOpl)ujkbJdk zYuOe~6BB`P+$oJqE5u(blZ@c{Qs>0Mh#zV!t?Y1MtWzErzh{b}`6*+(#h;&kGA}$i zhGqqD-OhCz*R5Rhxo+W_$2FJBnh)gv+wu;Sz98M>8g4U(2 zKK%^#@vl4OmOA}n+th6P_)qy}(bK1lWm)8uS>w#TF5j`ra`<&3Ij;x#x^ty+S$KzE zO>^+xwnJy1nVh-dA?|{g_!mjU_~?RO*)?)}B0ip(wm+t5PI5YHqj@E}Oe@B44t4&B zF;&hSqVJjqk{MsE=tTNo&wnfZ^`;ebO6l{wflJ)2W81G z^MeoR`()0h8OC^Z&Tnzg)Gq5~v^EZ*|9havlDFJB`#1zV+2A0c^EOhn&eJT0nO|2{hh^Hz3d+ws5dh!@!8Kq=_8%@Ew~hOL%y79gW#`Z ze8-;AHXRAX20$zLnxtob6&`6=R@A3tlgiq%#;)b^z+;(VW- zS_dxZ9WFZGj1+;RZ0dFW5PJR&e_8E|b_!(4vv{`Pq<`b#EP`fS8^}$-8e;B@ zhgH7DF1*?Dp~||*KAQ*IhYN2G>%T!_qz@Kc)FZg$zf=ZZM*phqVfUOWtrP47Pw{?j zlc~FgvzS!3YkzU^^cUOyg74NBEc=UWE^fWW)I0M!`yBXKT$SOw;rcs1D!LbK`o3q; z9(`x|>WLm0~VF5SLu#fm;qG7|!eoe>UMB~_k zOEiq1r1gwH;S#|CjKb-M&>m;VTW7B6jBY>e%QySZt6?6tpU<(L1#cDbmLfyCXU&Mt zb=HhzTl=h;LDpF_ORRIr&FKCQ@Ks@tOu##+S$K#&AAXMLnX{kNrk8-h#Y+IZt^d%n zw-8hQa(L8ac-16$)by3MHUIW6S@98B*R_0XHUoFavEg+ZYo-}?d?SgCIMSlsCNJf)&g7H- zBKA9-bK;+A(@{V9|Cj?V8JJC69@dxoZ!+>S1{kd`(%wg@V*}TEt{SeFYF(S-$@>%h zF}%4HztCLK+Lz(Y;*IoU06os4wR6xR`R1O)L+VOW~ z%-=)*w{dpde0*uOKK|;M;YP)))R6?57qzjCVXAlzyCp+G3s=C z1J0u#L&(44J?`0m;ytl@1Lgr|1o_c#*{a8clSMDi{s7ueT3>Vu{$wfI8vx(#)7@Zg zH96PM9)X)_x6Z>5On0*nfcR#c7dW)+i}e+A=-2~1u8;2k&g;=RJ{B*;m(9SJ&1c0g z93A%K)28v_+M@l?u^Z#F?~TwhF+TfEx6eJg92j!wZ}n{sK8oeJMg*Q<`TARH0jwb$ zK$b6tF6Lo((3wpuNBbXn$D0ye)nx3Q2Tni2ultt6CF4YMzqrKz$lKoT(GQ`!L+DiV zSyOn0y>uI)y=~CmD$ZIhhxXQ)ecSyl<_<9;!+=Bg(a2rG$4Kx|&zRL&P~u088rNp$ zbD)0ne#f|W*N6(!9CEK|2i{w%1l3SP$G_U)~Z?ev; z{cRdMyWsKe8MV?swEj97yakEn*GQe(r{n4X;+bWPn{4{}MfT}vtn6eSX8dp#@9;2Z zh_w{4M{g!`@Z;>`OcnnJe^)XOYurrjj@^wp*oUw9LFP-zslgWKoI}>Q8$RY4SS9zP z8@Fbn2Uv3dcGlaGX(Zn^Afx;E7U*iM)n2p`t=BVmDlVm%TuIe<%2Sk+Ox$ z9Qr$Feb=xnLn@Y%@GIF7nbndfB|rAQ#*9dYOoRiiT|Ci_%TFh#l*hp8(xc1wHTQ@n zBfx3*zb{T5cS$qYPnOiM+9r$!E=t^LhPhk z=Y$zCu%B{%jhPRubt7n^Cvev|aCgEp^dKC=$KLZX9|+gNyNlxpbYku81?FAQWzOW3 zuyCC`40;fc(>dJIQ^9v4o8oz&5#9su{Y&88l#_LSJG{kb0q@brT%ORe_IA>mYgXL4 zV}dg|{|WrE7fYWjhu>*FdGXMy*P^MvI5PK%myRT_wqqL2CANg(!j*z^#mp`qZiI^{ z{}$HT*%Q$@wghW4nm1hE&sW?!62v6bI+NBhE7vey`r zTD~dFrJd3^>kWDEsknG>XB8vqCk~7?&K?6l^Flc^X2}@Xmy?0hg(o{vTxaI+MDWDH za#k^WmO8MwwssemcKbMfqw}1;nAgQPt1{=ieGs?K?Uotudp(-;qqr{Rx`b;amt|{b ze!bK0u5p}(_ReC>yNEI^+QYZsr9F4eyNP&tRvZn-zhCrM=Cm1`UV1U>gk_3tLOmzZ zAM1~?^mma{Pdq;TvFoUX#Q%K#v#q1{bK7y2xc&RP#@fGe{guo0BNz-$^_&SGJJlMy zd#0x0JNeAS_Vpo0HY;YH&Cz~}IKQ1{>J-jPU04&Wk;m`rc#1sn>-?W*pTUa`4D6k< z*7#id?$jT%vG;w({t&!sW2Sp1fHRgw>+S32@Eo7P<*rlae!4a7A31esUws*T^NefS zlrMhrY1XtuZXM2AGxOSeXI#^E>iINl+TV2XZns5=>!fv`58MdJ*}lom;bxIF0u2~XYncd z!#l>>eO#|`?d96T^(xmZTrYE3yaWHZo<5f!$H}zt3CUHT+yDLyJmrtTqVZPmtT``F z;IsEx_GHyL<+^-3cFoyOpQtZBZS1edoifpXtiIfp0MBE{M67BJw?UdUY@AiI9;V%~N zI=^%#xO8d%RPx$(|||%vSmsALaJ+j*oJ{?CghZrH}D5Zcp#{8ONrNpC2uKCc!+d{jb@d!gs3ekTYL9 za_Jf88Or~(^UOcoI-EVPXEo0_^?aIn<|U_|ptE=UZ0DJH*>pAKtm0b9)lLWMcg^L{ zi$y2Msk^$KVtnEco1N5g?n&%k(H|feoN0ViJMAcS`o!i-_V_r!x7hJ9m+~}UxMh|z z=86-@W#4hi44o$ao?fn_=Pu>64&#Muiv@B~@=a`l6QyDh(gs+^UpXRJ8%e>cwF zdv7~!gtjh8&_+LdBxC6+$7_tW_Jt2m5R)>_f3b_xR>O(=%h=eIQ;rS8@n1}awgRXla=GUopQLM{ z=UciK^_-+@VN;0Jwe~sng#Lf5>qi|J>;8YB>wnk9m*ZFG%9ie!`z-c@JKQo)IgUGg zy`^h@k@R_73DYz^53eUvYlWqXr6`>AYiuFo;^m`i(!Y$88(;0rml=f)$5m80Wjkon}fh0B#S zex8(gjQq=V0eEnyHo$jd`TN~Y8-lLi?{8PX7P;k#Bg@};`AG4t%}1EOZJaU|ed6cf z@&nrI$`hxO+fOM|oF#6rcHnaLt;D$P>~Afe)R%mHT>Qd=z7m7qSY7KR-+}~dAx95( zjB9tzPU}qa(bQUqHD&!(I=oN`JX9aFJDTpiOoOUo(ibDiUKmbCQW4lJ3D9VV8RLgE#`;sb~NL@^TOL%&&;~P(SUIZ72c#-9S0+npQmhiN-{O=qg&H$G17@q_x9aNE5q$xEmUcT|Z1c1^=%2 zFPk2%xD98iCnwZn(U;Ud%Uv-fzu6!0@@}pEK;s>FU5y=gdEn$%~O=6kD);Uyf{DlwR5U9-`f2t1 z4b&mJ3ORFWtbX6jH_?V`cRXAD9-mOF%+uPC&!FFL{~R{70_qQPS-69?mV&$XIq6gJ zhR!l;Cp%Xr>j4)!;~KrdpT&Lv;uIG!XZhJbPyCF-4dM~d&Ov;or{E)vPfF{-=9iE7 zMh07^TzTk-WuJJv>b0h;o;Xsx@uef>E8jU{n8ioy@uzC%EiMld&$sP)?L4J}M%i=f z(6nguY^r=K$2vvM4sVD&jPs_|#dHD}BF1fy(-alEe+oH1kRY~gHebm+<56G)%B z^Rhd?e*_=X9536z&eg$|(~ZwrjL$cnG7a_z?j(95inLhh=S?flPzfpP^ypEURx z`lU7Y&?`0G)ke`yF?A-gX>WA#h3ufRV)e_9_-2()St{R^i&SPOnLBR&_@Rq0__p$E zEkXWn-{k!_xNhQ_!!?_07FR;v%s8=l^S^QIFu%<_Yu!q-Va~hd`jN0 zx{Xuw{@A%dIzlRCTKo(>cbfTG`Ps=nb^UJ-<~`iQ7^}HceUr_aybnL87dUf4duf(n z+fsj9zHaa$?R(JPEy*uCbMcu)#>sSKoC4-di?-lJvFXH<&UW5B@lR*oWLye&eupRN z*_}6c;y)u@^>XQlDv6JH!{RB-OpOdn-@e11Vhl|;v10RH-J*u6O`M!sR%ulmtHct?M=wVxGZuieNm^&X|y zIX2{p-9sxl8`(eGn8F+ge(N7ak0w5<_AjE#93IMEKy0^rb2$G&cA4jqd3+1XTh_7f zte~}xxQKyhz+m4jaCH$Jz^nhz&&BW(}=p0a+&Wm1RuS8P4Mwd&~|WfP&@m;bPN z=5hIG)3={EcLN^m_H+3+zVn)Ra(QFzkzLDo9Vz$KAIZ-uYIfr_#m{Md#(Tn{ckWxW zmT{r_gUpRf`7eKF{DX7P2fw8rPdJ{J|E{|2;c;tid*g|ogIg5Ov=8;FjFGgf3^>Yw zVJ9$@0Ye~bW^>t6bFT@W=Pv#FvwqT+uzow`%PVdOunsZ>AF;Vh&waKO{FZypZSfgK ztItP_Ed1rlmX@^mea2SxgYx;I4Sg?LYFKbdPC3!7uw@&xEj+9PwsZ%!DOAy*nd_^TQ$B)!Qp?YuQ*@g_`T1!x21IHjV<2-wtWw^J^UJ% zT~BBKlGt|bR6D@0XjtbiF)yX#GrUzi=GW|5%ZBHxFMUZys}VB8e*-4b1a#Ui7rAXv zI;FXve5LX)pzH+gJZ!QTRdI`ZKd`R4W)6Pyl=r{Tcnz_O>Gv%vpFTdRZSiHPKH)#~ z!mzY?nq@?nCF~=wD249XJt;$6wRa|Z}9$=3ST(Vv*wN-UCdTw-L2(4 zjPOB?bIN-Bx5LsdI9|AqeSP75>Bz%9f=6b-!(QzYT-e0Ez<12mmHB6Y0e?uDmm|H-ZXWadH7;e(uaA)oyBDSsd^G@3o8=H_HqWp^8X2>4os2y_B#0f|H;d7q>OP8kRP|DeDsUHB8`}c#i5R`t`81fZ=Q2 z0euShKJcyoh5T1JKX}X4^E=idRBoR%W3Tep{c>2^@we=L^V4rl%zaZRXA0#=CnyCU zZoj-u+GcRcUSM!5ocC#FuAF)6{*ndXOYTwChA*@J&jmlL+Hs!}ZD#N0EcR!rz8AL) zOX~xU*l#d3=YEguUklTLvy3u)X7`jb`at{Hckx`lKd|5+cve2&=3!}-9^X_SdDsVG z;k=xBRF=w6n$jnSrM*I1;`!s@HTD>2^Lnkh_SkLR*emX1j_@a z{cxS{;Em21E?aU^bQt$+_zbd2ZvFtyB!JI+<*y6Yh|h?}3}o(FLc8Da3~ZLZe)sb~ ze)e0Qk`{X|4&-WVF>x_w`$V%SUvaUgJO3NtO<&{r%SOwX#hyS*J>R<{kAL4|jJ-R{ zH>MJMWxyOgSLJGtw&GvJmiwhnloKlLN`uC4W!wA3s+w?#De zEO*8ERN9Z35I+-hQ;0i&5>n;Tgr%eu)=#zRlu9v?9rJV__;=w zeZ8fh;jb#ghhQ%AM^k^~6y&6X@Zf{z@Z6htNbET~#ytNHy71KQ!8Ork%VevrDjvQ& zV*oVPllkazaNRV**s6VNg5_i4BOC-LQ-Nn*)~@Ot;3)&1xxkZenunWs7aTclQO=Te z)fuKgTGGupJOW-?>-~?GBH*e8uE0p6qOlj}M2rY-t?gxuvEDJBB2x~f)eHq+z$biV z6B9E+K5IM<&v>MES)k>|;3kMpC)#hYXjC-SJNn#l<}JpI#)>;m#FrYGUka?b^oADY zuVo+JEYH_kW^vz%46C_%19iGSI>L*QYS6!fEW8K@nny~!#^FZdUi!>Ix!?B=7`q7D zgz8=A)GK&m>n>og-6zy77*zkgOK)iTU)GA|Q1>$K>uFcLHzT^Aw!Y~-C;Ap;{ew2Y zO8a8#Hqc{42f}|d^ma=-P202(0mq{05^#SI`UrvhDc~M{7u^LfYq9#+m-`@Na!W(E zG2(p@PoS5tOL6i}(-@=nwotal`6pak@OM*N)-$Iy{wx@&gFh^K{@iC5AlH=Lnjg{l zGvE;)Ts;+DHU*wm3~wtU4#pL>{Ok3$%fG_Ub*Jc;C5%(yWXrK`W2F!L^F&*J)g|8X z>t!V^ceiyL^LL(wzdCriaQQmtX8oCWDt8v;HUc}kMe{81D;a3?58ECNa9OlL8p*wq zDU|-pq*s~?`0mOSZXAB>UAfXVB#TWY-Cc$;MrpH1o6?@%mL+os8NEu5dn@XIzo@&> z%a2T|Gfh_UKR|4Nt8`Xcj#0rn$4uE*L(qZfy_7L<9k|mNn#x^q#a<#$Z5R8j6q9ss z^G)BaIgft+Ib-aVte2`+GRAf?#^%${7b-97F(K7My#>^x^ktKS&rTVbbnU?;WAqo4 zhVxbG7$1U3XM&zh**&23bvXc(gv=g58+vffSMOqdejt)s6>X!|T+Lnqs;I4I(qwa}{1^i)aS zEilH7@nLIDLC%+aA1k-pZ4Fs%U2(i^^as$x-3M6z<5It#DW=q0?AehO zy_wO0J%ejL@ODM!Pm10!{LdM(8-2`ttiI5=yUa+b5)bv#N(onzo**RkKYzTc#+2f$$ndr)82V`KwG>ZJ)RAZhvauD&_HTCcAXUOuj$NckS&(Fx<3uHgY03+@5NrsjPa{RcM44 zaaX*mj|^iA^5iCedSUAr=Hqg{^-K4(jyb+=CozV=`dIK7v{mp(22y_MHkBUeiuOwX`5`u^2=8C-YV7?1dFvM4jZ8#dY*23O zj1%1^wdK>e1TA?95X@5HzEEgFq}ofwv1QpYn~TevoJNk$hAeFf9= zthj~n7mbM%S8t05_jk@8mR8y|xb-`f4Q=I}xVl3hw$k+sv{<;FZueCII_@_G2jf}g z$`ZeYr%fzrI?>^ zF`c^83a`n#-7rQK9IM|c`@nm^7Cct6Ghn1y^G3n3^qt|hw$b{gc8GtRxD>q?eKp@| zdvL7UaN<(dEDF-|V&gmsr=_nPOl#keS~-K6(!y?t`sgpon>)=O5^O}I8` zz_gjq)lK-xpo^#Zk6p3vCd%0}=#pv4$1dOZ&q1T66%KlOTI%u1`?3Z-*(1liZOs&O z(VEAoKjppq_etJ)YtW`?R~g^@ua)Mv*W_}aXMSr<4s%z)xammx@k#qk?0xG=FPW*w z@vHU`lP{Wb{Hyy?k6*v9n0GIZA26*ac7O}JOn+(!Fpc!wME+IP0rS=)Sw`ua3%h*z zslDbmpPpqFJ$)hXr<>QVNj_GvubjHF25smu(OkGD`MKNo9Z3J$(?iVpYbKeK*Nots zr(pWi517SICs%xZ-<3vs^j0%1`UN8?dW(@7P1$wlzC&jB=u5!4lDpyg>X-|=j(dHz zdCgPXx_|Y^FOJ{0Z>7okv&Zk>x7xhwsW#I%tpD4%uQsoI>ZSCR)os``SD90vdSc1S z>K@eB{n+$(u*U&0l{&@ z;f(#0)7N*TKXx|hGh1B#Lisx>ziQ-tJ$Ig_{EqbSBP;!}j`ZS1$M5}30pS+bAQc zWvu?MA8PJB%)5}+7+vfAdJA#wH_v7sdy{XHCuBc3z&s@TV<3|~H`uiT*d$EkH|5_j z(cDX#UiVQ(t@mp!f=_)U8-!y2r6PYPf~E8nFxos=YZP4~pTLKY-rNlxBW9gqqKWKc zVxPuW1Y51<$V;jFV#*5)_rCstH!Vsmlf%rhz}Gvvg>N;f#;9M;Ho~Leoq9KJ_+_vE zg7?sr_5M%DJlB&y13LU)?qA_j>^`Oa3F-dW)kwc#sF7ZpY>Wz}wv62{NAgf_*;aae ziSG?V?f>g|4y72Q_tSoTH~Bt>cfP5MTAGl_wAR3S*i7jy*_<^VL8pl#4+zg2!1)1W zlsCyIJJ>Amk1|}GH%NabZ4+r^FE8L6^P#}^Rr3AWf!CHFdPf&J@EYh9ncX_W+B*i; zyLis*YK#^vMfCaUV9E0SupO2q^m{BUinrLCxD)}#`K+%Vy#3BgE^pny{8yMZ%3kky zdsw*i`J`}VJvJcjcQhDlm-8$d?L`{`gE$+TIddI-R!5&b!(6R-4xCqH-!tO%^~BZ@ zE_rY9giYLS-viNP;EzGd(K^g0%+KyR%+Z^ri%#ye7IV^g^7d*UPic&&Imn>cG`Gak z@7LimqJx|0quBT8Hf!BBZ=Y_r`FZ>k3&&@w&70;t@g=LxQ)#E#JeoFN$+Jb<%WT?i zg|=Htx*=owum}2yX=Df5cP zk$nyQ$-z&53qShy0q-P#dfi( zGU4;_^?z`6airDi+amaY)33`q*4S*EDvod$3x{gkbHagTdod~ub6vGX3#@N$gQtoQ zCdy;cm9@^7IFIIs+2GpFYfvA2d7>TvN8@}vb=H&LiZ!*&Xs=88_S3IQGlTs4ud!0P z%S;n2`Y)L|Z31>DeCAZX_`YkKXfzc=CB@R6n$m}*d4@pml&87CH*87mCH2PIB}PEOxAJGmF@yrR88u4L`lH76U+&TCAz?637R@n$nu zzGI>dY$anVp)u)w4c@-Q)v@2(<2aC8X6Xhe`<2&>T-GbzC%C=;y!JTyka6_E)!nSV zSN*nsZ|C}<@iApq{lZOOTNh8aVc6Ey7@39crtdBv_YJqdb>s=;`bIl2V@H*~;(pT{ z;I>EaWM{SBQT`CquwuLl2R06`hZ%Tp=8CPB-ESrdZ z9-C}y5BBvoXTlF^8=k}% z7#$3@jJcTD!YA6c@P3o=Y-;#Ryytljt4QI?cowZlh6rk0bv3rknH|h~-P5;fXD?)y zIhtSXc;;`yPq68>&gh12NE)5X82{aioo))>%YPTl6OYWtR$q*L20J{mO5f;tKJtDu znD=Y(3~YPYb~#%a8I|wK8(Y^n%0W)uJcso0_52z*F6KLYE}H4A2mFdM^*`bnuv;7;LG$#0ZaJ4Zz>l#+qy(`fc71NatLtdk6QTjEY&rVD3*G7p>W74Wq$Cs?j2y`~B4exU$0|eLgRIq*zG&n%dhkDK zGArnxnNw|gdeAsFCVZ9X$${~4;EPS0rFg#1x5xOVc~$nv1_6`5#>Ear9^3USDl-p5!LkMqT|?^QxyXG~;dRZ}8fB z+kWO8+4Ab3hqj46{EP}IOY+Z-cD`ITBZ!|*Z%fWGV`PBY7ZtFl#)!_rmU+`p{o$W@ z?D?awBfBp_f7W+%jzcYRjqWwqyd@taeDxmET@|CVOiP zV`HXaZWNx3%DM@Rs|g-s#zx=81+C`Fx(V5&8N&B0;_bS)G@#?!6vrR;vEn>y+*$au z*SjP~#I{dx#jeNL{r=yPW5^Bd@maxR+m4LA${VQl=OM4=stikJb!0!qLtX9(u9^E& z`c5`=!@s-vQPYxhgO{0UqgbPFnBxgI{sRBR>x|a-=$}mHtHylhQ|wIpNo&ixeWC|| ziFJv!>^m4MzEt<@(6mO<`-ng2R}8`@uV~HLaz(2LUf^RNp>*i|%wx%2SUtm-@p=XAsy+S!3vfsND822AA!Ut%ZWCrAp+^1P9G?LI6fzzU+9ibUF zkX~sUNV}i3Z}IH_vdRPSxTm3k5OPr?GGJ40@!J>1FFwy~Ez2-l8y_bY$Y8V8Us^Mx zY>3%fKEt!M@n;hwr7J=c7GFY|i+J}H&(@1*gJ7$9a%kGms7tgYJjC`gbc$%kiQpuWu zW&01=?`FaOM01tMVis)u%vRa2@9G7dQGZ^kr`N{P)u9QRNAD-&R&*XlH`&YRi=6)mh54o3eZ{>ay_v75lxSIv7DYtOP_bKIe z?tbofaqrH30rzz7_i^vbJ;Z$=_XjvX=G=l-|6~5V91IOH<24pmf71T zUa+?jd0gw7wk?74Uyvmq9qQTJfJ`PD{@B|kSF~bieY~6OAL;G1{4?lhJ?S@){w>~1 z4wil{S~j5Ndi1IW=e=b07M|C6<#%sHA4cb^-EqS>@u)25rR>|Rak73GKn~oX`PHBK zXCG^X`Y$^`{W94Ndq>5KTY0{Zx^oVA!`Y8|!*dIh!i}5@ljBVaXYcUxY(&cTd&4reUfEwzTv6tCBCXAd^LQ>zy45WdD*e-o*B$Z>Bny9W`qY! zG{W}|#jkIfd01yg_`JcbJK97K~V!)wJ88^TEbZ6y>w0Fp^6~SV`!6` zcNSw-eI3I#$waac8SC3rl(p@cUqJRHi+65i^8hprqbrWj5|1}=p zrDuKgX9H;;U1sc68->@Av<(=?$_7`1zg8(Ue;vA2?bA1mJB)tx9%$xKcKhx zJ<5_5FCm|7jDr|2m-6i9F`sCcyEYZt^5uhb9Qks%lcy(n&Wp)2D;kr>metzx3~=&z z$TN^bUyh<7-uxXEf{P z4jjbf1`fXs$7CB0`4Hx`!|`G}98dHzs!FJr@9EviC%-`9Z6h#z4;w%!zGW|76xxa| zUi~U`KR+Yb8e)uSeqK)O*P4YjMdRPtMUG0{ztBL$}BrCxK;eNAQ#!? zNKxKS@|14~MwCbLNaYblz2H{X^8&j{bwb6ZYQ$r##`^muqY`vuqomaDS9GECBa6c!RCN z|6iT7;Cg|DYxbIIOyqHXkm&Ufaj;zkETLY;)>q=*XY*d;W&fa#{>X=4FX0TSa{455 zVg2}mxIE`Ld7j6&`AmIi^(T7`SX=1ShslBm97dh@>lhE(`*v4cI)ikveSHjDy!yKE zT;@gKE)3YXJvANuYJ3D5!v3v&Gh0_XuquQcRBez{Z7HFz^{1bznfPTgCF+xJ+d4a zE5Xy`I5_E>vu>xxEMsm)GG+NG%N_TtDWjHe$PiT;Qy0Y5@qhTPezx$5Jm%(uPp*v} zJE!D*_xT@LLA|ndWzlat;Yq&xGpz9-e_yveWU#fhGrrh~m*$E-;EUp;;zPmf;iZ%} zC8izXYigV3(dU2LHZz~I^Sr-f4H}TXjz(ma8rkn}=@;(T@qd#M8Wr}9yu5Y2 z4}EicQux}AZ+nbP``Z%d+m*53S}wEJ1e|giLSL}TQ5g-S*SK`PJ!m{g>^bfn*84CrTl&*EHJm1XbyadFbu`qtpoqjm50cKv6X<@2Wh7EHtPt+Xm5i}rNu zNc*7ihcC8&Gx;_I+%Nqz@+x@+o8YSEzic$jn`hK*h$&^ump3%szSds1-&APZaUY!X z*!kfQa%DB`)cpak9qy6^Q?06+(Vw#F?nWPcj`PLC(m5+EQ!gp{mZA$bElK% z>*TqM=Mv4o*gB*~yp7DA?P(ceo1^t+L zy9oPhd|v54$S*UCQi**P2U`N0>n6$5Sy#5p@efM&Uk3fUvj2JDN%}$>I6I%`_%h1D zpKJ#C$WKq8V`(nP1ULEUs>nDq^O-Bwb4F4*@S_K}#IGZ2tvet6Qg~JS^3gFfRnEE0 zG3aEaThVE zMtuYg)F>@^8q`r$WAi7wQqq*tFNN+)_r^j>|I4bJfCUZZ|Xltwg>@I5q; z=skL!)wcx`VsybDj<@?ZGhpe0zxW@!Z+}F;ZsOU^v;MME)58WQ&r0$<%Ck)mo!9lt zQjK1h%9cytUnTqvH!9>uqJ0ka==|E}Pyu#5^{`QTHj%07p^XM; z>jSShS2ii=daZm-u#e_e4mNuE*gK%K7gFX3yWcA6@pVzXCUQa}`m(`VX10M%hkY1s z`i<0ye~Y!}p;T}I-;zE`Z_B{)&u`{hY^O9!&oAZ;B;YmkZL;2i36_w%(U5LhWJC#7W=5n`}Y$_t44T z>4O9A_sOA?@Uaqqn@aqsgv<57WEj1xb{ONvCi11wSWEQYrJe0LF|@@~jL z4(%N0-iJ#%SG~p!<6k~&ZW-&(Z!cq0;i%De8GpLWqFIkq#@pPzDg!=aGJf5>+lP0~ zYuP?BFShc&|3{nN|36S=rU9 z=g&@_9pw2-OrD0!lkz+`C&?a*FFARhA&+)w3PhVkAY!1?= z+GE@Zf1QeqT#7wmH~ov;c@i%xA$=XRIigEl-rRvkFJn-0G#7pK@e^%h^sOG-;RwI; zZ5-dwrFI{;zZv@0-T5|?Z|q%eK4yQ*q<=@GJKt{S8~SdF^DRjKjp*xqTgf-#N00c# z&ZqG?VxaS_mT%~zQ;*u;LeS2LbDeL$(aGy|fUs>8}VFe-Xcy-Huovt;c20{tHtt(S~b ztmppG5YLO5%gaWwelcx?C4Uv;r;iP;>Tw4rMd`toVrX%@1E2a&HluW>-&|W@Gq%9R z;HwV%m*yYW7HH2uwk=Te&j`m3L2yuq zO-b(#g0E7Z@jJHgC0lqoc9Y~)>VJQ86TTC!P3fd>-(8pS52qcm-==ooRb3wOKk`O` zZ&sP?QTvngttdUTpco!|IcS~B_cM;mLySZ(1HvUDT0ol6Mr?GWe<&9mJ@mnW< zXFFD(=2F`1&flUpcm6)D9m~R>WyiAi#g;Q3#wVy7oAipGo~n%xugh51(Z*+s;dhe~ zq@|1(zwf*+1Mfv|wmrjKZ1qJ^mr!0>%(n~&2A5_YIKdhmu=VYrEvuf~_WZ%TVtDs? z&i{L%wd9Vp7TzTX38$*t8v9=Bd{PU~rQSEj>wW36b=(6jpP;|T zq$yqY#&{!W+^W2XoOeaoKLt-&Papf+g01S`x14XPr_q}oEu;R1MD<|*mXFp+^$*`w zJvq^P#$3MhzKA+SKdPe`7^IV=GAHIE?-J z=?;>v9^NZF1n{j=8Kt`^1Ai;=SVPb9sp?ICr3KfNvCelbZBbg4V+elI9wcoI{MbrM zA19M`Zja=uDW>S$&wfK+)#c=)&+~-KN%r$rJs0qNH+?8y__iIXXS9pBazVr1M%PE{ zLD@xOW#5^9uw~CLy-q9*p4~hJdrqC_3MbD<@)X77S^tWi$C5wndiKcvB0c?!PM%@p zxy;V41~ZPrl5! zd`otnlyA?R0ofLe=}x{+xc7?7xBd5>^I7scwluZP>*PDcJ&DVOG3$4o^H_LaYs=Li z?X&S-Px_B}cJnOxZF`>g9GgcwKAN07`^a-JCQrljr_S?NC(rN5^EaMtS^P9I+_H?l z$ZWZi+2kuNpNgTZ8PD!f5P6Gr<51UN>pxhdl%MRR;OMGR@}KY-V`ujYw&Fv#S>NYi zw|$eeZ#n6HOqx34KiuO%_omN{HAB*#0v`OD9`tj$eoX=9^&!aIZC#Bg*E2>mCS5+s7Xz65Fo=-FVvN1+}xC?1FvF5-TK6ILg^5gfC1Nd?vdR zpU4RJy*Rk=LwxOu*l&yvnH3X2^evyALin=kQEY-%#gn;iGQPr-@SQ2_v?p_UGBJZ` zlh){2`#zl0V1$Fv+X(#67c*arCP%PFKhNw}6);np5Af}RzQNX2CNUSx?#;9LUq+w% z@m(7j{m&V{^!Td=phx^@^%Hlbj5H!$D3`O?ufd;rZ|#?iUS*%OjjE(h;k9wdvyb?x zC!hF($RIQQ)Ki*EEI`VaA72)AdQ7vbAj^aA0knF&+n7e?iE`>oMrRQ|vvbUd{9x?y ze{%d$Y+2EXhPhjN5*Mc$hs(fAiP5{cl<|nI{J|w!J6LdDSoU@GyKLz%yk@M;0`4;T ztAhji!j$1lcXx6yZ%)@>p7t|nZ-Mp#mh}i)dls}0tP;QS0iU!zyzPXyBILmjj5*fc zgV5jc^XZ$bJUvO%oARCd_hkL4w^P3_S9>`H!(+gp`)X*-?#IM2H)VI#e!tKLBO-jr zhwtMAK71XtWa5wJ!5_^FJ;cz{L?ev+e7MZ;RDH#Gpn7qV@#Hz_>;9scL~nS`X&!?7 z_8~Di-p5DeW7?{{BpM^48+}(g54JnW9Y?ver$N5<$b2K0Fm8$`23v|Qwf6(;BK8A3 zZ>#n?AnT1X&E(x}9N5WePOd{_Hmi(U&T>W50=A|9?_0wvWw^l0LrP7T{XT_fpE2Jn4={cPt*g z8Gp;$9RK|t9sc_tQ}0es#_oH*XOKIc3DwqxVV^zVtKFjEPiyIyOb;%4R@{a%ISeD zZbtlChT%E+T|K-|d`C8scKK;hyDYS)aHqAGxJYOOQu>J|jKw9n)Id60a^kdN3{f`r2nRk>jz;BS=lUfi->Qfl$I%s0VH*8WQ`GU!j)KQm5dW^p!((B6NNS~QgBK>Zh z8X0iYm642Fu8Iu0Yg%M*2tT2uYvy}WXUtFPbM5@DgJ#b64g2!^io1x*U#^D3H?emCAYf51&&pPzBdf6O0rSIPXrM#1qwQo-@G`&3Ra67U#d z_O-sIedf~*W6R)sQeGFVg3m}YBA!$e7(Kw~1;!*`>;jBkfw5a8ZITZ-{lJ+FoGHMW z3Y^`6vqxm`0(4}r5jOGr9UNj_Pf7>oUclTNnEL>8UtsPB%>99R05A^(<_usy2bc!| z^SQu07?=aVYyz`++yG9&CR~e;nb3`%1BRzL-|!wq=CsyF-o#hDiE)gK6%7qD*wf&P zD&I2Rm#5YJWdxUOSh;4(yh+g9mBhO^iH+ z&B@(GOp3?Nl$5uLt#rtn#on*f$1gCuSFbY*j`)th^w3r5>#8r}%I)&vLx$14S#fx? zj2?fP2QQxkO<`Br90H$$$%Q8$xIO5n#lYhOhN+pmst;1vh1`9^U#!06c=G$|DCUWBPL)d68e*^IqfRy@tFsF?pX@(la{s$&^O~dpWj@q9wkn zN$g*I1>UNCdRe~btJMa@4N)83rVWC3%J7%k+u*{TUE_Jghn<9Yg;BNV|3y38HvIPe zw$18`<@Xs8m#z-Az57~&ciYCMp~Urpccr!l*R*;4&D+e>qdTCL<`KcjH0xao?|K{^ z%DegK>WXzDTDbt-p~UnZoC+=Ktiphqd=x@uy(-kJjd?}&XijsV7o+Ep{^$z$ZEPCl zHOwhT>#>u#X+`UeE_@>jB7&>w3(wb10Up&emwPj|P`%gx(&6he+;$b37msCpjLL3V zyswEkVF$fKa{a@0Rc8%*zS@T`B)$RG7|G zeCh$#8S^RgannC_@piLfm79iiUm#6S_M5CWr$42%(;46InkiEix8@!17jnZ{uU5Cg zJ9?b=O7(P}zsDJ?Q-<%ZUdeTlr$@9$uhrG>^?r~TH~x7|-VwRod8fFNj|~hSJwzWb zCa>cC9PGWadU^Wt>Z#x+6};pSyJiY)KqfrA7#f@dOpMudt%J-1XY3t~mNV{)!5QsL zDF#1NO+RhKzn*gErmx8GF|K{4*~|BJf3D63G|ck{w@tKZ(T$^(J$p!+@Awn?gw9o8PTG{e$iX5H8{J&?_Fkn5|=4Td)i{8qW<=BA5F3%%jV&j0O;8ZRzg>J1k- z|JNVk|MT9k%9hWnTecDOgdf1Ska*JJrMf?FgjaAE%t{;P{4Bv+JKb*QPGaDnAU2rZ z8N3@sTNMKg*<(~Tdam9FuO4ExaXA)PzrS1SeY8pK(YMBFCzliC-H-(3gsyVRxs7tV zcWa#+Q%*MDg!fo@LRSt+OG{8r-BhQX`IOVQTkBV2$|>Vpd^vSf=!>N%x69zY+OYf% z${ECk{;klV2oRDVNdlt+v~ zbd%oEUi_apf_FFDwzm35WmD=M-2lxWC<(S6J0IHTU5zycyy05zjYH9qh|>y=H)WOe z4L3e&?+slFj!USIHti{F9BH@dCfekD-=Q|q_B%);99jB*=7ezL96SGP+IuzM(EVH2 zC);~SeczvmKYRWk75DZ{>eZe-yS>`G(>MCjaHl;(?e_c~_e`Q!E*j5OJD6fgJ%{98}Z z&S!EvcpY+YtNf0>`U-rGwz_;)<(we4*6*{y#R~-%F0QBE=@!n!2MZ!EWE*|lbk8Z> zcWj(pO}fit()~In-P209&@OK>>88Y_dy;e~Qnp170FTDBIon8kbEpmbG}4KuT5~{5 zng;lwo94EdG{=eQd4iapqo|{8V%lECJyHB1XfC%Nd?1(PdP0ih@5P>Cgg4WEy?@J_ z7B+cr?*r{^**LyUxovZ^#xZ6XXZ>ne zR&c_JVI*CTyB@@Yx z(YOrwx$tplO$VR#jEN@x*RHsnc*=e&t@4DJ-<76jMc38~$yW(&E1zsTA99~Y-Vk-% z#CXtn{*bhl*g1xfR`~^w54)z;>nA$(Tu)lTwU%@$yFY2|G)DM~PMYbYQMrO$^{K9Z zI`4{AmlwML`Gs%Qsq#mVSMT+149_aRo_xAK z7iUd8yErQWXBMssM~7!2!>GSE52Ji=HmlGRev;=|o+~y67-QQXJeW4S$K@L(>+FZ8 zE%796T-w9CF%6zt1D++n)X-*+|BBXD^11TN67m_tyR|Bxr)y|NQcQY+$gcHtzoPX} zOnTL0Txh3%9{$PHSmhoS7PeU`W|(Uw(H&xtbdM4U#|4$UeWrzlirxn4S&C4;-(f^ z_9%^M#@>U5kr)0=2%8=D^N?&WAN04z;CU}YOVDXHckHpb*0*6}t#1M6TNZc0oSi%* z&2RKc@qfqrtaQasC{Hm)Y`N2np16>*n0Lj4=fR`fcEE%2Yf_8`Kfb)<=ws&9O@%*1 zreU1e{-XY<=Az%iR~oQeZl}*Q&eiAc99EiakG210U0=S8nggKYK5gEvdyhX3&%dr8 zGFAUb<3uyOi`XSOSv|u|BiIwOU2%}jXw$VkFEPU}@=fPZG+t)3`U*VZCgd_J{gPhc zraOrlg!}^zqVOk6Hm_`JoZfhTy0s=#dtKAT<@Ec(iAJkc&a8CyDfhCz`35&$yo+zb z(X4IAap(88^L)SYVn1aHCynR#iC`ZH523#gehvF1ZBhCm_5ZwG_s71}G`)fEN;`+L zCUfBrVaYl0DfqqpP4lGY=my?R(KGjlRQl zFZj@YaOI~z6vOMopBWL!3i`I6@-&ux>GoWxcWsQ{_qj5GY0zl9jHCS5I*alNe$Rh4 zPS-uD<)61Jt>mO{aE)?coGsb_j%)Rwwv++0_U7&*j`asuUl%$4c#wYl3VM83OGa?# z<^NGV1$JA?f$LUy!~aLyyT?aaUHkvfGYRm_43}I91SJWG&J13;=Tr_8s2UQ~64F}j zg&?iwqSoN0fFJ?1CIl}dQI4S%&{{L2)O#hTwFa#%i0u(jPA})w1WlGf!P_7u=bAVl5rTeDKy=+b+X8 z;2RL_!7keK(HSS#eewQ0XtNbtyS2q>2mLG}yoRWQwjz=hfX9Ign%<9mBAS*S$C}zx zKD3~_7F}ERa)+kV6KBFtT6o9z!~$?Q64*tz%!%09y0j4+D=!{{?3`GEh4359Ynb{~F5qz6Bnce^Dc6ujamqY*qQLY*WMl zNTL6%Ia*i6yDZxCY5hayy`1`#|DWZ%=wHnDB{!dF#^yop^Z2#Dh|gh6CCeZ?-vOm{UxwxB{hOrThMH6{31q%C6Q=3sZ2YHs|a?gv{( zImtuPDI}9uzoB&{CozL__Vkk&)8*YemWH~q4aWWkzrvU1KI`=1G4|L$+`crwJCu4! zkNA!DZnPKhPUSRo-x+&tI^f-D?<(ecdSn=IAHVijwjOU$_I3U%|MNVPsG}P>O5e-C zy}nzUFR|~N3qc3Y|NL0;IL@gi*Ky|Am?GLsuJ}%OjXPGKTc#~Pmej9IQpLhpu z_BBuUvoE-XZ%gUlwdy;2gWq7zVaG;3_t`dQi@7rcn#x6v@nHES?G{qkBRp?LCRc1h zuifMGPu|Dn2TskQBdjIi=?=`Bh^a1G_H-ocB8SK5ovjbwINj!D*2t5*C-in+ipE{* zZ5DVhBnHdA;}_d=PWsik^hM>R`(`jlEar#-ezwvl(ZAwJ{2EwAKmX42`21I!LcG`f zjPA}$`SAAM^)<(OC#ep5{W|}`7lI!izTZ6b^jw;IZ+U+>_;usbudU`FoR+cOAdY=$X$LSiddkSqALK zZ;SRUX6*ji7<|hegM!Z+1J?#+T1Gq%+Qb(6d`NIHCpE72`tg{<3(>t23t4|p=v6Mw zRD2H2{F*&M(M&GiKA_z{3YXB#@8EYHt$pKj%58ParSa_@%Dmy0YoVM+Q@i;l`o3Mf zk#UTUZswEbDKzp|=4tP&0qpZ;*s@4%ijmTL7xVT}U)+%=h^^df#`mE=?q^T8l{hL! zfqW7MB>XO3rN?XET=6=N-Bt>%SoPHDu7mK7KKuWQX?v8qWYhWtI+|}8hcvgbRhBMb zuH^kR@D;s*!u7eFtu?-5*$PshqJ(eR9X?%WF+Jt3VLV*b89rZa`|DRU|+ zrg?E6BtLu=IYMV}@@lL^D{Tu8z}lcVefwzZ-gNjM=`s3Fe$L)EC{Ev>_@=z~@%>Ny z54qnB^V)}BvWO+kyWQl$Z>V7p>Hi{qE9o~$tDfHs;Jk>N#($&Xb<$oNgVEEOLnmNL z<@+nj3w(Kok!JG$m;CqIWS^V;JnjMr8V$^$tX$))(Q4!8w4u9?r$S4fO&I^LhBD6o zdh^)&G5ekDw=7_NG@=IAw>#^9;OuDJKLVK|w;+Bg=fP)c4E=NQ`-X7`IT zrg4srdLuWFo)>2SBs|1eM0|wi8eo#Xkb7mDeKuX?W*Gh|aAm)bAist)1NFI_YYwMI zo7oqiu5!vJf2ZT4PW5$ieD<7s1z$|-yfMQt>$f5UjQII^oWmHNc-e>FzRtOG?^Vvn zW_47)v>y=HhxQ)9@8~Y(+fNv8RKMCd`{(uLzW#k-eyT6XW_Di!Rek!B9&Ofq*PH;4 zHjIjucE8sqa}*w!uQnEt9-eH(en{T7U_pFq8ux&c-Z!iu{&VR5HTyk2=)BjQ0L~t4 zCk={C)EbN)`|}{9;TP_E;-)k-D^2^ONdHV}@Yu9; zq}A4V=4wLufkES-y(P7!wAN(%{eEmb;$zCE@#23r{~g%L%l|R_S8O8L31o{KPM_sV zcN`nA=fC6evKna7_{x;nIn3kVz{mOjwDGGcu`vJ3q^qwD#m*!>OFZ7Vuf&hM-ac$J zTLJjsuPA#~Y%$v)2=6{>Wz_p!(tGZ41R8 zHGY0j18?TOxZYkP-U$s!=24&C9;>zb^zNf>Oh$CqYVlty*qJi1bmdj}%toYJSNMzx z;nbF^!l_1yb!A0&cv;Ro%S^A&TUlG5$==*>@Ma*7+{*ohP3R|9hA|CWegvA2%;g(= zEaO4GX+7P{_tU|NBfC3!#*s(u=-tjS^lQ+pZt;cV?)^2H#4PgSYj5_MoH?+%n1iK3 z=G864klF0Zz%SA4x|(;gS0YI7+%`Su{HX%naU+GsyWR%;l)=|>)op&FTmh8Uyl}Yt_|1L17of@9U ziB;J)=A>+7;lIiM2K6Nl-11>MOg@cGIlhuv^v#pM3zLnxYX&>EitxbBlo|J#)nnno zZwwjcZpH@;61}KL@T5dY9G;;du~nRj^j;T_rfJhnJSSIzn+pc$x>N zvu;TiH4{%$Mlzm*Q+FS=53Qlk+i?&#`qH~J|ksp8~cV7MMCU>$ zW2?JLO+Vx7tmCq;wKK-r7aHP@@%I@=Z;XFP8wc3)DJGxA_*}uaYQ|GAYV7olHSWZ? ztQ0+C$2baq>0Rxt1y7N$Eh!lsCqu{1ofU$IGsf#%=${jVP%%?8A{S7X*2&hhv}QQ_ zn|l8-|3!~BKO_AN?Rd1%K>b=n;N=+}PS;^Cx*0z8@iKT-$T&2^$oX_E@(A&Iy1>z= zKGOL9+v$CbZz!c@U6}ija$fTvnqlUAx{!CieRpu*1o7OC_O8Dv%}9klvThn`%oX3d zDPYW%%zG2`0xnLBflXW3s2&AJ4t%VCcAuTTYafny-0SyJ?mt{U`pKUhI(yld^Xa3s z`(^sJif?NB59G_Dee2B;8#G_`((Vy(*S@qI8p~g-IO3u`yDa>1JNY}7-nlzDE zYa9LG*E*+YPaS#i&9QYX?tI-EHlp|Et+W#2IkNL=zgM)lzy~bIA@lRJX7<-FeTgZb zmF?+V&HcE=C4^9Q{Pr#L* zy_lk9=DhjDlAdiC6Zh%P;Nv;d3eg)>m;d70lEB4lOJ-AEbw#KvY_7?E2>QUkDY(~H zmwg6x-O2xX{5<`(h<7>{+X-J&J3-o+vpi|ud}6E=`;CdLNwLnP!I3W73ei@%ubeww zjYF34gOUJw3xR#j(3<98t^@OYWHI9Q1-JWZvuCgl?|rs5TXL=TeX#dLeBk0!&Jzj` zuR>oT{C;GsXZ~`YAR{pyJiP@yT*_0lt8x7q`ILV9+eX?0#G*KZ|1aEb&3l{s0!}Bb z^=Gu(r~hU=Eqwl?iOuV@}mpn@MuUmZJEykmXJ3WS9bon0H zO{B{=A$RQqXSLKJ9GyWYSmr-B@Bh(3bb@n%q<6V(IAOkAmR^`n&-6egzzy{n_;bveypv z6}fk;%E<=l${?(}5shWrO$O~6J<`+Kpy!dm`T#L!SSKUW&0byuJ>UcQ^21IHTFW#7 zP278F=VyINXZ%Ii?Kf#oIJ&Cej6VBuy3yQzmJwGS4v%%}ALP=DC&xsf@f^;yt^x-k zXb@Q|P59H<@=SRY;_Do$}VNy!8S#54S6I~p+ zcH<(`zWZY16wdN8h8yVL-K*!j+ z?3@A7s`ezFlxrPZYumm87h3bg*L4@Yb)k_qm>5Shh*`7=S>~K%fBjE6+dSVKS|vGW z3+LXiH;2@ljMEBpNY^Xi^M>-OY535`-Z2MP>0F)U7_9|eNkb(2W>I$}*QGnf@(4qB z^UVQWSCe;bdFQnH(~Yzz(VdGZv$njFJLgAC>|z~ZZK&crbtycpMBhY*efiTbMjH(g zXh8H(K%KMT1)}NI(8TZfMJg(%y-`Du zGu(PtQr|h$Th8-(%542d^>UW(D!#w^1@+#i_xuE}$^Ls5^|n**6_k18AJsdCm=Ap4 za!S3Uxu4gx{WY~#ia%-3@9VE&r{VmjExWsWYJK~*>vV^wZ|4a=vHAD`H!U6uuQ|cT zH}`4p9r6fQ_j0DaFE3~TPj9o%I&(5J@(yLR-af#3SgADMm+;d({^RJ+<*hdC@YYG< ztsEo~Z=DNooh*K#a&J)Xi`J+gx&86hsE+S-q&(TDZ(F{gZ-UJm`zE(V z-!<3U>yf^k$9QETui9%8d-G1e(<6^^whqTB>U8!oZ8`CC&LfUuE?OTxg?}72r`wFQ zTUX@FlO4K?`DEng+IDj3KC;Q-9tv@xhRT39 z+I9xv8WMY%CpCQl2t1Y~~pSseS>_Tk1f<*i};;NIm_oq6+YOv}OL4=9sG{kQQHuD(IJ4#vr@ zA9&PWa_Yuxugq9rI18BUwa^`x&FDJQsVn5xq4g&Iijj&g6Wif4^5=7}Q~bI+OA=4s zSyJ>&U3Lfiy))LC)sb<=;$ryP<~VD66(Kwi*NBU$`%1z0o|_|2H#Ucv{*0{(&vK z_kkDfU9?fQ&`M3q$%|I6ByGXx_i4SJ$2~~e<9|0RhVF4+I6O91i5<1*g;d5d!;v`) zro@o(8!OB;jnZQ*&KV$&az7DqHwV-;w#{S^Hxt)HVMxT$f50<34H4FLUS~ETx z+V(?dp(R=Krd(;HH8HoWD}8f^b06tmpMOFUcz7_ym{glqlNQfyEa|Mcza$8Zb*vdh zNt+glNBW7k{MOQ(d6SoCq*u(XD;8~4ZSF`(Bm$!=0$G*F#d~i)#kIx##dDW^h(0jhmm@Il^ zELd->%1ylEJoVg%7&paTYJxWK6P_!0;BApi>a~_x=si;c$VrhV_S3_6)|UkN$-dGt zck80AxtkUpyxl*FxEsc#O=2>}B!I`$#XBF#QOSqt+BywR*Nf*8^VRO@>HN7t{ z^3z7-!MjTmpS`?j^772|imy7j4n7F3Z+CEg_JY~k|={~Ot7 ze|PpyorN2+Bq!}<^xw4u)@EPk4+MX^BxfGyp{iDa(@w@V=WgQy?wu~S_p>;g5?*f3 zTfqL%lv{GrG|xU}jh0L-d=Bn|&x7ET7*dfUa3y>e`PZb+r(O@AMJ_%g;8QWW9ef7B zXMJ|&xY}&l33R8Iu@ZlB_g=5#*CNy5VcIojMJl%<7r!&m{k0=2GeY^O5(*^PCxt)Ju=|{x5-d zJir)9HtD^@X#SA@_wfJt_-M~#%$<&;Kye4}_aQ&7L2pVJ-BahA{;EpmFW(}ae2bXA z$QtHS1e)(mGI0SiGS;Av6;B>AuZ#bcM)_2I^YOlj=WDca8*RLA_sQ}5w)s<*5jziB z*81B@Izwv_w$)2cm;QBHH?irY^PoSNiA}(vHD&>0U%-3K-N#SU_l#m}i1uE_3v)VB zUZu|uGH*6MGOT)iU~hIib9XCtnbp8=CZYRK#|4x(2RZ3;)yD4Oqn^JQJ3ik&Vm_~A z{XNvvyM86H0Q7DgdBpoZp}pg-ANCim!#^K&s;(HH*pc!&@7n0&E$B@<-E@B$qt>q5 z*$eqKd9)_q`kCZBN4`OiYt~vTTp+tovZ_y?=ihXvtpijH`0*ma{cGv~<{rU1W-vB= z&QiY(?A}@&Vh_Z>jJ0q1jt%%{Rd=9&=dRqoPV}d5;#1f(iY?+P`I#$W(^u^045iM_ z%^<(#u*w*D{)ozWIMDceY0h1oNUtN^SLV9e#Z6ToeBAW~`1o=ke5`WuF`*AWHt?rJ@a(D z$;&neJpVUOHX8_Ro@^FWIb^f%Qm$`bwdW(>KecNOD75#nCfC$*UNJMl`rELIanczW z$pV{S0Y2(^06(4@;AL;g9{;hg7#Y4kc#u9SAD~q7mqAOO&E#78{~dl4m6tr*iF%y)>ij9{^rWc$OZDtJe&6#yYqOi2WHcZHrMm)L7t59PBO=8 zp0-|!y>Vzi-0lMo!Sjbc@OSx5&S@+7s`XKML z21l$N*|YETQ$7$04`5%*~Jp^@HSl zn%_w3eT=7Yuz`J-R^Zso`m&gJ$k)}|PnEB29YFFmu^l~I6LX0&jPrNF`&Zn${;%@& zpBb+|P*!}qnRH+I`bP01SDvke4*kY84~Keg-ZSa9(fgaA+05Uj%$-Ec;|AZHXSF6y zN;RIJ{DYdbCgj=Kz*>te+jP4%YU145;^D}!v=K=G{&r+te5&Jx$hqZwf9|qcTZVn$ z(-nJacdvM^13A{p+tWCWbJxssWITL8Rj%jZ-Q|_PINWsep2M{x4ji_YZAYfPWKa7t zN2bk58d=rB+~Lx~$+bQ+(8QfgiVZY!c@4H0BV#|Z)+YX|PSN*h>U3n;NwzEtO-!+J ze^}D=%T0?q1KS&C|F5+HJtZ|BFrJUxS-*R2S8R6}TXpB$t%v7q{pI1r=+_PpzH{f{ zHC=}eADr8I_=DR68@iIR5@BStPXfPP*XtYHB^j;rec!VO-#4F4JoM1vwf=(LmE1W| zN&Ew3xUSL*>KpF_Hp#sH67G*k#)kuWw21jOZF$PPBUcADgwHuGZN~IKbrb$R4nFKS zQnt+d0km)7|7FX(_}N%v9eJ0yg2fH5gz9fp-N?LQWZn?+ZXNP&)0x(&F!F93d3QMS zZtE4b#XFF%pS!Fs$hbC?({}i+g8E{f_+J#C{riHQk#XA_YxzC7G$(Dge`n)HM>`my6_RE z?%j7YR>*;A)P49;#_9>iY6xRh&scrHSm|D*@bch>BHF6+?^rhjJDSF-gR$yjtk6>q zS20#~$Rl+F^gY-$>4LS5v&XH;#@?HOzPw9w7@etW(zv=t_Odhl(T8k3X!cEy+d9yt z{vD0bO^Nyl%`7?y-`zq#)W0qMyVGB$FKY7;^KQ*4{ac$IMh@40628Oi(Xn5z^#hsx z4$aBFvN?MWo@_1|OtSf8p8r?b{C?`ciLv)&b3gN)eHL3b|0V0q{~xmXpK0?-+OTDF z*|yzt6RqbNvET9@T2Cl_4zL`@4n02G$f!VX3*48ST6IQETG5al=r%@V_BsAh(v5=` zcBEA9iquC3MB@SUhBD|;?~5<#Ncjsqr|J)t-Iu|0tmQ*TUANraaQ*U@4c7AX^f3Q# zSiWsT)pBFQ>`Uu{Ys?`}%z>tfEm^!{@;!|oB!wbj{;wr|aTRl*kYAYe8e$6I_nL@8 z=Z@Tx(;c#+_`h2T^f~tL+4~^wRU2|EvFs9_%oI8!8t+2Z4cP4)8^U2@gW^nB%oWMI zk-S$L!^A@JljQTqCxlRCm)-W9SYZ07kT#x=9t)KdkIevPzbmdE&hLSA6MSLbpi7hnHL@A{qkhFrXF=G3r~l=V?2qtc9gLsG5!S9-85d-Nx$WQZHMikk z{c^xqv>pB~KGU(TH>Hz(^!EMuTw*(seNlVwLHrPMA8MK26fn}hhJ9B1pGfTe*rM4&5y?y^r)|G=N0tqqb>RSM8q%a zu}jZ#?v~uZ|54!AGM-L*2YXm9vJZBi)chw9oT3OJ;iqS#$3X;4P|;vit4& zhGSF9iTsc{bPuuM*r#vcFqyMvN9X&RJCX*5h2!=tqvwywu1reVdd}?Wz3_ZXA3Tdc zoyq^+B+iVFl@Im+;#~~HS8NbIm+<-3I*;kZPo0WAvX!ck&q3=VGnGB+=Ko+_n3B}}V($&aMn?~-WsmbHHd*PsK7UrRY}*#J z(VdhPX*EYoX}@*!JU{!Bxs098)QmB$;-P%s?lYcHp198>#+1>8P3e!sf?0!)%9{4G ze74`OiG9L{F9kYBYz4Z;zF{-tcTT{6g#Yp%`7yA(2K*Mb?VZ3HFIqfp#x~+olkUbR z@>BFJ+4^Lo`Z#Gs#GDi3~} zuy2)9-vero|M>Q0H1R*?erG)^7Jol-`6cn=oC`mC#l^&JxQO$ZKIgm#d|Q4xPXOoR z^jm&9w~UaS0zZexiYK-L=P&rC=ZKrY8Sn64zR&2M5X(!eDLKR*LGLVRgL%_Ee;~90 zU0iO(u??}$ZTpqsUuOFNFt=-_XJL1g9Ulwk^lyGZ97JS(=}oPPnM+0M!fD&9&i+aJ zt499S-~pfA$d~Ec8Nk^(XjZ&?R(!BW~TT_*4gp<@M7cwQ0r2ZrpPz@u_CN z6n*Yq;w@F?8;f@8y%`L~&AP^&W_@-qym|0ABOdh^EDfd_&8_RajB~g1DU|Va9O&NNdsHbw61Y;j4+ ziNIHlo&f(fzx@jg&UKm**(5oFb740;%RhwgCg%uN)?C;=mN`P+eNXx9JvZXTH}^j3 zYwrD<+1xwNZ03vu>*>l1d!I0xo6vzq0pE7ce_=adpMON~D03!-ciZ$1SP%1`^PrP; zzEiqeExvx%@b0NY$m8ed^U4Fa3IBVK{08r`hC5}3P^J}_@|eG$@C^Fg_DGw|vp~N0$(%NH@@w&rd&k+9Ao78H;_RDk61i(MCIEw(E=o-7!qVmu-d;3)lsmKw^ zs6E+&j7{HI>Zh+Al+&K`?5fbTv+0Y?{?ayqkWBllEv4?B?Br`JT^AYTe<{*5_ z=))!C{heEP?cRoL{G&4@qj~sx9hil)0Ck_kw?ce?boQ!%vt%LaD#ZSJOLEFojqQ8D zt#w*`y9!!U-}rCGV`6XArgM*G3tXE0HaJ7a$r2qaujm-vtihw}FzHu@M&Sci?2qJ~ z<a1c+dWRX!vsoW6#rChY@~3&*v$u@fnN4iU z;GBz$t+La6KpsEq7G0rwmQ8=@i5G4+(+BIFFQZa^f2v=3f5y9`8Wa9YZm@YgX9DoY&N87F z;a+D1{t7*K?N8=B;p{YLCoUpI#Y>$lZsUkB}T z&$+!vYp|xD3tZeeU3EQtAQxC8{Kp@o%Gt+aZN|q#wtB^XMsKSc`OKPZ&9@I2qv3<( zZ=XrOheyi613t&hZ#(uvBH%0B@3KMN86mY`Fva;hyh99Z4InviZcey6h7A{VDdfCZCg`(mSH2L9X0 zn`bYD4!Bds3|fYJmUOiv+p@QHU!FAt`e6TCKJ+}xZag91zG<|a8*96CWl27If;V2D zFy~Vlr!v;5r)amBen=m9lJvEt6Feoe(^f-SZ|@XGPf)yl`|MBT#2FFBUE>ttIi9EV zp(@5Hhw<44K0{`pIJ`W%ZU}pU*7Byn**uH*zXe*5-EysH;+b0ZSFNrs(B)5;RBXL> zN#$0}3G4#9-Z6(&U(Bx9PoK(=EUPYdxp0Ur}J!sC=I)zI5C7i)dQs5!QO{)DMQ_^6eI8$fne^vx zw5hX3Rm}e~70f2H1D z+F3(8EzsJBv~`Gfa*RNiw&SK0!e z)Pua&cnza};$7;qg>OwcV+X%MFD=GLxd?qU$<{M+kUzI~^`>yo5%CSoxc0>SxzTuJ zcBo#q7ykXCLRBRy48T?EV1$Rfg{m7p| zKl}Ummmvd`4mOM)7=rFs@0pLhd?RHd(5F>HKHf8bdn)mfAMf(tpv!;7-zAIp-TS`e zKb^hrzJ8s8xe~glT2{74^o;!pKlq$PEqfeivvxhR>aBIaz3Z}NgEw5d?2QfITmHs| z-xW-H;>P8JH*A@FcjLLVCtS>#{^W+Iuy1Wz`MY&n7{e4_>Jw|tVU3&xe&PXQb2o7Z zg8V4Fb?yjjUlBC)JoUdoxmsUlg0mzq*!E9sjp0o23BL((?mozvYQ5082Ih6u8t@|8 z&izCAR&O2m=57GHw`dWYNf_isf>&0Ezs)UvEoW;S z-rB($%Uqq5L%Vvv1D{vXm}O=Zi@r`>BOUvy&hx3AP4N3QZ2!;A#3w+~#`xw0Cuw{(8U9zca3OkFD4fq`z_cJNwwT*99sn zw#qIWs0eROWZ7@0Y31@v5G`hvNP!wTp*7d!-qaK8$6 z&#G;AWX~UBToBz{yi{^5I(D_{EyjZ#NH+RF`W|$kz3>C@pL0kL zrY?P7i$BiVRG(W>V z<-dF2p2i$}q@HG<`Y#vULtJOw$|hUD-{ z^*e$;neL~M58LIOw=a^8$l4Odhb<&L0+;;P+Rp$Nr=9`mY753Veq54i zs=(`a_$J%yg8QTSACmqW`D}WJ-ZW>81IG7^8e=Js zEgL^qj?A+#n!k!R%dU3x;z_*I_`Gl}^OyZQ$~*SLSCO6Ey$Et( zK6dR%yxrO7?A8C0_WJk{~m4xlkL3K06y5w`BF4ZyAU3@B=_^ zULWGD_9pt!RAO-co7m6HCAFh`9v}5LV>jXdTjJ?`+I^pPXVR|d%3}Vh-H$1&wxRdu zhtlVlD<@48e}d042Ao^PUZ(pk-h(!hz$bh$@w01s*S`qudor@u26Tqa$=O3vTmGIE z_ZK3E?xT;l;A^FrO=<`I{6sqok=^p()js49wdb{^c78}ZKkCztRR$dsLoeWtYa#Z~ z5O?=@V>od}eST&?dd3y$YYvBVMO(&N|AyvZ5s$ zKhgY(K(v|rQi8<4bk-<$&T2jdIK$}Cm*$ZC*x4tpS3O_!9o?axm^HhUr>_iuW~yTw zJ)Ng$O19B_H{IVhdX)E`trcG&JAL5LNn7Tnyc16v!Sh+@H;J_c8LD9i>2}w5@+*9M zil6w?g*=6~(}ZWYf5(XJ;PH;$)z+?V@}Mg|j}QNwmr_rZeYROVU!{!d{xRR{`TuL4 z;;EuN@Y-;g|Dv@E`KJBTk(yu3kufb}>h=D6e?7@Bgp*_F$MWkBk-s-7cbD4J{A%|b zDe(4~+ST~VeyKgN5VE4|`rs_)ow?STjn>uJC|UO=0mF9acn7q1lHWbphu;lP5XWJC zYtU+Lm3+cA1_^Lt*Eu#fb_V5bIdW9AdHwCr2mWvk`zoyM{|(Kxv;SiKVewY(C#qTi zJ#D`_n*aKlGnxOK7k240FR89kJZFqy)lZ_YBhbA!>%1Lxe>5n$=S}v)SZwXP)z%{) zs$IdXI_Q7w2jEZsD92oV*`ssmL9g*G1Pyz7P%1d{^q}kejAdUsYvBFAqAUKEx(dnb z`K!(r9O#PQe~}m!ZrY(?M_2sri>K;}Kd0r~hkG9QywjPmlhW zxat1%Kc!FmHoE^=x87;rgzAg6WT z$oHw7x5hqW@2}Z=2sRxjv)_=F_z%t@O7GG#Odp!A`6ewf_)wB^o-ZbD!K33eso!QTTXzxE}4M`{Vjgy!Uv`NH@LX!&7~0 zFW|j!{n;>{r0)ie zzN2nh@NME;v3LIZIqLS{J47C(Hv^wHPqx8FE5XNL+Va+MAN*+)v?;w4fA~Zm_vK+L z1;75pPm%R(I&$TvYVvt;-)$KK+ZbzZPb;$1Thz^cdF%rjG0~XT4aut}?}Yn{KRhWr zv#vXIMt}FDsK1WvpnW9#+ko4NOYg~5@+t88pz&x1G!9`CNR^yl>)Lkv;{Fa7_qX-I{rWz*C*Ix( z+?V#j{rxWPXWF!JYTO9%YuOmtM~nzBN0SuCBndqF61UNpP2f@E{3-p!hJgR8bPpqT zl>gv5#(yVf32DtUtsAQ6ebEo+)Hd1l+Ki_bBut!AG+4v552D9I$|K~XdLXsK)|-;+%=^5T)x4w5h-@3 zl{g(5^2QDwJ^xAiAs&b?Zck*JF?aqr=WMoo6;|ShqPV%(7wkI_brvkLBs*=!auXfW zoEsf^<auX2uf5;DdrpS4qX z5=`2MgFZ7vH`u!qKIENOdDl*CNpKw@Rz_D1bJlYAKG3h6xN}+yspI$LJwo1e;oOxG zmNWkL-2`7U*w?nOm-%fU6Z`;T=ri_yqsI6^7xFwl08Q!eHNLGzZ;=gM{A?U{ScAR& zb(lBca%9$OU#BHvC++ z=*-~hw(Z)nSL6)IUZg%6rw^RBZHy6nWu^lQ_sB9n(dKOvc(=-VXN$*Kc!|>K{qy-l<~w!D)I;Gqh`)t`FPX@yQg+gm*f`CpvA((UYU)( zH;kS9>!NG)XTkl7pV+6+Nype(@sQR1Vkc$nI2@EIqD&?B;Tg&w#Mg-Y|3&_-{DXxDZZrYTQI2mMZqt-yPkTdm@gH;pqMXXmXvR`b$j~rxXQdr+zIL&g+I}w z{8t$d-VXYpvW1jUd>Gj#^u6<}S#b|OeeXPLK)jqh?F)_OtUmpE23yTNecC8t9a^LR zf_qrY^l#%^^#kw!#OO;AU|7Zf4(T^4D7nY`AL759ho5*w^z^Y^f3K97Gz#F2$O z{)Mb$>riGya`nyq^bTj8ck*aWkzV4h@!G4G-4(hl6|b{WoIMn~pKnZw9R>GVcf4X3hPbNj3L-drgJxZQySXkIzAN zvFa`O1b*^e>_L`V*rhWoZsklT<#BQ+;!Efq_qr`vhafb4? zH^#YZvd(BZ%pPCoCdL>0E>nj+KVx`TO}556nyH*Dd;U ztd#P-=Q`ipfNdW!LjJ(_a_a0Lk7cG!KyEmZXMvmN%~SHEPf$C#)E6bM{QlJ5Hsz(g z*T~yST?<(g`u1COprd893qSahu1Ud;LK(p$oQ&bW;K=cxz6iTUX-D_Hc1)-`&V(R~ z=3@g0_&I;VGm=X^8aq4YEx7R?o4F^Py5j!XXX#u=^#0QffBlb$zrVwGI&l<@L+17?~V{;KRLM}((5-Yo+cZQw|2_apG-pSbv~;hq4CHY_tc zA{rE)Wk($~6r7IL{Z=(4XHZ{OpZ}71^-W`i{U#&D{igrO$S1z}j5Q_lC9>S_1$>um zvvD*wZ)7D~#^If9J09Y+w~haTU*9&9eq{#tr}6(2_j?}id@UG&T#9$T|V~*B_HztW#EG6zG;-57kdbQNYYOm-RH(0B<?kCjP2Ql$c=t@@OX4*)@=61 z*mti!Jx%i&*((w-9oW7BY=W6Rm_t_e&@^khF9KegH-q<(=H6F~#jKV2T8Fi7M*M7I zRB%TJvUQ}qd|HrsXi;aRV*E7u6x(O@u1G@OO^#D5Z+A zig%02^eIe*@6XnHs?6GEE?t>n0Vyq7Qw-INLuSYtS^ljCd3tXyG^=+e`Hh5SK zYp>!K94BVM#lwt@yD0krKTn5IAEggUfARX)E?CfC1h1{X0JG%nvGl`_K9Ykz5=I}% zMSm%$zm|B6tH1b>n`}ME)n884cO3mC16isZyKtS)*ck+O2EMMd>8orCmFNn7#W$2-u5r(G`1~;ynj|-U7eFT(%FIS1?EML5;o z!}GM+f()fL+ZpTE-THpg-kY@|?Nqz5?R(uv9w>({6;DyNOP#&&Vk-LCE1PGUv9KFc zvDS^L7&!m^l=^=ZQ<1&Ei#Z#>7~3%w%RfJ+V)f_6RGh}xortN3KbYprY$v8-;vd9R ztoC9mewlgZ#Z(+eUFY-Pcok!eo*|QWs92&80`!n5ie|sA?YTJgT`lh?-55QSp zo78CFdmDS3)*bZd$aEJz#i80xnRLGYH}7Oyn>H93Xcl|5^8>7DL3q~Scp)?=-ZTY1 zI%aS*F8UL_X)kG>={rGlp@6f_tU2xPX>LHDIG)MeL%i_FNt$c_7if<4Aw%-2Xdr-1 zs|tEk9JV6p&GSLrkB-%e&v_Dj7~au8mgfn&`w9K^=q^OP_iOwvpF@A~SDBB$%B-Z= z*F3tTP0j=+4l>`=_7K{>NAza~yRL`+>WA#a|8elA_$b5NfHE-hsLx^`$y zvwXO^;Gu;^QUV_T{5w9$uRkDODRMgUt3P)Wa-9>SRBO1-+Xz2%TpE0Xap_Nk7ej;p z%ecYIY`PN-zDz#Rqep}1xMTb_V|*rQhXzmW<3FOodx*6!8oZOIM}wQ)bblKBb{`u2 zA$ep|ozss7mjgpz8vG$;yjW;wkzU02Df~o(>x0aP6MK-d-D!W&jx`y{pwF$y6oNr| zh3MJa!|dq9PYFJT9ph=)F}ysoKPZpl*v3ak?KrmDhb$#O_O@p6?kaFDe}f`?LUV}O ziaZeb@ z-($^RwJsoBafFGv+V`^@;%(Hs%JG2S-KnUT=&K@F!;DPf#eM*9quV}Ew+PdD?vHvNhF!~ z(=H#^LTF;t1GU-zR#VrQ6LiigwsH<_LDI8QPCL2o09erqZJCrw?l^h8I7;_j3BtyTWIm?d#>NXglz{2yZtEt{yG; zwvt!+r%^!s8U9bDec4U+2?owAS*-oSOCDz?=Np4<->H3^$y3~g)sEjF)R#H)BfcVi{9|l5BcK)L>F(L^U)GYIH4ir(E;@hr;mRl5 z56>_IU1RBYn0`d5r=55df(t)`W{a2HG#_9yKp055)w)z`r% zJ^&vTJk@UJCDG=VKy+yr?MnZoKN;`pJMv4r@JU~;tbEbikE1VCNuZsLtLo+8{XBymqU~jJ_}7F zKMD-+npEK_llFuo>7J~=8LA(BD&Mvl%&)P}5C!nh?F8?V%_0@Vl_j6_PSJvFLW28+ zPkUeJpidQ_4w~8qe5&&o@1f(;rU6cB`<|Kn26LS{k*ogx%p@@B8@i-@W^x`lYbF1Y z%ZuXho?}O^m<``3gnw`@_IsS2eAU?(vi0!!KKO~FiyxufMXWQ7Rdak`w0Q?OX#r00 z{1*EEbN=UUF0y?zHNSvmZV`Tp^3`v5eKg;Irx6=CaxiIaHhcUT6R7h5{ZdR&>Bx%f zC%?_(^YOErWyU6wM|^Jvyk!eCcMrewzFK!xSC-LS#hz^MkMPmN&-Q8bkS!0~-Pjv5 ztDnM0^S2k=-MEo5&oHJ%=8$^!t(s>JSkovu_uwoezumkqd&K~w`p_(+oAo=tBj==# z<}!HhT>2>I=@FfKjZyP{BY1} zNT=+7@{>>Jhg@|0|LW6uH+A&)>HK%vIFmNCf85un6B;?O*DhTBm3)QBKik=3TL2wh zjW4NW&+p8P<|{T7KJV)n43`dNBxblio?YbC{{{E}eV_7WquGa}%x}nR%d@V1!P60i z120|BC%xE)<)p91ChC>kzMiKiw?F5m`^)V&(yr$V@l*0B{cUUzp1tBXyi>pK=UD@O zw7>Lat>3Os*iPQVv}~WS7fGu>>-p~4M*924Xw1qT- zv#l??zCd-nSHIWtJVJig7pVDt(u_mH2fQzaPrRe=@^fYXsM7j-U!b$dU+eaFEot>v z`1&$qdJfkKYMuZ^>eD5 ze*gVb?E;tcUj5AGc@4iOfMXl|lFh7?|5xz4A9ysbdtDgMr=NXcN+yqB`rE*hFlF)1 z;V~JBDSiAu-r~InQ<|H81(*WFFAEc&3>#;nI6UX@oZm(dR~@@~kIq3C@&6uk&a*|w zZrM|XOy-@19&Flv?uW2LFxT$3^)HKkH_n7af?CtyU)!I2FJ&k3^Qz`OTrwD&T-Q~P zE-G67#D=0{rS^H5V)z&~x*qhdX8)3^#j_1#iEM`KF=jlmb+uil>f4XGWxjq&nF@S7 zRE{$CKH3_1bP(HLl_{M+*j35;5qvrtzaBgDmgR{JKc%hfY3m-!1ee^fxVSvLIE>$q z^b^tI{}T>4+amcu`_mo{JiYS(_;vKoGDq(uuHOd6QnGH2Z281#@nW>l5A@FRFVs6V zPdt5VO~)7Oo#V+Ty)(}9AL*UBuHLCJvaUUrg06X=r*}%lBtJYz-Cra>`~*Dol^>>2 zhI4QY-{i;n?o;Fk;+i-7g!c>iA&WI6Q8vL(@&h`;|FitCoI3i;59iWGE^YLeAASyg zyfs$x19Feehqn&EUP3*OLRSmMoGLH8!#7)A;7mvr`FD};pUDZ(+X%|x&2=obAp@nZb)Kdkm zJV{!8(fayDvO+m|Jz3!;(po#8GiwHP51A2NOicf!ZqYkdN}>=D=Xa2d-WY(o`w$cdw#?JLt3)JKHf`K zc#EeeE6gAG_p-ui{agbi^eY4un5%7qr@@VuDc->BnOp6b^;`em={uBbu%1Kwo#_ zQ@nWbMV<^h6&7ALs60I1M}~KQUOlaw$a^4a0JV4xer(TCnU#DJ{#GUw*9m+^)XtYu{Hr9X};o~OqJ_LPZQaa z@!pAjzuEN0J!r;{F($%gUp#&x{uZ9ZAN&0O7=L4hKVxfe@E_ohJU0I9dL8`9AMl^! zk9$d=xue`&`X2*MYp6K{O2v5DxwDjHcpxIdiHa5;7-5$g)!hGC5u%U4? z_+rc!5oM#%!(l+aA=*co_MUzBRo7(ad2q^mDYMx#v~-_6dr;W&0!5RD&Wjl60{HJ$ zW@d0f2x&{{Y$rW9n!i?gGqG_}=lDtQrKoJtxHqy7<~&_eH*QC^-apBE_9ClPzU!=w z#8)xWs=k{&k2QyVEzUJB56+u^y;0o>FR478yDE4;J~_H%MFDof_2^f5LHnKHs9Nru zS2f_YG}$7RPw-SNPv+g|lkZ%(EY2tC>{`*t;z%*}Ey@%LHkIp7pE`Smue*HsZ61pM zOXLyOYUaq4?bx&8%%x2HHSiV3hBp&CKQRJX*9%kuh zJv3NP{D2zNy~vrcu9wHY?y;+AA4D zz6#pCj`0anZajI`f`=;Z)7}U!$lqgPvlSdg{1kI!6+E*NIPRwZbHdU18Z$sY0$tmv zvy%1$lnIenu!KnGGR_w5RM8H3ccLrXwoPY);*VDM;k;}$xX_?;fUw5YE-SOyUv%b|b-Ea7VVdg>SpdXZ!={`9lP?b2y zogK2L7kXG3!2~$DTW^anPadCnmaUBcE9tjVIY>M(}@N?6ek1?zQev94PMg zU_OT0`mKSpO#Gg8?{jjzRr`#qoi$qXP&{u0_1w(d(>lF}xv>gge8tSP*HqSP_*=tA z@{Jzki|=7g+DE>#c(=lr(WQ5ssV?>E1Qz_gu!V7!KsIIMeJ9Q&af8)g!D}Idl|xTj z-{t%DqgLhsK3mWOzFWX&uixBhmPA?3qVLCNTW9l9na{{iJ@Q8@0~gQo{}}6O>!7I3 z*TplgOLof0&s$~Y;j6+r+p~hbFZ|s~S8&f_uAbb-7}ax)v*)lv_b@_7E4ZI=0d>zK z4k!4{SiyaZh2-;bW{UkI%?F*~%h*HwQpt(y$ftFDB{4yX0fp>guXT}El?E734eh{D5JVU)TO75dWt+7Z%Gc#G(*mT!OMr@Q{vxOe@1`!fj+ff zNk;7khblLer^<47c8~Jg{*`WqJbsHkI;*961kYQlm-l)nIu$&cBgOyY@F?BkcYJ)b=Oy8s z^BKpvA7mdqp>3ffgC#MRlG%0;Kf_3g_SC?C1Xt3?Xiu4uv)9yj&ZgwB_C|ky;KqBe zLeHWe#k&PY8&0o|t!^Dr>VQZxm}8u4an8?#fo&#o$lK7zt(+OUhyPXo3yfopnDqC) zHWs`6i)PyG+j`LDN%02yzYo9Mebl|c(qUn5Br1>Yh3E-aW|J zDgRF8U-5E0m%8vv@6kH((+P~fvxeX|B^lW{ud4hnyY<(4^%tc4ef_+<-L3yQH^1sn z{x|3RO)K)OSLYM%_nW=?7Nq`teY~r5>)UAOcgBAryjJqgJkBOMx?V;?`0?-uot6q;HnjdB>%jA$ugHd{I5ITo zlT4PASj)J3@@~_nRVCZV=g){vvoft<9(&#R3k6rAe=?8lGhjNKfzPp>N8dxKR?xrv zw0YL`_(r7qixf}T%PYJuaPbuJ@U$}R@A1UDTo+GYReskGPxt={Px!hM5+KU_lKz#6 zT%Vr!34Xi(tZz0xv9SmallWi4ANPj$GxN$RuJdlra|tqy2r$O#Ax+$r{U|>&l6Rl1IJD zgWccB)8^zUqYjP73i5a~AefKc_KSEu@bu0~+2z@RoH&SD_lX%^Q^UQb$fdc>gi$8|Qy}ItKZA?qt5_ROL-$UBV8M#e5u|$f6u=#PDfi z&*fJ(zHI&|If}mK@!L;3vbk8V71;esflo*e_T;B!ikIWAW3qo+`7?W3?;5a0IMQ0i zH^y-UpVq_=y*7r*6;AQ1{Zi=Wh!HHiS6S`u3UI8y{@# z%?e?=58L)K*~yZT`I5RK++i*p_P?L*2z|&ShW@BOJ8^Of9@uZ+6+QDe`_FG-oZt9~ zk*H?vBE9WoAMxwFM`Y&D7Vvp~X{w>6RlKc0F*Jk%`|NlB?eoXWy_4ytCiw}5p^1k_F z>b;hFRj2q*`)VUL=1*=p$wQROdv<15;RZA0{-d*cUy@3x6fEc$k0(VP6Y=SiyOQO@43kIdM?J!TA_ z#bDQSM!XAr9;BVF=gfH5L|=@U{Pp`?e28a${FKkZJLNj|bN=>~-1>H%B_Xf!wLfmg zH6}Lx_G7Q4Zk222t_6F%D5o-ZUbmc+*D0sGA3f@n^U7En6Z)k7j0A6rQ7zngwn)k4 z=SKbkcx?BsQPk-G6i z(*LHiXnq{I%7LBxO8Ue{(s#*@A#54yk93odlLjQDvniIhzSmN|&MhxnVE^(q&M0f+ z654)xe{WW<^y~Wu##-6)x9JTz)G%}Qstx&Zt6$86SQfZ(__rgUgyHYG{j#JH6^c8XZz#PxXuO}+a_}Fy1#xtWo2s?%-)*(3Ha0)n0!NjvU#8Q&awY-@T@tk zK9w`Ch%Y#y+~?S^WOtU$u$wzc^nKshS>gRjq65Vc$Vhy`d06Pn#;;%#&5Bl)w|l-x zS?S(McG>PeerNjL7r**1S|Dx`=c=6Xkz5po+&Yy)XkkV^)E{NA5^=0Kpf-{14RoVE*XS4oMeE0Afzi|5$-IMGWH%z8IGwrO29q>)1 zE3&Nf)CbWeAE!CkeyfcRzN3q7sOoge3d26^Ilc#sT5Fkc*TbzB`QG$}@^1W}wkuVZ zH_r8KV_Pu$H?*BT`~1%?4!k~B--yp1=eyJS2lu9L=r7^Ch5qpR$dpZg{fTlsT2&Z4 zo%zr0%Xa#@oxJK(!-pwzmv|}Vdc4%*H6E;!kJC`5q2=y$T!#GeIp-#1Yol|FnvZ>q zJN17Z`KB&bxD`XT(HO_(&GpHdd9!7F19;=ld(+47S-bKhe_>y>bISPRzGBsP8pGYk zgu*0~xp0bBGJ>~qZ)aiUbtxK?cQcPI8dO$1)t7DjyCW|Lm3AuQWdY-+z!nclk6j0B zTK5!IS9KP!?vbsP(iuE}w-2zpYBA&49m{(vYBr?M?%flackSdR^=-#pAE(LZ#uPg+ z(}hR8+=ETyA;aL#Nz7A*4>DJMw^cmIrI9*lSo}izao>Uax1auu@u3%Y#}j*gMy}1r z&eBbPuvGW^_=*)TUffDQSlFSoLDqr|f+a*I6 z+AEFEX!M=W7vtMT@K@u@eg^XJ1ZYh9xQQ)OMoNB|*pfd|@h#Aqx$g*Gen4_bVvI{> z{S)?c$n$0n6b_dV-`#&xC9ov^H)tG2O@8svUci(Q+w&7EL;8S&lgF68W$c;x&0?&4 zvIaZia2fKOW8{~K+J9f@;zQ$3^d~wTqcRfzhx|#wgUrc^Gef2ylt%GhUkPsS+eRNf zC^S6$0dOtCjw_h5CGUohx$6-dFYdaCBnRBHzKi>WmW1z5x@IN*8a^}2elcD#p(p0ZL!A}cQL&d%XKYfHbCCoS%Z$gJZ zaS!u^((8UO&R5Vk?5p*+{{BbdkcC%d%DM^ zoxel+#Y6Cl%Ajj=yN7iIaK_`5E1YR8-gVIHDZjpb=%GUJ4sY)D z)>Q5~i|`7UMm1kS55bM1dB)J4*SqgZ-nH`U=STm_U1#lnzoG9lK1j@a!-hnjz}`VH z=bG^%o{|$A4P5rdg0R9HfY

=~iSZ_}PN}{8svI^QK{8?4}G&wh-5v7(2QrOnrm@ z!H&A~>Xv(SqcE)}robB}Y+ROCif>|t6@gQ1K(E4PihI8ECMvAeZv`0-{n%$rnUa`$ zHO@R4s<6gkOuBqicnVZkcPgLGh8dZ=?S#zTHXVBjdC>7eBe-jv?o-xkF)s zPko|qjfJ|KnB#Alb5D_N%~6=aDf~j;o-TrQ@AJ;a3nR|aolX(=(Ke$q)R-_;~ zIvXKdCU{qdNqgMdnm6y zU^ywcR>XYbPi61In2VkCA*Yoc)u3`k!y{x%Ai`_QoIg zCG;c--Hz({kTSa}w6EHaF`dp>&WM7G$DFAdk=+Yfv$3`?|FxOYCC89);{~E5|e6O3$KpZv6SjY3*nAiE?+;W6mE3MXI4oAMx#Hofa)ZesJ#U8QDS@Ynd4K z7xDJ9(iHxg^Nf%EPu6wUum?L+;eDgu;|v{px9fyo=**l0^i3TbpF+6iNrg)`%euK& zJa>E7vMhYM>tA>k{oVT~S2yhbr^oK*U;eYUlW+E*i_93FbTwhMIs~@%=5{YMbz#`SjTM9Qu+mh8>Oc0B(P3 z-r7aF_Om2gv#$Yct1I%LDOXpZvkZRpK*QUrI=%LCHPSjFdu{#(`$ND~eJ>q^y+JqUXqo?NB)wZscI8fz`r zqFX%Xjx%c?l9gudA7k{8 zso+~-l`jrR%VR9#7g2M{Nj`xK@CiH>->+so8apRDHkENIxbMV%R&SfJDO^l@)t!^N zk7emCzbx;!PRV->dAr+FFusGX9OddUWaGx>w4oQL@FK<#KBju$<6@wF4SNlD;CE?x zK67^qds4e-e(~c3IdnezUt}^ zym^2-5AbuxovW;0n(;MSgQOZ~oh%Z`87N6!W} z>7%{%rF0=*s+Sgw%xBKc6-Fm*<}Jp9u?wJYbzkraS;^Hqo4JO56R-NmAF(}PA8j>! zXDV}!#u8GL*+)}oKT;1>(;8L0#(ultl@Roks8`Ijql5Z4^*#NWyZN%xL zbykZN@%D{WZu1?jY1{?Ee&7k)X!VWO3w7TQb<&^fG!NO*g~2Be!XG#fSzlm}9MOn8 zFZqtM2K6C(`*1f8Ee|Jt#`*kQQz zfo>Hz4$3YAn3Pv{2#P*buWVKs7iRzT%lz9prrkCDu;Va3?ws}ReL!A6c(iD-2PPSA zij~n(KD2)M;Z-^}p5Ec$N5{eMo$8a{dzE9Q)v@nZ-YJ+TP`B``b=m{usY}f9)Z2Zp z(9HWqgei}nQObA9e&OmNU%p>>ZnrvSdUYT-{97G_b+1GF-d_8>J-$cryCc3M*+p}m z+GQc9sXe{8>)G4uT1q?qNV@gDiz2fRjxjRHx)E7vPa{()pT_i)!16TxuWyAt&cDhN zO%?sID{U=(?D@Kv&gb9;t^0c-6J>EOHJdSG^u!DBWfE zy!PGlAGI{@;`tRl_BLV=k%4w>=A-((|BG ziPSMC;;V!3hj2cR!&+E-imj#f5z$0ql$GR`)t?*CF{rWmwEbv&e^RXYyeS_}PS~ zvm%o5ihk6~+&cs5#U|CU$ubv!TSb}q$>g8!OExx2GngkQK3X3{(JiY{UzS@)VtLO*S`84H-9tUZBP@n3QPNItZ`Q%f2_PsN_^s5r-o&S zpk14C3XpHR_XRTMiFo#VPK{Sy zF|HSAyj%hQblf#!>qo7(EB%|fZA05Dm|w`F^wUZIAZJ42ge@dbbDQGW|Ka^}n}5Ey zy$3(7pkI4&KL-Cw^N`A4L!Err@vXAgz3HwsAHTcJ)V1R~t!WCMys0&<{UUt0PM2*y zx_Hjm@E@;&?%Jp0XOl;;XpU|J2l7MvF?jf%>R=7H8C^g-ysYJTx~xRH?ARF6T}wKA zQOBo}PUUPG<;tCFfV-JIPwNfbvq<+hX!za)&Zl*?rU~a-58q3gv!T1$iMZAqTW|OJ zV>WSx#L1qnfbt$ydDL^oS=7V(p0Bv?#|F9Y*Rj7r{>-TK>PcxeeLJ0gsU$D7nQ=oR zuKepR3=4tb29--Y@6wxkRIlJsowqCO;jz(t?mrTZd-gQV^kX$~`>(hR8u>c3f`7DI z@sGC9z0c41)8Ouv?t7cXl=&&RDBwMo=g)k9gZI~YbT7#yY>K`tpM0uMfF}C!W&u@y zI`v-8`(hsDyOex3{!QDkwMjCzy-w_AY*7^EPyFK_A$YxPUn*E%oC24ha?Ydt!#st2 zW2;_&0q-*t<$q0ZEyNB{b~co!wFz@}U;KO;KdbPldg*iETagIgT1O2M-smH(ZO$YW~QYDbwf1AiRu%6#n(=OCD4oQ`XU~sGN3Z>tZ~p<^G-+E% z`x?uI^70}$T4!Zbpb!FUhNu6JImg%`f{y|&ZaWNg9@f_vuVLT!4 zJtm)O_eq~{(ACMFUoZTwqOYGP?#HA(P8W=glkBe^bn6kVXl&(>*Q1B0p~GV- zuScav(3(y7DXTo3rt^5hqtbeO+LKE(zpE_iUWg~Gsm?V^I#rq=)tAoJAqkna*j1kFmvA~d^10G2DIS8 zSV%qP%rUx$d@69b`>LfohVd^PxHi})^w_M&jg8r9#A|)e+_5f;?n-pOsemKnT4|eoXoiqif|`uq!N8w4CVIhbdS6`YP`Poo!G%mh=Cg`qjVw zWZUdJNb9v{4&S%(JjwF}kJ__D?P2Uh`S0Ei4~AO^7YwTNgbhLI4wd!aXnhj#UcKVC z<9X)t+{2@K?=*Py?r&f`(?^;s=0gwf(nnR$iul;6YYT6Dpg%cYeg)s?Nb0BaAp4o} zztOGy;e@FT;_cpeU6Y`Rv4s7%b_^okYezBP;xB5;r95f}$4bhf|e@ zy~6$dqKoK1&296K^@+~E!;0VaeJehO{53tT3!qosdkBBy9x3$X1?b7oRr((Cah)G4 zryrs3V49%;cmZdfE3-I@h%RR`w)Dc&pdY&Zy#~2KK26RPKj#iM*~QBrsP>-Z3-x3E zKUo2-f5jp$BiP0F)UPOAdhBBIRNaXDitJzYKgjm1Nfj>n0(luYD@v+ou!imF?zIcn zGW<6}qjBaRv#-V30QM2AjB^ukZQAL|*Mk#qu^wbTKKX7_Y@X4_INk+v1{I**qROCxR~R`NI1~Ms@;kLAJH-;6MB?N;mZd?U62wI}&0$-fG^5Kc~pi z>D=juZm#~5tO)0!@ekS~Vu!GIg^rcq>Px!@OOJ=$c>#AV2-l=(9oz$15Bn|?#~J2y zyQHha+VDH_U~4~XBj?GAxC5e?^^EeX{k7aT_+8?gk94iWmNLEy+SPvF0`R?t=O;YS zQAt<2ui^DBJNmlc?$lYel7#=iql4znHak%lG`ldU3`r&BiBV|8t*M-k*7NzCWv@y&wLoQu>Fjz4Ny3 zT+TT=aO|TVqi@9aJB7LgUsa#Y%b%K_vSJVL3bxnh+tEe98U@zHz`Y1q1zU~a_4~{@ zqx4xRE2JkXweyS~GI&*}Q|Drnud+IkQ{utC%(Xr6U)0y)&XJnYvOO<7YDY^0z|XhN z_8nx*$0@hepJ#jo6oA9+t06x9H5-nebmF5igEtTrT}GM03GhQr6}U0ZdpD8 z8avcyXaqZ;ZL`7Oy_`>IWY2EZCec84Y&Cs<2pkslu!gN)&6=^Nwe55EGE^?*Jhp?p zrhN1|GszqBx#`r7sr<92{a$(6SIv6h4dnEOx4M>n4$T(PA08bR$euTJF|=zN{}CE{ z2e6y);?4NEBxvGo>~=)6bbMi<3hil;+h|Y$1dvQ7+(#3k^)N>&b`r$wA!-?nUoLNx@ zvgLiDIUgKbdG$s2gyv*^RqF{mmTTMLtQ=RyDC!>wcXmB@hv@6Z)w_nygZJm24$nj1 zG=Owpq*%j>df{IcUzerD_&T6(>5C1ExkF%Lx4V97{7x92_Fm!X{UWP@4H_L@uyEt3 zny=N2zBXX3t2+-q%zLMAV8=#$rWT!57R|B)O;0eNNN&itb7mq#PAXz7;zuJKz@Dsk znH5>I4D2LjlZ9kw=vQ&Ymgx1l-^2tV?*v}oNiYeP{Wxv6e3e4DaV$J6M2 zRMwN{S@FARQ{C0HiE`^MwBlzb(zKu-EGEqX=;O(+S@A`eGA>E8=wkG4UVGA<$ah8a zerveOtD9g+Kb$clA70?5d8}|(VdPt+v3%C>;F_}NlR*o;;h&b*UB_Mk=UiJJ2Yo5_Eja6J9mHA@TU!Zx%6i4eHfzq(oft4 zB^mLP8yRQNvt6_5>ZWhNgV8A%dC0fw>NH?#=6}(kiRPZ?#mtM`u@%fBPW?S{>8>>F ztBh?7HpXFVIOp8)zuTN%Gurc)e30_n2g85tOZL`+udcyXoV&LAA|JD#>7-=Ymt2)! z0A0{`$WXyW&_(jhs*%Nkl!>^2-TuqqTw&_XegFX;ln7Xap$aG-s?fpNN8}aimUgncsPi1k$ z53H=a-1I*g9eIQJ9NH@xmy7Adb7Hpvv(DJ*t_Yot_3jjc7L1ICpYeKA-kZe+KW&t$ zJN~>q2I;6&j;BX=KHxk9_XZu~j^x9q=)ove!tbaJi=7y~`6VKeUQdCkv{89z?JiGeM7)zLuz8K=LM_v`}v zX3z(Z7H(g@7@ywN__)RIU2KY7yr+zLvpRWmUeVi5|L8;T)*GrC)*jTl)|ok-b^gm2 zqXS_JAH!oLfS=p3H)6+xM9Uj;IG-&Kb)JuUn}3Pzom@W zYuXnAe=0M1&YXtgURK}5M|)i$-2GHIyY07TF7j|10++g9$f;-ULq-su%^DGzz_ZzR zhPgVWq9kPE39O-zjjLBzaPMY5eV#9S@Vysc&r?+{S;6UOh2K|QfQ(F9&ccKzaGzeF zZ>S^%S}0ECegu4z6f-yIE`UMcRK4m#!Ndh8*^)B40u7oqvgQ(B7D}(%9DmchCJ0{Y*dfy6|lM zYwgoWnA*LN{FU&c@nc;+q49m`Sm{azcJ`$Wx*yja$F5(di)dprvW`10T|Y_KWCf34 zM?#y{NoVGrGwz<|P$GO4eRXv1Yth5}%f6_4+3whM&%2^ujrgJCDxI3VJqRiUm@Lcu?38P=SpGkuc8v7GZx8smTeJ#7?wd!Zup#4P~o3Zc<=#%-b z!3U;vZuWedPwe*19$KA0huSMq(rgALO%kD{KKe~)HHu&+z z#`m|#RyHFRC2TYHPSwbCb*!~(%DIbgffe!9T9E^+hnb7(SApBLq&vtQ;jmAg0_;jB z+nH%RgGf_=J+($H= z>MxxEFm@KCSGy}H``8qhw*ExgWk93X*i5(1|?@ z-mL+>uJL%1#@YpxCmd)_k&Wau;Kgn+)`#%O# zTg$o2&^^<1x348hXZ|a{WU1<&NFF|LaIN9NP0k0Q#61>#e_Y`>7QE&aU(Z+sK@TPWy*Wj@Bn9;Ge z`ZB>~M(n^7Mo&t6o!ATLp}PFCzwbl;okqW<(Qkd}w|>lp>1K~t@|EicO0?{YIX`mk zHpK_=NA*Gh^1bt9g|Ypg&z`e|?p^z7)_FBoFM2|{T-S#s`?1Du_7HLRKIrQ5#*N;U z)^#i;+O@iOw1B)_t4}j~hh3}tnf}^5iul!;QPtITf1haAcP-w1qg@Z_oe}N&G4J2$ zJ3HF-66?6V<#FyRG4?^q6MzRYkLcdT`U;Ktz7=uqJ2)P{>kVJTM;v#@tV zWh?jB(Gf3P<%t)tMt-btKvHBzq8#a?j4rUUU*ubfFyT)5Y{tE@Qvj#V3+3_s=r~lz zX3m&aQ(h~&V%>41w8Fbx653EiIxo!@(y076aT i|bj>4CnmTN?)$oms)%8oQ5s% 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 literal 0 HcmV?d00001 diff --git a/app/src/main/assets/lspatch/so/armeabi-v7a/liblspatch.so b/app/src/main/assets/lspatch/so/armeabi-v7a/liblspatch.so new file mode 100644 index 0000000000000000000000000000000000000000..e9a142602502272651bac684f1c439cabea04b1b GIT binary patch literal 319144 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%0DFvv3 zKH;U5f`qPptJu~lE_v3Z?l`&IB|sf`-HiZ zY^;UJOB9*O%vct`r`vTE6Ai<@&*f=P>B{9Tl3J4;V786EcAEMse{xM~!$sIhoZmyo+-FDn-d|j?q0nuAc6I%7 z%blyv-b2#Py$zi*{g*<{$g@{h-!_FI=PY*Ym*0#Fv5m%LITh)PN9195oyNi|U`1rYXpVsumO*}420TS+`cFiq%LKZ% z*EbF_TDm{_qlgCsV(azge25knu5YLk3ygLlVSPVgnk`NkSo3P~QPEaM4Dm0b#BpRq z?g2^z4oaaE?3V-Ms#kNcs~u0WWJf6EVzVD^)q{hJwWzl3I%|i`I`xkS8K&nuF>b4} zI@VjjD5|*)30uu6bO#$-HgGFb4T@0gS4XX7f1vh-LXL|WoqL#mCl>qX=$D>KUCl9F z#~+|&7720K<5VS;`Zh}4+o_Psl~>0@%9DWSaH+8GU8c7%Z>ub`1alh2)gPgBYDKjj zULvr;3^2OFta6w?pkG1@4pf47R8^~lLye5SO3c%-`h>T5YMHx8^%e&&hy|={ecW5@ z`hjmT>&?jw`gImcdjX|>2f1Th_1bn?*Ij2#x#8Tpuzjwc;C$*n>HUv>D!r$2y;#_% z_JhvrqQzye?}hF%83;M^HjST3aN4s51 zvJe;7LuLIG_dA;?OyfWg65d*7?yl14tksS8Kn6fOQ$&gdfAU=$g7rI}4$o>@!svhU zy%@A1){nh`w3Hwuk=QlPXH~G&67A}G+m}j})0T#v9PiS7r^NG5k-2)USv+El+GV1I zZj;I^wZ@-(-=QR`1Nq6q>d(^%?Kf=zYdmufhwbDjvRUe=>`TYF`)TIf2mkt~l z(iB(BL9$4Fbfk-H?Q7PTAx}LDzYt$3nN8F`gvvQpMY5BfBh!gK{eG;n1h)Do-wS~u z&G-H*5Xy%|;-{#4z6$h>$E2nlURalt;kg4AUKG3jo zud^FIf7%1s3)mk$q7XFMvO_jP_kL(y{k^LA_r>)i+wW!O3AzdRV)_kg=q`RK5r`)yWvg5A)AUwWdY>SY3d~7M z8GI^IiL|VOdJIYOFdXMxpfabGCR4A2zm8?{sP**!yf3rYcj^+oaj(zvJNo=y-vsFM ze;$0P-Rz|{%YNT^Nt^#a*)02g$1c(1_wAs{~ST{m}YQ9zeDd&}z-?`$LfPYmL|=8nj~`*d-et zPs#Q(=T&}!h7PO8gOkO0fKLDo&=*lRRPfE@~8XQ4Q;0yU4}HckA6;z_fVP3@AyBkQU3?|;9#j1GY-CF>?L{7RG6@n0Y0YEB};I!13u1FP6gx=)E=Dn zB=mWrQm}zyUQO}@pYO)gzqSfb_iSvYb}8#fx@X<#uuXWIZ=%1=H%;0nAGQha_5D$t z3;oJPoA7kc3V3`_|WLMochexibb9jJcB^C00AAGvD=)F`ri&X@g#_%j2BlOK< z=ovAOO|UTR^?e&;Hx&VMWMGbb7Q`G*RHYJxboAkT=mV7JTi-`LCQ_q0^MU+<~u z^{qtx?t`C*=sli(-)>;{u(vxoR#(Hx@E%we`bq9Eut>o)(tu;Q?ihYya#)RcMb&};{#eSx_v)SC!?bO!kvq5LGUpn*8RO3MS@5xB; zgv{8pI184%NxM4Pu`w;WCh*l9o(t~vY?R5|`{qyzhk^WOgG^SYi=(4L`8YZ%<&vK? zqQ|JtrK5@x5|A@vT%+u~y+1<3wqTTrOFlzhhEXNVNGfH+nCeZ^m{NOK;GUB0=TlZH zg;PcADbJzj(<>~4gohjtRM%8LxPJNDy0Nnzdpk=L_jcZ&RD!1*JdME9%%tqMWzXxz zs_>kZ1PVD(UavFC9b0N%-wdlk$g4N6S3!P8MiTD_cEFK0mT#xNvMDqf?vHVE3=MtN zoxPob4HFqopSJlatwcP|Zn}F?-6DU7zN0&_UiFuO-XWeH-L%~AL7$auqm+MZcNmAf z*$vOvqmrFQLFQoiH#YAqU{MphGV|c_`jWR~weU^W&DN?c#L)i;a>JsW$@>!b<-irc z^u8fUV^l}7>ow4~o$ehBx`~E5d$-h>l=6c#M}FEH@F?I69u;eLP)Xp*qcrx7T2m@x zq$QCo)7igcFRb6E?Onb-_WUaqB+~$U{Wo4Ao}rMPl@ET>toea@34xbhX7>%S-NF}k z_A(RP?X->zT2tRmb%!6=)gw)wuk1AK8>sUn>I*5&sDI=C;q6V}o2t_O@pH2`Z6RHN z(lzMno1r=Kn#+8{A zm=RIl3F=H}BXG-hZ__2e?{m{aVZ_(@eBS>bK50(QJ?GrBpXWTw_W^bo;>>h6ZaBTy zl`v!UU^_SraZ@Pv(i?JffNDp)0Q;F$m-YU=u#u*7H>MS7OcNDk%Au{Vc{T^ZvP3*< z9aI|`6QFj7Xe4epTmH6oo2qLpz73TEi5Ks5Z-54HZM4es@Y@r&Hb4WGP{(lhX?4N! zo!+pwRb8z?n9z|%w{EB|OWlAu0WBMuGpnkfb(p>@FYfhyzS0v{w@*{PuWDz*j`$+| zpWFWT0Hre=DKCya+TBZi&`XaU-QX$h!8bVCw87LSO>BE>&4y}|Kx1NZKIWe&+O*Hf z3FVcI6So*GG+$Wz!?l^v_+jE{nOQ%t&bPJcq9U%%jN;oH6a4{s@OP|7#tLEud> z@e7%HAh{7e?9TFYBf3Y0Mv=y)#BYK&Pf=r@*;Glh<=R8k^N~3*$`6EH!^0bin%f}5 z)(lqT1{a};UAi8UG4H9r3gwB)YEafl=;DZ6E34MgynpuJ3(hWk`;O+%D;Jzy@b+Th zIt59W}mT5TdPyh)CU1ceIh;&;}eTDuFyhS!VU-TW4`4^Boz3&>}IGb>(=FXvaV22xqXP4Abgh8D7$Uy<>~$3cYI!dJwHWA z;}6Jg(?hA66I;h^vABn`gDV@1@Kkj#urc_e7$Vh^&EdxA!tuZ80t59&Dm zK`Kqh@8pjJG=9#a!hD6^4L`kE#}qtW8@I+?{CT~B*Age;g_kgPz|#R;3Y%Zd-nc`N z-Evcic2AnCUt?v{w*fb2TKi|d2Wsm88(+Cw+)*Y_%h3zvYm*9vw4x1;w8pi>33~W- zM-IOeR`*ea%rr`q|GFdQ=p;GQ$&D_TvnshU?>o*x-T~Pq&K+_0OAZceLEKF-pDQu{ z9o3w83DpdaFet!FZ7D5cs6Jv#Np$ni$0Ky}Ptq$LKS^(QT(qTZlMaMZp>ss{)+pe0 zvK)iw0bYgkh-H}tv&AmwKq^JLP0#``b0a}fCL|Tc6&eapLGO-ss!7;4X{Ibt_$9NU zX&31~y?i$?>&$!+{t~Z(ZfK_YNW(-=(7<`)-x2CtzCudma^M0|nbEU8C3(*cI%gRw+rbDM0z0 zGU|)y=JIQpalh?mL#d$W1&N9sT65sF4o-$VpQ$DE1Q4OZ=!J5nof9{sojzIP(kr{) z)AGdTQXr^sE7@|wHzKYN-PCCQm!Wq)Egp8{sGQm`1J(tqQLr%J{>{_rm~?c8oL!m5 z|6bM%zKIXCscw0zO*IhxbIXCG!Tj`~UghP>VRu1R7aBJ=R=fPi0Ov7Vm|&L&+saX= zYr?P^jQ(o?t1J2wo_VT@ZAb8q^&5lH4Db2j_dLDVUYvYnhHQp)$qadbZ3_Qmo4)w< zHvP4DQ*lDjsD6!qv;g)Uy~zG!zijez*K1dBwp{*)3vbJd3SJV{I--0UC(C})3EhDaE1jhA8M#;U4Q{~C)|hJ{5!KKLAC(S*~ zv%e{QQ>r_u_7HB?g!XUR7V~y4@4mHtRptY@(T5TXM81nFIQx98;rO zjDPBOalR3Jy` z?YBTwrS2d<1uKpx!>)zuk1`!bq<*D66*_(B#YCbVKXt;2q|Z;7WwRP8cVmw;FLxNe zD-;rnsvVjmOjw#+E?XEdAkBm}g%JYcJGau|O#`Eh8~rbEgG`@tt409PDbdSq3`DC7zJj#MV44ef=@UzTnxq#wHG@7jq4OCjz~myDHwNx+==| zcOm{&HuUrQtN6Z<4;a4t*rEHL_QXs`2%wWJkN5v6eE`n};~sI%9nDLM^@rYt^(W>` zFFJLG#pwKh7wCIv3i#W9ex#@o9MGkLZaL_V0!Rut^^5!EY`=cxe&D-8R$yUQK?Z1w zUd{f#z|m^ZX3fuqtRU+yXzgjT&L%x4n;Y(Ej+sfk{pGm5k+dL=_{QP~vd&ME-*nu( zNmj5+R-~F$Xxk-Hf@l6uqy(MPhW1gABYxWcTciZ9|3)c6r}UUost2Y1b}7MQij<&J zS_3QQ|2ruGxH12Qlt2gWc*Lj0FUbi)(!vgs6J%DHpCCB_FaTTE|AL&LO`05roL~XT z2||+4VZJXHBO2=HmJ@W#BzoFpZSP@|HS;&xDz!<`m+%wXq*+(sC$vdZ!B5DH`ZXSI zNJ;?q0pU(?!Xg2!y8`Y+ND8<2w8iS?;kHSKJ1@nZz?{9n!_`0wD#F9v#V)K3GV);}Xomkn|q-kaQwkjwun6HrBKHFJYH(sSVhr{6nB)wEtHA zVH-4Hew}~VDeY?it^7m6Rq5s*(ppFVb@2~F(h6Ae*wITxu#V~G6kg;X!p27Kj=kd} z>bJio^?^1E5F&7@wF9F>hg4DGW)f zEB5obk6HaJ=sxwt#86}q7cenG(sl*2jxaGo($=<~mTQEG5t3eSyA%_nOmS?p}{p68eGE~U+~8ABk-O? zrFN%2cJlT39`XGD{0 zQSn$GQMbIe2>L}!p~*#P8Hy%XG85DdG9J4DbgDW{iVoM(O&ZS_tm$5m1_cA8UmKFL z+ZnJfXzZgu2!{(lQ}nnB3HLUle?SO$_dx$(=P&3V^!)|>gHads4<^d|mGln=T+lyw zWLS1y(Y>JPRBs!uZP1iJCx)~TMmtHCV_em(gD`}}{E7}jb`Ko{RhJGzy{uPs5JJ*v z=Y^|1`#;q} zxc$GPFEk2$anUY1g8g*SDmo-hB8}55Za__iWdY{A&WhF3Ci%ja`!4DuB&dkDMLJ;_ z&_`G)XPeY7sj?V%&sy*+7-_j}M9xBf<2BP9L3?b5w^2xihRpNSbC z!S0Fuy8Sm0@8sWZ{~eO{!D|NS{Vt7+Zu{>xX-T>Qy^_E6tH}S^v(zf;>JX&4E1r7U)W#t-xj{9>x-UO1<%rT0*0z zOJ`S$88Jv6n09x?<<{qRMH+3oM0%M3{mKMYn{*y?2fJkz?SYZL)ItV7b|KMkeL*jP zwwIr;KHBu`z;ZgXT7 z{&UDMGeNPHE0Xv&Nfn|V(<;(-Dvyxp;Y|a1Cqs%EiD&iSZU3!(x!@ArhLH4+E7-(` zq%U9-Z-gA|*KFcjVawfZ6WGQ=nnEp;tGW6m5ZC zwBie3FSt|1Gixc?j1D)hAc?BM4lQREQ)}30+@yl03f86tNSUgr&7|v5hP506J1#?( zemQwg)tXl zbldMuWw7DT$H<5~wDX2e2pZ-W{WN39O@A)BMb37Pv~Sb&a`N+Z;tjfM)O_=k#j(z( zlwZZoPxXm)X5IAJyg$Qt>J9qql=N)iIeV-#qbv6|Xc=(>cXQDB{!<@kFX7|D_s&h5 zXsCCM?Bg7_#037D_MGdFeVn!d1@m;x%ej~VxkYi#ClT(`heG@2nTraVUy6&lu}U1o zk(GOPd6PZPsUG*OorAWsp@?)57z?{%(D(1b9{pW>p2f$BkGw;VI{=-5F_?|;y5}7w zJlOw}CN}F?C+URAzu0SG>2Y`rxl*q|;(J-IMSR_SuAJ%Vyc_yL47iSC8uKx`{o$S4 zSx(7IBe42)IAvXx&`T}{kFdqW!OqxKS48%=nCEjVkouotji;o#FbQ6KxL)vw_)XIL z4i7AX-gk^W{DYu(_7$!!N^q)y2KkI*^Z`o+ag8lSONvJ{PEX~WCRk3IoWn?WTpTW= zjQD6FsVG74IJj?FPNqLgFgX1}$~>*W4IWvfb($KZg?QmbN6dlj3PVt*f;6;vNYQH! zP2+8;MknaDJkH7G==?tl?{;L;qRQAvf$f;W-$zFn`I6|J(Y@i(aNy`!F$fNK;OtL1x}xAisR0?<~HEFvLpj5 z708>pQH{`a$+GYb@bN^qtY}%aR_jL`wDZgum1DrNCu>)t+?Lg0Z;i*zvNqF_hJGF* zn>^aLRa=H7k;VXd{t4498FCrz8U}d)6LYcOs^WFHLmT36#J)(k*AW!Q?QkHD`=OD_ zBGeM(<37jDE`shs{+jGUzSk@eB77@u4Nif}cVagouT413JfvAahjw?{HuN-fQ&Y(E z?T=vzNED1Cxf`wMr|Z_iCk19*eAKX1pK(}{Z^kgSFB2Lj1Bdl$)NGw$A+*%b!!7U7 z_ueo`z9=v4lCi_IjSmj^Iq<-M=D@=Pjt9cSw1?p}B8#|;Ir0hUPSgeaPSis3_D3bI zME)^ggWm~CHC2fb~#fJ4t z{*!3$4omaH@Oz*o-w0NW#CKui_)V#XYR>$45hwQ6t^3_Dct?nWcLemOjXWeo`uuiz z!R{abLGskg%bn6yZh4s7O8yb3)Vgrg_(5rgYV|Lc3U49slR&zi3wA$;GKuD-T5EdL zHn*$PoUm%Ep{vvF3|*TU3Sye@}m%MZ+)k*C|UMwqNuyDodsg z^~)E1-kQZj$KiKIGIVHaWhow%O$68f?9PtxHqeQ6m?sh6xw5qSl5&1-zqFh>rJSGI zshpGGeMQRIf^zOr=uI}D7%TWGC+}2Q*nDO+;}nPd8(yib{J))*yQ6_pGS0h47!6Or z(0dRL$?Q{-(mLV&x3a`wIU}io4+L*D<_z(8_@Y-T@MebqLlAvxuo;}RU*3%0ksQq* zr^06u%Qgt$!fxshFV}x-!?_1K!GaSN5=*7rZ$9oW_oGY79d=o{=@-iV_+!*VFp9Np z5j$DeZmQq*3*~q&DaUwOIibPb^;`3C-415P`Bw}de<6k$I|!6Ep-i!zr1L`@Z}Mvg zoC#1sw3m=9oOTEDX*ULb3)5Py-eW?4uc2stg*{n@t-8Fs;I#JUJTGjx#;Aghcy3g3 zkrXiTfN)SZ@JKp zYd(gLLu$vpEL$Z`4rv9_YzO~HTmn1gCZ&EGD~gh_hOD zUpn~>_QP&JV!f~M6HX7g(Xed^JZOW0f#rDyY^l#mH=jBxmugrJ;$~$L0u3k{vnKZ3 zVsJjQ6Jueys_H|sbB&g*)?sdMY1exSa7K=tQp#tD{Ha)!iaX3A@^}u)!hKNQTX50i zd2h5Tb$8Ew?vR}CxVY2xTwj4u&viPst>^m65ZNhOrz6^EeO-^8CbGUJ?C1#VKJ36= zkvu`m&o44RT7TyD7s!9bNN;i}gU0Rd29Mr%{{m@ zdG)-aRClk{xyoK(a$A*ejoV<(0+y%2ZL=l1v(fsnRMe3LjXbOO2Z7_sPw{{bJ^z+d zQ!7ck+QMGV+e8E9qqiRmaoci%GipQl;Si)w;MN_(J_s$!mQ;jR02@0DzX72*3Qdj&SW?I>PbjyMJ3%?0I0B+_zB0 zR&Iyw(x-GbKU;@$9qWhe&NbUo%5wR~;NOvnV`V*jEius}>tE@I*6AQC%@Es9FxbEn znhx284{eS1=9rlsNEw6q%0;(uc2KPJf` z4u8*uV!$Ojw5cO}wo1i9?{tKpM|j9}G`2X8u@@ba9PQ+%msu7H&}fb$Ypg2gYfc(3 z()&t9tr*s1l(3{k%O}&Xd65~Z^`(t7Lnr*0^mb^$?nFHKLHake=Fa%IZSfct8zg&! zVUtDe8`0Y9Mvi|1_wr+sCuGCl+E8?9E+4JTMJ8m3vra@QC1kW74BUpgGJO8+QnB<8 zI>I~gT{lR@&i7KWHxT}be(#8x2knfkM3K{K>Sr0or=s@5>vkJ>i`TV-6YuCG-)A-0 z#eE-MoVny3xjV&87gE%JNOQBjfNo_T#WFNQ9DO1VGb(fb%!-4sJey>I#Hn`(xd+uvM3QbFz?vQL~AnpXAY>_84vA|i9gt~Uyq?LTpZIgCPdbN|) zzfd31tz+~0@R>q`J`;Dpnifvyd&f|39I(UD>)SgKYpCCIhF3H5rj&?1nHriu$D~EA zCjTD&n}VVKp41%03hk`)_0Q&c4SHR@05zPufgV#i^`hMvAs=RlfBjj7SxDX+Ne}9i z`c&{d$^;EiPD!g#g3iyC_tiIlj_j*3Kpdi-l|0~f?W>pVsOnJ99d+%`7k5+*e5iBo zL-LHm8t8Hom7`Yn)1H3dWof+JbKk6yFWooq`kD4kk4*dKYsekhHxuhR!hgly=_ma! z=u$_^%hB-|k7 z)VM3CYk^}qnt|WPAo(Y} z#;vaDH#YIpCzN8JnO~I4*OWxTE|$Khj*DtZVviOXF{Zoa$u~y9m%$TVDaI-(CL*r% zLfjN3Zai{1yK=oImm;WDT)y1z7V%oiL+0D#=c=9bO!N>#`(?f1&+R5*1Tc;6IwxoZtOB$1 zI>9Lrt$ALq0XL?`84c9D_XF(_j4zEJmw-L_QH4VAG{-6ZJGC>S zow*a^QH#&)zjlO=?hA+C$GLa%?T+w`_??G+x)kg0_RY92KCWU5Ku_@ac1EdKDZU%< zsl#rg#i?Kp#n=cBBNf`z5ro7Tn_qerNGWtb@Jnmz>2$IS4DxZJ96s8?2}u*4so*wd z@}3ft7b{@I0Dla6;Oo|eG7gmIV?|4xhT-6#nN85Wvm^R%8<5l;>aIxmDn*CFuz0ua9=?7{_#G72Echik-&yGJMnCO?Qyd2; zG8^Fam<227+}EJvsma&}uGVnxptNO9W+5)cdeEuXG%NlNLcYop4c67OJD1=l1bRw< zPC?j-zfzdald$w>wA>00ye9h@=~0|eoDkY6PvY#i8|W@b-~o=5WJwjlKQF z!ilb5{e4x*Sr0|{{oF$wKe+N(pmKMn0DqX^sgSqTHw4Thi{&98H#`)v88Gcsp2NC; z0r~PjpU3SiKwBJ6mDlYw?N}%*b0+YnuWG;(OW^xEtDFW<9Gp-F3iC=SN|7Scf6QXJ zFupWDE{&y8y%?M1ohd|lGsJhAA~Y!WHc&lLV((7ob?w%IveTCJRVX{67bGbTwum2W z>m%9ZtJ^g&Um7dA4k6Pa)LtteGi&QlG@}%X*5QqIA7L5cJ;r!g@!0u-@uQXY zJte19f4d!A6!E$+YSz9alh zC7og60=c?bG-&Y^L1N@bW;nf~;0G#)Rm|^T3a?Fa5V_gi#>CVKLWCjFy-KJcH!~AEApCoGlya~Du(<(k0>Pcg#i|>FpAOS^`ZqOoDScDf`hxvRT z?vKzpUeW!w0`NncK0Kq&F|C&wVFpPhF?fr&g&C_(1h$)aMBHYVs9$@!j;+HPdv}QQ#z1@6JNlLin-NI$>9-_S4sl5BX3-5m8^^WlG@$SnD4Jz79tq&KjpB6q(e zwCe!&S>VSNcL>Tm9=!05cd>^*fOnAh zLZIq&&2!!6zI?B*QtS1?$J1|z)UxMHPYMa>S5B6dv5fHCCFy97yR9S*zwF)TakrJE zLCU*FTzGdr-hCST3v8QiG?qqBcmhbsiQGKgax$^s?)_O`3L8K8&?4SoojqOb2c5Z{ zb5yM5d^r432glCgTjL-4FOBcUA7afl$G}|)GSe&g{oD^4@s*!AHtENQ7#lqYX4@Pq zKXxC&roYWO7I(v(V==Zuzi$5vKd3*M;9rCfv(@~V8ougSRqyg+s=P&+RlV(I4q*;q z4&ka^h#!vlUWiASLzqLjDi-lqBR&@K2y+N?2v@}*egxuU5RWj2Fo$qeG~!1hJ{s`| za|m+?R~Zq14dRW6N0>vHL%1pm@z)|g3h@YY2y+Nm84#b3cmv`Q<`Cu(uF@lZ6yo)W zN0>vHL%2$Z_|b^hAs%54VGiLcE#k)@UW<5yIfOZct2Broi+By<5#|u)5Ux^}A9L9d zuSPt=c7!>Et5oI3%oMLeJi;c5N4SbBKW3nK4)F+UC?4S|jE9Qi8R8M~*OYyYKY zHOJC178GWz=0_!r@nN=w|BA%d{CISKxVcN-xRH3db7ht@fNzl3mfvNumF{g)PvvFL z9ebO!<-`F!BfT4>8|z9ZVWTl?fzL9pMnRWx!e2wWc+=0sAIU!oT+vLdvjOR1ub(+^ zL!2|CzGo|S=8SQDvNF23kw3J~tYBs?lcTflmUQuO&_C0P`Pv>lRzZ{j3)Rf_d;PP0 zkUleUW2nx%Qg*WS4>Ty;w3*-tSb%$d0=&+DISqa)T{|u=OWRfYcB~FU_&Ibk9PYKQ zBis!B&;9s*s(Vk4*Wh0Kw6d!a9l!P5)F(9jp3*(z=yr?!G03b@@G_WM1q8kUtR*H& z18fCns?I%i>qp>E)9syZ@whcY7ZJKEEA{TEHCFNuIX9A0@uwR;JvxE z!06RxX+2*wv3tId4Ukj}bv`E#ahf)!i*E!=p*!lAidyxag~fdjz-t3Dwj}A7!8YaS z31jq^;MjhP&zC3E(cdEOOK8q_m$S&f3D%rR7LEIy^!X{*jU}nj4?5lIBE;P!OAVf> z@#LdZkB@slXz!h0U!qtxE^%04+g9SGwEuGHgC(qirHg$-io`Zpq@lOrO=frx(Be%? zP-9mWJX?@I3DhVh_rW=0KW^U%ma-3Zx^Lz=Y1t_jv_qdX)vXOSaGK@E7G6MeZ5=lwz%qFwg!e zJsD0KAqA+0`sxp1kDx`rP|13Cdi^wBU42?=l#j}$I@Q`z{-4qV;Scz!TT=p2o^ZcVemqCQ8Uc5WgGPpE;)4ZaAus&eDV;cwE^gI5~MN^C8 zeb%%*rL?}y25-{HbAcPZQ{|WxJGhB4rd*75xyNS{Q2dM@HM+S!mIK973kMW@NaH^6^6E0O9x+2?!bjxFO#zog4P*nT@(1hi6mFU zjUTn?DOtmsn1vNvI|kHtd*?-NaJsmvshb-d@m&Xs_rAZ&N$zL(lBCk-dp$pA7Wv}P zV+>gZyq_BW-V|+Ax!Ewn`kyBhq#JWH59bT^BJzf!yS;3|LksBN^{fyQhjj5DO-Z{5 z%W7X!UrvR4>3zNr(DN0({L-poRsA>cVObO8qW0l^clbw)TjH3}m|syYN1LX>XQ@fE z@m`0}eD5M*pX{MeSW#{`vRyRbpIC$9F-? zs>Z^j#x-xx+9yw_5$--MwV$%yWh5JHJQMDW_UBhjgP%S_%D$!)6AM16+J9Ro`p7InC(Z@dn7JAKq)ITcpuCL_y%4!GM;6t!BnLIWxFB$Rci!%z*~ zrHuadql(s_bM=E1z|D;`Sf>Cj9W?gP$+za@-fo%5^ms;m^>i_@Nyi_5M;Bz}diVDM z8`h1jEL&MOTK_Qo8df%-YZcuLWX-&?WYC%U{vpcu2>;-+UifYEoB4QgqimbEz?xcL zIj`8N_0`RrfUr1^w+?OOwvdF{j8*Z+jdpXVZe!PhJF)P^wXN4 z)};7udD_3D8ai8yGc-p0w{(J^8PQ{au8R3t$aLh1PtIXOOMOdmw{)5GJj-?XUIyPJ zgMHIv8Q})@hbjcVUPyfgaq2a8M>Eq+Y`)zTmVRoU0?Tfjz0Q%_Na(#`=}7Z8^0O>7 zhb+F`j`V|1v2W0VZ?Gz=rdKsbtGGdNhd=tm6nOwcJG54`V`W!61|j#xuzgn~t>&69 z^#AfvTjUos!KWCtMJ7D>iG&1!J1{eOwF(c$`3Gig_0`b* z8bw%nN%d&c0G4CE|4GMB2WI}^_4}9fUpjqEk?QgOMVjR*u{Q_n?p(v+Dk0CS27hWg zPiXdZ>oHx!jr=h{T5UwFr?oPV8R(Q6W}cf0-U?}`vG}m`E;zL-Sp`z8ZPm1RxGG04 z_*rpP*ahOZXuDFa4{N(p?SL+@w#CD0fIk2!P`n~HgcYR8TZ26CS#SPG(T`c~7>jZU zUyE6Arxstn;CDy4Lslet)5Ppk%xs?NhtAQ=iZt=2Q&bZszAbAo%l|29pqWFQ<9|xw z4=cf6j|IME82I6~UE~*<^o+yOr{Hx~0>hGi5w|uht*94wD7*TWUhue%ePE^;9I4aN zyC)6>0_Y z#oHo@?KMKJlbH{JCIC$lZFbe|CJaGqJ?RH7VQJzQ7=zj1sU-kkgu`u^p{I4A)yTGY zYUm?yP9_K|9fpH%B(H_vqAcLB#1%nWoM2L9gPqby;DfHm`A2mRNk4Tslsj?(w41u` z?vHxuZW)EUWmswr&xDjd44xcX1Fn6Yy+v9F5A!4~=V~KZ{+tJM1sD@l7kC*Yp8SCP zUFd}biYb;k54VaNFkr6PNqmV((BXrpPCnI4e8JvnX`-{^FTe#fL0^;f#7kw)Yy{zE4LUm`NrIWda{mpv zW|+0pSFm+h@cVdl+2?a1br+DHA-i~pUM?ziNNE-ZZ+X4aVcA-rbfP~midbdS{hWRw|} z{$2l{Ix|DPNs7))hg8!U2g&WcUEG#Fn6rexzpfLv6X?stW7Iof-%W9EcJ{`vh|Y{( zT7a{%r_M~8*z1H1)Y*RdK;RuG?$_Uk!#ACT%pPF|2V5?EKZwu#9Vs_yKH3VLZu$FI_cN^-QZ4Q2lY#%QIqeXy@OaTqQ8?S zehyv%-Ee$?L3rogsLP%c9GkCGF*A$*(aaq2lUPmMCmA(yxC_QHcJq&B+pPGwt83zH zszq^=;+6PgwBNpk{g%Pr!vmf(_T4PvHi0g)b2hUu!{?Jdh#^f%9sjvGO^k161Bo{c zj^pZNadK;eytk5N9vj!tH1to87B$EpRW>vYp8G%eJy7}m27X)q)XlRkn7I4<2#!nSp6n6|sf9m=o1?t%DiuwWGdKLq+?K)I@OgXyhA&Gn<}sBfksudzEFXs&R4+pm*+6YLYKZLW+E(pt!FylRWTl z=VleYCQ~Wx05q2QB>m0w$v+RzSGdYiK?8di^1pI$HTb?C-(y#SCIub(JDhF* z*>{>N)Gz5(wMhN)MAHrrTyCl4}cDm zr_{U=WX8APrOj3GP+JbMR`>mkWNv65WhT6A!n7L!e1|HNkBRe#vrp4fvPw?gzF*reirR z-PY{B-aS$Z^nJx8E_We6iw?3l=zWXdb}aEz4#aUuuSRiEL6$`CfWMTQ^+DF>I&Y~` zLVmORI_Pploez8_J6+nfeP6lXZ--aW7r3+1kW=2981AE38AiM}>CfO=7&Q}$?LI@$ zs3q=uU5OSqaBw6z3MC)1d`T2f9v) zy&s|bmC!td=HdBZJYS6PV#FF-+{ObNFZ2f7H+oe(WBTH!8VBDwT~vEmMQ5r3WPo{3_h^?t%}~RF+(uuw38bf-H1@ zQ!^&_RQaM87c4y9?{P zoLB8+`R(Sa`*U|56{HAYP*Y{Yac%gyzPvm_Yp z_dI+ju4LjL+O(0{MJKwW-9~qRa2g)*8P~CFma`4=9XodSe}pte@JYack!Pphe+?ax zlS~CT0l1Mr2Poy{;z-I*l$6;QQtm=Z+l7?T>sSuUe$z1kKCY+L+4;jIT9i8$sk6)J z*AclCX^|UY6Z#bhtf<=&d5RLtjW~w;>fF@NxcujTWZRSB2@rUeRrpY;iJlrqvajzt zJI!E}>g+1D4yE4TRchTOrOvxhYHzd|_>-Cr^E+XABKFe%`MHSEDMe=(op!J)5Te%5*+{Dg=kp#=tR;zV zAR`JaGj27}0CbkcyAyz|$;4{cVbELqBy*B<`1# zBa(U@xc^qXkAW_$gJ+?d55Sq1Vab{P9m0r(cV`~XmWdu9_IY!;@2PN0whNV9}tI197{kfqmB|Hgv?BKm{& z2b-YHRK22{^5}DLaS@ZtC%&QsO|ug*gO!+Ws)U|((;qA=N};4uJ?MM1y^otC8qSqm z>neW8XM>(C&R>jgq~EzX8t1N&$?kh$WU7>rS4QIIiz#bqM0PCXHy2xc-!*X<4TH~- zOfA4TJY++Efpg+#18sX;Sf=d6C7x{`kDXy!y}3T$4qy^QaR9w!Qs zT1k`?^|#aAN9k`H^|xjeZll!xS*fGIXNj~w(jVPzCYqJnVQA4X>eZ)EvOcrVD=N^# zI~~+pRC0G8rFv?;z&_Mi1iMh`Q1g*>@Y$OU|_U<{IGONw20ET?L+vMK-${- zz3H!PAPqO11swR^iPuSiG*3o#RI(_2)~@mlR5(kVIJ*^CR*;CRgajV`!^a;}u%|P= zU(w3hIB@}Y=b8O+2k;w$`lwrELq=5cuHgFK)^ACZj1!-4 zb@5~qqg}-Y7?KGEVPbQQk$6pZJpBSx&=QVwYnHR%GPaSe4?eA8!KIway~1m6&;Su} zH~2{$c!W-8qJI;lyh}kxAx+jSuR(dPUe0ZeylGCW6(ufdW&W8?9reZ2ihV{2+0s*8 zi<93ry%*fjJLlWigf~&w1l03&{CW?Zm*NBE$?x!4@RT4mH4DtmeI5&8M1CZGn%K`aOmE(Hr0CQN#GI8qQRnpbus)OL;mu54(Gd z^!pPv0vl!sE+Y%jN7p<3zN!=(I9XzeC>{Hd6N|yWfr{_~y30OO*NabtC3J;v5wFJF zz`eRQm0v;odz8VZ*zV6V2vx^peruoEp}0CpzRy5Xy-YiAqYtj9>uey=*< z+NXPau(I3#p1-)?@01t9gDJ@ujBeETb{ZvW|9Kgs!$mFM9Mp2~2M;V0SA)T=d)o|N zI0rwz`O1F(mAoCR1~{JU?sjT75^rNNp5E3<9CJ==hDH_9uZLPa*qdm5O zsOGrfLM|qc6NB($w^!cFlE>|B8U_vPy-h<*NjHM83SDYoJh!+Q{T1-nOm~fpJlGta z4f|)$e1KN(@sM*iCu%xs?&rj~4*wrGF}=f#zk@rR_i zKb6x*`8CX)+vAtT-E}f4&#Y@=&wcdxHE!3bau=O$aTO+^u_-CfP!#{7$z1{q`>|a9 z@-Z7VdFJKU<8Q|D0{l&1UbJz)>~m}Ku3k=F9Y^7>l^ck^soVhkHE|kSwp-Ow$5Qdv z!-nFoiw$u{gP!e;u)qc*oWydL_j1Q8=X&y!R?mL3`q2!}Xr zjj6hv8@V>`mFQ_)5LX`Pzq1OGl`O7~TVq%`d@ZB~<=1-lH$|21Z;HP6s9fvHebu&B z56%}*qFvh6x|L_)ze%U8BRb`~W+Ef5Om}!xk1)|q-SO8}Uks1z5gy(noYEtl*(03Q z6())D{6(}5^7tn~eYtF<#2K_+yXtOm>Zb91*Wfu0_xswB z)wnx>ulJpDx7~r$d-Q>FIS1Y(Vo1ZG3SswPPYLc9cem*j`_mC?sdtH&`E@2yl9_^@ zr;`T#dS`dP(&0_D194ej!P6l~*0a@P7rm4Bos z$+kT}`;9Fd{ywxs>o9R!`v&X;Ox)C-H19K;(gBZn=;3U=3A)TDtwq#6if4J z62HhqT)Uw_^@m3YPn`(4O;>xI19?z|5jZMs#-o2%sASu%|$eF#Dty7tv!Ysf1x zXQb1VbaB)#os~8LP1L6FN~sPPY0Lfc=XHvH2Ko^e>_dRVy|A$qdw2ApmHXwr?v3z3 zT40Cm714vLtQDEdRc-8?boLu$m?MEX%|b>d#-uj{-!A`_MHFmLruNxHJ~1}DWl*I zl>=_a)K|%JjOab#_`Lp8-LIfrSQdzys;fQl>FQ4R6u2`y*SpQ0G4A2mS&HLuE&{LI z5!WE>Z@M9Ff794FW6&P;WwA^Ai|Yfd?0xSXZJJv7G$=T|%-x>npW?|+E=U~(x@s6C zl2gX(`FzjA?t$KXK1F;BdlBwI12zXWDqT=-ct445b#qr!&PwQWeO>k7>J};KIMw|Y z&qMBMm|s)weQ@Rerb=MtOsnF=Bw*Y&&r2CPb+y5lJajjKt`;W*f z++atqDykj5i4zY3FP8~*A10bp#QVZ(UN`e=vXtpX>X z#rj9fs@}$6gYjU1?&nmW(n3g#L})2On?`5+EI_p50vMPTtr=H6dqTG7>X+vi)sz&h znOHr*lm2o|$@Oa{ROfgy5E`@Q=IVhSGeVr1=F^=M#?(^U>)~0Y0G}d!My%`JNlGv5 z26X2onZbm@qfMpCZZJ;S4e0JjyY11Y@fXs%y3=CU8Ly-*=-PF<)82F;E$tLaxk!7H zlGbur+DRAE633-G?Ib1bs2*t>P=_hlHEGXT)RoeXQl}tgG-8PxIj9O8Ut9<@F4`A&x6;n~LF>quZELuzxgiVA4&SQsr+Bh$+5al- zaS}`nMNWbZm>bzR5!Sb6k3FTF2#c#r`D@lFUI{=Wa#r#ju;AF<2bp}ode#S!k6ATZjk>k?i`mQEXekY2n&}!@$`5?5@rR30uousqRVT6 zAj7BBnd)$7jX40!qYzo8Jl!9+NcNUfl!l+Y7Z!ZL*nn;$+2*+TL^I)v$EKx-uL8{( zCy16aXF{hl2D%^lOB}MPH}Un(0uO@?EZ)VcRj{7OLX4)3Tg?s3f&8BnuZt4qr{oq6l82Kc#X8$A8SR7c?PeoHm+Kltad+dV%FPzD5G@|Ki#i;NmmQX zP>c!xp8pP($J#ZTRhxqUkl9H^8q?*qk~TwRjY2| zjVS$A*g{?JMVikj%`&9XTz?+ApNXz}1kUp&bVUnL(#ukDWH)gUiT=%F_Jy2cPT+vrK5bWR4dKozcQVr`q|9u*eB} z+013oyZN0B=eLWQ%&c?_CH8=ZcqQ!wKlR42k%t8%D(no;YWp@12luZ{^c)|-|3Mev?v$=8;= z7;;uc6RAU5)Zt<&;^GfUhe($8v~@1J`0S6$vqyl7El*rTrE6mO8pyM8M;1SkSxchk zCO_75Wum1a<&1RpIJA#bt))*n#vOL?{**-64mTgq0k@4bw0TCnHlF9beDRpWI_S;O zdrR9~Jg0Eeqrlb5KieG^whw{A(OlviG+tHrLDtoF~Tdl^uIVLNbB)6Q=4UFhj&?L;l`4ox;@&Ha3 zBOA)ZN2*k7$mVzq*7$5f_)~kZDyE~%T_Mo+x_rNS9lY43a6xk%H2(1JKUS&YJSiWH zM-8I9K|j{RCnk@w{woW(mrIdzHtcDs1P^Kz&6)CImZNsq0cwIOXe)?Pes}F=b=QtK z5;4HK)WF(A2$l01NPll@<*wTrFxDE-kDs?1p`TR~yv3x?kFK<5JcrNiy8^R#oa0w&(mYTRh&%TmdLcp2WKLc1rR zMQ8`7vqQp$0T>Z*~t^|Beggl6<0-(~X|burd*XhBf!(Sj^$ zfzh)D8o4>b1E~X?L+9z{y<#_9J+e?+c_v^`-l>|m%zksE_LashWCIVsrqBi_9Zki@ z!3)%%x4>Iux1`{-lzNiZ&2Y?Opi3y$nDEaIopaKa)pd*1H;)x| z3#f~(*H`(@UVmX0oXaKJc6eqw;3~*bYLjAwsTk@kG@6-c)!zMmh0% zNjVcE=gl(t`6nWFofps3lkgnWwfjH@rAT#Damni3QcA4roV4Z?|y z9rTahdj!G_rFMp;Rbdm_NxSLYptep*&CrglggqtgO~5!|F?=oTI~nwSN!u5*7vE$% zOP<4`juOIEET1gy3Ku9eKcRAv-yPGALSP8qmek*?R*>^T0S9zgBl|gU4Z@E3IJ=?m zi?_hqmE>`F7Z=e&M*TrQk~KEbF7_@u@TBw#v`Hh+OrTT3H}pChp;Kt3d6kp9K+$xf z^+uEm=`Q!AHMmP?jg!(J(b9``S`*&(IN^xlo#wu16YTcXxnA0jV-8rkWU(~Ng1R`2 z0DLAgXd}RHUVP>54k^F2ZU><>)(B5JbiNwM5n}S!JHzP5a~J5ElhO@%m(rpyU>)A@ zTh2b}L7;*7aE^?pK9mE6=s|TJNqJ66{eU+p@7O13x1+v_l*s5a3nU{_A94!$K((0> zGC@LgI&e%dL(5yOQU$rVm^>OAW_He0LoTFJ|I70gcuu3Nu@Qov!nP&mt6Fkq6 znxG!?B@OtYYGw!DGcyuDd}_0b_4lm^z1H$lXoE-yGv+)tG^rlvRf|5@2s;ywnw|01=hE5N5Iyy(-9T*|#%E$tC87fsHGmk}>RdF~V?uZr+MSTGdP>elo`pH6V z^I!U;_s>BeJR(Siy5`UN4iFbyGZp=$YBUT_ED8ozh2A{laBdGRI)gqqZN8e?55Dgi zP4J*9&dxbSXbp5ugwHoo4O-&=@%AO)O;vf{=iaPMw-k!Br9je_l0t!$MarV2X}E0) z*n*(A&7|PyEhrSxv4Bbn2&g!dB1_9=WzGQ_xt93p7-nXq<1^pJ@=gd`Jeyt`^PC0VeQE1@r5^i3Vm^!Fe3;XWgD#K z8D|FQlG6eX-E%2y_|c)2H000ipA*dpZL`|Y06S!*mSkDd`11b6E4iJM2YFKc5XYGY zoH6tDov~DNtg&F78jrEGHJrn15Uz;XvUcW9l>H+=lpkkF1%kRpk!mZh%;R{Tw6l7O zRS2J%(Vw?c&3CM42yJD%PLGx{#hijt^3t$q`YZKGqw+txH=r2$g#Vf+!fI(eVzq($ z%Z8nU6z95aayeFG_kAJLpq6sp%xGuVcWUK!m7%9;yGq0GgKLcOeXh?-L;P$~Y#|s4 z8WU~ntMCwr{lY!#8y;WSr%|wwPp8_F&|2o^k6Qb{uWvWje3cYSzT-3bA(k|o3U8BU zbLNy)I`B5?Bz+5MkHtF;2bz;JbLA{bj~JhZMa%<6Z`0ZeE6=tjPE+iE(v}Z79pd%1 ztMyEKY?8ak0lf^(>n>t$eXsS^_RolBIPLY95F6W3uA%)PzyAbTW)R1*AF{{kT!x2+ zJkQ~y)r{|42u+gqwsgqfV$er}A4Xh)7|++KCA=0gZ6f=R#7o+-h}F!O^E3*2*zk8q zTi4L?S=NKwq`FAtr^HzN+(2Zhfy5+WFSeDWG@*J!`o@NeVzSuEeo+gJd zU*7sJ^QHIC<_l;>!CJ^9XG{69@toO_$o0W4S(|5G1pgP3Afq>_A(7BP*HmAm?l9oY zAfM&pELT3uhb9?OY!UYzGqE5f#v@){-ld4l$pT6g!DRV0-XJ;3JG>5*Tm3dj|xSrvamtlMN>&mrD$i`Ki%s{T?B`xIp<$^8*tRV=3i4J)GG*UR{O z(R4g9QY5ov;}7DKvZNqlgXQGNRl{ScR0kPDvAy6M{zT#dlBLZ4Gc;ziq?9-!+uO{N zlH<%koS)&>VzddZNS98ZMmVYyvaQV|KcphtCby{@Cbuc;Ot(<0uZR4TC!cAt(4JXy z0Y0jfM*k70;Og}n*U1VXy}SUsJlHj37bR2xosj69zCMMzCpb`*6?55|Xe7(XIUlWhKv;43!VyNa+S>uagI!UOqA_fRopGoP?GD$y> z^=Xx`O=^73m%zT(!HmlEu`KkX;}9pFox!j0B`69zLSqN}6bewa@pt)jiUFQ2fnC5Z zYPkGHV2x-P8?hC}S}H2rKUZj9RQR-UFhrZU@VBL_W^c)#P|Vp1U6|*CF4-Szu<#5RZ@HnWaf>uA67`_ z3MNarwQ$xe7{5PN^)NGGMnr4aQ7I{p3$_|gT%3|WymgI43r!2KC zgBA?dbUgLUqW4#oJRQ9YJRsa9nYMW*Sm~&?Y2b;F2W;a^#1xqzsc}W|=q3Ou4SRBq zn5cb_R*th0NIRsKX{F~@VNaD{yIvEge4W9!V2V?#K|6|=hi8_Bg{%ibwyg$zgCPB_g z(lV_*k;e$!6_D4sHYfO9T10w z$cP_3knBgxBq$Rxk5HyoE;ERIT?)!v9%2S5yb5;*a6!o+S`Gs%XkLCB6Bm(IPt1XT z>A@r*9&QObA*-NY5tKRVwHcWOWH5ssjH_ffGkfTM<+%`x{=*&y@nA?(5zo4H+Zf1s z2EyVYEOv&}oVqvfT`q2Gs2(I#bt}M8+^jzJ6tKy!k zhj3NabF~6jvwN;;apmZ_+J`H?=jv@-RrXwciL0ufD`CYp_;zY#ghN#geGBDEt&DOA zJQF9qPFraJxAGQzLS04FJ2a0w0Lr&Vw%t;5^^n$5Z`AHPWs{99Nwu>N(ESi>+c18$ zu2B?s1oGV1VZ6HyT!NvSN;=9M`laQG`wj!ZkMynVN2_*yIeETET}!xmP-@L~DwRAa)pr_f6~DH+wW$I^O`=OoV$owcgu@<$3NNrfFIF5WNRo zjii<)kl|iVn&2AcT{CDDmI(LX5KS8pmEp7|Q*HDqhdWO`jG4J;j8_G(S6WK$A_dLy zkVmpD(!)ZJ-AXncDpFAFOCy!>&khXrem|HcJMc434~FN1UdP~Qpg;b}1$x*X-n*zf zANfJA6Ms0aI|ZBr`sIVDt?Y(!u|`6=7b$rt(4T2fskgB3#!xP%zAxELidt$Le@UFx zW#S^cP)&y(KIC7CDSq02gZD+o)3-h234FzI1NU{wH!@%0Et0SngRAo=eXr?Ak#lx} z1DJG0AI*987dbyG`7D~Vs+{J$)gSl{{J5O+A9BvX-bkINev$KJ$p_ta$~lexZ;{g^ z=Y(Dqb$%Po`PMITHkUMa*ExsQsq~*lPP3fzWjW{RXwJXcb)gsI$hH5k+V$BX_j;TKALmw4LRRFVc?!FS>0WyoO7|{K+f56 z&faoPM>OY?zsR|?WNCMuzoT{DA(bGf13AypxRdCil4#CFzsR|uWMOxma?WwmXyoMO zoM+{nqoX+=_(jgSC3Cy$e1O)OE)77=N;&6IIp=_A&bxn+^Ujjl-E|`8IWZj8B4?GH z^F=wQHkz~a7dfYvOzp1oL7MZM@K4`r`=1k6g;jO*EwAp0j9S}``9KK@N($tB?jltk zb3%)p?;ywdZ&kI}+spONmFqnp%|G_W{P;4XOGZcQRn@Jf$O z%>vftBf;?33*bYJ^P?!Qwj>z73+FH3xS%2!HsbtV)bXcjNQbseLzzFf%zFO@%dDS2 zx%h9NocXs;y#Mye(SQ5o<$wF6@rEaQa8)dy&V39UaEgzkx1zYZj;Ym5e0BIxD9e)m+C%XFI162DQeky5&eW*lr z@#DEEIA1GGDvsZZILvico}yCIc!Np64X0As4smyw?kzjS$3w|Lpw%Nkwc7nK)C*YQ zBkiMPgvM0C<)e4s4w>-(bjZNR)L9qMx5nDYtLtPR%tz>&WhyNLPf6{!4;96^4;5KB z=H`I-M`$B=x039UUaZ?rGKeDo&6bq&IiTkm_(c`h%d$fv51&D~ELi7_35biZ`}KjJ z0#?QjHCFdS=nLxIO*uIxV+u_z_YS^=%xBY9nYli)3`&cA)Ow8TuKp}}2y-eM^Q|*E zf~6e6<4xkz5Qm2Y-_nTh5$TDHFvaBU5Pt|>$K>r03quMyGFt?bH&xL3XkSbSDZ%Ma z4n;7P@1BDBh>77fBPt%H8`2!}**a{c0v zF6BN$G^!B3R2Q{4^NSC6X}0%+Jra#7lqx`0+!IyEFS5ai#o0|I29Bb5`$co`y2V){ zq6#I--x0BfyL4#p>%gS_Qalx6@c(3pMinB>C+-P`U$q6pyYZWo&XRKQHak)gqX#r1 z--s_}c%k()g&RDkc$;O->L<<6phVrwF02lPmt2p6Ul!0sNXAemC{b)V6V!v?)?@ zqHVItljesFmdS7id#OeiW0?pC;Sotu;Hge%OH>w5{##wuTZ9O&O4^&LZS$Gddz-Rk zP1W171ip;x)>Q46HC3|Q6*g=UJyl2?*$F=eAj>IZfi9;d*}zWJdHL1Wxu88xXsfbY z9Pr9ky0Ej8?QtJK>mt-MEKUh~d1gEDeV+74T1DD)i`H^oTNU?(kzf07^i@VaNm3mz z##2ZMnM^*(647T-DLmC_QH|BROcFF!@8HeGK@LwOb^R|jR!(@KeBPQ+YLRIwmB7CX zN$oqb1Rg5~@=^)>yZ=Q3ACWSU=2D2FXp9WRIt^W)ArU`N9lXX_2gdz~Scla?)Aac( z;$}fUNv-ykL<>1_k|mzQf5%uml@#BE_+U|4v4(8U2d}d_@DS`lsI3N#~8&57PxHh@~xt@hQ}INowa>UjozA!9b790K-Mi8inO~AItjX1lB6c zh-Jy~$mu>-BkPy1)&yP>4+fsTY8XRfNkdwERo(unO65~%%A~PnuK@RA+5pC7#zk$IlR$fT4Vw}r`miSs3DC9IlgHT5Bq*ZeDRBhAj|hU zY~{(2$2}`~+8-}C`txop143Ui=aS;Qjff!B1pKu`PW#agNUajN zd5wCD+3QwjF`|<}XEDw5SM07!JV)_=vWH|dgWY`2GM3+ns4xYG zM=Vw^_KU-UCLXA4z*n2hn;?;dB~Q-ymI@kcW*K8DY;p6$7uQ?Uo0(-Kr(equZ+E_o zARo=A;&XaZ^C*E`#tg}m^U<=BTIykwkEk}B_GGOU*e_fk{zxlh&@Yybt;BkbaS*q< zl|fV)=@_k5x9nq$)eumEPl~*^w(0qgVYpB z@RzAi9+eIzOe0wdw~@h5+McpqNIfV1B$>wA=Dcy$upCn3`;WJ&ZI@d##TvV|BoYsa z){`PsfOfC%h4_fDx32g;9A1F)vU*tD0k2=Nhf3Qz#G-(z?qP5SSH;~ysxLQjUy5d| zMIGWTG7|rFTXDZQ?S^=OesQ!M573W&-gR5?6yeGZw&H$q&@bWv`o-ISH6EZ}Ohr6E zLHr!?0KY^O2fA`!l5NGefXDw9u^xR`qn{d&_8q5{ zG>NS7GB+`<`if#iXnGbgoglqO9wIys4OsdyNu1p!9DJ!U3(`hN8ka_7hB2P}D#pY% zLm~k$0*Z)eL|k5q9C%LLgWc?po`*TD!LU&Ul%;{Lo51r7Ky1nWu0A+RM_kE%uHHCH zbLoIu)T>xuQ)Nqm1nwr6-mXJj9_2_iig0(P=419*3ntUnRNErTMA0WFAyTn17&wC-lVk>APN9E_vbVQ`eC*LUj$ z`B?j~46}I&EX3P8`6jv>&_I^giE2J^nQiQ2pH^zM%k9OP`&vgi{D-jX*qIlbppT~V;gi$nJd{5k5nr7mW zNSPTwD^vH2G6M&@%gj2`9rrCDt`1+1bt{R_9*wN0&%@?VsgGmhZWO;sDM{Ov%%?0qJY?Ys*%(#*#%@=jb8Ohby_h;)(1pi zP~W5j=Ey%`YYRIuAUeK}?@)!9QN;8UO&=wP~-pKOPXRn3Lm>yBr7h)aB zhourl%cQuPEbQLB7uer@DSiVBF?JgZ%r?qt!>(J_PZu~S@@+lVA^kCBaW(9x17c>7 z0S2*?qzD;Ds7*WrYG7(Yw8r*o<{5HP9QI~qk#O*t#=%p`;3sSp>+HdDSRp25;rpuj ztm3R`RkkN>L$D{J=x2lH41o=zI>~^ijnM6c&Gbzmz0?qcBEy)O0{nfOWJ*jeHbP6I zH5b4Zm36&T&brmEu(&pyjQcc-Aoe@J?Mp&bI!c2Z9I$sXPz-+ObS5K3FkQ4sS@*^j z$H`9_M+|7f6MB|>gE4!gGaSy{%8(Wu-#WmM4{!_uBqWUAH;F8H9uVi)+XLJD%(TQk z8Y-_9%Kh8r_Nbs^l*H3PSdg13$4OlAxUL8#Y~KXigE37MP0=bNE*czzyzw0#8Uvu* z0;y|qdoOolLqJ^7l?`7niioaM4#B8rlZk7jd(D&r+V(liY#rF6j;ghCT5vgP!)R^= z#(avPZI1`N4hKj!8TNY*jV+MaV8QITr>j(mk3lJ`(Sw^t?|s}pIKxCaE8(V4478z= zScSI6FbOo$0&r3*ON??$lOeruggSvOWyg^Oggn-FMp)GnQc2*b*9B`+n2xX$B*W?kb55 z0jha67$vbWKwP6yq9J1x-l3_}(loX%4{@!>*IClM5qv8TlM-%lyvT17qu+IY4ufY)hJ9&QXunpoRQ6&y}4)qYRs|dW>*o<7_xq zk72GsILpQAG1Qe=Y}!<18{!(cIepVjn=&@i5w0~4a1E4u5i#Q>@0|Q5CR>kpdtibFfquL=A{Z{ZIT&t*tgQobyh6zA#^73YCt?oYhBcxIxUcXxT8AH%S3Qq?Odi@r zqH%jQn9KQxhuc*^S|2H+mcAI}WoTUic7wR2fqMT2{;@2%kvs_9UJn6LRI_NArvh#_V;- zJ&RoXObtU&QoK+JshJ0Lro_zHau@On@NUx9rJ`l^MKKu3`AD+^WslZU)O$pd6JC)h zl2)W#nwREL2i0y<0}v*%Yt}7PutefpO%aWlKq5cBB`$<rb$J zAS4I&7_+gWs^zzT3_SGrjxR-hm#GyL!8T$i__zT0;6F|ehb7FPbj+n^^MhgAtr0(pDl_mW z5I653aHivNq+X6s<5-O2pKye=lkfqKSvXzX8UOVFW3)yq;(@r$fMxWFk&djLt|o2gjYI!=IRZrrJ~{^ z+FJDvi!|5*f3DZ5H?Ou+sk(sOV`|HYiZ{@%KIgDU?WNfPJU25|Av4hCP)aIFp?>(T z-eyj{V{MV;@KNj!bIYmpW(9nI^^NKsi}2=ai<0C~R0X>5bFG5bdfi8y`s1!|jFDrm zhsDRR1Ihv2e?ub1c)Ic#2jf4>#O*WL&GI_>2zD!H#ou(%*gD5G35e2DnVx}Jxps~c za}IIi{W1FnM&+xLSdO@yl*>Hk*KDT|(W!j3uVDC*xb(Q60qi=gqJbntZPz#SfqYeo zku8bNfX#kAS3XfC6WfROE$iPRnR!$ zw4V)<0&7tQ-ukS#CMX@deL^rAGg}fD1#XO)jkO&9M+0&wj(>cIMoEBtnu3^bjR)6S zHJ;=uRn;q2WpjF!vXXkiQU4J|6~zJSEig)D^IckNdRYqf=8dmX!VmWcp#1Y%7f|?} zX|+J%mo?;w$VYdE@JbLL_QU^&TPq{|(+EHd($hJL_7B@Cver@9lvCxF<4~Eo>XZ!b zqIky-COOu5ImxMf$k71)Mhg^SV$ja2L~QJK@l)(UDA%kt^c4;V74|ti_Eve|=X>do zJ=FlYbcuxry+PDqodbTu%@5%o<-6O(Lq{z@>>|AoZSt=)f&t^AUP>Zbnhv`gS|*KA z4G%7?mh5r#31+?i*iXo>KX_xzfVy9e84!sCp+RY8$h8|S?V=Od__S0#XlDPY#QLn5 z0-pbWQrcZTrO|kY5qfkMJ|)-Rgj&9)%liPzAK2kX6C)X6Z~hECRw?yr7sno@v3RM~ zIQ6u$z#F^Xs_^LZ&tg~Rhu2wSv>%T1kO8z?7=tWXtp>gnG@vZSU!#6g6y;&qsc(f0X%jR~6}>?q~@SD`N(F9g?AQXq(!_=g@lU8`b~c`bK>n*2=z7 zUU)U2XW<)loXV{KZNEy#)-AcQUuPdV!N(j1dLO*=h(!GZ&x(9#A^6G0gL|*45e1F% zUo@(j+EscbP^odL_9DIl&<~%lRk+sGvaaW98P~Hig%_Z?ggy#%BL*vQhd47Fj}qWT z*Sur^91~?fJkV44;ju2ByNy399);|K#!5ab{@uSEW#*I_tN^)N6C~XdRw?XJ%{02VncASyV`Wk4mGzZPppTq4lC62UG3!ydfm+M>9o$_j%cAKq5!NzB9_TjP;mfNVFGQ#UATl#uPv)kXoiP+!4&k;Y|R4}QIpTGYV? z(*m@4W{n>2!goG^*dl)hzP!M{;;^Q`J6w;wE=!-?-AUh&<-887|Bt#&l7T_kXJ~^N zVVLCQpXLuX0jDzWIA|7YoL#Pfgyf?5c02AF5J^G*mXw}^crVaN(5tZce3<$hF@t2g z_-Z;+EER^sG}|-9*j*shy4K&n0tfFh7_k2I@^+v1lE(8d^{bzp zWUFnq!($;v6~`&O$@nT5_5Jo({VkB#u0&54^`R(ibEtfCbHA4monU&Z251P?*8XQ> z+U<zVk1bk3k5Z75bca&7e%kh4Lr<8 ztP<_&<*)=j%D;!S?@8Kv;D@60eC$?6A)UE%F!w_%-Brjop}>b_?2J%$h%}RCDm#%% zhh0)W_hF+GNSCS?nDrT;BKfgoFmQ8#wI1s~^{lF6B3aAD7*jT<>{7ZI;fVh?T*_v( z{A4Og*%f0{;O@76rGef({%ndI_nh6t2nm5?fgz{bh7yd`i4@KFR9iNqha@G-X4-s8 zN^xTT`@cbq5f(8Cu`<7NgpW{D2QIH2Y$`>D2pc$$usy*A#JU7M5g2dh&^dOE(Y zvY!?Eq?R^jvb7;B4hZM;V;m{&u(&ups8+*kt~e~EK8?Ncs-v`5OW!NU%MyWm{W|>f zF#1Ci<1|;QER9zyODDD5l5A2gJ3|Z;VcYO}<7_-9ADWf)DD66yTlb|nBppt zQNg|n+kR@T)cA<3rF6It)R9DCh%e7D?<4a8{@L7|HZ!*!^aJPI`3E~vkLc+3C2r%r~tzvdT^WD}tt|EX_&U8wupCiZ;WA41w%E36W-!o3-n{B6or@a(epxg5#&1Ktv2GkeGVdn*p{L$$sOi1SY?gfk{9J)j zP`s&F9!YP&zx`C3<$m-qejMhe&0#_R(pDbq%JqKs5<}j`?<@Si!H*Cxio}rj)l@2<_w1v!TwEf=)sV{*G|7l4AVK&h*!?|);FN0` zeZEC+j?}qFuJev)oejZ(-Zw!vhP2QzxT%{_eCNs2u5bogD4>}!;X1W>>@_1%ZAxDxu$S^ zQ4Lp9EYGA9oqsGw`xY_2$v_23)oTk&eOryyzE3l%eY5gdfngasJA5n3EWQ(Eu$fqt zpqw|V|U}I{dUxs3vnc-ne=M(3Z+wM^6cFh`zwi&Ot>#ed^+jT6SmyNg4wlHjQvqe~L=^iaf zHrb;TQc5B`*hwQ-Jn7ZIiXqX|zXfrB=agRYI#}P?kt(5CL41AmX*N*d9N-~2>p>OQ zJLy=+-KNDzB)Om%O1x*5KJ6)Q>9ysRf8+8krPqGTthJW3B-CPsj=424{_3iwm}6Q> z-DYruLEmy~WAOb7U0Rr=&F1XDoitPr+J+dMSf{krK$pc)UtNq@-x^5za)G+W?%+Zzdy)QxcPgY`dUtl znMiW!T#UTGB@MIDru4!GAWVcwgk-&QSpnaNDXzqfgxbk9MKwwzrQDJ6R=A$4iBRq5 z0{9A;jpVeVE!h-FX@?ETskY*u(Ox>r2%Ek_|{Js{|6{+`y*WS5o zopAu~qHSh}|uXlGfu%6Noo2!`PYUs*E zD74z>!y{sA{o$GNv40a?@K< zWN)pI1p14eqP|9JPNbX+cwQT8pd%wAQEo5e{}i|`>9t8VCNC^Hpe;{w1I7u`se7UC z?sbQC&q2gm8NtIIw}Nu2L>Ls*Hd*-ma^;wg*7I!xYpr`qxuVIpdTv1))4WKU-f|k# z9Oc-K*7RE7L?1`nGrwwM9>rcP;X@#P9JTgqN%!8uGsA9bc@h>J``T4%<*j7+`^}8; z_It?iOu?xr^qokWemnW}_txpDQ`Rc3R2GgZoZ^fd`)BJnEni6{LmWJ`;nz+zATcK< zpKM7&tIJ>=Gb*InhCO7j>1jX*3kgj(x%#_?)xv`)MB@N5TdgVZrS3I!%irkL5T=>Q zJL}Nea8EyyN-@j^2Ql<PdY-PCW*xZ+2k^vms>{^bW!wI>*$GM*5eL zKJRDgx60}BkbYz|y%OoIoq4rpq+b`9dIPd5RL~0WBtEUP{_CqMLOdHGd&C|aHWU@u zUEIOQcrc6lX>CpoyrCf3qA^=7hbtjZf%LWUcI?d+lV?=ec})#8%ri8QRBQ7fY3Qx4 znUC?pCaZTbpq<-0wZJwZ&DkiQRD{K%Lj~oPMG^U!x<`g-k<$ASVI(wWRDwnX$I)FI zfE}3`7UK`ooqxLFCgA5$ETq{$cBK}3be~^&@L6aX<2hqRZ;nPdpt1sIQw1ypV`>ry z^|m|HR4**CDPUQntzm04FQ{G08f`-_ZwjUA*%aX_wzz_a9&i)2xdBq=1HgpRCqfUQ z&{uHmE(2=PNIKch*oF2iz)w18hxI({WY#A@m#WQUYuMeT!isX}93?7S8I3d+*ez+( zBKT*Ou;ZtaD*}uyWm0vy^B7aEG*+Vz^arU-MQMce!(XkF@mvfB*&c$*3z+r-9khEc zDlv#bERSmIKu8CkB|!3a-XyGt-_>>bfY!4ww5_oZj0%jh^cvtIe@7NTcyS3nWh}E04=NPXC)5tXEr_WjPAu9luv{PxAug z9U5&Md`wUN2!0gk*c!xyX|Sr#lJ+vluYn;H#=HC;kqt?sHQtlQRikCF@XUS9G5wMv zHf|h!qqtiyw+`lMPAb!oRtg6xqDvfToZ`XByrqKOc&bfRsgvg;gKw!&7x>u9yLjxY z#!%ULj5HZLP(uX~hDaLNXw#P!yf3&yX8nB@vRUdURONxT1b5V zuP8-O9#R?^9LXW*Avm2q88XDM_(S-e%eRr3DVh?J%W!iq|I?V#Y(dF1rVO2F|A2%; z=2xU}SPT!u+*EO9LmYRLu)$CBdqaB2o?AjW+-fNo>CeD=sS+`W5q-GE)28kH9Hc=y z2Qv@yhB=7!+>x#{@XW40{ayH`yQAOqHHm46@%E9w=^pu;#`kBu%D*d*H&{DcjzY`w zKb>EU5m9nOvBilQbbc{dO^8tiI-yRgfF%n{zmI{=udsMFsFUe~xrQML_)(eE3dr~F z;8+)APNj*E6ERFB&uk{ZV05YIw>$wXIFkivD@-vT2b)io$H*VHax@MTbFEbmTEY6k z-D)9$ZzEN9D!*F$C1jCLr$wYzuPEp!enk2bI$kQZa$8TrKRWv?(jW>M{8Z93{7Fem zA~LJVvdoI&sYE1JlVgB2UPh%>f2C3@C!|(R_}oC2Or=)Tb7itL7E&ui|A@?r$`mmd zX3&{@C+31m3tQ6mKdV)U$yRMmKdWxPBSwXBU2VMyGyEBHlkg|$#@P+&AHTay3F%*( zxGU^SMcRn;Z-xpp2HGr75@w8&&X`-Qk`l7NK|C!xGEW*0G80lQz}HvY1GL>yO<(bE zJHBwd&A;4K@95=?=Y}=SkOoqw74DbU`J1~-geB8j27UI zv{)r0Va82Ozt#e@D)=Qtv{EcQ5-2@aPr+z6Du*aNtL|kw6$MmYN#jqE=1CA_Mtfl+ z?FGo=V9|9GTAhG5UW+%zoV< zo_&X+<02*%q4AuktX1yqU#+K)a4r1b)zcaJPwEj0@Kx8)_lf7Uh_P91jX#@Z=p(!h z6#whAnZC;b`CT~qUH%@T5_UCo_K!#2Ou*Y;(;J37|_YEMk#h-6l z>oijt1)ZxKU}0V4Bj!{u^6J#yYdIw#WEk&W=Q)%@^F?UlOsx3e3(Mj- zN)s%U9;oR|PL#}+42*dvDc}je7IQ(tzW_T$tyu)JMrF@f4U2m~o2kBm@NJ?pM0KYB zTk}J%#b79>dRodM8u~|cp>#f^t)pvCq!lNEv=wXxG#!eRG%YaW8E66q0IMPiZ?^Uj z)zsmgv68+4zS{5+)r5t`*6^+h8jsvi5dt=ON2?_3F_dNodvEF?B+1B;$fsWm>WJvk z4xU$tpU8`J)ZMvWM2)z$%LHSI+V^cOnB`H0f8XGtI77N8AWpAD3jMP@@A zke45UCga&2O$Mc9Iu8p z(BpS4Jvzt^z8t>=oHDS~~GPpcuh?>84+A)3dh$Bp`~mCh_8EDuv&bkI?P z{tE%?aBX88muS?~#FYS5->}rCaH(9_vk~n`rAxhD#)UDm>*<^di=lw2!U!~iZvvFF zz4zG&-|XZcsBrdMYh|$asywDQ#B+Uw=HQ}KtUY&>mt!3&$K8W5;4eU}fVh|fO0ho} z(W()n!BJ3dg~l)mR@$U_>i4jvlMw_V?}k+fl|eiKBt>NgkQ;<;0ZL_Rf^z(G@TZ`{ z4RjVj>s0#$#xu#BnWC7ZnueOKPueKgsU3s*r^B0IRO7LI&rlwgY8U_CM#q?*(P948 z(NTF&EhDA#@J!Npn9~fe!@iDM1YPx19)rv?V6brmU|SQgSk>UbOz6Rya3mF-)q3#9 zVezZ*abEUw{U405xZuAVVZFQlCnJnnvk-oG1p^)O+9GWeJY>9|wK1St1H>?ZLAl64pX#0msagM@FhzEQgeemSzG zZ?+T`IlsP`?zc7Y1^_M3(3(NJS+#2(XgFci_^x5G*dK@JG$C;pjtn0ID{**b;{I=d z2GdLCoi40l;4ej>i&d7;eTF7!sjXm+b|mX?9-Dz@k?{>AB2DiW>Z^%8p~OR?MK*@T z>X0g0DlDi_>YqT5=(sK(V3etKBY4X{HB(!E%0n~Qxm>sQSIT9BjtzRdP1Q$N48+t~ zl-fZvsiOTbsY^|@W3!gn4CS(RtPl0vAkEThh8)6=e))ffua|cQ_b6So@ZVJIEO$u; zMAczz6bbxN)QTh|zI>>ga%RC!MSo0Xr@G*Xg^r?F2|t;owm!laN4maY$Uk9fJ>=m? zna4Gdo=qe|A9??nCGo)WNjK8icJ#Zkej;e)C#A3%(I2CHBE?73^vu^dywB&b05DK{ z{G@7mp6)>%bPqvBzJN7{`QUAS9W=g}!6+fJANbFyF=8u3sqv6soo{+@_^7dW9XzD; z$Knt*af6ldDD$p?veBJ0LH`u;y8c_xqGTTY;8e;vT6yJo>Ma+E2Kt{<@w*X4?ANJy zdEkFC$LKdKaIlc3t%5B<2990_WCLNm8I@S+Bm3aN==1QKbPq)i9mTBFLMKn@9Lv$T z+~K^D)IMA<+lD~Xl9Aa*xX|9%5zd1gkvj^Wl#Zr!^Q6VwsvZxtirvUF4Cv;Opm9E(gL8?lYh!KA8S~W2>8@t zZEPj^7yO?7l~`%{7Zg`NI-SQZ(DtlDiVwV7szNOH9FCt3fK2`0=p3BJkIavgs)GhW`8x8W=cJGup}S-l@2Sy6z>6Wn@agV z<9!Y1uc4pS_*P%~h!OUEh~M(L_+;qy*1d8b1M*xF?TAO9g*~kS^s>>B4?l%dfks%& zK|keu*`90ws-i{{MQnSi#K1iZ$@Nm(HL(to{Ypqz&N#Q*dmECXDYha-n<5l)mvbAI%;Q=4LTNl!~FNuE&iE~sqJ`fP*(YN`dQ{!HS zdMJY2CGoUhTTAag<9ytnYDkE-UeoXx+DD)N%a7KTKjC@Ao?+1VjgxsCIu zd*8SJUGAO0_wU=^m(Q+#|6cS=z}b89z4q_ljh=n~{ks@BIxqdNk^d{b@8Fz~{~x!j zLDl;RjcpqA?IHii-yfHsoxuO*=(C+|wEuVcFSQ=U-K*Zi9chWv&;8Y&azi_hM%y{U zzi58rTy0@N%ORxwrkxzUa%C`_7YkfF z92c8{;j6uZ;kI;Op9~6y&+33R0!JQCQZW2CoLBV+mI>~EI5-&ofJGU|{}M>4V$8EJTKv!&ZQ$r;eG*MAw&KOdnL$lF@iQYU3R4* zKAKC>@O(7aTgYX`_+Eot>q;qxg$no;I{Y;FQQF9ER10S?3lO`@xdyutX4y%YcxjlG z_pSn>$1q-nI0>nR)ic>;ZLh%wPC?o~CV%VDD$ZK0RY`>fm8@GU#KHgKK@aOz37Hrv z^h_&Aku&fp8euA0@qm1H5>nDLjqo;TP~;xs;Y9EK0jM;%C+E>4CU+1%=xtr&77wT5WclJQiR1ZnB+|&+2hDSw7qPoh^E{31^XXHQyCR&(`6r zP)@hzJ8Sf81y38c*c)}`o~Lpkp>*%nJD(&ur`m?)-RJpn+VF-KAQ64i2CrRZ25i1Q!?>94 zf&RsGyJuK~8Pn5qpqQ#)z`$ofHS-()`!jfkcwPTbXT64 zVjsFz!wUYA$ak)R??}TQn&*;utaCT$_!;{d`P(E5D}JPR4|c8w9ck_yjtF>a>{lqp zAY+8zFAvmBC#~zft}mMY4$q|sg-aG5_z`|%!VibLX_>fmiXC3IY5H{y!dwfyPX$ zJXyECh>cpHV#D5ZJtE`gK_SoT!rwG{gG-yFLG^yQA|``-HleTrW!ela8q zJKtkE;Y%rDqjFQ$;aA<$QXJTn5Vj|q^YmM8s&E3#|_@=B**an=CT(udN(R+g_ zhqqze>jYJ3^_~KJmkx1HuvW%KiV@xiy3J?e@XokxtM_hen7}DJ@>vto?hI-T&%l#L zC;Sw&jaG51&>vUD8t5)pWonH^tQglsJ?OJ`BO)kC$@Qn*<2?y=9pdufIIN>H&oSh% zzbmYb1D(M6deEJ_Ks%f`9!m~}e~;s>c>Z|`A-@|*$b+Xt;k;Br?vuL0d$4Z$&N8Ir zbB5fC-}gv2q=O-AK&PGpO-t$O3V#E>_AUGlBdrnbKN6r8D?1xr-39y(ITUEJhb?uxD=cTSD4R68o!RYe>T0*A=bL=zG6;K=Q=H|PY%qo7KYhFXSo2}^$ zZ6UFkk^1I<3ZB@Q?JkVHkQ!d$@h*k1F7RqC$z}(2kB&dr#iSi+Hx3;0F|_MX!;*c; zskYNkpWeSBwV0a@q-337MQf&WR@eyK%@uB7g?GZsYtxLUT~=;IEt~n#hWQ)jVN{c% zd2ZH4`yk*?Kzf~!9Ez`12s2S1#i^`L)!!VmtN>a%M*BA6GheByZLq+)eG07S&n!{Z z6=Q7d=)zksEyLZ{!i)F*h!JYS`S`FEzLWVVIo3~Y^2b3+$Yd$7-nU{bsA0L@SkwSY zQvx3&ozTBa0~tt{s0o+heldRVPTbU3L=5L8L;WLYX(b}iHZp3%Jj5L*Bw@#jIt%}B zjUD}HhLmH0O((n&j6rWHglm2sY)pPEszQe=4_t4!R9L81HW#S zwZVk8P4rU)7oAWSq*rJCJKZPb8TOq&rD?UB70ScBcPEZZ!rlWIF;zS9_A#(!yl;O2 z-i;OB3pKdMA^)w=q|%wS)2}wn=U3E0BI=sCm&u|%F%Nc~bOb$!2uieluliTOU;3jB zr_r)W%GK`E4U=~3ggK!VbtGfEv|%Kk)SPZ$h5KL~`kA=IKiGTU-koSIE4WY_ElC5L z921_+M{Ub~QQN3!ZRTig3sD=BQMiF*TCtj0QEpy%HRzhPYtr5|_LcCSqTUckJ5TS~ zx&PH&bU(xjFNg51OSZv-GZSlxPDq7}q)QwJPtMQ8JpWRAK5{99+tEi>^vy@18D6xT zWlSSl;yb#uc8qeJu%T<>Ub{S-{@A53Shk#U5yOYB58X_55*_Q%P&1hd#J!2ZXs2J` zi!OW>^iE&DrIuuz#<=}x)9D5#lNHXQUREIJjdbtnJ=VRH8`TN-cQM%?)lLG%v22_!k%S>KF@95 zHDWjIulGan%rK7JIvT56;|%Hz%yN@3F0P8d4Nk=IB4iS`fP*+K`_f(%w}n06Acop= zqg3C~ZbF(3;fd~x@Ep%aRCdeOe9$8F)2u7vn?S1@gHkSuGo?srhDd39#(_3p6d#jI zOS7j%OB>%#?>;P-_IP-ld(0k6i9drx?xHvXt)IjcY_x0y9`eJkqCC_%sB;wl=iq&J zdo4dOWc3o*SX^SrH0)WvYG+7SpI|r*JmTXWUEz1JAIZV73dcS3KRiJDVw5YdW{i8( zt~|Lftf8CH_WZgG?uvLHS{`Y!7^eMkQT$uTLi-`w@)Wt{2kn1}w)`s}ZKED(FN$es z`9!(pOXQY+92kSU9|i96p4vuHtiomm^?y_o1Kr~!3kmHXqD~dpChqZ3nGBPWEIiQ; zs`!9slVS&5*9rorrb%v!nA{=S0t)XWtZ|=;e+f_8N2xZ=GZF~WYT*q;v^L|((eSz^ zIv>(MUSpTp%=tqH_q?B^>yTaUvl5FVb2r?Hwp9etlieTmyoyFV2- zhsUDrRe`bYt7Y;bdKJdf&RmO4Okaf#3PVX z(XW3|oP{q+kH(NZmZE+5`w$&V^X(6He|@Zd)^?k9+$xY|i6 zyOW;?nG~=$IC=$nKHms0-F$umzV7MG9?2rluTxUKtC~CQzL#5x`8OQ+!!(_W8;-RF z_AX8nIL;Noq&dOQ=6VSegYq}pM&BQ+8s7hS5yp;XLIc&c-wxVVASG;H3Ey8@iUv=q zAMgo&BBb2Cg#O4azoj8j@*Mb)O7JUVuooKoV^?@7_G1Ts=n5-w{L>IZG8Qw0_Qw6P)xmWh za2)R4?x&RYbk|e(zpSeo|Es#_`t(j$tvi0ZyJ(wRX?7Rw1optI?k;gbX9NB-{?+?q z(QEnW^B)m`{e0W%UTa(pcqjCGS3Z1OUSDylZTHrT;!uAM))iKm3N*~~ZM#>&=5*&p z(cstPO~!@3FBwt`P8DO-SAD)scbHmW!xB2zBB-jp^4>UEAkd!O|)nwCYcg|iKkLouevS}W62K2kY zHzAa`y_lO{$7BwfCy93l=$--lw65!WhKu6WF1jB(VLuTai*H_#M;ZDD^>=*)9z`Y0 z>YQJv!kVHI$~t4f1JT{WJ=_qAnQ1M?{w7lHqbN7-MY_|YyOE3H`*O*9?0cgnuaiqY zE|+|=%Z;%Hi30lNfmKfIFR)w4h{;q7MWJ%{PCJ2Jmqz$==XHenJ62)T)?Y`N|LrPf z4CO*C*TPGfEJQBIrjZLMO4OYfG>HZ2MHe)3L<>J}@WsS7U3Hcs>y`_;YlP&pv`fm^xn;Zb3IWJK0B8zynEr3R%UEVYut;kw36&K z-%!l>Nms;u%%H&cq}@VRlR;iTAEDHmD5a)!di;fz9AkdebB|r(nX8uRjd(9*^VFXR z^AX;Q@x{vM_KaC7r|*zh%T?0aU-Fj~$F{4LRkmvWC5H!=T&g;oKT$&}jAaxffogZ0 z7uDO(OIhFu?D)u_@Ui0;+O<}|E($uWK2?^!L1h71W9h}wjt1I4@V>gDosw@ zGQFbOn(1lbtF3lV3(lu_YVd!)XZpNq>q1Y>{Az2ZXFC2b^0eUpBc3GOU+k&D|3^J7 z`2UzE3HP69SpvKi|JMn1)8WwlSj%Uvy@mIG)PUdZEqn;SdbMG|)Ct^xk|&^HGUDEx zA8&lmVgA$-HCD8xw%(8cltcbiFSmC@(1Q|N93*FIOJgg}PY3|8T z_%Zx)E@EvCb%j4_?+OpV@sZOE;jteg$HU<>)eQLqdfUp5KWK=f=pID3o4n3G#f@*cQG+O;JQIxT}9k=K}p zElD%A`FplDY)P@`!PRP5y{({ z#o*TqQHlajch~J+f5OpF7r(XPg#yQ(x;^We@?CYi)>k|B)m4}8Ti*a$JuYmlNQ7Jf zk?ABI*##@Je^q2uq*{{XS}88375G7hpc3WItlj6@3oGy4@P%k#9tEY*x>AM^;T30t zTf6P)l*ILv3uc6Eh&xRYE7RG0AXfIZ;0G;6B77vBM2VT8-Xa z)Rnk}(ulZ`ceZM3EsB0;Xz#h%bo6k8>of6gNpI*asDr6?^_C^J6^;Ujj(?6nF2%XZ z99jqKn4P}X(SUNMbt!6rtia0Es&$WwFgXQk4C0D1>ctlB=Puko?Gu@X<>|6pkNO#dtgx({+{c*;GRL9kl=$ZwT8hRDQ zPehdN>M`3BU(DeqJXGy2-}R%+a~yf-Da_6s$PFeuJjuOSK0EU8MEADHy#*h-cSi0l zh`(A=Rf}^AO}jAus&dIvTv3U`k%jRc-|Fte6_r86)y8*x6`R8q@~^@(kV+y>wdqMO z*M7J20!jSPz0Wn#z1Q`Bczg4}rmD1m{M?&8O-ot|lu{r`S<wIHJvl_`kWg3M5)wl1jX=%g$Ps55aKnl?d50lBwnXnvpP zCM`wF>-&Cx@4SDU+~nr$%X7|omd|r-)wc3StKKRvtJ+#Vp$fEU`$F)V`QWgS@g36S zJS-k=gZ~Ds)wALg;FCQ5FqL&yd=j@^qiR)!V|^L)u}H4V2MySDDaBr#lFy1|;Zwkh zxy-Et@1z0T)P}q(sv7bpB0P@pIl|u%u0psL;ZcM#gw0jkWC_KskYOxAs6g0+uo2+_ zgxLti2;aA0W3YJE{(Wuq9=H%`)vqdF>3~ihgVyc(_cX0WoRbfW^B`-v_Uxv&hGSiX zPe{189~O5&nV4dv$T4QhG1k8&2?les$Oje|Q=Ce~dG0;<=!t;lwK`N*yt_({`LFGX z<_Q%zf8STU<-sY0C=(DTbo5%UolkKdk2E$>ifM9+bU8(1SBlwNN@6L}kYbgb;_gU; zoMN_|LNBLi=t}XxmRn;f6ja8YRK~2xJ93J-a*9@PC9ggEPFISJTV};l_|KyZImN`t zD{_kYa*88zidVW)Y}(?CrD#M7?E)&p6nREYu}Dr)FQ<5>D@DbYD`P2kQyFp!O=M{k z?aP0x?T}?O{Z5A?Z$f7HPrNI{zCH{0@jUF^;=jX@SFw*%FFh#dUM}appey$!TZY7P zf0F8R7uDxT#|=${@OD^ySdM*TSL|E242Z?PpXzc~iX5wN|GX%Zr;*siWT%HAl`J|us+{Ku{L*%Yhv{)AR{6d`8i}c1@Cu6R_=!EX%|}?=Tyk2W-eG7hVFa44*XrhqBS@Zfhb{ers70C3b$c8 z(FMe>B7{>P5I1yOz^M<2r!K;&?;U&>ynuk{>rjFYw*sf0^o9m{!;wYk+m2l-@TB13 zueCROM(S+G5KH>JcL8Dr#}06^53|+`pXur zQJ1gV0eL+nmCd1bYerssa#?4bWQB!cw?y%!)1WjYC4mI-A= z`&G$@j71G9;~_$pRS1v3&MMJqHv(sCh{mhO4NouMe|iTEem2Aeofxu@0IE)g=rN+a zJHme7{08XW;I3PPd3pH<(7{KrB82gt^iRq$iY%kont7f{@T_^2Rt1?9kSCpwEL3kN zET?;<_*R>KEGREH9_==a*|D}sC4{0!|4o9u#VJMf*8_-|q9tk7S@FBJ7I3?Xp8n7_ zbOtQ+^p82T6+CF_Ko9IhQMWna%9=?+VoFlc0gbj%FU-=Y4(Wx3XLw%knh32htp6B6+Ar<8c)k#SmFCM!bsfN?Qa~4vD?bQ{V+FVl9L|Xc!L3Xq zjA8koL(;q1l|U8bgMp4TSZ1i4K(GQzjXGG{Hmyc0kJyMB8eIz{mfR2qU3-e54#q(i z1)Gg}st51`X|!WIYHA}P1RoY33|G~}%bIWb#fB*#wD4>R>A;!v`FdFc4ivvxhnRKE zZu?>JuY28fg?l-cgD?o;vT^4lW1wUNxgSfxZ&{-*7{v)9T%b{xzy)GKiuJD@bN`bXb`-5J9D2xg4gjd()m*4Znc z@Qf%wSWz^_BL#Hll5DVqn8yxi((0qwyk=0O(hhY#d8;G}5w$K#LB8XVj}1YO&~v?V zE>W*?xn4ZdokpAd2vo0QcrHb~jNR(hOP;NC9#}Rt2+u2aheU>BF?IEOFfN&cE)onVS|Fb^(`g~7))=>+(h(OPt>s57$dYuDu zF{?j`bpJp&hCucD1W&40Vz)kvZ|oHtOZBft@~QK>d>Tje=vZ~2nC-_nbHW!z8M1vu zO5OtGHy>dMLeKRpx)TMR25GQPaw*YA6=Z&j*5`1ENmt`i0cXUp<$4R=+6#q`>;HxTJ z#ST2Jg2_ea4)3lZHcrOh`vC12yo(J1=flpgJ1-KD`29@FkI@jg4DYhFb$Vbj_U=FuIZbB9vTvZOFz|`B; zl9m$A!BvoL7r)_OF5SiX0s|?D%!c0FWoiB$-PCku+$IZkUl{I z0`La-K>_t!2HOdvgZEm67NB;STuV{c@C-iqm=c_Y35^n~X68G|M(x>81&o3mpfa7fPM%^WyPjv+VOi z)yP$_KWWkLM#pYn6t4;%FP@Y2&;`=f{-s|K?=G!CwuQ8VMzyZJyL3YLU)-9g4;`hY z4Jeyrv)1z(`9$iOwj{$BH>;lxT<>cT2RQbQiwKXb6dt}#?z+@Eef$!2H~@PfR(}lXK1cWjf$FdW&(3uk5pz(3=sJac z!G#+1uuhjEUC({sxJ3DDJl$rrmcJAx5A z0;}(+xm1}6mnd_tTxJOA{0L15ROSIZJIn0<8)a@q+@9NcsH3N`JtSJ>G9N;^1qkyH zsLbhjUKrbdU`@ql+9k$z2;%o#Zp9_aZF--^b`a7fAm|aO+;i2@u{C0j$D@y5>)=sx zY-~TcZ~~Z#v5lSqTzQ`%P0wZDe2KEF|Md>X4j_DmK;`bilW3T}pbzfunLyZMV=t8b1mZWEqVt~T1&ziKaoJS*DI=XQUBxILFS`VwU>mCM|UbQ=&}M4&R4;n}Us zUybjDGWYJDhqyhLc{beh*yhM(o<_QVA^Zb@%KRKp8e0|QiEm1=wQIgGk7;Jb_Ne+d z5Vz+t_gtb(tz71_NcSkh5(Fx90iK;@-u)Y8+7Y+sGToOb^D7`Mv-;6UHwYmWfyz|l zDbp!fWYYPV)!+mh-4lCk?XkCI9!EL+vy}5P2TdV!(4gA_|1C;z&{+Nbm@{;*V>s0+ z8BW-cKhbUAD)95}mQUJbe+@2QjUX6nO~Mv|a|t-j?u2Ftcq>D#PWiN%y$U+j$ibMX zFY_m54|L+QI2m%VUO1nYaV+qG?3?Y7xV!ycoWyb&6HZQ^rn;AgXJ`8=<~2_al| z;XHm1&f{sj=-eyYCT?KXVu26j@F+L1jHUfYPPqeq7;@EbCtq3$vUc@tcW*{CyL_FV7TC4pp zZ3S}I8?STgh1sF!;^3tpdsq!N2EFX!ro5f)Yg-Jin0-0 zMRSK3e|}Z1E`J=fOypf>rlxBjxNZ(f+?cy6kMJJU&VcV3xh8RU!7ewFm%>nahl9~ zJtV#)*8nIcz^az(P#Uen@z4q1LnwCvf(s!Zp%iyhx-GvDNwadt*pRvK#@;WT6O>h> z!IN$gUxn@Ns+}fbfLWi;gpqiMyPH|LB~$+Q&mH!iVf?3SMA@ z5l&9vtCU+?#62B~isl-VfZL+RnQFbs1%2di3UA+nzVbJ< zDKYrnNj5}}SZY%=USjYN-tbi|;z4lmTf}d`8IAgy9sgrE@*-p+{k{xG)_on0%>6DL zc^bdR9EJSk`*6gM@5>O*e;bb6i>LKWn6PyqV*s|nny8$CZrvnjD04;7-v(!+M!B9V zC(ak~y^`nXg*gKG`Xa0tg^V;$m{lvP(Q{5^m0!FyM3M)yK(^3+aYsl2EhO@>_b@a& z5`zz&q_O*g);?Oj~SR%T1kL6gVP-sC~%IDv{+v| zMM$b)z}V+pgg%86&Nwz?nybIO$NR-udzRw09e2P96f z33z*D)qh~D&bb%6lePYL!P0EZl-R&iggR+mH479s2#7w3KtoU|Y zsJ`w`hr*Eq?-LCo{3T{mmJ?3I+wi}_mnWORi`v4qCaaXD$!%^um8O9YF5+L^h>{3R ziCRy)0_2L~&-A+vPKkm8I^m?>H8L;MOwHn6woq*hq2t2uYlf9<&rx|cV-#5M#kL{Wh(51STryOSaTx8VaVP%= zC&f_vy^#M>S@8OZeHWhV6#Z*bvDm&NxNtDuF0T@mBJHfu`#RCbx<7CCi+Z5O3e@O#Bp4F5G|;# zqxEI2KOS=L(VDoj-*Mme>_Us+xQFQ?A_GM7e! zI_qImL&zoRPL4R2cG&ZSpHhuHs1*GH@?u11l6?{MMk3|<8hm|_oOCW|L@sIzEHTg? z7Z4bT3(QGw;A*6R`xftf6C**Z{OEb~%LGyO2eYDDw=up|X;7}yZrs+Kh6^TU@mk7( ziL z(dN#1^N-Nw{|ZNHTA4fsYr>zg#NgUJMywOP+%nZV-Nv34@sYSd));5Ul`7Pq^n6^RZp1%~@1}$Q>d{)^bpH+xg`A$7_ z4H{|B$5}#_08m@g;Fm^=74oF;Bs(tt7@NH~VbvJSD&e?z4A_*C5A+;kNVhTcE|2>d z_L&*bl`JrUH!GN(TVc`6f=;}d5_{v9-&~D1&e)sG5{h#f-Z)}!7Rql%;LXjQ`N(f9 zc$3qakNl=T-sE=Xvyk#J;?4D)`N(g89pt>x#4^x>cu)SSR=`^-6J}wzSKLcpw&=W+ zfu8yJyi99lkEtzU|BG}r5`+I}u^~>P+Q2-`2s#5cRrni(H4ZBv~Z`PqN$ysZEkBwMlaIMVV23Op@8q z-fRsUH=ai7Ws8-kY{~pOKU}_ zDo7p+Ok<;+1<)9t)FR2AZO9}neKbsKjYXBxp98C zQ3+X#HrEK>;#$aANXnAs_=_()jq~94;H4813yucXk8(re{U5flLJd*s|0UUr2>r6B z>*{56D<1neSq_Ym=9QQQz9O|&Ker=O-^eVl3*7kEUAnn$%uR06ykaHE;e`B}%7BO4 zBF`5J5%G>ZPvMgB1GAuEB;TsKak z4EDomm&3YAd%*W#&BuX{*$`PD!VQaV^5+EmQ5xGBEcpEHy5Cs_+U zPlF4$W7pHJ<*q5h7s52x-&{Gak6cqqa*C%F8|yv;rUIR+F6ghge^Y;DDbif1TSaVs zVrG(Vj;ol0O?@>MJd z&2y(9&rjT-r2l$;mI$+@42BawgI^!5u9edr^ew0vhMHnd23E+rM4j^zypMXCm;Z?s z9F-*l$FB!ja&k=KuWpm~hCIm16_Ax*23a{_Um6tc$`JPT{7)b+XP_IiB@JZddZOf= zG<$*)lssD~!&^}Dah510A9sVFXDObwp-n_tf<$4W)CF|>j3#gppqWLI$@Ty!xG+fN zXR3Li-@N@t;vTZkb9JEJoPSx2dMg_Zty+Tt2g7Nrr1kskzB!GT7+mAVWxBGFDZ51NcOLEGYvn1q}ge#Cn2Z`YEw1-zZ)ltO30 zmo8L-Li7f0NS*y7(TM83t?ph5AV4CP;&#WCj+;y83C2dC+uC3;Vk63+s{9vnN<>be zBgl#9!V%vr{EJw|9K__Vo+sOveCc~LaF}Uuw(O(b_2%By8>^mfCDN{50(5)in@<+ne5gYK4#7m)@t`-t;WQ&*jYl;$Qi1PEh{@S$ z(DnF|rR!5NoCCbX2Uouu5&J}-GmpEnatyTu=L&v=kUAUfSDX??3s>656YW=zM~h)? zC-Bg!Nxz@yKThsI9qc|M{&)A<*Zz<9TJY9;+-u{)zouuaPh6UwUD#_!#rE2v-S*nQ z{SWq9NE@)%ehsTO>hA_TYlJeFLEdryjvW`4Gnd?P*T_3A?YE>gMEmW}SXo#@S~lEI z>qqAmR>E2hXeU@d!yAFGD(|$+O{=I7v+NJ><6VeVG!Ano7dtK6!2Dk)K9V{!b&g$Y z$2{RQ)<5Gu9e2bcG-4H5gzlD7+!bG872yPdRm3-}zjzg?X%*e(81I-xvSRplNZVj?zn*lQ7Y0NMSacLuB#mIE)|B`BX~ z*pI&aiH}?EqF&qWyKo|k?zysF({mSgv@!6h8C`$+U+uSU;J1>-7;z<)z{^tFw2)nO z*9(h?nh=lGmjS*5tv%wc1hZFEv!P1Zu_YG{b}C;`f+x>a^@Z2J2<)BzBpHlc1-Fym z@C|4_aN2#QB;Q1biOEqjs)zCd!{AO6~zrM zN>wz_Ga@Z7(t9~CR)-a^J(00sV^jq+IX9|>roBiDZ4Fx9i>>O^LQ`|FFgqZ=e_jo4 zY5`7bg#P(tI6F<@0a~<~r4#*`NLWDdEOID(UkSKMrfkV%0(Iubl_V1V;eRd}Uy^B0 zb*L~~QXO3S%u-5=wSaS1I<@tIpG!c6?f_Ruk?GKU#G$=Uw}F;IW9`zsW?dJrxmo;c zq$gf;v-n82`+T$Lx#&J`46eg{z8PNRl~v8+fv)@fKi>&QMt?|m(oR`Gvv|`*`E2_| zKBaO#Z^-#<@5<*T5CnYI#hxh zzF2zY8>cOHEOiiqj0GB6>ei9K2abNr>iXu8zg-#Q7m}_?&UlXf`#IPt;JKt<6jSV_ zYVt2&Ffw!88fMkuyC(4{Bwfn2>a~x0o{_FHCan2-TKwBfVZA^$$B{_FTRgszyyVMp z!JNvxN4UB4oo(a34Kj_ezOJKL4k8drEGj1aeY#(?)@9pVZF%kTlQ1}vexwp$I}?^c7S!`(~%%dbj~ zZv}Zx=~Gde(^JX0-AdjpmwccjT5=Hhlh#^w)p_v`Qa||?L)xkNtO6YA#PS2;(sl!A z=Kc=Yw(^R#&rc^yQ&^cw-vj6AQ3rgaKf)|u!-nz$9rmLM{94YhQ{E&gz0dmL#31xqbzg=6OE!`p>X4ZQT`m;%C!@sEsLj z7(XimhdJcPVJ@m}k%kuDfKxB*OF0AbyQ7tH|G=p?fjgL+0DcAUU!IgG>xOC@`SnyA z^1Whq?D9=XGdIEq6|}Oz|6r(dx@seCf_Ad*W$DX{Z=crCq8Pu_(a^%>DmLO?$!5bQ`vz_+Sb_rbo&GQ+4T~TTVJlo=@-+SU4$C}?0F2t z(b2L1tZv;#m4A8f6q%!=iE(t6_kY*dA3UHDjnoo%gT7pbQ^T*^u?MDnsuvPaT`__$F2JoUNLytBKKR#V4`0acKO^=@^h3V zd0;m-9hfr7&jULUYjPXH+LxgJ{SR={Ny%#%-UIxBu z+9<`r;rR*pt@REVrDzCs)cLPJ)bb$+`aQOOAc}%omURILO;!XJXR2 zh#&nK@J7jZfC-q6vsQC(l5jq<>`B=5;QKg)+4xj{5-PUDK{t#qTjFMJ zAzNPP|HMZ*B^fOEmYXPzmAwv1qXVVMYs1QfltIm@F>gKuUL$#sR>R_p1xJ=?{$$u< zg@*(aQ6diOZQNnWSlyuG+Ib1ygnJuaWfsL6ZY}A3Fn^p1tM00ql8WdMS-IPGz~bGF z6~+9#o(rf*M;-TZt$g!_-nuRJpY~?F8{`2G_4J0&)*v`~r%mGs|3Y4Or&T~cMeaP# zYKH5jk!*L)AkQAGA-$jJ1*|&ar_!oRV5G~FfOSV&>rqZBtvkhf;-y;Qua&vq^4;v@ zaaMd9++sz=6DgXCY=JLHbUc$|@bIq!od~VHIii8LTYd+OyN%iT3SvvA$g|#UXuDduQLFr(cQo-8lh0H4fgt z*ASOtj--L+zLud!#?G{ZS7GCT$PWvB>MwAj<^CE^{Z$C(yEFYvF~CzEsyw|W^xBzd zU$KmodhjexYXS#&-mg}C6!^$+n=}&00R25v266CTiHZc3It9&RZm9FLgPn71PK&=^GJn9`%BdQ4*ak zMxaM>1Bui7UPnG@DBQ(@PXK#v4sJnYH_=;a_NjqRM||bqOFDSHYdF6XG%9!=`X(zm z_7Fnq3VA+f55fuBKt6(Qgtx?qZD1G%x+bAx*da(?-wdz>ZsK&JXQ_zYB6|(*%~eJGAPw+^0XA#!>HLUp(EYW$7IDMr}q`J(r#Z9frr$OiF+R zm-w27F21I-)K!w=a23<-f$lT0)=VaUyjHYkYIsb3$1u{L;-NLfOXe`WIEdhBYK{WDkLU)h`X zu$21ifr~!SgT3o4?e2siA-CuAk8{heN#U6SF*mRrQ?L(6HLA~D@TZA^D?P!GC;+)G)`MsY)glf8GJ1D1mo z*s%AVC*48CTckZ05vPR|8?eKaV0Fhd1ZDqBWhC7L)srQ?0%py%K)z%oq2)+}FqqxR zqp5KA!@niCbJM+uY;1lfMP(*YP7N@|rHKM~tm(Ou4cH%qN{TyT0m}r=inEN5Vd5rd8hmEsk;}nI}+e)iADm5aFE{sU)X9F9w zq(j=#(E%INWLsFg?N|3|wEq8?^J)8E;(Y$^^0_wrpYpl7^Xxw$p8a1=2)%;qL%-y4 z{aZ{4{C9X*L2B~HvEP>>285`?p$dcQ$Vtm?b62NN%LzUOOko^A78|?4~w_# zA#Ujf-tbxRZ|8gB4GTEwb>|K518*2wNOIkxyy0p8LEbPQ*r!Mae|SRaE#Uduz~^dU zxvop`i4XYjzh)LzHc~V^h7=Qw+|_f0+g-#lwlz@dY*+my`Nm;!d-#`pV>%bp+J%ok z@|gm?pNPo79WX-9?FFwns&jBnmwbYB9*N&vk95T0XTeEQ-|P5_KROncWC$0er*A=e z`c{|pbfGLgZ5HgZ^mMB%Jyk<`3SW#~&O|y0oRkI4hYG=EmIw9h{;s5J7ub^QK<)L63JA#s7$r; zk3{do!0{V5eK_Qlbf1HlN#&ys`1+%p-3z#jR`v?^ZgV?LG1=-TvTXI=;@XyoN&JOu zwMJk=nju#$E#5SFsHcCM5^}3Shlq+cV2;^A#es$r8GDg5RTRemN}76~EKMa&!44^H z0(aRrJ~}h@@(`9(W=x)1Aj?zLt;vk1GjLv5Tmk-Wcx9H{rr?YxtFwWvmnF0b&^il8 zr6f@Bkx2ClG&kENbbDNCJZ#^=rsTI_0R?R~Td@YQvF< zLjDaQVIp=?b=OV`IVz+ilVmw+lEgI>&JGFSWXe(!lBJR)^%e*2ym2H?T_TVi^(n|v zABPT&RZ+T7yCK-M7Zg%FVd^bDrtGgMsU#{mx_p@)MWR~Li z0-w}VankSLrHkaq#AU&~Gl?uf+|Zqjo&&U9=YXiLsS&6#m%a-`L`7_b=v^<)onJ)!F?L3&-em*_f?LeN-kck%D&>PIAp^8qOp6!S5MBzmn0l?c z&a#*@bEPaZ&}c3tJ3Bt8+%puhxlq7Yx|n0j5Pn2Zga4!x^hGMr`~gC0u2Oz($ki8? z=3S2e_l)A$Ul0hpDM?5OihFT?`2*6)zY`0If29*RXpSo7HfCT{uRuc@98(P*SGH$aF*1Hm=B_)lr1&ruO@M8 zxEejEbsgE6y1sAK_9=uc*d#6r_p6{c$!~9+(kq>i!fiJ94|27fM9=r^I()ozNtH74BWZSqC542rHqDvaL-*u;Bz7`jdBk z!G@Sk(fWe*F`J@<;12n}7ZLl#SnREM^MkinRU&K-=rs0DC?5Hf57Vt78-Q2E_Ap#aXVlB=}Vk9Wi5cVC9GT((*tevguW?+YzPf^|bfJ=a=m%`1~AmbD(@SJc^M%8f){r0XFno z-+E`ikqxK+>fVFi*c1DwDnRJsQ=N(p!+bL~g(E-0reoI@*pclCN4|R(d)h;=1>7Bu z1YQkCQlRVGzakvT$M1hsha*{d_Qt!>cqVKFFCEX1HiRRGeh=O_f(PLM!p8_pp}#z9 z1Ta2p!;$Nr4@Wk>8IBD3YdA7~FTQ7jp0tD`!TUIN2u}~5%nyBMJX6=lRc)F=Nbya; zyax^+di_gxD!dUKcBjJA=Kj0MeQuQ^^F#D*q`nBNzffNFw}etF(#$tZ(Z;C3^;2fb@0W!*vmU-O*nI_P zu{wRaOl9C>r(9R1E!S5~f}aGnE44~huG*fDnFL8k@Qg$&z~-DB^UVe9a>-H9XC%?3 z{*Ac>@z6)jnUOpFVaH<*@|HBo36%Nulbl#J&TG&<*a^jcT_yjrx~MN+3Q-TOgB+ID ziL2@A*y>rVl9I;^@KVN})hOi6YSC@l#jd@tPD;)Xs?QrBL%v;m_ zkojOf(!0N6`X#LoN1k~dwhEYs)emwk3(q2iaW94=PgaH_yLW~oU*C&;3i%(!yNB0? zBZo1si=RW@KFnb&$3&FlL>>v4(?^g$=}F+El1(xeR&{BrpO$hF7!K?vdDak#iA_wwEVG>FN$ae2G$zD2$|Is8?b?D^hgXi_I=v2pQ zvH!dltHf4di_wf{jLf!=i zNk~zlUZ0mTRHj_?xy(5PpUdS>Xi!z`&Y9rhHd*U-Wy*zY^wg}6MzE$aDbW8OiR-q8C?83IBS}X{C z?gL&vP%QuHQ&hE!TB(!2@F?oP4S}9-MB9?R3O-bo@b%CNeo9J~*4q1s6_VV4$dX+6 zhy(5{P7q~it8fgfFiH4H%#R$AcR{OgljWOOyxEb%Gnkbyl%JC09*o5u7s+x}*II?C zmcPehUK{x;7IT9f(-(_55G7@~Sa3}lB%E5SkZU;}OEE0+V=RSBPVqx5g;GvoZ?p(dwso<%wHs z7Tn?Xmb z#eL8~P{6K=l`Gy>ZzcL05;umGK$4BX^AP7$fw#5-)a1CB7*W8|9lqov59F&h((Q+v zV?OJ?kDECb6l+!9z0tXj7+*!wU_;KCe*k4tR~;AIJB(g>iXF^EwO)X>43_Kr<@x!s zR=l*7ZI1xY4kKRo>09a|=0kBfc-i z_r(ZL<9iOCl!H~c){+|QxtGp+YiQ*9#m3{|^KNIKe6oL9>}Y_jJ*A%3(~WYOkIJ71 z@HqrFcv-HensDpa`g{XpwKyjKzu7mifc%DQU9X`&*HGC%gd=?g;N#o{yeZTph`OCX zNH`vjyn$yWLNdPJjOUFAsrYWh(||A%-)G@D9ib54)p+sgO{Pvardjo;u+3@>* ze7_B05`Hg0nO=PV3ZWFgKf!Yc!ZPgh0`|&h@vZ{(`vlL`cn-t4wGa01>#$EBKp9O4 zRroIpVLQGPHgNRbT?!ljEr=Rqr|MM25ORWqw*zadBAp(tn3NTRxR9E1D!aMYBK(L(q^^b+*F-+(nkozYGGK- zGXiOrz^#}sy+&P-g0tb@MOBy$`3~ddK^>|Po<+D0XQU{m8w-+`B9fhy!fsyWoFL!y zImpaEyw?QeC|$YPITkC>Cgh|kt5|TMWD~N}vOS{;Sh@y219Xt%jD=p*2OQ)%g~U^t z>dJMIriF=7OIYw$DLsD#xCgwTg9lssO}N~=V5!kWe79)=&zCUI38Y<5wHW#|(+zre#oBnw_AG4nX; zM=o00<&p<&x1i0*2w21H80L}(;cSpkbiFl(7V&+)3-h}7&4}ZVKjvQfnu!Lcu?9smRqOZ2!9~! zD)JPl^C1}}0C~wa-`y>PS#VmL8d~BeaQMgux(MSzcDOy4bszF!_3%L7g^^&pOO-@_E*jS8t(il09(i+ZWb1nDvic!FaeEo3W=@;t}c7mCH z?@Nk$7>76Xz6H^LSTIN0i}`j0nClA`0H5tn;Ntul_Y2%3cH><>-hGCr0nZ%J&Jh0J zi)Ry_pKQim1a}EH;=h64YZ3ar5RROf&$0eb;htUa^|A~t%@pTeev9HPDJ;wdUk3z7*H`Wn$gI`Q*-vM3& z5DI2k>raV)53geJLC>DjU2GWPC#-NeUA&nsWme!_)RPy6JwR=50#|V_IEsy$C^k(L zO+_V)oO6Sq7y1KvhtR8Bruoyo=dgrT2)T(rsgOzO(#9pux2d*Xkm6&za8 zy}Y+BDv$l5ypQGbqz#V@x(hzYfMWq;$7qYAvA*-7xl=&OkUTWt|x$`#0ibkHgGD-VQpIJ8jCkn+u%56 zsmSw^MyII~pN9_p@*c*555B*tnE2I78BL|`+RE>uD8U+=vY9~%M`+enhm#TV{g3@@!_>D zE$D_3bu`vJ_&sn_kk9*g4#M--^-X(UjrWAC*Ln6(fy2y~KJ18Ftib6)Ukc=p_fNT? ze}_P_t9Ef=NLx!Kw2MPSY1TH>Y?ftctPZb8RkC(%dhEpKmdr7Vd%TfaFgO-(wPcgy z5%+}d3yY)yv3QM$cZa2aEZ#%XZk!;2o)wE%B=w2Kt81hdYGbs~lUKjH{J$%hwv`KCj7n%&vJyN2*>c-f@cwe1L1<~qcl&~)eme0XhU!%tcIyKmdmJ# z(AdNt*nB(mbP;GQ+r?MfEY|ezOhUe;cdYjPq-MGHM!EJU#I{JUf|=Omw9rd6{Rei_A>N_G<-{Gk5MAY?t zw3952euw>;{2UFJ5@9{Sw8s3a!IdMf<~>4PPNHW#5CNyw+}~|x9xU<;6?vz8gi-_V zUT(inK>9}{vI=7LCy?(#1Q~M!XD{f1Vpg&8zl$a9D(rv6BU}QB`x)HZ(@>WaI0qd< zi1r<8OSN8xnPiX65b}pPNbZL$;G|t?Nt1i)gm`bnB+r}FSZ@_ZQsh{q<9(T>Z!Fd= zk!rb5lVh>2j`aS;%1FVyJ>b*C=8V^;>zXqR{W}-!n1pBHT-+ZJo<*3A-#6m98euU) zHOAa6EXHZL(ghk~~)1`M+0?Wo|o-BC99gv7A9JNoF7fG4urCkr?Zq z7oM*P?mE!ICXW{G68_-2#KS4Y8$Zl)&mveLC-ss$% zAfryQ;8@7lZp8dJAlH**W9{M$X^?dwd=0jXtEJCCH*U1_iuKmV9TjqK#m9PUb4Q%q zTeey~PGC__BnEiYBYk&8tjAh?3xNNYa|>u4!fgmQzJj|Ac#_60*`l#7q3ag2x`yoFnDyVD-d;mK53PMBW3}{?$OGUF@G8aG zCO0#VWk`*L=J$7TSeqTFYGK&)%|+Q8Z^pe6Z8JcMm@3Swxdr+?7clclM#`Cuc|^q- z5O7p-|0M}!kY2L-CZuaXxC(ht8wSX2;L!%wy$ydL{qa?3L(U*AygtgchCSdmiCF`l z{;=eWw(8loe*^8B#aa-7o=jH@vMz4HJ}KIQ3Y2|p4$8+9e8KFue|F!x40Zq^aY{tC z#VAOXEjUg9BW84rrcU>uf2>nIBc`X0deouEdK_ZOh|Q9k^VaA}+i4R@cQO;O7`bPF zh{4M@tmzW8ye`5j<;>-IY{f+P8z%%FbPfIz!+j>KX9ISEFU*AczlURJ7i5QjL|2@a8^Yd!|3A%eD~t{Af8X- zxenpv%izJ{Jf(NeIP0Ftg7?=Fwh(T$BZmUDk{_zLDy4p;le-_{dm7}XJQ@j2tMT!EXxKI;w*MF(8+%Eh#rt81i_;2z> z=~P|+aVFl&O!a5RJVz;~dpqmn?20iSsV8*RQ`z-C!`qo^98z5?-;3T4?0Rpw z=zU_>d&+|Y=c=;~7s@*0qq1OGgHsNj#Nu!g>u!77K^C{^igMN3XPSW)YEiCHRF%kQ zLGmmGt#o)P=BvmC_etkh;$>}Ycr$eMV8H?&^Jlf!j_GsMj`vo0AmZVxm8B=8K9zlg zU&$1ns?-Mq3a0rsAF-3MK7aIZUhWDnP~2pF^p&)eG2u1bhts8E=*|((k&w#ZXVyG3 z^#N#fYra(q95{X~I8Z7?{nP5;f40;}|FNoiL-6aL6khTu^%WsC;NK~O_)Nt?RR+9Z z2%sr)&(e)Z1v}zo#L`4e;J0l7mWe-75-YK~&Ro-bF*lJ(+?8!UXjEXOb)M~HZH}O& zcG6Acp9nO|qK>Vw58IV78bGxsU8Pyygd@p_NBbOUQz(So8r+!zce0;wmQ@LXBA`rp zDR=g7=0%JrUKw$o|#Y_Tn_gx~~!c<5(Id^e-^QsM5pj{bYJmh@HKk zrBAG$_qIoOau0T}ftJMB+dJBg-S&5r(AN?@U7ZkbY{zL()+LCJ2AvsUQ}T5OeV(4w5*(4uynX(Yct zT6k?D^ig2)*$u&m-vbsr(w{~Clfmi<-GKe^JBI$ykai8m{j8({pGhVAdZIg{A$U8| z%r4^C9f*Gw;{Lkqk30T5WnYPWHi709eHM=FLtc;K``K^1m;IMtm2F0vBiQGB&{u2d z7WXT0b;mF38Hc!8I6tmI-s=!I%7vsour$vN9u-$gs3ovONB9%MM-eUfbJ~1DYFmsR zf|skrr(A~M(*e?{+3y>KypG|VbuIFnj{InkQaY3JXPhKfn} zC@et*f0LAwmNl3UEawg5+To2ZuSLBguSK~aPf{-WbE}n|5eJ2=SO3^(!VVrRd-Sj@ ztIWf>;b+tD2jt_7t0S4$4U%E$n4N5ha@e0?(RG8AVt`t!Re9(JDcN9iw2OnoX_s@C z1$~HTz`tqGqT{=J%d!q`7mv12mXsSOx2U&FZc(ncUTwvx*4s9DvZs;u-r&kClr8Pj zO$R*~%7#Dc@L~r2aNc^wVi8Io;R)}PEiliBTd|Lo?lR!aN~bgUbABwrqfJ*judG?-pRH;F+TNX7?#hwQ zb3WMp+d11$zS26=^4&je#F?;qmv-ub+(#S*HAab>dUyvnagqIcX^8!Cf0E^_&yx$9 zTE77CfMGdf)K5tRAO~N#+G(sMKI(zcOyGo8^U&{o)qSeay-zZht6E)gu-`VTTJtsg z1y$=`lvaFJspHl(7wBIEcXo}=dj5#2wOsqpW@Av#E@S!ZJ9Zzd;`VcW_=)^v-U^R$ zEa(f76zQ&IoJqId>QY+_6^7tuKeO6{FD!%a0N|KHh8a05?KZB;u?MFvGcBh7UM_n< z`YY>YWv5>(f(1>0}(n;N12Fu2BH*d1KlqN#3U}o$5eJz>B zXxUrjvNM()mbS4BXEM4>ZN@xN^Yi;@}-u- zQ*21%1X3RTYeKAsnW{4zW-kwyX=>!w9)le-|Gd$$ zwd70q%=l6=dL!^d$;>z_cKvs_MV;RHFBcrp2HAJQKG?0k(rhT?#@K`RmTCR4g|MkT ztNd!V+^^)cx%S{Z$aEuPpY(IA3|5cYT(##(*ogw&PyYA%GV7w=XkSW_yT7BAY2X4T zz;oP)eJv@R+Vg#j>S5)GxJJ-9i^2y54ZH?qPAZ9@U2?Y+tWF3e{^T3eGc?jn!Vb&G9&M z7TB0-rmB#Gb)nL#@o?7Ojg`);AW59*G+C71&hK{Ihi+@5xwp$b+{u|7PO==ax+XNK zhwt#R`oj-|Bis;v*q4&2no6=dk4aiv{04A2IoWqivJ(Z$xysU}$Q0+G46ynM3*Hi!4 zHqB+3sm_z09IP9nB1vsU@L-u@F$7mNH@v5%9+LZn1&>Lbb!?*!Zwy$&+gLRIHc8mI zOWMOGpPOS|l{2_e)%q?|%e3b1^O)nHHGLWnx0tYE-!-|lc7IuEp}o+*hUpt$kajc8 z@Wr(+NVO~jzUYB>I9%)13|D(KPGzh%&{-NTEUd11t~MU}LS>WV8?i!I9BikxNN9EX)Y44Q4qt_QHN)d7K1VvVw>-;PcOq$kjKKRG`C6wo zS4e;JX@-A~74(@;HT)AFVNPRZSg^+=x+SX-`pSt7(l%4R&E6KT?TJ z?=%GY=EXHir*j_R?yz8U=wqyQ!YGGUctqhfIpc!TDY}c5))j(d4;|ph9n0Z+J z5Ed*^Cc92X`vI0|V+*G%cdmApO&&mFZ=6hHUwD_0F!vDF_ax_!;s$9fy?IZ;-$0X%PVd=Nqj>8q7VA7$X&+IKGw$peX15a zjGc5POPW8GmFCQuG5KdXkfK*wMOiCy{%pOUROE zuZHvA-79rojep@9tk===w!r`2p%w*igqEXMOgove&{Wb=yk$|A!&JO~z?S(*jm?W_ z*CD!|Tvl~2J&k1ocrW&#p-g2OJ-^D8;nMqxOXv*4m7z5_%{+FNf2Vm7^+H)r{n_yL zv)-0Pbgnt&-Xtu`dAuIucEzhX_R}qHV=7c+QDcoWb75d%Rmsb#uVP#VJD`k@nj}iImr^78;jE!|(8PW*zTJA2XX<0~=XEer}C7~sXM8r)&+}%G}7n(~x zCtXZoqQhKF?SIe5hD%K}-~5ZTb4wN(9U1dETl4&_@;mKZg*jvXmPJ|zXRDfD8GEP1 zJH|K9uZaET^@3oHXRZ%~3xU^%G`9>%DZjx7A zaY7$rt^0FJ?iyvz&uti>2{8Rz0X_S4ht{MWQ-RiJIdx{Qc>f7~Km$)T4g6aHj@y%( z==glczLo)|LZI;~Gp;{EBf*7WTbOITi%z-MOKQ^&d97LJH^Z5D&cQ7LH*rc@ya(fu zj=AHxKJ5-yy0BsH-NF`Ej$dI}=sM}k8>~SaPR+l)=>@6KnEhV%jvAco)Zg<~%MqfWG#-@P@KY&hJwJN#9iQA0=ix>hz)6h@vY#r8vucUb zD}RDTANHooJ1XI2zO-(5#^bJv&#+g8B0yEj2XKv@H2Y92RDn-psqSa}Qr*wtM|u2G zma^e0#9Peb%fFPY@EV@*)lvAJL5XZdjytGWeiUb3V4$4tSO%1Tpd|b?VEkP|ql0bc)l;QHQFW0e=RnZFjudWyhoz++M_YjQ>)jkTV;+--$^`oRNU ziXG>!4CobA0X;`K?+WxrUl?B*K)qlurP6IEoxO3ZvE1S34E4BQ(*&Cs9oS=<-8)*@xx$NBJt!GbS@j!J?_ zk&ZDis)14Q{2tc6C~8^Ayej87 zskiGhJ!@B=eKSXW&^kajU~}NczWA4^yq{nsU}+R6>}!RG0_;>O%Ef{dX#LR1{#>PL zM7r~fgKxCjc||5Wy~@2G^RM{_%t9k9yhHM6(8|2OYefDO8xh;0&JnTSa;tG&u3wvu zGGW)9>*W1*LtG$7sSHe0V`PS0E+rN&%6&aYckuOq5~HKkzZtlp53?Y?TkYNVGrMb( zv%;wg+|-8+NBt`8Y#35ZXRm|SbC)lJRhv6wtn>YYhV}U<)5MNSDa<+hC@4Nr`~A`o zyqV8{7Fhkgl+~cL4m`k2gT0lQeFFwi-)jfZXu>OnZ9&(F-q$&z#y4(#)~R|0J&LhW zvLdg}`gFZIOOZt*wV>&(v>UYXndlW8JN=IP%~sC9hH}FcA;W3zW$G&he13i0YFF@q zTz*q4pAa1}1CKFFq8V@#jaccESV7VJnb+XFM(S(&LH`FfGncGzKKz;8!3VBSj`yP1 zZT3`sNF^2jf9!n;cvR)t_IqZ|tl1_Tge1TW36KE7gf&>yNisP}5G5c`P}GTvo*-zj z)<#R~1Q5`o4TzW^Xi#ediY5qcKrlhk0!lkUR8~7!H6(*NLGheSmih1J%w%C#+wcFs z@4J4uCTDxkd)|F{mivy+vQuj4yDxgC#&F}fF;sKI%*Hlv_+E@?bsSYV|YEMoy z@}W*#J}0XZZTMMd2+9K3>m$-@4d#7~eT<0J!3Ogv(KzQ3w=I5F{L7wcF^Jzr-=dU8 z)Kfn(r~+SOCi-HG9BzAF=q%X@NX>`F*;y5t_jQgCHX0#@p@xpgGp*0N=k}-43#nI1 zFP2I#(BAWIrP8C4tME)?1^V}TYdl$MZj`2J8gI69S5qmWc1{1RkLNhF!f9qUphrDi z5EG@BVoOIqIBC3#eeu~?cke5K;N132}u2n`8o#RvMaf`fF=6cqZ&m8eEK&|P zWi+XkexoW+Luu|tE&d@>OSR}YBG0x`i5uLv#Ai@>qfB}0k;dLP?UNn(lm=C~B~W%~ zC$mw8)4;qEYYj0|z3I(-Ikn(i%q4eW4~M6iSM(Tf%)pol|2wS7zsDBR9E;pC?6su$T8IZ~Oq-vz7ngxbZ0Yco0QP-q@qENTivMNd5S*d*bL_)y0Z zu|CUUe=#$;HWSEGDshQ8efHgnOC7P(CnjbTPQgAY5?ZS>^}q*;dLolJiNT!Y;1Jtl zaer34y&P|56dLWj#mH(VI%h+7fM+CORf}&nJ0A@>=xS8YNKmOAze&^;*u~AaW;gKz zp>K9)i=oRuGiqCTX;)^r(jO*!RiSmVSU1_L*Hga;adIA2B%e0UO|AG?La6iW1eTob z*oslYfE1~P&UjzONUK4tle%Jz2*zkUC&ufQ7`d~H7KFLKPC%?t6P^D|;LdUjCVQho zF@6@)_p=?`AoSeuw>`b@H_~^Ku2bn8vlID(gR?W6G)Y-V{ZJtdqeGi<8pcb_M|~5n zOF;jR%64en7$@co#ymMas;{7PSP<%=;0P&XfBeyFKtoTnm)uQqW9(Ze9m_hHwa{Kd z64HBPjR&`6H>u~$uyNz3$z#oPZ9I_k2^lat>1)VKk7O0?vQOgJhtjREqayC97U|bM z;+|@e7WjxSgVr)8>xW?a3an#3lyYG^ByW2U7HI9&Y!Dl~E7J%>l{(0w)rV+D?3cdu zo5ynF&NL8m6mVr!nBgNs(>QNk2lkBx>O9(oK1|3%CXyjP0iUytHsE{UwpFA{8MY^zyq)Cf3(Q556 zSoFd}NHBWG`k~zx{wY;_t6rVbSG|!dRYQMI*k>hJ(Q{Vd#ofoXveprWs+E(QjsOvq z0sTy;njx!zeilL)?W2+cXzUZT;4{w>7vpXZwvF`Ju<%bHl(=T#GX~i<0;rY5wxI&s zM!M}bAi->a{|fLb6*R_9e7FGe*^w;5JyUn#o@whDcs3Z=%(sJQqYtp+@&vVaA7R@8 zO$_$NHrN}hRL|e!2q#=!ZfN0LAf89sfx@hcwBK0tv8;D93%@cPp7Oci3(!}8CRMic zmETFBkmYNX5g|}Yi-9Q4t>mrTMz!}znMws^GV)j>w^%`h>o|td5A8pcHF3I`z-}ff zB}zoWr`LOQ&`~^UJtz~yd$=mIxnu00CY1^v^JDX|&Wv+`7vp=vk|Mk>^XMR!)b~0d zdl@19A8C6HIB=Q$fWpV_1`b@WAa4ErO-25o4Q{1M_MB5RW;eL8z{gQ1y+er8n*;lp(dJcg0-l^%!yp+E$<2vXa) zZltzfDoAZ3#RtW&fNQoifNM53fDX`!)TRX*0OgaA+Jd-d8sv4zUwz90NNwMrkJNUk zCmMhTNNxF4%9O^QXl>a=$FOE1G=Ml3s4>Fv(HB1<)e~db_yIp?L#fNtJ@H{H=|D-Jp1HTLq6a7T-=2PD=~@ zRy>P?Z|;XuY^x3y(;pYM`F{|}E++&jKBlBNvN&$yhUQH5BX<4Jki)8G8%Nd;n)s-Q zUJ((=eVMA+!6mqFO6}#kIaO7!YR>0k+$!MyM!F-QXEmjTxkGU@ry1Nj9JOw;JG7>$ z+~mh^OOvIue$%c~lc875haU!hTKp36OQs{rPM2#WUw*_ZD&@wNff*1eN;3Q}$u{gb z-tCD3&Uya~v}}?_4nXf)2o&(1OnJAUgeGBrJ9LQhWE7(F^h04mr&x4oVxz+%!@~OZ zX4bS=_f11gt{M2$XN%*Wio0VlQuo40ZN7U? zV+?q@%v=Wc=n)h5K&t(S-H81~hCC@^!(DVNia2>U9T!GyxJPd>i#pg7)iqABkfj)_ zy?PV$@rSY6z|pr6z9sM_b#Egp95w9f6t;_uCt!8&R50;k;eVjwN~(>0r^1Sb84mUaW(%2A@AwHDhxE%cK8oqOyf4C3qu8+ zH`B+J?}b)_tOnJxk;bkPDveMp=gsOM{x|p`!Y-F&z~4#}F~`x!_D8h-uu9{~CduwU z(HO>YcFw!8)tg77The`OFg%|pgscwmGSH}}jCMcp&C@vjO3fP9q}J#~!!sGPQtY~w z3v4#bhL4WameRh45R9EoS_TwjJzybxt9!O zOkrPA8!F}-JbAi&d9Z_dmVv_wsVxUrW(QK6WQE1vX~=`)-XdP6kadJ4dM~UsLYi2} z2;nASe}k@EyLK;-OPr>9V3l;EiWFcG!)RI7J8S5A1aKxS5-K%CGwv5f*})4Z@1 zNTjOdw;SA9^_W+jrk*vZ2P2B!6T((E6en&J66^KwpXI%7U&uP}A$n|V!+iRpvHWxB z064_Keo!)ELTU37G=-o)vB3U{grB z76@Q(!58nwJHmzC_;$bAnb0SFCe3J>Bv7ety94NLd|2ff=`ZaSVuZ3*0Uo@3S{m9G zz_V)u-zsO_Z{TZTZIoD)li_v3c!o>ltdYWZ4OJK$;3aN83EO+)!Rrm2x4&kpoMiRb zj_Fh`F72e_Oaputy+5?M;m>svc3d6X$R{nVIfSWKsb7VMjg_xd!}gN*u4v`UVytAr zHS$jZAM|DLLD$2ID*`Ql3~aYjih(z4*r?3Og^A?DpV^iUuYTe+;(>wif%K$*tK%!j zJRzKHmM{|2d{coi7KG_7TMNtx^IJb>P8GZkFdVVHknsB@L)%_C#-T8&E%xT34WZ{$ zz16Xe0kH$#@8GUTgT8~lV!rp}z34sA?x|d=vd6@}(3FwK1FS6-D}v(oN{1}1Z)c^2 zn9G=VfUI$tMRxXee5DXfF&RM6HH&Rl=IxIs@ZUa%34`~}>Y4+2@A$T&U6hieShrJ| zah1IHg?1Izs>J?&>2h@WJIk>Neux;Kb4sfWuW2Dcf_8&epx&4K+U8<|1tq5OCd=C9 zg^&|*u03h=l;w>bl=B3b&j zmF8`De*4|X(+A+nu_DiJBhTM<&}_#?&~+*Lf=T8bhK;o6?oVfEcdMXLG*P=-#zc)b zqvlfi(s=z~4+*r7DCFzX;bye(Wy6$q)C9jEvV+&66+Mn`rpfnX??#Lq#G#j~)YuDc zm5y|zxd@2Ggnh;PPdUJoff9*vQ98%UDFvql+_~$O%rM+Z6GjyJrREL>J#7Y_r^=?W z%?-?)0$rA3C68RZv%QE`5YQts@TFEb^oX~t6+RC5PH_h;DQ0ZTBuikw^knev{0`HY z?_t41WpMuvnsHsw0G4KsuQiCOI_g1(I*3)3YI8+ZShLv>COG#|o9`!-q6UVy!VotXg4S;8j`|`g|9e}zI@^+wqd=}`Qsd+N^Q`* z{!Eqb4Ib^L7s~8$e5KV#D~B}1^ghsg6B*?nR#MHm3@Aw6wH;KpXQYf)QLKCmt={{m z4juGqX~;_`JTU!IV{47WjI{ZsDINC-=>=A$1e29@E%R1%$neNJBUSmR$Gnf$<7(HH zVvU4xbPd{0MTgEodK_ID>?0UyfjCbEdk?;>DMG9=a#bn%Xj%F*cEUVXo3ivM7#FIP zQUlHa#*WTXTdS1X)4u!Awynt7Q@%i%jY8V)MyjpI<2~(EW_Pt078*z+T!hk^qWDrT zQ+yvq?hVp@r^7#1mhSTfdc~LR1%>(oYEQX9Ii^uZC6iBMAZ6S>*edjurC<6Sg{1oo z$PI|6Zgwm5fMA!Sl`~W9*F)u`zFcYe2hipuam~q$Fsn2&SBAAS+Q{IGwvp?VHlnP_ zvI4wCh|4=ub_zVoaf3Ku9uqO*nfA(hGclf)fL*vwWQC4ujN$jNfp4Q#a(~x*f7hzQ zdK;3wF=rdtz>0e}%BuVn`$ovYXtWy(lw&P7U%(22+W^_cK2azBT_n$8TH(`p(9n{u zj0d;1ll{U6(mQS5guOCfO7@up?k#{Ob9t>v*hqV@<_U~P&JxhKm3`OZ@GKgCHD2cq z`kV7s(KeD}!4IR*U9b&)7qtHZXSgpJ9Kr#cx$}EUez2#=Sz&0k)8*0qo#=~P(p-Gk z=*lr*?9on<2iw#>?GK~Tr#b7H1`f9FYS_A~VKc(KedHr@Iu^ldw;em{40*7bvtU)6 zzZ|%BiiSUx6EnpSF|;-bJMj1{qk}AVsWl)iT$LxIzrH>L{t2A7pATNMIG$<|G5-}h z@NJG8@PsW@Oe(e+xS?3nSYv{*5PuIzbCkZ1Rf6Uq_4@@K8q~fD^9%=WKnG^fz?%Dm zDy?7=p2L{F93_4T`t6%tVP}^Q3g-*PF})?0z_eyowfS7WIhkzzRPNaRLvg4(4TF}1$>Ue0bxz40Rz%J4AS zGG_b)Rq3$Jx^gP%N8}l9!W01-H#BXkTH2Q%hIXkWbB2pE2g8TxUo&BcB!kski_yx0 zw9Eq+R~(b2S6eeNXU#%Pc`}9OEC``9rRYCWzOynu_#HtGfqwHqqdMWqQ(-J}v%#WU zi+V|t!D^o_^m5}}$a)Sm=IA(tQsKwa3>K_St8##Vl(bp5mP?|Ro!m+(pt)|SA8hJK z!Q9rY$`7O|m;tX>#-M8!`Tc*mxy^s=0mdeZsv$hA+hS^&Sr6-OgXqNSfqeg$gGXI$ z(X9+E*RIrV)T|6C=T{ob!31DA0R8g-Fz<$0D0QcOdT>3{So}s+gb-Q0NGMfS{`rZl zxSud7#a18I{F;F{u4y%tB_qWZVa@A8Zk9tsQi0nu6KOWfBXd(}FYdh)GrJSmka<9h zVcz>N?#_bedluf*x4W=LwF%8qvwtRfY@-jp9wsh%y5MyX_|N_)SS zr!dLWSTIc<1P|}=SpBJLi^PX<9D;hIHxO2<*&Jb^QZxFD!BQ(lYo=2Bhp(4AJQ!bi zkN7gtvZ#I+VwE9FJAFe@wl6`;W~#^+MkwVw6UM|eN*V>?lGS*5%oZoXR>80)>sQN_ znXHMs4BjWcc5aiTm;B5ETkgn`0>W{mG7l}+p{%LQ1Le(imA4VBTC((B3zhf9!*i(P=sSGuJ6O~EgYHmP27DDSHriDhrakpTruwl z+gBC>_F;QE?krL6ypF#QAk+rD^AL``aUFr94%ffIF+vFyzJojr>KnDttsAiti9wlH zcD%EN<}5;iWZoe=QiO0z;5=bR$F?U6c|jEUlsK0vBVCpw0T z5h<|87<$7IW_f2zwI_P=%=+iHn1yJI&K(F-jQEExHw*C=HPs}(VcEf@b14H4Pmx1^ zOR?P30Td!-=D4F{GZ3H*=ExD7Wut?b9wWfWt2W1t4r|tOn`JF#BF-Dv9@cEc8lUsN z+^*V4$BOojUG%l9FsIsJJ4z{uog7jBDpJzR@=ik^HEGJCteY{;&M`JMQjkas=}i)JSm4dRBKePJt0hPYShqPJ3BkvHB(tj z>N}*YW=Jm4Pxn4Hp+nPA@ zX2=WI%SPBEug9*MN6IRJMIFUik+0G1xlI~VSaUdMYtor*O+0cC&gjXSwzWVo*R@k=_S)k{0zQ zXRRq*uFS{U99q?1-CiQ3CvcWb6X$WLN#aGb&-b!gxZU^onG~!;6`PwZ=KZv$3T-_! zjcoDzBem3G2L$`UzM6$y&m!A9+iGZg>f`TjIkSbWGz&@ShbQHQn8iEeXm1O|(LWf+ zpKIX#0j&`H)ceEk_9OBJP^DNt;)joL^&TEo|9T;i0+2qx|5c=3$r*av+?vjJ-fY`g zNU8S&_nu-7q6!RNoDDIcP#EM?7ACr zBdmTj6h0AO#0ohFZO_JSq%(79XWOHzg^-s{>BTS?;0-<)EA?v=r;G$f?1;3=*s!J* zGlFQF3x-lyh?OwzVGa^+=uG1cZud65wUBUJl9+d-OqQD~Y|br3If+V&_;pCBEfBvt ztvl}Hz+4N&Eh6rnlmbm>zUWB`_#Zj%KA*OXboA5<+NykkM8*#8J|f@!3%I9=lZMA6f%7ytc0&uIM-8L@h!x;uCQ8H1vuAl z>q0x1<3^t;LhZ_QW zluoYtZ=|)Y0j_!;T=k(nxa#kOPTUCw-9ccWK7bt}^9YeNXWa*^;7;85Yy57JTMwT4 z$OqyJpz^K!3S_HQ*Hk z=D5?M-aFraexErZo&NU6^qC>SJ~M#0lY@Qcjvjp`?FxMcJWSwDCfPU5(o?!v1Ljrl z@$6yfJFpCJ60^)D`_90(|LgjWUz&SS%za66wr(gaDLC{s4@P4?gd}i0Bb!#zSG7yO zuI=s<`!47cfBp~jiC!1!?{mx#Q!$V?Ee=C%~tCYV>=x_6BMt@z(->u5uGUe|=<*!5e zI}>Agk|Gx+IWym!j_dI_!Vd`Sfwb=+=^JTN!83?Fkw4~dp!OxXFOZ(S6TS(^jw`S} z=*)WnO@yOaeE@bu)yJiWkh4oaz2~w|XI}Pc-esR&ec7i&@s!poHZcr7i2O%|iI^j> z?+lYQUN~HeoQ15&3k_4ja~hWgwo?|6&#r(CkxhJ39$_xY{Kb(?;s#jy@9<>y=MPWi zUi26t3m4FNHWG_7Xi$6gfgsxgiWnqYcpup@T>SuSlNxl zNTt?RQX1};p8;OLiAMc6<2oRIt%2-#+-nZ~tGah>m_?8J^zK4OgnI~Nrv0^rjtm2M zSPhT{tz{mt`~Z?put8d+j=wvANa!FoIJKH2 zekBJ&Y ze|`#a)frndjq7yvNXt~7 zq%2_lsF$^FDLv43+w{PilhP1!BDWvv z&66KXZ8lYCk|twsowTP4DfLTV!MFK|D!Z6u&vFc_zPsP8{qD1whjRz@?pyoKH&}+I z*Rp|Xkqyd{2RiVzXw+Xc@NlAlFCN9CbRg$lSzw^D;Y;-!wVU`?MWjUq>jRSSDk#@T zAs-WXM-}xE-o2OB>{0wi)g}t5Rb)0RV1tBudAYxCbB3<+6guVdQCu3h|I-CNR+$anoUNsXuENbV9r9c(q(PmXE)uoVZ z0a}Xpab6CR&?!h~U%5!^pTgH$MIL@)3|6?Dwa8Jd+)Ky3^x(Z>$Dsz2i$RWT+S{l~ z+I7mm45^JWU|j-ffu%z_v=j1%3@3JmGvl@8y5}E{2ltAOjmSD-6`Oz_PaZ6)@7`%P ztDen_5o&5D2vG_3HvT{#o6)8guS-a3;H`;AQ1(p%@LFPIdm zL+-Cj@4&Z%b}ctK;n| z#{$@1TEzt-($A4q2+2ka>u!mMRe9aZ@x15V5YjWxJi&&{av_b{x3DH51)*TS>ofi^DvO@tiS@QVTJ-ye3+r)$?A=W z$2>It*hs;&Zxin0S;$nGe>B+_es+|oYcl9Q#NJVj6pwOTlZBXyVjVkeNm-*Dy##jy zH}u+LxMzDlyQcP6!s{M2q(=Uc(Chj5?+5raXNTFwh`$jAHu3y^cqfi_(7jX}-pJ?Z zY1U{5z5Qj}cXku(#LS!oXB zvIy^!hiC!n?T?SbS~LvYDyypd6sL$>s;*vDYQYXk4SOJBywSRua?O=eFH8p_Dp_RF zxc4abm(UX>Jxy(KH1AWNr8+Io?1%ac7oJOaJb~Iwj5riI*T183Tn}Dy|7hw{vDK#c zxocV*BGKE!Txeymd-RWioq%m1yj(1p1(Hm_eBe0jQ3Kz2?uy@_b{Y5zOFsV_;Vz21 z^E>p7Wb}=mUr|_oqERN%k;oedo}WySr5f$rp(zH9`$hDV4|;Q+j|%c4Rp?2X4wXop z+(=(eV0`?%<=XsCd)yzS``gGCc%SqO#qySV@lvqFkRFF|`gj^SDRdwo8ZZqxfF&klbe-~z@aab#8Np@O7 zbAxko*g=)(gd9UVvD)K+rAUUU6!zt?6UopEG%F01SuNRb5VuY!tbi~}Moo=h8gHfE z-*`80Wkg4TnCfsiHi)8F=%{d<6f5EH=5{zlGwMQFk9d25Nh_}Uq-cmgE?upxzyf99 zXt{cFC+=pG6y3U<>Af-AGmuVJvq*dbzJ)-hxq6YKrQy;gl6;X8x$Q@kNWWl-kWFNu zME>3KnD8^o6g-BdB~03A*BP{q#A;a!e{ovk73%Oxqrs;4f_90GSI8oZ8zSiY!_1MsB?QA)`v<5;Gi+zB1I{NJ2 z79{HamHw2vi1q{KUKp?UG^*8os^gT=V4|$`yw7Po@2Rk6f<$wX3YG~NUtpsURYbbN z43r!8L!rX`-XyNlqh+uQJPqGiRv^MQ%;VHSdW(JiFOV0je9sj|0UB)r<3N7bIB-lF ztFVmGIPe8EehHQrK=*6xvjJYK-agD5 zD<_YW8f?n!f^THds6n0#VerG#xJXO*gS4}awER_9tTDfos1-&!xDlM0;4tyj@njQ%U@*7J}xzV^W*v?Ss^GEYU4LJd<~tW z_c7@fNCydnJy37Xjz{t^hhcqx81*(vwxP~OzfE=hQ%lG%t@fWgvstk(IOq?|Y?mt` zzw`&pnRh`t_7ZBab8d5P)1!p1yFfnLQ-(>;?#Ik zT!mZrMTJ{ef5gUUBq2>72W>@;9FSpF24$EE>RV8T3B);(WUaJ5AbBjeGQhLT5BNq3 zZ6~JP5b=;%4cjpDztO zE`9O!#iW6ox+LfmgA(+FZV7rtK!U!lOBx82ohz_R2PEk4pd?i{q5Lp93_Gb0NeCcDa=A~wPf!t7Y6*o!;{`ykkDvp(owPD#TdwHov$z!n6nzCZS9l4|Gp?UOXuDC z)*r54%2cqF(x-8bebUu66A{k2jbw@lvw$Rq$E3gR2!#c&eka{ICRM=}Z}RuwEZ~LX zQgRT-fMzr31qZf4Zduo8n|@r1JI$YU7VVMS7=LzY5r1~Yf<29y8vbk<>`Z9Oqh` zL)v)ubDV2%PIJwk#s~4n;VCqBD9IXyPrK?FTSdK}p+o^X1bXv4VgS1N21C=+|@i=xT$0QHfMG5DgMx7+# zCRslsD!$tDd4vh_Id*%*!8=55vnl=^U|`W+EU>p4hx`K>1~Md)W>NbxDZAWt@&7Va zd%lR^kL-&l?E&-7t|^CCFL97$V2v7>LqGG4%?x1sUARtzJ{jvYj4tP_&o11H9hW+q ze%!oH_S4<7`Gcqf(=N(cN^PTbQ`=t5-_v%SyWh|&`!8BgYq7GLA?y3|_{)bH;8UOL`wI^vAZOLBW=kuC$~nT`ei*k}c`hb6Qg8daS0U>AHWvEgk;R z``Dgs=|-i;b+)CeTB$7!KW{Jp|J%~VMx~=tl`>~vYE(KZRX`5%f4eQMlApik-)~D> zezXjryDc4+Qk1<|XIs+ws4eNw+xP$PY)e%%*PcBEUxiX-K4#w4${Y>f2pm5l9|qZW z1Aq4KK^^1!ieB+;@RTqJ&uQQT!iC?I4;Gp4#y{O+=}Bl*UH)q3^{qwm>XmZ)>yQ@qE*mQY5Xp%eH0mQ z(KbOOpNCf<(J@_X1sCZHvfMCFksFh~9$r3(&4ii_TqPqd-B&V7j;?;ZF8`?1s%V~n z${U~mQi`UA1J3DKI?7D5Jmx@fai%%yn?iSPu$d*o7{S71b6?tXQLF79yXd-Se~LcuI!3wfxl1`JmAwTmQjdMhQR$Bt+*yh{ zmn*}E{-e27@9fUeh5M?b(sfrz&4~YKYIeSL`P9f@le=8moZ9izT0&=EaK3f9SaLL`nY__{a*Q2F2?a2l&mo2MXerBxSDXZ>FtrDz1GuFMAjaBnA zV_kolSdU0YYkyj6=`7a=YB(^#rBvsMkoi6^CF_W^P1)7+g2~LhAwi!El8I%v{Lx6Z zrKHUTW`kMlEv`YEgA|QH<^=xV*U(#W#iO10rMjGLSl}vic zB1km5wc*{?B#A+J9rrqE!AKWU85)fA5S4`>R<1vP~gU7A8(?(}x}uhRrZKwqB$eGKgF zn?rf%dtM>`w~t|is`1|Dhc}j82j2$g09dj*ZNgFM_(i<~DuK7c8(6X}J{S7Hm$Fmg z9l*n*X22n8G4EVN6UePyKJ7)s{H-`t9B=Dm*Lij7KJb|UPY?V8KKYu3ko|uhj@4p` zBNS{pA2pEuU$`s8b3Gdx^bdf2WOJy>Ca6hHJoy_batC?WKr@&VkkOwMJ;08GRRDBU zPQ6=PmU%z?LF(WSl3WjT8jSz_(T=bfe=rMWF2C}uR>66Ic#!rc#1#b{7 zp%bMLCQr!W0b>31e~AOcIGahq=QG(einww04M`$$6CN$A>dL463v9lug1kV~P2pOg z_^D^uN7-jl-ncu(UiE6UYBek?o)-V$IEWnX#?K;hvd;OrXc4d}AS4&Q1azVp z(Il{8QoY{24p^%ufu6Hr-_|p?N-$zXQf7JcyU^N{JE95SM$}iE9nqpg>;wMvLv0lz zXRT1eowMges)!Lf&T>TRwTon;yfDoSU;g%K77g0&(r*G98I>}28qszpK$~^3QL|Uu z&mT4WUUbwV$fZn{yQz3+bjlmrC2$4(=Q` z8>B2hjhpseml`+cwbHnGp{BXFoLkM6VdP1I7cPfhg`QF1=&5b)_Nn?BC<|9DXM z3`^{2(ms>!`4fy;-P-36y%pGDdXw!^`seXI^v_q%YBK7sazXdpT<+T#)IV?U(m(5= ze+EuC(BSkyce6nk-H8;IE$S*YH3T6cSEz+ba_ZP4AmLod<3 zSHY|F=dKF=r?l@Sr+-fS_9;@sK>Ieg?MUu!-ygM8`#$v6rP}u?AGL3^PQ}7r57eIC z7!^kYH;i=DWZ_H*W1N+9F>``DMOmZ0OkT8TQ2|dl(tAhwQbitC70ai;g4xj{4(Wje zn_I-0fe^#A9s#UJEJ}qLGR;o*{$xYf-Ak&1z2q@)9FTpkQ9lh>RE&xb+q zg1DCKj0juLh@OI&wLq;lRSI_j_g-M=D@8PyXNwN_5&s>SdSt^m06pc4R?r@m6DA^S z(reVu6`;4g3`9Mkakx()<~pz(?xOPpC~lkW6&_Dz%0H~-(P*OvM&T(9w-i`j4e_gJre zEiK!1{(7wmwle>Jz2-eEzDBlAcop2 zt>=nb{=2N_zLZY;ue_cc4tYiqX1s7=n#_+#LLZNimt-1Tgb1cl)~tQy01qNNPL|H( z=Ry3u;lliCje;r1yrFW&mb&li07W$ujLp+!bG{eYkwvgqC7niiZYaj3Vmpo0ePm9{ zTvfopFagEI#C<8{w{t?~7K}L7EwE?Z3-pzJTUe^TR*zjct6f__z8axG0VJd(^1Rnq z`^{AfHUia9)h_3@FQwt_bzABT&RsNf$6)3*2Y2;7krv4Mn|AiJI!(Ul?A;;V`oDZn ze^h$qXYA<@ONm{3`p>0Ixg)WA?mmk>J@5VD5_|d%X=_Jt?!N3Ui1&UB*7N@!yPz+D zaCoI&b69#B9C{cFup15&G#eM8U%*ZiR&YGLCAVUC2ObJwr|9*t!781oc)G$S`neQA zQ+_qV<;gZdwNAB$5dOG9(CjBmgyeWa&kmfgVV3Rv%d2PCclrp5bGse<7cklRL9 zlRW@w?4Zwl82%I~d@bqczLxH58CGo;tnm6a*$zuzK}#Lz#~spyjtdb}diLYEOZ4NH z+kgHl{C|RM?uhixkMt*CJ$%3pOX-SMpVr_frQ15j_UZ1&kuvq;sJAb^2Jets+o&H? zy@Z-Oq@s49*nlsT!5g&_HoHCR#Bqr_S@>`4jQ(fTiTpG6{fDLdy7v7irPb{(_U^2c zuYm7Ob&`9DeSe4ak+LtMI?Nlizhvo&0|1rTWQlyXu7c$??|CI=Qf)OuIy_jPU($AG_}Q8S;a} zzgKDUZF^vaK>mFJoll1Zs8Gx+J=sKBC1V$oI<4>t z>Eg%u)tI`ZopoUIxtO#QD=YXl{bzk^2K*@B8l(vRHBL55_)fCP7y8#6xuO&^#a`7V z#Z+Yfe?(cD$>);yj`P9xKWY)NhfWC~vi$f}>G&S2(yXpk>D0@vO6$&9l@i;ExjL}s z{H{L49l&S@`apH(n)K8~R-*aAmFSU{?v<#z<;Sc<7s=wWOqH>r5svnrCoYU~0@vlCq`x!mIl;6C(ruIb0SkB}_R+xNBm`^0vGLmN2== z(r0p$Ij+WI>Hh(6MsS|M2H&0?ax`C&4Em*6%A29}+&I%{)0pN4&b%Ag6O@RqiK$8+h^_35^l>X;CY+I82TnR!Cqi0oJuU6ToJlMA_oT|V z0}=u)!qg&cs_>rlhYl@J=PiOyGPYPD8KAck@z%3Imou^Vq^E++H1A1|zfF4zXlQ}| z8y?xYt2l!-XGI~(ma8maW=JyZgV5oZt)Tnk&i)K9wH*$#Q~!e?<06huhB|k^R!&+b=&N z2V?_kujwbs2ELHCUmzRM2W0~-QZ#V9Nj7kK8Ng}j=^iqGPo*y)0|<=jp=U9C*db`K9B3^#fMx95CceE0^bdpF1Aoq(=NM_q&P3 z_DAfCg;hdjPQ)`|&C~SWJR3OLfRW#9(q>==Kn!N}v+2LFfwRcwtji&!<*7nF!he;A z@WzMjgqS~22wkmfHuEvhPZ7dbn}K4>%**6qEMKV0nJDZR4#>HsGZDiCAn@$XIYMvh z9|jkFCB9?jGla0!*$U<^Ggk@A?HMbNIX zB7XYPBz&n7X*-H9*{jm0QgG$OZhjMfvKSZf9S0Azc_lP`XC6{kmlOFsg|sRmH|2${qp%e@m6KC}5lCgu znbUto;YccVvoHqXUZivw9=7Kq9F=U$x;#OJ)K?(&>A%TESekWj7Iq7Vl~|w6Ltd*W z-oprQ)~4cX6qd>qGOHY7kg}JifeR%U;h*d(PYP{S>Mam@f|5Hb4dQpX0bg+CEK)*; zK2K#rIkW}KB%~{slkircwnzr6(0( zDLwP@K7w6NciW&+oFZ_~ngzq^K+Bk?w2Y`1auNT2Fc2NiiGA&Ml(`voaodd+d_BMP z_x3>Rv;NAA^2tZ~1L1xd45x+U&mwFR^v|XvXOtG}Zzv?CWV{fyE*HAK!#OulZbKfn z&qTVk&1T&!L5J{_2)z_#ITPW>3lT`i0HFrC%tYK2&KeTCab_^o1SNmDU=&coY`z*{ zQk2+i#+bFlB~+@!Hc4q4gq=13s~@JX$w`|8HhOr5Q_nP(Ynsh0d~HRJ0cSQAwze8I zs$Hvr_fZvL_<$T&Rgt4w3!b!^A=umfE3Csm^*+XC zf6hRa%-A6O)KB^SMN=6o;@bQ+b({Y_ZJS@KYxA#DwfQS>z9Ov6KkX!A8@_Ax&uMA( zZ*OSzAI2OMbGp@kbx524HonbY>}KqPh&F%fnO48!+gAUV2>a3#elS9~*%YKArlJD9 z*Gm0K&hH;#sgq-zb&cHeIyuzoljgNXuctYiAXWaA?#@T8Tugidh{=jH%G!=0kJrymrYfEBMzm3jZ3h zo$u84x1bAt8BashWH|w*HEu6t)M1$i&*4@(Ax|pRD@>xs`p{;5Xebb9{?rhMcM%%T z`eVfzVe(0Tfn0+)nPbWcfwx)uup_eEWNnuAc2M4;p39mJ++MIY&o<-Q)NOZ_Rip>< z(|XAH2a({)nB>KOeyLG?phkf^$7W7a{b0dFnC>J0H(hFdah5 zU>~~|SCz0np^$|*-@`P@lQC^~-^d0=SblH+b-|q6_ZwByi|s(-(^yf*e4G0!cnCV9 zpScEo7c-HxwMVT-tt5V2>=U?{XU+nz0evLYw2JCn1DhGDaoEk+Y^d{)^XuG5ta|~r z-0nKR8I}QqT#t9vIUzVuork~Ejo?5QGz&z0LH9S$-;_OOO!*lpyk)O~;Q%efJ7gtO zsMNWE`}myN4%DrLg9)5(w~(yn!Zf+QSM-Ygw$r#gO5dIkJ6oi%($ zOcQ(7ZuI)tHxkFpYuKaI?sKh)sNF==ZcJ`WUM%YNVa&y9@6Dd+iXF~}xo!T(mizth zOk(W1zJC7)U$y!_#BVEp<+wizeRPef&A$Wv+mF6G0sZ;&V~n|kHvjl#e*aTP8T(=) zV+*mDU}o)lHnif7iUJ@KL^-{romVvfExR`?Pe6d}S(jwB&VPL3ETB;7%0)`)*8 z#|aTH-AUKE5!tY>yz?$PpB7;$NSYJ1T|XCSYKn9_3Og}kHR;t6*gHnTzU-7#*?I_U zWBLKR8>gtu!oq+C1)Ls&Z2k?|nX@DX)l#*)k&VI*JsK%fiG+R`eM)))yCsq(sl|99 zs)f7$BzPWFhcdp?a!Kx|u@B}jmfZ2(fk-w)eQ0fB#&=;{Z`@az@Az(Y8r?gJdof%X z?x}I_mML^EzHi2N37py;|1c2k7u?)e1zZwHWs2`i)w=FVPv9V*VYvmr+i<};ciKBv2txpIo78m>?`K%ZZz3f+_k$g)V|`*-C$l_amVgP-oBy$HECbr z*ew_0{W*9)5%E5TV}HDtg!2tJAB6KEINycyt8ku%^CLJPjq`MzpT+qvaDE-mBQti( zVHvv{1)N`n^HiMQfb%?@XXAVt&gbB~0Oz;hyaeaJ!}%R{pY%X0Ss8KOo$YiyBJ1Us9jIAvF__D)3U6EdK_`cq&47LnFQ7kr}#{9GKN^-gZuq{+uy&vd;t z0&mq67LDCrK=1XF|JKOQ>3&NK6t^X&Q1i>J%t>t3oSCKAgw8KU(z|nK*tg$7?=rlr zzYAlbVikpS+FXqWyr0dM0nKBF=a*gIJPZ5IihBk7hCB7upGaT$_cVsy)BVj*<(re6 zZ2BFZX^(b)?I_-=nK#D1{VsZIpZ{--rfI>q9InO)ytT}<2OuR?o=@*Lccl?B9ieJ| zw!L}|z4f~P{l=JIvO!2)ML{3D?KCz!LNqJ)%S9&eOBK~6{KZod5qmJQ49HXB5^ytd z-Y>u$`Ac~aa{;@Ju5a`mm5W%4-HvoY~`DK#qiTq*rM~8RxyB1y@yI<+41HIoK6j%3C7Ku-mCHHZRl? zOUs|-m{L4N&Mbn{)T@;4SzB=D*KfdXgZqa?Pz_+>W_hNRDGftPE3K}^e)-`@V|dwPna8oeiYjH^jm{LY zGo`Y8pfLsun8>mbuq2KyWzA(u3TMdUMU#@Qn_E5wqM1Iv1g(|pil3Bgir9z(7qM7!-sqO%e)^P|hu@m~sQsU( z;Egxt8ly%teR?YJXTE|2niB@O%~<0`t>*+QR|`ao;Zuft3oSu|w{CiLdA{h_g@dPOq{x4Noa+N)G%l(PgIc*!3>C zlJR5o_Ly?LV{))2%Ag;A*B^$Om>GiB;$X>{)N)wj;FwjhYwF}Z=1ox>xBef!fbiXqil`+fJ<&?WQWEc`Is#d4bpFNE0Z0?DL#= zD%jrlnCM$6z@AD0Mldty$~tBq$Bo_}Owm@P=n;PmQgpaS+c2PQxUHi$x*8Lld|LEM zV`;C~jcCQdC@7(JoTjv6=56%j$`)RVSu)AIe6w7`4uO5>fV_j1#argq={L)7Gpe5m z?0OFYO-LWlTWqGZQp$4}+L9}T@WibC(9+@9tC$9Gz=1@#D0*&MJuTj49e}r2f$>jo zs+V1+u()CNKV{x~Fr|1jb}&F-X57OYn)|9$LsSRf=nE!ocdt}kEgOtJY+-|K53AF4 zDcOgqE%D)o-gdh^rEoc==NfsuJ8+gSk9I%&=Et(iME85k?;-ue+~V>yAswk?EPWFL zwnMx0b_W9!JoCP^)K-r~INb1z#y` z*LZB2wGFJcA&Rk~cXjy7uWj>NfeB(-dl2i5<(bU;p_4|J1M)Cu4BoJyP0@aAL*b~> ze5@~eEk7U^I1k9TI%8IjU3s8!^zyI3B17#rb|v$!^v9yEX1d0fg*ES2#gw0rXIJIK zZROIi-d?kdXb(=FyFDq-0(5O`dN8b&MQb!?f+d+j$TP#_ zbue;mzC5HVT0DmNa_#)(Kr}zr7>fFz?NT?N))N0+%t$J?7uusS9~ii(^?`A=GKa!- zpVJ&j<1gKh>TzzE)9cySf!L|~J4pwCPzC=hyt%a3vsKwz*G!pD2;ArWKj41E3`%vc zXNk#Ebs+F0RCyz6#<_PvfYlIF7F`~@)&11-7#G!}2`NjB(Bgw%t#H-(=v508T)AY>%(f9G#D^ zUR4yBotI^%xzd9(9(MTcf%*6vQJIm?Ry;&C@L5|-DeT5kww*IF^WM{rJAXKwZ48zq z^FG&3b2WJo&T2n{IXR!>$6@@p$D);Vj<^iG70g@L7Ij{VMk7Vmi>7Goc_~_@r0AK8 zq^REoDVo}qB9oG$(HBk8Dx~N)ND&(tXtSY8n^mLD##usxEp{7Ptke5qNxnRg?J0~b zW5dAGH9xGh(1p5MO||uTn@VIuY~II8!dFutIMm2(rBN&T88$GaG-mZn+0&I(0j*+n zB8?L2c9r1DRvkQbO7%ddyV9f4V;umz?NdhVe{Xks&n&(%VN32XtRY`fxYl1WF3r5( z>#(KNE)r;m9O(V~Zy@?Ps?MZ^3gw<$a;`YT8l8o<0$pp)}zWsoWQ{j#ele8`uEL$?!6kY(&~!jeHdw zbU;pa#+DwC6DwlN7H8jdUQV8G;@1+KxjQ^BE4g^t zxa6E%#H8|Q4=wTm8I~gz^3zYH z*F5@hTF-uc-)fR}ej<(WWeXDo%1LFz2|3+KUmYk)vLP2*@3#z36rY>Ax(>AHVpar)Ta?R*eV8UB9m&uhMM40gu5N4=hKjbi5?B4 z8}OCY#R7Ys=9f>TgDtNL(d#Mw)T1jKu-3pVjd`@SSLtD_IS*sip^tZ(dY6{rZyfIF zIE=MUT4m_ZE_u*t>Z4#xvsR4T6{Z2Oz+`5j|Bbyi5?|g4jHj9LBr`YGu z!aXVzn%fS`aglmEy{U7>mLbPLK>b8|tc7BXDNCu=mK)+fk$$IK8*!~uu79muBMx&| zIq^|(VgbaqIz1OpGfXUP(Q0Jv}QdtY!o7)Kc;X zR!Gk~pFZV7uN5=qc0GTR&F%U8_krj4c0KBP85R-h7FQkji9r?oW%~dx#tiQJtV_~|ODlD`Hj%C5)*5J_Utey{^Nz;+CvAZy!|}Ap6vxbLLhO$ z@`yC=z>$R1hQ}Jj+p<^~SZyuKNJv3_KZzA6t6)hqlOJtV1E+tLX)XA;r+~>|Y2nLa zvMAt;8})qyN;v6gqalikfiNZ|%wzXrReMizVX`<-9)*_wF3*j+Mx5guBhGQ0#yd1h z@*;jR*qjZlkLNEYJkpGrTRid>(9G{yi2;7$$t^7`AGR;UcFl0r(0y0A0c=ciJ{ zths7W7WV|xyGrJ=q5NEWW=0%`=-ItT>HfXAe{bjgy>x$`a(^D~&+ELulkU&InM3&b zxIe%1eiiOtJK14PQ<%L{#5DAxnjAWo1&>>UM_2H8I(VdB6bMPZsPn9%>+JQevz<8O z%4(|nSM+*~>dGvTMV&d1a}Z~D0(2_YxfS5O0cN*1)gRyh=e)E0v}$^6fivz?PhO?`;K|9)7=SWwpC>&|cKC+9Di^XN<-UDe#X= z%D(6ER}XyKaePPFL(@i@yeAL7+lohzeAw#G6z`}eNh@Y*p4fCbyB_HOyI`xrc}su= zLAEHiLeAZx&|-pWCiO%7cSIf>JL_n@Q>G&ILM!#yu^y#siHf=Iy z7Cr(-1mgYXMyfC?s7v)=22 z#Dz=Yd7ds#K#!K-e^8ZaK3I(XaC7~HzHw&G+W-%DEv$Cla0D#I2Rg(8k`pk|R1NP0 zW)Z;~&pwx)!5Ur9IO|^gW$tUhR35{~bDp0)oE|Aj0L1nbY-HeIj@5~+xho&pt#UItz3*X zK4cd1nFblWu!LPrtX{XbWhMmdsc(~a;(kff$p^SsR~y)X(bXAVr)K>$ZsZq+eUVZF zN$ksU)d#WUBJ807sgOQp2+lcPBXoMri zi%4)eXoVaR`_L9E=F|Z~y8RPr-8bn#crMzO4Q9S@cTD5ToG{7wNb;F|KxByc7N4w1$}b<|qt)WcTKmZm*?wLI{Jz>eXA+!Y-qi z!!O07Z5QLc9}+4>{baZs!)l3tvk1Olnjo7<2{=6b zQkoz8D%2kD;{HxGW&(0ykz%X;ne=`89j99Ti$u=+I9P1b6$v=`>G@GF|8=Li*>{A|LmM5v5nlq7x zh!)jGo4^hD&fV9{EObZPQi)lPr_n6KFV(zViFOum-sw&ZKL0`P`Furf%HwPxc+>M$ z8*`^~W0=fMperEkLX*)_4Fl4`BHE5E$)8E0q0JAq(5>V$RG3mv8GaF7S&4n zcF*tLH0^R z;@4*2m!#Moj;dWE#!kraz|!IKJMdS6gj zZJkTsWflu?Lt-o+O9B7?07^Y(CKe_rX#bGZzAJs>ODS|zW0(2RU$JiH{^1nAl@3Ej zXcpd;+`jJ{^m%4jWV{O>fKy=MA^zmRvx7bvKB6m+w)$ruY6Vv>J=^K$itVX!wG&gh zdX?F^OKqNnt6Nf8y>r(L=rAMm$X#^5xQj%3dF>r6j9O|qauRJU~Xc^?r6(slxS=0 z*fHsl#%K~r^o9&ZJ*77|Af=+b-#VvCj>o$F-S>U({rC3AV()d%`t7y%+G`JW_8Cky zM=)~6p>3{q+0$lwOB0A|KfdEXc8TNL&&Q_5_m8ui>>jKM=v(Xb+qek(E=A7-MZ9Vh z&9C4Ke(W;#dpUeh&=wTI%&*ed2%Bem%%dXg+!)XKQ`mJQ#1a+a!X-NT-y;HK#6lI~ zQy>EV4I)TJq^J=4fC&0G2)ecy)cm{(Q4R#&bn)NTqgNiyVH0gNn1{uWjQC;=GvV#M zd)}qd`Cnwq>0MOcUNZ|Z+ghKo^jm>FzgMgxuH|PS?_R%Qts`w&{aB>S2=8uw&J$@0 zwR59A=Uq*K@;lpJ@!)4m1>&iQmwFl|UpjH>Vocts8B4A2PBx&O=-W9( zxH=gWA;RXvu;QF_NgUq>{Uh>XR8rJlYN?@Ksj*WAO&v7D^vitQNwUo9vK_?NBO_B! zT;%Wt(}3nsIoGkswf7}DDyoi>t^oOHpepYK9PM`@RiRoE70P_AVcZ^{6-#;x^r@`le;H}oWz$M z$F`kk(FIic=rUy<9~aQdMa#Q|sqn*W7;Nj^07#U(Sf`;Ys&x4yp&e>KW~G7-$MWI&dRd{ zW_B!k+WsP$e~)*6bB4#1-$>knB@I{^7`ff)Hde-MW%)t*vud(%Rg~VX7yuukcPoyH zXlq__i0%d;Yc9bUyW|j`I;%fte<*)WEq#mjku%1Ijo@eHmj?u#!q;^f*Y+eAFS$bX zt*82n_AtS5ZLM)*J{{%o1clL3R7>Ar}VuCL|MM$vsW znbHC7I$@G^n6=*)!F@fc#naz@7Eg`T3I$TNfDy(L;I82)-G56szQAgNz1kg(wof5b zkNVVd#kUIX##ws0s~K@E`0}3~+NiGec(33M`)EtQ#tBy91a~bTRUC?3VojX8&C%qs zxBe6P?1O9r$64^-5ZcJO>-ixYdAET>nPuCwc!pbG8(0X|F_;@CVh^c7jM*fj*1Y@5 zycS#`{v7$#LAsg`w%|XcU>$LQEYso{2V1qzJ7qfssTxSt@#7nZ;#yZVqjZaB0=~Os zDrN5L_D5maVA!&OxuhDr0jN$eS*mT69<(J4C7)zRy#?mJYA=9aJlgn>*FFuxOlvsm zO?ImnsCI(oTbsiQ&Jer3);4g zWc#alJJ4Crs%k<83xkW-;!e{T(wRf8Fxk2c9&&wNk7C$aKyCTe(%rn3u#MSb-jXQY zSVU>EPe`fJI-rWVui2~d1|Mf0$)yLJ1S4+lvBWhd8UglK6WtM?et0m9kcwkaDBuY1z7~t91VL1|MJ?mL_guHU#^mX{=@G?tu)ef71 zJf1shqf(JyrdeXWWvj#c4@GFY?g+1n2e!*5j%sZ0vUYUren<9&!`t1|45a9&%|0 zl}&KBC84cQx~vVmZ3B=`E!ywyq5|X>2#X|Gbfr;Lcagj!x+)1ZTykWUR0~@zXvO`- z0qZ2axJv49p7rFrR!O&Xa}8q84Whdz>rqal32^8mwQ}#I^0@Ft z=`a})BmW0#@t9%vw=2Xiy z_@-iqkkTDC^48#T)LtI5$^S{df7KkzOx&?cCGB*Y?pYzIG}LN_-?lmQ+cH=1qyx)kRxym2MxeFO9AWwFW}I(*X>uQ7vPJ08Lm!Do%u@DiG3!YXJ){Ma@b z9>$}^1ZlqzmcVZ(d~8L5bUUX&x}FnBW0P~cO?2-QA~uJXlZWpYR!Qy7fsolJL{&ax zA&%M%cFuhRbJjM-z`zl7Vp1N_*JOxjsmJ+2JG0a+S)4{)^5_ILOq#Mpb zmGob3O|pF6pYYzZ{bJabD60itN&EG+6mMx&hSnWrNC_Jo&P|AZR-X zZLkz@SgpwT-~d<)+Vo_l?5J}3&+xx}F^y;#@lZqLi`J+C>V{oUHPi*b?|9@hSz-oL zSun6|&~`f;qii+e{3eeJqd0E3bid07Z@`?!o`R>79|3L9p|_KL%vHvO9>8{F$5wfJ zVzokZkt7_)lu&X zEoJDPI^+;lHP$*j!C2A1k`Q+i3#A*t-Cc%$r9+R^HF?%iIkCQ};UcZn$BbKsCj?Yd z-|AH{5qfUqnt&zLZOjlxnjs*4KsTKHMJKwiB=_3#WB36ZECP+yy4b4W2|X)Fo4HCU zWoK@zx0JPfKdk|+0RXuO*n=asK!hSI;>j4-GO$*7u;_#CrQpEkCd%!rB8i zI4ICeOzR6mMO9|wVvEn_9q29NT<9(GSTdv}%o;9RAq!e+NPdyIat*D?D%ME1mK7kc zUt`UcOzjDes252hwj#><=5(^g8rY}5bqz*VJytuk7P*mIgJ+2%=3{)<(W-=20&!Id zmSNUX?+WHRRxqAL{Y&4m4TH{(yn{Af6?sY+#+zzgA^e9hgQ`+2aa41e8;sT8-DQP1 z|Dya$K=H0xKD2TuWa@Ntj0sy|h~DT=JY{HfE*GM-rt@_+-7G7eyso zjFAhnb;2-f0NVU|5_wdQD#0B>^Ey1G7MAVEO(JhxCZdJNmNlHAiheWD?}ZxU1d<)LC3DwdFlh27A+-ERPg%xJ&n{V~({)*ea=!1(naV4B58SPUG%i zc?|4}|2MPoyA}1Ld5mV2+13g6q4F;A7w^yenD&`^$~#0lu8+;=KFY_tpIvz5+A$$4 z{MbcZq$M`|B;F68|N9k7px!Ou-sHz@pLduq(oRzso=ph6@+8|aS@+qM@K}5W%hP4S z6`e8kq*${CUu2T(( zl$Z|B1K9PWhTPJ%fBq~t_NVi>;ve9`d%SU1HFncDb63aPU2HJ!aJk-@Ro&jYJg`|g z4vCpv9b3DuoaeD?pod&>m#o3uXJ|;XxlPa^cR@cYWzOJR!Zp2zAH|Kia^7Tn0oT=! zU!Z*m%hl`sk6dMjPOE*2?P~p`f8DsVgwmF)lkOe2TpcysCu6xfZjvwk)YakryXA-9 zI}UkOx?8@vf!~X7xyF{^>Kt7IYP?`NaJ1vIPGgO0%8m2QheXrKj+m~a9Z7e@Y2wrL z%vTVu$(`)@2fh({7Z-CqpstQHhua#2y)!)GYb&d zhM%C}hiiC~hVP@{^(vl6c{;ng%R_vdhW|mspVsi7X!s)9deu;+9((uU|ezu06uHh{jew>Dn)$si_yivo88s2l~etTZh@U0sDl!ia9;SXx~ zY7PIEhA-3b>omMe!#g#6s)m0-!_U<4RxfY)7+>i?*pK+eXKXyuPk_=u z=fG3=z$^1QWJY|!*kX`RW+KuQc0eWw=X-!2!ZYs2|0%Mun;3Hci?y((iE;!UagD`0R0?9=OmmXYzN{?I8PxKd_2x?1icNSK>GHyGIj^#D~GPQ z8#C35c?4yA8#0t`;$1g;Ae~tR|de4WI*{ zL!iT;i4h!o9MlWXq$VIH%vE40pQDIlfuoS>2R{w+YJ6NjJXa4~#O7|?4nH`&^hm}% zIY7}n4Kd-KRpCzi!6iaYt?!x_=ThN}O(J_@B*&J5-UHnR4f+}C2J+Q&KGLLbuNUX| zC2!VeGUoU-Zw^jI?BM&q|9iyAOkDC3;tc*_Id&R!@8p4B6wH2+j`(GRNPJRK2;a33 z@q$49_AiThraX$ zd@z+KJ)PtCEnzIfq0_}eJ|l(ivln_Z<};DxGMr4@jrwFP(utw3F_!r&-aH<1nVI~+ zfy8I?5gVZ|3;9o(i+BNVh{N%$bWy(#xU4LWZ$tUBa+oL|cZx#b>x?bT4KkfUeY0oq z<`k4a8};Y|J7&XPGhz4abUwJH05R&b9r@?r_-*8qlfxT3oQTm*&9Fxf+J|Ciih&;s zz0Nd)Krw|0|9Y@Loc-PX{xxWx;wP6>{*~nicK~u~zidfTaQ#ZU`@t?hxNjh*#$8KR za8Ijnt$uJfA*aUOeo4W-tipvgKUhC*{{6V0QWac{3OCaat{rk}eLeo5;96C31z%Mm}g*C40Hjm}VTkEw7TKe+LbQ{$e=RB$h;aHCE`aHsv?1}wWD*S=iA4J+-or}47~ z>vsooYJCoug8Q8cH`Na=4RUJSo)rr2k1CwY53T`nYTSte1$R`1+wTY00y#DAPN9Ok zrNXuO!3nGH$CZGm@qJ8Lw_RdSK4_Qp*YC&ue1n2ZR^jY^a1D@Cmvhl31y`oRmHELf zg;K!4GZ<0-a5a!q<7Vts zaNAV4U4C%ChMXF={7(w*pDJ9dA6y~i)VNu@6dd+f@2ywEzI@Owb0DY2-SOh$Rk)dc zaJoO=kNY!tYWG|fuE-B=uLc*jTfx1f!X5F0i-VlHoZ){}aA#CFj~`qlOi}d1bDqN}`T#N=+>c!=&a6A0q4%908rqn6x|K|{sJ$I^br~TkY z?7P35x!?)+r3zuIjdn-4E^$kW>51MK5la3RmU_*Z#Nracd7N`qrv&&3#SiYB7nk$CqHhIa(l=yBw_Wo6;M$Mg zU%!ICE4b%WxN6{D#qndHF3{s2aLfT(1M16^@;KuzqVHr?$&YFYX^I+yvmdaGb7(2p=lfLjn_QXV42p-vYV<;tumn00n`3;oSQ;2Z}q& zvtgk9xF$FW*H?Xk^yCf~*iujlXea1x&>oO4ke+{nKLNT3x(T`s;zo4K#Elf#Fwkhw zG|(K-{{lHczCihGorw1_f)0UBfKGy1K)!JC7yi@pXA7+Em)+<7r~JY1Mb^ugIpUJU z`}0UbzP?a6r#pS(1%XXOSz1)(ITs+Z5WUFSQQmLOq7TLnJR!1=KwpE>KE-o8h~H{r zYy&8L6#Q*8+7Z+Q>I;8-5i|mAlnz?>3C|A23G52&#Jz}o3t+oK*dO%NYVe@NYXlZv zB(Nve3haGQ{5pX(fS!5{b_7jaFR;khfkC_#ao-IBdkv)9D6kcvo1pYf$P4sbvA{k8 zT`3XR!Yw#oi?;t5d7lzk=vM+e_N~BjzXKjr@;!9?fHwURb^xVag8u&!Sm7d(aj5+y zn2TbYH~ytJ9^#G1A?}Iuzd<|@u^x20t1FW*p`g}ay!8pLQLmx;r!?T#vVcX z^wW%yC!_l_WWkbu6j>j{goOyh*F0DV#ULGMNg%%aj5ry>?RUE}?cl?~5B~x4H{#Qv z2v9Wm{)kCm8}w~JW_X-9(**f0#NE9I0^X3;jAyez6k@*i?rC9s>jRn!if`@SzZwVr zSd@LCvj0!rHkb~Z zWq~gLC&tci7&E6cW`M!Edn99D=E3(~#rp;i@N9i9e033I&+yEFxhHWcV;3*+Z00(~ z2CZbQ;WE!saV%pEV;>m>mV@+LFJu3+ufWDEfxp3Sn7_aAoc-+a#^~9@Bj9e(+TkOO2WseA9TsRlOo4Fwz z8=01o=A7%u&UP$jBVPjJOUM6e#>kZXwB&p?(wUO)WFzNi;$KFlGi9VBBRM-WEqP>G zatijb=)}mZ1xRG4EKm~ja&p*6%D~}tW~a@|b*6w%UYwER%!YVI?#R59?3}dBjJaTw z9ZrXg%+6GDfZTmT3UYC}d~j}Z%Dmk93(_+Fpva^;a#CejcIMnHM{;r+HrQm%D6(VT z+_?*q^7H3rLR~fr>n%PNU|w$8g5(it$#Uk7^t2=uijB-kMM;52&Y4s`rIcjs1vyy` zXHx1&xftMkH+~GS`=5oMK`ao2hGWlSP$a_T>wCfH&;NxZJ~=Gw7*X^+scyf23&&_Y zr2J@XByu4W!U7`q4;m{=LB4U0#y**F%;#N%C&D(NJT6k&giMGmNc+m-E8lxKcEdYv z+HsPI##di{KDpm}k5PU!Ruj=!?F&>!3hO~ZAd;gwf{5k_pD5)=K2KviFj*@R7fn)V zCMF#G$-$?0IylO2GKl6BA`>#F{2m7R@(V_0R0h(ES5eC}fhH(#@Z~qiD>sIj*r>U< z9{^;{@JT825pkzLzWkh63lN2Mi^+P4jrPi+DdaT+tsB;z_to}Z|7IBO)uj@SKU0nBdsVd@w#313*>%x3ZawgwNZyt!) zbKbPTOzemU_lV#+YtcM9qXdgLejYJ&W_ejz4(@s{__FSc1eMJf&LF=LzLPlUOYT;s QN!Ebte6%j|1z&ytH&-L@I{*Lx literal 0 HcmV?d00001 diff --git a/app/src/main/assets/lspatch/version.txt b/app/src/main/assets/lspatch/version.txt new file mode 100644 index 00000000..0e2c9395 --- /dev/null +++ b/app/src/main/assets/lspatch/version.txt @@ -0,0 +1 @@ +0.7 \ No newline at end of file diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/LogManager.kt b/app/src/main/kotlin/me/eternal/purrfectsnap/LogManager.kt similarity index 84% rename from app/src/main/kotlin/me/rhunk/snapenhance/LogManager.kt rename to app/src/main/kotlin/me/eternal/purrfectsnap/LogManager.kt index 4d901265..4a4af563 100644 --- a/app/src/main/kotlin/me/rhunk/snapenhance/LogManager.kt +++ b/app/src/main/kotlin/me/eternal/purrfectsnap/LogManager.kt @@ -1,11 +1,11 @@ -package me.rhunk.snapenhance +package me.eternal.purrfectsnap import android.util.Log import com.google.gson.GsonBuilder -import me.rhunk.snapenhance.common.data.FileType -import me.rhunk.snapenhance.common.logger.AbstractLogger -import me.rhunk.snapenhance.common.logger.LogChannel -import me.rhunk.snapenhance.common.logger.LogLevel +import me.eternal.purrfectsnap.common.data.FileType +import me.eternal.purrfectsnap.common.logger.AbstractLogger +import me.eternal.purrfectsnap.common.logger.LogChannel +import me.eternal.purrfectsnap.common.logger.LogLevel import java.io.File import java.io.OutputStream import java.io.RandomAccessFile @@ -159,7 +159,8 @@ class LogManager( fun internalLog(tag: String, logLevel: LogLevel, message: Any?) { synchronized(printLogLock) { runCatching { - val anonymizedMessage = message.toString().let { + val originalMessage = message.toString() + val anonymizedMessage = originalMessage.let { if (remoteSideContext.config.isInitialized() && anonymizeLogs) it.replace(uuidRegex, "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx") .replace(contentUriRegex, "content://xxx") @@ -190,7 +191,7 @@ class LogManager( private fun newLogFile() { val currentTime = System.currentTimeMillis() - logFile = File(logFolder, "snapenhance_${getCurrentDateTime(pathSafe = true)}.log").also { + logFile = File(logFolder, "purrfectsnap_${getCurrentDateTime(pathSafe = true)}.log").also { it.createNewFile() remoteSideContext.sharedPreferences.edit().putString("log_file", it.absolutePath).putLong("last_created", currentTime).apply() } @@ -202,31 +203,33 @@ class LogManager( } fun exportLogsToZip(outputStream: OutputStream) { - val zipOutputStream = ZipOutputStream(outputStream).apply { - setMethod(ZipOutputStream.DEFLATED) - } - - // add device info to zip - zipOutputStream.putNextEntry(ZipEntry("device_info.json")) - val gson = GsonBuilder().setPrettyPrinting().create() - zipOutputStream.write(gson.toJson(remoteSideContext.installationSummary).toByteArray()) - zipOutputStream.closeEntry() - - // add config - zipOutputStream.putNextEntry(ZipEntry("config.json")) - zipOutputStream.write(remoteSideContext.config.exportToString(exportSensitiveData = false).toByteArray()) - zipOutputStream.closeEntry() - - //add logFolder to zip - logFolder.walk().forEach { - if (it.isFile) { - zipOutputStream.putNextEntry(ZipEntry(it.name)) - it.inputStream().copyTo(zipOutputStream) + ZipOutputStream(outputStream).use { zipOutputStream -> + fun putEntry(fileName: String, writer: ZipOutputStream.() -> Unit) { + zipOutputStream.putNextEntry(ZipEntry(fileName)) + zipOutputStream.writer() zipOutputStream.closeEntry() } - } - zipOutputStream.close() + // add device info to zip + putEntry("device_info.json") { + val gson = GsonBuilder().setPrettyPrinting().create() + write(gson.toJson(remoteSideContext.installationSummary).toByteArray()) + } + + // add config + putEntry("config.json") { + write(remoteSideContext.config.exportToString(exportSensitiveData = false).toByteArray()) + } + + // add log files to zip + logFolder.walk().forEach { + if (it.isFile) { + putEntry(it.name) { + write(it.readBytes()) + } + } + } + } } fun newReader(onAddLine: (LogLine) -> Unit) = LogReader(logFile!!).also { @@ -261,4 +264,4 @@ class LogManager( override fun assert(message: Any?, tag: String) { internalLog(tag, LogLevel.ASSERT, message) } -} \ No newline at end of file +} diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/RemoteAccountStorage.kt b/app/src/main/kotlin/me/eternal/purrfectsnap/RemoteAccountStorage.kt similarity index 91% rename from app/src/main/kotlin/me/rhunk/snapenhance/RemoteAccountStorage.kt rename to app/src/main/kotlin/me/eternal/purrfectsnap/RemoteAccountStorage.kt index a5ad1b47..38771650 100644 --- a/app/src/main/kotlin/me/rhunk/snapenhance/RemoteAccountStorage.kt +++ b/app/src/main/kotlin/me/eternal/purrfectsnap/RemoteAccountStorage.kt @@ -1,8 +1,8 @@ -package me.rhunk.snapenhance +package me.eternal.purrfectsnap import android.os.ParcelFileDescriptor -import me.rhunk.snapenhance.bridge.AccountStorage -import me.rhunk.snapenhance.common.util.ktx.toParcelFileDescriptor +import me.eternal.purrfectsnap.bridge.AccountStorage +import me.eternal.purrfectsnap.common.util.ktx.toParcelFileDescriptor class RemoteAccountStorage( private val context: RemoteSideContext diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/RemoteFileHandleManager.kt b/app/src/main/kotlin/me/eternal/purrfectsnap/RemoteFileHandleManager.kt similarity index 90% rename from app/src/main/kotlin/me/rhunk/snapenhance/RemoteFileHandleManager.kt rename to app/src/main/kotlin/me/eternal/purrfectsnap/RemoteFileHandleManager.kt index 6344d83f..62a6d68b 100644 --- a/app/src/main/kotlin/me/rhunk/snapenhance/RemoteFileHandleManager.kt +++ b/app/src/main/kotlin/me/eternal/purrfectsnap/RemoteFileHandleManager.kt @@ -1,13 +1,13 @@ -package me.rhunk.snapenhance +package me.eternal.purrfectsnap import android.os.ParcelFileDescriptor -import me.rhunk.snapenhance.bridge.storage.FileHandle -import me.rhunk.snapenhance.bridge.storage.FileHandleManager -import me.rhunk.snapenhance.common.bridge.FileHandleScope -import me.rhunk.snapenhance.common.bridge.InternalFileHandleType -import me.rhunk.snapenhance.common.bridge.wrapper.LocaleWrapper -import me.rhunk.snapenhance.common.logger.AbstractLogger -import me.rhunk.snapenhance.common.util.ktx.toParcelFileDescriptor +import me.eternal.purrfectsnap.bridge.storage.FileHandle +import me.eternal.purrfectsnap.bridge.storage.FileHandleManager +import me.eternal.purrfectsnap.common.bridge.FileHandleScope +import me.eternal.purrfectsnap.common.bridge.InternalFileHandleType +import me.eternal.purrfectsnap.common.bridge.wrapper.LocaleWrapper +import me.eternal.purrfectsnap.common.logger.AbstractLogger +import me.eternal.purrfectsnap.common.util.ktx.toParcelFileDescriptor import java.io.File import java.io.OutputStream @@ -146,4 +146,3 @@ class RemoteFileHandleManager( }.isSuccess } } - diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/RemoteLocationManager.kt b/app/src/main/kotlin/me/eternal/purrfectsnap/RemoteLocationManager.kt similarity index 68% rename from app/src/main/kotlin/me/rhunk/snapenhance/RemoteLocationManager.kt rename to app/src/main/kotlin/me/eternal/purrfectsnap/RemoteLocationManager.kt index 269e80d5..b0a45b2a 100644 --- a/app/src/main/kotlin/me/rhunk/snapenhance/RemoteLocationManager.kt +++ b/app/src/main/kotlin/me/eternal/purrfectsnap/RemoteLocationManager.kt @@ -1,7 +1,7 @@ -package me.rhunk.snapenhance +package me.eternal.purrfectsnap -import me.rhunk.snapenhance.bridge.location.FriendLocation -import me.rhunk.snapenhance.bridge.location.LocationManager +import me.eternal.purrfectsnap.bridge.location.FriendLocation +import me.eternal.purrfectsnap.bridge.location.LocationManager class RemoteLocationManager( private val remoteSideContext: RemoteSideContext diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/RemoteSideContext.kt b/app/src/main/kotlin/me/eternal/purrfectsnap/RemoteSideContext.kt similarity index 79% rename from app/src/main/kotlin/me/rhunk/snapenhance/RemoteSideContext.kt rename to app/src/main/kotlin/me/eternal/purrfectsnap/RemoteSideContext.kt index 2ea78143..3dacad0b 100644 --- a/app/src/main/kotlin/me/rhunk/snapenhance/RemoteSideContext.kt +++ b/app/src/main/kotlin/me/eternal/purrfectsnap/RemoteSideContext.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance +package me.eternal.purrfectsnap import android.app.Activity import android.content.Context @@ -21,29 +21,30 @@ import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import kotlinx.coroutines.runBlocking -import me.rhunk.snapenhance.bridge.BridgeService -import me.rhunk.snapenhance.common.BuildConfig -import me.rhunk.snapenhance.common.Constants -import me.rhunk.snapenhance.common.action.EnumAction -import me.rhunk.snapenhance.common.bridge.wrapper.LocaleWrapper -import me.rhunk.snapenhance.common.bridge.wrapper.LoggerWrapper -import me.rhunk.snapenhance.common.bridge.wrapper.MappingsWrapper -import me.rhunk.snapenhance.common.config.ModConfig -import me.rhunk.snapenhance.common.logger.fatalCrash -import me.rhunk.snapenhance.common.util.constantLazyBridge -import me.rhunk.snapenhance.common.util.getPurgeTime -import me.rhunk.snapenhance.e2ee.E2EEImplementation -import me.rhunk.snapenhance.scripting.RemoteScriptManager -import me.rhunk.snapenhance.storage.AppDatabase -import me.rhunk.snapenhance.task.TaskManager -import me.rhunk.snapenhance.ui.manager.MainActivity -import me.rhunk.snapenhance.ui.manager.data.InstallationSummary -import me.rhunk.snapenhance.ui.manager.data.ModInfo -import me.rhunk.snapenhance.ui.manager.data.PlatformInfo -import me.rhunk.snapenhance.ui.manager.data.SnapchatAppInfo -import me.rhunk.snapenhance.ui.overlay.RemoteOverlay -import me.rhunk.snapenhance.ui.setup.Requirements -import me.rhunk.snapenhance.ui.setup.SetupActivity +import me.eternal.purrfectsnap.bridge.BridgeService +import me.eternal.purrfectsnap.common.BuildConfig +import me.eternal.purrfectsnap.common.Constants +import me.eternal.purrfectsnap.common.action.EnumAction +import me.eternal.purrfectsnap.common.bridge.wrapper.LocaleWrapper +import me.eternal.purrfectsnap.common.bridge.wrapper.LoggerWrapper +import me.eternal.purrfectsnap.common.bridge.wrapper.MappingsWrapper +import me.eternal.purrfectsnap.common.config.ModConfig +import me.eternal.purrfectsnap.common.logger.fatalCrash +import me.eternal.purrfectsnap.common.util.constantLazyBridge +import me.eternal.purrfectsnap.common.util.getPurgeTime +import me.eternal.purrfectsnap.e2ee.E2EEImplementation +import me.eternal.purrfectsnap.scripting.RemoteScriptManager +import me.eternal.purrfectsnap.storage.AppDatabase +import me.eternal.purrfectsnap.task.RemoteTaskInterface +import me.eternal.purrfectsnap.task.TaskManager +import me.eternal.purrfectsnap.ui.manager.MainActivity +import me.eternal.purrfectsnap.ui.manager.data.InstallationSummary +import me.eternal.purrfectsnap.ui.manager.data.ModInfo +import me.eternal.purrfectsnap.ui.manager.data.PlatformInfo +import me.eternal.purrfectsnap.ui.manager.data.SnapchatAppInfo +import me.eternal.purrfectsnap.ui.overlay.RemoteOverlay +import me.eternal.purrfectsnap.ui.setup.Requirements +import me.eternal.purrfectsnap.ui.setup.SetupActivity import java.io.ByteArrayInputStream import java.lang.ref.WeakReference import java.security.cert.CertificateFactory @@ -73,11 +74,12 @@ class RemoteSideContext( val sharedPreferences: SharedPreferences get() = androidContext.getSharedPreferences("prefs", 0) val fileHandleManager = RemoteFileHandleManager(this) val database = AppDatabase(this) - val trackerDataManager = me.rhunk.snapenhance.storage.TrackerDataManagerImpl(database) + val trackerDataManager = me.eternal.purrfectsnap.storage.TrackerDataManagerImpl(database) val config = ModConfig(androidContext, constantLazyBridge { fileHandleManager }) val translation = LocaleWrapper(androidContext, constantLazyBridge { fileHandleManager }) val mappings = MappingsWrapper(constantLazyBridge { fileHandleManager }) val taskManager = TaskManager(this) + val taskInterface = RemoteTaskInterface(this) val streaksReminder = StreaksReminder(this) val log = LogManager(this) val scriptManager = RemoteScriptManager(this) @@ -88,6 +90,13 @@ class RemoteSideContext( val accountStorage = RemoteAccountStorage(this) val locationManager = RemoteLocationManager(this) + init { + val prefs = androidContext.getSharedPreferences("prefs", 0) + if (!prefs.contains("debug_test_mode")) { + prefs.edit().putBoolean("debug_test_mode", true).apply() + } + } + //used to load bitmoji selfies and download previews val imageLoader by lazy { ImageLoader.Builder(androidContext) @@ -147,7 +156,7 @@ class RemoteSideContext( } scriptManager.runtime.eachModule { - callFunction("module.onSnapEnhanceLoad", androidContext) + callFunction("module.onPurrfectSnapLoad", androidContext) } } @@ -205,12 +214,20 @@ class RemoteSideContext( fun checkForRequirements(overrideRequirements: Int? = null): Boolean { var requirements = overrideRequirements ?: 0 + if (sharedPreferences.getBoolean("setup_in_progress", false)) { + requirements = requirements or Requirements.FIRST_RUN + } if (!config.wasPresent) { requirements = requirements or Requirements.FIRST_RUN } config.root.downloader.saveFolder.get().let { - if (it.isEmpty() || run { + val allowDefaultSaveFolder = sharedPreferences.getBoolean("downloader_use_default_save_folder", false) + if (it.isEmpty()) { + if (!allowDefaultSaveFolder) { + requirements = requirements or Requirements.SAVE_FOLDER + } + } else if (run { val documentFile = runCatching { DocumentFile.fromTreeUri(androidContext, Uri.parse(it)) }.getOrNull() documentFile == null || !documentFile.exists() || !documentFile.canWrite() }) { @@ -248,4 +265,3 @@ class RemoteSideContext( androidContext.startActivity(intent) } } - diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/RemoteTracker.kt b/app/src/main/kotlin/me/eternal/purrfectsnap/RemoteTracker.kt similarity index 56% rename from app/src/main/kotlin/me/rhunk/snapenhance/RemoteTracker.kt rename to app/src/main/kotlin/me/eternal/purrfectsnap/RemoteTracker.kt index cb5bc0a6..65406afa 100644 --- a/app/src/main/kotlin/me/rhunk/snapenhance/RemoteTracker.kt +++ b/app/src/main/kotlin/me/eternal/purrfectsnap/RemoteTracker.kt @@ -1,14 +1,14 @@ -package me.rhunk.snapenhance +package me.eternal.purrfectsnap -import me.rhunk.snapenhance.bridge.logger.TrackerInterface -import me.rhunk.snapenhance.common.data.ScopedTrackerRule -import me.rhunk.snapenhance.common.data.TrackerEventsResult -import me.rhunk.snapenhance.common.data.TrackerRule -import me.rhunk.snapenhance.common.data.TrackerRuleEvent -import me.rhunk.snapenhance.common.util.toSerialized -import me.rhunk.snapenhance.storage.getRuleTrackerScopes -import me.rhunk.snapenhance.storage.getTrackerEvents -import me.rhunk.snapenhance.storage.updateFriendScore +import me.eternal.purrfectsnap.bridge.logger.TrackerInterface +import me.eternal.purrfectsnap.common.data.ScopedTrackerRule +import me.eternal.purrfectsnap.common.data.TrackerEventsResult +import me.eternal.purrfectsnap.common.data.TrackerRule +import me.eternal.purrfectsnap.common.data.TrackerRuleEvent +import me.eternal.purrfectsnap.common.util.toSerialized +import me.eternal.purrfectsnap.storage.getRuleTrackerScopes +import me.eternal.purrfectsnap.storage.getTrackerEvents +import me.eternal.purrfectsnap.storage.updateFriendScore class RemoteTracker( diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/SharedContextHolder.kt b/app/src/main/kotlin/me/eternal/purrfectsnap/SharedContextHolder.kt similarity index 95% rename from app/src/main/kotlin/me/rhunk/snapenhance/SharedContextHolder.kt rename to app/src/main/kotlin/me/eternal/purrfectsnap/SharedContextHolder.kt index af6bf3a8..f0b2d36c 100644 --- a/app/src/main/kotlin/me/rhunk/snapenhance/SharedContextHolder.kt +++ b/app/src/main/kotlin/me/eternal/purrfectsnap/SharedContextHolder.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance +package me.eternal.purrfectsnap import android.app.Activity import android.content.Context diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/StreaksReminder.kt b/app/src/main/kotlin/me/eternal/purrfectsnap/StreaksReminder.kt similarity index 94% rename from app/src/main/kotlin/me/rhunk/snapenhance/StreaksReminder.kt rename to app/src/main/kotlin/me/eternal/purrfectsnap/StreaksReminder.kt index 4ba956ba..3b32041c 100644 --- a/app/src/main/kotlin/me/rhunk/snapenhance/StreaksReminder.kt +++ b/app/src/main/kotlin/me/eternal/purrfectsnap/StreaksReminder.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance +package me.eternal.purrfectsnap import android.app.AlarmManager import android.app.NotificationChannel @@ -10,11 +10,11 @@ import android.content.Intent import androidx.core.app.NotificationCompat import androidx.core.graphics.drawable.toBitmap import kotlinx.coroutines.launch -import me.rhunk.snapenhance.bridge.ForceStartActivity -import me.rhunk.snapenhance.common.util.snap.BitmojiSelfie -import me.rhunk.snapenhance.storage.getFriendStreaks -import me.rhunk.snapenhance.storage.getFriends -import me.rhunk.snapenhance.ui.util.coil.ImageRequestHelper +import me.eternal.purrfectsnap.bridge.ForceStartActivity +import me.eternal.purrfectsnap.common.util.snap.BitmojiSelfie +import me.eternal.purrfectsnap.storage.getFriendStreaks +import me.eternal.purrfectsnap.storage.getFriends +import me.eternal.purrfectsnap.ui.util.coil.ImageRequestHelper import kotlin.time.Duration.Companion.hours import kotlin.time.Duration.Companion.milliseconds import kotlin.time.Duration.Companion.minutes diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/action/EnumQuickActions.kt b/app/src/main/kotlin/me/eternal/purrfectsnap/action/EnumQuickActions.kt similarity index 89% rename from app/src/main/kotlin/me/rhunk/snapenhance/action/EnumQuickActions.kt rename to app/src/main/kotlin/me/eternal/purrfectsnap/action/EnumQuickActions.kt index ad8e2b7b..5786f2d6 100644 --- a/app/src/main/kotlin/me/rhunk/snapenhance/action/EnumQuickActions.kt +++ b/app/src/main/kotlin/me/eternal/purrfectsnap/action/EnumQuickActions.kt @@ -1,11 +1,11 @@ -package me.rhunk.snapenhance.action +package me.eternal.purrfectsnap.action import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.FolderOpen import androidx.compose.material.icons.filled.History import androidx.compose.material.icons.filled.PersonSearch import androidx.compose.ui.graphics.vector.ImageVector -import me.rhunk.snapenhance.ui.manager.Routes +import me.eternal.purrfectsnap.ui.manager.Routes enum class EnumQuickActions( val key: String, diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/bridge/BiometricPromptActivity.kt b/app/src/main/kotlin/me/eternal/purrfectsnap/bridge/BiometricPromptActivity.kt similarity index 95% rename from app/src/main/kotlin/me/rhunk/snapenhance/bridge/BiometricPromptActivity.kt rename to app/src/main/kotlin/me/eternal/purrfectsnap/bridge/BiometricPromptActivity.kt index bfa66264..29940660 100644 --- a/app/src/main/kotlin/me/rhunk/snapenhance/bridge/BiometricPromptActivity.kt +++ b/app/src/main/kotlin/me/eternal/purrfectsnap/bridge/BiometricPromptActivity.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.bridge +package me.eternal.purrfectsnap.bridge import android.content.Intent import android.hardware.biometrics.BiometricManager @@ -8,7 +8,7 @@ import android.os.Bundle import android.os.CancellationSignal import androidx.activity.ComponentActivity import androidx.activity.compose.setContent -import me.rhunk.snapenhance.SharedContextHolder +import me.eternal.purrfectsnap.SharedContextHolder import java.util.concurrent.Executors class BiometricPromptActivity: ComponentActivity() { diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/bridge/BridgeService.kt b/app/src/main/kotlin/me/eternal/purrfectsnap/bridge/BridgeService.kt similarity index 92% rename from app/src/main/kotlin/me/rhunk/snapenhance/bridge/BridgeService.kt rename to app/src/main/kotlin/me/eternal/purrfectsnap/bridge/BridgeService.kt index 3466c890..d9c2bf21 100644 --- a/app/src/main/kotlin/me/rhunk/snapenhance/bridge/BridgeService.kt +++ b/app/src/main/kotlin/me/eternal/purrfectsnap/bridge/BridgeService.kt @@ -1,24 +1,24 @@ -package me.rhunk.snapenhance.bridge +package me.eternal.purrfectsnap.bridge import android.app.Service import android.content.Intent import android.os.IBinder import android.os.ParcelFileDescriptor import kotlinx.coroutines.runBlocking -import me.rhunk.snapenhance.RemoteSideContext -import me.rhunk.snapenhance.SharedContextHolder -import me.rhunk.snapenhance.bridge.snapclient.MessagingBridge -import me.rhunk.snapenhance.common.data.MessagingFriendInfo -import me.rhunk.snapenhance.common.data.MessagingGroupInfo -import me.rhunk.snapenhance.common.data.SocialScope -import me.rhunk.snapenhance.common.logger.LogLevel -import me.rhunk.snapenhance.common.ui.OverlayType -import me.rhunk.snapenhance.common.util.toParcelable -import me.rhunk.snapenhance.download.DownloadProcessor -import me.rhunk.snapenhance.download.FFMpegProcessor -import me.rhunk.snapenhance.storage.* -import me.rhunk.snapenhance.task.Task -import me.rhunk.snapenhance.task.TaskType +import me.eternal.purrfectsnap.RemoteSideContext +import me.eternal.purrfectsnap.SharedContextHolder +import me.eternal.purrfectsnap.bridge.snapclient.MessagingBridge +import me.eternal.purrfectsnap.common.data.MessagingFriendInfo +import me.eternal.purrfectsnap.common.data.MessagingGroupInfo +import me.eternal.purrfectsnap.common.data.SocialScope +import me.eternal.purrfectsnap.common.logger.LogLevel +import me.eternal.purrfectsnap.common.ui.OverlayType +import me.eternal.purrfectsnap.common.util.toParcelable +import me.eternal.purrfectsnap.download.DownloadProcessor +import me.eternal.purrfectsnap.download.FFMpegProcessor +import me.eternal.purrfectsnap.storage.* +import me.eternal.purrfectsnap.task.Task +import me.eternal.purrfectsnap.task.TaskType import java.io.File import java.util.UUID import kotlin.system.measureTimeMillis @@ -213,6 +213,7 @@ class BridgeService : Service() { override fun getAccountStorage() = remoteSideContext.accountStorage override fun getFileHandleManager() = remoteSideContext.fileHandleManager override fun getLocationManager() = remoteSideContext.locationManager + override fun getTaskInterface() = remoteSideContext.taskInterface override fun registerMessagingBridge(bridge: MessagingBridge) { messagingBridge = bridge @@ -249,4 +250,3 @@ class BridgeService : Service() { } } } - diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/bridge/ForceStartActivity.kt b/app/src/main/kotlin/me/eternal/purrfectsnap/bridge/ForceStartActivity.kt similarity index 81% rename from app/src/main/kotlin/me/rhunk/snapenhance/bridge/ForceStartActivity.kt rename to app/src/main/kotlin/me/eternal/purrfectsnap/bridge/ForceStartActivity.kt index 1aa4d3f0..9f037c91 100644 --- a/app/src/main/kotlin/me/rhunk/snapenhance/bridge/ForceStartActivity.kt +++ b/app/src/main/kotlin/me/eternal/purrfectsnap/bridge/ForceStartActivity.kt @@ -1,10 +1,10 @@ -package me.rhunk.snapenhance.bridge +package me.eternal.purrfectsnap.bridge import android.app.Activity import android.content.Intent import android.os.Bundle -import me.rhunk.snapenhance.SharedContextHolder -import me.rhunk.snapenhance.common.Constants +import me.eternal.purrfectsnap.SharedContextHolder +import me.eternal.purrfectsnap.common.Constants class ForceStartActivity : Activity() { override fun onCreate(savedInstanceState: Bundle?) { diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/download/DownloadProcessor.kt b/app/src/main/kotlin/me/eternal/purrfectsnap/download/DownloadProcessor.kt similarity index 83% rename from app/src/main/kotlin/me/rhunk/snapenhance/download/DownloadProcessor.kt rename to app/src/main/kotlin/me/eternal/purrfectsnap/download/DownloadProcessor.kt index fcb0595f..43df5793 100644 --- a/app/src/main/kotlin/me/rhunk/snapenhance/download/DownloadProcessor.kt +++ b/app/src/main/kotlin/me/eternal/purrfectsnap/download/DownloadProcessor.kt @@ -1,9 +1,13 @@ -package me.rhunk.snapenhance.download +package me.eternal.purrfectsnap.download +import android.content.ContentValues import android.content.Intent import android.graphics.Bitmap import android.graphics.BitmapFactory import android.net.Uri +import android.os.Build +import android.os.Environment +import android.provider.MediaStore import android.widget.Toast import androidx.documentfile.provider.DocumentFile import com.google.gson.GsonBuilder @@ -12,25 +16,26 @@ import kotlinx.coroutines.job import kotlinx.coroutines.joinAll import kotlinx.coroutines.launch import kotlinx.coroutines.runBlocking -import me.rhunk.snapenhance.RemoteSideContext -import me.rhunk.snapenhance.bridge.DownloadCallback -import me.rhunk.snapenhance.common.Constants -import me.rhunk.snapenhance.common.ReceiversConfig -import me.rhunk.snapenhance.common.data.FileType -import me.rhunk.snapenhance.common.data.download.DownloadMediaType -import me.rhunk.snapenhance.common.data.download.DownloadMetadata -import me.rhunk.snapenhance.common.data.download.DownloadRequest -import me.rhunk.snapenhance.common.data.download.InputMedia -import me.rhunk.snapenhance.common.data.download.SplitMediaAssetType -import me.rhunk.snapenhance.common.util.snap.MediaDownloaderHelper -import me.rhunk.snapenhance.common.util.snap.RemoteMediaResolver -import me.rhunk.snapenhance.core.features.impl.downloader.decoder.AttachmentType -import me.rhunk.snapenhance.task.PendingTask -import me.rhunk.snapenhance.task.PendingTaskListener -import me.rhunk.snapenhance.task.Task -import me.rhunk.snapenhance.task.TaskStatus -import me.rhunk.snapenhance.task.TaskType +import me.eternal.purrfectsnap.RemoteSideContext +import me.eternal.purrfectsnap.bridge.DownloadCallback +import me.eternal.purrfectsnap.common.Constants +import me.eternal.purrfectsnap.common.ReceiversConfig +import me.eternal.purrfectsnap.common.data.FileType +import me.eternal.purrfectsnap.common.data.download.DownloadMediaType +import me.eternal.purrfectsnap.common.data.download.DownloadMetadata +import me.eternal.purrfectsnap.common.data.download.DownloadRequest +import me.eternal.purrfectsnap.common.data.download.InputMedia +import me.eternal.purrfectsnap.common.data.download.SplitMediaAssetType +import me.eternal.purrfectsnap.common.util.snap.MediaDownloaderHelper +import me.eternal.purrfectsnap.common.util.snap.RemoteMediaResolver +import me.eternal.purrfectsnap.core.features.impl.downloader.decoder.AttachmentType +import me.eternal.purrfectsnap.task.PendingTask +import me.eternal.purrfectsnap.task.PendingTaskListener +import me.eternal.purrfectsnap.task.Task +import me.eternal.purrfectsnap.task.TaskStatus +import me.eternal.purrfectsnap.task.TaskType import java.io.File +import java.io.FileOutputStream import java.io.InputStream import java.net.HttpURLConnection import java.net.URL @@ -114,8 +119,17 @@ class DownloadProcessor ( } val fileName = metadata.outputPath.substringAfterLast("/") + "." + fileType.fileExtension + val configuredFolder = remoteSideContext.config.root.downloader.saveFolder.get().orEmpty().trim() + if (configuredFolder.isBlank()) { + val outputUri = saveToSystemDefault(fileName, fileType, inputFile, metadata) + ?: throw Exception("Failed to save media (no output uri)") + pendingTask.task.extra = outputUri.toString() + pendingTask.success() + callbackOnSuccess(fileName) + return + } - val outputFolder = DocumentFile.fromTreeUri(remoteSideContext.androidContext, Uri.parse(remoteSideContext.config.root.downloader.saveFolder.get())) + val outputFolder = DocumentFile.fromTreeUri(remoteSideContext.androidContext, Uri.parse(configuredFolder)) ?: throw Exception("Failed to open output folder") val outputFileFolder = metadata.outputPath.let { @@ -191,6 +205,60 @@ class DownloadProcessor ( } } + private fun saveToSystemDefault( + fileName: String, + fileType: FileType, + inputFile: File, + metadata: DownloadMetadata, + ): Uri? { + val subPath = metadata.outputPath.substringBeforeLast("/", missingDelimiterValue = "") + .replace("\\", "/") + .trim('/') + val baseRelative = when { + fileType.isImage -> Environment.DIRECTORY_PICTURES + fileType.isVideo -> Environment.DIRECTORY_MOVIES + else -> Environment.DIRECTORY_DOWNLOADS + } + val relativePath = listOfNotNull(baseRelative, "PurrfectSnap", subPath.takeIf { it.isNotBlank() }) + .joinToString("/") + "/" + + return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + val collection = when { + fileType.isImage -> MediaStore.Images.Media.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY) + fileType.isVideo -> MediaStore.Video.Media.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY) + else -> MediaStore.Downloads.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY) + } + val values = ContentValues().apply { + put(MediaStore.MediaColumns.DISPLAY_NAME, fileName) + put(MediaStore.MediaColumns.MIME_TYPE, fileType.mimeType) + put(MediaStore.MediaColumns.RELATIVE_PATH, relativePath) + } + val resolver = remoteSideContext.androidContext.contentResolver + val uri = resolver.insert(collection, values) ?: return null + resolver.openOutputStream(uri)?.use { out -> + inputFile.inputStream().use { it.copyTo(out) } + } ?: return null + uri + } else { + @Suppress("DEPRECATION") + val baseDir = Environment.getExternalStoragePublicDirectory(baseRelative) + val destDir = File(baseDir, "PurrfectSnap" + (if (subPath.isNotBlank()) "/$subPath" else "")) + destDir.mkdirs() + val destFile = File(destDir, fileName) + FileOutputStream(destFile).use { out -> + inputFile.inputStream().use { it.copyTo(out) } + } + runCatching { + remoteSideContext.androidContext.sendBroadcast( + Intent("android.intent.action.MEDIA_SCANNER_SCAN_FILE").apply { + data = Uri.fromFile(destFile) + } + ) + } + Uri.fromFile(destFile) + } + } + private fun createMediaTempFile(): File { return File.createTempFile("media", ".tmp") } @@ -486,4 +554,4 @@ class DownloadProcessor ( enqueue(downloadRequest, downloadMetadata) } -} \ No newline at end of file +} diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/download/FFMpegProcessor.kt b/app/src/main/kotlin/me/eternal/purrfectsnap/download/FFMpegProcessor.kt similarity index 96% rename from app/src/main/kotlin/me/rhunk/snapenhance/download/FFMpegProcessor.kt rename to app/src/main/kotlin/me/eternal/purrfectsnap/download/FFMpegProcessor.kt index ee5f81d6..db67388a 100644 --- a/app/src/main/kotlin/me/rhunk/snapenhance/download/FFMpegProcessor.kt +++ b/app/src/main/kotlin/me/eternal/purrfectsnap/download/FFMpegProcessor.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.download +package me.eternal.purrfectsnap.download import android.media.AudioFormat import android.media.MediaMetadataRetriever @@ -7,12 +7,12 @@ import com.arthenica.ffmpegkit.FFmpegSession import com.arthenica.ffmpegkit.Level import com.arthenica.ffmpegkit.Statistics import kotlinx.coroutines.suspendCancellableCoroutine -import me.rhunk.snapenhance.LogManager -import me.rhunk.snapenhance.RemoteSideContext -import me.rhunk.snapenhance.common.config.impl.DownloaderConfig -import me.rhunk.snapenhance.common.data.download.AudioStreamFormat -import me.rhunk.snapenhance.common.logger.LogLevel -import me.rhunk.snapenhance.task.PendingTask +import me.eternal.purrfectsnap.LogManager +import me.eternal.purrfectsnap.RemoteSideContext +import me.eternal.purrfectsnap.common.config.impl.DownloaderConfig +import me.eternal.purrfectsnap.common.data.download.AudioStreamFormat +import me.eternal.purrfectsnap.common.logger.LogLevel +import me.eternal.purrfectsnap.task.PendingTask import java.io.File import java.util.concurrent.Executors diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/e2ee/E2EEImplementation.kt b/app/src/main/kotlin/me/eternal/purrfectsnap/e2ee/E2EEImplementation.kt similarity index 88% rename from app/src/main/kotlin/me/rhunk/snapenhance/e2ee/E2EEImplementation.kt rename to app/src/main/kotlin/me/eternal/purrfectsnap/e2ee/E2EEImplementation.kt index 43171af3..72bba384 100644 --- a/app/src/main/kotlin/me/rhunk/snapenhance/e2ee/E2EEImplementation.kt +++ b/app/src/main/kotlin/me/eternal/purrfectsnap/e2ee/E2EEImplementation.kt @@ -1,16 +1,10 @@ -package me.rhunk.snapenhance.e2ee +package me.eternal.purrfectsnap.e2ee -import me.rhunk.snapenhance.RemoteSideContext -import me.rhunk.snapenhance.bridge.e2ee.E2eeInterface -import me.rhunk.snapenhance.bridge.e2ee.EncryptionResult -import me.rhunk.snapenhance.core.util.EvictingMap -import org.bouncycastle.pqc.crypto.crystals.kyber.KyberKEMExtractor -import org.bouncycastle.pqc.crypto.crystals.kyber.KyberKEMGenerator -import org.bouncycastle.pqc.crypto.crystals.kyber.KyberKeyGenerationParameters -import org.bouncycastle.pqc.crypto.crystals.kyber.KyberKeyPairGenerator -import org.bouncycastle.pqc.crypto.crystals.kyber.KyberParameters -import org.bouncycastle.pqc.crypto.crystals.kyber.KyberPrivateKeyParameters -import org.bouncycastle.pqc.crypto.crystals.kyber.KyberPublicKeyParameters +import me.eternal.purrfectsnap.RemoteSideContext +import me.eternal.purrfectsnap.bridge.e2ee.E2eeInterface +import me.eternal.purrfectsnap.bridge.e2ee.EncryptionResult +import me.eternal.purrfectsnap.core.util.EvictingMap +import org.bouncycastle.pqc.crypto.crystals.kyber.* import java.io.File import java.security.MessageDigest import java.security.SecureRandom diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/scripting/AutoReloadHandler.kt b/app/src/main/kotlin/me/eternal/purrfectsnap/scripting/AutoReloadHandler.kt similarity index 97% rename from app/src/main/kotlin/me/rhunk/snapenhance/scripting/AutoReloadHandler.kt rename to app/src/main/kotlin/me/eternal/purrfectsnap/scripting/AutoReloadHandler.kt index f9e362aa..8fb1af94 100644 --- a/app/src/main/kotlin/me/rhunk/snapenhance/scripting/AutoReloadHandler.kt +++ b/app/src/main/kotlin/me/eternal/purrfectsnap/scripting/AutoReloadHandler.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.scripting +package me.eternal.purrfectsnap.scripting import android.net.Uri import androidx.documentfile.provider.DocumentFile diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/scripting/RemoteScriptManager.kt b/app/src/main/kotlin/me/eternal/purrfectsnap/scripting/RemoteScriptManager.kt similarity index 89% rename from app/src/main/kotlin/me/rhunk/snapenhance/scripting/RemoteScriptManager.kt rename to app/src/main/kotlin/me/eternal/purrfectsnap/scripting/RemoteScriptManager.kt index 27a71cb5..35cb2a9d 100644 --- a/app/src/main/kotlin/me/rhunk/snapenhance/scripting/RemoteScriptManager.kt +++ b/app/src/main/kotlin/me/eternal/purrfectsnap/scripting/RemoteScriptManager.kt @@ -1,25 +1,25 @@ -package me.rhunk.snapenhance.scripting +package me.eternal.purrfectsnap.scripting import android.annotation.SuppressLint import android.net.Uri import android.os.ParcelFileDescriptor import androidx.documentfile.provider.DocumentFile -import me.rhunk.snapenhance.RemoteSideContext -import me.rhunk.snapenhance.bridge.scripting.AutoReloadListener -import me.rhunk.snapenhance.bridge.scripting.IPCListener -import me.rhunk.snapenhance.bridge.scripting.IScripting -import me.rhunk.snapenhance.common.scripting.ScriptRuntime -import me.rhunk.snapenhance.common.scripting.bindings.BindingSide -import me.rhunk.snapenhance.common.scripting.impl.ConfigInterface -import me.rhunk.snapenhance.common.scripting.impl.ConfigTransactionType -import me.rhunk.snapenhance.common.scripting.type.ModuleInfo -import me.rhunk.snapenhance.common.scripting.type.readModuleInfo -import me.rhunk.snapenhance.common.util.ktx.await -import me.rhunk.snapenhance.common.util.ktx.toParcelFileDescriptor -import me.rhunk.snapenhance.scripting.impl.IPCListeners -import me.rhunk.snapenhance.scripting.impl.ManagerIPC -import me.rhunk.snapenhance.scripting.impl.ManagerScriptConfig -import me.rhunk.snapenhance.storage.isScriptEnabled +import me.eternal.purrfectsnap.RemoteSideContext +import me.eternal.purrfectsnap.bridge.scripting.AutoReloadListener +import me.eternal.purrfectsnap.bridge.scripting.IPCListener +import me.eternal.purrfectsnap.bridge.scripting.IScripting +import me.eternal.purrfectsnap.common.scripting.ScriptRuntime +import me.eternal.purrfectsnap.common.scripting.bindings.BindingSide +import me.eternal.purrfectsnap.common.scripting.impl.ConfigInterface +import me.eternal.purrfectsnap.common.scripting.impl.ConfigTransactionType +import me.eternal.purrfectsnap.common.scripting.type.ModuleInfo +import me.eternal.purrfectsnap.common.scripting.type.readModuleInfo +import me.eternal.purrfectsnap.common.util.ktx.await +import me.eternal.purrfectsnap.common.util.ktx.toParcelFileDescriptor +import me.eternal.purrfectsnap.scripting.impl.IPCListeners +import me.eternal.purrfectsnap.scripting.impl.ManagerIPC +import me.eternal.purrfectsnap.scripting.impl.ManagerScriptConfig +import me.eternal.purrfectsnap.storage.isScriptEnabled import okhttp3.OkHttpClient import okhttp3.Request import java.io.File @@ -258,4 +258,4 @@ class RemoteScriptManager( override fun registerAutoReloadListener(listener: AutoReloadListener?) { autoReloadListener = listener } -} \ No newline at end of file +} diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/scripting/impl/ManagerIPC.kt b/app/src/main/kotlin/me/eternal/purrfectsnap/scripting/impl/ManagerIPC.kt similarity index 89% rename from app/src/main/kotlin/me/rhunk/snapenhance/scripting/impl/ManagerIPC.kt rename to app/src/main/kotlin/me/eternal/purrfectsnap/scripting/impl/ManagerIPC.kt index 908c8721..8da9236c 100644 --- a/app/src/main/kotlin/me/rhunk/snapenhance/scripting/impl/ManagerIPC.kt +++ b/app/src/main/kotlin/me/eternal/purrfectsnap/scripting/impl/ManagerIPC.kt @@ -1,9 +1,9 @@ -package me.rhunk.snapenhance.scripting.impl +package me.eternal.purrfectsnap.scripting.impl import android.os.DeadObjectException -import me.rhunk.snapenhance.bridge.scripting.IPCListener -import me.rhunk.snapenhance.common.scripting.impl.IPCInterface -import me.rhunk.snapenhance.common.scripting.impl.Listener +import me.eternal.purrfectsnap.bridge.scripting.IPCListener +import me.eternal.purrfectsnap.common.scripting.impl.IPCInterface +import me.eternal.purrfectsnap.common.scripting.impl.Listener import java.util.concurrent.ConcurrentHashMap typealias IPCListeners = ConcurrentHashMap>> // channel, eventName -> listeners diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/scripting/impl/ManagerScriptConfig.kt b/app/src/main/kotlin/me/eternal/purrfectsnap/scripting/impl/ManagerScriptConfig.kt similarity index 90% rename from app/src/main/kotlin/me/rhunk/snapenhance/scripting/impl/ManagerScriptConfig.kt rename to app/src/main/kotlin/me/eternal/purrfectsnap/scripting/impl/ManagerScriptConfig.kt index 552f6709..070f8bf4 100644 --- a/app/src/main/kotlin/me/rhunk/snapenhance/scripting/impl/ManagerScriptConfig.kt +++ b/app/src/main/kotlin/me/eternal/purrfectsnap/scripting/impl/ManagerScriptConfig.kt @@ -1,8 +1,8 @@ -package me.rhunk.snapenhance.scripting.impl +package me.eternal.purrfectsnap.scripting.impl import com.google.gson.JsonObject -import me.rhunk.snapenhance.common.scripting.impl.ConfigInterface -import me.rhunk.snapenhance.scripting.RemoteScriptManager +import me.eternal.purrfectsnap.common.scripting.impl.ConfigInterface +import me.eternal.purrfectsnap.scripting.RemoteScriptManager import java.io.File class ManagerScriptConfig( diff --git a/app/src/main/kotlin/me/eternal/purrfectsnap/security/AppIntegrityVerifier.kt b/app/src/main/kotlin/me/eternal/purrfectsnap/security/AppIntegrityVerifier.kt new file mode 100644 index 00000000..ffad2ba0 --- /dev/null +++ b/app/src/main/kotlin/me/eternal/purrfectsnap/security/AppIntegrityVerifier.kt @@ -0,0 +1,10 @@ +package me.eternal.purrfectsnap.security + +import android.content.Context + +object AppIntegrityVerifier { + fun enforce(context: Context) { + // Intentionally disabled: do not perform APK signature/hash enforcement. + return + } +} diff --git a/app/src/main/kotlin/me/eternal/purrfectsnap/security/KeystoreAesGcm.kt b/app/src/main/kotlin/me/eternal/purrfectsnap/security/KeystoreAesGcm.kt new file mode 100644 index 00000000..8d43eff0 --- /dev/null +++ b/app/src/main/kotlin/me/eternal/purrfectsnap/security/KeystoreAesGcm.kt @@ -0,0 +1,60 @@ +package me.eternal.purrfectsnap.security + +import android.security.keystore.KeyGenParameterSpec +import android.security.keystore.KeyProperties +import android.util.Base64 +import java.security.KeyStore +import javax.crypto.Cipher +import javax.crypto.KeyGenerator +import javax.crypto.SecretKey +import javax.crypto.spec.GCMParameterSpec + +object KeystoreAesGcm { + private const val ANDROID_KEYSTORE = "AndroidKeyStore" + private const val AES_MODE = "AES/GCM/NoPadding" + private const val GCM_TAG_BITS = 128 + private const val IV_LEN = 12 + + fun encrypt(alias: String, plaintext: String): String { + val key = getOrCreateKey(alias) + val cipher = Cipher.getInstance(AES_MODE) + cipher.init(Cipher.ENCRYPT_MODE, key) + val iv = cipher.iv + val ciphertext = cipher.doFinal(plaintext.toByteArray(Charsets.UTF_8)) + val out = ByteArray(iv.size + ciphertext.size) + System.arraycopy(iv, 0, out, 0, iv.size) + System.arraycopy(ciphertext, 0, out, iv.size, ciphertext.size) + return Base64.encodeToString(out, Base64.NO_WRAP) + } + + fun decrypt(alias: String, encoded: String): String? { + val raw = runCatching { Base64.decode(encoded, Base64.NO_WRAP) }.getOrNull() ?: return null + if (raw.size <= IV_LEN) return null + val iv = raw.copyOfRange(0, IV_LEN) + val ciphertext = raw.copyOfRange(IV_LEN, raw.size) + val key = getOrCreateKey(alias) + val cipher = Cipher.getInstance(AES_MODE) + cipher.init(Cipher.DECRYPT_MODE, key, GCMParameterSpec(GCM_TAG_BITS, iv)) + return runCatching { cipher.doFinal(ciphertext).toString(Charsets.UTF_8) }.getOrNull() + } + + private fun getOrCreateKey(alias: String): SecretKey { + val ks = KeyStore.getInstance(ANDROID_KEYSTORE).apply { load(null) } + val existing = (ks.getEntry(alias, null) as? KeyStore.SecretKeyEntry)?.secretKey + if (existing != null) return existing + + val keyGenerator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES, ANDROID_KEYSTORE) + val spec = KeyGenParameterSpec.Builder( + alias, + KeyProperties.PURPOSE_ENCRYPT or KeyProperties.PURPOSE_DECRYPT + ) + .setKeySize(256) + .setBlockModes(KeyProperties.BLOCK_MODE_GCM) + .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE) + .setRandomizedEncryptionRequired(true) + .build() + keyGenerator.init(spec) + return keyGenerator.generateKey() + } +} + diff --git a/app/src/main/kotlin/me/eternal/purrfectsnap/security/SecurityAbort.kt b/app/src/main/kotlin/me/eternal/purrfectsnap/security/SecurityAbort.kt new file mode 100644 index 00000000..f8bcec3d --- /dev/null +++ b/app/src/main/kotlin/me/eternal/purrfectsnap/security/SecurityAbort.kt @@ -0,0 +1,12 @@ +package me.eternal.purrfectsnap.security + +import android.os.Process +import kotlin.system.exitProcess + +object SecurityAbort { + fun failFast(): Nothing { + Process.killProcess(Process.myPid()) + exitProcess(139) + } +} + diff --git a/app/src/main/kotlin/me/eternal/purrfectsnap/security/SigningCertSha256.kt b/app/src/main/kotlin/me/eternal/purrfectsnap/security/SigningCertSha256.kt new file mode 100644 index 00000000..5cb390de --- /dev/null +++ b/app/src/main/kotlin/me/eternal/purrfectsnap/security/SigningCertSha256.kt @@ -0,0 +1,31 @@ +package me.eternal.purrfectsnap.security + +import android.content.Context +import android.content.pm.PackageManager +import java.security.MessageDigest + +object SigningCertSha256 { + fun get(context: Context): String { + val signatures = runCatching { + val pm = context.packageManager + val pkg = context.packageName + val pkgInfo = if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.P) { + pm.getPackageInfo(pkg, PackageManager.GET_SIGNING_CERTIFICATES) + } else { + @Suppress("DEPRECATION") + pm.getPackageInfo(pkg, PackageManager.GET_SIGNATURES) + } + if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.P) { + pkgInfo.signingInfo?.apkContentsSigners?.map { it.toByteArray() } + } else { + @Suppress("DEPRECATION") + pkgInfo.signatures?.map { it.toByteArray() } + } + }.getOrNull().orEmpty() + + val first = signatures.firstOrNull() ?: return "" + val digest = MessageDigest.getInstance("SHA-256").digest(first) + return digest.joinToString("") { "%02x".format(it) } + } +} + diff --git a/app/src/main/kotlin/me/eternal/purrfectsnap/setup/patch/APKMirror.kt b/app/src/main/kotlin/me/eternal/purrfectsnap/setup/patch/APKMirror.kt new file mode 100644 index 00000000..24ea01b0 --- /dev/null +++ b/app/src/main/kotlin/me/eternal/purrfectsnap/setup/patch/APKMirror.kt @@ -0,0 +1,97 @@ +package me.eternal.purrfectsnap.setup.patch + +import okhttp3.OkHttpClient +import okhttp3.Request +import org.jsoup.Jsoup +import java.net.UnknownHostException +import java.util.concurrent.TimeUnit +import kotlin.math.absoluteValue + +data class DownloadItem( + val title: String, + val releaseDate: String, + val downloadPage: String +) { + val shortTitle: String = title.substringBefore("(").trim() + val hash: String = (title + releaseDate + downloadPage).hashCode().absoluteValue.toString(16) + val isBeta: Boolean = title.contains("Beta", ignoreCase = true) +} + +class APKMirror { + val okhttpClient = OkHttpClient.Builder() + .callTimeout(1, TimeUnit.HOURS) + .connectTimeout(1, TimeUnit.HOURS) + .readTimeout(1, TimeUnit.HOURS) + .writeTimeout(1, TimeUnit.HOURS) + .addInterceptor { + it.proceed( + it.request().newBuilder() + .addHeader("User-Agent", System.getProperty("http.agent") ?: "Mozilla/5.0") + .build() + ) + } + .build() + + companion object { + private const val BASE_URL = "https://www.apkmirror.com" + private const val FETCH_BUILD_URL = + "$BASE_URL/apk/snap-inc/snapchat/variant-%7B%22arches_slug%22%3A%5B%22arm64-v8a%22%2C%22armeabi-v7a%22%5D%2C%22dpis_slug%22%3A%5B%22nodpi%22%5D%7D/page/{page}/" + } + + fun fetchDownloadLink(downloadPageUri: String): String? { + try { + okhttpClient.newCall( + Request.Builder() + .url("$BASE_URL$downloadPageUri") + .build() + ).execute().use { response -> + if (!response.isSuccessful) return null + val bodyString = response.body?.string() ?: return null + val finalDownloadPageUri = + Jsoup.parse(bodyString).getElementsByClass("downloadButton").first()?.attr("href") + ?: return null + + okhttpClient.newCall( + Request.Builder() + .url("$BASE_URL$finalDownloadPageUri") + .build() + ).execute().use { response2 -> + if (!response2.isSuccessful) return null + val bodyString2 = response2.body?.string() ?: return null + val document = Jsoup.parse(bodyString2) + val downloadLink = document.getElementById("download-link")?.attr("href") ?: return null + return BASE_URL + downloadLink + } + } + } catch (e: UnknownHostException) { + throw DNSBlockedException(e) + } + } + + fun fetchSnapchatVersions(page: Int = 1): List? { + try { + val versions = mutableListOf() + okhttpClient.newCall( + Request.Builder() + .url(FETCH_BUILD_URL.replace("{page}", page.toString())) + .build() + ).execute().use { response -> + if (!response.isSuccessful) return null + val bodyString = response.body?.string() ?: return null + val document = Jsoup.parse(bodyString) + document.getElementById("primary")?.getElementsByClass("appRow")?.forEach { app -> + val title = app.getElementsByTag("h5").first()?.attr("title") ?: return@forEach + val releaseDate = app.getElementsByClass("dateyear_utc").attr("data-utcdate") ?: return@forEach + val downloadPage = app.getElementsByClass("downloadLink").first()?.attr("href") ?: return@forEach + + versions.add(DownloadItem(title, releaseDate, downloadPage)) + } + } + return versions + } catch (e: UnknownHostException) { + throw DNSBlockedException(e) + } + } +} + +class DNSBlockedException(e: Throwable) : Exception(e) diff --git a/manager/src/main/kotlin/me/rhunk/snapenhance/manager/patch/util/ApkSignatureHelper.kt b/app/src/main/kotlin/me/eternal/purrfectsnap/setup/patch/ApkSignatureHelper.kt similarity index 83% rename from manager/src/main/kotlin/me/rhunk/snapenhance/manager/patch/util/ApkSignatureHelper.kt rename to app/src/main/kotlin/me/eternal/purrfectsnap/setup/patch/ApkSignatureHelper.kt index 5121f304..dc294ef6 100644 --- a/manager/src/main/kotlin/me/rhunk/snapenhance/manager/patch/util/ApkSignatureHelper.kt +++ b/app/src/main/kotlin/me/eternal/purrfectsnap/setup/patch/ApkSignatureHelper.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.manager.patch.util; +package me.eternal.purrfectsnap.setup.patch import com.android.tools.build.apkzlib.sign.SigningExtension import com.android.tools.build.apkzlib.sign.SigningOptions @@ -15,11 +15,12 @@ import java.util.Enumeration import java.util.jar.JarEntry import java.util.jar.JarFile - -//https://github.com/LSPosed/LSPatch/blob/master/patch/src/main/java/org/lsposed/patch/util/ApkSignatureHelper.java +// Ported from LSPosed/LSPatch helper object ApkSignatureHelper { - private val APK_V2_MAGIC = charArrayOf('A', 'P', 'K', ' ', 'S', 'i', 'g', ' ', - 'B', 'l', 'o', 'c', 'k', ' ', '4', '2') + private val APK_V2_MAGIC = charArrayOf( + 'A', 'P', 'K', ' ', 'S', 'i', 'g', ' ', + 'B', 'l', 'o', 'c', 'k', ' ', '4', '2' + ) fun provideSigningExtension(keyStoreInputStream: InputStream): SigningExtension { val keyStore = KeyStore.getInstance(KeyStore.getDefaultType()) @@ -38,10 +39,9 @@ object ApkSignatureHelper { } private fun toChars(mSignature: ByteArray): CharArray { - val N = mSignature.size - val N2 = N * 2 - val text = CharArray(N2) - for (j in 0 until N) { + val n = mSignature.size + val text = CharArray(n * 2) + for (j in 0 until n) { val v = mSignature[j] var d = v.toInt() shr 4 and 0xf text[j * 2] = (if (d >= 10) 'a'.code + d - 10 else '0'.code + d).toChar() @@ -62,7 +62,7 @@ object ApkSignatureHelper { } `is`.close() return je?.certificates as Array? - } catch (e: Exception) { + } catch (_: Exception) { } return null } @@ -83,12 +83,8 @@ object ApkSignatureHelper { val entries: Enumeration<*> = jarFile.entries() while (entries.hasMoreElements()) { val je = entries.nextElement() as JarEntry - if (je.isDirectory) { - continue - } - if (je.name.startsWith("META-INF/")) { - continue - } + if (je.isDirectory) continue + if (je.name.startsWith("META-INF/")) continue val localCerts = loadCertificates(jarFile, je, readBuffer) if (certs == null) { certs = localCerts @@ -110,7 +106,7 @@ object ApkSignatureHelper { } jarFile.close() return if (certs != null) String(toChars(certs[0]!!.encoded)) else null - } catch (ignored: Throwable) { + } catch (_: Throwable) { } return null } @@ -132,7 +128,6 @@ object ApkSignatureHelper { throw UnsupportedEncodingException("no apk v2") } - // Read and compare size fields apk.seek((offset - 0x18).toLong()) apk.readFully(buffer.array(), 0x0, 0x8) buffer.rewind() @@ -140,20 +135,17 @@ object ApkSignatureHelper { val block = ByteBuffer.allocate(size + 0x8) block.order(ByteOrder.LITTLE_ENDIAN) apk.seek((offset - block.capacity()).toLong()) - apk.readFully(block.array(), 0x0, block.capacity()) + apk.readFully(block.array(), 0, block.capacity()) if (size.toLong() != block.getLong()) { throw UnsupportedEncodingException("no apk v2") } while (block.remaining() > 24) { size = block.getLong().toInt() if (block.getInt() == 0x7109871a) { - // signer-sequence length, signer length, signed data length block.position(block.position() + 12) - size = block.getInt() // digests-sequence length - - // digests, certificates length + size = block.getInt() block.position(block.position() + size + 0x4) - size = block.getInt() // certificate length + size = block.getInt() break } else { block.position(block.position() + size - 0x4) @@ -164,4 +156,4 @@ object ApkSignatureHelper { return String(toChars(certificate)) } } -} \ No newline at end of file +} diff --git a/app/src/main/kotlin/me/eternal/purrfectsnap/setup/patch/AutoPatchServer.kt b/app/src/main/kotlin/me/eternal/purrfectsnap/setup/patch/AutoPatchServer.kt new file mode 100644 index 00000000..0c5cbae0 --- /dev/null +++ b/app/src/main/kotlin/me/eternal/purrfectsnap/setup/patch/AutoPatchServer.kt @@ -0,0 +1,62 @@ +package me.eternal.purrfectsnap.setup.patch + +import com.google.gson.JsonParser +import java.util.concurrent.TimeUnit +import okhttp3.OkHttpClient +import okhttp3.Request + +class AutoPatchServer( + private val okHttpClient: OkHttpClient = OkHttpClient.Builder() + .callTimeout(1, TimeUnit.MINUTES) + .connectTimeout(30, TimeUnit.SECONDS) + .readTimeout(5, TimeUnit.MINUTES) + .writeTimeout(5, TimeUnit.MINUTES) + .addInterceptor { chain -> + chain.proceed( + chain.request().newBuilder() + .addHeader("Accept", "application/vnd.github+json") + .addHeader("User-Agent", "PurrfectSnap") + .build() + ) + } + .build() +) { + data class LatestApk( + val tagName: String, + val apkName: String, + val downloadUrl: String, + ) + + fun fetchLatestSnapchatApk(): LatestApk? { + val request = Request.Builder() + .url("https://api.github.com/repos/particle-box/auto-patch-server/releases/latest") + .build() + + okHttpClient.newCall(request).execute().use { response -> + if (!response.isSuccessful) return null + val json = response.body?.string() ?: return null + val release = JsonParser.parseString(json).asJsonObject + val tagName = release.getAsJsonPrimitive("tag_name")?.asString ?: "latest" + + val assets = release.getAsJsonArray("assets") ?: return null + val apkAssets = assets.mapNotNull { element -> + val asset = element.asJsonObject + val name = asset.getAsJsonPrimitive("name")?.asString ?: return@mapNotNull null + val downloadUrl = asset.getAsJsonPrimitive("browser_download_url")?.asString ?: return@mapNotNull null + if (!name.endsWith(".apk", ignoreCase = true)) return@mapNotNull null + name to downloadUrl + } + + val selected = apkAssets.firstOrNull { it.first.contains("snapchat", ignoreCase = true) } + ?: apkAssets.firstOrNull() + ?: return null + + return LatestApk( + tagName = tagName, + apkName = selected.first, + downloadUrl = selected.second, + ) + } + } +} + diff --git a/app/src/main/kotlin/me/eternal/purrfectsnap/setup/patch/Constants.kt b/app/src/main/kotlin/me/eternal/purrfectsnap/setup/patch/Constants.kt new file mode 100644 index 00000000..d2e770f7 --- /dev/null +++ b/app/src/main/kotlin/me/eternal/purrfectsnap/setup/patch/Constants.kt @@ -0,0 +1,7 @@ +package me.eternal.purrfectsnap.setup.patch + +// Mirrors LSPatch constant used to flag patched APKs. +object Constants { + const val PROXY_APP_COMPONENT_FACTORY = + "org.lsposed.lspatch.metaloader.LSPAppComponentFactoryStub" +} diff --git a/manager/src/main/kotlin/me/rhunk/snapenhance/manager/patch/util/DexLibExt.kt b/app/src/main/kotlin/me/eternal/purrfectsnap/setup/patch/DexLibExt.kt similarity index 69% rename from manager/src/main/kotlin/me/rhunk/snapenhance/manager/patch/util/DexLibExt.kt rename to app/src/main/kotlin/me/eternal/purrfectsnap/setup/patch/DexLibExt.kt index d0bdf350..3e5fc7f0 100644 --- a/manager/src/main/kotlin/me/rhunk/snapenhance/manager/patch/util/DexLibExt.kt +++ b/app/src/main/kotlin/me/eternal/purrfectsnap/setup/patch/DexLibExt.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.manager.patch.util +package me.eternal.purrfectsnap.setup.patch import com.android.tools.smali.dexlib2.Opcodes import com.android.tools.smali.dexlib2.dexbacked.DexBackedDexFile @@ -11,19 +11,17 @@ import java.io.BufferedInputStream import java.io.File import java.io.InputStream - private fun obfuscateStrings(dexFile: DexFile, dexStrings: Map): DexPool { - val dexPool = object: DexPool(dexFile.opcodes) { + val dexPool = object : DexPool(dexFile.opcodes) { override fun getSectionProvider(): SectionProvider { val dexPool = this - return object: DexPoolSectionProvider() { - override fun getStringSection() = object: StringPool(dexPool) { + return object : DexPoolSectionProvider() { + override fun getStringSection() = object : StringPool(dexPool) { private val cacheMap = mutableMapOf() override fun intern(string: CharSequence) { dexStrings[string.toString()]?.let { cacheMap[string.toString()] = it - println("mapping $string to $it") super.intern(it) return } @@ -31,15 +29,11 @@ private fun obfuscateStrings(dexFile: DexFile, dexStrings: Map) } override fun getItemIndex(key: CharSequence): Int { - return cacheMap[key.toString()]?.let { - internedItems[it] - } ?: super.getItemIndex(key) + return cacheMap[key.toString()]?.let { internedItems[it] } ?: super.getItemIndex(key) } override fun getItemIndex(key: StringReference): Int { - return cacheMap[key.toString()]?.let { - internedItems[it] - } ?: super.getItemIndex(key) + return cacheMap[key.toString()]?.let { internedItems[it] } ?: super.getItemIndex(key) } } } @@ -51,10 +45,14 @@ private fun obfuscateStrings(dexFile: DexFile, dexStrings: Map) return dexPool } -fun InputStream.obfuscateDexFile(cacheFolder: File, dexStrings: Map) - = this.obfuscateDexFile(cacheFolder, { true }, dexStrings)!! +fun InputStream.obfuscateDexFile(cacheFolder: File, dexStrings: Map) = + this.obfuscateDexFile(cacheFolder, { true }, dexStrings)!! -fun InputStream.obfuscateDexFile(cacheFolder: File, filter: (DexFile) -> Boolean, dexStrings: Map): File? { +fun InputStream.obfuscateDexFile( + cacheFolder: File, + filter: (DexFile) -> Boolean, + dexStrings: Map +): File? { val dexFile = DexBackedDexFile.fromInputStream(Opcodes.forApi(29), BufferedInputStream(this)) if (!filter(dexFile)) return null val outputFile = File.createTempFile("dexobf", ".dex", cacheFolder) diff --git a/manager/src/main/kotlin/me/rhunk/snapenhance/manager/patch/LSPatch.kt b/app/src/main/kotlin/me/eternal/purrfectsnap/setup/patch/LSPatch.kt similarity index 60% rename from manager/src/main/kotlin/me/rhunk/snapenhance/manager/patch/LSPatch.kt rename to app/src/main/kotlin/me/eternal/purrfectsnap/setup/patch/LSPatch.kt index f7fb18b1..9302de6d 100644 --- a/manager/src/main/kotlin/me/rhunk/snapenhance/manager/patch/LSPatch.kt +++ b/app/src/main/kotlin/me/eternal/purrfectsnap/setup/patch/LSPatch.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.manager.patch +package me.eternal.purrfectsnap.setup.patch import android.content.Context import com.android.tools.build.apkzlib.zip.AlignmentRules @@ -8,10 +8,6 @@ import com.google.gson.Gson import com.wind.meditor.core.ManifestEditor import com.wind.meditor.property.AttributeItem import com.wind.meditor.property.ModificationProperty -import me.rhunk.snapenhance.manager.patch.config.Constants.PROXY_APP_COMPONENT_FACTORY -import me.rhunk.snapenhance.manager.patch.config.PatchConfig -import me.rhunk.snapenhance.manager.patch.util.ApkSignatureHelper -import me.rhunk.snapenhance.manager.patch.util.ApkSignatureHelper.provideSigningExtension import java.io.ByteArrayInputStream import java.io.ByteArrayOutputStream import java.io.File @@ -20,21 +16,17 @@ import kotlin.io.encoding.Base64 import kotlin.io.encoding.ExperimentalEncodingApi import kotlin.random.Random - -//https://github.com/LSPosed/LSPatch/blob/master/patch/src/main/java/org/lsposed/patch/LSPatch.java class LSPatch( private val context: Context, - private val modules: Map, //packageName -> file + private val modules: Map, // packageName -> module file private val obfuscate: Boolean, private val printLog: (Any) -> Unit ) { private fun patchManifest(data: ByteArray, lspatchMetadata: Pair): ByteArray { val property = ModificationProperty() - - property.addApplicationAttribute(AttributeItem("appComponentFactory", PROXY_APP_COMPONENT_FACTORY)) + property.addApplicationAttribute(AttributeItem("appComponentFactory", Constants.PROXY_APP_COMPONENT_FACTORY)) property.addMetaData(ModificationProperty.MetaData(lspatchMetadata.first, lspatchMetadata.second)) - return ByteArrayOutputStream().apply { ManifestEditor(ByteArrayInputStream(data), this, property).processManifest() flush() @@ -46,34 +38,25 @@ class LSPatch( printLog("Resigning ${inputApkFile.absolutePath} to ${outputFile.absolutePath}") val dstZFile = ZFile.openReadWrite(outputFile, ZFileOptions()) val inZFile = ZFile.openReadOnly(inputApkFile) - - inZFile.entries().forEach { entry -> - dstZFile.add(entry.centralDirectoryHeader.name, entry.open()) - } - - // sign apk + inZFile.entries().forEach { entry -> dstZFile.add(entry.centralDirectoryHeader.name, entry.open()) } runCatching { - provideSigningExtension(context.assets.open("lspatch/keystore.jks")).register(dstZFile) - }.onFailure { - throw Exception("Failed to sign apk", it) - } - + ApkSignatureHelper.provideSigningExtension(context.assets.open("lspatch/keystore.jks")).register(dstZFile) + }.onFailure { throw Exception("Failed to sign apk", it) } dstZFile.realign() dstZFile.close() inZFile.close() printLog("Done") } - private fun uniqueHash(): String { - return Random.nextBytes(Random.nextInt(5, 10)).joinToString("") { "%02x".format(it) } - } + private fun uniqueHash(): String = Random.nextBytes(Random.nextInt(5, 10)).joinToString("") { "%02x".format(it) } @Suppress("UNCHECKED_CAST") @OptIn(ExperimentalEncodingApi::class) private fun patchApk(inputApkFile: File, outputFile: File) { printLog("Patching ${inputApkFile.absolutePath} to ${outputFile.absolutePath}") - val obfuscationCacheFolder = File(context.cacheDir, "lspatch").apply { + val cacheRoot = context.cacheDir ?: throw IllegalStateException("context.cacheDir is null") + val obfuscationCacheFolder = File(cacheRoot, "lspatch").apply { if (exists()) deleteRecursively() mkdirs() } @@ -86,75 +69,69 @@ class LSPatch( loaderFilePath = uniqueHash(), libNativeFilePath = mapOf( "arm64-v8a" to uniqueHash() + ".so", - "armeabi-v7a" to uniqueHash() + ".so", + "armeabi-v7a" to uniqueHash() + ".so" ), originApkPath = uniqueHash(), cachedOriginApkPath = uniqueHash(), openAtApkPath = uniqueHash(), - assetModuleFolderPath = uniqueHash(), + assetModuleFolderPath = uniqueHash() ) else null - val dstZFile = ZFile.openReadWrite(outputFile, ZFileOptions().setAlignmentRule( - AlignmentRules.compose( - AlignmentRules.constantForSuffix(".so", 4096), - AlignmentRules.constantForSuffix("assets/" + (dexObfuscationConfig?.originApkPath ?: "lspatch/origin.apk"), 4096) + val dstZFile = ZFile.openReadWrite( + outputFile, + ZFileOptions().setAlignmentRule( + AlignmentRules.compose( + AlignmentRules.constantForSuffix(".so", 4096), + AlignmentRules.constantForSuffix("assets/" + (dexObfuscationConfig?.originApkPath ?: "lspatch/origin.apk"), 4096) + ) ) - )) + ) + val origSign = ApkSignatureHelper.getApkSignInfo(inputApkFile.absolutePath) val patchConfig = PatchConfig( useManager = false, debuggable = false, overrideVersionCode = false, sigBypassLevel = 2, - originalSignature = ApkSignatureHelper.getApkSignInfo(inputApkFile.absolutePath), + originalSignature = origSign, appComponentFactory = "androidx.core.app.CoreComponentFactory" ).let { Gson().toJson(it) } - // sign apk runCatching { - provideSigningExtension(context.assets.open("lspatch/keystore.jks")).register(dstZFile) - }.onFailure { - throw Exception("Failed to sign apk", it) - } + ApkSignatureHelper.provideSigningExtension(context.assets.open("lspatch/keystore.jks")).register(dstZFile) + }.onFailure { throw Exception("Failed to sign apk", it) } printLog("Patching manifest") - val sourceApkFile = dstZFile.addNestedZip({ "assets/" + (dexObfuscationConfig?.originApkPath ?: "lspatch/origin.apk") }, inputApkFile, false) - val originalManifestEntry = sourceApkFile.get("AndroidManifest.xml") ?: throw Exception("No original manifest found") + val originalManifestEntry = sourceApkFile.get("AndroidManifest.xml") ?: throw Exception("No original manifest found in base APK") originalManifestEntry.open().use { inputStream -> - val patchedManifestData = patchManifest(inputStream.readBytes(), (dexObfuscationConfig?.metadataManifestField ?: "lspatch") to Base64.encode(patchConfig.toByteArray())) + val patchedManifestData = patchManifest( + inputStream.readBytes(), + (dexObfuscationConfig?.metadataManifestField ?: "lspatch") to Base64.encode(patchConfig.toByteArray()) + ) dstZFile.add("AndroidManifest.xml", patchedManifestData.inputStream()) } - //add config printLog("Adding config") dstZFile.add("assets/" + (dexObfuscationConfig?.configFilePath ?: "lspatch/config.json"), ByteArrayInputStream(patchConfig.toByteArray())) - // add loader dex printLog("Adding loader dex") context.assets.open("lspatch/dexes/loader.dex").use { inputStream -> - dstZFile.add("assets/" + (dexObfuscationConfig?.loaderFilePath ?: "lspatch/loader.dex"), dexObfuscationConfig?.let { - lspatchObfuscation.obfuscateLoader(inputStream, it).inputStream() - } ?: inputStream) + dstZFile.add( + "assets/" + (dexObfuscationConfig?.loaderFilePath ?: "lspatch/loader.dex"), + dexObfuscationConfig?.let { lspatchObfuscation.obfuscateLoader(inputStream, it).inputStream() } ?: inputStream + ) } - //add natives printLog("Adding natives") - val nativeAssetPath = "snapenhance/so" - context.assets.list(nativeAssetPath)?.forEach { abi -> - val libPath = "$nativeAssetPath/$abi" - // The library name is now fixed, let's find it. - val libName = context.assets.list(libPath)?.find { it.startsWith("lib") && it.endsWith(".so") } ?: return@forEach - val fullAssetPath = "$libPath/$libName" - - // The destination path inside the APK must be in the `lib` folder. - val finalApkPath = "lib/$abi/$libName" - - printLog("Adding native library from $fullAssetPath to $finalApkPath") - dstZFile.add(finalApkPath, context.assets.open(fullAssetPath), false) + context.assets.list("lspatch/so")?.forEach { native -> + dstZFile.add( + "assets/${dexObfuscationConfig?.libNativeFilePath?.get(native) ?: "lspatch/so/$native/liblspatch.so"}", + context.assets.open("lspatch/so/$native/liblspatch.so"), + false + ) } - //embed modules printLog("Embedding modules") modules.forEach { (packageName, module) -> val obfuscatedPackageName = dexObfuscationConfig?.packageName ?: packageName @@ -162,38 +139,33 @@ class LSPatch( dstZFile.add("assets/${dexObfuscationConfig?.assetModuleFolderPath ?: "lspatch/modules"}/$obfuscatedPackageName.apk", module.inputStream()) } - // link apk entries printLog("Linking apk entries") - for (entry in sourceApkFile.entries()) { val name = entry.centralDirectoryHeader.name if (dexObfuscationConfig == null && name.startsWith("classes") && name.endsWith(".dex")) continue if (dstZFile[name] != null) continue if (name == "AndroidManifest.xml") continue - if (name.startsWith("META-INF") && (name.endsWith(".SF") || name.endsWith(".MF") || name.endsWith( - ".RSA" - )) - ) continue + if (name.startsWith("META-INF") && (name.endsWith(".SF") || name.endsWith(".MF") || name.endsWith(".RSA"))) continue sourceApkFile.addFileLink(name, name) } printLog("Adding meta loader dex") context.assets.open("lspatch/dexes/metaloader.dex").use { inputStream -> - dstZFile.add(dexObfuscationConfig?.let { - val dexFileIndex = sourceApkFile.entries().count { - it.centralDirectoryHeader.name.startsWith("classes") && it.centralDirectoryHeader.name.endsWith(".dex") - } + 1 - "classes${dexFileIndex}.dex" - } ?: "classes.dex", dexObfuscationConfig?.let { - lspatchObfuscation.obfuscateMetaLoader(inputStream, it).inputStream() - } ?: inputStream) + dstZFile.add( + dexObfuscationConfig?.let { + val dexFileIndex = sourceApkFile.entries().count { + it.centralDirectoryHeader.name.startsWith("classes") && it.centralDirectoryHeader.name.endsWith(".dex") + } + 1 + "classes${dexFileIndex}.dex" + } ?: "classes.dex", + dexObfuscationConfig?.let { lspatchObfuscation.obfuscateMetaLoader(inputStream, it).inputStream() } ?: inputStream + ) } printLog("Writing apk") dstZFile.realign() dstZFile.close() sourceApkFile.close() - printLog("Cleaning obfuscation cache") obfuscationCacheFolder.deleteRecursively() printLog("Done") @@ -201,8 +173,9 @@ class LSPatch( fun patchSplits(inputs: List): Map { val outputs = mutableMapOf() + val extCacheDir = context.externalCacheDir ?: context.cacheDir ?: throw IllegalStateException("No valid cache dir") inputs.forEach { input -> - val outputFile = File.createTempFile("patched", ".apk", context.externalCacheDir ?: context.cacheDir) + val outputFile = File.createTempFile("patched", ".apk", extCacheDir) if (input.name.contains("split")) { resignApk(input, outputFile) outputs[input.name] = outputFile @@ -215,34 +188,32 @@ class LSPatch( } private fun patch(input: File, outputFile: File) { - //check if input apk is already patched + if (!input.exists()) { + printLog("!! Input file does not exist: ${input.absolutePath}") + return + } + if (outputFile.exists()) outputFile.delete() + var isAlreadyPatched = false var inputFile = input - // extract origin printLog("Extracting origin apk") ZipFile(input).use { zipFile -> zipFile.getEntry("assets/lspatch/origin.apk")?.apply { - inputFile = File.createTempFile("origin", ".apk") - inputFile.outputStream().use { - zipFile.getInputStream(this).copyTo(it) - } + inputFile = File.createTempFile("origin", ".apk", context.cacheDir ?: context.externalCacheDir) + inputFile.outputStream().use { zipFile.getInputStream(this).copyTo(it) } isAlreadyPatched = true } } - if (outputFile.exists()) outputFile.delete() - printLog("Patching apk") runCatching { patchApk(inputFile, outputFile) }.onFailure { - if (isAlreadyPatched) { - inputFile.delete() - } + if (isAlreadyPatched) inputFile.delete() outputFile.delete() printLog("Failed to patch") printLog(it) } } -} \ No newline at end of file +} diff --git a/app/src/main/kotlin/me/eternal/purrfectsnap/setup/patch/LSPatchObfuscation.kt b/app/src/main/kotlin/me/eternal/purrfectsnap/setup/patch/LSPatchObfuscation.kt new file mode 100644 index 00000000..8f63cba7 --- /dev/null +++ b/app/src/main/kotlin/me/eternal/purrfectsnap/setup/patch/LSPatchObfuscation.kt @@ -0,0 +1,62 @@ +package me.eternal.purrfectsnap.setup.patch + +import java.io.File +import java.io.InputStream + +data class DexObfuscationConfig( + val packageName: String, + val metadataManifestField: String? = null, + val metaLoaderFilePath: String? = null, + val configFilePath: String? = null, + val loaderFilePath: String? = null, + val originApkPath: String? = null, + val cachedOriginApkPath: String? = null, + val openAtApkPath: String? = null, + val assetModuleFolderPath: String? = null, + val libNativeFilePath: Map = mapOf(), +) + +class LSPatchObfuscation( + private val cacheFolder: File, + private val printLog: (String) -> Unit = { println(it) } +) { + + fun obfuscateMetaLoader(inputStream: InputStream, config: DexObfuscationConfig): File { + return inputStream.obfuscateDexFile( + cacheFolder, + mapOf( + "assets/lspatch/config.json" to "assets/${config.configFilePath}", + "assets/lspatch/loader.dex" to "assets/${config.loaderFilePath}", + ) + (config.libNativeFilePath.takeIf { it.isNotEmpty() }?.let { + mapOf( + "!/assets/lspatch/so/" to "!/assets/", + "assets/lspatch/so/" to "assets/", + "/liblspatch.so" to "", + "arm64-v8a" to config.libNativeFilePath["arm64-v8a"], + "armeabi-v7a" to config.libNativeFilePath["armeabi-v7a"], + "x86" to config.libNativeFilePath["x86"], + "x86_64" to config.libNativeFilePath["x86_64"], + ) + } ?: mapOf()) + ) + } + + fun obfuscateLoader(inputStream: InputStream, config: DexObfuscationConfig): File { + return inputStream.obfuscateDexFile( + cacheFolder, mapOf( + "assets/lspatch/config.json" to config.configFilePath?.let { "assets/$it" }, + "assets/lspatch/loader.dex" to config.loaderFilePath?.let { "assets/$it" }, + "assets/lspatch/metaloader.dex" to config.metaLoaderFilePath?.let { "assets/$it" }, + "assets/lspatch/origin.apk" to config.originApkPath?.let { "assets/$it" }, + "/lspatch/origin/" to config.cachedOriginApkPath?.let { "/$it/" }, // context.getCacheDir() + ==> "/lspatch/origin/" <== + sourceFile.getEntry(ORIGINAL_APK_ASSET_PATH).getCrc() + ".apk"; + "/lspatch/" to config.cachedOriginApkPath?.let { "/$it/" }, // context.getCacheDir() + "/lspatch/" + packageName + "/" + "cache/lspatch/origin/" to config.cachedOriginApkPath?.let { "cache/$it" }, //LSPApplication => Path originPath = Paths.get(appInfo.dataDir, "cache/lspatch/origin/"); + "assets/lspatch/modules/" to config.assetModuleFolderPath?.let { "assets/$it/" }, // Constants.java => EMBEDDED_MODULES_ASSET_PATH + "lspatch/modules" to config.assetModuleFolderPath, // LocalApplicationService.java => context.getAssets().list("lspatch/modules"), + "lspatch/modules/" to config.assetModuleFolderPath?.let { "$it/" }, // LocalApplicationService.java => try (var is = context.getAssets().open("lspatch/modules/" + name)) { + "lspatch" to config.metadataManifestField, // SigBypass.java => "lspatch", + "org.lsposed.lspatch" to config.cachedOriginApkPath?.let { "$it/${config.packageName}/" }, // Constants.java => "org.lsposed.lspatch", (Used in LSPatchUpdater.kt) + ) + ) + } +} diff --git a/manager/src/main/kotlin/me/rhunk/snapenhance/manager/patch/config/PatchConfig.kt b/app/src/main/kotlin/me/eternal/purrfectsnap/setup/patch/PatchConfig.kt similarity index 91% rename from manager/src/main/kotlin/me/rhunk/snapenhance/manager/patch/config/PatchConfig.kt rename to app/src/main/kotlin/me/eternal/purrfectsnap/setup/patch/PatchConfig.kt index ea06cf83..8fe696d7 100644 --- a/manager/src/main/kotlin/me/rhunk/snapenhance/manager/patch/config/PatchConfig.kt +++ b/app/src/main/kotlin/me/eternal/purrfectsnap/setup/patch/PatchConfig.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.manager.patch.config +package me.eternal.purrfectsnap.setup.patch data class PatchConfig( val useManager: Boolean = false, @@ -16,4 +16,4 @@ data class PatchConfig( var CORE_VERSION_CODE: Int = 6649, var CORE_VERSION_NAME: String = "1.8.5", ) -} \ No newline at end of file +} diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/storage/AppDatabase.kt b/app/src/main/kotlin/me/eternal/purrfectsnap/storage/AppDatabase.kt similarity index 93% rename from app/src/main/kotlin/me/rhunk/snapenhance/storage/AppDatabase.kt rename to app/src/main/kotlin/me/eternal/purrfectsnap/storage/AppDatabase.kt index 350982dc..95f0b131 100644 --- a/app/src/main/kotlin/me/rhunk/snapenhance/storage/AppDatabase.kt +++ b/app/src/main/kotlin/me/eternal/purrfectsnap/storage/AppDatabase.kt @@ -1,10 +1,10 @@ -package me.rhunk.snapenhance.storage +package me.eternal.purrfectsnap.storage import android.database.sqlite.SQLiteDatabase -import me.rhunk.snapenhance.RemoteSideContext -import me.rhunk.snapenhance.common.data.MessagingFriendInfo -import me.rhunk.snapenhance.common.data.MessagingGroupInfo -import me.rhunk.snapenhance.common.util.SQLiteDatabaseHelper +import me.eternal.purrfectsnap.RemoteSideContext +import me.eternal.purrfectsnap.common.data.MessagingFriendInfo +import me.eternal.purrfectsnap.common.data.MessagingGroupInfo +import me.eternal.purrfectsnap.common.util.SQLiteDatabaseHelper import java.util.concurrent.ExecutorService import java.util.concurrent.Executors @@ -115,4 +115,4 @@ class AppDatabase( ), )) } -} \ No newline at end of file +} diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/storage/Location.kt b/app/src/main/kotlin/me/eternal/purrfectsnap/storage/Location.kt similarity index 88% rename from app/src/main/kotlin/me/rhunk/snapenhance/storage/Location.kt rename to app/src/main/kotlin/me/eternal/purrfectsnap/storage/Location.kt index c1ea98ac..aa32cc54 100644 --- a/app/src/main/kotlin/me/rhunk/snapenhance/storage/Location.kt +++ b/app/src/main/kotlin/me/eternal/purrfectsnap/storage/Location.kt @@ -1,12 +1,12 @@ -package me.rhunk.snapenhance.storage +package me.eternal.purrfectsnap.storage import android.content.ContentValues import kotlinx.coroutines.asCoroutineDispatcher import kotlinx.coroutines.runBlocking -import me.rhunk.snapenhance.bridge.location.LocationCoordinates -import me.rhunk.snapenhance.common.util.ktx.getDoubleOrNull -import me.rhunk.snapenhance.common.util.ktx.getInteger -import me.rhunk.snapenhance.common.util.ktx.getStringOrNull +import me.eternal.purrfectsnap.bridge.location.LocationCoordinates +import me.eternal.purrfectsnap.common.util.ktx.getDoubleOrNull +import me.eternal.purrfectsnap.common.util.ktx.getInteger +import me.eternal.purrfectsnap.common.util.ktx.getStringOrNull fun AppDatabase.getLocationCoordinates(): List { diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/storage/Messaging.kt b/app/src/main/kotlin/me/eternal/purrfectsnap/storage/Messaging.kt similarity index 93% rename from app/src/main/kotlin/me/rhunk/snapenhance/storage/Messaging.kt rename to app/src/main/kotlin/me/eternal/purrfectsnap/storage/Messaging.kt index 82ac4a54..773768b8 100644 --- a/app/src/main/kotlin/me/rhunk/snapenhance/storage/Messaging.kt +++ b/app/src/main/kotlin/me/eternal/purrfectsnap/storage/Messaging.kt @@ -1,12 +1,12 @@ -package me.rhunk.snapenhance.storage +package me.eternal.purrfectsnap.storage -import me.rhunk.snapenhance.common.data.FriendStreaks -import me.rhunk.snapenhance.common.data.MessagingFriendInfo -import me.rhunk.snapenhance.common.data.MessagingGroupInfo -import me.rhunk.snapenhance.common.data.MessagingRuleType -import me.rhunk.snapenhance.common.util.ktx.getInteger -import me.rhunk.snapenhance.common.util.ktx.getLongOrNull -import me.rhunk.snapenhance.common.util.ktx.getStringOrNull +import me.eternal.purrfectsnap.common.data.FriendStreaks +import me.eternal.purrfectsnap.common.data.MessagingFriendInfo +import me.eternal.purrfectsnap.common.data.MessagingGroupInfo +import me.eternal.purrfectsnap.common.data.MessagingRuleType +import me.eternal.purrfectsnap.common.util.ktx.getInteger +import me.eternal.purrfectsnap.common.util.ktx.getLongOrNull +import me.eternal.purrfectsnap.common.util.ktx.getStringOrNull import java.io.Serializable fun AppDatabase.getGroups(): List { @@ -41,7 +41,7 @@ fun AppDatabase.syncGroupInfo(conversationInfo: MessagingGroupInfo) { try { database.execSQL( "INSERT OR REPLACE INTO groups (conversationId, name, participantsCount) VALUES (?, ?, ?)", - arrayOf( + arrayOf( conversationInfo.conversationId, conversationInfo.name, conversationInfo.participantsCount diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/storage/QuickTiles.kt b/app/src/main/kotlin/me/eternal/purrfectsnap/storage/QuickTiles.kt similarity index 87% rename from app/src/main/kotlin/me/rhunk/snapenhance/storage/QuickTiles.kt rename to app/src/main/kotlin/me/eternal/purrfectsnap/storage/QuickTiles.kt index 7066e656..d77b2625 100644 --- a/app/src/main/kotlin/me/rhunk/snapenhance/storage/QuickTiles.kt +++ b/app/src/main/kotlin/me/eternal/purrfectsnap/storage/QuickTiles.kt @@ -1,6 +1,6 @@ -package me.rhunk.snapenhance.storage +package me.eternal.purrfectsnap.storage -import me.rhunk.snapenhance.common.util.ktx.getStringOrNull +import me.eternal.purrfectsnap.common.util.ktx.getStringOrNull fun AppDatabase.getQuickTiles(): List { return database.rawQuery("SELECT `key` FROM quick_tiles ORDER BY position ASC", null).use { cursor -> diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/storage/Repositories.kt b/app/src/main/kotlin/me/eternal/purrfectsnap/storage/Repositories.kt similarity index 90% rename from app/src/main/kotlin/me/rhunk/snapenhance/storage/Repositories.kt rename to app/src/main/kotlin/me/eternal/purrfectsnap/storage/Repositories.kt index f96d15f2..c8533fdf 100644 --- a/app/src/main/kotlin/me/rhunk/snapenhance/storage/Repositories.kt +++ b/app/src/main/kotlin/me/eternal/purrfectsnap/storage/Repositories.kt @@ -1,9 +1,9 @@ -package me.rhunk.snapenhance.storage +package me.eternal.purrfectsnap.storage import android.content.ContentValues import kotlinx.coroutines.asCoroutineDispatcher import kotlinx.coroutines.runBlocking -import me.rhunk.snapenhance.common.util.ktx.getStringOrNull +import me.eternal.purrfectsnap.common.util.ktx.getStringOrNull fun AppDatabase.getRepositories(type: String): List { @@ -32,4 +32,3 @@ fun AppDatabase.addRepo(type: String, url: String) { }) } } - diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/storage/ScopeNotes.kt b/app/src/main/kotlin/me/eternal/purrfectsnap/storage/ScopeNotes.kt similarity index 97% rename from app/src/main/kotlin/me/rhunk/snapenhance/storage/ScopeNotes.kt rename to app/src/main/kotlin/me/eternal/purrfectsnap/storage/ScopeNotes.kt index 93d87b62..e3d797f2 100644 --- a/app/src/main/kotlin/me/rhunk/snapenhance/storage/ScopeNotes.kt +++ b/app/src/main/kotlin/me/eternal/purrfectsnap/storage/ScopeNotes.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.storage +package me.eternal.purrfectsnap.storage import androidx.core.database.getStringOrNull diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/storage/Scripting.kt b/app/src/main/kotlin/me/eternal/purrfectsnap/storage/Scripting.kt similarity index 94% rename from app/src/main/kotlin/me/rhunk/snapenhance/storage/Scripting.kt rename to app/src/main/kotlin/me/eternal/purrfectsnap/storage/Scripting.kt index b7c0fa0f..57e7a4b3 100644 --- a/app/src/main/kotlin/me/rhunk/snapenhance/storage/Scripting.kt +++ b/app/src/main/kotlin/me/eternal/purrfectsnap/storage/Scripting.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.storage +package me.eternal.purrfectsnap.storage import kotlinx.coroutines.asCoroutineDispatcher import kotlinx.coroutines.runBlocking diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/storage/Tracker.kt b/app/src/main/kotlin/me/eternal/purrfectsnap/storage/Tracker.kt similarity index 92% rename from app/src/main/kotlin/me/rhunk/snapenhance/storage/Tracker.kt rename to app/src/main/kotlin/me/eternal/purrfectsnap/storage/Tracker.kt index 0b49f448..34492648 100644 --- a/app/src/main/kotlin/me/rhunk/snapenhance/storage/Tracker.kt +++ b/app/src/main/kotlin/me/eternal/purrfectsnap/storage/Tracker.kt @@ -1,16 +1,16 @@ -package me.rhunk.snapenhance.storage +package me.eternal.purrfectsnap.storage import android.content.ContentValues import com.google.gson.JsonArray import kotlinx.coroutines.runBlocking -import me.rhunk.snapenhance.common.data.TrackerRule -import me.rhunk.snapenhance.common.data.TrackerRuleAction -import me.rhunk.snapenhance.common.data.TrackerRuleActionParams -import me.rhunk.snapenhance.common.data.TrackerRuleEvent -import me.rhunk.snapenhance.common.data.TrackerScopeType -import me.rhunk.snapenhance.common.util.ktx.getInteger -import me.rhunk.snapenhance.common.util.ktx.getLongOrNull -import me.rhunk.snapenhance.common.util.ktx.getStringOrNull +import me.eternal.purrfectsnap.common.data.TrackerRule +import me.eternal.purrfectsnap.common.data.TrackerRuleAction +import me.eternal.purrfectsnap.common.data.TrackerRuleActionParams +import me.eternal.purrfectsnap.common.data.TrackerRuleEvent +import me.eternal.purrfectsnap.common.data.TrackerScopeType +import me.eternal.purrfectsnap.common.util.ktx.getInteger +import me.eternal.purrfectsnap.common.util.ktx.getLongOrNull +import me.eternal.purrfectsnap.common.util.ktx.getStringOrNull import kotlin.coroutines.suspendCoroutine fun AppDatabase.clearTrackerRules() { @@ -57,7 +57,7 @@ fun AppDatabase.addOrUpdateTrackerRuleEvent( suspendCoroutine { continuation -> executeAsync { val id = if (ruleEventId != null) { - database.execSQL("UPDATE tracker_rules_events SET params = ?, actions = ? WHERE id = ?", arrayOf( + database.execSQL("UPDATE tracker_rules_events SET params = ?, actions = ? WHERE id = ?", arrayOf( context.gson.toJson(params), context.gson.toJson(actions.map { it.key }), ruleEventId @@ -126,13 +126,13 @@ fun AppDatabase.getTrackerRuleByName(name: String): TrackerRule? { fun AppDatabase.setTrackerRuleName(ruleId: Int, name: String) { executeAsync { - database.execSQL("UPDATE tracker_rules SET name = ? WHERE id = ?", arrayOf(name, ruleId)) + database.execSQL("UPDATE tracker_rules SET name = ? WHERE id = ?", arrayOf(name, ruleId)) } } fun AppDatabase.setTrackerRuleAuthor(ruleId: Int, author: String) { executeAsync { - database.execSQL("UPDATE tracker_rules SET author = ? WHERE id = ?", arrayOf(author, ruleId)) + database.execSQL("UPDATE tracker_rules SET author = ? WHERE id = ?", arrayOf(author, ruleId)) } } @@ -234,9 +234,9 @@ fun AppDatabase.updateFriendScore(userId: String, score: Long): Long { cursor.getLongOrNull("score") } if (currentScore != null) { - database.execSQL("UPDATE friend_scores SET score = ? WHERE userId = ?", arrayOf(score, userId)) + database.execSQL("UPDATE friend_scores SET score = ? WHERE userId = ?", arrayOf(score, userId)) } else { - database.execSQL("INSERT INTO friend_scores (userId, score) VALUES (?, ?)", arrayOf(userId, score)) + database.execSQL("INSERT INTO friend_scores (userId, score) VALUES (?, ?)", arrayOf(userId, score)) } continuation.resumeWith(Result.success(currentScore ?: -1)) } diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/storage/TrackerDataManagerImpl.kt b/app/src/main/kotlin/me/eternal/purrfectsnap/storage/TrackerDataManagerImpl.kt similarity index 80% rename from app/src/main/kotlin/me/rhunk/snapenhance/storage/TrackerDataManagerImpl.kt rename to app/src/main/kotlin/me/eternal/purrfectsnap/storage/TrackerDataManagerImpl.kt index f562c788..30c636cf 100644 --- a/app/src/main/kotlin/me/rhunk/snapenhance/storage/TrackerDataManagerImpl.kt +++ b/app/src/main/kotlin/me/eternal/purrfectsnap/storage/TrackerDataManagerImpl.kt @@ -1,13 +1,13 @@ -package me.rhunk.snapenhance.storage +package me.eternal.purrfectsnap.storage -import me.rhunk.snapenhance.common.data.ExportedTrackerData -import me.rhunk.snapenhance.common.data.TrackerDataManager -import me.rhunk.snapenhance.storage.AppDatabase +import me.eternal.purrfectsnap.common.data.ExportedTrackerData +import me.eternal.purrfectsnap.common.data.TrackerDataManager +import me.eternal.purrfectsnap.storage.AppDatabase class TrackerDataManagerImpl(private val db: AppDatabase) : TrackerDataManager { override fun getExportedTrackerData(): ExportedTrackerData { return ExportedTrackerData( - type = me.rhunk.snapenhance.common.data.ExportType.BULK, + type = me.eternal.purrfectsnap.common.data.ExportType.BULK, rules = db.getTrackerRulesDesc().map { rule -> rule.copy( events = db.getTrackerEvents(rule.id), @@ -20,7 +20,7 @@ class TrackerDataManagerImpl(private val db: AppDatabase) : TrackerDataManager { override fun getExportedTrackerData(ruleId: Int): ExportedTrackerData? { return db.getTrackerRule(ruleId)?.let { ExportedTrackerData( - type = me.rhunk.snapenhance.common.data.ExportType.SINGLE, + type = me.eternal.purrfectsnap.common.data.ExportType.SINGLE, rules = listOf(it.copy( events = db.getTrackerEvents(it.id), scopes = db.getRuleTrackerScopes(it.id) @@ -30,7 +30,7 @@ class TrackerDataManagerImpl(private val db: AppDatabase) : TrackerDataManager { } override fun importTrackerData(data: ExportedTrackerData) { - if (data.type == me.rhunk.snapenhance.common.data.ExportType.BULK) { + if (data.type == me.eternal.purrfectsnap.common.data.ExportType.BULK) { db.clearTrackerRules() } data.rules.forEach { rule -> diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/task/PendingTask.kt b/app/src/main/kotlin/me/eternal/purrfectsnap/task/PendingTask.kt similarity index 96% rename from app/src/main/kotlin/me/rhunk/snapenhance/task/PendingTask.kt rename to app/src/main/kotlin/me/eternal/purrfectsnap/task/PendingTask.kt index 63c94080..3b43d6ac 100644 --- a/app/src/main/kotlin/me/rhunk/snapenhance/task/PendingTask.kt +++ b/app/src/main/kotlin/me/eternal/purrfectsnap/task/PendingTask.kt @@ -1,11 +1,12 @@ -package me.rhunk.snapenhance.task +package me.eternal.purrfectsnap.task enum class TaskType( val key: String ) { DOWNLOAD("download"), - CHAT_ACTION("chat_action"); + CHAT_ACTION("chat_action"), + SCHEDULED_SEND("scheduled_send"); companion object { fun fromKey(key: String): TaskType { @@ -132,4 +133,4 @@ class PendingTask( listeners.forEach { it.onCancel() } } } -} \ No newline at end of file +} diff --git a/app/src/main/kotlin/me/eternal/purrfectsnap/task/RemoteTaskInterface.kt b/app/src/main/kotlin/me/eternal/purrfectsnap/task/RemoteTaskInterface.kt new file mode 100644 index 00000000..6df9ebfb --- /dev/null +++ b/app/src/main/kotlin/me/eternal/purrfectsnap/task/RemoteTaskInterface.kt @@ -0,0 +1,66 @@ +package me.eternal.purrfectsnap.task + +import me.eternal.purrfectsnap.RemoteSideContext +import me.eternal.purrfectsnap.bridge.task.TaskInterface +import me.eternal.purrfectsnap.bridge.task.TaskListener + +class RemoteTaskInterface( + private val context: RemoteSideContext +) : TaskInterface.Stub() { + private val activeTasks = context.taskManager.getActiveTasks() + + override fun createTask(type: String, title: String, author: String, hash: String): String { + val task = Task( + type = TaskType.fromKey(type), + title = title, + author = author.takeIf { it.isNotBlank() }, + hash = hash + ) + context.taskManager.createPendingTask(task) + return hash + } + + override fun updateTaskProgress(hash: String, label: String, progress: Int) { + activeTasks.values.find { it.task.hash == hash }?.updateProgress(label, progress) + ?: context.taskManager.getTaskByHash(hash)?.let { + if (!it.status.isFinalStage()) { + it.status = TaskStatus.RUNNING + it.extra = label + } + } + } + + override fun cancelTask(hash: String) { + activeTasks.values.find { it.task.hash == hash }?.cancel() ?: context.taskManager.getTaskByHash(hash)?.let { + it.status = TaskStatus.CANCELLED + } + } + + override fun failTask(hash: String, reason: String) { + activeTasks.values.find { it.task.hash == hash }?.fail(reason) ?: context.taskManager.getTaskByHash(hash)?.let { + it.status = TaskStatus.FAILURE + it.extra = reason + } + } + + override fun successTask(hash: String) { + activeTasks.values.find { it.task.hash == hash }?.success() ?: context.taskManager.getTaskByHash(hash)?.let { + it.status = TaskStatus.SUCCESS + } + } + + override fun registerTaskListener(hash: String, listener: TaskListener) { + activeTasks.values.find { it.task.hash == hash }?.addListener( + PendingTaskListener( + onSuccess = { listener.onSuccess() }, + onCancel = { listener.onCancel() }, + onProgress = { label, progress -> listener.onProgress(label ?: "", progress) }, + onStateChange = { status -> listener.onStateChange(status.key) } + ) + ) + } + + override fun unregisterTaskListener(hash: String, listener: TaskListener) { + activeTasks.values.find { it.task.hash == hash }?.removeListener(PendingTaskListener()) + } +} diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/task/TaskManager.kt b/app/src/main/kotlin/me/eternal/purrfectsnap/task/TaskManager.kt similarity index 95% rename from app/src/main/kotlin/me/rhunk/snapenhance/task/TaskManager.kt rename to app/src/main/kotlin/me/eternal/purrfectsnap/task/TaskManager.kt index 990f318a..e7eeb60c 100644 --- a/app/src/main/kotlin/me/rhunk/snapenhance/task/TaskManager.kt +++ b/app/src/main/kotlin/me/eternal/purrfectsnap/task/TaskManager.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.task +package me.eternal.purrfectsnap.task import android.content.ContentValues import android.content.Context @@ -6,10 +6,10 @@ import android.database.sqlite.SQLiteDatabase import kotlinx.coroutines.asCoroutineDispatcher import kotlinx.coroutines.launch import kotlinx.coroutines.runBlocking -import me.rhunk.snapenhance.RemoteSideContext -import me.rhunk.snapenhance.common.util.SQLiteDatabaseHelper -import me.rhunk.snapenhance.common.util.ktx.getLong -import me.rhunk.snapenhance.common.util.ktx.getStringOrNull +import me.eternal.purrfectsnap.RemoteSideContext +import me.eternal.purrfectsnap.common.util.SQLiteDatabaseHelper +import me.eternal.purrfectsnap.common.util.ktx.getLong +import me.eternal.purrfectsnap.common.util.ktx.getStringOrNull import java.util.concurrent.Executors import kotlin.coroutines.suspendCoroutine diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/task/UpdateCheckWorker.kt b/app/src/main/kotlin/me/eternal/purrfectsnap/task/UpdateCheckWorker.kt similarity index 89% rename from app/src/main/kotlin/me/rhunk/snapenhance/task/UpdateCheckWorker.kt rename to app/src/main/kotlin/me/eternal/purrfectsnap/task/UpdateCheckWorker.kt index f4394031..b9ab2877 100644 --- a/app/src/main/kotlin/me/rhunk/snapenhance/task/UpdateCheckWorker.kt +++ b/app/src/main/kotlin/me/eternal/purrfectsnap/task/UpdateCheckWorker.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.task +package me.eternal.purrfectsnap.task import android.app.NotificationChannel import android.app.NotificationManager @@ -13,9 +13,9 @@ import android.Manifest import androidx.core.content.ContextCompat import android.content.pm.PackageManager import androidx.work.WorkerParameters -import me.rhunk.snapenhance.R -import me.rhunk.snapenhance.ui.manager.MainActivity -import me.rhunk.snapenhance.ui.manager.data.Updater +import me.eternal.purrfectsnap.R +import me.eternal.purrfectsnap.ui.manager.MainActivity +import me.eternal.purrfectsnap.ui.manager.data.Updater class UpdateCheckWorker( private val appContext: Context, @@ -35,9 +35,9 @@ class UpdateCheckWorker( } private fun showUpdateNotification(versionName: String) { - val channelId = "snapenhance_updates" - val name = inputData.getString("channel_name") ?: "SnapEnhance Updates" - val descriptionText = inputData.getString("channel_description") ?: "Notifications for SnapEnhance updates" + val channelId = "purrfectsnap_updates" + val name = inputData.getString("channel_name") ?: "PurrfectSnap Updates" + val descriptionText = inputData.getString("channel_description") ?: "Notifications for PurrfectSnap updates" val title = inputData.getString("notification_title") ?: "PurrfectSnap Update Available" val text = inputData.getString("notification_text") ?: "Version %s is now available." diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/MainActivity.kt b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/MainActivity.kt similarity index 61% rename from app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/MainActivity.kt rename to app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/MainActivity.kt index 707f89b3..0f08bd8f 100644 --- a/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/MainActivity.kt +++ b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/MainActivity.kt @@ -1,5 +1,5 @@ @file:OptIn(androidx.compose.animation.ExperimentalAnimationApi::class) -package me.rhunk.snapenhance.ui.manager +package me.eternal.purrfectsnap.ui.manager import android.app.Activity import android.content.Intent @@ -7,6 +7,7 @@ import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.appcompat.app.AppCompatDelegate +import androidx.compose.material3.LocalContentColor import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Scaffold import androidx.compose.runtime.* @@ -31,12 +32,14 @@ import androidx.navigation.NavGraph.Companion.findStartDestination import androidx.navigation.NavHostController import androidx.navigation.compose.currentBackStackEntryAsState import androidx.navigation.compose.rememberNavController -import me.rhunk.snapenhance.RemoteSideContext -import me.rhunk.snapenhance.SharedContextHolder -import me.rhunk.snapenhance.common.ui.AppMaterialTheme -import me.rhunk.snapenhance.common.ui.ThemeMode -import me.rhunk.snapenhance.common.ui.ThemePreferences -import me.rhunk.snapenhance.ui.util.ActivityLauncherHelper +import me.eternal.purrfectsnap.RemoteSideContext +import me.eternal.purrfectsnap.SharedContextHolder +import me.eternal.purrfectsnap.common.ui.AppMaterialTheme +import me.eternal.purrfectsnap.common.ui.ThemeMode +import me.eternal.purrfectsnap.common.ui.ThemePreferences +import me.eternal.purrfectsnap.ui.manager.theme.PurrfectPalette +import me.eternal.purrfectsnap.ui.util.ActivityLauncherHelper +import me.eternal.purrfectsnap.ui.util.ThankYouDialog import android.content.IntentFilter class MainActivity : ComponentActivity() { @@ -44,7 +47,7 @@ class MainActivity : ComponentActivity() { private lateinit var managerContext: RemoteSideContext companion object { - const val RESTART_ACTION = "me.rhunk.snapenhance.RESTART" + const val RESTART_ACTION = "me.eternal.purrfectsnap.RESTART" } private val restartReceiver = object : android.content.BroadcastReceiver() { @@ -58,6 +61,7 @@ class MainActivity : ComponentActivity() { override fun onNewIntent(intent: Intent) { super.onNewIntent(intent) if (::navController.isInitialized.not()) return + intent.getStringExtra("route")?.let { route -> navController.popBackStack() navController.navigate(route) { @@ -68,9 +72,17 @@ class MainActivity : ComponentActivity() { } } + override fun onStart() { + super.onStart() + if (::managerContext.isInitialized) { + managerContext.checkForRequirements() + } + } + override fun onCreate(savedInstanceState: Bundle?) { AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM) super.onCreate(savedInstanceState) + registerReceiver(restartReceiver, IntentFilter(RESTART_ACTION), RECEIVER_EXPORTED) managerContext = SharedContextHolder.remote(this).apply { activity = this@MainActivity @@ -91,6 +103,7 @@ class MainActivity : ComponentActivity() { it.navController = navController }) } + routes.navigation = navigation val startDestination = remember { intent.getStringExtra("route") ?: run { val def = managerContext.sharedPreferences.getString("manager_default_tab", "home") ?: "home" @@ -128,57 +141,62 @@ class MainActivity : ComponentActivity() { ) } val isFullscreen = currentRoute in fullscreenRoutes - Scaffold( - modifier = Modifier.fillMaxSize(), - containerColor = MaterialTheme.colorScheme.background, - topBar = { - if (!isFullscreen) { - navigation.TopBar() - } - }, - floatingActionButton = { - if (!isFullscreen) { - Box(Modifier.padding(bottom = bottomPadding)) { - navigation.Fab() + ThankYouDialog() + CompositionLocalProvider(LocalContentColor provides PurrfectPalette.iconTint) { + Scaffold( + modifier = Modifier + .fillMaxSize() + .background(PurrfectPalette.backgroundGradient), + containerColor = Color.Transparent, + topBar = { + if (!isFullscreen) { + navigation.TopBar() } - } - }, - // Disable automatic padding so content can draw behind the bottom bar - contentWindowInsets = WindowInsets(0, 0, 0, 0) - ) { innerPadding -> - Box(Modifier.fillMaxSize()) { - val contentPadding = if (!isFullscreen) { - PaddingValues( - top = innerPadding.calculateTopPadding(), - start = innerPadding.calculateStartPadding(LayoutDirection.Ltr), - end = innerPadding.calculateEndPadding(LayoutDirection.Ltr), - bottom = innerPadding.calculateBottomPadding() - ) - } else { - PaddingValues(0.dp) - } - navigation.NavContent(contentPadding, startDestination) - if (!isFullscreen) { - Box( - modifier = Modifier - .align(Alignment.BottomCenter) - .fillMaxWidth() - .height(routes.bottomPadding) - .background( - brush = Brush.verticalGradient( - colors = listOf( - Color.Transparent, - MaterialTheme.colorScheme.background + }, + floatingActionButton = { + if (!isFullscreen) { + Box(Modifier.padding(bottom = bottomPadding)) { + navigation.Fab() + } + } + }, + // Disable automatic padding so content can draw behind the bottom bar + contentWindowInsets = WindowInsets(0, 0, 0, 0) + ) { innerPadding -> + Box(Modifier.fillMaxSize()) { + val contentPadding = if (!isFullscreen) { + PaddingValues( + top = innerPadding.calculateTopPadding(), + start = innerPadding.calculateStartPadding(LayoutDirection.Ltr), + end = innerPadding.calculateEndPadding(LayoutDirection.Ltr), + bottom = innerPadding.calculateBottomPadding() + ) + } else { + PaddingValues(0.dp) + } + navigation.NavContent(contentPadding, startDestination) + if (!isFullscreen) { + Box( + modifier = Modifier + .align(Alignment.BottomCenter) + .fillMaxWidth() + .height(routes.bottomPadding) + .background( + brush = Brush.verticalGradient( + colors = listOf( + Color.Transparent, + Color(0xFF241F52) + ) ) ) - ) - ) - Box( - modifier = Modifier - .fillMaxWidth() - .align(Alignment.BottomCenter) - ) { - navigation.FloatingBottomBar() + ) + Box( + modifier = Modifier + .fillMaxWidth() + .align(Alignment.BottomCenter) + ) { + navigation.FloatingBottomBar() + } } } } diff --git a/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/Navigation.kt b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/Navigation.kt new file mode 100644 index 00000000..29c6cf96 --- /dev/null +++ b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/Navigation.kt @@ -0,0 +1,808 @@ +package me.eternal.purrfectsnap.ui.manager + +import androidx.compose.animation.AnimatedVisibility +import androidx.compose.animation.core.animateDpAsState +import androidx.compose.animation.core.animateFloatAsState +import androidx.compose.animation.core.Animatable +import androidx.compose.animation.core.Spring +import androidx.compose.animation.core.spring +import androidx.compose.animation.core.FastOutSlowInEasing +import androidx.compose.animation.core.tween +import androidx.compose.animation.fadeIn +import androidx.compose.animation.fadeOut +import androidx.compose.animation.scaleIn +import androidx.compose.animation.scaleOut +import androidx.compose.animation.slideInHorizontally +import androidx.compose.animation.slideInVertically +import androidx.compose.animation.slideOutHorizontally +import androidx.compose.animation.slideOutVertically +import androidx.compose.foundation.BorderStroke +import androidx.compose.foundation.background +import androidx.compose.foundation.border +import androidx.compose.foundation.gestures.detectDragGestures +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.FlowRow +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.RowScope +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxHeight +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.navigationBarsPadding +import androidx.compose.foundation.layout.offset +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.layout.widthIn +import androidx.compose.foundation.layout.wrapContentWidth +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.itemsIndexed +import androidx.compose.foundation.lazy.rememberLazyListState +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.automirrored.filled.ArrowBack +import androidx.compose.material.icons.filled.Close +import androidx.compose.material.icons.filled.DragHandle +import androidx.compose.material.icons.filled.Tune +import androidx.compose.material3.Button +import androidx.compose.material3.ButtonDefaults +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.ElevatedCard +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.ModalBottomSheet +import androidx.compose.material3.NavigationBar +import androidx.compose.material3.NavigationBarItem +import androidx.compose.material3.NavigationBarItemDefaults +import androidx.compose.material3.OutlinedButton +import androidx.compose.material3.RadioButton +import androidx.compose.material3.AssistChip +import androidx.compose.material3.AssistChipDefaults +import androidx.compose.material3.Surface +import androidx.compose.material3.Text +import androidx.compose.material3.TopAppBar +import androidx.compose.material3.TopAppBarDefaults +import androidx.compose.material3.RadioButtonDefaults +import androidx.compose.material3.rememberModalBottomSheetState +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.draw.drawBehind +import androidx.compose.ui.draw.shadow +import androidx.compose.ui.geometry.CornerRadius +import androidx.compose.ui.graphics.Brush +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.SolidColor +import androidx.compose.ui.graphics.graphicsLayer +import androidx.compose.ui.input.pointer.PointerInputChange +import androidx.compose.ui.input.pointer.pointerInput +import androidx.compose.ui.layout.onGloballyPositioned +import androidx.compose.ui.platform.LocalHapticFeedback +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.text.style.TextOverflow +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.lerp +import androidx.compose.ui.unit.sp +import androidx.compose.ui.zIndex +import androidx.compose.foundation.ExperimentalFoundationApi +import androidx.compose.foundation.layout.ExperimentalLayoutApi +import androidx.navigation.NavHostController +import androidx.navigation.compose.NavHost +import androidx.navigation.compose.composable +import androidx.navigation.compose.currentBackStackEntryAsState +import androidx.navigation.compose.navigation +import me.eternal.purrfectsnap.RemoteSideContext +import me.eternal.purrfectsnap.ui.manager.theme.PurrfectPalette +import kotlin.math.round +import kotlin.math.PI +import kotlin.math.sin + +@OptIn( + ExperimentalMaterial3Api::class, + ExperimentalFoundationApi::class, + ExperimentalLayoutApi::class, + androidx.compose.animation.ExperimentalAnimationApi::class +) +class Navigation( + private val context: RemoteSideContext, + private val navController: NavHostController, + val routes: Routes = Routes(context).also { it.navController = navController } +) { + private val translation by lazy { context.translation.getCategory("manager.navigation") } + var openBottomBarCustomization by mutableStateOf(false) + @Composable + fun TopBar() { + val navBackStackEntry by navController.currentBackStackEntryAsState() + val currentRoute = remember(navBackStackEntry) { routes.getCurrentRoute(navBackStackEntry) } + if (currentRoute?.routeInfo?.hasOwnTopBar == true) return + val canGoBack = remember(navBackStackEntry) { + currentRoute?.let { !it.routeInfo.primary || it.routeInfo.childIds.contains(routes.currentDestination) } == true + } + TopAppBar( + title = { + currentRoute?.apply { + title?.invoke() ?: routeInfo.translatedKey?.value?.let { + Text( + text = it, + maxLines = 1, + overflow = TextOverflow.Ellipsis + ) + } + } + }, + navigationIcon = { + val backButtonAnimation by animateFloatAsState(if (canGoBack) 1f else 0f, label = "backButton") + Box( + modifier = Modifier + .graphicsLayer { alpha = backButtonAnimation } + .width(lerp(0.dp, 48.dp, backButtonAnimation)) + .height(48.dp) + ) { + IconButton(onClick = { if (canGoBack) navController.popBackStack() }) { + Icon(Icons.AutoMirrored.Filled.ArrowBack, contentDescription = null) + } + } + }, + colors = TopAppBarDefaults.topAppBarColors( + containerColor = Color.Transparent, + scrolledContainerColor = Color.Transparent + ), + actions = { + currentRoute?.topBarActions?.invoke(this) + if (currentRoute?.routeInfo?.id == routes.settings.routeInfo.id) { + IconButton(onClick = { openBottomBarCustomization = true }) { + Icon(Icons.Filled.Tune, contentDescription = null) + } + } + } + ) + } + @Composable + fun FloatingBottomBar() { + val navBackStackEntry by navController.currentBackStackEntryAsState() + val currentRoute = remember(navBackStackEntry) { routes.getCurrentRoute(navBackStackEntry) } + val availableRoutes = remember { + listOf(routes.tasks, routes.features, routes.home, routes.social, routes.scripting, routes.friendTracker) + } + val availableRouteMap = remember(availableRoutes) { availableRoutes.associateBy { it.routeInfo.id } } + val prefs = remember { context.sharedPreferences } + val defaultOrder = remember { listOf("tasks", "features", "home", "social", "scripts") } + fun loadSelected(): List { + val raw = prefs.getString("manager_nav_tabs", null)?.split(',')?.map { it.trim() }?.filter { it.isNotEmpty() } ?: emptyList() + val cleaned = raw.filter { availableRouteMap.containsKey(it) } + val list = (if (cleaned.isNotEmpty()) cleaned else defaultOrder).distinct() + return list.take(5) + } + var defaultTabId by remember { mutableStateOf(prefs.getString("manager_default_tab", "home") ?: "home") } + fun saveDefault(id: String) { + defaultTabId = id + prefs.edit().putString("manager_default_tab", id).apply() + } + fun saveSelected(ids: List) { + if (defaultTabId !in ids) { + val candidate = when { + "home" in ids -> "home" + ids.isNotEmpty() -> ids.first() + else -> defaultTabId + } + saveDefault(candidate) + } + prefs.edit().putString("manager_nav_tabs", ids.joinToString(",")).apply() + } + var selectedTabIds by remember { mutableStateOf(loadSelected()) } + val selectedRoutes = remember(selectedTabIds) { selectedTabIds.mapNotNull { availableRouteMap[it] } } + val barShape = RoundedCornerShape(28.dp) + val barBorder = remember { + Brush.linearGradient( + listOf( + PurrfectPalette.glowPrimary.copy(alpha = 0.9f), + PurrfectPalette.glowSecondary.copy(alpha = 0.85f) + ) + ) + } + val barSheen = remember { + Brush.verticalGradient( + colors = listOf( + Color.White.copy(alpha = 0.14f), + Color.Transparent + ) + ) + } + Box( + Modifier + .fillMaxWidth() + .padding(start = 16.dp, end = 16.dp, bottom = 8.dp) + .navigationBarsPadding(), + contentAlignment = Alignment.BottomCenter + ) { + val baseItemWidth = 92.dp + val containerPadding = 24.dp + val targetBarWidth = if (selectedRoutes.size < 5) baseItemWidth * selectedRoutes.size.toFloat() + containerPadding else null + val animatedBarWidth by animateDpAsState(targetValue = targetBarWidth ?: 0.dp, label = "barWidth") + Surface( + shape = barShape, + color = Color.Transparent, + contentColor = MaterialTheme.colorScheme.onSurface, + border = BorderStroke(1.dp, Color.White.copy(alpha = 0.08f)), + modifier = Modifier + .then(if (targetBarWidth != null) Modifier.width(animatedBarWidth) else Modifier.fillMaxWidth()) + .drawBehind { + val radius = size.width * 0.62f + drawCircle( + brush = Brush.radialGradient( + colors = listOf( + PurrfectPalette.glowPrimary.copy(alpha = 0.25f), + Color.Transparent + ), + center = center, + radius = radius + ), + radius = radius, + center = center + ) + } + .shadow( + elevation = 28.dp, + shape = barShape, + spotColor = PurrfectPalette.glowPrimary.copy(alpha = 0.35f), + ambientColor = PurrfectPalette.glowSecondary.copy(alpha = 0.26f) + ) + ) { + Box( + Modifier + .fillMaxWidth() + .height(82.dp) + .clip(barShape) + .background(PurrfectPalette.cardOverlay) + .border(BorderStroke(1.dp, barBorder), barShape) + ) { + Box( + modifier = Modifier + .fillMaxWidth() + .height(18.dp) + .align(Alignment.TopCenter) + .background(barSheen) + .graphicsLayer { alpha = 0.6f } + ) + Box( + modifier = Modifier + .matchParentSize() + .graphicsLayer { alpha = 0.25f } + .drawBehind { + val radius = size.width * 0.42f + drawCircle( + brush = Brush.radialGradient( + colors = listOf( + PurrfectPalette.glowSecondary.copy(alpha = 0.2f), + Color.Transparent + ), + center = center, + radius = radius + ), + radius = radius, + center = center + ) + } + ) + Box(Modifier.fillMaxWidth().height(82.dp)) { + var barWidthPx by remember { mutableStateOf(0f) } + val itemCount = selectedRoutes.size.coerceAtLeast(1) + val density = androidx.compose.ui.platform.LocalDensity.current + val selectedIndex = remember(currentRoute, selectedRoutes) { + val index = selectedRoutes.indexOf(currentRoute) + if (index >= 0) index else null // indexOf returns -1 when not found, replace with null + } + + selectedIndex?.let { // Null check + val itemWidthPx = + remember(barWidthPx, itemCount) { if (itemCount > 0) barWidthPx / itemCount else 0f } + val offsetAnim = remember { Animatable(0f) } + var lastSelectedIndex by remember { mutableStateOf(selectedIndex) } + LaunchedEffect(itemWidthPx) { + if (itemWidthPx > 0f) { + offsetAnim.snapTo(selectedIndex * itemWidthPx) + } + } + LaunchedEffect(selectedIndex, itemWidthPx) { + if (itemWidthPx <= 0f) return@LaunchedEffect + val dist = kotlin.math.abs(selectedIndex - lastSelectedIndex).coerceAtLeast(1) + val damping = when { + dist >= 3 -> 0.65f + dist == 2 -> 0.75f + else -> 0.90f + } + val stiffness = Spring.StiffnessMediumLow + offsetAnim.animateTo( + targetValue = selectedIndex * itemWidthPx, + animationSpec = spring(dampingRatio = damping, stiffness = stiffness) + ) + lastSelectedIndex = selectedIndex + } + val horizontalInset = 2.dp + val indicatorWidth = (with(density) { itemWidthPx.toDp() } - horizontalInset * 2) + .coerceAtLeast(70.dp) + .coerceAtMost(with(density) { itemWidthPx.toDp() }) + Box( + modifier = Modifier + .fillMaxSize() + .onGloballyPositioned { barWidthPx = it.size.width.toFloat() } + ) { + val motionProgress = remember { Animatable(1f) } + LaunchedEffect(selectedIndex) { + motionProgress.snapTo(0f) + val dist = kotlin.math.abs(selectedIndex - lastSelectedIndex).coerceAtLeast(1) + val dur = when { + dist >= 3 -> 440 + dist == 2 -> 380 + else -> 320 + } + motionProgress.animateTo( + 1f, + animationSpec = tween(durationMillis = dur, easing = FastOutSlowInEasing) + ) + } + val pulse = sin(PI * motionProgress.value).toFloat() + val distForScale = kotlin.math.abs(selectedIndex - lastSelectedIndex).coerceAtLeast(1) + val scaleXBase = 0.18f + val scaleXExtra = 0.06f + val scaleYBase = 0.06f + val scaleYExtra = 0.02f + val mult = (distForScale - 1).coerceAtLeast(0) + val scaleXAnim = 1f + (scaleXBase + scaleXExtra * mult) * pulse + val scaleYAnim = 1f - (scaleYBase + scaleYExtra * mult) * pulse + if (barWidthPx > 0f && itemCount > 0) { + val offsetX = with(density) { offsetAnim.value.toDp() } + horizontalInset + val indicatorShape = RoundedCornerShape(18.dp) + Box( + modifier = Modifier + .fillMaxHeight() + .width(indicatorWidth.coerceAtLeast(0.dp)) + .offset(x = offsetX) + .padding(vertical = 10.dp, horizontal = 2.dp) + .graphicsLayer { scaleX = scaleXAnim; scaleY = scaleYAnim } + ) { + Box( + modifier = Modifier + .matchParentSize() + .clip(indicatorShape) + .background( + Brush.linearGradient( + listOf( + PurrfectPalette.glowPrimary.copy(alpha = 0.42f), + PurrfectPalette.glowSecondary.copy(alpha = 0.38f) + ) + ) + ) + .border( + BorderStroke(1.dp, Brush.linearGradient(listOf(PurrfectPalette.glowPrimary, PurrfectPalette.glowSecondary))), + indicatorShape + ) + .drawBehind { + drawCircle( + brush = Brush.radialGradient( + colors = listOf( + PurrfectPalette.glowPrimary.copy(alpha = 0.35f), + Color.Transparent + ), + center = center, + radius = size.minDimension + ), + radius = size.minDimension, + center = center + ) + drawRoundRect( + color = Color.White.copy(alpha = 0.08f), + cornerRadius = CornerRadius(size.height / 2, size.height / 2), + size = size + ) + } + ) + } + } + } + } + NavigationBar( + containerColor = Color.Transparent, + tonalElevation = 0.dp, + modifier = Modifier + .fillMaxSize() + .padding(horizontal = 6.dp) + ) { + selectedRoutes.forEach { route -> + val isSelected = currentRoute == route + val selectionProgress by animateFloatAsState(if (isSelected) 1f else 0f, label = "${route.routeInfo.id}-selection") + NavigationBarItem( + alwaysShowLabel = true, + icon = { + Icon( + imageVector = route.routeInfo.icon, + contentDescription = null, + modifier = Modifier + .size(22.dp + 2.dp * selectionProgress) + .graphicsLayer { alpha = 0.65f + 0.35f * selectionProgress } + ) + }, + label = { + val label = context.translation["manager.routes.${route.routeInfo.key.substringBefore("/")}"] + val isLong = label.length > 11 + Text( + text = label, + textAlign = TextAlign.Center, + fontSize = 12.sp, + fontWeight = FontWeight.SemiBold, + color = Color.White.copy(alpha = 0.6f + 0.4f * selectionProgress), + maxLines = if (isLong) 2 else 1, + overflow = if (isLong) TextOverflow.Ellipsis else TextOverflow.Clip, + softWrap = isLong, + modifier = if (isLong) Modifier.widthIn(max = 90.dp).wrapContentWidth(Alignment.CenterHorizontally) else Modifier.wrapContentWidth(Alignment.CenterHorizontally) + ) + }, + selected = isSelected, + colors = NavigationBarItemDefaults.colors( + selectedIconColor = Color.White, + unselectedIconColor = Color.White.copy(alpha = 0.72f), + selectedTextColor = Color.White, + unselectedTextColor = Color.White.copy(alpha = 0.72f), + indicatorColor = Color.Transparent + ), + onClick = { route.navigateReset() } + ) + } + } + } + } + } + if (openBottomBarCustomization) { + val sheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true) + ModalBottomSheet( + onDismissRequest = { openBottomBarCustomization = false }, + sheetState = sheetState, + containerColor = Color.Transparent, + dragHandle = {} + ) { + Surface( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 8.dp, vertical = 4.dp), + shape = RoundedCornerShape(topStart = 26.dp, topEnd = 26.dp), + color = Color.Transparent, + tonalElevation = 0.dp, + shadowElevation = 12.dp, + border = BorderStroke(1.dp, Color.White.copy(alpha = 0.1f)) + ) { + Column( + modifier = Modifier + .background(PurrfectPalette.backgroundGradient) + .padding(vertical = 12.dp) + ) { + Box( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 16.dp, vertical = 10.dp) + .clip(RoundedCornerShape(22.dp)) + .background( + brush = Brush.linearGradient( + colors = listOf( + PurrfectPalette.glowPrimary.copy(alpha = 0.28f), + PurrfectPalette.glowSecondary.copy(alpha = 0.26f) + ) + ) + ) + .padding(horizontal = 18.dp, vertical = 16.dp) + ) { + Column( + modifier = Modifier.fillMaxWidth(), + horizontalAlignment = Alignment.CenterHorizontally + ) { + Text( + text = translation["customize_bottom_bar_title"], + style = MaterialTheme.typography.titleLarge, + color = Color.White, + textAlign = TextAlign.Center + ) + Spacer(Modifier.height(4.dp)) + Text( + text = translation["customize_bottom_bar_subtitle"], + style = MaterialTheme.typography.labelLarge, + color = Color.White.copy(alpha = 0.8f), + textAlign = TextAlign.Center + ) + } + } + Box( + modifier = Modifier + .align(Alignment.CenterHorizontally) + .padding(top = 6.dp, bottom = 2.dp) + .width(40.dp) + .height(5.dp) + .clip(RoundedCornerShape(50)) + .background(Color.White.copy(alpha = 0.35f)) + ) + Spacer(Modifier.height(6.dp)) + Text( + text = translation["shown_tabs_title"], + style = MaterialTheme.typography.titleSmall, + modifier = Modifier.padding(horizontal = 16.dp), + color = Color.White + ) + Spacer(Modifier.height(6.dp)) + if (selectedTabIds.isEmpty()) { + Text( + text = translation["no_tabs_selected_text"], + style = MaterialTheme.typography.bodyMedium, + color = PurrfectPalette.textSecondary, + modifier = Modifier.padding(horizontal = 16.dp, vertical = 8.dp) + ) + } else { + val haptic = LocalHapticFeedback.current + var draggingId by remember { mutableStateOf(null) } + var dragDelta by remember { mutableStateOf(0f) } + var dragStartIndex by remember { mutableStateOf(-1) } + var rowHeight by remember { mutableStateOf(0) } + val listState = rememberLazyListState() + LazyColumn( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 12.dp), + contentPadding = PaddingValues(bottom = 8.dp), + state = listState + ) { + itemsIndexed(selectedTabIds, key = { _, id -> id }) { index, id -> + val route = availableRouteMap[id] ?: return@itemsIndexed + val label = context.translation["manager.routes.${route.routeInfo.key.substringBefore("/")}"] + val isDragging = draggingId == id + val rowShape = RoundedCornerShape(18.dp) + Surface( + modifier = Modifier + .fillMaxWidth() + .padding(bottom = 8.dp) + .animateItem() + .zIndex(if (isDragging) 1f else 0f) + .graphicsLayer { if (isDragging) { scaleX = 1.02f; scaleY = 1.02f } } + .onGloballyPositioned { if (rowHeight == 0) rowHeight = it.size.height } + .pointerInput(id) { + detectDragGestures( + onDragStart = { + draggingId = id + dragStartIndex = selectedTabIds.indexOf(id) + dragDelta = 0f + haptic.performHapticFeedback(androidx.compose.ui.hapticfeedback.HapticFeedbackType.LongPress) + }, + onDrag = { _: PointerInputChange, dragAmount -> + dragDelta += dragAmount.y + if (rowHeight > 0 && dragStartIndex >= 0) { + val currentIndex = selectedTabIds.indexOf(id) + val deltaRows = round(dragDelta / rowHeight.toFloat()).toInt() + val targetIndex = (dragStartIndex + deltaRows).coerceIn(0, selectedTabIds.lastIndex) + if (targetIndex != currentIndex) { + val list = selectedTabIds.toMutableList() + list.removeAt(currentIndex) + list.add(targetIndex, id) + selectedTabIds = list + saveSelected(selectedTabIds) + haptic.performHapticFeedback(androidx.compose.ui.hapticfeedback.HapticFeedbackType.TextHandleMove) + } + } + }, + onDragEnd = { draggingId = null; dragDelta = 0f; dragStartIndex = -1 }, + onDragCancel = { draggingId = null; dragDelta = 0f; dragStartIndex = -1 } + ) + }, + shape = rowShape, + color = Color.Transparent, + border = BorderStroke( + 1.dp, + if (isDragging) Brush.linearGradient(listOf(PurrfectPalette.glowPrimary, PurrfectPalette.glowSecondary)) + else SolidColor(Color.White.copy(alpha = 0.1f)) + ), + tonalElevation = 0.dp, + shadowElevation = 0.dp + ) { + Row( + modifier = Modifier + .padding(12.dp) + .fillMaxWidth() + .clip(rowShape) + .background( + if (isDragging) Brush.linearGradient( + colors = listOf( + PurrfectPalette.glowPrimary.copy(alpha = 0.18f), + PurrfectPalette.glowSecondary.copy(alpha = 0.16f) + ) + ) else SolidColor(Color.White.copy(alpha = 0.08f)) + ), + verticalAlignment = Alignment.CenterVertically + ) { + Icon(Icons.Filled.DragHandle, contentDescription = null, tint = Color.White.copy(alpha = 0.8f)) + Spacer(Modifier.width(8.dp)) + Icon(route.routeInfo.icon, contentDescription = null, tint = Color.White) + Spacer(Modifier.width(12.dp)) + Text(text = label, modifier = Modifier.weight(1f), maxLines = 1, overflow = TextOverflow.Ellipsis, color = Color.White) + val defaultEligible = remember { setOf("tasks","features","home","social","scripts") } + RadioButton( + selected = defaultTabId == id, + onClick = { if (id in defaultEligible) saveDefault(id) }, + enabled = id in defaultEligible, + colors = RadioButtonDefaults.colors( + selectedColor = PurrfectPalette.glowPrimary, + unselectedColor = Color.White.copy(alpha = 0.7f), + disabledSelectedColor = PurrfectPalette.glowPrimary.copy(alpha = 0.4f), + disabledUnselectedColor = Color.White.copy(alpha = 0.35f) + ) + ) + IconButton( + onClick = { + if (selectedTabIds.size > 1 && id != defaultTabId && id != "home") { + selectedTabIds = selectedTabIds.toMutableList().also { it.removeAt(index) } + saveSelected(selectedTabIds) + } + }, + enabled = id != defaultTabId && id != "home" + ) { Icon(Icons.Filled.Close, contentDescription = null, tint = Color.White) } + } + } + } + } + } + Spacer(Modifier.height(12.dp)) + Text(text = translation["available_tabs_title"], style = MaterialTheme.typography.titleSmall, modifier = Modifier.padding(horizontal = 16.dp), color = Color.White) + Spacer(Modifier.height(6.dp)) + FlowRow( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 12.dp), + horizontalArrangement = Arrangement.spacedBy(6.dp) + ) { + availableRoutes.forEach { route -> + val id = route.routeInfo.id + val already = selectedTabIds.contains(id) + val label = context.translation["manager.routes.${route.routeInfo.key.substringBefore("/")}"] + AnimatedVisibility( + visible = !already && selectedTabIds.size < 5, + enter = scaleIn(tween(160), initialScale = 0.95f) + fadeIn(tween(180)) + slideInVertically(tween(180), initialOffsetY = { it / 3 }), + exit = scaleOut(tween(120)) + fadeOut(tween(120)) + slideOutVertically(tween(120)) + ) { + AssistChip( + onClick = { + if (!already && selectedTabIds.size < 5) { + selectedTabIds = selectedTabIds + id + saveSelected(selectedTabIds) + } + }, + label = { Text(text = label) }, + leadingIcon = { Icon(route.routeInfo.icon, contentDescription = null) }, + enabled = true, + colors = AssistChipDefaults.assistChipColors( + containerColor = Color.White.copy(alpha = 0.08f), + labelColor = Color.White, + leadingIconContentColor = PurrfectPalette.glowSecondary + ) + ) + } + } + } + Spacer(Modifier.height(16.dp)) + Row( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 16.dp, vertical = 8.dp), + horizontalArrangement = Arrangement.SpaceBetween + ) { + OutlinedButton( + onClick = { + selectedTabIds = defaultOrder + saveSelected(selectedTabIds) + }, + colors = ButtonDefaults.outlinedButtonColors(contentColor = Color.White), + border = BorderStroke(1.dp, Brush.linearGradient(listOf(PurrfectPalette.glowPrimary, PurrfectPalette.glowSecondary))) + ) { + Text(text = translation["reset_button"], style = MaterialTheme.typography.labelLarge) + } + Button( + onClick = { openBottomBarCustomization = false }, + colors = ButtonDefaults.buttonColors( + containerColor = Color.White.copy(alpha = 0.08f), + contentColor = Color.White + ) + ) { + Text(text = translation["done_button"], style = MaterialTheme.typography.labelLarge) + } + } + } + } + } + } + } + } + @Composable + fun Fab() { + val navBackStackEntry by navController.currentBackStackEntryAsState() + remember(navBackStackEntry) { routes.getCurrentRoute(navBackStackEntry) }?.floatingActionButton?.invoke() + } + @Composable + fun NavContent(paddingValues: PaddingValues, startDestination: String) { + NavHost( + navController = navController, + startDestination = startDestination, + modifier = Modifier.padding(paddingValues) + ) { + routes.getRoutes().filter { it.parentRoute == null }.forEach { route -> + val children = routes.getRoutes().filter { it.parentRoute == route } + if (children.isEmpty()) { + val isSummaryScreen = route.routeInfo.id == Routes.CONFIG_IMPORT_CONFIRMATION_ROUTE || + route.routeInfo.id == Routes.CONFIG_EXPORT_SUMMARY_ROUTE || + route.routeInfo.id == Routes.FRIEND_TRACKER_CONFIG_EXPORT_ROUTE || + route.routeInfo.id == Routes.FRIEND_TRACKER_CONFIG_IMPORT_ROUTE + val isAddRuleScreen = route.routeInfo.id.startsWith("edit_rule") + val animatedRoutes = setOf("friend_tracker_catalog", "manage_friend_tracker_repos", "manage_script_repos", "manage_repos") + val isAnimatedRoute = animatedRoutes.contains(route.routeInfo.id) + val addRuleEnterAnimation = slideInHorizontally(animationSpec = tween(400)) { it } + val addRuleExitAnimation = slideOutHorizontally(animationSpec = tween(400)) { -it } + val addRulePopEnterAnimation = slideInHorizontally(animationSpec = tween(400)) { -it } + val addRulePopExitAnimation = slideOutHorizontally(animationSpec = tween(400)) { it } + val animatedRouteEnter = slideInHorizontally(animationSpec = tween(400)) { it } + val animatedRouteExit = slideOutHorizontally(animationSpec = tween(400)) { -it } + val animatedRoutePopEnter = slideInHorizontally(animationSpec = tween(400)) { -it } + val animatedRoutePopExit = slideOutHorizontally(animationSpec = tween(400)) { it } + composable( + route.routeInfo.id, + enterTransition = { + when { + isSummaryScreen -> slideInHorizontally { it } + isAddRuleScreen -> addRuleEnterAnimation + isAnimatedRoute -> animatedRouteEnter + else -> fadeIn(tween(100)) + } + }, + exitTransition = { + when { + isSummaryScreen -> slideOutHorizontally { -it } + isAddRuleScreen -> addRuleExitAnimation + isAnimatedRoute -> animatedRouteExit + else -> fadeOut(tween(100)) + } + }, + popEnterTransition = { + when { + isSummaryScreen -> slideInHorizontally { -it } + isAddRuleScreen -> addRulePopEnterAnimation + isAnimatedRoute -> animatedRoutePopEnter + else -> fadeIn(tween(100)) + } + }, + popExitTransition = { + when { + isSummaryScreen -> slideOutHorizontally { it } + isAddRuleScreen -> addRulePopExitAnimation + isAnimatedRoute -> animatedRoutePopExit + else -> fadeOut(tween(100)) + } + } + ) { route.content.invoke(it) } + route.customComposables.invoke(this) + } else { + navigation("main_" + route.routeInfo.id, route.routeInfo.id) { + composable("main_" + route.routeInfo.id) { route.content.invoke(it) } + children.forEach { child -> composable(child.routeInfo.id) { child.content.invoke(it) } } + route.customComposables.invoke(this) + } + } + } + } + } + + @Composable fun FloatingActionButton() = Fab() + @Composable fun Content(paddingValues: PaddingValues, startDestination: String) = NavContent(paddingValues, startDestination) +} diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/Routes.kt b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/Routes.kt similarity index 66% rename from app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/Routes.kt rename to app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/Routes.kt index 4fae657c..33a75793 100644 --- a/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/Routes.kt +++ b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/Routes.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.ui.manager +package me.eternal.purrfectsnap.ui.manager import androidx.compose.foundation.layout.RowScope import androidx.compose.material.icons.Icons @@ -11,27 +11,27 @@ import androidx.navigation.NavController import androidx.navigation.NavDestination.Companion.hierarchy import androidx.navigation.NavGraph.Companion.findStartDestination import androidx.navigation.NavGraphBuilder -import me.rhunk.snapenhance.RemoteSideContext -import me.rhunk.snapenhance.ui.manager.pages.FileImportsRoot -import me.rhunk.snapenhance.ui.manager.pages.LoggerHistoryRoot -import me.rhunk.snapenhance.ui.manager.pages.ManageReposSection -import me.rhunk.snapenhance.ui.manager.pages.TasksRootSection -import me.rhunk.snapenhance.ui.manager.pages.features.FeaturesRootSection -import me.rhunk.snapenhance.ui.manager.pages.features.ManageRuleFeature -import me.rhunk.snapenhance.ui.manager.pages.home.HomeLogs -import me.rhunk.snapenhance.ui.manager.pages.home.HomeRootSection -import me.rhunk.snapenhance.ui.manager.pages.home.HomeSettings -import me.rhunk.snapenhance.ui.manager.pages.location.BetterLocationRoot -import me.rhunk.snapenhance.ui.manager.pages.scripting.ScriptingRootSection -import me.rhunk.snapenhance.ui.manager.pages.social.LoggedStories -import me.rhunk.snapenhance.ui.manager.pages.social.ManageScope -import me.rhunk.snapenhance.ui.manager.pages.social.MessagingPreview -import me.rhunk.snapenhance.ui.manager.pages.social.SocialRootSection -import me.rhunk.snapenhance.ui.manager.pages.tracker.EditRule -import me.rhunk.snapenhance.ui.manager.pages.tracker.FriendTrackerManagerRoot -import me.rhunk.snapenhance.ui.manager.pages.tracker.FriendTrackerCatalog -import me.rhunk.snapenhance.ui.manager.pages.tracker.ManageFriendTrackerReposSection -import me.rhunk.snapenhance.ui.manager.pages.scripting.ManageScriptReposSection +import me.eternal.purrfectsnap.RemoteSideContext +import me.eternal.purrfectsnap.ui.manager.pages.FileImportsRoot +import me.eternal.purrfectsnap.ui.manager.pages.LoggerHistoryRoot +import me.eternal.purrfectsnap.ui.manager.pages.ManageReposSection +import me.eternal.purrfectsnap.ui.manager.pages.TasksRootSection +import me.eternal.purrfectsnap.ui.manager.pages.features.FeaturesRootSection +import me.eternal.purrfectsnap.ui.manager.pages.features.ManageRuleFeature +import me.eternal.purrfectsnap.ui.manager.pages.home.HomeLogs +import me.eternal.purrfectsnap.ui.manager.pages.home.HomeRootSection +import me.eternal.purrfectsnap.ui.manager.pages.home.HomeSettings +import me.eternal.purrfectsnap.ui.manager.pages.location.BetterLocationRoot +import me.eternal.purrfectsnap.ui.manager.pages.scripting.ScriptingRootSection +import me.eternal.purrfectsnap.ui.manager.pages.social.LoggedStories +import me.eternal.purrfectsnap.ui.manager.pages.social.ManageScope +import me.eternal.purrfectsnap.ui.manager.pages.social.MessagingPreview +import me.eternal.purrfectsnap.ui.manager.pages.social.SocialRootSection +import me.eternal.purrfectsnap.ui.manager.pages.tracker.EditRule +import me.eternal.purrfectsnap.ui.manager.pages.tracker.FriendTrackerManagerRoot +import me.eternal.purrfectsnap.ui.manager.pages.tracker.FriendTrackerCatalog +import me.eternal.purrfectsnap.ui.manager.pages.tracker.ManageFriendTrackerReposSection +import me.eternal.purrfectsnap.ui.manager.pages.scripting.ManageScriptReposSection data class RouteInfo( @@ -59,43 +59,44 @@ class Routes( } lateinit var navController: NavController - lateinit var activityLauncher: me.rhunk.snapenhance.ui.util.ActivityLauncherHelper + lateinit var activityLauncher: me.eternal.purrfectsnap.ui.util.ActivityLauncherHelper + var navigation: me.eternal.purrfectsnap.ui.manager.Navigation? = null private val routes = mutableListOf() var bottomPadding: androidx.compose.ui.unit.Dp = 0.dp var configJsonForImport: String? = null var friendTrackerConfigJsonForImport: String? = null var onRuleImported: (() -> Unit)? = null - val configImportConfirmation = route(RouteInfo(CONFIG_IMPORT_CONFIRMATION_ROUTE), me.rhunk.snapenhance.ui.manager.pages.features.ConfigImportConfirmationScreen()) - val configExportSummary = route(RouteInfo(CONFIG_EXPORT_SUMMARY_ROUTE), me.rhunk.snapenhance.ui.manager.pages.features.ConfigExportSummaryScreen()) + val configImportConfirmation = route(RouteInfo(CONFIG_IMPORT_CONFIRMATION_ROUTE), me.eternal.purrfectsnap.ui.manager.pages.features.ConfigImportConfirmationScreen()) + val configExportSummary = route(RouteInfo(CONFIG_EXPORT_SUMMARY_ROUTE), me.eternal.purrfectsnap.ui.manager.pages.features.ConfigExportSummaryScreen()) - val tasks = route(RouteInfo("tasks", icon = Icons.Default.TaskAlt, primary = true), TasksRootSection()) + val tasks = route(RouteInfo("tasks", icon = Icons.Default.TaskAlt, primary = true, hasOwnTopBar = true), TasksRootSection()) - val features = route(RouteInfo("features", icon = Icons.Default.Stars, primary = true), FeaturesRootSection()) - val manageRuleFeature = route(RouteInfo("manage_rule_feature/?rule_type={rule_type}"), ManageRuleFeature()).parent(features) + val features = route(RouteInfo("features", icon = Icons.Default.Stars, primary = true, hasOwnTopBar = true), FeaturesRootSection()) + val manageRuleFeature = route(RouteInfo("manage_rule_feature/?rule_type={rule_type}", hasOwnTopBar = true), ManageRuleFeature()).parent(features) - val home = route(RouteInfo("home", icon = Icons.Default.Home, primary = true), HomeRootSection()) - val settings = route(RouteInfo("home_settings"), HomeSettings()).parent(home) - val homeLogs = route(RouteInfo("home_logs"), HomeLogs()).parent(home) - val loggerHistory = route(RouteInfo("logger_history"), LoggerHistoryRoot()).parent(home) - val viewLoggerHistory = route(RouteInfo(VIEW_LOGGER_HISTORY_ROUTE), LoggerHistoryRoot()).parent(home) - val friendTracker = route(RouteInfo("friend_tracker", icon = Icons.Default.PersonSearch), FriendTrackerManagerRoot()).parent(home) + val home = route(RouteInfo("home", icon = Icons.Default.Home, primary = true, hasOwnTopBar = true), HomeRootSection()) + val settings = route(RouteInfo("home_settings", hasOwnTopBar = true), HomeSettings()).parent(home) + val homeLogs = route(RouteInfo("home_logs", hasOwnTopBar = true), HomeLogs()).parent(home) + val loggerHistory = route(RouteInfo("logger_history", hasOwnTopBar = true), LoggerHistoryRoot()).parent(home) + val viewLoggerHistory = route(RouteInfo(VIEW_LOGGER_HISTORY_ROUTE, hasOwnTopBar = true), LoggerHistoryRoot()).parent(home) + val friendTracker = route(RouteInfo("friend_tracker", icon = Icons.Default.PersonSearch, hasOwnTopBar = true), FriendTrackerManagerRoot()).parent(home) val editRule = route(RouteInfo("edit_rule/?rule_id={rule_id}", hasOwnTopBar = true), EditRule()) - val friendTrackerConfigExport = route(RouteInfo(FRIEND_TRACKER_CONFIG_EXPORT_ROUTE), me.rhunk.snapenhance.ui.manager.pages.tracker.FriendTrackerConfigExportScreen()) - val friendTrackerConfigImport = route(RouteInfo(FRIEND_TRACKER_CONFIG_IMPORT_ROUTE), me.rhunk.snapenhance.ui.manager.pages.tracker.FriendTrackerConfigImportScreen()) - val friendTrackerCatalog = route(RouteInfo("friend_tracker_catalog"), FriendTrackerCatalog()) - val manageFriendTrackerRepos = route(RouteInfo("manage_friend_tracker_repos"), ManageFriendTrackerReposSection()) + val friendTrackerConfigExport = route(RouteInfo(FRIEND_TRACKER_CONFIG_EXPORT_ROUTE), me.eternal.purrfectsnap.ui.manager.pages.tracker.FriendTrackerConfigExportScreen()) + val friendTrackerConfigImport = route(RouteInfo(FRIEND_TRACKER_CONFIG_IMPORT_ROUTE), me.eternal.purrfectsnap.ui.manager.pages.tracker.FriendTrackerConfigImportScreen()) + val friendTrackerCatalog = route(RouteInfo("friend_tracker_catalog", hasOwnTopBar = true), FriendTrackerCatalog()) + val manageFriendTrackerRepos = route(RouteInfo("manage_friend_tracker_repos", hasOwnTopBar = true), ManageFriendTrackerReposSection()) val fileImports = route(RouteInfo("file_imports"), FileImportsRoot()).parent(home) val manageRepos = route(RouteInfo("manage_repos/?type={type}"), ManageReposSection()) - val social = route(RouteInfo("social", icon = Icons.Default.Group, primary = true), SocialRootSection()) - val manageScope = route(RouteInfo("manage_scope/?scope={scope}&id={id}"), ManageScope()).parent(social) - val messagingPreview = route(RouteInfo("messaging_preview/?scope={scope}&id={id}"), MessagingPreview()).parent(social) + val social = route(RouteInfo("social", icon = Icons.Default.Group, primary = true, hasOwnTopBar = true), SocialRootSection()) + val manageScope = route(RouteInfo("manage_scope/?scope={scope}&id={id}", hasOwnTopBar = true), ManageScope()).parent(social) + val messagingPreview = route(RouteInfo("messaging_preview/?scope={scope}&id={id}", hasOwnTopBar = true), MessagingPreview()).parent(social) val loggedStories = route(RouteInfo("logged_stories/?id={id}"), LoggedStories()).parent(social) - val scripting = route(RouteInfo("scripts", icon = Icons.Filled.DataObject, primary = true), ScriptingRootSection()) - val manageScriptRepos = route(RouteInfo("manage_script_repos"), ManageScriptReposSection()) + val scripting = route(RouteInfo("scripts", icon = Icons.Filled.DataObject, primary = true, hasOwnTopBar = true), ScriptingRootSection()) + val manageScriptRepos = route(RouteInfo("manage_script_repos", hasOwnTopBar = true), ManageScriptReposSection()) val betterLocation = route(RouteInfo("better_location", showInNavBar = false, primary = true), BetterLocationRoot()) diff --git a/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/components/AestheticDialog.kt b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/components/AestheticDialog.kt new file mode 100644 index 00000000..b47fbb82 --- /dev/null +++ b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/components/AestheticDialog.kt @@ -0,0 +1,173 @@ +package me.eternal.purrfectsnap.ui.manager.components + +import androidx.compose.animation.AnimatedVisibility +import androidx.compose.animation.fadeIn +import androidx.compose.animation.fadeOut +import androidx.compose.animation.scaleIn +import androidx.compose.animation.scaleOut +import androidx.compose.foundation.BorderStroke +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.ColumnScope +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Close +import androidx.compose.material3.Button +import androidx.compose.material3.ButtonDefaults +import androidx.compose.material3.Card +import androidx.compose.material3.CardDefaults +import androidx.compose.material3.CircularProgressIndicator +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Brush +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.dp +import androidx.compose.ui.window.Dialog +import me.eternal.purrfectsnap.ui.manager.theme.PurrfectPalette +import me.eternal.purrfectsnap.ui.util.Motion + +@Composable +fun AestheticDialog( + onDismissRequest: () -> Unit, + title: String, + text: String, + icon: ImageVector, + confirmButtonText: String, + onConfirm: () -> Unit, + dismissButtonText: String? = null, + onDismiss: (() -> Unit)? = null, + customContent: (@Composable ColumnScope.() -> Unit)? = null, + loading: Boolean = false, + opaque: Boolean = false, + showCloseButton: Boolean = true, + confirmEnabled: Boolean = true +) { + var visible by remember { mutableStateOf(false) } + LaunchedEffect(Unit) { visible = true } + + val surfaceColor = if (opaque) { + PurrfectPalette.cardOverlayColor.copy(alpha = 1f) + } else { + PurrfectPalette.cardOverlayColor + } + + Dialog(onDismissRequest = onDismissRequest) { + AnimatedVisibility( + visible = visible, + enter = fadeIn(animationSpec = Motion.tweenFloatSpec(180)) + scaleIn(animationSpec = Motion.tweenFloatSpec(220)), + exit = fadeOut(animationSpec = Motion.tweenFloatSpec(150)) + scaleOut(animationSpec = Motion.tweenFloatSpec(180)) + ) { + val shape = RoundedCornerShape(22.dp) + Card( + shape = shape, + border = BorderStroke(1.dp, Color.White.copy(alpha = 0.12f)), + colors = CardDefaults.cardColors(containerColor = surfaceColor) + ) { + Box( + modifier = Modifier + .background(PurrfectPalette.cardOverlay, shape) + .padding(20.dp) + ) { + Column( + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.spacedBy(14.dp) + ) { + Box( + modifier = Modifier + .size(62.dp) + .background( + Brush.linearGradient( + listOf( + PurrfectPalette.glowPrimary.copy(alpha = 0.3f), + PurrfectPalette.glowSecondary.copy(alpha = 0.28f) + ) + ), + CircleShape + ), + contentAlignment = Alignment.Center + ) { + Icon(icon, contentDescription = null, tint = Color.White, modifier = Modifier.size(30.dp)) + } + Text( + text = title, + style = MaterialTheme.typography.titleLarge.copy(fontWeight = FontWeight.ExtraBold), + color = Color.White, + textAlign = TextAlign.Center + ) + if (text.isNotBlank()) { + Text( + text = text, + style = MaterialTheme.typography.bodyMedium, + color = PurrfectPalette.textSecondary, + textAlign = TextAlign.Center + ) + } + customContent?.invoke(this) + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.spacedBy(10.dp, Alignment.CenterHorizontally) + ) { + if (dismissButtonText != null && onDismiss != null) { + Button( + onClick = onDismiss, + colors = ButtonDefaults.buttonColors( + containerColor = Color.White.copy(alpha = 0.08f), + contentColor = Color.White + ) + ) { Text(dismissButtonText) } + } + Button( + onClick = onConfirm, + enabled = confirmEnabled && !loading, + colors = ButtonDefaults.buttonColors( + containerColor = PurrfectPalette.glowPrimary.copy(alpha = 0.34f), + contentColor = Color.White + ) + ) { + if (loading) { + CircularProgressIndicator( + modifier = Modifier.size(20.dp), + strokeWidth = 2.dp, + color = Color.White + ) + } else { + Text(confirmButtonText) + } + } + } + } + if (showCloseButton) { + IconButton( + onClick = onDismissRequest, + modifier = Modifier.align(Alignment.TopEnd) + ) { + Icon(Icons.Default.Close, contentDescription = null, tint = Color.White) + } + } + } + } + } + } +} diff --git a/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/components/AestheticEmptyState.kt b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/components/AestheticEmptyState.kt new file mode 100644 index 00000000..19a2f609 --- /dev/null +++ b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/components/AestheticEmptyState.kt @@ -0,0 +1,92 @@ +package me.eternal.purrfectsnap.ui.manager.components + +import androidx.compose.foundation.BorderStroke +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Surface +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Brush +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.dp +import me.eternal.purrfectsnap.ui.manager.theme.PurrfectPalette + +@Composable +fun AestheticEmptyState( + icon: ImageVector, + title: String, + subtitle: String? = null, + modifier: Modifier = Modifier, + actions: (@Composable () -> Unit)? = null +) { + Column( + modifier = modifier, + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.spacedBy(12.dp) + ) { + Surface( + shape = CircleShape, + color = Color.White.copy(alpha = 0.08f), + tonalElevation = 0.dp, + shadowElevation = 0.dp, + border = BorderStroke(1.dp, Color.White.copy(alpha = 0.12f)) + ) { + Box( + modifier = Modifier + .size(58.dp) + .background( + Brush.linearGradient( + listOf( + PurrfectPalette.glowPrimary.copy(alpha = 0.32f), + PurrfectPalette.glowSecondary.copy(alpha = 0.28f) + ) + ), + CircleShape + ), + contentAlignment = Alignment.Center + ) { + androidx.compose.material3.Icon( + imageVector = icon, + contentDescription = null, + tint = Color.White + ) + } + } + + Text( + text = title, + style = MaterialTheme.typography.titleMedium.copy(fontWeight = FontWeight.ExtraBold), + color = Color.White, + textAlign = TextAlign.Center + ) + + if (!subtitle.isNullOrBlank()) { + Text( + text = subtitle, + style = MaterialTheme.typography.bodyMedium, + color = PurrfectPalette.textSecondary, + textAlign = TextAlign.Center, + modifier = Modifier.fillMaxWidth().padding(horizontal = 18.dp) + ) + } + + if (actions != null) { + Spacer(modifier = Modifier.size(2.dp)) + actions() + } + } +} + diff --git a/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/components/FloatingTopBar.kt b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/components/FloatingTopBar.kt new file mode 100644 index 00000000..c7bdb76c --- /dev/null +++ b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/components/FloatingTopBar.kt @@ -0,0 +1,126 @@ +package me.eternal.purrfectsnap.ui.manager.components + +import androidx.compose.foundation.BorderStroke +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.RowScope +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.WindowInsets +import androidx.compose.foundation.layout.asPaddingValues +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.statusBars +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.automirrored.filled.ArrowBack +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.Surface +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.Immutable +import androidx.compose.runtime.remember +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Brush +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextOverflow +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import me.eternal.purrfectsnap.ui.manager.theme.PurrfectPalette + +@Immutable +data class FloatingTopBarColors( + val container: Color, + val border: Brush +) + +@Composable +fun rememberDefaultFloatingTopBarColors(): FloatingTopBarColors { + return remember { + FloatingTopBarColors( + container = Color.White.copy(alpha = 0.07f), + border = Brush.linearGradient( + listOf( + PurrfectPalette.glowPrimary.copy(alpha = 0.55f), + PurrfectPalette.glowSecondary.copy(alpha = 0.35f) + ) + ) + ) + } +} + +@Composable +fun FloatingTopBar( + title: String, + subtitle: String? = null, + onBack: (() -> Unit)? = null, + modifier: Modifier = Modifier, + actions: @Composable RowScope.() -> Unit = {}, + colors: FloatingTopBarColors = rememberDefaultFloatingTopBarColors() +) { + val shape = RoundedCornerShape(26.dp) + Surface( + modifier = modifier + .fillMaxWidth() + .padding(horizontal = 14.dp, vertical = 12.dp) + .padding(top = WindowInsets.statusBars.asPaddingValues().calculateTopPadding()), + shape = shape, + color = colors.container, + tonalElevation = 0.dp, + shadowElevation = 0.dp, + border = BorderStroke(1.dp, colors.border) + ) { + Row( + modifier = Modifier.padding(horizontal = 16.dp, vertical = 14.dp), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(10.dp) + ) { + if (onBack != null) { + IconButton(onClick = onBack, modifier = Modifier.size(42.dp)) { + Icon( + imageVector = Icons.AutoMirrored.Filled.ArrowBack, + contentDescription = null, + tint = Color.White + ) + } + } else { + Spacer(modifier = Modifier.height(0.dp)) + } + + Column(modifier = Modifier.weight(1f)) { + Text( + text = title, + color = Color.White, + fontWeight = FontWeight.ExtraBold, + fontSize = 18.sp, + maxLines = 1, + overflow = TextOverflow.Ellipsis + ) + if (!subtitle.isNullOrBlank()) { + Spacer(modifier = Modifier.height(2.dp)) + Text( + text = subtitle, + color = PurrfectPalette.textSecondary, + fontSize = 12.sp, + maxLines = 2, + overflow = TextOverflow.Ellipsis + ) + } + } + + Box(contentAlignment = Alignment.CenterEnd) { + Row( + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(6.dp), + content = actions + ) + } + } + } +} diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/data/InstallationSummary.kt b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/data/InstallationSummary.kt similarity index 93% rename from app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/data/InstallationSummary.kt rename to app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/data/InstallationSummary.kt index 323b807e..296bcfb6 100644 --- a/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/data/InstallationSummary.kt +++ b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/data/InstallationSummary.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.ui.manager.data +package me.eternal.purrfectsnap.ui.manager.data data class SnapchatAppInfo( diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/data/UpdateDownloader.kt b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/data/UpdateDownloader.kt similarity index 88% rename from app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/data/UpdateDownloader.kt rename to app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/data/UpdateDownloader.kt index 73dba544..c44c8e15 100644 --- a/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/data/UpdateDownloader.kt +++ b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/data/UpdateDownloader.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.ui.manager.data +package me.eternal.purrfectsnap.ui.manager.data import android.content.Context import android.content.Intent @@ -9,7 +9,7 @@ import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.delay import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.launch -import me.rhunk.snapenhance.RemoteSideContext +import me.eternal.purrfectsnap.RemoteSideContext import java.io.File import java.io.FileOutputStream import java.util.zip.ZipInputStream @@ -19,17 +19,12 @@ object UpdateDownloader { private var listener: FetchListener? = null private fun getInstance(context: Context): Fetch { - val appContext = context.applicationContext - // If RemoteSideContext is part of your app, keep this, otherwise remove fetch?.let { return it } - fetch = when (appContext) { - is RemoteSideContext -> appContext.fetch - else -> { - val fetchConfiguration = FetchConfiguration.Builder(appContext) - .setDownloadConcurrentLimit(3) - .build() - Fetch.getInstance(fetchConfiguration) - } + fetch = run { + val fetchConfiguration = FetchConfiguration.Builder(context.applicationContext) + .setDownloadConcurrentLimit(3) + .build() + Fetch.getInstance(fetchConfiguration) } return fetch!! } @@ -101,7 +96,7 @@ object UpdateDownloader { unzip(downloadedFile, unzipDir) val apkFile = unzipDir.walk().find { it.isFile && it.extension == "apk" } ?: throw Exception("No APK found in the downloaded file") - val uri = FileProvider.getUriForFile(context, "me.rhunk.snapenhance.fileprovider", apkFile) + val uri = FileProvider.getUriForFile(context, "me.eternal.purrfectsnap.fileprovider", apkFile) val installIntent = Intent(Intent.ACTION_VIEW).apply { setDataAndType(uri, "application/vnd.android.package-archive") addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_ACTIVITY_NEW_TASK) diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/data/Updater.kt b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/data/Updater.kt similarity index 94% rename from app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/data/Updater.kt rename to app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/data/Updater.kt index 870e0bb1..d6ed7918 100644 --- a/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/data/Updater.kt +++ b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/data/Updater.kt @@ -1,8 +1,8 @@ -package me.rhunk.snapenhance.ui.manager.data +package me.eternal.purrfectsnap.ui.manager.data import com.google.gson.JsonParser -import me.rhunk.snapenhance.common.BuildConfig -import me.rhunk.snapenhance.common.logger.AbstractLogger +import me.eternal.purrfectsnap.common.BuildConfig +import me.eternal.purrfectsnap.common.logger.AbstractLogger import okhttp3.OkHttpClient import okhttp3.Request diff --git a/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/FileImportsRoot.kt b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/FileImportsRoot.kt new file mode 100644 index 00000000..dc6ce842 --- /dev/null +++ b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/FileImportsRoot.kt @@ -0,0 +1,285 @@ +package me.eternal.purrfectsnap.ui.manager.pages + +import android.net.Uri +import android.text.format.Formatter +import androidx.compose.foundation.BorderStroke +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.AttachFile +import androidx.compose.material.icons.filled.DeleteOutline +import androidx.compose.material.icons.filled.Upload +import androidx.compose.material3.ExtendedFloatingActionButton +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Surface +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Brush +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.text.style.TextOverflow +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import androidx.documentfile.provider.DocumentFile +import androidx.navigation.NavBackStackEntry +import kotlinx.coroutines.launch +import me.eternal.purrfectsnap.common.ui.AsyncUpdateDispatcher +import me.eternal.purrfectsnap.common.ui.rememberAsyncMutableState +import me.eternal.purrfectsnap.common.ui.rememberAsyncMutableStateList +import me.eternal.purrfectsnap.ui.manager.Routes +import me.eternal.purrfectsnap.ui.manager.theme.PurrfectPalette +import me.eternal.purrfectsnap.ui.util.ActivityLauncherHelper +import me.eternal.purrfectsnap.ui.util.openFile +import java.text.DateFormat + +class FileImportsRoot: Routes.Route() { + private lateinit var activityLauncherHelper: ActivityLauncherHelper + private val reloadDispatcher = AsyncUpdateDispatcher() + + override val init: () -> Unit = { + activityLauncherHelper = ActivityLauncherHelper(context.activity!!) + } + + override val floatingActionButton: @Composable () -> Unit = { + val coroutineScope = rememberCoroutineScope() + Row { + ExtendedFloatingActionButton( + icon = { + Icon(Icons.Default.Upload, contentDescription = null) + }, + text = { + Text(translation["import_file_button"]) + }, + onClick = { + context.coroutineScope.launch { + activityLauncherHelper.openFile { filePath -> + val fileUri = Uri.parse(filePath) + runCatching { + DocumentFile.fromSingleUri(context.activity!!, fileUri)?.let { file -> + if (!file.exists()) { + context.shortToast(translation["file_not_found"]) + return@openFile + } + context.fileHandleManager.importFile(file.name!!) { + context.androidContext.contentResolver.openInputStream(fileUri)?.use { inputStream -> + inputStream.copyTo(this) + } + } + } + }.onFailure { + context.log.error("Failed to import file", it) + context.shortToast(translation.format("file_import_failed", "error" to it.message.toString())) + }.onSuccess { + context.shortToast(translation["file_imported"]) + coroutineScope.launch { + reloadDispatcher.dispatch() + } + } + } + } + }) + } + } + + override val content: @Composable (NavBackStackEntry) -> Unit = { + val files = rememberAsyncMutableStateList(defaultValue = listOf(), updateDispatcher = reloadDispatcher) { + context.fileHandleManager.getStoredFiles() + } + + Box( + modifier = Modifier + .fillMaxSize() + .background(PurrfectPalette.backgroundGradient) + ) { + Column( + modifier = Modifier.fillMaxSize() + ) { + Surface( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 14.dp, vertical = 12.dp), + shape = RoundedCornerShape(24.dp), + color = Color.Transparent, + tonalElevation = 0.dp, + shadowElevation = 12.dp, + border = BorderStroke( + 1.dp, + Brush.linearGradient( + listOf( + PurrfectPalette.glowPrimary.copy(alpha = 0.55f), + PurrfectPalette.glowSecondary.copy(alpha = 0.35f) + ) + ) + ) + ) { + Column( + modifier = Modifier + .background(PurrfectPalette.cardOverlay, RoundedCornerShape(24.dp)) + .padding(horizontal = 18.dp, vertical = 14.dp), + verticalArrangement = Arrangement.spacedBy(6.dp) + ) { + Row( + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(10.dp) + ) { + Surface( + shape = RoundedCornerShape(16.dp), + color = PurrfectPalette.cardOverlayColor + ) { + Icon( + Icons.Default.AttachFile, + contentDescription = null, + tint = Color.White, + modifier = Modifier.padding(10.dp) + ) + } + Column { + Text( + text = translation["import_file_button"], + color = Color.White, + fontWeight = FontWeight.ExtraBold, + fontSize = 18.sp + ) + Text( + text = translation["manager.dialogs.file_imports.settings_select_file_hint"], + color = PurrfectPalette.textSecondary, + style = MaterialTheme.typography.bodySmall + ) + } + } + } + } + + LazyColumn( + modifier = Modifier + .fillMaxSize() + .padding(horizontal = 10.dp), + verticalArrangement = Arrangement.spacedBy(10.dp), + contentPadding = PaddingValues(bottom = routes.bottomPadding + 16.dp, top = 4.dp) + ) { + item { + if (files.isEmpty()) { + Surface( + modifier = Modifier.fillMaxWidth(), + shape = RoundedCornerShape(20.dp), + color = PurrfectPalette.cardOverlayColor, + tonalElevation = 0.dp, + shadowElevation = 10.dp, + border = BorderStroke(1.dp, Color.White.copy(alpha = 0.1f)) + ) { + Text( + text = translation["no_files_hint"], + modifier = Modifier + .padding(horizontal = 18.dp, vertical = 16.dp) + .fillMaxWidth(), + textAlign = TextAlign.Center, + fontSize = 16.sp, + fontWeight = FontWeight.Medium, + color = Color.White + ) + } + } + } + items(files, key = { it }) { file -> + val fileInfo by rememberAsyncMutableState(defaultValue = null) { + context.fileHandleManager.getFileInfo(file.name) + } + Surface( + modifier = Modifier.fillMaxWidth(), + shape = RoundedCornerShape(20.dp), + color = PurrfectPalette.cardOverlayColor, + tonalElevation = 0.dp, + shadowElevation = 10.dp, + border = BorderStroke( + 1.dp, + Brush.linearGradient( + listOf( + PurrfectPalette.glowPrimary.copy(alpha = 0.4f), + PurrfectPalette.glowSecondary.copy(alpha = 0.35f) + ) + ) + ) + ) { + Row( + modifier = Modifier + .padding(horizontal = 14.dp, vertical = 12.dp) + .fillMaxWidth(), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(12.dp) + ) { + Surface( + shape = RoundedCornerShape(14.dp), + color = PurrfectPalette.glowPrimary.copy(alpha = 0.16f) + ) { + Icon( + Icons.Default.AttachFile, + contentDescription = null, + modifier = Modifier.padding(10.dp), + tint = Color.White + ) + } + Column( + modifier = Modifier.weight(1f), + verticalArrangement = Arrangement.spacedBy(4.dp) + ) { + Text( + text = file.name, + fontWeight = FontWeight.Bold, + fontSize = 16.sp, + color = Color.White, + maxLines = 1, + overflow = TextOverflow.Ellipsis + ) + fileInfo?.let { (size, lastModified) -> + Text( + text = "${Formatter.formatFileSize(context.androidContext, size)} • ${ + DateFormat.getDateTimeInstance().format(lastModified) + }", + lineHeight = 15.sp, + color = PurrfectPalette.textSecondary, + fontSize = 12.sp + ) + } + } + + IconButton(onClick = { + context.coroutineScope.launch { + if (context.fileHandleManager.deleteFile(file.name)) { + files.remove(file) + } else { + context.shortToast(translation["file_delete_failed"]) + } + } + }) { + Icon( + Icons.Default.DeleteOutline, + contentDescription = null, + tint = PurrfectPalette.glowSecondary + ) + } + } + } + } + } + } + } + } +} diff --git a/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/LoggerHistoryRoot.kt b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/LoggerHistoryRoot.kt new file mode 100644 index 00000000..8a481f47 --- /dev/null +++ b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/LoggerHistoryRoot.kt @@ -0,0 +1,516 @@ +package me.eternal.purrfectsnap.ui.manager.pages + +import androidx.compose.foundation.BorderStroke +import androidx.compose.foundation.background +import androidx.compose.foundation.gestures.detectTapGestures +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.ExperimentalLayoutApi +import androidx.compose.foundation.layout.FlowRow +import androidx.compose.foundation.layout.RowScope +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items +import androidx.compose.foundation.text.KeyboardActions +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Close +import androidx.compose.material.icons.filled.Download +import androidx.compose.material.icons.filled.Search +import androidx.compose.material3.* +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableLongStateOf +import androidx.compose.runtime.mutableStateListOf +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Brush +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.input.pointer.pointerInput +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.ui.text.font.FontStyle +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.text.style.TextOverflow +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import androidx.core.net.toUri +import androidx.navigation.NavBackStackEntry +import com.google.gson.JsonParser +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext +import me.eternal.purrfectsnap.bridge.DownloadCallback +import me.eternal.purrfectsnap.common.bridge.wrapper.ConversationInfo +import me.eternal.purrfectsnap.common.bridge.wrapper.LoggedMessage +import me.eternal.purrfectsnap.common.bridge.wrapper.LoggerWrapper +import me.eternal.purrfectsnap.common.data.ContentType +import me.eternal.purrfectsnap.common.data.download.DownloadMetadata +import me.eternal.purrfectsnap.common.data.download.DownloadRequest +import me.eternal.purrfectsnap.common.data.download.MediaDownloadSource +import me.eternal.purrfectsnap.common.data.download.createNewFilePath +import me.eternal.purrfectsnap.common.ui.rememberAsyncMutableState +import me.eternal.purrfectsnap.common.ui.transparentTextFieldColors +import me.eternal.purrfectsnap.common.util.ktx.copyToClipboard +import me.eternal.purrfectsnap.common.util.ktx.longHashCode +import me.eternal.purrfectsnap.common.util.protobuf.ProtoReader +import me.eternal.purrfectsnap.core.features.impl.downloader.decoder.DecodedAttachment +import me.eternal.purrfectsnap.core.features.impl.downloader.decoder.MessageDecoder +import me.eternal.purrfectsnap.download.DownloadProcessor +import me.eternal.purrfectsnap.storage.findFriend +import me.eternal.purrfectsnap.ui.manager.Routes +import me.eternal.purrfectsnap.ui.manager.components.FloatingTopBar +import me.eternal.purrfectsnap.ui.manager.theme.PurrfectPalette +import java.net.URLDecoder +import java.text.DateFormat +import java.util.concurrent.ConcurrentHashMap +import kotlin.math.absoluteValue + + +class LoggerHistoryRoot : Routes.Route() { + override val translation by lazy { context.translation.getCategory("logger_history") } + private lateinit var loggerWrapper: LoggerWrapper + private var selectedConversation by mutableStateOf(null) + private var stringFilter by mutableStateOf("") + private var reverseOrder by mutableStateOf(true) + + private inline fun decodeMessage(message: LoggedMessage, result: (contentType: ContentType, messageReader: ProtoReader, attachments: List) -> Unit) { + runCatching { + val messageObject = JsonParser.parseString(String(message.messageData, Charsets.UTF_8)).asJsonObject + val messageContent = messageObject.getAsJsonObject("mMessageContent") + val messageReader = messageContent.getAsJsonArray("mContent").map { it.asByte }.toByteArray().let { ProtoReader(it) } + result(ContentType.fromMessageContainer(messageReader) ?: ContentType.UNKNOWN, messageReader, MessageDecoder.decode(messageContent)) + }.onFailure { + context.log.error("Failed to decode message", it) + } + } + + private fun downloadAttachment(creationTimestamp: Long, attachment: DecodedAttachment) { + context.shortToast(translation["download_started_toast"]) + val attachmentHash = attachment.mediaUniqueId!!.longHashCode().absoluteValue.toString() + + DownloadProcessor( + remoteSideContext = context, + callback = object: DownloadCallback.Default() { + override fun onSuccess(outputPath: String?) { + context.shortToast(translation.format("download_success_toast", "path" to outputPath.toString())) + } + + override fun onFailure(message: String?, throwable: String?) { + context.shortToast(translation.format("download_failed_toast", "message" to message.toString())) + } + } + ).enqueue( + DownloadRequest( + inputMedias = arrayOf(attachment.createInputMedia()!!) + ), + DownloadMetadata( + mediaIdentifier = attachmentHash, + outputPath = createNewFilePath( + context.config.root, + attachment.mediaUniqueId!!, + MediaDownloadSource.MESSAGE_LOGGER, + attachmentHash, + creationTimestamp + ), + iconUrl = null, + mediaAuthor = null, + downloadSource = MediaDownloadSource.MESSAGE_LOGGER.translate(context.translation), + ) + ) + } + + @OptIn(ExperimentalLayoutApi::class) + @Composable + private fun MessageView(message: LoggedMessage) { + var contentView by remember { mutableStateOf<@Composable () -> Unit>({ + Spacer(modifier = Modifier.height(30.dp)) + }) } + + Surface( + modifier = Modifier + .padding(vertical = 4.dp) + .fillMaxWidth(), + shape = RoundedCornerShape(18.dp), + color = PurrfectPalette.cardOverlayColor, + tonalElevation = 0.dp, + shadowElevation = 12.dp, + border = BorderStroke( + 1.dp, + Brush.linearGradient( + listOf( + PurrfectPalette.glowPrimary.copy(alpha = 0.45f), + PurrfectPalette.glowSecondary.copy(alpha = 0.35f) + ) + ) + ) + ) { + Row( + modifier = Modifier + .padding(12.dp) + .fillMaxWidth(), + verticalAlignment = Alignment.CenterVertically + ) { + contentView() + + LaunchedEffect(Unit, message) { + runCatching { + decodeMessage(message) { contentType, messageReader, attachments -> + @Composable + fun ContentHeader() { + val date = remember { DateFormat.getDateTimeInstance().format(message.sendTimestamp) } + Text( + translation.format("log_header_format", "username" to message.username, "type" to contentType.toString().lowercase(), "date" to date), + modifier = Modifier.padding(end = 4.dp), + fontWeight = FontWeight.ExtraLight, + color = PurrfectPalette.textSecondary + ) + } + + if (contentType == ContentType.CHAT) { + val content = messageReader.getString(2, 1) ?: "[${translation["empty_message"]}]" + contentView = { + Column { + Text( + content, + modifier = Modifier + .fillMaxWidth() + .pointerInput(Unit) { + detectTapGestures(onLongPress = { + context.androidContext.copyToClipboard(content) + }) + }, + color = Color.White + ) + + val edits by rememberAsyncMutableState(defaultValue = emptyList()) { + loggerWrapper.getChatEdits(selectedConversation!!, message.messageId) + } + edits.forEach { messageEdit -> + val date = remember { + DateFormat.getDateTimeInstance().format(messageEdit.timestamp) + } + Text( + modifier = Modifier.pointerInput(Unit) { + detectTapGestures(onLongPress = { + context.androidContext.copyToClipboard(messageEdit.message) + }) + }.fillMaxWidth().padding(start = 4.dp), + text = translation.format("edited_at_text", "message" to messageEdit.message, "date" to date), + fontWeight = FontWeight.Light, + fontStyle = FontStyle.Italic, + fontSize = 12.sp, + color = PurrfectPalette.textSecondary + ) + } + ContentHeader() + } + } + return@runCatching + } + contentView = { + Column column@{ + if (attachments.isEmpty()) return@column + + FlowRow( + modifier = Modifier + .fillMaxWidth() + .padding(2.dp), + horizontalArrangement = Arrangement.spacedBy(4.dp), + ) { + attachments.forEachIndexed { index, attachment -> + Button( + onClick = { + context.coroutineScope.launch { + runCatching { + downloadAttachment(message.sendTimestamp, attachment) + }.onFailure { + context.log.error("Failed to download attachment", it) + context.shortToast(translation["download_attachment_failed_toast"]) + } + } + }, + colors = ButtonDefaults.buttonColors( + containerColor = PurrfectPalette.glowPrimary.copy(alpha = 0.28f), + contentColor = Color.White + ) + ) { + Icon( + imageVector = Icons.Default.Download, + contentDescription = translation["download_button"], + modifier = Modifier.padding(end = 4.dp) + ) + Text(translation.format("chat_attachment", "index" to (index + 1).toString())) + } + } + } + ContentHeader() + } + } + } + }.onFailure { + context.log.error("Failed to parse message", it) + contentView = { + Text(translation["message_parse_failed"]) + } + } + } + } + } + } + + + @OptIn(ExperimentalMaterial3Api::class) + override val content: @Composable (NavBackStackEntry) -> Unit = { navBackStackEntry -> + LaunchedEffect(Unit) { + val uri = navBackStackEntry.arguments?.getString("uri")?.let { + runCatching { + URLDecoder.decode(it, "UTF-8").toUri() + }.getOrNull() + } + loggerWrapper = LoggerWrapper(context.androidContext, uri) + } + + val conversationInfoCache = remember { ConcurrentHashMap() } + + Box( + modifier = Modifier + .fillMaxSize() + .background(PurrfectPalette.backgroundGradient) + ) { + Column(modifier = Modifier.fillMaxSize()) { + FloatingTopBar( + title = context.translation["manager.routes.logger_history"] ?: "Logger History", + onBack = { routes.navController.popBackStack() } + ) + + Column(modifier = Modifier.fillMaxSize().padding(horizontal = 12.dp)) { + var expanded by remember { mutableStateOf(false) } + + Surface( + modifier = Modifier + .fillMaxWidth() + .padding(top = 4.dp, bottom = 10.dp), + shape = RoundedCornerShape(22.dp), + color = PurrfectPalette.cardOverlayColor, + tonalElevation = 0.dp, + shadowElevation = 10.dp, + border = BorderStroke(1.dp, Color.White.copy(alpha = 0.12f)) + ) { + Column( + modifier = Modifier + .background(PurrfectPalette.cardOverlay, RoundedCornerShape(22.dp)) + .padding(horizontal = 14.dp, vertical = 12.dp), + verticalArrangement = Arrangement.spacedBy(10.dp) + ) { + ExposedDropdownMenuBox( + expanded = expanded, + onExpandedChange = { expanded = it }, + ) { + fun formatConversationInfo(conversationInfo: ConversationInfo?): String? { + if (conversationInfo == null) return null + + return conversationInfo.groupTitle?.let { + translation.format("list_group_format", "name" to it) + } ?: conversationInfo.usernames.takeIf { it.size > 1 }?.let { + translation.format("list_friend_format", "name" to ("(" + it.joinToString(", ") + ")")) + } ?: context.database.findFriend(conversationInfo.conversationId)?.let { + translation.format("list_friend_format", "name" to "(" + (conversationInfo.usernames + listOf(it.mutableUsername)).toSet().joinToString(", ") + ")") + } ?: conversationInfo.usernames.firstOrNull()?.let { + translation.format("list_friend_format", "name" to "($it)") + } + } + + val selectedConversationInfo by rememberAsyncMutableState(defaultValue = null, keys = arrayOf(selectedConversation)) { + selectedConversation?.let { + conversationInfoCache.getOrPut(it) { + formatConversationInfo(loggerWrapper.getConversationInfo(it)) + } + } + } + + OutlinedTextField( + value = selectedConversationInfo ?: translation["select_conversation_placeholder"], + onValueChange = {}, + readOnly = true, + modifier = Modifier + .menuAnchor(MenuAnchorType.PrimaryNotEditable) + .fillMaxWidth(), + colors = TextFieldDefaults.colors( + focusedIndicatorColor = Color.Transparent, + unfocusedIndicatorColor = Color.Transparent, + focusedContainerColor = Color.White.copy(alpha = 0.08f), + unfocusedContainerColor = Color.White.copy(alpha = 0.06f), + focusedTextColor = Color.White, + unfocusedTextColor = Color.White, + cursorColor = PurrfectPalette.glowSecondary + ) + ) + + val conversations by rememberAsyncMutableState(defaultValue = emptyList()) { + loggerWrapper.getAllConversations().toMutableList() + } + + ExposedDropdownMenu(expanded = expanded, onDismissRequest = { expanded = false }) { + conversations.forEach { conversationId -> + DropdownMenuItem(onClick = { + selectedConversation = conversationId + expanded = false + }, text = { + val conversationInfo by rememberAsyncMutableState(defaultValue = null, keys = arrayOf(conversationId)) { + conversationInfoCache.getOrPut(conversationId) { + formatConversationInfo(loggerWrapper.getConversationInfo(conversationId)) + } + } + + Text( + text = remember(conversationInfo) { conversationInfo ?: conversationId }, + fontWeight = if (conversationId == selectedConversation) FontWeight.Bold else FontWeight.Normal, + color = Color.White, + overflow = TextOverflow.Ellipsis + ) + }) + } + } + } + + TextField( + value = stringFilter, + onValueChange = { stringFilter = it }, + singleLine = true, + modifier = Modifier.fillMaxWidth(), + placeholder = { + Text( + text = context.translation["manager.dialogs.add_friend.search_hint"] ?: "Search", + color = PurrfectPalette.textSecondary + ) + }, + leadingIcon = { + Icon( + imageVector = Icons.Filled.Search, + contentDescription = null, + tint = PurrfectPalette.textSecondary + ) + }, + trailingIcon = if (stringFilter.isNotBlank()) { + { + IconButton(onClick = { stringFilter = "" }) { + Icon( + imageVector = Icons.Filled.Close, + contentDescription = translation["close_button_description"], + tint = PurrfectPalette.textSecondary + ) + } + } + } else null, + colors = TextFieldDefaults.colors( + focusedIndicatorColor = Color.Transparent, + unfocusedIndicatorColor = Color.Transparent, + focusedContainerColor = Color.White.copy(alpha = 0.08f), + unfocusedContainerColor = Color.White.copy(alpha = 0.06f), + focusedTextColor = Color.White, + unfocusedTextColor = Color.White, + cursorColor = PurrfectPalette.glowSecondary + ) + ) + + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.End, + verticalAlignment = Alignment.CenterVertically + ) { + Text( + translation["reverse_order_checkbox"], + color = PurrfectPalette.textSecondary, + fontSize = 13.sp + ) + Checkbox( + checked = reverseOrder, + onCheckedChange = { reverseOrder = it }, + colors = CheckboxDefaults.colors( + checkedColor = PurrfectPalette.glowPrimary, + checkmarkColor = Color.White, + uncheckedColor = Color.White.copy(alpha = 0.35f) + ) + ) + } + } + } + + var hasReachedEnd by remember(selectedConversation, stringFilter, reverseOrder) { mutableStateOf(false) } + var lastFetchMessageTimestamp by remember(selectedConversation, stringFilter, reverseOrder) { mutableLongStateOf(if (reverseOrder) Long.MAX_VALUE else Long.MIN_VALUE) } + val messages = remember(selectedConversation, stringFilter, reverseOrder) { mutableStateListOf() } + + LazyColumn( + contentPadding = PaddingValues(bottom = routes.bottomPadding) + ) { + items(messages) { message -> + MessageView(message) + } + item { + if (selectedConversation != null) { + if (hasReachedEnd) { + Text(translation["no_more_messages"], modifier = Modifier + .padding(8.dp) + .fillMaxWidth(), textAlign = TextAlign.Center) + } else { + Row( + horizontalArrangement = Arrangement.Center, + modifier = Modifier.fillMaxWidth() + ) { + CircularProgressIndicator( + modifier = Modifier + .height(20.dp) + .padding(8.dp), + color = PurrfectPalette.glowSecondary, + strokeWidth = 2.dp + ) + } + } + } + LaunchedEffect(Unit, selectedConversation, stringFilter, reverseOrder) { + withContext(Dispatchers.IO) { + val newMessages = loggerWrapper.fetchMessages( + selectedConversation ?: return@withContext, + lastFetchMessageTimestamp, + 30, + reverseOrder + ) { messageData -> + if (stringFilter.isEmpty()) return@fetchMessages true + var isMatch = false + decodeMessage(messageData) { contentType, messageReader, _ -> + if (contentType == ContentType.CHAT) { + val content = messageReader.getString(2, 1) ?: return@decodeMessage + isMatch = content.contains(stringFilter, ignoreCase = true) + } + } + isMatch + } + if (newMessages.isEmpty()) { + hasReachedEnd = true + return@withContext + } + lastFetchMessageTimestamp = newMessages.lastOrNull()?.sendTimestamp ?: return@withContext + withContext(Dispatchers.Main) { + messages.addAll(newMessages) + } + } + } + } + } + } + } + } + } +} diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/ManageReposSection.kt b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/ManageReposSection.kt similarity index 93% rename from app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/ManageReposSection.kt rename to app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/ManageReposSection.kt index a094ef56..faeab3b5 100644 --- a/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/ManageReposSection.kt +++ b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/ManageReposSection.kt @@ -1,5 +1,5 @@ @file:OptIn(androidx.compose.foundation.ExperimentalFoundationApi::class) -package me.rhunk.snapenhance.ui.manager.pages +package me.eternal.purrfectsnap.ui.manager.pages import androidx.compose.foundation.layout.* import androidx.compose.foundation.lazy.LazyColumn @@ -23,15 +23,15 @@ import androidx.navigation.NavBackStackEntry import androidx.navigation.compose.currentBackStackEntryAsState import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch -import me.rhunk.snapenhance.common.data.RepositoryIndex -import me.rhunk.snapenhance.common.ui.AsyncUpdateDispatcher -import me.rhunk.snapenhance.common.ui.rememberAsyncMutableStateList -import me.rhunk.snapenhance.common.util.ktx.copyToClipboard -import me.rhunk.snapenhance.common.util.ktx.getUrlFromClipboard -import me.rhunk.snapenhance.storage.addRepo -import me.rhunk.snapenhance.storage.getRepositories -import me.rhunk.snapenhance.storage.removeRepo -import me.rhunk.snapenhance.ui.manager.Routes +import me.eternal.purrfectsnap.common.data.RepositoryIndex +import me.eternal.purrfectsnap.common.ui.AsyncUpdateDispatcher +import me.eternal.purrfectsnap.common.ui.rememberAsyncMutableStateList +import me.eternal.purrfectsnap.common.util.ktx.copyToClipboard +import me.eternal.purrfectsnap.common.util.ktx.getUrlFromClipboard +import me.eternal.purrfectsnap.storage.addRepo +import me.eternal.purrfectsnap.storage.getRepositories +import me.eternal.purrfectsnap.storage.removeRepo +import me.eternal.purrfectsnap.ui.manager.Routes import okhttp3.OkHttpClient class ManageReposSection: Routes.Route() { diff --git a/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/TasksRootSection.kt b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/TasksRootSection.kt new file mode 100644 index 00000000..4008dc60 --- /dev/null +++ b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/TasksRootSection.kt @@ -0,0 +1,1045 @@ +package me.eternal.purrfectsnap.ui.manager.pages + +import android.content.Intent +import android.graphics.drawable.ColorDrawable +import androidx.compose.animation.AnimatedVisibility +import androidx.compose.animation.fadeIn +import androidx.compose.animation.fadeOut +import androidx.compose.animation.scaleIn +import androidx.compose.animation.scaleOut +import androidx.compose.animation.core.FastOutSlowInEasing +import androidx.compose.animation.core.LinearEasing +import androidx.compose.animation.core.animateFloat +import androidx.compose.animation.core.infiniteRepeatable +import androidx.compose.animation.core.rememberInfiniteTransition +import androidx.compose.animation.core.tween +import androidx.compose.foundation.BorderStroke +import androidx.compose.foundation.background +import androidx.compose.foundation.Image +import androidx.compose.foundation.border +import androidx.compose.foundation.clickable +import androidx.compose.foundation.gestures.detectTapGestures +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items +import androidx.compose.foundation.lazy.rememberLazyListState +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.* +import androidx.compose.material3.* +import androidx.compose.runtime.* +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.draw.clipToBounds +import androidx.compose.ui.draw.rotate +import androidx.compose.ui.graphics.Brush +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.StrokeCap +import androidx.compose.ui.graphics.SolidColor +import androidx.compose.ui.graphics.toArgb +import androidx.compose.ui.input.pointer.pointerInput +import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import androidx.compose.ui.window.Dialog +import androidx.core.net.toUri +import androidx.documentfile.provider.DocumentFile +import androidx.lifecycle.Lifecycle +import androidx.navigation.NavBackStackEntry +import coil.compose.rememberAsyncImagePainter +import coil.request.ImageRequest +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import me.eternal.purrfectsnap.bridge.DownloadCallback +import me.eternal.purrfectsnap.common.data.download.DownloadMetadata +import me.eternal.purrfectsnap.common.data.download.MediaDownloadSource +import me.eternal.purrfectsnap.common.data.download.createNewFilePath +import me.eternal.purrfectsnap.common.ui.TopBarActionButton +import me.eternal.purrfectsnap.common.ui.rememberAsyncMutableState +import me.eternal.purrfectsnap.common.util.ktx.longHashCode +import me.eternal.purrfectsnap.download.DownloadProcessor +import me.eternal.purrfectsnap.download.FFMpegProcessor +import me.eternal.purrfectsnap.task.* +import me.eternal.purrfectsnap.ui.manager.Routes +import me.eternal.purrfectsnap.ui.manager.theme.PurrfectPalette +import me.eternal.purrfectsnap.ui.util.OnLifecycleEvent +import me.eternal.purrfectsnap.ui.util.coil.cacheKey +import java.io.File +import java.util.UUID +import kotlin.math.absoluteValue +import kotlin.text.Regex + +class TasksRootSection : Routes.Route() { + private var activeTasks by mutableStateOf(listOf()) + private lateinit var recentTasks: MutableList + private val taskSelection = mutableStateListOf>() + + private fun fetchActiveTasks(scope: CoroutineScope = context.coroutineScope) { + scope.launch(Dispatchers.IO) { + activeTasks = context.taskManager.getActiveTasks().values.sortedByDescending { it.taskId }.toMutableList() + } + } + + private fun mergeSelection(selection: List>) { + val firstTask = selection.first().first + + val taskHash = UUID.randomUUID().toString().longHashCode().absoluteValue.toString(16) + val pendingTask = context.taskManager.createPendingTask( + Task(TaskType.DOWNLOAD, "Merge ${selection.size} files", firstTask.author, taskHash) + ) + pendingTask.status = TaskStatus.RUNNING + fetchActiveTasks() + + context.coroutineScope.launch { + val filesToMerge = mutableListOf() + + selection.forEach { (task, documentFile) -> + val tempFile = File.createTempFile(task.hash, "." + documentFile.name?.substringAfterLast("."), context.androidContext.cacheDir).also { + it.deleteOnExit() + } + + runCatching { + pendingTask.updateProgress("Copying ${documentFile.name}") + context.androidContext.contentResolver.openInputStream(documentFile.uri)?.use { inputStream -> + //copy with progress + val length = documentFile.length().toFloat() + tempFile.outputStream().use { outputStream -> + val buffer = ByteArray(16 * 1024) + var read: Int + while (inputStream.read(buffer).also { read = it } != -1) { + outputStream.write(buffer, 0, read) + pendingTask.updateProgress("Copying ${documentFile.name}", (outputStream.channel.position().toFloat() / length * 100f).toInt()) + } + outputStream.flush() + filesToMerge.add(tempFile) + } + } + }.onFailure { + pendingTask.fail("Failed to copy file $documentFile to $tempFile") + filesToMerge.forEach { it.delete() } + return@launch + } + } + + val mergedFile = File.createTempFile("merged", ".mp4", context.androidContext.cacheDir).also { + it.deleteOnExit() + } + + runCatching { + context.shortToast(translation.format("merge_files_toast", "count" to filesToMerge.size.toString())) + FFMpegProcessor.newFFMpegProcessor(context, pendingTask).execute( + FFMpegProcessor.Request(FFMpegProcessor.Action.MERGE_MEDIA, filesToMerge.map { it.absolutePath }, mergedFile) + ) + DownloadProcessor(context, object: DownloadCallback.Default() { + override fun onSuccess(outputPath: String) { + context.log.verbose("Merged files to $outputPath") + } + }).saveMediaToGallery(pendingTask, mergedFile, DownloadMetadata( + mediaIdentifier = taskHash, + outputPath = createNewFilePath( + context.config.root, + taskHash, + downloadSource = MediaDownloadSource.MERGED, + mediaAuthor = firstTask.author, + creationTimestamp = System.currentTimeMillis() + ), + mediaAuthor = firstTask.author, + downloadSource = MediaDownloadSource.MERGED.translate(context.translation), + iconUrl = null + )) + }.onFailure { + context.log.error("Failed to merge files", it) + pendingTask.fail(it.message ?: "Failed to merge files") + }.onSuccess { + pendingTask.success() + } + filesToMerge.forEach { it.delete() } + mergedFile.delete() + }.also { + pendingTask.addListener(PendingTaskListener(onCancel = { it.cancel() })) + } + } + + private fun clearTasks(alsoDeleteFiles: Boolean, scope: CoroutineScope) { + if (taskSelection.isNotEmpty()) { + taskSelection.forEach { (task, documentFile) -> + scope.launch(Dispatchers.IO) { + context.taskManager.removeTask(task) + if (alsoDeleteFiles) documentFile?.delete() + } + recentTasks.remove(task) + } + activeTasks = activeTasks.filter { task -> !taskSelection.map { it.first }.contains(task.task) } + taskSelection.clear() + } else { + scope.launch(Dispatchers.IO) { context.taskManager.clearAllTasks() } + recentTasks.clear() + activeTasks.forEach { + runCatching { it.cancel() }.onFailure { throwable -> + context.log.error("Failed to cancel task $it", throwable) + } + } + activeTasks = listOf() + context.taskManager.getActiveTasks().clear() + } + } + + @Composable + private fun TaskDangerDialog( + visible: Boolean, + title: String, + message: String, + showDeleteFiles: Boolean, + deleteFilesChecked: Boolean, + onToggleDeleteFiles: (Boolean) -> Unit, + onConfirm: () -> Unit, + onDismiss: () -> Unit + ) { + if (!visible) return + + val dialogShape = RoundedCornerShape(24.dp) + val borderGradient = remember { + Brush.linearGradient( + listOf( + PurrfectPalette.glowPrimary.copy(alpha = 0.65f), + PurrfectPalette.glowSecondary.copy(alpha = 0.55f) + ) + ) + } + + Dialog(onDismissRequest = onDismiss) { + Surface( + shape = dialogShape, + color = Color.White.copy(alpha = 0.06f), + tonalElevation = 0.dp, + shadowElevation = 20.dp, + border = BorderStroke(1.dp, borderGradient) + ) { + Box( + modifier = Modifier + .background(PurrfectPalette.cardOverlay, dialogShape) + ) { + Column( + modifier = Modifier + .padding(horizontal = 20.dp, vertical = 18.dp), + verticalArrangement = Arrangement.spacedBy(14.dp) + ) { + Row( + horizontalArrangement = Arrangement.spacedBy(12.dp), + verticalAlignment = Alignment.CenterVertically + ) { + Surface( + shape = CircleShape, + color = Color.White.copy(alpha = 0.08f), + tonalElevation = 0.dp, + shadowElevation = 0.dp, + border = BorderStroke(1.dp, Color.White.copy(alpha = 0.12f)) + ) { + Box( + modifier = Modifier + .size(56.dp) + .background( + Brush.linearGradient( + listOf( + PurrfectPalette.glowPrimary.copy(alpha = 0.38f), + PurrfectPalette.glowSecondary.copy(alpha = 0.32f) + ) + ), + CircleShape + ), + contentAlignment = Alignment.Center + ) { + Icon( + Icons.Filled.DeleteOutline, + contentDescription = null, + tint = Color.White + ) + } + } + Column(verticalArrangement = Arrangement.spacedBy(4.dp)) { + Text( + text = title, + style = MaterialTheme.typography.titleLarge.copy(fontWeight = FontWeight.ExtraBold), + color = Color.White + ) + Text( + text = message, + style = MaterialTheme.typography.bodyMedium, + color = PurrfectPalette.textSecondary + ) + } + } + + if (showDeleteFiles) { + Surface( + shape = RoundedCornerShape(18.dp), + color = Color.White.copy(alpha = 0.04f), + tonalElevation = 0.dp, + shadowElevation = 0.dp, + border = BorderStroke(1.dp, Color.White.copy(alpha = 0.08f)) + ) { + Row( + modifier = Modifier + .fillMaxWidth() + .clickable { onToggleDeleteFiles(!deleteFilesChecked) } + .padding(horizontal = 12.dp, vertical = 10.dp), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(10.dp) + ) { + Checkbox( + checked = deleteFilesChecked, + onCheckedChange = { onToggleDeleteFiles(it) }, + colors = CheckboxDefaults.colors( + checkedColor = PurrfectPalette.glowPrimary, + uncheckedColor = Color.White, + checkmarkColor = Color.Black + ) + ) + Column { + Text( + text = context.translation["delete_files_option"], + color = Color.White, + fontWeight = FontWeight.SemiBold + ) + Text( + text = context.translation["delete_files_option_hint"] ?: "Also remove downloaded files", + color = PurrfectPalette.textSecondary, + style = MaterialTheme.typography.bodySmall + ) + } + } + } + } + + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.spacedBy(10.dp, Alignment.End) + ) { + Button( + onClick = onDismiss, + colors = ButtonDefaults.buttonColors( + containerColor = Color.White.copy(alpha = 0.08f), + contentColor = Color.White + ) + ) { + Text(context.translation["button.negative"]) + } + Button( + onClick = onConfirm, + colors = ButtonDefaults.buttonColors( + containerColor = PurrfectPalette.glowPrimary.copy(alpha = 0.34f), + contentColor = Color.White + ) + ) { + Text(context.translation["button.positive"]) + } + } + } + } + } + } + } + + @Composable + private fun TasksEmptyState(text: String) { + Column( + modifier = Modifier + .fillMaxWidth() + .padding(top = 60.dp), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.spacedBy(12.dp) + ) { + Surface( + shape = CircleShape, + color = Color.White.copy(alpha = 0.08f), + tonalElevation = 0.dp, + shadowElevation = 0.dp, + border = BorderStroke(1.dp, Color.White.copy(alpha = 0.12f)) + ) { + Box( + modifier = Modifier + .size(58.dp) + .background( + Brush.linearGradient( + listOf( + PurrfectPalette.glowPrimary.copy(alpha = 0.32f), + PurrfectPalette.glowSecondary.copy(alpha = 0.28f) + ) + ), + CircleShape + ), + contentAlignment = Alignment.Center + ) { + Icon( + Icons.Filled.CheckCircle, + contentDescription = text, + tint = Color.White + ) + } + } + Text( + text = text, + style = MaterialTheme.typography.titleMedium.copy(fontWeight = FontWeight.ExtraBold), + color = Color.White + ) + } + } + + override val topBarActions: @Composable (RowScope.() -> Unit) = { + var showConfirmDialog by remember { mutableStateOf(false) } + val coroutineScope = rememberCoroutineScope() + + if (taskSelection.size > 1) { + val canMergeSelection by rememberAsyncMutableState(defaultValue = false, keys = arrayOf(taskSelection.size)) { + taskSelection.all { it.second?.type?.contains("video") == true } + } + + if (canMergeSelection) { + TopBarActionButton( + onClick = { + mergeSelection(taskSelection.toList().also { + taskSelection.clear() + }.map { it.first to it.second!! }) + }, + icon = Icons.Filled.Merge, + text = translation["merge_button"] + ) + } + } + + IconButton(onClick = { + showConfirmDialog = true + }) { + Icon(Icons.Filled.Delete, contentDescription = "Clear tasks") + } + + if (showConfirmDialog) { + var alsoDeleteFiles by remember { mutableStateOf(false) } + val isSelection = taskSelection.isNotEmpty() + val titleText = if (isSelection) { + translation.format("remove_selected_tasks_confirm", "count" to taskSelection.size.toString()) + } else { + translation["remove_all_tasks_confirm"] + } + val messageText = if (isSelection) translation["remove_selected_tasks_title"] else translation["remove_all_tasks_title"] + + TaskDangerDialog( + visible = showConfirmDialog, + title = titleText, + message = messageText, + showDeleteFiles = isSelection, + deleteFilesChecked = alsoDeleteFiles, + onToggleDeleteFiles = { alsoDeleteFiles = it }, + onConfirm = { + showConfirmDialog = false + clearTasks(alsoDeleteFiles, coroutineScope) + }, + onDismiss = { showConfirmDialog = false } + ) + } + } + + @Composable + private fun TaskCard(modifier: Modifier, task: Task, pendingTask: PendingTask? = null) { + var taskStatus by remember { mutableStateOf(task.status) } + var taskProgressLabel by remember { mutableStateOf(null) } + var taskProgress by remember { mutableIntStateOf(-1) } + val isSelected by remember { derivedStateOf { taskSelection.any { it.first == task } } } + + var documentFileMimeType by remember { mutableStateOf("") } + var isDocumentFileReadable by remember { mutableStateOf(true) } + val documentFile by rememberAsyncMutableState(defaultValue = null, keys = arrayOf(taskStatus.key)) { + DocumentFile.fromSingleUri(context.androidContext, task.extra?.toUri() ?: return@rememberAsyncMutableState null)?.apply { + documentFileMimeType = type ?: "" + isDocumentFileReadable = canRead() + } + } + + + val listener = remember { PendingTaskListener( + onStateChange = { + taskStatus = it + }, + onProgress = { label, progress -> + taskProgressLabel = label + taskProgress = progress + } + ) } + + LaunchedEffect(Unit) { + pendingTask?.addListener(listener) + } + + DisposableEffect(Unit) { + onDispose { + pendingTask?.removeListener(listener) + } + } + + fun toggleSelection() { + if (isSelected) { + taskSelection.removeIf { it.first == task } + return + } + taskSelection.add(task to documentFile) + } + + fun openFile() { + if (!isDocumentFileReadable || documentFile == null) return + runCatching { + context.androidContext.startActivity(Intent(Intent.ACTION_VIEW).apply { + setDataAndType(documentFile!!.uri, documentFile!!.type) + flags = Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_ACTIVITY_NEW_TASK + }) + }.onFailure { + context.log.error("Failed to open file ${documentFile?.uri}", it) + context.shortToast(translation["failed_to_open_file"]) + } + } + + val isActive = pendingTask != null && !taskStatus.isFinalStage() + val cardModifier = modifier + .pointerInput(Unit) { + detectTapGestures( + onTap = { + if (taskSelection.isNotEmpty()) { + toggleSelection() + return@detectTapGestures + } + openFile() + }, + onLongPress = { + if (taskSelection.isNotEmpty()) { + openFile() + return@detectTapGestures + } + toggleSelection() + } + ) + } + .let { + if (isSelected) { + it + .border(2.dp, PurrfectPalette.glowSecondary, MaterialTheme.shapes.large) + .clip(MaterialTheme.shapes.large) + } else it + } + + val chipLabel = when { + isActive -> translation.getOrNull("task_sending") ?: "Sending" + taskStatus == TaskStatus.SUCCESS -> null + taskStatus == TaskStatus.FAILURE -> translation.getOrNull("task_failed") ?: "Failed" + taskStatus == TaskStatus.CANCELLED -> translation.getOrNull("task_cancelled") ?: "Cancelled" + else -> taskStatus.name.lowercase().replaceFirstChar { it.titlecase() } + } + val chipIcon = when { + isActive -> null + taskStatus == TaskStatus.SUCCESS -> Icons.Filled.Check + taskStatus == TaskStatus.FAILURE -> Icons.Filled.WarningAmber + taskStatus == TaskStatus.CANCELLED -> Icons.Filled.Cancel + else -> Icons.Filled.Info + } + val chipColors = when { + isActive -> AssistChipDefaults.assistChipColors( + containerColor = Color.White.copy(alpha = 0.08f), + labelColor = Color.White + ) + taskStatus == TaskStatus.SUCCESS -> AssistChipDefaults.assistChipColors() + taskStatus == TaskStatus.FAILURE -> AssistChipDefaults.assistChipColors( + containerColor = Color(0xFFFF6B9B).copy(alpha = 0.18f), + labelColor = Color.White + ) + taskStatus == TaskStatus.CANCELLED -> AssistChipDefaults.assistChipColors( + containerColor = Color.White.copy(alpha = 0.06f), + labelColor = PurrfectPalette.textSecondary + ) + else -> AssistChipDefaults.assistChipColors() + } + val countdownText = if (isActive) { + taskProgressLabel?.let { label -> + Regex("""(\d+d\s+)?(\d+h\s+)?(\d+m\s+)?\d+s""").find(label)?.value?.trim() ?: label + } + } else null + + val cardShape = RoundedCornerShape(22.dp) + Surface( + modifier = cardModifier, + shape = cardShape, + color = Color.Transparent, + tonalElevation = 0.dp, + shadowElevation = if (isSelected) 12.dp else 6.dp, + border = BorderStroke( + 1.dp, + if (isSelected) Brush.linearGradient(listOf(PurrfectPalette.glowPrimary, PurrfectPalette.glowSecondary)) + else SolidColor(Color.White.copy(alpha = 0.1f)) + ) + ) { + Row( + modifier = Modifier + .background(PurrfectPalette.cardOverlay, cardShape) + .padding(12.dp), + verticalAlignment = Alignment.CenterVertically + ) { + Box( + modifier = Modifier + .padding(end = 15.dp) + .size(50.dp) + .clipToBounds(), + contentAlignment = Alignment.Center + ) { + var loadFailed by remember { mutableStateOf(false) } + documentFile?.let { + if (taskStatus.isFinalStage() && isDocumentFileReadable && !loadFailed && (documentFileMimeType.contains("image") || documentFileMimeType.contains("video"))) { + Image( + painter = rememberAsyncImagePainter( + model = ImageRequest.Builder(context.androidContext) + .data(it.uri) + .cacheKey(it.uri.toString()) + .placeholder(ColorDrawable(PurrfectPalette.cardOverlayColor.toArgb())) + .build(), + imageLoader = context.imageLoader, + onError = { loadFailed = true } + ), + contentDescription = null, + contentScale = ContentScale.FillWidth, + modifier = Modifier + .size(50.dp) + .clip(MaterialTheme.shapes.medium) + ) + } else { + when { + !isDocumentFileReadable -> Icon(Icons.Filled.DeleteOutline, contentDescription = "File not found") + documentFileMimeType.contains("image") -> Icon(Icons.Filled.Image, contentDescription = "Image") + documentFileMimeType.contains("video") -> Icon(Icons.Filled.Videocam, contentDescription = "Video") + documentFileMimeType.contains("audio") -> Icon(Icons.Filled.MusicNote, contentDescription = "Audio") + else -> Icon(Icons.Filled.FileCopy, contentDescription = "File") + } + } + } ?: run { + when (task.type) { + TaskType.DOWNLOAD -> Icon(Icons.Filled.Download, contentDescription = "Download") + TaskType.CHAT_ACTION -> Icon(Icons.Filled.ChatBubble, contentDescription = "Chat Action") + TaskType.SCHEDULED_SEND -> { + val isActive = !taskStatus.isFinalStage() + val rotation = if (isActive) { + val transition = rememberInfiniteTransition(label = "scheduled_send") + transition.animateFloat( + initialValue = 0f, + targetValue = 360f, + animationSpec = infiniteRepeatable(animation = tween(1200, easing = LinearEasing)), + label = "rotation" + ).value + } else 0f + Box( + modifier = Modifier + .size(50.dp) + .clip(CircleShape) + .background( + if (isActive) { + Brush.linearGradient( + colors = listOf( + PurrfectPalette.glowPrimary.copy(alpha = 0.25f), + PurrfectPalette.glowSecondary.copy(alpha = 0.22f) + ) + ) + } else { + Brush.linearGradient( + colors = listOf( + Color.White.copy(alpha = 0.06f), + Color.White.copy(alpha = 0.06f) + ) + ) + } + ), + contentAlignment = Alignment.Center + ) { + Icon( + Icons.Filled.Schedule, + contentDescription = "Scheduled Send", + modifier = Modifier + .size(28.dp) + .rotate(rotation), + tint = if (isActive) PurrfectPalette.glowSecondary else PurrfectPalette.textSecondary + ) + } + } + } + } + } + Column( + modifier = Modifier.weight(1f), + ) { + if (task.type == TaskType.SCHEDULED_SEND) { + // Professional design for scheduled send tasks + Column( + verticalArrangement = Arrangement.spacedBy(6.dp) + ) { + // Feature title + Text( + context.translation.getOrNull("scheduled_send_title") ?: "Scheduled Snaps", + style = MaterialTheme.typography.labelMedium, + color = PurrfectPalette.textSecondary, + fontWeight = androidx.compose.ui.text.font.FontWeight.Medium + ) + + // Scheduled time without icon + Text( + task.title, + style = MaterialTheme.typography.titleMedium, + fontWeight = androidx.compose.ui.text.font.FontWeight.SemiBold, + color = Color.White + ) + + // Recipients with icon + task.author?.takeIf { it != "null" }?.let { recipients -> + Row( + verticalAlignment = Alignment.Top, + horizontalArrangement = Arrangement.spacedBy(6.dp) + ) { + Icon( + Icons.Filled.People, + contentDescription = null, + modifier = Modifier.size(16.dp).padding(top = 2.dp), + tint = PurrfectPalette.textSecondary + ) + Text( + recipients, + style = MaterialTheme.typography.bodyMedium, + color = Color.White, + lineHeight = 20.sp + ) + } + } + } + } else { + Row( + modifier = Modifier.fillMaxWidth(), + verticalAlignment = Alignment.CenterVertically + ) { + Text(task.title, style = MaterialTheme.typography.bodyMedium, color = Color.White) + task.author?.takeIf { it != "null" }?.let { + Spacer(modifier = Modifier.width(5.dp)) + Text(it, style = MaterialTheme.typography.bodySmall, color = PurrfectPalette.textSecondary) + } + } + Text(task.hash, style = MaterialTheme.typography.labelSmall, color = PurrfectPalette.textSecondary) + } + Column( + modifier = Modifier.padding(top = 5.dp), + verticalArrangement = Arrangement.spacedBy(5.dp) + ) { + chipLabel?.let { label -> + val leadingIcon: (@Composable () -> Unit)? = if (isActive && task.type == TaskType.SCHEDULED_SEND) { + { + Icon( + Icons.Filled.Timer, + contentDescription = null, + modifier = Modifier.size(16.dp) + ) + } + } else if (isActive) { + countdownText?.let { countdown -> + { + Text( + countdown, + style = MaterialTheme.typography.labelSmall + ) + } + } + } else chipIcon?.let { icon -> + { Icon(icon, contentDescription = null) } + } + val displayLabel = if (isActive && task.type == TaskType.SCHEDULED_SEND && countdownText != null) { + val sendingText = translation.getOrNull("schedule_sending_in")?.replace("{time}", countdownText) ?: "Sending in $countdownText" + sendingText + } else { + label + } + AssistChip( + onClick = {}, + enabled = false, + leadingIcon = leadingIcon, + label = { Text(displayLabel) }, + colors = chipColors + ) + } + if (taskStatus.isFinalStage()) { + if (taskStatus != TaskStatus.SUCCESS) { + Text("$taskStatus", style = MaterialTheme.typography.bodySmall, color = PurrfectPalette.textSecondary) + } + } else { + if (!isActive) { + taskProgressLabel?.let { + Text(it, style = MaterialTheme.typography.bodySmall, color = Color.White) + } + } + if (taskProgress != -1 && taskProgressLabel == null) { + LinearProgressIndicator( + progress = { taskProgress.toFloat() / 100f }, + strokeCap = StrokeCap.Round, + modifier = Modifier.fillMaxWidth(), + color = PurrfectPalette.glowSecondary, + trackColor = Color.White.copy(alpha = 0.12f) + ) + } + if (!isActive) { + task.extra?.takeIf { it?.isNotEmpty() == true }?.let { + Text(it, style = MaterialTheme.typography.bodySmall, color = PurrfectPalette.textSecondary) + } + } + } + } + } + + Column { + if (pendingTask != null && !taskStatus.isFinalStage()) { + FilledIconButton( + onClick = { + runCatching { + pendingTask.cancel() + }.onFailure { throwable -> + context.log.error("Failed to cancel task $pendingTask", throwable) + } + }, + colors = IconButtonDefaults.filledIconButtonColors( + containerColor = Color(0xFFFF6B9B).copy(alpha = 0.35f), + contentColor = Color.White + ) + ) { + Icon(Icons.Filled.Close, contentDescription = "Cancel") + } + } else { + if (taskStatus == TaskStatus.SUCCESS) { + AnimatedVisibility( + visible = true, + enter = fadeIn(animationSpec = tween(250, easing = FastOutSlowInEasing)) + scaleIn(animationSpec = tween(300, easing = FastOutSlowInEasing)), + exit = fadeOut(animationSpec = tween(150)) + scaleOut(targetScale = 0.5f, animationSpec = tween(150)) + ) { + Box( + modifier = Modifier + .size(40.dp) + .clip(CircleShape) + .background(PurrfectPalette.glowPrimary.copy(alpha = 0.22f)), + contentAlignment = Alignment.Center + ) { + Icon(Icons.Filled.Check, contentDescription = "Success", tint = Color.White) + } + } + } else { + when (taskStatus) { + TaskStatus.FAILURE -> Icon(Icons.Filled.Error, contentDescription = "Failure", tint = Color(0xFFFF6B9B)) + TaskStatus.CANCELLED -> Icon(Icons.Filled.Cancel, contentDescription = "Cancelled", tint = Color(0xFFFF6B9B)) + else -> {} + } + } + } + } + } + } + } + + override val content: @Composable (NavBackStackEntry) -> Unit = { + val scrollState = rememberLazyListState() + val scope = rememberCoroutineScope() + recentTasks = remember { mutableStateListOf() } + var lastFetchedTaskId by remember { mutableStateOf(null as Long?) } + var showConfirmDialog by remember { mutableStateOf(false) } + var alsoDeleteFiles by remember { mutableStateOf(false) } + + fun fetchNewRecentTasks() { + scope.launch(Dispatchers.IO) { + val tasks = context.taskManager.fetchStoredTasks(lastFetchedTaskId ?: Long.MAX_VALUE, limit = 20) + if (tasks.isNotEmpty()) { + lastFetchedTaskId = tasks.keys.last() + val activeTaskIds = activeTasks.map { it.taskId } + recentTasks.addAll(tasks.filter { it.key !in activeTaskIds }.values) + } + } + } + + LaunchedEffect(Unit) { + fetchActiveTasks(this) + } + + DisposableEffect(Unit) { + onDispose { + taskSelection.clear() + } + } + + OnLifecycleEvent { _, event -> + if (event == Lifecycle.Event.ON_RESUME) { + fetchActiveTasks(scope) + } + } + + Box( + modifier = Modifier + .fillMaxSize() + .background(PurrfectPalette.backgroundGradient) + ) { + Column(modifier = Modifier.fillMaxSize()) { + Surface( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 14.dp, vertical = 12.dp) + .padding(top = WindowInsets.statusBars.asPaddingValues().calculateTopPadding()), + shape = RoundedCornerShape(26.dp), + color = Color.White.copy(alpha = 0.07f), + tonalElevation = 0.dp, + shadowElevation = 0.dp, + border = BorderStroke( + 1.dp, + Brush.linearGradient( + listOf( + PurrfectPalette.glowPrimary.copy(alpha = 0.55f), + PurrfectPalette.glowSecondary.copy(alpha = 0.35f) + ) + ) + ) + ) { + Row( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 16.dp, vertical = 14.dp), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.SpaceBetween + ) { + Column(verticalArrangement = Arrangement.spacedBy(6.dp)) { + Text( + text = context.translation["manager.routes.tasks"], + color = Color.White, + fontWeight = FontWeight.ExtraBold, + fontSize = 18.sp + ) + Text( + text = if (activeTasks.isNotEmpty()) "${activeTasks.size} active · ${recentTasks.size} recent" else "Idle · ${recentTasks.size} recent", + color = PurrfectPalette.textSecondary, + fontSize = 12.sp + ) + } + Row( + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(8.dp) + ) { + if (taskSelection.size > 1 && taskSelection.all { it.second?.type?.contains("video") == true }) { + Surface( + onClick = { + mergeSelection( + taskSelection.toList().also { taskSelection.clear() } + .map { it.first to it.second!! } + ) + }, + shape = RoundedCornerShape(18.dp), + color = Color.White.copy(alpha = 0.08f), + tonalElevation = 0.dp, + shadowElevation = 0.dp, + border = BorderStroke( + 1.dp, + Brush.linearGradient(listOf(PurrfectPalette.glowPrimary, PurrfectPalette.glowSecondary)) + ) + ) { + Row( + modifier = Modifier.padding(horizontal = 12.dp, vertical = 8.dp), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(8.dp) + ) { + Icon(Icons.Filled.Merge, contentDescription = translation["merge_button"], tint = Color.White) + Text(translation["merge_button"], color = Color.White, fontWeight = FontWeight.SemiBold, fontSize = 12.sp) + } + } + } + Surface( + shape = RoundedCornerShape(18.dp), + color = Color.White.copy(alpha = 0.08f), + border = BorderStroke(1.dp, Color.White.copy(alpha = 0.16f)) + ) { + Row( + modifier = Modifier.padding(horizontal = 12.dp, vertical = 8.dp), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(8.dp) + ) { + Icon(Icons.Filled.PlaylistAddCheckCircle, contentDescription = null, tint = Color.White) + Text(text = "${activeTasks.size} running", color = Color.White, fontWeight = FontWeight.SemiBold, fontSize = 12.sp) + } + } + IconButton(onClick = { showConfirmDialog = true }) { + Icon(Icons.Filled.Delete, contentDescription = "Clear tasks", tint = Color.White) + } + } + } + } + + Surface( + modifier = Modifier + .weight(1f) + .fillMaxWidth() + .padding(horizontal = 12.dp), + shape = RoundedCornerShape(22.dp), + color = Color.White.copy(alpha = 0.04f), + tonalElevation = 0.dp, + shadowElevation = 0.dp, + border = BorderStroke(1.dp, Color.White.copy(alpha = 0.08f)) + ) { + LazyColumn( + state = scrollState, + modifier = Modifier.fillMaxSize(), + contentPadding = PaddingValues( + start = 12.dp, + end = 12.dp, + top = 0.dp, + bottom = routes.bottomPadding + 16.dp + ), + verticalArrangement = Arrangement.spacedBy(16.dp) + ) { + item { + if (activeTasks.isEmpty() && recentTasks.isEmpty()) { + TasksEmptyState(text = translation["no_tasks"]) + } + } + items(activeTasks, key = { it.taskId }) { pendingTask -> + TaskCard(modifier = Modifier.fillMaxWidth(), pendingTask.task, pendingTask = pendingTask) + } + items(recentTasks, key = { it.hash }) { task -> + TaskCard(modifier = Modifier.fillMaxWidth(), task) + } + item { + Spacer(modifier = Modifier.height(40.dp)) + LaunchedEffect(remember { derivedStateOf { scrollState.firstVisibleItemIndex } }) { + fetchNewRecentTasks() + } + } + } + } + } + } + + if (showConfirmDialog) { + val isSelection = taskSelection.isNotEmpty() + val titleText = if (isSelection) { + translation.format("remove_selected_tasks_confirm", "count" to taskSelection.size.toString()) + } else { + translation["remove_all_tasks_confirm"] + } + val messageText = if (isSelection) translation["remove_selected_tasks_title"] else translation["remove_all_tasks_title"] + + TaskDangerDialog( + visible = showConfirmDialog, + title = titleText, + message = messageText, + showDeleteFiles = isSelection, + deleteFilesChecked = alsoDeleteFiles, + onToggleDeleteFiles = { alsoDeleteFiles = it }, + onConfirm = { + showConfirmDialog = false + clearTasks(alsoDeleteFiles, scope) + }, + onDismiss = { showConfirmDialog = false } + ) + } + } +} diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/features/CallbackAlias.kt b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/features/CallbackAlias.kt similarity index 65% rename from app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/features/CallbackAlias.kt rename to app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/features/CallbackAlias.kt index 469d5d1c..c3b789a7 100644 --- a/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/features/CallbackAlias.kt +++ b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/features/CallbackAlias.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.ui.manager.pages.features +package me.eternal.purrfectsnap.ui.manager.pages.features typealias ClickCallback = (Boolean) -> Unit typealias RegisterClickCallback = (ClickCallback) -> ClickCallback \ No newline at end of file diff --git a/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/features/ConfigExportSummaryScreen.kt b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/features/ConfigExportSummaryScreen.kt new file mode 100644 index 00000000..4395c3a0 --- /dev/null +++ b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/features/ConfigExportSummaryScreen.kt @@ -0,0 +1,381 @@ +package me.eternal.purrfectsnap.ui.manager.pages.features + +import androidx.compose.animation.AnimatedVisibility +import androidx.compose.animation.core.animateFloatAsState +import androidx.compose.foundation.BorderStroke +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.statusBarsPadding +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.automirrored.filled.ArrowBack +import androidx.compose.material.icons.filled.ArrowDownward +import androidx.compose.material.icons.filled.KeyboardArrowDown +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Surface +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateMapOf +import androidx.compose.runtime.remember +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Brush +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.graphicsLayer +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import me.eternal.purrfectsnap.ui.manager.Routes +import me.eternal.purrfectsnap.ui.manager.theme.PurrfectPalette +import me.eternal.purrfectsnap.ui.util.saveFile +import org.json.JSONArray +import org.json.JSONObject + +class ConfigExportSummaryScreen : Routes.Route() { + override val translation by lazy { context.translation.getCategory("manager.features.config_export") } + + private data class ImportedFeature( + val category: String, + val name: String, + val key: String, + val value: Any, + val indentation: Int + ) + + private inner class ConfigParser { + fun parse(configJson: String): Map> { + val featureList = mutableListOf() + val json = JSONObject(configJson) + fun parseProperties(categoryKey: String, niceCategoryName: String, properties: JSONObject, prefix: String, indent: Int) { + for (key in properties.keys()) { + val value = properties.get(key) + val currentPrefix = if (prefix.isEmpty()) key else "$prefix.$key" + if (value is JSONObject && value.has("state") && value.has("properties")) { + val featureNameKey = "features.properties.$categoryKey.properties.${currentPrefix.split('.').joinToString(".properties.")}.name" + val featureName = context.translation[featureNameKey] ?: key + featureList.add(ImportedFeature(niceCategoryName, featureName, key, value.getBoolean("state"), indent)) + parseProperties(categoryKey, niceCategoryName, value.getJSONObject("properties"), currentPrefix, indent + 1) + } else if (value is JSONObject && value.has("properties")) { + parseProperties(categoryKey, niceCategoryName, value.getJSONObject("properties"), currentPrefix, indent) + } else { + val featureNameKey = "features.properties.$categoryKey.properties.${currentPrefix.split('.').joinToString(".properties.")}.name" + var featureName = context.translation[featureNameKey] ?: key + if (key == "save_folder") { + featureName = "Save Folder" + } + featureList.add(ImportedFeature(niceCategoryName, featureName, key, value, indent)) + } + } + } + for (categoryKey in json.keys()) { + val value = json.get(categoryKey) + if (value is JSONObject) { + val niceCategoryName = context.translation["features.properties.$categoryKey.name"] ?: categoryKey.replaceFirstChar { it.uppercase() } + if (value.has("state") && !value.has("properties")) { + featureList.add(ImportedFeature(niceCategoryName, translation["enable_feature"], categoryKey, value.getBoolean("state"), 0)) + } else if (value.has("properties")) { + parseProperties(categoryKey, niceCategoryName, value.getJSONObject("properties"), "", 0) + } + } + } + return featureList.groupBy { it.category } + } + + fun parseValue(featureKey: String, value: Any): Any { + fun innerParse(v: Any): String { + if (v is String) { + if (v.isBlank()) { + val emptyKey = "features.options.$featureKey.empty" + val translatedEmpty = context.translation[emptyKey] + val fallback = context.translation["features.options.empty"]?.takeUnless { it == "features.options.empty" } + return if (!translatedEmpty.isNullOrBlank() && translatedEmpty != emptyKey && !translatedEmpty.startsWith("features.")) translatedEmpty else (fallback ?: "Empty") + } + val translationKey = "features.options.$featureKey.$v" + val translated = context.translation[translationKey] + return if (!translated.isNullOrBlank() && translated != translationKey && !translated.startsWith("features.")) translated else v + } + return v.toString() + } + return when (value) { + is Boolean -> if (value) translation["enabled"] else translation["disabled"] + is JSONArray -> { + val list = mutableListOf() + for (i in 0 until value.length()) { + list.add(innerParse(value.get(i))) + } + list + } + else -> innerParse(value) + } + } + } + + override val content: @Composable (androidx.navigation.NavBackStackEntry) -> Unit = { + val exportSensitiveData = it.arguments?.getBoolean("exportSensitiveData") ?: false + val parser = remember { ConfigParser() } + val featuresByCategory = remember { + parser.parse(context.config.exportToString(exportSensitiveData)) + } + val expandedState = remember { mutableStateMapOf() } + + Box( + modifier = Modifier + .fillMaxSize() + .background(PurrfectPalette.backgroundGradient) + ) { + Column(modifier = Modifier.fillMaxSize()) { + Surface( + modifier = Modifier + .fillMaxWidth() + .statusBarsPadding() + .padding(horizontal = 14.dp, vertical = 12.dp), + shape = RoundedCornerShape(24.dp), + color = Color.Transparent, + tonalElevation = 0.dp, + shadowElevation = 12.dp, + border = BorderStroke( + 1.dp, + Brush.linearGradient( + listOf( + PurrfectPalette.glowPrimary.copy(alpha = 0.55f), + PurrfectPalette.glowSecondary.copy(alpha = 0.45f) + ) + ) + ) + ) { + Row( + modifier = Modifier + .background(PurrfectPalette.cardOverlay, RoundedCornerShape(24.dp)) + .padding(horizontal = 16.dp, vertical = 12.dp), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.SpaceBetween + ) { + Row( + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(10.dp) + ) { + IconButton(onClick = { routes.navController.popBackStack() }) { + Icon( + Icons.AutoMirrored.Filled.ArrowBack, + contentDescription = translation["back_button_description"], + tint = Color.White + ) + } + Column { + Text( + text = translation["title"], + color = Color.White, + fontWeight = FontWeight.ExtraBold, + fontSize = 18.sp + ) + } + } + Surface( + shape = CircleShape, + color = PurrfectPalette.glowPrimary.copy(alpha = 0.22f), + tonalElevation = 0.dp, + shadowElevation = 10.dp, + border = BorderStroke( + 1.dp, + Brush.linearGradient( + listOf( + PurrfectPalette.glowPrimary.copy(alpha = 0.55f), + PurrfectPalette.glowSecondary.copy(alpha = 0.45f) + ) + ) + ) + ) { + IconButton( + onClick = { + routes.activityLauncher.saveFile("config.json", "application/json") { uri -> + runCatching { + context.androidContext.contentResolver.openOutputStream(android.net.Uri.parse(uri))?.use { + context.config.writeConfig() + context.config.exportToString(exportSensitiveData).byteInputStream().copyTo(it) + context.shortToast(context.translation["manager.sections.features.config_export_success_toast"]) + } + }.onFailure { + context.longToast( + context.translation.format( + "manager.sections.features.config_export_failure_toast", + "error" to it.message.toString() + ) + ) + } + } + } + ) { + Icon( + imageVector = Icons.Default.ArrowDownward, + contentDescription = translation["save_button"], + tint = Color.White + ) + } + } + } + } + + LazyColumn( + modifier = Modifier + .fillMaxSize() + .padding(horizontal = 12.dp), + contentPadding = PaddingValues( + top = 8.dp, + bottom = 16.dp + routes.bottomPadding + ), + verticalArrangement = Arrangement.spacedBy(10.dp) + ) { + items(featuresByCategory.toList()) { (category, features) -> + val isExpanded = expandedState[category] ?: false + val rotationState by animateFloatAsState(targetValue = if (isExpanded) 180f else 0f) + Surface( + modifier = Modifier + .fillMaxWidth() + .clickable { expandedState[category] = !isExpanded }, + shape = RoundedCornerShape(18.dp), + color = PurrfectPalette.cardOverlayColor, + tonalElevation = 0.dp, + shadowElevation = 10.dp, + border = BorderStroke( + 1.dp, + Brush.linearGradient( + listOf( + PurrfectPalette.glowPrimary.copy(alpha = 0.4f), + PurrfectPalette.glowSecondary.copy(alpha = 0.32f) + ) + ) + ) + ) { + Column(modifier = Modifier.padding(horizontal = 14.dp, vertical = 12.dp)) { + Row(verticalAlignment = Alignment.CenterVertically) { + Column(modifier = Modifier.weight(1f)) { + Text( + text = category, + fontWeight = FontWeight.Bold, + fontSize = 17.sp, + color = Color.White + ) + } + IconButton(onClick = { expandedState[category] = !isExpanded }) { + Icon( + imageVector = Icons.Default.KeyboardArrowDown, + contentDescription = translation["expand_button_description"], + modifier = Modifier.graphicsLayer(rotationZ = rotationState), + tint = Color.White + ) + } + } + AnimatedVisibility(visible = isExpanded) { + Column( + modifier = Modifier + .padding(top = 10.dp), + verticalArrangement = Arrangement.spacedBy(8.dp) + ) { + features.forEachIndexed { index, feature -> + when (val parsedValue = parser.parseValue(feature.key, feature.value)) { + is List<*> -> { + Column( + modifier = Modifier.padding(start = (feature.indentation * 16).dp), + verticalArrangement = Arrangement.spacedBy(6.dp) + ) { + Text( + text = feature.name, + fontWeight = FontWeight.SemiBold, + color = Color.White + ) + Column( + modifier = Modifier.padding(start = 6.dp), + verticalArrangement = Arrangement.spacedBy(6.dp) + ) { + parsedValue.forEachIndexed { itemIndex, item -> + Row( + horizontalArrangement = Arrangement.spacedBy(10.dp), + verticalAlignment = Alignment.CenterVertically + ) { + NumberBubble(itemIndex + 1) + Text( + text = item.toString(), + color = PurrfectPalette.textSecondary + ) + } + } + } + } + } + is String -> { + Column( + modifier = Modifier + .fillMaxWidth() + .padding(start = (feature.indentation * 16).dp), + verticalArrangement = Arrangement.spacedBy(4.dp) + ) { + Text( + text = feature.name, + fontWeight = FontWeight.SemiBold, + color = Color.White + ) + Text( + text = parsedValue, + color = PurrfectPalette.glowSecondary, + textAlign = TextAlign.Start + ) + } + } + } + if (index < features.size - 1) { + Spacer(modifier = Modifier.height(6.dp)) + } + } + } + } + } + } + } + } + } + } + } + + @Composable + private fun NumberBubble(number: Int) { + Surface( + shape = CircleShape, + color = Color.White.copy(alpha = 0.08f), + tonalElevation = 0.dp, + shadowElevation = 6.dp, + border = BorderStroke( + 1.dp, + Brush.linearGradient( + listOf( + PurrfectPalette.glowPrimary.copy(alpha = 0.5f), + PurrfectPalette.glowSecondary.copy(alpha = 0.4f) + ) + ) + ) + ) { + Box( + modifier = Modifier.padding(horizontal = 10.dp, vertical = 6.dp), + contentAlignment = Alignment.Center + ) { + Text(number.toString(), color = Color.White, fontWeight = FontWeight.Bold) + } + } + } +} diff --git a/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/features/ConfigImportConfirmationScreen.kt b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/features/ConfigImportConfirmationScreen.kt new file mode 100644 index 00000000..5a47f9ab --- /dev/null +++ b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/features/ConfigImportConfirmationScreen.kt @@ -0,0 +1,417 @@ +package me.eternal.purrfectsnap.ui.manager.pages.features + +import androidx.compose.animation.AnimatedVisibility +import androidx.compose.animation.core.animateFloatAsState +import androidx.compose.foundation.BorderStroke +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.automirrored.filled.ArrowBack +import androidx.compose.material.icons.filled.KeyboardArrowDown +import androidx.compose.material3.Button +import androidx.compose.material3.ButtonDefaults +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Surface +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateMapOf +import androidx.compose.runtime.remember +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Brush +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.graphicsLayer +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import me.eternal.purrfectsnap.ui.manager.Routes +import me.eternal.purrfectsnap.ui.manager.theme.PurrfectPalette +import org.json.JSONArray +import org.json.JSONObject + +class ConfigImportConfirmationScreen : Routes.Route() { + override val translation by lazy { context.translation.getCategory("manager.features.config_import") } + + private data class ImportedFeature( + val category: String, + val name: String, + val key: String, + val value: Any, + val indentation: Int + ) + + private inner class ConfigParser { + fun parse(configJson: String): Map> { + val featureList = mutableListOf() + val json = JSONObject(configJson) + fun parseProperties( + categoryKey: String, + niceCategoryName: String, + properties: JSONObject, + prefix: String, + indent: Int + ) { + for (key in properties.keys()) { + val value = properties.get(key) + val currentPrefix = if (prefix.isEmpty()) key else "$prefix.$key" + if (value is JSONObject && value.has("state") && value.has("properties")) { + val featureNameKey = + "features.properties.$categoryKey.properties.${currentPrefix.split('.') + .joinToString(".properties.")}.name" + val featureName = context.translation[featureNameKey] ?: key + featureList.add( + ImportedFeature( + niceCategoryName, + featureName, + key, + value.getBoolean("state"), + indent + ) + ) + parseProperties( + categoryKey, + niceCategoryName, + value.getJSONObject("properties"), + currentPrefix, + indent + 1 + ) + } else if (value is JSONObject && value.has("properties")) { + parseProperties( + categoryKey, + niceCategoryName, + value.getJSONObject("properties"), + currentPrefix, + indent + ) + } else { + val featureNameKey = + "features.properties.$categoryKey.properties.${currentPrefix.split('.') + .joinToString(".properties.")}.name" + val featureName = context.translation[featureNameKey] ?: key + featureList.add( + ImportedFeature( + niceCategoryName, + featureName, + key, + value, + indent + ) + ) + } + } + } + for (categoryKey in json.keys()) { + val value = json.get(categoryKey) + if (value is JSONObject) { + val niceCategoryName = + context.translation["features.properties.$categoryKey.name"] + ?: categoryKey.replaceFirstChar { it.uppercase() } + if (value.has("state") && !value.has("properties")) { + featureList.add( + ImportedFeature( + niceCategoryName, + translation["enable_feature"], + categoryKey, + value.getBoolean("state"), + 0 + ) + ) + } else if (value.has("properties")) { + parseProperties( + categoryKey, + niceCategoryName, + value.getJSONObject("properties"), + "", + 0 + ) + } + } + } + return featureList.groupBy { it.category } + } + + fun parseValue(featureKey: String, value: Any): Any { + fun innerParse(v: Any): String { + if (v is String) { + if (v.isBlank()) { + val emptyKey = "features.options.$featureKey.empty" + val translatedEmpty = context.translation[emptyKey] + val fallback = context.translation["features.options.empty"]?.takeUnless { it == "features.options.empty" } + return if (!translatedEmpty.isNullOrBlank() && translatedEmpty != emptyKey && !translatedEmpty.startsWith("features.")) translatedEmpty else (fallback ?: "Empty") + } + val translationKey = "features.options.$featureKey.$v" + val translated = context.translation[translationKey] + return if (!translated.isNullOrBlank() && translated != translationKey && !translated.startsWith("features.")) translated else v + } + return v.toString() + } + return when (value) { + is Boolean -> if (value) translation["enabled"] else translation["disabled"] + is JSONArray -> { + val list = mutableListOf() + for (i in 0 until value.length()) { + list.add(innerParse(value.get(i))) + } + list + } + else -> innerParse(value) + } + } + } + + override val content: @Composable (androidx.navigation.NavBackStackEntry) -> Unit = { + val parser = remember { ConfigParser() } + val featuresByCategory = remember { + routes.configJsonForImport?.let { parser.parse(it) } ?: emptyMap() + } + val expandedState = remember { mutableStateMapOf() } + + Box( + modifier = Modifier + .fillMaxSize() + .background(PurrfectPalette.backgroundGradient) + ) { + Column(modifier = Modifier.fillMaxSize()) { + Surface( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 14.dp, vertical = 12.dp), + shape = RoundedCornerShape(24.dp), + color = Color.Transparent, + tonalElevation = 0.dp, + shadowElevation = 12.dp, + border = BorderStroke( + 1.dp, + Brush.linearGradient( + listOf( + PurrfectPalette.glowPrimary.copy(alpha = 0.55f), + PurrfectPalette.glowSecondary.copy(alpha = 0.45f) + ) + ) + ) + ) { + Row( + modifier = Modifier + .background(PurrfectPalette.cardOverlay, RoundedCornerShape(24.dp)) + .padding(horizontal = 16.dp, vertical = 12.dp), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.SpaceBetween + ) { + Row( + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(10.dp) + ) { + IconButton(onClick = { routes.navController.popBackStack() }) { + Icon( + Icons.AutoMirrored.Filled.ArrowBack, + contentDescription = translation["back_button_description"], + tint = Color.White + ) + } + Column { + Text( + text = translation["title"], + color = Color.White, + fontWeight = FontWeight.ExtraBold, + fontSize = 18.sp + ) + } + } + Button( + onClick = { + routes.configJsonForImport?.let { json -> + runCatching { + context.config.loadFromString(json) + }.onFailure { err -> + context.longToast( + context.translation.format( + "config_import_failure_toast", + "error" to (err.message ?: "Unknown error") + ) + ) + } + context.shortToast(translation["config_imported_toast"]) + context.coroutineScope.launch(Dispatchers.Main) { + routes.features.navigateReload() + } + } + }, + colors = ButtonDefaults.buttonColors( + containerColor = PurrfectPalette.glowPrimary.copy(alpha = 0.3f), + contentColor = Color.White + ) + ) { + Text(translation["confirm_button"]) + } + } + } + + LazyColumn( + modifier = Modifier + .fillMaxSize() + .padding(horizontal = 12.dp), + contentPadding = PaddingValues( + top = 8.dp, + bottom = 16.dp + routes.bottomPadding + ), + verticalArrangement = Arrangement.spacedBy(10.dp) + ) { + items(featuresByCategory.toList()) { (category, features) -> + val isExpanded = expandedState[category] ?: false + val rotationState by animateFloatAsState(targetValue = if (isExpanded) 180f else 0f) + + Surface( + modifier = Modifier + .fillMaxWidth() + .clickable { expandedState[category] = !isExpanded }, + shape = RoundedCornerShape(18.dp), + color = PurrfectPalette.cardOverlayColor, + tonalElevation = 0.dp, + shadowElevation = 10.dp, + border = BorderStroke( + 1.dp, + Brush.linearGradient( + listOf( + PurrfectPalette.glowPrimary.copy(alpha = 0.4f), + PurrfectPalette.glowSecondary.copy(alpha = 0.32f) + ) + ) + ) + ) { + Column(modifier = Modifier.padding(horizontal = 14.dp, vertical = 12.dp)) { + Row(verticalAlignment = Alignment.CenterVertically) { + Column(modifier = Modifier.weight(1f)) { + Text( + text = category, + fontWeight = FontWeight.Bold, + fontSize = 17.sp, + color = Color.White + ) + } + IconButton(onClick = { expandedState[category] = !isExpanded }) { + Icon( + imageVector = Icons.Default.KeyboardArrowDown, + contentDescription = translation["expand_button_description"], + modifier = Modifier.graphicsLayer(rotationZ = rotationState), + tint = Color.White + ) + } + } + + AnimatedVisibility(visible = isExpanded) { + Column( + modifier = Modifier.padding(top = 10.dp), + verticalArrangement = Arrangement.spacedBy(8.dp) + ) { + features.forEachIndexed { index, feature -> + when (val parsedValue = parser.parseValue(feature.key, feature.value)) { + is List<*> -> { + Column( + modifier = Modifier.padding(start = (feature.indentation * 16).dp), + verticalArrangement = Arrangement.spacedBy(6.dp) + ) { + Text( + text = feature.name, + fontWeight = FontWeight.SemiBold, + color = Color.White + ) + Column( + modifier = Modifier.padding(start = 6.dp), + verticalArrangement = Arrangement.spacedBy(6.dp) + ) { + parsedValue.forEachIndexed { itemIndex, item -> + Row( + horizontalArrangement = Arrangement.spacedBy(10.dp), + verticalAlignment = Alignment.CenterVertically + ) { + NumberBubble(itemIndex + 1) + Text( + text = item.toString(), + color = PurrfectPalette.textSecondary + ) + } + } + } + } + } + + is String -> { + Column( + modifier = Modifier + .fillMaxWidth() + .padding(start = (feature.indentation * 16).dp), + verticalArrangement = Arrangement.spacedBy(4.dp) + ) { + Text( + text = feature.name, + fontWeight = FontWeight.SemiBold, + color = Color.White + ) + Text( + text = parsedValue, + color = PurrfectPalette.glowSecondary, + textAlign = TextAlign.Start, + ) + } + } + } + if (index < features.size - 1) { + Spacer(modifier = Modifier.height(6.dp)) + } + } + } + } + } + } + } + } + } + } + } + + @Composable + private fun NumberBubble(number: Int) { + Surface( + shape = CircleShape, + color = Color.White.copy(alpha = 0.08f), + tonalElevation = 0.dp, + shadowElevation = 6.dp, + border = BorderStroke( + 1.dp, + Brush.linearGradient( + listOf( + PurrfectPalette.glowPrimary.copy(alpha = 0.5f), + PurrfectPalette.glowSecondary.copy(alpha = 0.4f) + ) + ) + ) + ) { + Box( + modifier = Modifier.padding(horizontal = 10.dp, vertical = 6.dp), + contentAlignment = Alignment.Center + ) { + Text(number.toString(), color = Color.White, fontWeight = FontWeight.Bold) + } + } + } +} diff --git a/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/features/FeaturesRootSection.kt b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/features/FeaturesRootSection.kt new file mode 100644 index 00000000..966e1a3f --- /dev/null +++ b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/features/FeaturesRootSection.kt @@ -0,0 +1,1637 @@ +package me.eternal.purrfectsnap.ui.manager.pages.features + +import android.net.Uri +import androidx.compose.animation.AnimatedContentTransitionScope +import androidx.compose.animation.core.tween +import androidx.compose.foundation.BorderStroke +import androidx.compose.foundation.LocalIndication +import androidx.compose.foundation.background +import androidx.compose.foundation.border +import androidx.compose.foundation.clickable +import androidx.compose.foundation.interaction.MutableInteractionSource +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.RowScope +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.WindowInsets +import androidx.compose.foundation.layout.asPaddingValues +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.heightIn +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.statusBars +import androidx.compose.foundation.layout.statusBarsPadding +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.layout.widthIn +import androidx.compose.foundation.layout.wrapContentWidth +import androidx.compose.foundation.layout.ExperimentalLayoutApi +import androidx.compose.foundation.layout.FlowRow +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items +import androidx.compose.foundation.lazy.itemsIndexed +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.foundation.text.KeyboardActions +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.automirrored.filled.ArrowBack +import androidx.compose.material.icons.automirrored.filled.OpenInNew +import androidx.compose.material.icons.filled.* +import androidx.compose.material3.* +import androidx.compose.runtime.* +import androidx.compose.runtime.snapshots.SnapshotStateList +import androidx.compose.runtime.saveable.rememberSaveable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.drawBehind +import androidx.compose.ui.focus.FocusRequester +import androidx.compose.ui.focus.focusRequester +import androidx.compose.ui.geometry.CornerRadius +import androidx.compose.ui.geometry.Offset +import androidx.compose.ui.geometry.Size +import androidx.compose.ui.graphics.Brush +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.SolidColor +import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.graphicsLayer +import androidx.compose.ui.hapticfeedback.HapticFeedbackType +import androidx.compose.ui.layout.onGloballyPositioned +import androidx.compose.ui.platform.LocalHapticFeedback +import androidx.compose.ui.platform.LocalDensity +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.text.style.TextOverflow +import androidx.compose.ui.text.TextRange +import androidx.compose.ui.text.input.TextFieldValue +import androidx.compose.ui.unit.DpOffset +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import androidx.compose.ui.window.Dialog +import androidx.compose.ui.zIndex +import androidx.lifecycle.Lifecycle +import androidx.navigation.NavBackStackEntry +import androidx.navigation.NavGraph.Companion.findStartDestination +import androidx.navigation.NavGraphBuilder +import androidx.navigation.NavOptions +import androidx.navigation.compose.composable +import androidx.navigation.compose.currentBackStackEntryAsState +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.Job +import kotlinx.coroutines.delay +import kotlinx.coroutines.launch +import me.eternal.purrfectsnap.common.config.* +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import me.eternal.purrfectsnap.common.ui.TopBarActionButton +import me.eternal.purrfectsnap.common.ui.rememberAsyncMutableStateList +import me.eternal.purrfectsnap.ui.manager.Routes +import me.eternal.purrfectsnap.ui.manager.theme.PurrfectPalette +import me.eternal.purrfectsnap.ui.util.* +import org.json.JSONArray +import org.json.JSONObject +import kotlin.math.max +import kotlin.math.min + +class FeaturesRootSection : Routes.Route() { + override val title: @Composable (() -> Unit)? = @Composable { + val navBackStackEntry by routes.navController.currentBackStackEntryAsState() + val currentDestination = navBackStackEntry?.destination + + val titleText = when (currentDestination?.route) { + FEATURE_CONTAINER_ROUTE -> { + navBackStackEntry?.arguments?.getString("name")?.let { containerName -> + allContainers[containerName]?.let { + context.translation[it.key.propertyName()] + } + } ?: routeInfo.translatedKey?.value + } + SEARCH_FEATURE_ROUTE -> { + translation["search_button"] ?: "Search" + } + else -> { + routeInfo.translatedKey?.value + } + } + Text(titleText ?: "", maxLines = 1, overflow = TextOverflow.Ellipsis) + } + + private val alertDialogs by lazy { AlertDialogs(context.translation) } + private val gson by lazy { Gson() } + private val listTypeToken = object : TypeToken>() {}.type + + companion object { + const val FEATURE_CONTAINER_ROUTE = "feature_container/{name}" + const val SEARCH_FEATURE_ROUTE = "search_feature/{keyword}" + } + + private val allContainers by lazy { + val containers = mutableMapOf>() + fun queryContainerRecursive(container: ConfigContainer) { + container.properties.forEach { + if (it.key.dataType.type == DataProcessors.Type.CONTAINER) { + containers[it.key.name] = PropertyPair(it.key, it.value) + queryContainerRecursive(it.value.get() as ConfigContainer) + } + } + } + queryContainerRecursive(context.config.root) + containers + } + + private val allProperties by lazy { + val properties = mutableMapOf, PropertyValue<*>>() + allContainers.values.forEach { + val container = it.value.get() as ConfigContainer + container.properties.forEach { property -> + properties[property.key] = property.value + } + } + properties + } + + private data class SearchEntry(val keyword: String, val tokens: List) + + private fun buildSearchEntries(): List { + return allProperties.keys.mapNotNull { key -> + val name = context.translation[key.propertyName()] + val description = context.translation[key.propertyDescription()] + val tokens = listOfNotNull(name, description, key.name).map { it.trim() }.filter { it.isNotEmpty() } + if (tokens.isEmpty()) null else SearchEntry(keyword = name ?: key.name, tokens = tokens) + } + } + + private fun levenshtein(a: String, b: String): Int { + if (a == b) return 0 + if (a.isEmpty()) return b.length + if (b.isEmpty()) return a.length + val prev = IntArray(b.length + 1) { it } + val curr = IntArray(b.length + 1) + for (i in a.indices) { + curr[0] = i + 1 + for (j in b.indices) { + val cost = if (a[i] == b[j]) 0 else 1 + curr[j + 1] = min( + min(curr[j] + 1, prev[j + 1] + 1), + prev[j] + cost + ) + } + prev.indices.forEach { prev[it] = curr[it] } + } + return curr[b.length] + } + + private fun similarityScore(query: String, target: String): Float { + val q = query.lowercase() + val t = target.lowercase() + val maxLen = max(q.length, t.length) + if (maxLen == 0) return 1f + val dist = levenshtein(q, t) + return 1f - (dist.toFloat() / maxLen.toFloat()) + } + + private fun fuzzySuggest(query: String, entries: List): List { + val q = query.trim() + if (q.length < 2) return emptyList() + return entries.map { entry -> + val best = entry.tokens.maxOfOrNull { similarityScore(q, it) } ?: 0f + best to entry.keyword + }.filter { it.first >= 0.45f } + .sortedWith(compareByDescending> { it.first }.thenBy { it.second.length }) + .map { it.second } + .distinct() + .take(6) + } + + private fun loadSearchHistory(): List { + return context.sharedPreferences + .getString("features_search_history", "") // stored as | separated + ?.split("|") + ?.map { it.trim() } + ?.filter { it.isNotEmpty() } + ?: emptyList() + } + + private fun saveSearchHistory(history: List) { + context.sharedPreferences.edit() + .putString("features_search_history", history.joinToString("|")) + .apply() + } + + private fun upsertHistory(term: String, history: SnapshotStateList) { + val cleaned = term.trim() + if (cleaned.isEmpty()) return + val existingIndex = history.indexOfFirst { it.equals(cleaned, ignoreCase = true) } + if (existingIndex >= 0) history.removeAt(existingIndex) + history.add(0, cleaned) + while (history.size > 12) history.removeLast() + saveSearchHistory(history) + } + + private fun navigateToMainRoot() { + routes.navController.navigate(routeInfo.id, NavOptions.Builder() + .setPopUpTo(routes.navController.graph.findStartDestination().id, false) + .setLaunchSingleTop(true) + .build() + ) + } + + private fun activityLauncher(block: ActivityLauncherHelper.() -> Unit) { + routes.activityLauncher.let(block) + } + + override val content: @Composable (NavBackStackEntry) -> Unit = { + Container(context.config.root) + } + + override val customComposables: NavGraphBuilder.() -> Unit = { + routeInfo.childIds.addAll(listOf(FEATURE_CONTAINER_ROUTE, SEARCH_FEATURE_ROUTE)) + + composable(FEATURE_CONTAINER_ROUTE, enterTransition = { + slideIntoContainer( + AnimatedContentTransitionScope.SlideDirection.Left, + animationSpec = tween(140) + ) + }, exitTransition = { + slideOutOfContainer( + AnimatedContentTransitionScope.SlideDirection.Right, + animationSpec = tween(160) + ) + }) { backStackEntry -> + backStackEntry.arguments?.getString("name")?.let { containerName -> + allContainers[containerName]?.let { + val containerTitle = translation[it.key.propertyName()] + val containerSubtitle = translation[it.key.propertyDescription()] + Container( + configContainer = it.value.get() as ConfigContainer, + sectionTitle = containerTitle, + sectionSubtitle = containerSubtitle, + onBack = { routes.navController.popBackStack() } + ) + } + } + } + + composable(SEARCH_FEATURE_ROUTE) { backStackEntry -> + backStackEntry.arguments?.getString("keyword")?.let { keyword -> + val properties = allProperties.filter { + it.key.name.contains(keyword, ignoreCase = true) || + context.translation[it.key.propertyName()].contains(keyword, ignoreCase = true) || + context.translation[it.key.propertyDescription()].contains(keyword, ignoreCase = true) + }.map { PropertyPair(it.key, it.value) } + + PropertiesView( + properties = properties, + isSearchResults = true, + searchKeyword = keyword, + enableGlobalSearch = true, + onBack = { navigateToMainRoot() } + ) + } + } + } + + @Composable + private fun FeatureAuroraBackdrop(modifier: Modifier = Modifier) { + Box( + modifier = modifier + .fillMaxSize() + .background(PurrfectPalette.backgroundGradient) + ) + } + + @Composable + private fun NoticeBadge(text: String, color: Color) { + Surface( + shape = RoundedCornerShape(50), + color = color.copy(alpha = 0.16f), + shadowElevation = 0.dp, + tonalElevation = 0.dp, + border = BorderStroke(1.dp, color.copy(alpha = 0.35f)) + ) { + Text( + text = text, + color = color, + fontSize = 12.sp, + fontWeight = FontWeight.SemiBold, + modifier = Modifier.padding(horizontal = 10.dp, vertical = 6.dp) + ) + } + } + + @Composable + private fun EmptyState(isSearchResults: Boolean) { + val shape = RoundedCornerShape(24.dp) + val border = Brush.linearGradient( + listOf( + PurrfectPalette.glowPrimary.copy(alpha = 0.45f), + PurrfectPalette.glowSecondary.copy(alpha = 0.35f) + ) + ) + Surface( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 18.dp, vertical = 12.dp), + shape = shape, + color = Color.White.copy(alpha = 0.04f), + tonalElevation = 10.dp, + shadowElevation = 0.dp, + border = BorderStroke(1.dp, border) + ) { + Box(modifier = Modifier.background(PurrfectPalette.cardOverlay, shape)) { + Row( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 18.dp, vertical = 16.dp), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(14.dp) + ) { + Surface( + shape = CircleShape, + color = PurrfectPalette.glowPrimary.copy(alpha = 0.18f) + ) { + Icon( + imageVector = Icons.Filled.SearchOff, + contentDescription = null, + modifier = Modifier.padding(12.dp), + tint = Color.White + ) + } + Column( + verticalArrangement = Arrangement.spacedBy(6.dp) + ) { + Text( + text = if (isSearchResults) "No matches found" else "Nothing to show", + style = MaterialTheme.typography.titleMedium, + fontWeight = FontWeight.SemiBold, + color = Color.White + ) + Text( + text = if (isSearchResults) "Try a different keyword or clear filters." else "Toggle visibility with the new controls above.", + style = MaterialTheme.typography.bodyMedium, + color = PurrfectPalette.textSecondary + ) + } + } + } + } + } + + @Composable + private fun PropertyAction(property: PropertyPair<*>, registerClickCallback: RegisterClickCallback) { + var showDialog by remember { mutableStateOf(false) } + var dialogComposable by remember { mutableStateOf<@Composable () -> Unit>({}) } + + fun registerDialogOnClickCallback() = registerClickCallback { showDialog = true } + + if (showDialog) { + Dialog( + properties = DialogProperties( + usePlatformDefaultWidth = false + ), + onDismissRequest = { showDialog = false }, + ) { + dialogComposable() + } + } + + val propertyValue = property.value + + if (property.key.params.flags.contains(ConfigFlag.USER_IMPORT)) { + registerDialogOnClickCallback() + dialogComposable = { + var isEmpty by remember { mutableStateOf(false) } + val files = rememberAsyncMutableStateList(defaultValue = listOf()) { + context.fileHandleManager.getStoredFiles { + property.key.params.filenameFilter?.invoke(it.name) == true + }.also { + isEmpty = it.isEmpty() + if (isEmpty) { + propertyValue.setAny(null) + } + } + } + var selectedFile by remember(files.size) { mutableStateOf(files.firstOrNull { it.name == propertyValue.getNullable() }.also { + if (files.isNotEmpty() && it == null) propertyValue.setAny(null) + }?.name) } + + Surface( + shape = RoundedCornerShape(24.dp), + modifier = Modifier.fillMaxWidth(), + color = Color.Transparent, + tonalElevation = 0.dp, + shadowElevation = 18.dp, + border = BorderStroke( + 1.dp, + Brush.linearGradient( + listOf( + PurrfectPalette.glowPrimary.copy(alpha = 0.45f), + PurrfectPalette.glowSecondary.copy(alpha = 0.35f) + ) + ) + ) + ) { + Box( + modifier = Modifier + .background(PurrfectPalette.cardOverlay, RoundedCornerShape(24.dp)) + ) { + LazyColumn( + modifier = Modifier + .fillMaxWidth() + .padding(8.dp), + ) { + item { + Column( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 16.dp, vertical = 12.dp), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.spacedBy(6.dp) + ) { + Text( + text = context.translation["manager.dialogs.file_imports.settings_select_file_hint"], + fontSize = 18.sp, + fontWeight = FontWeight.ExtraBold, + color = Color.White + ) + if (isEmpty) { + Text( + text = context.translation["manager.dialogs.file_imports.no_files_settings_hint"], + fontSize = 15.sp, + fontWeight = FontWeight.Medium, + color = PurrfectPalette.textSecondary, + modifier = Modifier.padding(top = 4.dp), + textAlign = TextAlign.Center + ) + } else { + Text( + text = translation["manager.dialogs.file_imports.settings_select_file_subtitle"] + ?: translation["manager.dialogs.file_imports.settings_select_file_hint"], + fontSize = 13.sp, + color = PurrfectPalette.textSecondary, + textAlign = TextAlign.Center + ) + } + } + } + items(files, key = { it.name }) { file -> + val isSelected = selectedFile == file.name + Surface( + modifier = Modifier + .fillMaxWidth() + .padding(vertical = 4.dp) + .clickable { + selectedFile = if (isSelected) null else file.name + propertyValue.setAny(selectedFile) + }, + shape = RoundedCornerShape(16.dp), + color = Color.White.copy(alpha = 0.05f), + tonalElevation = 0.dp, + shadowElevation = 0.dp, + border = BorderStroke( + 1.dp, + if (isSelected) Brush.linearGradient( + listOf( + PurrfectPalette.glowPrimary.copy(alpha = 0.6f), + PurrfectPalette.glowSecondary.copy(alpha = 0.48f) + ) + ) else SolidColor(Color.White.copy(alpha = 0.08f)) + ) + ) { + Row( + modifier = Modifier.padding(horizontal = 12.dp, vertical = 10.dp), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(10.dp) + ) { + Surface( + shape = CircleShape, + color = PurrfectPalette.glowPrimary.copy(alpha = 0.16f) + ) { + Icon( + Icons.Filled.AttachFile, + contentDescription = null, + modifier = Modifier.padding(10.dp), + tint = Color.White + ) + } + Text( + text = file.name, + modifier = Modifier.weight(1f), + fontSize = 14.sp, + lineHeight = 16.sp, + color = Color.White + ) + if (isSelected) { + Surface( + shape = CircleShape, + color = PurrfectPalette.glowSecondary.copy(alpha = 0.18f) + ) { + Icon( + Icons.Filled.Check, + contentDescription = null, + modifier = Modifier.padding(8.dp), + tint = PurrfectPalette.glowSecondary + ) + } + } + } + } + } + } + } + } + } + + Icon(Icons.Filled.AttachFile, contentDescription = null) + return + } + + if (property.key.params.flags.contains(ConfigFlag.FOLDER)) { + IconButton(onClick = registerClickCallback { + activityLauncher { + chooseFolder { uri -> + propertyValue.setAny(uri) + } + } + }.let { { it.invoke(true) } }) { + Icon(Icons.Filled.FolderOpen, contentDescription = null) + } + return + } + + when (val dataType = remember { property.key.dataType.type }) { + DataProcessors.Type.BOOLEAN -> { + var state by remember { mutableStateOf(propertyValue.get() as Boolean) } + val hapticFeedback = LocalHapticFeedback.current + Switch( + checked = state, + onCheckedChange = registerClickCallback { + if (context.config.root.global.uiSettings.hapticFeedback.get()) { + hapticFeedback.performHapticFeedback(HapticFeedbackType.LongPress) + } + state = state.not() + propertyValue.setAny(state) + }, + colors = purrfectSwitchColors() + ) + } + + DataProcessors.Type.MAP_COORDINATES -> { + registerDialogOnClickCallback() + dialogComposable = { + alertDialogs.ChooseLocationDialog(property) { + showDialog = false + } + } + + Text( + overflow = TextOverflow.Ellipsis, + maxLines = 1, + modifier = Modifier.widthIn(0.dp, 120.dp), + text = (propertyValue.get() as Pair<*, *>).let { + "${it.first.toString().toFloatOrNull() ?: 0F}, ${it.second.toString().toFloatOrNull() ?: 0F}" + } + ) + } + + DataProcessors.Type.STRING_UNIQUE_SELECTION -> { + registerDialogOnClickCallback() + + dialogComposable = { + alertDialogs.UniqueSelectionDialog(property) + } + + Text( + overflow = TextOverflow.Ellipsis, + maxLines = 1, + modifier = Modifier.widthIn(0.dp, 120.dp), + text = (propertyValue.getNullable() as? String ?: "null").let { + property.key.propertyOption(context.translation, it) + } + ) + } + + DataProcessors.Type.STRING_MULTIPLE_SELECTION, DataProcessors.Type.STRING, DataProcessors.Type.INTEGER, DataProcessors.Type.FLOAT -> { + dialogComposable = { + when (dataType) { + DataProcessors.Type.STRING_MULTIPLE_SELECTION -> { + alertDialogs.MultipleSelectionDialog(property) + } + DataProcessors.Type.STRING, DataProcessors.Type.INTEGER, DataProcessors.Type.FLOAT -> { + // Check if this is a message list property + val isMessageListProperty = property.key.name.endsWith("_messages") + if (isMessageListProperty) { + alertDialogs.MessageListPropertyDialog(property) { showDialog = false } + } else { + alertDialogs.KeyboardInputDialog(property) { showDialog = false } + } + } + else -> {} + } + } + + registerDialogOnClickCallback().let { { it.invoke(true) } }.also { + if (dataType == DataProcessors.Type.INTEGER || + dataType == DataProcessors.Type.FLOAT) { + ValueGlowChip( + text = propertyValue.get().toString(), + onClick = it + ) + } else { + // Check if this is a message list property + val isMessageListProperty = property.key.name.endsWith("_messages") + if (isMessageListProperty) { + // Show message count + val messageCount = try { + val messageList: List = gson.fromJson(propertyValue.get().toString(), listTypeToken) ?: emptyList() + messageList.size + } catch (e: Exception) { + 1 + } + + Surface( + shape = RoundedCornerShape(14.dp), + color = Color.White.copy(alpha = 0.06f), + tonalElevation = 0.dp, + shadowElevation = 0.dp, + border = BorderStroke(1.dp, Color.White.copy(alpha = 0.12f)) + ) { + Text( + text = "$messageCount messages", + modifier = Modifier.padding(horizontal = 10.dp, vertical = 6.dp), + style = MaterialTheme.typography.bodyMedium, + color = Color.White + ) + } + } else { + IconButton(onClick = it) { + Icon(Icons.AutoMirrored.Filled.OpenInNew, contentDescription = null) + } + } + } + } + } + + DataProcessors.Type.INT_COLOR -> { + dialogComposable = { + alertDialogs.ColorPickerPropertyDialog(property) { + showDialog = false + } + } + + registerDialogOnClickCallback().let { { it.invoke(true) } }.also { + CircularAlphaTile(selectedColor = (propertyValue.getNullable() as? Int)?.let { Color(it) }) + } + } + + DataProcessors.Type.CONTAINER -> { + val container = propertyValue.get() as ConfigContainer + + registerClickCallback { + routes.navController.navigate(FEATURE_CONTAINER_ROUTE.replace("{name}", property.name)) + } + + if (!container.hasGlobalState) return + + var state by remember { mutableStateOf(container.globalState ?: false) } + + Box( + modifier = Modifier + .padding(end = 15.dp), + ) { + + Box(modifier = Modifier + .height(50.dp) + .width(1.dp) + .background( + color = MaterialTheme.colorScheme.primary.copy(alpha = 0.12f), + shape = RoundedCornerShape(5.dp) + )) + } + + val hapticFeedback = LocalHapticFeedback.current + Switch( + checked = state, + onCheckedChange = { + if (context.config.root.global.uiSettings.hapticFeedback.get()) { + hapticFeedback.performHapticFeedback(HapticFeedbackType.LongPress) + } + state = state.not() + container.globalState = state + }, + colors = purrfectSwitchColors() + ) + } + } + + } + + @Composable + private fun ValueGlowChip( + text: String, + onClick: () -> Unit + ) { + Surface( + modifier = Modifier + .size(52.dp) + .clip(CircleShape) + .clickable { onClick() }, + shape = CircleShape, + color = Color.White.copy(alpha = 0.08f), + tonalElevation = 0.dp, + shadowElevation = 10.dp, + border = BorderStroke( + 1.dp, + Brush.linearGradient( + listOf( + PurrfectPalette.glowPrimary.copy(alpha = 0.55f), + PurrfectPalette.glowSecondary.copy(alpha = 0.45f) + ) + ) + ) + ) { + Box( + modifier = Modifier + .fillMaxSize() + .background( + Brush.radialGradient( + listOf( + PurrfectPalette.glowPrimary.copy(alpha = 0.28f), + Color.Transparent + ) + ) + ), + contentAlignment = Alignment.Center + ) { + Text( + text = text, + color = Color.White, + fontWeight = FontWeight.Bold + ) + } + } + } + + @Composable + private fun PropertyCard(property: PropertyPair<*>, onOpen: (() -> Unit)? = null) { + var clickCallback by remember { mutableStateOf(null) } + val noticeColorMap = remember { + mapOf( + FeatureNotice.UNSTABLE.key to Color(0xFFFFFB87), + FeatureNotice.BAN_RISK.key to Color(0xFFFF8585), + FeatureNotice.INTERNAL_BEHAVIOR.key to Color(0xFFFFFB87), + ) + } + + val versionCheck = remember { property.key.params.versionCheck } + val versionCheckPair = remember(property) { versionCheck?.checkVersion(context.installationSummary.snapchatInfo?.versionCode ?: return@remember null)} + val isComponentDisabled = remember { versionCheckPair != null && versionCheck?.isDisabled == true } + + val cardShape = RoundedCornerShape(22.dp) + val interactionSource = remember { MutableInteractionSource() } + val density = LocalDensity.current + val cardBorder = remember { + Brush.linearGradient( + listOf( + PurrfectPalette.glowPrimary.copy(alpha = 0.55f), + PurrfectPalette.glowSecondary.copy(alpha = 0.35f) + ) + ) + } + val cardBackground = remember { PurrfectPalette.cardOverlay } + + Surface( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 12.dp, vertical = 7.dp) + .graphicsLayer { if (isComponentDisabled) alpha = 0.5f } + .clickable( + interactionSource = interactionSource, + indication = null + ) { + onOpen?.invoke() + clickCallback?.invoke(true) + } + .scaleOnPress(interactionSource), + shape = cardShape, + color = Color.Transparent, + tonalElevation = 0.dp, + shadowElevation = 0.dp + ) { + Box( + modifier = Modifier + .background(cardBackground, cardShape) + .border(BorderStroke(1.dp, cardBorder), cardShape) + .padding(horizontal = 14.dp, vertical = 16.dp) + ) { + Row( + modifier = Modifier.fillMaxWidth(), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(14.dp) + ) { + property.key.params.icon?.let { icon -> + Surface( + shape = RoundedCornerShape(18.dp), + color = PurrfectPalette.glowPrimary.copy(alpha = 0.16f), + tonalElevation = 0.dp, + modifier = Modifier.size(62.dp) + ) { + Box( + modifier = Modifier + .fillMaxSize() + .background( + Brush.linearGradient( + listOf( + PurrfectPalette.glowPrimary.copy(alpha = 0.35f), + PurrfectPalette.glowSecondary.copy(alpha = 0.28f) + ) + ) + ), + contentAlignment = Alignment.Center + ) { + Icon( + imageVector = icon, + contentDescription = null, + tint = Color.White, + modifier = Modifier.size(30.dp) + ) + } + } + } + + Column( + modifier = Modifier.weight(1f), + verticalArrangement = Arrangement.spacedBy(6.dp) + ) { + Text( + text = context.translation[property.key.propertyName()], + fontSize = 17.sp, + fontWeight = FontWeight.ExtraBold, + color = PurrfectPalette.textPrimary, + lineHeight = 20.sp + ) + Text( + text = context.translation[property.key.propertyDescription()], + fontSize = 13.sp, + lineHeight = 16.sp, + color = PurrfectPalette.textSecondary + ) + + if (property.key.params.notices.isNotEmpty()) { + Column(verticalArrangement = Arrangement.spacedBy(6.dp)) { + property.key.params.notices.forEach { + NoticeBadge( + text = context.translation["features.notices.${it.key}"], + color = noticeColorMap[it.key] ?: Color(0xFFFFFB87) + ) + } + } + } + + if (versionCheckPair != null) { + NoticeBadge( + text = context.translation.format( + "manager.sections.features.${versionCheckPair.second.key}", + "version" to versionCheckPair.first.first + ), + color = Color(0xFFFF8585) + ) + } + } + + Row( + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.End + ) { + PropertyAction(property, registerClickCallback = { callback -> + if (property.key.propertyTranslationPath().startsWith("rules.properties")) { + clickCallback = { + routes.manageRuleFeature.navigate { + put("rule_type", property.key.name) + } + } + return@PropertyAction clickCallback!! + } + clickCallback = callback + callback + }) + } + } + } + } + } + + @Composable + private fun FeatureSearchBar(rowScope: RowScope, focusRequester: FocusRequester) { + var searchValue by remember { mutableStateOf("") } + val scope = rememberCoroutineScope() + var currentSearchJob by remember { mutableStateOf(null) } + val searchHistory = remember { mutableStateListOf().apply { addAll(loadSearchHistory()) } } + fun launchSearch(term: String, record: Boolean, delayMs: Long = 0L) { + val keyword = term.trim() + if (keyword.isEmpty()) { + navigateToMainRoot() + return + } + currentSearchJob?.cancel() + currentSearchJob = scope.launch { + if (delayMs > 0) delay(delayMs) + if (record) upsertHistory(keyword, searchHistory) + routes.navController.navigate( + SEARCH_FEATURE_ROUTE.replace("{keyword}", keyword), + NavOptions.Builder() + .setLaunchSingleTop(true) + .setPopUpTo(routeInfo.id, false) + .build() + ) + } + } + + rowScope.apply { + val searchBorder = remember { + Brush.linearGradient( + listOf( + Color(0xFF8C7BFF).copy(alpha = 0.48f), + Color(0xFF5FD8FF).copy(alpha = 0.4f) + ) + ) + } + Surface( + modifier = Modifier + .focusRequester(focusRequester) + .weight(1f, fill = true) + .padding(end = 10.dp) + .height(62.dp), + shape = RoundedCornerShape(18.dp), + tonalElevation = 8.dp, + shadowElevation = 0.dp, + border = BorderStroke(1.dp, searchBorder), + color = Color.Transparent + ) { + TextField( + value = searchValue, + onValueChange = { keyword -> + searchValue = keyword + if (keyword.isEmpty()) { + navigateToMainRoot() + } else { + launchSearch(keyword, record = false, delayMs = 250L) + } + }, + keyboardActions = KeyboardActions(onDone = { + launchSearch(searchValue, record = true, delayMs = 0L) + focusRequester.freeFocus() + }), + singleLine = true, + leadingIcon = { + Surface( + shape = CircleShape, + color = Color.White.copy(alpha = 0.16f), + tonalElevation = 0.dp + ) { + Icon( + imageVector = Icons.Filled.Search, + contentDescription = null, + tint = Color.White, + modifier = Modifier.padding(8.dp) + ) + } + }, + placeholder = { + Text( + text = translation["search_button"] ?: "Search", + color = Color(0xFFE0DCFF) + ) + }, + trailingIcon = { + if (searchValue.isNotEmpty()) { + IconButton(onClick = { + searchValue = "" + navigateToMainRoot() + focusRequester.requestFocus() + }) { + Icon( + imageVector = Icons.Filled.Close, + contentDescription = null, + tint = Color.White + ) + } + } + }, + colors = TextFieldDefaults.colors( + focusedIndicatorColor = Color.Transparent, + unfocusedIndicatorColor = Color.Transparent, + disabledIndicatorColor = Color.Transparent, + focusedContainerColor = Color.White.copy(alpha = 0.08f), + unfocusedContainerColor = Color.White.copy(alpha = 0.06f), + cursorColor = Color.White, + focusedTextColor = Color.White, + unfocusedTextColor = Color.White, + disabledTextColor = Color.White.copy(alpha = 0.65f), + focusedPlaceholderColor = Color(0xFFE0DCFF), + unfocusedPlaceholderColor = Color(0xFFE0DCFF), + focusedLeadingIconColor = Color.White, + unfocusedLeadingIconColor = Color.White.copy(alpha = 0.9f), + focusedTrailingIconColor = Color.White, + unfocusedTrailingIconColor = Color.White.copy(alpha = 0.9f) + ) + ) + } + } + } + + @Composable + private fun SensitiveDataDialog( + onDismiss: () -> Unit, + onConfirm: (exportSensitiveData: Boolean) -> Unit + ) { + Dialog(onDismissRequest = onDismiss) { + Surface( + shape = RoundedCornerShape(24.dp), + color = Color.White.copy(alpha = 0.06f), + tonalElevation = 0.dp, + shadowElevation = 16.dp, + border = BorderStroke( + 1.dp, + Brush.linearGradient( + listOf( + PurrfectPalette.glowPrimary.copy(alpha = 0.55f), + PurrfectPalette.glowSecondary.copy(alpha = 0.45f) + ) + ) + ) + ) { + Box(modifier = Modifier.background(PurrfectPalette.cardOverlay)) { + Column( + modifier = Modifier + .padding(horizontal = 20.dp, vertical = 18.dp), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.spacedBy(14.dp) + ) { + Text( + text = context.translation["manager.dialogs.export_config.title"], + style = MaterialTheme.typography.titleLarge.copy( + fontWeight = FontWeight.ExtraBold + ), + color = Color.White, + textAlign = TextAlign.Center + ) + Text( + text = context.translation["manager.dialogs.export_config.content"], + style = MaterialTheme.typography.bodyMedium, + textAlign = TextAlign.Center, + color = PurrfectPalette.textSecondary, + modifier = Modifier.padding(horizontal = 6.dp) + ) + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.spacedBy(10.dp, Alignment.End) + ) { + Button( + onClick = { onConfirm(false) }, + colors = ButtonDefaults.buttonColors( + containerColor = Color.White.copy(alpha = 0.08f), + contentColor = Color.White + ) + ) { + Text(context.translation["button.negative"]) + } + Button( + onClick = { onConfirm(true) }, + colors = ButtonDefaults.buttonColors( + containerColor = PurrfectPalette.glowPrimary.copy(alpha = 0.32f), + contentColor = Color.White + ) + ) { + Text(context.translation["button.positive"]) + } + } + } + } + } + } + } + + override val topBarActions: @Composable (RowScope.() -> Unit) = {} + + @OptIn(ExperimentalLayoutApi::class) + @Composable + private fun FloatingControls( + isSearchResults: Boolean, + modifier: Modifier = Modifier, + activeSectionTitle: String? = null, + activeSectionSubtitle: String? = null, + searchKeyword: String? = null, + searchHistory: SnapshotStateList, + onSearchQueryChange: (String) -> Unit, + onBack: (() -> Unit)? = null + ) { + var showSearchBar by rememberSaveable { mutableStateOf(isSearchResults) } + val focusRequester = remember { FocusRequester() } + var searchValue by rememberSaveable(stateSaver = TextFieldValue.Saver) { + mutableStateOf( + TextFieldValue( + text = searchKeyword.orEmpty(), + selection = TextRange(searchKeyword?.length ?: 0) + ) + ) + } + val searchEntries = remember { buildSearchEntries() } + val combinedSuggestions by remember(searchValue.text, searchHistory, searchEntries) { + derivedStateOf { + val query = searchValue.text + val historyMatches = searchHistory.filter { + query.isBlank() || it.contains(query, ignoreCase = true) + } + val fuzzy = fuzzySuggest(query, searchEntries) + (historyMatches + fuzzy).distinct().take(6) + } + } + + fun updateSearch(keyword: String, record: Boolean = true) { + val term = keyword.trim() + onSearchQueryChange(term) + if (record && term.isNotEmpty()) upsertHistory(term, searchHistory) + } + + var showExportDropdownMenu by remember { mutableStateOf(false) } + var showResetConfirmationDialog by remember { mutableStateOf(false) } + var showExportDialog by remember { mutableStateOf(false) } + + if (showResetConfirmationDialog) { + Dialog(onDismissRequest = { showResetConfirmationDialog = false }) { + Surface( + shape = RoundedCornerShape(24.dp), + color = Color.White.copy(alpha = 0.06f), + tonalElevation = 0.dp, + shadowElevation = 16.dp, + border = BorderStroke( + 1.dp, + Brush.linearGradient( + listOf( + PurrfectPalette.glowPrimary.copy(alpha = 0.55f), + PurrfectPalette.glowSecondary.copy(alpha = 0.45f) + ) + ) + ) + ) { + Box(modifier = Modifier.background(PurrfectPalette.cardOverlay)) { + Column( + modifier = Modifier.padding(horizontal = 20.dp, vertical = 18.dp), + verticalArrangement = Arrangement.spacedBy(14.dp) + ) { + Text( + text = context.translation["manager.dialogs.reset_config.title"], + style = MaterialTheme.typography.titleLarge.copy(fontWeight = FontWeight.ExtraBold), + color = Color.White + ) + Text( + text = context.translation["manager.dialogs.reset_config.content"], + style = MaterialTheme.typography.bodyMedium, + color = PurrfectPalette.textSecondary + ) + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.spacedBy(10.dp, Alignment.End) + ) { + Button( + onClick = { showResetConfirmationDialog = false }, + colors = ButtonDefaults.buttonColors( + containerColor = Color.White.copy(alpha = 0.08f), + contentColor = Color.White + ) + ) { + Text(text = context.translation["button.negative"]) + } + Button( + onClick = { + context.config.reset() + context.shortToast(context.translation["manager.dialogs.reset_config.success_toast"]) + showResetConfirmationDialog = false + }, + colors = ButtonDefaults.buttonColors( + containerColor = PurrfectPalette.glowPrimary.copy(alpha = 0.32f), + contentColor = Color.White + ) + ) { + Text(text = context.translation["button.positive"]) + } + } + } + } + } + } + } + + if (showExportDialog) { + SensitiveDataDialog( + onDismiss = { showExportDialog = false }, + onConfirm = { exportSensitiveData -> + showExportDialog = false + routes.configExportSummary.navigate { + put("exportSensitiveData", exportSensitiveData.toString()) + } + } + ) + } + + val actions = remember { + listOf( + Triple(translation["export_option"], Icons.Filled.SaveAlt) { showExportDialog = true }, + Triple(translation["import_option"], Icons.Filled.FileDownload) { + activityLauncher { + openFile("application/json") { uri -> + context.androidContext.contentResolver.openInputStream(Uri.parse(uri))?.use { + routes.configJsonForImport = it.readBytes().toString(Charsets.UTF_8) + routes.navController.navigate(Routes.CONFIG_IMPORT_CONFIRMATION_ROUTE) + } + } + } + }, + Triple(translation["reset_option"], Icons.Filled.Refresh) { showResetConfirmationDialog = true } + ) + } + + val topBarShape = RoundedCornerShape(26.dp) + val topBarBackground = remember { PurrfectPalette.cardOverlay } + val topBarBorder = remember { + Brush.linearGradient( + listOf( + PurrfectPalette.glowPrimary.copy(alpha = 0.6f), + PurrfectPalette.glowSecondary.copy(alpha = 0.52f) + ) + ) + } + + val headerTitle = activeSectionTitle ?: translation["manager.routes.features"] + val subtitleText = when { + isSearchResults -> translation["search_button"] ?: "Search" + !activeSectionSubtitle.isNullOrBlank() -> activeSectionSubtitle + else -> translation["manager.sections.features.subtitle"] ?: "" + } + + LaunchedEffect(isSearchResults, searchKeyword) { + if (isSearchResults || !searchKeyword.isNullOrBlank()) { + showSearchBar = true + if (!searchKeyword.isNullOrBlank()) { + val text = searchKeyword + searchValue = TextFieldValue( + text = text, + selection = TextRange(text.length) + ) + } + } + } + + Box( + modifier = modifier + .fillMaxWidth() + .statusBarsPadding() + .padding(horizontal = 14.dp, vertical = 0.dp) + .zIndex(1f) + ) { + Surface( + modifier = Modifier + .align(Alignment.TopCenter) + .fillMaxWidth(), + shape = topBarShape, + color = PurrfectPalette.cardOverlayColor, + border = BorderStroke(1.dp, topBarBorder), + tonalElevation = 0.dp, + shadowElevation = 8.dp + ) { + Box { + Box( + modifier = Modifier + .matchParentSize() + .clip(topBarShape) + .background(topBarBackground) + ) + Column( + modifier = Modifier + .padding(horizontal = 14.dp, vertical = 12.dp) + ) { + Row( + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(10.dp) + ) { + if (onBack != null) { + IconButton(onClick = onBack) { + Icon( + imageVector = Icons.AutoMirrored.Filled.ArrowBack, + contentDescription = translation["button.back"] ?: "Back", + tint = Color.White + ) + } + } + + if (showSearchBar) { + TextField( + value = searchValue, + onValueChange = { keywordValue -> + searchValue = keywordValue + if (keywordValue.text.isEmpty()) { + updateSearch("", record = false) + } else { + updateSearch(keywordValue.text, record = false) + } + }, + modifier = Modifier + .weight(1f) + .focusRequester(focusRequester), + singleLine = true, + placeholder = { Text(text = translation["search_button"] ?: "Search", color = Color(0xFFE0DCFF)) }, + leadingIcon = { + Icon( + imageVector = Icons.Filled.Search, + contentDescription = null, + tint = Color.White + ) + }, + trailingIcon = { + if (searchValue.text.isNotEmpty()) { + IconButton(onClick = { + searchValue = TextFieldValue("", TextRange(0)) + navigateToMainRoot() + showSearchBar = false + }) { + Icon(Icons.Filled.Close, contentDescription = null, tint = Color.White) + } + } + }, + keyboardActions = KeyboardActions( + onDone = { + updateSearch(searchValue.text, record = true) + } + ), + colors = TextFieldDefaults.colors( + focusedContainerColor = Color.Transparent, + unfocusedContainerColor = Color.Transparent, + focusedIndicatorColor = Color.Transparent, + unfocusedIndicatorColor = Color.Transparent, + cursorColor = Color.White, + focusedTextColor = Color.White, + unfocusedTextColor = Color.White, + disabledTextColor = Color.White.copy(alpha = 0.65f), + focusedPlaceholderColor = Color(0xFFE0DCFF), + unfocusedPlaceholderColor = Color(0xFFE0DCFF), + focusedLeadingIconColor = Color.White, + unfocusedLeadingIconColor = Color.White.copy(alpha = 0.9f), + focusedTrailingIconColor = Color.White, + unfocusedTrailingIconColor = Color.White.copy(alpha = 0.9f) + ) + ) + LaunchedEffect(Unit) { focusRequester.requestFocus() } + } else { + Column(modifier = Modifier.weight(1f)) { + Text( + text = headerTitle ?: "", + color = Color.White, + fontWeight = FontWeight.ExtraBold, + fontSize = 18.sp + ) + Text( + text = subtitleText, + color = Color(0xFFCEC8FF), + fontSize = 12.sp + ) + } + } + + if (!showSearchBar || searchValue.text.isEmpty()) { + IconButton(onClick = { + if (showSearchBar) { + searchValue = TextFieldValue("", TextRange(0)) + navigateToMainRoot() + } + showSearchBar = !showSearchBar + }) { + Icon( + imageVector = if (showSearchBar) Icons.Filled.Close else Icons.Filled.Search, + contentDescription = null, + tint = Color.White + ) + } + } + + if (context.activity != null) { + Box { + IconButton(onClick = { showExportDropdownMenu = !showExportDropdownMenu }) { + Icon( + imageVector = Icons.Filled.MoreVert, + contentDescription = null, + tint = PurrfectPalette.glowSecondary + ) + } + DropdownMenu( + expanded = showExportDropdownMenu, + onDismissRequest = { showExportDropdownMenu = false }, + offset = DpOffset(0.dp, 8.dp), + containerColor = Color(0xFF161821), + shape = RoundedCornerShape(14.dp), + tonalElevation = 8.dp, + shadowElevation = 12.dp + ) { + actions.forEach { (name, icon, action) -> + DropdownMenuItem( + leadingIcon = { + Icon( + imageVector = icon, + contentDescription = null, + tint = PurrfectPalette.glowPrimary + ) + }, + text = { Text(text = name, color = Color.White) }, + onClick = { + action() + showExportDropdownMenu = false + }, + colors = MenuDefaults.itemColors( + textColor = Color.White, + leadingIconColor = PurrfectPalette.glowPrimary + ) + ) + } + } + } + } + } + + if (showSearchBar && combinedSuggestions.isNotEmpty()) { + Spacer(Modifier.height(10.dp)) + FlowRow(horizontalArrangement = Arrangement.spacedBy(8.dp), verticalArrangement = Arrangement.spacedBy(8.dp)) { + combinedSuggestions.forEach { suggestion -> + AssistChip( + onClick = { + searchValue = TextFieldValue(suggestion, TextRange(suggestion.length)) + updateSearch(suggestion, record = true) + }, + label = { Text(text = suggestion, maxLines = 1, overflow = TextOverflow.Ellipsis) }, + leadingIcon = { Icon(Icons.Filled.Search, contentDescription = null, tint = Color.White) }, + colors = AssistChipDefaults.assistChipColors( + containerColor = Color.White.copy(alpha = 0.08f), + labelColor = Color.White, + leadingIconContentColor = Color.White + ) + ) + } + } + if (searchHistory.isNotEmpty()) { + Spacer(Modifier.height(8.dp)) + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.End + ) { + TextButton( + onClick = { + searchHistory.clear() + saveSearchHistory(emptyList()) + } + ) { + Icon(Icons.Filled.Delete, contentDescription = null, tint = Color.White.copy(alpha = 0.85f)) + Spacer(Modifier.width(6.dp)) + Text(text = translation["clear_history"] ?: "Clear history", color = Color.White) + } + } + } + } + } + } + } + } + + } + + @Composable + private fun PropertiesView( + properties: List>, + isSearchResults: Boolean = false, + activeSectionTitle: String? = null, + activeSectionSubtitle: String? = null, + searchKeyword: String? = null, + enableGlobalSearch: Boolean = false, + onBack: (() -> Unit)? = null + ) { + val density = LocalDensity.current + var controlsHeight by remember { mutableStateOf(96.dp) } + val sharedSearchHistory = remember { mutableStateListOf().apply { addAll(loadSearchHistory()) } } + var liveSearchQuery by rememberSaveable { mutableStateOf(searchKeyword.orEmpty()) } + val isActiveSearch = isSearchResults || liveSearchQuery.isNotBlank() + val globalSearchProperties = remember(enableGlobalSearch) { + if (enableGlobalSearch) { + allProperties.map { PropertyPair(it.key, it.value) } + } else { + emptyList() + } + } + val displayProperties = remember(properties, globalSearchProperties, liveSearchQuery, enableGlobalSearch) { + val query = liveSearchQuery + if (query.isBlank()) return@remember properties + val candidates = if (enableGlobalSearch) (properties + globalSearchProperties) else properties + candidates.filter { + it.key.name.contains(query, ignoreCase = true) || + context.translation[it.key.propertyName()].contains(query, ignoreCase = true) || + context.translation[it.key.propertyDescription()].contains(query, ignoreCase = true) + } + } + + LaunchedEffect(searchKeyword) { + if (searchKeyword != null && searchKeyword != liveSearchQuery) { + liveSearchQuery = searchKeyword + } + } + + Box(modifier = Modifier.fillMaxSize()) { + FeatureAuroraBackdrop() + LazyColumn( + modifier = Modifier + .fillMaxSize(), + verticalArrangement = Arrangement.spacedBy(6.dp), + contentPadding = PaddingValues( + start = 6.dp, + end = 6.dp, + top = controlsHeight + 12.dp, + bottom = routes.bottomPadding + ) + ) { + if (displayProperties.isEmpty()) { + item { EmptyState(isActiveSearch) } + } else { + itemsIndexed(displayProperties, key = { _, item -> item.key.propertyName() }) { _, item -> + val onOpen = if (isActiveSearch && liveSearchQuery.isNotBlank()) { + { + upsertHistory(liveSearchQuery, sharedSearchHistory) + } + } else null + PropertyCard(item, onOpen = onOpen) + } + } + item { Spacer(modifier = Modifier.height(12.dp)) } + } + FloatingControls( + isSearchResults = isActiveSearch, + activeSectionTitle = activeSectionTitle, + activeSectionSubtitle = activeSectionSubtitle, + searchKeyword = liveSearchQuery, + searchHistory = sharedSearchHistory, + onSearchQueryChange = { liveSearchQuery = it }, + onBack = onBack, + modifier = Modifier.onGloballyPositioned { + val newHeight = with(density) { it.size.height.toDp() } + if (newHeight != controlsHeight) { + controlsHeight = newHeight + } + } + ) + } + } + + override val floatingActionButton: @Composable () -> Unit = { + fun saveConfig() { + context.coroutineScope.launch(Dispatchers.IO) { + context.config.writeConfig() + context.log.verbose("saved config!") + } + } + + OnLifecycleEvent { _, event -> + if (event == Lifecycle.Event.ON_PAUSE || event == Lifecycle.Event.ON_STOP) { + saveConfig() + } + } + + DisposableEffect(Unit) { + onDispose { + saveConfig() + } + } + } + + + + @Composable + private fun Container( + configContainer: ConfigContainer, + sectionTitle: String? = null, + sectionSubtitle: String? = null, + searchKeyword: String? = null, + onBack: (() -> Unit)? = null, + ) { + PropertiesView( + properties = remember { + configContainer.properties.map { PropertyPair(it.key, it.value) }.filter { + !it.key.params.flags.contains(ConfigFlag.HIDDEN) + } + }, + activeSectionTitle = sectionTitle, + activeSectionSubtitle = sectionSubtitle, + searchKeyword = searchKeyword, + enableGlobalSearch = configContainer == context.config.root, + onBack = onBack + ) + } +} diff --git a/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/features/ManageRuleFeature.kt b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/features/ManageRuleFeature.kt new file mode 100644 index 00000000..81462b66 --- /dev/null +++ b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/features/ManageRuleFeature.kt @@ -0,0 +1,402 @@ +package me.eternal.purrfectsnap.ui.manager.pages.features + +import androidx.compose.foundation.BorderStroke +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.foundation.verticalScroll +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.automirrored.filled.ArrowBack +import androidx.compose.material.icons.filled.DeleteSweep +import androidx.compose.material.icons.filled.GroupAdd +import androidx.compose.material3.Button +import androidx.compose.material3.ButtonDefaults +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.RadioButton +import androidx.compose.material3.RadioButtonDefaults +import androidx.compose.material3.Surface +import androidx.compose.material3.Text +import androidx.compose.runtime.* +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.Brush +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.layout.onGloballyPositioned +import androidx.compose.ui.platform.LocalDensity +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextOverflow +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import androidx.compose.ui.zIndex +import androidx.navigation.NavBackStackEntry +import androidx.navigation.compose.currentBackStackEntryAsState +import kotlinx.coroutines.asCoroutineDispatcher +import kotlinx.coroutines.launch +import me.eternal.purrfectsnap.common.data.MessagingRuleType +import me.eternal.purrfectsnap.common.data.RuleState +import me.eternal.purrfectsnap.common.ui.rememberAsyncMutableState +import me.eternal.purrfectsnap.common.ui.rememberAsyncUpdateDispatcher +import me.eternal.purrfectsnap.storage.clearRuleIds +import me.eternal.purrfectsnap.storage.getRuleIds +import me.eternal.purrfectsnap.storage.setRule +import me.eternal.purrfectsnap.ui.manager.Routes +import me.eternal.purrfectsnap.ui.manager.components.AestheticDialog +import me.eternal.purrfectsnap.ui.manager.components.FloatingTopBar +import me.eternal.purrfectsnap.ui.manager.theme.PurrfectPalette +import me.eternal.purrfectsnap.ui.manager.pages.social.AddFriendDialog +import me.eternal.purrfectsnap.ui.manager.pages.social.AddFriendDialog.Actions + +class ManageRuleFeature : Routes.Route() { + override val title: @Composable () -> Unit = { + val navBackStackEntry by routes.navController.currentBackStackEntryAsState() + val text = remember(navBackStackEntry) { + navBackStackEntry?.arguments?.getString("rule_type")?.let { ruleType -> + MessagingRuleType.getByName(ruleType)?.let { + context.config.root.rules.getPropertyPair(it.key).let { + context.translation[it.key.propertyName()] + } + } + } + } + text?.let { Text(it, maxLines = 1, overflow = TextOverflow.Ellipsis) } + } + + @Composable + fun SelectRuleTypeRadio( + checked: Boolean, + text: String, + onStateChanged: (Boolean) -> Unit, + selectedBlock: @Composable () -> Unit = {}, + ) { + val shape = RoundedCornerShape(22.dp) + val border = if (checked) { + Brush.linearGradient(listOf(PurrfectPalette.glowPrimary.copy(alpha = 0.8f), PurrfectPalette.glowSecondary.copy(alpha = 0.7f))) + } else { + Brush.linearGradient(listOf(Color.White.copy(alpha = 0.12f), Color.White.copy(alpha = 0.12f))) + } + Surface( + shape = shape, + color = Color.White.copy(alpha = 0.04f), + tonalElevation = 0.dp, + shadowElevation = 0.dp, + border = BorderStroke(1.dp, border), + modifier = Modifier + .fillMaxWidth() + .clickable { onStateChanged(!checked) } + ) { + Column( + modifier = Modifier + .background(PurrfectPalette.cardOverlay, shape) + .padding(horizontal = 14.dp, vertical = 12.dp), + verticalArrangement = Arrangement.spacedBy(8.dp), + ) { + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.spacedBy(10.dp), + verticalAlignment = Alignment.CenterVertically, + ) { + RadioButton( + selected = checked, + onClick = null, + colors = RadioButtonDefaults.colors( + selectedColor = PurrfectPalette.glowSecondary, + unselectedColor = Color.White.copy(alpha = 0.7f) + ) + ) + Column(modifier = Modifier.weight(1f)) { + Text(text, color = Color.White, fontWeight = FontWeight.SemiBold, fontSize = 15.sp) + } + } + if (checked) { + Column( + modifier = Modifier + .padding(start = 44.dp, end = 6.dp, bottom = 2.dp), + verticalArrangement = Arrangement.spacedBy(8.dp) + ) { + selectedBlock() + } + } + } + } + } + + override val content: @Composable (NavBackStackEntry) -> Unit = content@{ navBackStackEntry -> + val currentRuleType = navBackStackEntry.arguments?.getString("rule_type")?.let { + MessagingRuleType.getByName(it) + } ?: return@content + + var ruleState by remember { + mutableStateOf(context.config.root.rules.getRuleState(currentRuleType)) + } + + val propertyKeyPair = remember { + context.config.root.rules.getPropertyPair(currentRuleType.key) + } + + val updateDispatcher = rememberAsyncUpdateDispatcher() + val currentRuleIds by rememberAsyncMutableState(defaultValue = mutableListOf(), updateDispatcher = updateDispatcher) { + context.database.getRuleIds(currentRuleType.key) + } + + fun setRuleState(newState: RuleState?) { + ruleState = newState + propertyKeyPair.value.setAny(newState?.key ?: "null") + context.coroutineScope.launch { + context.config.writeConfig(dispatchConfigListener = false) + } + } + + var addFriendDialog by remember { mutableStateOf(null as AddFriendDialog?) } + + LaunchedEffect(addFriendDialog) { + if (addFriendDialog == null) { + updateDispatcher.dispatch() + } + } + + fun showAddFriendDialog() { + addFriendDialog = AddFriendDialog( + context = context, + pinnedIds = currentRuleIds, + actionHandler = Actions( + onFriendState = { friend, state -> + context.database.setRule(friend.userId, currentRuleType.key, state) + if (state) { + currentRuleIds.add(friend.userId) + } else { + currentRuleIds.remove(friend.userId) + } + }, + onGroupState = { group, state -> + context.database.setRule(group.conversationId, currentRuleType.key, state) + if (state) { + currentRuleIds.add(group.conversationId) + } else { + currentRuleIds.remove(group.conversationId) + } + }, + getFriendState = { friend -> + currentRuleIds.contains(friend.userId) + }, + getGroupState = { group -> + currentRuleIds.contains(group.conversationId) + } + ) + ) + } + + if (addFriendDialog != null) { + addFriendDialog?.Content { + addFriendDialog = null + } + } + + var confirmationDialog by remember { mutableStateOf(false) } + if (confirmationDialog) { + AestheticDialog( + onDismissRequest = { confirmationDialog = false }, + title = translation["clear_list_button"], + text = translation["dialog_clear_confirmation_text"], + icon = Icons.Default.DeleteSweep, + confirmButtonText = "Clear", + dismissButtonText = context.translation["button.cancel"], + onDismiss = { confirmationDialog = false }, + onConfirm = { + context.database.clearRuleIds(currentRuleType.key) + context.coroutineScope.launch(context.database.executor.asCoroutineDispatcher()) { + updateDispatcher.dispatch() + } + confirmationDialog = false + }, + opaque = true, + showCloseButton = false + ) + } + + Box( + modifier = Modifier + .fillMaxSize() + .background(PurrfectPalette.backgroundGradient) + ) { + val density = LocalDensity.current + var topBarHeight by remember { mutableStateOf(96.dp) } + FloatingTopBar( + title = remember { context.translation[propertyKeyPair.key.propertyName()] }, + onBack = { routes.navController.popBackStack() }, + modifier = Modifier + .zIndex(2f) + .onGloballyPositioned { + val newHeight = with(density) { it.size.height.toDp() } + if (newHeight != topBarHeight) topBarHeight = newHeight + } + ) + + Column( + modifier = Modifier + .fillMaxSize() + .padding(top = topBarHeight + 10.dp) + .padding(horizontal = 12.dp, vertical = 10.dp) + .verticalScroll(rememberScrollState()), + verticalArrangement = Arrangement.spacedBy(12.dp) + ) { + val headerShape = RoundedCornerShape(22.dp) + Surface( + shape = headerShape, + color = Color.White.copy(alpha = 0.04f), + tonalElevation = 0.dp, + shadowElevation = 0.dp, + border = BorderStroke( + 1.dp, + Brush.linearGradient( + listOf( + PurrfectPalette.glowPrimary.copy(alpha = 0.45f), + PurrfectPalette.glowSecondary.copy(alpha = 0.35f) + ) + ) + ) + ) { + Column( + modifier = Modifier + .background(PurrfectPalette.cardOverlay, headerShape) + .padding(horizontal = 16.dp, vertical = 14.dp), + verticalArrangement = Arrangement.spacedBy(6.dp) + ) { + Text( + text = context.translation[propertyKeyPair.key.propertyDescription()], + fontWeight = FontWeight.Normal, + fontSize = 12.sp, + lineHeight = 16.sp, + color = PurrfectPalette.textSecondary + ) + } + } + + SelectRuleTypeRadio( + checked = ruleState == null, + text = translation["disable_state_option"], + onStateChanged = { setRuleState(null) } + ) { + Text(text = translation["disable_state_subtext"], fontWeight = FontWeight.Normal, fontSize = 12.sp, color = PurrfectPalette.textSecondary) + } + + val manageLabel = when (ruleState) { + RuleState.WHITELIST -> translation["whitelist_state_button"] + RuleState.BLACKLIST -> translation["blacklist_state_button"] + else -> null + } + + SelectRuleTypeRadio( + checked = ruleState == RuleState.WHITELIST, + text = translation["whitelist_state_option"], + onStateChanged = { setRuleState(RuleState.WHITELIST) } + ) { + Text( + text = translation.format("whitelist_state_subtext", "count" to currentRuleIds.size.toString()), + fontWeight = FontWeight.Normal, + fontSize = 12.sp, + color = PurrfectPalette.textSecondary + ) + Button( + onClick = { showAddFriendDialog() }, + colors = ButtonDefaults.buttonColors( + containerColor = PurrfectPalette.glowPrimary.copy(alpha = 0.34f), + contentColor = Color.White + ) + ) { + Text(text = translation["whitelist_state_button"]) + } + } + + SelectRuleTypeRadio( + checked = ruleState == RuleState.BLACKLIST, + text = translation["blacklist_state_option"], + onStateChanged = { setRuleState(RuleState.BLACKLIST) } + ) { + Text( + text = translation.format("blacklist_state_subtext", "count" to currentRuleIds.size.toString()), + fontWeight = FontWeight.Normal, + fontSize = 12.sp, + color = PurrfectPalette.textSecondary + ) + Button( + onClick = { showAddFriendDialog() }, + colors = ButtonDefaults.buttonColors( + containerColor = PurrfectPalette.glowPrimary.copy(alpha = 0.34f), + contentColor = Color.White + ) + ) { + Text(text = translation["blacklist_state_button"]) + } + } + + Surface( + shape = RoundedCornerShape(22.dp), + color = Color.White.copy(alpha = 0.04f), + tonalElevation = 0.dp, + shadowElevation = 0.dp, + border = BorderStroke(1.dp, Color.White.copy(alpha = 0.1f)) + ) { + Row( + modifier = Modifier + .fillMaxWidth() + .background(PurrfectPalette.cardOverlay, RoundedCornerShape(22.dp)) + .padding(horizontal = 14.dp, vertical = 12.dp), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(12.dp) + ) { + Surface( + shape = CircleShape, + color = Color.White.copy(alpha = 0.08f), + border = BorderStroke(1.dp, Color.White.copy(alpha = 0.12f)), + modifier = Modifier.size(46.dp) + ) { + Box( + modifier = Modifier + .fillMaxSize() + .clip(CircleShape) + .background(PurrfectPalette.glowSecondary.copy(alpha = 0.22f)), + contentAlignment = Alignment.Center + ) { + Icon(Icons.Default.DeleteSweep, contentDescription = null, tint = Color.White) + } + } + Column(modifier = Modifier.weight(1f)) { + Text( + text = translation["clear_list_button"], + color = Color.White, + fontWeight = FontWeight.SemiBold, + maxLines = 1, + overflow = TextOverflow.Ellipsis + ) + if (!manageLabel.isNullOrBlank()) { + Text( + text = manageLabel, + color = PurrfectPalette.textSecondary, + fontSize = 12.sp, + maxLines = 1, + overflow = TextOverflow.Ellipsis + ) + } + } + Button( + onClick = { confirmationDialog = true }, + colors = ButtonDefaults.buttonColors( + containerColor = Color.White.copy(alpha = 0.08f), + contentColor = Color.White + ) + ) { + Text(text = "Clear") + } + } + } + + Spacer(modifier = Modifier.height(routes.bottomPadding)) + } + } + } +} diff --git a/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/home/HomeLogs.kt b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/home/HomeLogs.kt new file mode 100644 index 00000000..71a4c3df --- /dev/null +++ b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/home/HomeLogs.kt @@ -0,0 +1,565 @@ +@file:OptIn(androidx.compose.foundation.ExperimentalFoundationApi::class) +package me.eternal.purrfectsnap.ui.manager.pages.home + +import android.net.Uri +import androidx.compose.foundation.BorderStroke +import androidx.compose.foundation.background +import androidx.compose.foundation.gestures.detectTapGestures +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.RowScope +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.WindowInsets +import androidx.compose.foundation.layout.asPaddingValues +import androidx.compose.foundation.layout.fillMaxHeight +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.layout.statusBars +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.LazyListState +import androidx.compose.foundation.lazy.items +import androidx.compose.foundation.ExperimentalFoundationApi +import androidx.compose.material.icons.automirrored.filled.ArrowBack +import androidx.compose.animation.animateContentSize +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.DeleteSweep +import androidx.compose.material.icons.filled.Download +import androidx.compose.material.icons.filled.KeyboardDoubleArrowDown +import androidx.compose.material.icons.filled.KeyboardDoubleArrowUp +import androidx.compose.material.icons.filled.MoreVert +import androidx.compose.material.icons.filled.Refresh +import androidx.compose.material.icons.outlined.BugReport +import androidx.compose.material.icons.outlined.Info +import androidx.compose.material.icons.outlined.Report +import androidx.compose.material.icons.outlined.Warning +import androidx.compose.material3.* +import androidx.compose.runtime.* +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Brush +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.input.pointer.pointerInput +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextOverflow +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.DpOffset +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import androidx.navigation.NavBackStackEntry +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.delay +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext +import me.eternal.purrfectsnap.LogLine +import me.eternal.purrfectsnap.LogReader +import me.eternal.purrfectsnap.common.logger.LogChannel +import me.eternal.purrfectsnap.common.logger.LogLevel +import me.eternal.purrfectsnap.ui.manager.Routes +import me.eternal.purrfectsnap.ui.manager.theme.PurrfectPalette +import me.eternal.purrfectsnap.ui.util.ActivityLauncherHelper +import me.eternal.purrfectsnap.ui.util.pullrefresh.PullRefreshIndicator +import me.eternal.purrfectsnap.ui.util.pullrefresh.pullRefresh +import me.eternal.purrfectsnap.ui.util.pullrefresh.rememberPullRefreshState +import me.eternal.purrfectsnap.ui.util.saveFile +import me.eternal.purrfectsnap.common.util.ktx.copyToClipboard + +class HomeLogs : Routes.Route() { + private val logListState by lazy { LazyListState(0) } + private lateinit var activityLauncherHelper: ActivityLauncherHelper + private val externalRefreshTick = mutableStateOf(0) + override val init: () -> Unit = { + activityLauncherHelper = ActivityLauncherHelper(context.activity!!) + } + + private fun clearLogsAndReload() { + context.coroutineScope.launch { + context.log.clearLogs() + withContext(Dispatchers.Main) { + navigateReload() + } + } + } + + private fun exportLogs() { + activityLauncherHelper.saveFile("purrfectsnap-logs-${System.currentTimeMillis()}.zip", "application/zip") { uri -> + context.coroutineScope.launch { + context.shortToast(translation["saving_logs_toast"]) + context.androidContext.contentResolver.openOutputStream(Uri.parse(uri))?.use { + runCatching { + context.log.exportLogsToZip(it) + context.longToast(translation["saved_logs_success_toast"]) + }.onFailure { error -> + context.longToast(translation["saved_logs_failure_toast"]) + context.log.error("Failed to save logs to $uri!", error) + } + } + } + } + } + + override val topBarActions: @Composable (RowScope.() -> Unit) = {} + override val content: @Composable (NavBackStackEntry) -> Unit = { + val coroutineScope = rememberCoroutineScope() + val composeContext = LocalContext.current + var logReader by remember { mutableStateOf(null) } + val visibleLogs = remember { mutableStateListOf() } + val mainExecutor = remember { context.androidContext.mainExecutor } + var isRefreshing by remember { mutableStateOf(false) } + fun refreshLogs() { + coroutineScope.launch { + val readerResult = withContext(Dispatchers.IO) { + runCatching { + context.log.newReader { line -> + if (shouldHideLog(line)) return@newReader + mainExecutor.execute { + visibleLogs.add(line) + } + } + } + } + readerResult.onFailure { + context.longToast("Failed to read logs!") + } + readerResult.getOrNull()?.let { reader -> + logReader = reader + val filteredLogs = withContext(Dispatchers.IO) { + (0 until reader.lineCount).mapNotNull { index -> + reader.getLogLine(index)?.takeUnless(::shouldHideLog) + } + } + visibleLogs.clear() + visibleLogs.addAll(filteredLogs) + } + delay(220) + if (visibleLogs.isNotEmpty()) { + val targetIndex = (visibleLogs.size - 1).coerceAtLeast(0) + logListState.scrollToItem(targetIndex) + } + isRefreshing = false + } + } + LaunchedEffect(externalRefreshTick.value) { + if (externalRefreshTick.value > 0) { + isRefreshing = true + refreshLogs() + } + } + val pullRefreshState = rememberPullRefreshState(isRefreshing, onRefresh = { + isRefreshing = true + refreshLogs() + }) + LaunchedEffect(Unit) { + isRefreshing = true + refreshLogs() + } + Box( + modifier = Modifier + .fillMaxSize() + .background(PurrfectPalette.backgroundGradient) + .pullRefresh(pullRefreshState) + ) { + Column(modifier = Modifier.fillMaxSize()) { + LogsFloatingBar( + isRefreshing = isRefreshing, + onRefresh = { + isRefreshing = true + refreshLogs() + }, + onExport = { exportLogs() }, + onClear = { clearLogsAndReload() } + ) + Spacer(modifier = Modifier.height(12.dp)) + Surface( + modifier = Modifier + .weight(1f) + .padding(horizontal = 12.dp), + shape = RoundedCornerShape(24.dp), + color = Color.White.copy(alpha = 0.04f), + tonalElevation = 0.dp, + shadowElevation = 0.dp, + border = BorderStroke(1.dp, Color.White.copy(alpha = 0.08f)) + ) { + if (visibleLogs.isEmpty() && logReader != null) { + EmptyLogsState() + } else { + LazyColumn( + modifier = Modifier + .fillMaxSize(), + state = logListState, + verticalArrangement = Arrangement.spacedBy(8.dp), + contentPadding = PaddingValues( + start = 8.dp, + end = 8.dp, + top = 12.dp, + bottom = routes.bottomPadding + 22.dp + ) + ) { + items(visibleLogs, key = { it.hashCode() }) { line -> + LogEntryCard(line = line, composeContext = composeContext) + } + } + } + } + } + PullRefreshIndicator( + refreshing = isRefreshing, + state = pullRefreshState, + modifier = Modifier + .align(Alignment.TopCenter) + .padding(top = WindowInsets.statusBars.asPaddingValues().calculateTopPadding() + 8.dp) + ) + } + } + override val floatingActionButton: @Composable () -> Unit = { + val coroutineScope = rememberCoroutineScope() + Column( + verticalArrangement = Arrangement.spacedBy(5.dp), + ) { + val firstVisibleItem by remember { derivedStateOf { logListState.firstVisibleItemIndex } } + val layoutInfo by remember { derivedStateOf { logListState.layoutInfo } } + Surface( + shape = RoundedCornerShape(18.dp), + color = Color.White.copy(alpha = 0.08f), + tonalElevation = 0.dp, + shadowElevation = 0.dp, + border = BorderStroke(1.dp, Color.White.copy(alpha = 0.12f)) + ) { + Column( + verticalArrangement = Arrangement.spacedBy(6.dp), + modifier = Modifier.padding(6.dp) + ) { + FilledIconButton( + onClick = { + coroutineScope.launch { + logListState.scrollToItem(0) + } + }, + enabled = firstVisibleItem != 0 + ) { + Icon(Icons.Filled.KeyboardDoubleArrowUp, contentDescription = null) + } + FilledIconButton( + onClick = { + coroutineScope.launch { + logListState.scrollToItem((logListState.layoutInfo.totalItemsCount - 1).takeIf { it >= 0 } ?: return@launch) + } + }, + enabled = layoutInfo.visibleItemsInfo.lastOrNull()?.index != layoutInfo.totalItemsCount - 1 + ) { + Icon(Icons.Filled.KeyboardDoubleArrowDown, contentDescription = null) + } + } + } + } + } + + @Composable + private fun LogsFloatingBar( + isRefreshing: Boolean, + onRefresh: () -> Unit, + onExport: () -> Unit, + onClear: () -> Unit + ) { + var showDropDown by remember { mutableStateOf(false) } + val topPadding = WindowInsets.statusBars.asPaddingValues().calculateTopPadding() + Surface( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 14.dp, vertical = 12.dp) + .padding(top = topPadding), + shape = RoundedCornerShape(28.dp), + color = Color.White.copy(alpha = 0.07f), + tonalElevation = 0.dp, + shadowElevation = 0.dp, + border = BorderStroke( + 1.dp, + Brush.linearGradient( + listOf( + PurrfectPalette.glowPrimary.copy(alpha = 0.6f), + PurrfectPalette.glowSecondary.copy(alpha = 0.45f) + ) + ) + ) + ) { + Column( + modifier = Modifier.padding(horizontal = 18.dp, vertical = 16.dp), + verticalArrangement = Arrangement.spacedBy(12.dp) + ) { + Row( + modifier = Modifier.fillMaxWidth(), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.SpaceBetween + ) { + Row( + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(10.dp) + ) { + IconButton(onClick = { routes.navController.popBackStack() }) { + Icon(Icons.AutoMirrored.Filled.ArrowBack, contentDescription = null, tint = Color.White) + } + Text( + text = routeInfo.translatedKey?.value ?: translation["manager.routes.home_logs"] ?: "Logs", + color = PurrfectPalette.textPrimary, + fontSize = 18.sp, + fontWeight = FontWeight.ExtraBold + ) + } + Row( + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(6.dp) + ) { + if (isRefreshing) { + CircularProgressIndicator( + modifier = Modifier.size(18.dp), + strokeWidth = 2.dp, + color = PurrfectPalette.glowSecondary + ) + } + IconButton(onClick = onRefresh) { + Icon(Icons.Filled.Refresh, contentDescription = "Refresh", tint = Color.White) + } + Box { + IconButton(onClick = { showDropDown = true }) { + Icon(Icons.Filled.MoreVert, contentDescription = null, tint = PurrfectPalette.glowSecondary) + } + DropdownMenu( + expanded = showDropDown, + onDismissRequest = { showDropDown = false }, + offset = DpOffset(0.dp, 8.dp), + containerColor = Color(0xFF161821), + tonalElevation = 8.dp, + shadowElevation = 12.dp, + shape = RoundedCornerShape(14.dp) + ) { + DropdownMenuItem( + onClick = { + onClear() + showDropDown = false + }, + leadingIcon = { Icon(Icons.Filled.DeleteSweep, contentDescription = null, tint = PurrfectPalette.glowPrimary) }, + text = { Text(translation["clear_logs_button"], color = Color.White) }, + colors = MenuDefaults.itemColors( + textColor = Color.White, + leadingIconColor = PurrfectPalette.glowPrimary + ) + ) + DropdownMenuItem( + onClick = { + onExport() + showDropDown = false + }, + leadingIcon = { Icon(Icons.Filled.Download, contentDescription = null, tint = PurrfectPalette.glowSecondary) }, + text = { Text(translation["export_logs_button"], color = Color.White) }, + colors = MenuDefaults.itemColors( + textColor = Color.White, + leadingIconColor = PurrfectPalette.glowSecondary + ) + ) + } + } + } + } + } + } + } + + @Composable + private fun EmptyLogsState() { + Column( + modifier = Modifier + .fillMaxSize() + .padding(horizontal = 18.dp), + verticalArrangement = Arrangement.Center, + horizontalAlignment = Alignment.CenterHorizontally + ) { + Surface( + shape = RoundedCornerShape(50), + color = Color.White.copy(alpha = 0.1f), + tonalElevation = 0.dp, + shadowElevation = 0.dp, + border = BorderStroke(1.dp, Color.White.copy(alpha = 0.18f)) + ) { + Icon( + imageVector = Icons.Outlined.Info, + contentDescription = null, + tint = Color.White, + modifier = Modifier.padding(14.dp) + ) + } + Spacer(modifier = Modifier.height(12.dp)) + Text( + text = translation["no_logs_hint"], + color = PurrfectPalette.textPrimary, + fontWeight = FontWeight.SemiBold, + fontSize = 15.sp, + textAlign = TextAlign.Center + ) + Text( + text = "Pull to refresh or trigger an action to see new entries.", + color = PurrfectPalette.textSecondary, + fontSize = 13.sp, + textAlign = TextAlign.Center, + modifier = Modifier.padding(top = 6.dp) + ) + } + } + + @Composable + private fun LogEntryCard(line: LogLine, composeContext: android.content.Context) { + // Normalize overly fragmented log text (some entries were rendered with one character per line) + val normalizedMessage = remember(line.message) { + val cleaned = line.message.replace("\r", "") + val fragments = cleaned.lines() + if (fragments.size > 3 && fragments.count { it.length <= 2 } > fragments.size / 2) { + fragments.joinToString("") { it.trim() } + } else { + cleaned + } + } + val levelColor = logLevelColor(line.logLevel) + Surface( + modifier = Modifier + .fillMaxWidth() + .animateContentSize() + .pointerInput(line.hashCode()) { + detectTapGestures( + onLongPress = { + composeContext.copyToClipboard(line.message) + } + ) + }, + shape = RoundedCornerShape(18.dp), + color = Color.White.copy(alpha = 0.05f), + tonalElevation = 0.dp, + shadowElevation = 0.dp, + border = BorderStroke(1.dp, levelColor.copy(alpha = 0.4f)) + ) { + Row( + modifier = Modifier + .fillMaxWidth() + ) { + Box( + modifier = Modifier + .width(6.dp) + .fillMaxHeight() + .background( + Brush.verticalGradient( + listOf(levelColor, levelColor.copy(alpha = 0.35f)) + ), + shape = RoundedCornerShape(topStart = 18.dp, bottomStart = 18.dp) + ) + ) + Column( + modifier = Modifier + .padding(horizontal = 12.dp, vertical = 10.dp) + .fillMaxWidth(), + verticalArrangement = Arrangement.spacedBy(6.dp) + ) { + Row( + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(10.dp), + modifier = Modifier.fillMaxWidth() + ) { + Surface( + shape = RoundedCornerShape(12.dp), + color = levelColor.copy(alpha = 0.18f), + tonalElevation = 0.dp, + shadowElevation = 0.dp, + border = BorderStroke(1.dp, levelColor.copy(alpha = 0.45f)) + ) { + Row( + modifier = Modifier.padding(horizontal = 10.dp, vertical = 6.dp), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(6.dp) + ) { + Icon( + imageVector = logLevelIcon(line.logLevel), + contentDescription = null, + tint = levelColor, + modifier = Modifier.size(16.dp) + ) + Text( + text = logLevelLabel(line.logLevel), + color = levelColor, + fontWeight = FontWeight.Bold, + fontSize = 12.sp + ) + } + } + Column( + modifier = Modifier.weight(1f), + verticalArrangement = Arrangement.spacedBy(2.dp) + ) { + Text( + text = LogChannel.fromChannel(line.tag)?.shortName ?: line.tag, + fontWeight = FontWeight.SemiBold, + color = PurrfectPalette.textPrimary, + fontSize = 13.sp, + maxLines = 1, + overflow = TextOverflow.Ellipsis + ) + Text( + text = line.dateTime, + color = PurrfectPalette.textSecondary, + fontSize = 11.sp + ) + } + } + Text( + text = normalizedMessage, + color = Color.White, + lineHeight = 16.sp, + fontSize = 12.sp, + modifier = Modifier.fillMaxWidth() + ) + } + } + } + } + + private fun logLevelColor(logLevel: LogLevel): Color = when (logLevel) { + LogLevel.DEBUG -> PurrfectPalette.glowSecondary + LogLevel.INFO, LogLevel.VERBOSE -> Color(0xFFA3F0C2) + LogLevel.WARN -> Color(0xFFFFD782) + LogLevel.ERROR, LogLevel.ASSERT -> Color(0xFFFF9CAB) + } + + private fun logLevelLabel(logLevel: LogLevel): String = when (logLevel) { + LogLevel.DEBUG -> "Debug" + LogLevel.INFO -> "Info" + LogLevel.VERBOSE -> "Verbose" + LogLevel.WARN -> "Warning" + LogLevel.ERROR -> "Error" + LogLevel.ASSERT -> "Assert" + } + + private fun logLevelIcon(logLevel: LogLevel) = when (logLevel) { + LogLevel.DEBUG -> Icons.Outlined.BugReport + LogLevel.ERROR, LogLevel.ASSERT -> Icons.Outlined.Report + LogLevel.INFO, LogLevel.VERBOSE -> Icons.Outlined.Info + LogLevel.WARN -> Icons.Outlined.Warning + } + + private fun shouldHideLog(line: LogLine): Boolean { + val message = line.message.lowercase() + val tag = line.tag.lowercase() + return message.startsWith("blocked ep") || + message.startsWith("allowed ep") || + message.startsWith("blocked call") || + message.contains("detection keyword matched") || + message.startsWith("enc:v1:") || + message.contains("endpointsblocker") || + tag.contains("endpointsblocker") || + message.contains("securityfeatures") || + tag.contains("securityfeatures") + } +} 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 new file mode 100644 index 00000000..4b589739 --- /dev/null +++ b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/home/HomeRootSection.kt @@ -0,0 +1,1127 @@ +package me.eternal.purrfectsnap.ui.manager.pages.home + +import android.content.SharedPreferences +import androidx.compose.animation.AnimatedContent +import androidx.compose.animation.ExperimentalAnimationApi +import androidx.compose.animation.core.LinearEasing +import androidx.compose.animation.core.RepeatMode +import androidx.compose.animation.core.animateFloat +import androidx.compose.animation.core.Spring +import androidx.compose.animation.core.animateFloatAsState +import androidx.compose.animation.core.infiniteRepeatable +import androidx.compose.animation.core.rememberInfiniteTransition +import androidx.compose.animation.core.spring +import androidx.compose.animation.core.tween +import androidx.compose.foundation.BorderStroke +import androidx.compose.foundation.Canvas +import androidx.compose.foundation.ExperimentalFoundationApi +import androidx.compose.foundation.LocalIndication +import androidx.compose.foundation.background +import androidx.compose.foundation.border +import androidx.compose.foundation.clickable +import androidx.compose.foundation.gestures.detectDragGestures +import androidx.compose.foundation.interaction.MutableInteractionSource +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.BoxWithConstraints +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.ColumnScope +import androidx.compose.foundation.layout.ExperimentalLayoutApi +import androidx.compose.foundation.layout.FlowRow +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.RowScope +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.WindowInsets +import androidx.compose.foundation.layout.asPaddingValues +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.navigationBars +import androidx.compose.foundation.layout.offset +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.statusBars +import androidx.compose.foundation.layout.wrapContentWidth +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.foundation.verticalScroll +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.automirrored.filled.Help +import androidx.compose.material.icons.filled.Add +import androidx.compose.material.icons.filled.Bolt +import androidx.compose.material.icons.filled.BugReport +import androidx.compose.material.icons.filled.Check +import androidx.compose.material.icons.filled.Close +import androidx.compose.material.icons.filled.Download +import androidx.compose.material.icons.filled.DragHandle +import androidx.compose.material.icons.filled.Schedule +import androidx.compose.material.icons.filled.Settings +import androidx.compose.material.icons.outlined.Widgets +import androidx.compose.material3.Button +import androidx.compose.material3.ButtonDefaults +import androidx.compose.material3.CircularProgressIndicator +import androidx.compose.material3.ElevatedCard +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.Icon +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.OutlinedButton +import androidx.compose.material3.Surface +import androidx.compose.material3.Text +import androidx.compose.material3.surfaceColorAtElevation +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.State +import androidx.compose.runtime.DisposableEffect +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.mutableIntStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.draw.clipToBounds +import androidx.compose.ui.geometry.Offset +import androidx.compose.ui.geometry.Rect +import androidx.compose.ui.geometry.Size +import androidx.compose.ui.graphics.Brush +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.input.pointer.pointerInput +import androidx.compose.ui.layout.onGloballyPositioned +import androidx.compose.ui.platform.LocalDensity +import androidx.compose.ui.res.vectorResource +import androidx.compose.ui.text.SpanStyle +import androidx.compose.ui.text.buildAnnotatedString +import androidx.compose.ui.text.font.Font +import androidx.compose.ui.text.font.FontFamily +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.text.style.TextOverflow +import androidx.compose.ui.text.withLink +import androidx.compose.ui.text.withStyle +import androidx.compose.ui.unit.Dp +import androidx.compose.ui.unit.IntOffset +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import androidx.compose.ui.zIndex +import androidx.navigation.NavBackStackEntry +import kotlin.math.roundToInt +import kotlinx.coroutines.delay +import kotlinx.coroutines.launch +import me.eternal.purrfectsnap.R +import me.eternal.purrfectsnap.action.EnumQuickActions +import me.eternal.purrfectsnap.common.BuildConfig +import me.eternal.purrfectsnap.common.action.EnumAction +import me.eternal.purrfectsnap.common.ui.rememberAsyncMutableState +import me.eternal.purrfectsnap.common.ui.rememberAsyncMutableStateList +import me.eternal.purrfectsnap.common.util.ktx.openLink +import me.eternal.purrfectsnap.storage.getQuickTiles +import me.eternal.purrfectsnap.storage.setQuickTiles +import me.eternal.purrfectsnap.ui.manager.Routes +import me.eternal.purrfectsnap.ui.manager.theme.PurrfectPalette +import me.eternal.purrfectsnap.ui.manager.data.UpdateDownloader +import me.eternal.purrfectsnap.ui.manager.data.Updater +import me.eternal.purrfectsnap.ui.util.ActivityLauncherHelper +import me.eternal.purrfectsnap.ui.util.AlertDialogs +import me.eternal.purrfectsnap.ui.util.scaleOnPress + +class HomeRootSection : Routes.Route() { + override val translation by lazy { context.translation.getCategory("manager.sections.home") } + + companion object { + val cardMargin = 10.dp + val pageBackgroundGradient = Brush.verticalGradient( + listOf( + Color(0xFF261F58), + Color(0xFF302A6D), + Color(0xFF241F52) + ) + ) + } + + private val heroGradientColors = listOf( + Color(0xFF5C4B99), + Color(0xFF322B5E), + Color(0xFF1B1836) + ) + private val quickActionsGradientColors = listOf( + Color(0xFF241C3E), + Color(0xFF151127) + ) + private lateinit var activityLauncherHelper: ActivityLauncherHelper + data class QaCard(val id: String, val name: String, val icon: ImageVector, val action: (Routes) -> Unit) + private val cardEntries by lazy { + val list = mutableListOf() + EnumQuickActions.entries.forEach { q -> + val name = context.translation["actions.${q.key}.name"] + list.add(QaCard(id = "quick.${q.key}", name = name, icon = q.icon, action = q.action)) + } + EnumAction.entries.forEach { a -> + val name = context.translation["actions.${a.key}.name"] + list.add(QaCard(id = "action.${a.key}", name = name, icon = a.icon, action = { context.launchActionIntent(a) })) + } + list + } + private val cards by lazy { + EnumQuickActions.entries.map { + (context.translation["actions.${it.key}.name"] to it.icon) to it.action + }.associate { + it.first to it.second + }.toMutableMap().apply { + EnumAction.entries.forEach { action -> + this[context.translation["actions.${action.key}.name"] to action.icon] = { + context.launchActionIntent(action) + } + } + } + } + + @Composable + private fun rememberPreferenceBool(key: String, default: Boolean = false): State { + val prefs = remember { context.sharedPreferences } + val state = remember { mutableStateOf(prefs.getBoolean(key, default)) } + DisposableEffect(prefs, key) { + val listener = SharedPreferences.OnSharedPreferenceChangeListener { _, changedKey -> + if (changedKey == key) { + state.value = prefs.getBoolean(key, default) + } + } + prefs.registerOnSharedPreferenceChangeListener(listener) + onDispose { prefs.unregisterOnSharedPreferenceChangeListener(listener) } + } + return state + } + + @Composable + fun ExternalLinkIcon( + modifier: Modifier = Modifier, + size: Dp = 44.dp, + imageVector: ImageVector, + onClick: (() -> Unit)? = null, + tint: Color = MaterialTheme.colorScheme.onSurfaceVariant, + containerColor: Color = MaterialTheme.colorScheme.primary.copy(alpha = 0.08f), + ) { + val interactionSource = remember { MutableInteractionSource() } + val clickModifier = if (onClick != null) { + Modifier.clickable( + interactionSource = interactionSource, + indication = LocalIndication.current + ) { onClick() } + } else { + Modifier + } + Box( + modifier = modifier + .size(size) + .clip(RoundedCornerShape(50)) + .background(containerColor) + .scaleOnPress(interactionSource) + .then(clickModifier) + ) { + Icon( + imageVector = imageVector, + contentDescription = null, + tint = tint, + modifier = Modifier + .align(Alignment.Center) + .size(size * 0.55f) + ) + } + } + + @Composable + private fun HeroBadge(text: String) { + Text( + text = text, + color = Color.White, + fontSize = 12.sp, + fontWeight = FontWeight.SemiBold, + modifier = Modifier + .clip(RoundedCornerShape(50)) + .background(Color.White.copy(alpha = 0.15f)) + .padding(horizontal = 14.dp, vertical = 6.dp) + ) + } + + @Composable + private fun TopBarActionChip( + icon: ImageVector, + label: String, + onClick: () -> Unit, + ) { + Surface( + shape = RoundedCornerShape(40), + color = Color.White.copy(alpha = 0.06f), + border = BorderStroke(1.dp, Color.White.copy(alpha = 0.12f)) + ) { + Row( + modifier = Modifier + .clip(RoundedCornerShape(40)) + .clickable(onClick = onClick) + .padding(horizontal = 14.dp, vertical = 8.dp), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(8.dp) + ) { + Icon(icon, contentDescription = label, tint = Color.White) + Text( + text = label, + color = Color.White, + fontSize = 13.sp, + fontWeight = FontWeight.Medium + ) + } + } + } + + @Composable + private fun RowScope.HomeActionChips() { + TopBarActionChip( + icon = Icons.Filled.BugReport, + label = context.translation["manager.routes.home_logs"] + ) { routes.homeLogs.navigate() } + TopBarActionChip( + icon = Icons.Filled.Settings, + label = context.translation["manager.routes.home_settings"] + ) { routes.settings.navigate() } + } + + + @Composable + private fun AuroraBackground() { + val infiniteTransition = rememberInfiniteTransition(label = "aurora") + val driftX by infiniteTransition.animateFloat( + initialValue = -120f, + targetValue = 220f, + animationSpec = infiniteRepeatable( + animation = tween(durationMillis = 16000, easing = LinearEasing), + repeatMode = RepeatMode.Reverse + ), + label = "driftX" + ) + val driftY by infiniteTransition.animateFloat( + initialValue = 80f, + targetValue = -140f, + animationSpec = infiniteRepeatable( + animation = tween(durationMillis = 14000, easing = LinearEasing), + repeatMode = RepeatMode.Reverse + ), + label = "driftY" + ) + val shimmer by infiniteTransition.animateFloat( + initialValue = -120f, + targetValue = 160f, + animationSpec = infiniteRepeatable( + animation = tween(durationMillis = 11000, easing = LinearEasing), + repeatMode = RepeatMode.Reverse + ), + label = "shimmer" + ) + + val primaryGlow = MaterialTheme.colorScheme.primary.copy(alpha = 0.28f) + val tertiaryGlow = MaterialTheme.colorScheme.tertiary.copy(alpha = 0.22f) + val trailGradient = listOf( + MaterialTheme.colorScheme.primary.copy(alpha = 0.18f), + MaterialTheme.colorScheme.secondary.copy(alpha = 0.16f), + MaterialTheme.colorScheme.tertiary.copy(alpha = 0.14f) + ) + + Canvas(modifier = Modifier.fillMaxSize()) { + drawCircle( + brush = Brush.radialGradient( + colors = listOf(primaryGlow, Color.Transparent), + center = Offset( + x = size.width * 0.25f + driftX, + y = size.height * 0.18f + driftY * 0.4f + ), + radius = size.minDimension * 0.9f + ), + alpha = 0.85f + ) + drawCircle( + brush = Brush.radialGradient( + colors = listOf(tertiaryGlow, Color.Transparent), + center = Offset( + x = size.width * 0.78f - driftX * 0.45f, + y = size.height * 0.72f + ), + radius = size.minDimension * 0.95f + ), + alpha = 0.9f + ) + drawRect( + brush = Brush.linearGradient( + colors = trailGradient, + start = Offset(x = 0f, y = size.height * 0.15f + shimmer), + end = Offset(x = size.width, y = size.height * 0.9f + shimmer) + ), + size = this.size, + alpha = 0.24f + ) + } + } + + @OptIn(ExperimentalLayoutApi::class) + @Composable + private fun HeroSection( + versionName: String, + latestUpdate: Updater.LatestRelease?, + downloadState: UpdateDownloader.DownloadState, + downloadProgress: Float, + onUpdateAction: () -> Unit, + isPurrAuraActive: Boolean, + onWikiClick: () -> Unit, + onTelegramClick: () -> Unit, + onGithubClick: () -> Unit, + authorName: String, + onManageClick: () -> Unit, + avenirNext: FontFamily + ) { + val heroShape = RoundedCornerShape(36.dp) + Box( + modifier = Modifier + .padding(horizontal = cardMargin, vertical = 6.dp) + .clip(heroShape) + .background( + Brush.linearGradient( + heroGradientColors + ) + ) + .border(1.dp, Color.White.copy(alpha = 0.1f), heroShape) + ) { + Column( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 20.dp, vertical = 22.dp), + verticalArrangement = Arrangement.spacedBy(16.dp), + horizontalAlignment = Alignment.CenterHorizontally + ) { + Column( + verticalArrangement = Arrangement.spacedBy(6.dp), + horizontalAlignment = Alignment.CenterHorizontally + ) { + Text( + text = "PurrfectSnap", + color = Color.White, + fontSize = 34.sp, + fontWeight = FontWeight.ExtraBold, + fontFamily = avenirNext + ) + Text( + text = "by $authorName", + color = Color.White.copy(alpha = 0.75f), + fontSize = 14.sp + ) + Text( + text = "An Xposed Module meant to enhance your Snapchat experience", + color = Color.White.copy(alpha = 0.9f), + fontSize = 15.sp, + lineHeight = 20.sp, + textAlign = TextAlign.Center + ) + } + FlowRow( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.spacedBy(12.dp, Alignment.CenterHorizontally), + verticalArrangement = Arrangement.spacedBy(10.dp) + ) { + HeroBadge("Codename: Rass Malayi") + HeroBadge("Debug Build") + } + + Surface( + color = Color.White.copy(alpha = 0.08f), + shape = RoundedCornerShape(24.dp), + border = BorderStroke(1.dp, Color.White.copy(alpha = 0.10f)), + tonalElevation = 0.dp, + shadowElevation = 0.dp + ) { + Column( + modifier = Modifier + .fillMaxWidth() + .padding(16.dp), + verticalArrangement = Arrangement.spacedBy(12.dp), + horizontalAlignment = Alignment.CenterHorizontally + ) { + Surface( + shape = RoundedCornerShape(50), + color = Color.White.copy(alpha = 0.06f), + border = BorderStroke(1.dp, Color.White.copy(alpha = 0.10f)), + tonalElevation = 0.dp, + shadowElevation = 0.dp + ) { + Row( + modifier = Modifier.padding(horizontal = 14.dp, vertical = 10.dp), + horizontalArrangement = Arrangement.spacedBy(10.dp), + verticalAlignment = Alignment.CenterVertically + ) { + Box( + modifier = Modifier + .size(14.dp) + .clip(RoundedCornerShape(50)) + .background(if (isPurrAuraActive) PurrfectPalette.glowPrimary else Color(0xFF8C8CA3)) + ) + Text( + text = if (isPurrAuraActive) "PurrAura Active!" else "PurrAura Inactive", + color = Color.White, + fontWeight = FontWeight.Bold, + fontSize = 14.sp + ) + } + } + + OutlinedButton( + onClick = onManageClick, + border = BorderStroke(1.dp, Color.White.copy(alpha = 0.3f)), + colors = ButtonDefaults.outlinedButtonColors(contentColor = Color.White), + modifier = Modifier.align(Alignment.CenterHorizontally) + ) { + Icon(Icons.Filled.Settings, contentDescription = null, tint = Color.White) + Spacer(modifier = Modifier.width(6.dp)) + Text("Open Settings") + } + } + } + + Surface( + modifier = Modifier.fillMaxWidth(), + shape = RoundedCornerShape(26.dp), + color = Color.White.copy(alpha = 0.06f), + border = BorderStroke(1.dp, Color.White.copy(alpha = 0.10f)), + tonalElevation = 0.dp, + shadowElevation = 0.dp + ) { + Row( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 12.dp, vertical = 10.dp), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(10.dp) + ) { + Button( + modifier = Modifier.weight(1f), + onClick = onWikiClick, + colors = ButtonDefaults.buttonColors( + containerColor = Color.White, + contentColor = Color(0xFF1B152E) + ) + ) { + Icon(Icons.AutoMirrored.Filled.Help, contentDescription = null, modifier = Modifier.size(18.dp)) + Spacer(modifier = Modifier.width(8.dp)) + Text(text = "Wiki", maxLines = 1, overflow = TextOverflow.Ellipsis) + } + OutlinedButton( + modifier = Modifier.weight(1f), + onClick = onGithubClick, + border = BorderStroke(1.dp, Color.White.copy(alpha = 0.35f)), + colors = ButtonDefaults.outlinedButtonColors(contentColor = Color.White) + ) { + Icon( + imageVector = ImageVector.vectorResource(id = R.drawable.ic_github), + contentDescription = null, + tint = Color.White, + modifier = Modifier.size(18.dp) + ) + Spacer(modifier = Modifier.width(6.dp)) + Text(text = "GitHub", maxLines = 1, overflow = TextOverflow.Ellipsis) + } + ExternalLinkIcon( + imageVector = ImageVector.vectorResource(id = R.drawable.ic_telegram), + onClick = onTelegramClick, + tint = Color.White, + containerColor = Color.White.copy(alpha = 0.14f) + ) + } + } + } + } + } + private fun resolveTileKey(name: String): String { + val entry = cardEntries.firstOrNull { it.name == name } + return entry?.id ?: name + } + private fun getTileSpan(name: String): Pair { + val prefs = context.sharedPreferences + val key = resolveTileKey(name) + val raw = prefs.getString("quick_tile_size_$key", null) ?: "1x1" + val parts = raw.split('x') + val w = parts.getOrNull(0)?.toIntOrNull()?.coerceIn(1, 3) ?: 1 + val h = parts.getOrNull(1)?.toIntOrNull()?.coerceIn(1, 3) ?: 1 + return w to h + } + private fun setTileSpan(name: String, w: Int, h: Int) { + val prefs = context.sharedPreferences + val key = resolveTileKey(name) + prefs.edit().putString("quick_tile_size_$key", "${w.coerceIn(1,3)}x${h.coerceIn(1,3)}").apply() + } + private fun clearTileSpan(name: String) { + val prefs = context.sharedPreferences + val key = resolveTileKey(name) + prefs.edit().remove("quick_tile_size_$key").apply() + } + + private fun getTileOffset(name: String): Pair { + val prefs = context.sharedPreferences + val key = resolveTileKey(name) + val raw = prefs.getString("quick_tile_offset_$key", null) + if (raw == null) return 0f to 0f + val parts = raw.split(',') + val x = parts.getOrNull(0)?.toFloatOrNull() ?: 0f + val y = parts.getOrNull(1)?.toFloatOrNull() ?: 0f + return x to y + } + + private fun setTileOffset(name: String, x: Float, y: Float) { + val prefs = context.sharedPreferences + val key = resolveTileKey(name) + prefs.edit().putString("quick_tile_offset_$key", "$x,$y").apply() + } + + private fun clearTileOffset(name: String) { + val prefs = context.sharedPreferences + val key = resolveTileKey(name) + prefs.edit().remove("quick_tile_offset_$key").apply() + } + + override val title: @Composable (() -> Unit)? = {} + override val init: () -> Unit = { + activityLauncherHelper = ActivityLauncherHelper(context.activity!!) + } + override val topBarActions: @Composable (RowScope.() -> Unit) = { + Row( + horizontalArrangement = Arrangement.spacedBy(10.dp), + verticalAlignment = Alignment.CenterVertically, + modifier = Modifier.fillMaxWidth(), + ) { + Spacer(modifier = Modifier.weight(1f)) + HomeActionChips() + } + } + + + @OptIn(ExperimentalLayoutApi::class, ExperimentalAnimationApi::class, ExperimentalFoundationApi::class, ExperimentalMaterial3Api::class) + override val content: @Composable (NavBackStackEntry) -> Unit = { + val avenirNext = remember { + FontFamily(Font(R.font.avenir_next_medium, FontWeight.Medium)) + } + val selectedTiles = rememberAsyncMutableStateList(defaultValue = listOf()) { + context.database.getQuickTiles().filter { it.isNotBlank() } + } + val latestUpdate by rememberAsyncMutableState(defaultValue = null) { Updater.latestRelease } + val downloadState by UpdateDownloader.downloadState.collectAsState() + val downloadProgress by UpdateDownloader.downloadProgress.collectAsState() + val coroutineScope = rememberCoroutineScope() + val isPurrAuraActive by rememberPreferenceBool("debug_test_mode", true) + + val handleUpdateAction: () -> Unit = { + latestUpdate?.let { latest -> + val supportedAbis = android.os.Build.SUPPORTED_ABIS + var abiName: String? = null + for (abi in supportedAbis) { + when (abi) { + "arm64-v8a" -> { + abiName = "armv8" + break + } + "armeabi-v7a" -> { + abiName = "armv7" + break + } + } + } + + if (latest.workflowId == null) { + context.androidContext.openLink(latest.releaseUrl) + } else if (abiName == null) { + android.widget.Toast.makeText( + context.androidContext, + "Your device architecture is not supported for automatic updates.", + android.widget.Toast.LENGTH_LONG + ).show() + } else { + val artifactName = "purrfectsnap-${abiName}-debug" + val downloadUrl = "https://nightly.link/particle-box/PurrfectSnap/actions/runs/${latest.workflowId}/$artifactName.zip" + UpdateDownloader.downloadAndInstall(context.androidContext, downloadUrl, "$artifactName.zip", coroutineScope) + } + } + } + + var showQuickActionsMenu by remember { mutableStateOf(false) } + var editMode by remember { mutableStateOf(false) } + val scrollState = rememberScrollState() + val statusBarPadding = WindowInsets.statusBars.asPaddingValues().calculateTopPadding() + val navigationBarPadding = WindowInsets.navigationBars.asPaddingValues().calculateBottomPadding() + val density = LocalDensity.current + val contentBottomPadding = routes.bottomPadding + navigationBarPadding + 96.dp + + Box( + modifier = Modifier + .fillMaxSize() + .background(pageBackgroundGradient) + ) { + Column( + modifier = Modifier + .fillMaxSize() + .verticalScroll(scrollState, enabled = !editMode) + .padding(bottom = contentBottomPadding) + ) { + Row( + modifier = Modifier + .fillMaxWidth() + .padding(WindowInsets.statusBars.asPaddingValues()) + .padding(horizontal = cardMargin, vertical = 8.dp), + horizontalArrangement = Arrangement.spacedBy(10.dp), + verticalAlignment = Alignment.CenterVertically + ) { + Spacer(modifier = Modifier.weight(1f)) + HomeActionChips() + } + Spacer(modifier = Modifier.height(4.dp)) + HeroSection( + versionName = BuildConfig.VERSION_NAME, + latestUpdate = latestUpdate, + downloadState = downloadState, + downloadProgress = downloadProgress, + onUpdateAction = handleUpdateAction, + isPurrAuraActive = isPurrAuraActive, + onWikiClick = { context.androidContext.openLink("https://github.com/particle-box/PurrfectSnap/wiki") }, + onTelegramClick = { context.androidContext.openLink("https://t.me/purrfectsnap_official") }, + onGithubClick = { context.androidContext.openLink("https://github.com/particle-box/PurrfectSnap") }, + authorName = "ΞTΞRNAL", + onManageClick = { routes.settings.navigate() }, + avenirNext = avenirNext, + ) + Spacer(modifier = Modifier.height(12.dp)) + AnimatedContent(targetState = selectedTiles.isNotEmpty(), label = "QuickActionsAnim") { hasQuickActions -> + val quickCardShape = RoundedCornerShape(34.dp) + Surface( + modifier = Modifier + .padding(horizontal = cardMargin, vertical = 10.dp), + shape = quickCardShape, + tonalElevation = 0.dp, + shadowElevation = 24.dp, + color = Color.Transparent, + border = BorderStroke(1.dp, Color.White.copy(alpha = 0.05f)) + ) { + Column( + modifier = Modifier + .fillMaxWidth() + .background(Brush.linearGradient(quickActionsGradientColors)) + .padding(horizontal = 24.dp, vertical = 28.dp) + .padding(bottom = navigationBarPadding + 32.dp), + horizontalAlignment = Alignment.CenterHorizontally + ) { + if (!hasQuickActions) { + Text( + translation["quick_actions_title"], + fontSize = 18.sp, + fontWeight = FontWeight.SemiBold, + color = Color.White.copy(alpha = 0.85f), + maxLines = 1, + overflow = TextOverflow.Ellipsis, + modifier = Modifier.fillMaxWidth() + ) + Spacer(modifier = Modifier.height(24.dp)) + Column( + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.Center, + modifier = Modifier.fillMaxWidth() + ) { + Icon( + imageVector = Icons.Outlined.Widgets, + contentDescription = translation["quick_actions_icon_description"], + modifier = Modifier.size(72.dp), + tint = Color.White + ) + Spacer(modifier = Modifier.height(16.dp)) + Text( + text = "No quick tiles yet", + fontSize = 20.sp, + fontWeight = FontWeight.Bold, + color = Color.White + ) + Spacer(modifier = Modifier.height(8.dp)) + Text( + text = "Design your dream grid with the actions you use the most.", + fontSize = 14.sp, + color = Color.White.copy(alpha = 0.75f), + textAlign = TextAlign.Center + ) + Spacer(modifier = Modifier.height(20.dp)) + Button( + onClick = { showQuickActionsMenu = true }, + colors = ButtonDefaults.buttonColors( + containerColor = Color.White, + contentColor = Color(0xFF1B152E) + ) + ) { + Icon( + imageVector = Icons.Default.Add, + contentDescription = translation["add_quick_action_description"], + modifier = Modifier.size(20.dp) + ) + Spacer(modifier = Modifier.width(6.dp)) + Text(text = "Add tile") + } + } + } else { + Column( + modifier = Modifier + .fillMaxWidth() + .padding(bottom = 18.dp), + verticalArrangement = Arrangement.spacedBy(10.dp), + horizontalAlignment = Alignment.CenterHorizontally + ) { + Text( + translation["quick_actions_title"], + fontSize = 24.sp, + fontWeight = FontWeight.Bold, + textAlign = TextAlign.Center, + color = Color.White, + maxLines = 3, + overflow = TextOverflow.Clip + ) + Text( + text = "${selectedTiles.size} curated shortcuts", + fontSize = 13.sp, + color = Color.White.copy(alpha = 0.75f), + textAlign = TextAlign.Center + ) + Row( + modifier = Modifier.wrapContentWidth(), + horizontalArrangement = Arrangement.spacedBy(10.dp), + verticalAlignment = Alignment.CenterVertically + ) { + OutlinedButton( + onClick = { showQuickActionsMenu = true }, + border = BorderStroke(1.dp, Color.White.copy(alpha = 0.3f)), + colors = ButtonDefaults.outlinedButtonColors(contentColor = Color.White) + ) { + Icon( + imageVector = ImageVector.vectorResource(id = R.drawable.ic_manage), + contentDescription = translation["manage_quick_actions_description"], + modifier = Modifier.size(18.dp) + ) + Spacer(modifier = Modifier.width(6.dp)) + Text(text = "Manage") + } + Button( + onClick = { editMode = !editMode }, + colors = ButtonDefaults.buttonColors( + containerColor = if (editMode) Color.White else Color.White.copy(alpha = 0.12f), + contentColor = if (editMode) Color(0xFF1B152E) else Color.White + ) + ) { + Icon( + imageVector = if (editMode) Icons.Default.Check else Icons.Filled.DragHandle, + contentDescription = null, + modifier = Modifier.size(18.dp) + ) + Spacer(modifier = Modifier.width(6.dp)) + Text(if (editMode) "Done" else "Reorder") + } + } + } + val spacing = 12.dp + var spanTick by remember { mutableIntStateOf(0) } + + BoxWithConstraints( + modifier = Modifier.fillMaxWidth() + ) { + val density = LocalDensity.current + val baseCell = remember { (maxWidth - (spacing * 2)) / 3f } + val baseCellPx = with(density) { baseCell.toPx() } + + val (tilePositions, totalHeight) = remember(selectedTiles.size, spanTick) { + val positions = mutableMapOf() + var currentX = 0f + var currentY = 0f + var rowMaxHeight = 0f + val screenWidthPx = with(density) { maxWidth.toPx() } + + selectedTiles.forEach { tileName -> + cards.entries.find { entry -> entry.key.first == tileName }?.let { + val card = it.key + val (wSpan, hSpan) = getTileSpan(card.first) + val tileWidthPx = with(density) { (baseCell * wSpan + spacing * (wSpan - 1)).toPx() } + val tileHeightPx = with(density) { (baseCell * hSpan + spacing * (hSpan - 1)).toPx() } + + if (currentX + tileWidthPx > screenWidthPx) { + currentX = 0f + currentY += rowMaxHeight + rowMaxHeight = 0f + } + + positions[tileName] = Offset(currentX, currentY) + currentX += tileWidthPx + with(density) { spacing.toPx() } + if (tileHeightPx > rowMaxHeight) { + rowMaxHeight = tileHeightPx + } + } + } + positions to (currentY + rowMaxHeight) + } + + Box(modifier = Modifier.height(with(density) { totalHeight.toDp() })) { + remember(selectedTiles.size, context.translation.loadedLocale) { + selectedTiles.mapNotNull { + cards.entries.find { entry -> entry.key.first == it } + } + }.forEach { (card, action) -> + val interactionSource = remember { MutableInteractionSource() } + val _tick = spanTick + val (wSpan, hSpan) = getTileSpan(card.first) + val tileWidth = baseCell * wSpan + spacing * (wSpan - 1) + val tileHeight = baseCell * hSpan + spacing * (hSpan - 1) + val tileWidthPx = with(density) { tileWidth.toPx() } + val tileHeightPx = with(density) { tileHeight.toPx() } + + var offsetX by remember(card.first) { mutableStateOf(0f) } + var offsetY by remember(card.first) { mutableStateOf(0f) } + var isDragging by remember { mutableStateOf(false) } + + LaunchedEffect(card.first, spanTick) { + val (x, y) = getTileOffset(card.first) + if (x != 0f || y != 0f) { + offsetX = x + offsetY = y + } else { + val pos = tilePositions[card.first] + if (pos != null) { + offsetX = pos.x + offsetY = pos.y + setTileOffset(card.first, offsetX, offsetY) + } + } + } + + val animatedOffsetX by animateFloatAsState( + targetValue = offsetX, + animationSpec = spring( + dampingRatio = Spring.DampingRatioMediumBouncy, + stiffness = Spring.StiffnessLow + ), + label = "offsetX" + ) + val animatedOffsetY by animateFloatAsState( + targetValue = offsetY, + animationSpec = spring( + dampingRatio = Spring.DampingRatioMediumBouncy, + stiffness = Spring.StiffnessLow + ), + label = "offsetY" + ) + + val currentOffsetX = if (isDragging) offsetX else animatedOffsetX + val currentOffsetY = if (isDragging) offsetY else animatedOffsetY + + val baseModifier = Modifier + .offset { IntOffset(currentOffsetX.roundToInt(), currentOffsetY.roundToInt()) } + .width(tileWidth) + .height(tileHeight) + .padding(all = 6.dp) + + val editModifier = baseModifier.then( + Modifier.pointerInput(card.first, tileWidthPx, tileHeightPx) { + var originalOffsetX = 0f + var originalOffsetY = 0f + detectDragGestures( + onDragStart = { + isDragging = true + originalOffsetX = offsetX + originalOffsetY = offsetY + }, + onDrag = { change, dragAmount -> + change.consume() + offsetX += dragAmount.x + offsetY += dragAmount.y + }, + onDragEnd = { + isDragging = false + var targetTile: String? = null + var maxOverlap = 0f + val tileRect = Rect(Offset(offsetX, offsetY), Size(tileWidthPx, tileHeightPx)) + + for (otherTileName in selectedTiles) { + if (otherTileName == card.first) continue + val (otherOffsetX, otherOffsetY) = getTileOffset(otherTileName) + val (otherWSpan, otherHSpan) = getTileSpan(otherTileName) + val otherTileWidth = baseCell * otherWSpan + spacing * (otherWSpan - 1) + val otherTileHeight = baseCell * otherHSpan + spacing * (otherHSpan - 1) + val otherRect = Rect(Offset(otherOffsetX, otherOffsetY), Size(with(density) { otherTileWidth.toPx() }, with(density) { otherTileHeight.toPx() })) + val intersectRect = tileRect.intersect(otherRect) + val overlapArea = intersectRect.width * intersectRect.height + if (overlapArea > maxOverlap) { + maxOverlap = overlapArea + targetTile = otherTileName + } + } + + if (targetTile != null) { + val (wSpan, hSpan) = getTileSpan(card.first) + val (targetWSpan, targetHSpan) = getTileSpan(targetTile!!) + if (wSpan == targetWSpan && hSpan == targetHSpan) { + // swap + val (targetOffsetX, targetOffsetY) = getTileOffset(targetTile!!) + setTileOffset(card.first, targetOffsetX, targetOffsetY) + setTileOffset(targetTile!!, originalOffsetX, originalOffsetY) + spanTick++ // this will trigger recomposition for all tiles + } else { + // revert + offsetX = originalOffsetX + offsetY = originalOffsetY + } + } else { + setTileOffset(card.first, offsetX, offsetY) + } + } + ) + } + ) + val viewModifier = baseModifier.then(Modifier.scaleOnPress(interactionSource)) + + val tileContent: @Composable (Modifier, Boolean) -> Unit = { tileModifier, isEdit -> + Surface( + modifier = tileModifier, + shape = RoundedCornerShape(18.dp), + color = Color.White.copy(alpha = 0.06f), + tonalElevation = 0.dp, + shadowElevation = 0.dp, + border = BorderStroke(1.dp, Color.White.copy(alpha = 0.16f)) + ) { + Box( + Modifier + .fillMaxSize() + .background( + Brush.linearGradient( + listOf( + PurrfectPalette.glowPrimary.copy(alpha = 0.3f), + PurrfectPalette.glowSecondary.copy(alpha = 0.22f) + ) + ) + ) + .clipToBounds() + ) { + Column( + modifier = Modifier + .fillMaxSize() + .padding(all = 10.dp), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.SpaceEvenly, + ) { + Icon( + imageVector = card.second, contentDescription = null, + tint = Color.White, + modifier = Modifier.size(50.dp) + ) + Text( + text = card.first, + lineHeight = 16.sp, + fontSize = 14.sp, + fontWeight = FontWeight.Bold, + textAlign = TextAlign.Center, + color = Color.White, + overflow = TextOverflow.Ellipsis, + ) + } + if (isEdit) { + var dxAccResize by remember(card.first, spanTick) { mutableStateOf(0f) } + var dyAccResize by remember(card.first, spanTick) { mutableStateOf(0f) } + Box( + modifier = Modifier + .align(Alignment.BottomEnd) + .size(28.dp) + .pointerInput(card.first, spanTick) { + detectDragGestures( + onDragStart = { + dxAccResize = 0f + dyAccResize = 0f + }, + onDrag = { change, dragAmount -> + change.consume() + dxAccResize += dragAmount.x + dyAccResize += dragAmount.y + + var newW = wSpan + var newH = hSpan + val step = baseCellPx / 2f + + while (dxAccResize > step) { + newW = (wSpan + 1).coerceIn(1, 3) + dxAccResize -= step + } + while (dxAccResize < -step) { + newW = (wSpan - 1).coerceIn(1, 3) + dxAccResize += step + } + while (dyAccResize > step) { + newH = (hSpan + 1).coerceIn(1, 3) + dyAccResize -= step + } + while (dyAccResize < -step) { + newH = (hSpan - 1).coerceIn(1, 3) + dyAccResize += step + } + + if (newW != wSpan || newH != hSpan) { + setTileSpan(card.first, newW, newH) + spanTick++ + selectedTiles.forEach { clearTileOffset(it) } + } + } + ) + }, + contentAlignment = Alignment.Center + ) { + Icon(Icons.Filled.DragHandle, contentDescription = null, tint = Color.White) + } + } + } + } + } + + if (editMode) { + tileContent(editModifier, true) + } else { + tileContent(viewModifier.then(Modifier.clickable { action(routes) }), false) + } + } + } + } + } + } + Spacer(modifier = Modifier.height(32.dp)) + } + } + + if (showQuickActionsMenu) { + QuickActionsDialog( + quickActions = cards, + selectedQuickActions = selectedTiles, + onDismiss = { showQuickActionsMenu = false }, + onSave = { newList -> + val previous = selectedTiles.toList() + val removed = previous.filter { it !in newList } + removed.forEach { clearTileSpan(it); clearTileOffset(it) } + newList.forEach { clearTileOffset(it) } + selectedTiles.clear() + selectedTiles.addAll(newList) + if (newList.isEmpty()) { + editMode = false + } + context.coroutineScope.launch { + context.database.setQuickTiles(selectedTiles) + } + showQuickActionsMenu = false + }, + translation = translation + ) + } + } +} +} +} diff --git a/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/home/HomeSettings.kt b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/home/HomeSettings.kt new file mode 100644 index 00000000..5eefc2a2 --- /dev/null +++ b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/home/HomeSettings.kt @@ -0,0 +1,755 @@ +package me.eternal.purrfectsnap.ui.manager.pages.home + +import android.content.SharedPreferences +import android.net.Uri +import androidx.compose.foundation.BorderStroke +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +import androidx.compose.foundation.horizontalScroll +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.foundation.verticalScroll +import androidx.compose.animation.AnimatedVisibility +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.automirrored.filled.ArrowBack +import androidx.compose.material.icons.automirrored.filled.OpenInNew +import androidx.compose.material.icons.filled.DeleteSweep +import androidx.compose.material.icons.filled.Tune +import androidx.compose.material3.* +import androidx.compose.runtime.* +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Brush +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.hapticfeedback.HapticFeedbackType +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.platform.LocalHapticFeedback +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import androidx.compose.ui.window.Dialog +import androidx.compose.foundation.layout.WindowInsets +import androidx.compose.foundation.layout.asPaddingValues +import androidx.core.content.edit +import androidx.core.net.toUri +import androidx.navigation.NavBackStackEntry +import androidx.work.Constraints +import androidx.work.Data +import androidx.work.ExistingPeriodicWorkPolicy +import androidx.work.NetworkType +import androidx.work.PeriodicWorkRequestBuilder +import androidx.work.WorkManager +import kotlinx.coroutines.launch +import me.eternal.purrfectsnap.common.action.EnumAction +import me.eternal.purrfectsnap.common.bridge.InternalFileHandleType +import me.eternal.purrfectsnap.common.ui.rememberAsyncMutableState +import me.eternal.purrfectsnap.storage.getAllScopeNotes +import me.eternal.purrfectsnap.storage.setAllScopeNotes +import me.eternal.purrfectsnap.task.UpdateCheckWorker +import me.eternal.purrfectsnap.ui.manager.Routes +import me.eternal.purrfectsnap.ui.manager.theme.PurrfectPalette +import me.eternal.purrfectsnap.ui.setup.Requirements +import me.eternal.purrfectsnap.ui.util.ActivityLauncherHelper +import me.eternal.purrfectsnap.ui.util.AlertDialogs +import me.eternal.purrfectsnap.ui.util.openFile +import me.eternal.purrfectsnap.ui.util.saveFile +import me.eternal.purrfectsnap.ui.util.purrfectSwitchColors +import java.io.File +import java.io.FileOutputStream +import java.net.URLEncoder +import java.util.concurrent.TimeUnit + +class HomeSettings : Routes.Route() { + override val translation by lazy { context.translation.getCategory("manager.sections.home_settings") } + private lateinit var activityLauncherHelper: ActivityLauncherHelper + private val dialogs by lazy { AlertDialogs(context.translation) } + + private fun scheduleUpdateCheck() { + val workManager = WorkManager.getInstance(context.androidContext) + if (context.config.root.global.updateSettings.autoUpdateCheck.get()) { + val frequency = context.config.root.global.updateSettings.updateCheckFrequency.get() + val repeatInterval = when (frequency) { + "daily" -> 1L + "weekly" -> 7L + "monthly" -> 30L + else -> 1L + } + + val constraints = Constraints.Builder() + .setRequiredNetworkType(NetworkType.CONNECTED) + .build() + + val inputData = Data.Builder() + .putString("channel_name", translation["update_notification_channel_name"]) + .putString("channel_description", translation["update_notification_channel_description"]) + .putString("notification_title", translation["update_notification_title"]) + .putString("notification_text", translation["update_notification_text"]) + .build() + + val workRequest = PeriodicWorkRequestBuilder(repeatInterval, TimeUnit.DAYS) + .setConstraints(constraints) + .setInputData(inputData) + .build() + + workManager.enqueueUniquePeriodicWork( + "purrfectsnap_update_check", + ExistingPeriodicWorkPolicy.REPLACE, + workRequest + ) + } else { + workManager.cancelUniqueWork("purrfectsnap_update_check") + } + } + override val init: () -> Unit = { + activityLauncherHelper = ActivityLauncherHelper(context.activity!!) + } + @Composable + private fun RowTitle(title: String) { + Text( + text = title, + modifier = Modifier.padding(horizontal = 4.dp, vertical = 8.dp), + fontSize = 18.sp, + fontWeight = FontWeight.Bold, + color = Color.White + ) + } + @Composable + private fun PremiumPreferenceToggle( + sharedPreferences: SharedPreferences, + key: String, + text: String, + defaultValue: Boolean = false + ) { + val realKey = "debug_$key" + var value by remember { mutableStateOf(sharedPreferences.getBoolean(realKey, defaultValue)) } + val hapticFeedback = LocalHapticFeedback.current + + LaunchedEffect(realKey) { + if (!sharedPreferences.contains(realKey)) { + sharedPreferences.edit().putBoolean(realKey, defaultValue).apply() + value = defaultValue + } + } + + Row( + modifier = Modifier + .fillMaxWidth() + .heightIn(min = 55.dp) + .clickable { + if (context.config.root.global.uiSettings.hapticFeedback.get()) { + hapticFeedback.performHapticFeedback(HapticFeedbackType.LongPress) + } + value = !value + sharedPreferences + .edit() { + putBoolean(realKey, value) + } + }, + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.CenterVertically + ) { + Text(text = text, modifier = Modifier.padding(start = 26.dp, end = 16.dp), fontSize = 14.sp) + Switch( + checked = value, + onCheckedChange = null, + modifier = Modifier.padding(end = 26.dp), + colors = purrfectSwitchColors() + ) + } + } + + @Composable + private fun PreferenceToggle(sharedPreferences: SharedPreferences, key: String, text: String) { + val realKey = "debug_$key" + var value by remember { mutableStateOf(sharedPreferences.getBoolean(realKey, false)) } + val hapticFeedback = LocalHapticFeedback.current + Row( + modifier = Modifier + .fillMaxWidth() + .heightIn(min = 55.dp) + .clickable { + if (context.config.root.global.uiSettings.hapticFeedback.get()) { + hapticFeedback.performHapticFeedback(HapticFeedbackType.LongPress) + } + value = !value + sharedPreferences + .edit() { + putBoolean(realKey, value) + } + }, + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.CenterVertically + ) { + Text(text = text, modifier = Modifier.padding(start = 26.dp, end = 16.dp), fontSize = 14.sp) + Switch( + checked = value, + onCheckedChange = null, + modifier = Modifier.padding(end = 26.dp), + colors = purrfectSwitchColors() + ) + } + } + + @Composable + private fun RowAction(key: String, requireConfirmation: Boolean = false, action: () -> Unit) { + var confirmationDialog by remember { + mutableStateOf(false) + } + fun takeAction() { + if (requireConfirmation) { + confirmationDialog = true + } else { + action() + } + } + if (requireConfirmation && confirmationDialog) { + Dialog(onDismissRequest = { confirmationDialog = false }) { + dialogs.ConfirmDialog(title = context.translation["manager.dialogs.action_confirm.title"], onConfirm = { + action() + confirmationDialog = false + }, onDismiss = { + confirmationDialog = false + }) + } + } + ShiftedRow( + modifier = Modifier + .fillMaxWidth() + .heightIn(min = 55.dp) + .clickable { + takeAction() + }, + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.CenterVertically + ) { + Column( + modifier = Modifier.weight(1f), + ) { + Text(text = context.translation["actions.$key.name"], fontSize = 16.sp, fontWeight = FontWeight.Bold, lineHeight = 20.sp) + context.translation.getOrNull("actions.$key.description")?.let { Text(text = it, fontSize = 12.sp, fontWeight = FontWeight.Light, lineHeight = 15.sp) } + } + IconButton(onClick = { takeAction() }, + modifier = Modifier.padding(end = 2.dp) + ) { + Icon( + imageVector = Icons.AutoMirrored.Filled.OpenInNew, + contentDescription = context.translation.getOrNull("actions.$key.name"), + modifier = Modifier.size(24.dp) + ) + } + } + } + @Composable + private fun ShiftedRow( + modifier: Modifier = Modifier, + horizontalArrangement: Arrangement.Horizontal = Arrangement.Start, + verticalAlignment: Alignment.Vertical = Alignment.Top, + content: @Composable RowScope.() -> Unit + ) { + Row( + modifier = modifier.padding(start = 26.dp), + horizontalArrangement = horizontalArrangement, + verticalAlignment = verticalAlignment + ) { content(this) } + } + + @OptIn(ExperimentalMaterial3Api::class) + override val content: @Composable (NavBackStackEntry) -> Unit = { + val contextC = LocalContext.current + val scope = rememberCoroutineScope() + val scrollState = rememberScrollState() + val sharedButtonColors = ButtonDefaults.buttonColors( + containerColor = Color.White.copy(alpha = 0.12f), + contentColor = Color.White + ) + val sharedOutlinedColors = ButtonDefaults.outlinedButtonColors(contentColor = Color.White) + + @Composable + fun GlassCard( + modifier: Modifier = Modifier, + content: @Composable ColumnScope.() -> Unit + ) { + Surface( + modifier = modifier, + shape = RoundedCornerShape(22.dp), + color = Color.White.copy(alpha = 0.04f), + tonalElevation = 0.dp, + shadowElevation = 0.dp, + border = BorderStroke(1.dp, Color.White.copy(alpha = 0.08f)), + contentColor = Color.White + ) { + Column( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 16.dp, vertical = 14.dp), + verticalArrangement = Arrangement.spacedBy(10.dp) + ) { + content() + } + } + } + + val topPadding = WindowInsets.statusBars.asPaddingValues().calculateTopPadding() + Box( + modifier = Modifier + .fillMaxSize() + .background(PurrfectPalette.backgroundGradient) + ) { + Column( + modifier = Modifier.fillMaxSize() + ) { + Spacer(modifier = Modifier.height(topPadding)) + Surface( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 14.dp, vertical = 12.dp), + shape = RoundedCornerShape(26.dp), + color = Color.White.copy(alpha = 0.07f), + tonalElevation = 0.dp, + shadowElevation = 0.dp, + border = BorderStroke( + 1.dp, + Brush.linearGradient( + listOf( + PurrfectPalette.glowPrimary.copy(alpha = 0.55f), + PurrfectPalette.glowSecondary.copy(alpha = 0.35f) + ) + ) + ), + contentColor = Color.White + ) { + Row( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 16.dp, vertical = 14.dp), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.SpaceBetween + ) { + IconButton(onClick = { routes.navController.popBackStack() }) { + Icon( + imageVector = Icons.AutoMirrored.Filled.ArrowBack, + contentDescription = null, + tint = Color.White + ) + } + Text( + text = translation["manager.routes.home_settings"], + fontWeight = FontWeight.ExtraBold, + fontSize = 18.sp + ) + IconButton(onClick = { routes.navigation?.openBottomBarCustomization = true }) { + Icon( + imageVector = Icons.Filled.Tune, + contentDescription = null, + tint = Color.White.copy(alpha = 0.85f) + ) + } + } + } + + Spacer(modifier = Modifier.height(8.dp)) + + Column( + modifier = Modifier + .fillMaxSize() + .verticalScroll(scrollState) + ) { + Column( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 12.dp, vertical = 8.dp), + verticalArrangement = Arrangement.spacedBy(12.dp) + ) { + GlassCard { + RowTitle(title = translation["actions_title"]) + EnumAction.entries.forEach { enumAction -> + RowAction(key = enumAction.key) { context.launchActionIntent(enumAction) } + } + RowAction(key = "regen_mappings") { context.checkForRequirements(Requirements.MAPPINGS) } + RowAction(key = "change_language") { context.checkForRequirements(Requirements.LANGUAGE) } + } + + GlassCard { + RowTitle(title = translation["ui_settings_title"]) + ShiftedRow { + Row( + modifier = Modifier + .fillMaxWidth() + .heightIn(min = 55.dp), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.SpaceBetween + ) { + Text(text = translation["haptic_feedback_label"]) + var hapticFeedbackEnabled by remember { mutableStateOf(context.config.root.global.uiSettings.hapticFeedback.getNullable() ?: true) } + val hapticFeedback = LocalHapticFeedback.current + Switch( + checked = hapticFeedbackEnabled, + onCheckedChange = { + if (it) { + hapticFeedback.performHapticFeedback(HapticFeedbackType.LongPress) + } + hapticFeedbackEnabled = it + context.config.root.global.uiSettings.hapticFeedback.set(it) + context.config.writeConfig() + }, + modifier = Modifier.padding(end = 26.dp), + colors = purrfectSwitchColors() + ) + } + } + } + + GlassCard { + RowTitle(title = translation["updates_title"]) + Column(verticalArrangement = Arrangement.spacedBy(10.dp)) { + var autoUpdateCheck by remember { mutableStateOf(context.config.root.global.updateSettings.autoUpdateCheck.getNullable() ?: true) } + var selectedFrequency by remember { mutableStateOf(context.config.root.global.updateSettings.updateCheckFrequency.getNullable() ?: "weekly") } + var frequencyMenuExpanded by remember { mutableStateOf(false) } + Row( + modifier = Modifier + .fillMaxWidth() + .heightIn(min = 55.dp), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.SpaceBetween + ) { + Text(text = translation["auto_update_check"]) + val hapticFeedback = LocalHapticFeedback.current + Switch( + checked = autoUpdateCheck, + onCheckedChange = { + if (context.config.root.global.uiSettings.hapticFeedback.get()) { + hapticFeedback.performHapticFeedback(HapticFeedbackType.LongPress) + } + autoUpdateCheck = it + if (it && context.config.root.global.updateSettings.updateCheckFrequency.getNullable() == null) { + selectedFrequency = "weekly" + context.config.root.global.updateSettings.updateCheckFrequency.set("weekly") + } + context.config.root.global.updateSettings.autoUpdateCheck.set(it) + context.config.writeConfig() + scheduleUpdateCheck() + }, + modifier = Modifier.padding(end = 26.dp), + colors = purrfectSwitchColors() + ) + } + AnimatedVisibility(visible = autoUpdateCheck) { + ExposedDropdownMenuBox( + expanded = frequencyMenuExpanded, + onExpandedChange = { frequencyMenuExpanded = it }, + modifier = Modifier + .fillMaxWidth() + .padding(start = 10.dp, end = 26.dp) + ) { + TextField( + value = translation.getOrNull("update_check_frequency_${selectedFrequency}") ?: selectedFrequency, + onValueChange = {}, + readOnly = true, + modifier = Modifier + .fillMaxWidth(), + trailingIcon = { ExposedDropdownMenuDefaults.TrailingIcon(expanded = frequencyMenuExpanded) }, + colors = ExposedDropdownMenuDefaults.textFieldColors( + focusedContainerColor = Color.White.copy(alpha = 0.08f), + unfocusedContainerColor = Color.White.copy(alpha = 0.06f), + focusedIndicatorColor = Color.Transparent, + unfocusedIndicatorColor = Color.Transparent + ) + ) + ExposedDropdownMenu( + expanded = frequencyMenuExpanded, + onDismissRequest = { frequencyMenuExpanded = false } + ) { + listOf("daily", "weekly", "monthly").forEach { frequency -> + DropdownMenuItem( + text = { Text(text = translation.getOrNull("update_check_frequency_${frequency}") ?: frequency) }, + onClick = { + selectedFrequency = frequency + frequencyMenuExpanded = false + context.config.root.global.updateSettings.updateCheckFrequency.set(frequency) + context.config.writeConfig() + scheduleUpdateCheck() + } + ) + } + } + } + } + } + } + + GlassCard { + RowTitle(title = translation["message_logger_title"]) + Column(verticalArrangement = Arrangement.spacedBy(10.dp)) { + var storedMessagesCount by rememberAsyncMutableState(defaultValue = 0) { + context.messageLogger.getStoredMessageCount() + } + var storedStoriesCount by rememberAsyncMutableState(defaultValue = 0) { + context.messageLogger.getStoredStoriesCount() + } + Column( + modifier = Modifier + .fillMaxWidth() + .padding(5.dp), + verticalArrangement = Arrangement.spacedBy(10.dp), + horizontalAlignment = Alignment.CenterHorizontally + ) { + val summary = translation.format( + "message_logger_summary", + "messageCount" to storedMessagesCount.toString(), + "storyCount" to storedStoriesCount.toString() + ).replace("\n", " | ") + Text( + summary, + maxLines = 2, + color = Color.White, + textAlign = TextAlign.Center, + modifier = Modifier.fillMaxWidth() + ) + Row( + modifier = Modifier + .wrapContentWidth() + .align(Alignment.CenterHorizontally), + horizontalArrangement = Arrangement.spacedBy(10.dp), + verticalAlignment = Alignment.CenterVertically + ) { + Button( + onClick = { + runCatching { + activityLauncherHelper.saveFile("message_logger.db", "application/octet-stream") { uri -> + context.androidContext.contentResolver.openOutputStream(uri.toUri())?.use { outputStream -> + context.messageLogger.databaseFile.inputStream().use { inputStream -> + inputStream.copyTo(outputStream) + } + } + } + }.onFailure { + context.log.error("Failed to export database", it) + context.longToast(translation.format("export_database_failed_toast", "message" to (it.localizedMessage ?: ""))) + } + }, + colors = sharedButtonColors, + border = BorderStroke(1.dp, Color.White.copy(alpha = 0.12f)) + ) { + Text(text = translation["export_button"]) + } + Button( + onClick = { + runCatching { + activityLauncherHelper.openFile("application/octet-stream") { uri -> + val tempFile = File(context.androidContext.cacheDir, "view_message_logger.db") + context.androidContext.contentResolver.openInputStream(uri.toUri())?.use { inputStream -> + FileOutputStream(tempFile).use { outputStream -> + inputStream.copyTo(outputStream) + } + } + routes.viewLoggerHistory.navigate { + put("uri", URLEncoder.encode(tempFile.toUri().toString(), "UTF-8")) + } + } + }.onFailure { + context.log.error("Failed to open file", it) + context.longToast("Failed to open file! ${it.localizedMessage}") + } + }, + colors = sharedButtonColors, + border = BorderStroke(1.dp, Color.White.copy(alpha = 0.12f)) + ) { + Text(text = translation["view_button"]) + } + Button( + onClick = { + runCatching { + context.messageLogger.purgeAll() + storedMessagesCount = 0 + storedStoriesCount = 0 + }.onFailure { + context.log.error("Failed to clear messages", it) + context.longToast(translation.format("clear_messages_failed_toast", "message" to (it.localizedMessage ?: ""))) + }.onSuccess { + context.shortToast(translation["success_toast"]) + } + }, + colors = sharedButtonColors, + border = BorderStroke(1.dp, Color.White.copy(alpha = 0.12f)) + ) { + Text(text = translation["clear_button"]) + } + } + } + OutlinedButton( + modifier = Modifier + .fillMaxWidth() + .padding(5.dp), + onClick = { routes.loggerHistory.navigate() }, + colors = sharedOutlinedColors, + border = BorderStroke(1.dp, Color.White.copy(alpha = 0.2f)) + ) { + Text(translation["view_logger_history_button"]) + } + } + } + + GlassCard { + RowTitle(title = translation["friend_notes_title"]) + Column(verticalArrangement = Arrangement.spacedBy(12.dp)) { + Text( + text = translation["friend_notes_description"], + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 5.dp), + color = Color.White, + textAlign = TextAlign.Center + ) + Row( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 5.dp), + horizontalArrangement = Arrangement.Center, + verticalAlignment = Alignment.CenterVertically + ) { + Row(horizontalArrangement = Arrangement.spacedBy(10.dp)) { + Button(onClick = { + runCatching { + val notes = context.database.getAllScopeNotes() + if (notes.isEmpty()) { + context.shortToast(translation["friend_notes_no_notes_to_backup"]) + return@runCatching + } + val json = context.gson.toJson(notes) + activityLauncherHelper.saveFile("friend_notes_backup.json", "application/json") { uri -> + context.androidContext.contentResolver.openOutputStream(uri.toUri())?.use { + it.write(json.toByteArray()) + } + context.shortToast(translation["friend_notes_backup_success"]) + } + }.onFailure { + context.log.error("Failed to backup notes", it) + context.longToast(translation.format("friend_notes_backup_failure", "error" to (it.localizedMessage ?: ""))) + } + }, + colors = sharedButtonColors, + border = BorderStroke(1.dp, Color.White.copy(alpha = 0.12f)) + ) { + Text(text = translation["backup_button"]) + } + Button(onClick = { + runCatching { + activityLauncherHelper.openFile("application/json") { uri -> + context.androidContext.contentResolver.openInputStream(uri.toUri())?.use { + val json = it.reader().readText() + val notes = context.gson.fromJson>(json, object : com.google.gson.reflect.TypeToken>() {}.type) + context.database.setAllScopeNotes(notes) + context.shortToast(translation["friend_notes_restore_success"]) + } + } + }.onFailure { + context.log.error("Failed to restore notes", it) + context.longToast(translation.format("friend_notes_restore_failure", "error" to (it.localizedMessage ?: ""))) + } + }, + colors = sharedButtonColors, + border = BorderStroke(1.dp, Color.White.copy(alpha = 0.12f)) + ) { + Text(text = translation["restore_button"]) + } + } + } + } + } + + GlassCard { + RowTitle(title = translation["debug_title"]) + Column(verticalArrangement = Arrangement.spacedBy(10.dp)) { + Row( + horizontalArrangement = Arrangement.spacedBy(12.dp), + verticalAlignment = Alignment.CenterVertically, + ) { + var selectedFileType by remember { mutableStateOf(InternalFileHandleType.entries.first()) } + Box( + modifier = Modifier + .weight(1f) + .padding(start = 26.dp) + ) { + var expanded by remember { mutableStateOf(false) } + ExposedDropdownMenuBox( + expanded = expanded, + onExpandedChange = { expanded = it }, + modifier = Modifier.fillMaxWidth() + ) { + TextField( + value = translation.getOrNull("debug_file_${selectedFileType.name.lowercase()}") ?: selectedFileType.fileName, + onValueChange = {}, + readOnly = true, + modifier = Modifier + .fillMaxWidth(), + colors = ExposedDropdownMenuDefaults.textFieldColors( + focusedContainerColor = Color.White.copy(alpha = 0.08f), + unfocusedContainerColor = Color.White.copy(alpha = 0.06f), + focusedIndicatorColor = Color.Transparent, + unfocusedIndicatorColor = Color.Transparent + ) + ) + ExposedDropdownMenu(expanded = expanded, onDismissRequest = { expanded = false }) { + InternalFileHandleType.entries.forEach { fileType -> + DropdownMenuItem(onClick = { + expanded = false + selectedFileType = fileType + }, text = { + Text(text = translation.getOrNull("debug_file_${fileType.name.lowercase()}") ?: fileType.fileName) + }) + } + } + } + } + Button( + onClick = { + runCatching { + context.coroutineScope.launch { + selectedFileType.resolve(context.androidContext).delete() + } + }.onFailure { + context.log.error("Failed to clear file", it) + context.longToast(translation.format("clear_file_failed_toast", "message" to (it.localizedMessage ?: ""))) + }.onSuccess { + context.shortToast(translation["success_toast"]) + } + }, + colors = ButtonDefaults.buttonColors( + containerColor = Color.White.copy(alpha = 0.1f), + contentColor = Color.White + ), + border = BorderStroke(1.dp, Color.White.copy(alpha = 0.18f)), + shape = RoundedCornerShape(14.dp) + ) { + Icon(Icons.Default.DeleteSweep, contentDescription = null, modifier = Modifier.size(18.dp)) + Spacer(modifier = Modifier.width(8.dp)) + Text(translation["clear_button"]) + } + } + ShiftedRow { + Column( + verticalArrangement = Arrangement.spacedBy(4.dp), + ) { + PremiumPreferenceToggle( + context.sharedPreferences, + key = "test_mode", + text = translation["test_mode_label"], + defaultValue = true + ) + PreferenceToggle(context.sharedPreferences, key = "disable_feature_loading", text = translation["disable_feature_loading_label"]) + PreferenceToggle(context.sharedPreferences, key = "disable_mapper", text = translation["disable_auto_mapper_label"]) + PreferenceToggle(context.sharedPreferences, key = "disable_bypass_indicator", text = translation["disable_bypass_indicator_label"]) + } + } + } + } + + Spacer(modifier = Modifier.height(routes.bottomPadding + 12.dp)) + } + } + } + } +} +} diff --git a/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/home/QuickActionsDialog.kt b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/home/QuickActionsDialog.kt new file mode 100644 index 00000000..31533424 --- /dev/null +++ b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/home/QuickActionsDialog.kt @@ -0,0 +1,206 @@ +package me.eternal.purrfectsnap.ui.manager.pages.home + +import androidx.compose.foundation.BorderStroke +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.wrapContentHeight +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.foundation.verticalScroll +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.AutoAwesome +import androidx.compose.material3.Button +import androidx.compose.material3.ButtonDefaults +import androidx.compose.material3.Icon +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Switch +import androidx.compose.material3.Surface +import androidx.compose.material3.Text +import androidx.compose.material3.TextButton +import androidx.compose.runtime.Composable +import androidx.compose.runtime.mutableStateListOf +import androidx.compose.runtime.remember +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.Brush +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.dp +import me.eternal.purrfectsnap.common.bridge.wrapper.LocaleWrapper +import me.eternal.purrfectsnap.ui.manager.theme.PurrfectPalette +import me.eternal.purrfectsnap.ui.util.purrfectSwitchColors +import androidx.compose.ui.window.Dialog + +@Composable +fun QuickActionsDialog( + quickActions: Map, Any>, + selectedQuickActions: List, + onDismiss: () -> Unit, + onSave: (List) -> Unit, + translation: LocaleWrapper +) { + val selected = remember { mutableStateListOf(*selectedQuickActions.toTypedArray()) } + + Dialog(onDismissRequest = onDismiss) { + val dialogShape = RoundedCornerShape(24.dp) + Surface( + modifier = Modifier + .fillMaxWidth() + .wrapContentHeight(), + shape = dialogShape, + color = Color.Transparent, + tonalElevation = 0.dp, + shadowElevation = 16.dp, + border = BorderStroke( + 1.dp, + Brush.linearGradient( + listOf( + PurrfectPalette.glowPrimary.copy(alpha = 0.55f), + PurrfectPalette.glowSecondary.copy(alpha = 0.45f) + ) + ) + ) + ) { + Column( + modifier = Modifier + .background(PurrfectPalette.cardOverlay, dialogShape) + .padding(horizontal = 18.dp, vertical = 16.dp) + .verticalScroll(rememberScrollState()), + verticalArrangement = Arrangement.spacedBy(14.dp) + ) { + Row( + modifier = Modifier.fillMaxWidth(), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(12.dp) + ) { + Box( + modifier = Modifier + .size(54.dp) + .clip(CircleShape) + .background( + Brush.linearGradient( + listOf( + PurrfectPalette.glowPrimary.copy(alpha = 0.4f), + PurrfectPalette.glowSecondary.copy(alpha = 0.35f) + ) + ) + ), + contentAlignment = Alignment.Center + ) { + Icon( + imageVector = Icons.Filled.AutoAwesome, + contentDescription = null, + tint = Color.White, + modifier = Modifier.size(28.dp) + ) + } + Column( + modifier = Modifier.weight(1f), + verticalArrangement = Arrangement.spacedBy(4.dp) + ) { + Text( + text = translation["manager.dialogs.quick_actions_dialog.title"], + style = MaterialTheme.typography.titleLarge, + color = Color.White, + fontWeight = FontWeight.ExtraBold + ) + Text( + text = translation["manager.dialogs.quick_actions_dialog.subtitle"], + style = MaterialTheme.typography.bodyMedium, + color = PurrfectPalette.textSecondary + ) + } + } + + quickActions.keys.forEach { (name, icon) -> + val isSelected = selected.contains(name) + Surface( + modifier = Modifier + .fillMaxWidth() + .clickable { + if (isSelected) selected.remove(name) else selected.add(name) + }, + shape = RoundedCornerShape(16.dp), + color = PurrfectPalette.cardOverlayColor, + tonalElevation = 0.dp, + shadowElevation = 0.dp, + border = BorderStroke(1.dp, Color.White.copy(alpha = 0.08f)) + ) { + Row( + modifier = Modifier.padding(horizontal = 14.dp, vertical = 12.dp), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(10.dp) + ) { + Surface( + shape = CircleShape, + color = PurrfectPalette.glowPrimary.copy(alpha = 0.18f), + tonalElevation = 0.dp + ) { + Icon( + imageVector = icon, + contentDescription = name, + modifier = Modifier.padding(10.dp), + tint = Color.White + ) + } + Column( + modifier = Modifier.weight(1f), + verticalArrangement = Arrangement.spacedBy(2.dp) + ) { + Text( + name, + color = Color.White, + fontWeight = FontWeight.SemiBold + ) + Text( + text = if (isSelected) translation["enabled"] else translation["disabled"], + color = PurrfectPalette.textSecondary, + style = MaterialTheme.typography.labelSmall + ) + } + Switch( + checked = isSelected, + onCheckedChange = { toggled -> + if (toggled) selected.add(name) else selected.remove(name) + }, + colors = purrfectSwitchColors() + ) + } + } + } + + Spacer(modifier = Modifier.height(4.dp)) + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.spacedBy(10.dp, Alignment.End) + ) { + TextButton(onClick = onDismiss) { + Text(translation["button.cancel"], color = PurrfectPalette.textSecondary) + } + Button( + onClick = { onSave(selected.toList()) }, + colors = ButtonDefaults.buttonColors( + containerColor = PurrfectPalette.glowPrimary.copy(alpha = 0.35f), + contentColor = Color.White + ) + ) { + Text(translation["button.save"]) + } + } + } + } + } +} diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/location/AddCoordinatesDialog.kt b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/location/AddCoordinatesDialog.kt similarity index 93% rename from app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/location/AddCoordinatesDialog.kt rename to app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/location/AddCoordinatesDialog.kt index ce0b636a..7f38a0b2 100644 --- a/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/location/AddCoordinatesDialog.kt +++ b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/location/AddCoordinatesDialog.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.ui.manager.pages.location +package me.eternal.purrfectsnap.ui.manager.pages.location import androidx.compose.foundation.layout.* import androidx.compose.material3.Button @@ -14,9 +14,9 @@ import androidx.compose.ui.text.input.TextFieldValue import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import kotlinx.coroutines.delay -import me.rhunk.snapenhance.bridge.location.LocationCoordinates -import me.rhunk.snapenhance.common.bridge.wrapper.LocaleWrapper -import me.rhunk.snapenhance.ui.util.AlertDialogs +import me.eternal.purrfectsnap.bridge.location.LocationCoordinates +import me.eternal.purrfectsnap.common.bridge.wrapper.LocaleWrapper +import me.eternal.purrfectsnap.ui.util.AlertDialogs @Composable diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/location/BetterLocationRoot.kt b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/location/BetterLocationRoot.kt similarity index 50% rename from app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/location/BetterLocationRoot.kt rename to app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/location/BetterLocationRoot.kt index 7ce90eba..e0f2549a 100644 --- a/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/location/BetterLocationRoot.kt +++ b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/location/BetterLocationRoot.kt @@ -1,19 +1,26 @@ -package me.rhunk.snapenhance.ui.manager.pages.location +package me.eternal.purrfectsnap.ui.manager.pages.location import android.os.Parcel +import androidx.compose.foundation.BorderStroke +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.* import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.foundation.lazy.items +import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Add import androidx.compose.material.icons.filled.DeleteOutline import androidx.compose.material.icons.filled.Edit +import androidx.compose.material.icons.filled.Map +import androidx.compose.material.icons.filled.Navigation import androidx.compose.material3.* import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clipToBounds +import androidx.compose.ui.graphics.Brush import androidx.compose.ui.graphics.Color import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextAlign @@ -24,40 +31,75 @@ import androidx.navigation.NavBackStackEntry import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import kotlinx.coroutines.withContext -import me.rhunk.snapenhance.bridge.location.FriendLocation -import me.rhunk.snapenhance.bridge.location.LocationCoordinates -import me.rhunk.snapenhance.common.ui.rememberAsyncMutableStateList -import me.rhunk.snapenhance.common.ui.rememberAsyncUpdateDispatcher -import me.rhunk.snapenhance.common.util.snap.BitmojiSelfie -import me.rhunk.snapenhance.storage.addOrUpdateLocationCoordinate -import me.rhunk.snapenhance.storage.getLocationCoordinates -import me.rhunk.snapenhance.storage.removeLocationCoordinate -import me.rhunk.snapenhance.ui.manager.Routes -import me.rhunk.snapenhance.ui.util.AlertDialogs -import me.rhunk.snapenhance.ui.util.DialogProperties -import me.rhunk.snapenhance.ui.util.coil.BitmojiImage +import me.eternal.purrfectsnap.bridge.location.FriendLocation +import me.eternal.purrfectsnap.bridge.location.LocationCoordinates +import me.eternal.purrfectsnap.common.ui.rememberAsyncMutableStateList +import me.eternal.purrfectsnap.common.ui.rememberAsyncUpdateDispatcher +import me.eternal.purrfectsnap.common.util.snap.BitmojiSelfie +import me.eternal.purrfectsnap.storage.addOrUpdateLocationCoordinate +import me.eternal.purrfectsnap.storage.getLocationCoordinates +import me.eternal.purrfectsnap.storage.removeLocationCoordinate +import me.eternal.purrfectsnap.ui.manager.Routes +import me.eternal.purrfectsnap.ui.manager.theme.PurrfectPalette +import me.eternal.purrfectsnap.ui.util.AlertDialogs +import me.eternal.purrfectsnap.ui.util.DialogProperties +import me.eternal.purrfectsnap.ui.util.purrfectSwitchColors +import me.eternal.purrfectsnap.ui.util.coil.BitmojiImage import org.osmdroid.util.GeoPoint import org.osmdroid.views.MapView import org.osmdroid.views.overlay.Marker class BetterLocationRoot : Routes.Route() { - private val alertDialogs by lazy { AlertDialogs(context.translation) } + override val translation by lazy { context.translation.getCategory("manager.sections.better_location") } + private val alertDialogs by lazy { AlertDialogs(translation) } + + @Composable + private fun GlassPanel( + modifier: Modifier = Modifier, + content: @Composable ColumnScope.() -> Unit + ) { + Surface( + modifier = modifier, + shape = RoundedCornerShape(22.dp), + color = Color.White.copy(alpha = 0.06f), + tonalElevation = 0.dp, + shadowElevation = 12.dp, + border = BorderStroke( + 1.dp, + Brush.linearGradient( + listOf( + PurrfectPalette.glowPrimary.copy(alpha = 0.45f), + PurrfectPalette.glowSecondary.copy(alpha = 0.35f) + ) + ) + ) + ) { + Column( + modifier = Modifier + .background(PurrfectPalette.cardOverlay) + .padding(horizontal = 16.dp, vertical = 14.dp), + verticalArrangement = Arrangement.spacedBy(10.dp) + ) { + content() + } + } + } @Composable private fun FriendLocationItem( friendLocation: FriendLocation, dismiss: () -> Unit ) { - ElevatedCard(onClick = { - context.config.root.global.betterLocation.coordinates.setAny(friendLocation.latitude to friendLocation.longitude) - dismiss() - }, modifier = Modifier.padding(4.dp)) { - Row( - modifier = Modifier - .padding(8.dp) - .fillMaxWidth(), - verticalAlignment = Alignment.CenterVertically - ) { + GlassPanel( + modifier = Modifier + .padding(vertical = 6.dp, horizontal = 4.dp) + .fillMaxWidth() + .clickable { + context.config.root.global.betterLocation.coordinates.setAny(friendLocation.latitude to friendLocation.longitude) + dismiss() + } + ) { + Row(verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy(10.dp)) { BitmojiImage( context = context, url = BitmojiSelfie.getBitmojiSelfie( @@ -65,25 +107,37 @@ class BetterLocationRoot : Routes.Route() { friendLocation.bitmojiId, BitmojiSelfie.BitmojiSelfieType.NEW_THREE_D ), - size = 48, - modifier = Modifier.padding(6.dp) + size = 50, + modifier = Modifier.padding(2.dp) ) - Column( - modifier = Modifier.weight(1f), - ) { - Text(friendLocation.displayName?.let { "$it (${friendLocation.username})" } - ?: friendLocation.username, fontSize = 16.sp, fontWeight = FontWeight.Bold) + Column(modifier = Modifier.weight(1f), verticalArrangement = Arrangement.spacedBy(2.dp)) { Text( - text = buildString { - append(friendLocation.localityPieces.joinToString(", ")) - append("\n") - append("Lat: ${friendLocation.latitude.toFloat()}, Lng: ${friendLocation.longitude.toFloat()}") - }, - fontSize = 10.sp, + friendLocation.displayName?.let { "$it (${friendLocation.username})" } + ?: friendLocation.username, + fontSize = 16.sp, + fontWeight = FontWeight.ExtraBold, + color = Color.White + ) + Text( + text = friendLocation.localityPieces.joinToString(", "), + fontSize = 12.sp, + fontWeight = FontWeight.Medium, + color = PurrfectPalette.textSecondary, + maxLines = 1, + overflow = TextOverflow.Ellipsis + ) + Text( + text = "Lat ${friendLocation.latitude.toFloat()}, Lng ${friendLocation.longitude.toFloat()}", + fontSize = 11.sp, fontWeight = FontWeight.Light, - lineHeight = 15.sp + color = Color.White.copy(alpha = 0.8f) ) } + Icon( + imageVector = Icons.Default.Navigation, + contentDescription = null, + tint = PurrfectPalette.glowSecondary + ) } } } @@ -102,50 +156,61 @@ class BetterLocationRoot : Routes.Route() { } ?: friendsLocation } - ElevatedCard( - shape = MaterialTheme.shapes.large, - modifier = Modifier.padding(top = 32.dp, bottom = 32.dp) + GlassPanel( + modifier = Modifier + .padding(vertical = 24.dp, horizontal = 10.dp) + .fillMaxWidth() ) { - Text( - translation["teleport_to_friend_title"], - fontSize = 20.sp, - fontWeight = FontWeight.Bold, - textAlign = TextAlign.Center, - modifier = Modifier - .fillMaxWidth() - .padding(12.dp) - ) - OutlinedTextField( - modifier = Modifier - .fillMaxWidth() - .padding(8.dp), - value = search, - onValueChange = { search = it }, - label = { Text(translation["search_bar"]) } - ) - LazyColumn( - modifier = Modifier - .fillMaxSize() - ) { - item { - if (friendsLocation.isEmpty()) { - Text( - translation["no_friends_map"], - fontSize = 16.sp, - modifier = Modifier.padding(16.dp), - fontWeight = FontWeight.Light - ) - } else if (filteredFriendsLocation.isEmpty()) { - Text( - translation["no_friends_found"], - fontSize = 16.sp, - modifier = Modifier.padding(16.dp), - fontWeight = FontWeight.Light - ) + Column(verticalArrangement = Arrangement.spacedBy(12.dp)) { + Text( + translation["teleport_to_friend_title"], + fontSize = 20.sp, + fontWeight = FontWeight.ExtraBold, + textAlign = TextAlign.Center, + modifier = Modifier.fillMaxWidth(), + color = Color.White + ) + OutlinedTextField( + modifier = Modifier.fillMaxWidth(), + value = search, + onValueChange = { search = it }, + label = { Text(translation["search_bar"]) }, + colors = TextFieldDefaults.colors( + focusedContainerColor = Color.White.copy(alpha = 0.08f), + unfocusedContainerColor = Color.White.copy(alpha = 0.05f), + focusedIndicatorColor = Color.Transparent, + unfocusedIndicatorColor = Color.Transparent, + cursorColor = PurrfectPalette.glowSecondary + ), + singleLine = true + ) + LazyColumn( + modifier = Modifier.fillMaxWidth() + ) { + item { + if (friendsLocation.isEmpty()) { + Text( + translation["no_friends_map"], + fontSize = 16.sp, + modifier = Modifier.padding(16.dp), + fontWeight = FontWeight.Light, + color = PurrfectPalette.textSecondary, + textAlign = TextAlign.Center + ) + } else if (filteredFriendsLocation.isEmpty()) { + Text( + translation["no_friends_found"], + fontSize = 16.sp, + modifier = Modifier.padding(16.dp), + fontWeight = FontWeight.Light, + color = PurrfectPalette.textSecondary, + textAlign = TextAlign.Center + ) + } + } + items(filteredFriendsLocation) { friendLocation -> + FriendLocationItem(friendLocation, dismiss) } - } - items(filteredFriendsLocation) { friendLocation -> - FriendLocationItem(friendLocation, dismiss) } } } @@ -192,7 +257,7 @@ class BetterLocationRoot : Routes.Route() { } if (showTeleportDialog) { - me.rhunk.snapenhance.ui.util.Dialog( + me.eternal.purrfectsnap.ui.util.Dialog( properties = DialogProperties(usePlatformDefaultWidth = false), onDismissRequest = { showTeleportDialog = false }, content = { @@ -210,22 +275,27 @@ class BetterLocationRoot : Routes.Route() { modifier = Modifier .fillMaxSize() ) { - Text( - translation.format( - "spoofed_coordinates_title", - "latitude" to ((spoofedCoordinates?.first as? Double)?.toFloat() ?: "0.0").toString(), - "longitude" to ((spoofedCoordinates?.second as? Double)?.toFloat() ?: "0.0").toString() - ), - fontSize = 18.sp, - fontWeight = FontWeight.Bold, - textAlign = TextAlign.Center, + GlassPanel( modifier = Modifier .fillMaxWidth() - .padding(8.dp) - ) + .padding(horizontal = 12.dp, vertical = 8.dp) + ) { + Text( + translation.format( + "spoofed_coordinates_title", + "latitude" to ((spoofedCoordinates?.first as? Double)?.toFloat() ?: "0.0").toString(), + "longitude" to ((spoofedCoordinates?.second as? Double)?.toFloat() ?: "0.0").toString() + ), + fontSize = 18.sp, + fontWeight = FontWeight.ExtraBold, + textAlign = TextAlign.Center, + color = Color.White, + modifier = Modifier.fillMaxWidth() + ) + } if (addSavedCoordinateDialog) { - me.rhunk.snapenhance.ui.util.Dialog( + me.eternal.purrfectsnap.ui.util.Dialog( onDismissRequest = { addSavedCoordinateDialog = false }, content = { AddCoordinatesDialog( @@ -248,14 +318,32 @@ class BetterLocationRoot : Routes.Route() { } if (showMap) { - me.rhunk.snapenhance.ui.util.Dialog( + me.eternal.purrfectsnap.ui.util.Dialog( onDismissRequest = { showMap = false }, content = { - alertDialogs.ChooseLocationDialog(property = coordinatesProperty, marker, mapView, saveCoordinates = { - addSavedCoordinateDialog = true - }) { - showMap = false - context.config.writeConfig() + Surface( + shape = RoundedCornerShape(24.dp), + color = Color.White.copy(alpha = 0.06f), + tonalElevation = 0.dp, + shadowElevation = 16.dp, + border = BorderStroke( + 1.dp, + Brush.linearGradient( + listOf( + PurrfectPalette.glowPrimary.copy(alpha = 0.45f), + PurrfectPalette.glowSecondary.copy(alpha = 0.35f) + ) + ) + ) + ) { + Box(modifier = Modifier.background(PurrfectPalette.cardOverlay)) { + alertDialogs.ChooseLocationDialog(property = coordinatesProperty, marker, mapView, saveCoordinates = { + addSavedCoordinateDialog = true + }) { + showMap = false + context.config.writeConfig() + } + } } DisposableEffect(Unit) { onDispose { @@ -290,7 +378,8 @@ class BetterLocationRoot : Routes.Route() { onCheckedChange = { state.value = it onCheckedChange(it) - } + }, + colors = purrfectSwitchColors() ) } } @@ -308,41 +397,76 @@ class BetterLocationRoot : Routes.Route() { } } item { - Row( + GlassPanel( modifier = Modifier .fillMaxWidth() - .padding(8.dp), - horizontalArrangement = Arrangement.SpaceEvenly, - verticalAlignment = Alignment.CenterVertically + .padding(horizontal = 12.dp, vertical = 6.dp) ) { - Button(onClick = { showMap = true }) { - Text(translation["choose_location_button"]) - } - Button(onClick = { showTeleportDialog = true }) { - Text(translation["teleport_to_friend_button"]) + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.spacedBy(10.dp), + verticalAlignment = Alignment.CenterVertically + ) { + Button( + onClick = { showMap = true }, + modifier = Modifier.weight(1f), + colors = ButtonDefaults.buttonColors( + containerColor = PurrfectPalette.glowPrimary.copy(alpha = 0.28f), + contentColor = Color.White + ) + ) { + Icon(Icons.Filled.Map, contentDescription = null, modifier = Modifier.size(18.dp)) + Spacer(Modifier.width(6.dp)) + Text(translation["choose_location_button"]) + } + Button( + onClick = { showTeleportDialog = true }, + modifier = Modifier.weight(1f), + colors = ButtonDefaults.buttonColors( + containerColor = PurrfectPalette.glowSecondary.copy(alpha = 0.28f), + contentColor = Color.White + ) + ) { + Icon(Icons.Filled.Navigation, contentDescription = null, modifier = Modifier.size(18.dp)) + Spacer(Modifier.width(6.dp)) + Text(translation["teleport_to_friend_button"]) + } } } } item { - Row( + GlassPanel( modifier = Modifier .fillMaxWidth() - .padding(start = 12.dp, end = 12.dp), - verticalAlignment = Alignment.CenterVertically, + .padding(horizontal = 12.dp, vertical = 6.dp) ) { - Text( - translation["saved_coordinates_title"], - fontSize = 20.sp, - fontWeight = FontWeight.Bold, - modifier = Modifier.weight(1f), - lineHeight = 20.sp - ) - IconButton( - onClick = { - addSavedCoordinateDialog = true - } + Row( + modifier = Modifier.fillMaxWidth(), + verticalAlignment = Alignment.CenterVertically, ) { - Icon(Icons.Default.Add, contentDescription = translation["add_icon_description"]) + Column(Modifier.weight(1f)) { + Text( + translation["saved_coordinates_title"], + fontSize = 20.sp, + fontWeight = FontWeight.ExtraBold, + lineHeight = 22.sp, + color = Color.White + ) + Text( + translation["saved_coordinates_subtitle"], + fontSize = 12.sp, + color = PurrfectPalette.textSecondary + ) + } + FilledIconButton( + onClick = { addSavedCoordinateDialog = true }, + colors = IconButtonDefaults.filledIconButtonColors( + containerColor = Color.White.copy(alpha = 0.12f), + contentColor = Color.White + ) + ) { + Icon(Icons.Default.Add, contentDescription = translation["add_icon_description"]) + } } } } @@ -351,8 +475,10 @@ class BetterLocationRoot : Routes.Route() { Text( translation["no_saved_coordinates_hint"], fontSize = 16.sp, - modifier = Modifier.padding(start = 20.dp), - fontWeight = FontWeight.Light + modifier = Modifier + .padding(start = 20.dp, top = 8.dp), + fontWeight = FontWeight.Light, + color = PurrfectPalette.textSecondary ) } } @@ -371,7 +497,7 @@ class BetterLocationRoot : Routes.Route() { } if (showDeleteDialog) { - me.rhunk.snapenhance.ui.util.Dialog( + me.eternal.purrfectsnap.ui.util.Dialog( onDismissRequest = { showDeleteDialog = false }, content = { alertDialogs.ConfirmDialog( @@ -391,7 +517,7 @@ class BetterLocationRoot : Routes.Route() { } if (showEditDialog) { - me.rhunk.snapenhance.ui.util.Dialog( + me.eternal.purrfectsnap.ui.util.Dialog( onDismissRequest = { showEditDialog = false }, content = { AddCoordinatesDialog( @@ -418,46 +544,48 @@ class BetterLocationRoot : Routes.Route() { ) } - ElevatedCard( - onClick = { - mutableCoordinates = coordinates - setSpoofedCoordinates() - GeoPoint(coordinates.latitude, coordinates.longitude).also { - marker.value?.position = it - mapView.value?.controller?.apply { - animateTo(it) - setZoom(16.0) - } - } - }, + GlassPanel( modifier = Modifier .fillMaxWidth() - .padding(5.dp), + .padding(horizontal = 8.dp, vertical = 6.dp) + .clickable { + mutableCoordinates = coordinates + setSpoofedCoordinates() + GeoPoint(coordinates.latitude, coordinates.longitude).also { + marker.value?.position = it + mapView.value?.controller?.apply { + animateTo(it) + setZoom(16.0) + } + } + } ) { Row( - modifier = Modifier - .fillMaxWidth() - .padding(4.dp), - verticalAlignment = Alignment.CenterVertically + modifier = Modifier.fillMaxWidth(), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(10.dp) ) { Column( modifier = Modifier - .padding(2.dp) - .weight(1f) + .padding(vertical = 2.dp) + .weight(1f), + verticalArrangement = Arrangement.spacedBy(4.dp) ) { Text( text = remember(mutableCoordinates) { mutableCoordinates.name }, - fontWeight = if (isSelected) FontWeight.Bold else FontWeight.Light, + fontWeight = if (isSelected) FontWeight.ExtraBold else FontWeight.SemiBold, fontSize = 16.sp, lineHeight = 20.sp, - overflow = TextOverflow.Ellipsis + overflow = TextOverflow.Ellipsis, + color = Color.White ) Text( text = remember(mutableCoordinates) { "(${mutableCoordinates.latitude.toFloat()}, ${mutableCoordinates.longitude.toFloat()})" }, - fontWeight = if (isSelected) FontWeight.Bold else FontWeight.Light, + fontWeight = FontWeight.Medium, fontSize = 12.sp, lineHeight = 15.sp, - overflow = TextOverflow.Ellipsis + overflow = TextOverflow.Ellipsis, + color = PurrfectPalette.textSecondary ) } FilledIconButton(onClick = { @@ -465,7 +593,6 @@ class BetterLocationRoot : Routes.Route() { }) { Icon(Icons.Default.Edit, contentDescription = translation["edit_icon_description"]) } - Spacer(modifier = Modifier.width(4.dp)) FilledIconButton(onClick = { showDeleteDialog = true }) { diff --git a/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/scripting/ManageScriptReposSection.kt b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/scripting/ManageScriptReposSection.kt new file mode 100644 index 00000000..d6a66b09 --- /dev/null +++ b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/scripting/ManageScriptReposSection.kt @@ -0,0 +1,409 @@ +package me.eternal.purrfectsnap.ui.manager.pages.scripting + +import androidx.compose.animation.AnimatedVisibility +import androidx.compose.foundation.BorderStroke +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.WindowInsets +import androidx.compose.foundation.layout.asPaddingValues +import androidx.compose.foundation.layout.statusBars +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Error +import androidx.compose.material.icons.filled.Public +import androidx.compose.material3.Button +import androidx.compose.material3.ButtonDefaults +import androidx.compose.material3.CircularProgressIndicator +import androidx.compose.material3.ExtendedFloatingActionButton +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.OutlinedTextField +import androidx.compose.material3.Surface +import androidx.compose.material3.Text +import androidx.compose.material3.TextButton +import androidx.compose.material3.TextFieldDefaults +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalDensity +import androidx.compose.ui.focus.FocusRequester +import androidx.compose.ui.focus.focusRequester +import androidx.compose.ui.graphics.Brush +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.layout.onGloballyPositioned +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import androidx.compose.ui.zIndex +import androidx.core.net.toUri +import androidx.compose.ui.window.Dialog +import com.google.gson.JsonParser +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import kotlinx.coroutines.runBlocking +import me.eternal.purrfectsnap.common.util.ktx.getUrlFromClipboard +import me.eternal.purrfectsnap.storage.addRepo +import me.eternal.purrfectsnap.storage.getRepositories +import me.eternal.purrfectsnap.storage.removeRepo +import me.eternal.purrfectsnap.ui.manager.Routes +import me.eternal.purrfectsnap.ui.manager.components.AestheticDialog +import me.eternal.purrfectsnap.ui.manager.components.AestheticEmptyState +import me.eternal.purrfectsnap.ui.manager.components.FloatingTopBar +import me.eternal.purrfectsnap.ui.manager.theme.PurrfectPalette +import okhttp3.OkHttpClient + +class ManageScriptReposSection : Routes.Route() { + override val translation by lazy { context.translation.getCategory("manager.scripting.repos") } + private val refreshTrigger = mutableStateOf(0) + private val okHttpClient by lazy { OkHttpClient() } + + private fun extractRepoInfo(url: String): Pair { + if (url.contains("raw.githubusercontent.com")) { + val parts = url.removePrefix("https://raw.githubusercontent.com/").split("/") + if (parts.size >= 2) { + return parts[1] to parts[0] + } + } + return url.substringAfterLast("/").substringBeforeLast(".") to url.substringAfter("://").substringBefore("/") + } + + override val floatingActionButton: @Composable () -> Unit = { + var showAddDialog by remember { mutableStateOf(false) } + var showErrorDialog by remember { mutableStateOf(false) } + var errorDialogMessage by remember { mutableStateOf("") } + + if (showErrorDialog) { + AestheticDialog( + onDismissRequest = { showErrorDialog = false }, + title = translation["invalid_repo_title"], + text = errorDialogMessage, + icon = Icons.Default.Error, + confirmButtonText = translation["button.ok"], + onConfirm = { showErrorDialog = false }, + showCloseButton = false + ) + } + + ExtendedFloatingActionButton( + onClick = { showAddDialog = true }, + containerColor = PurrfectPalette.glowPrimary.copy(alpha = 0.34f), + contentColor = Color.White + ) { + Icon(Icons.Default.Public, contentDescription = null, tint = Color.White) + Spacer(modifier = Modifier.width(8.dp)) + Text(translation["add_repo_button"]) + } + + if (showAddDialog) { + val coroutineScope = rememberCoroutineScope { Dispatchers.IO } + + var url by remember { mutableStateOf("") } + var loading by remember { mutableStateOf(false) } + + Dialog(onDismissRequest = { showAddDialog = false }) { + val focusRequester = remember { FocusRequester() } + Surface( + shape = RoundedCornerShape(24.dp), + color = Color.Transparent, + tonalElevation = 0.dp, + shadowElevation = 16.dp, + border = BorderStroke( + 1.dp, + Brush.linearGradient( + listOf( + PurrfectPalette.glowPrimary.copy(alpha = 0.55f), + PurrfectPalette.glowSecondary.copy(alpha = 0.45f) + ) + ) + ) + ) { + Column( + modifier = Modifier + .background(PurrfectPalette.cardOverlay, RoundedCornerShape(24.dp)) + .padding(horizontal = 18.dp, vertical = 16.dp), + verticalArrangement = Arrangement.spacedBy(12.dp) + ) { + Row( + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(10.dp) + ) { + Surface( + shape = CircleShape, + color = PurrfectPalette.glowPrimary.copy(alpha = 0.18f) + ) { + Icon( + Icons.Default.Public, + contentDescription = null, + tint = Color.White, + modifier = Modifier.padding(10.dp) + ) + } + Column { + Text( + text = translation["add_repo_dialog_title"], + color = Color.White, + fontWeight = FontWeight.ExtraBold, + fontSize = 18.sp + ) + Text( + text = translation["manager.dialogs.scripting.repo_hint"] + ?: translation["repo_url_label"] + ?: "", + color = PurrfectPalette.textSecondary, + style = MaterialTheme.typography.bodySmall + ) + } + } + OutlinedTextField( + modifier = Modifier + .fillMaxWidth() + .focusRequester(focusRequester) + .onGloballyPositioned { focusRequester.requestFocus() }, + value = url, + onValueChange = { url = it }, + label = { Text(translation["repo_url_label"], color = PurrfectPalette.textSecondary) }, + singleLine = true, + colors = TextFieldDefaults.colors( + focusedIndicatorColor = Color.Transparent, + unfocusedIndicatorColor = Color.Transparent, + focusedContainerColor = Color.White.copy(alpha = 0.08f), + unfocusedContainerColor = Color.White.copy(alpha = 0.05f), + cursorColor = PurrfectPalette.glowSecondary, + focusedLabelColor = PurrfectPalette.textSecondary, + unfocusedLabelColor = PurrfectPalette.textSecondary + ) + ) + LaunchedEffect(Unit) { + context.androidContext.getUrlFromClipboard()?.let { url = it } + } + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.spacedBy(10.dp, Alignment.End) + ) { + TextButton(onClick = { showAddDialog = false }) { + Text(translation["button.cancel"], color = PurrfectPalette.textSecondary) + } + Button( + enabled = !loading && url.isNotBlank(), + onClick = { + loading = true + coroutineScope.launch { + runCatching { + var modifiedUrl = url + if (url.startsWith("https://github.com/")) { + val splitUrl = modifiedUrl.removePrefix("https://github.com/").split("/") + val repoName = splitUrl[0] + "/" + splitUrl[1] + okHttpClient.newCall( + okhttp3.Request.Builder().url("https://api.github.com/repos/$repoName").build() + ).execute().use { response -> + if (!response.isSuccessful) { + throw Exception("Failed to fetch default branch: ${response.code}") + } + val json = response.body?.string() ?: throw Exception("Empty response") + val defaultBranch = Regex("\"default_branch\":\"([^\"]+)\"").find(json)?.groupValues?.get(1) + ?: throw Exception("No default_branch field") + modifiedUrl = "https://raw.githubusercontent.com/$repoName/$defaultBranch/" + } + } + + val indexUrl = modifiedUrl.toUri().buildUpon().appendPath("index.json").build().toString() + val request = okhttp3.Request.Builder().url(indexUrl).build() + val isValid = okHttpClient.newCall(request).execute().use { response -> + if (!response.isSuccessful) throw Exception("Failed to fetch index.json: ${response.code}") + val indexJson = response.body?.string() ?: throw Exception("Empty index.json") + JsonParser.parseString(indexJson).asJsonObject.has("scripts") + } + + if (isValid) { + context.database.addRepo("script", modifiedUrl) + context.shortToast(translation["repo_added_toast"]) + showAddDialog = false + refreshTrigger.value++ + } else { + errorDialogMessage = translation["invalid_repo_error"] + showErrorDialog = true + } + }.onFailure { + context.log.error("Failed to add repository", it) + context.shortToast(translation.format("add_repo_failed_toast", "message" to (it.message ?: "Unknown"))) + } + loading = false + } + }, + colors = ButtonDefaults.buttonColors( + containerColor = PurrfectPalette.glowPrimary.copy(alpha = 0.3f), + contentColor = Color.White + ) + ) { + if (loading) { + CircularProgressIndicator(modifier = Modifier.size(24.dp), color = Color.White, strokeWidth = 2.dp) + } else { + Text(translation["add_button"]) + } + } + } + } + } + } + } + } + + override val content: @Composable (androidx.navigation.NavBackStackEntry) -> Unit = { + val repositories by remember(refreshTrigger.value) { + mutableStateOf>(runBlocking { context.database.getRepositories("script") }) + } + val density = LocalDensity.current + val statusBarTopPadding = WindowInsets.statusBars.asPaddingValues().calculateTopPadding() + var topBarHeight by remember { mutableStateOf(statusBarTopPadding + 96.dp) } + + Box( + modifier = Modifier + .fillMaxSize() + .background(PurrfectPalette.backgroundGradient) + ) { + FloatingTopBar( + title = routeInfo.translatedKey?.value ?: (translation["title"] ?: "Repositories"), + onBack = { routes.navController.popBackStack() }, + modifier = Modifier + .zIndex(2f) + .onGloballyPositioned { + val newHeight = with(density) { it.size.height.toDp() } + if (newHeight != topBarHeight) topBarHeight = newHeight + } + ) + if (repositories.isEmpty()) { + Box( + modifier = Modifier.fillMaxSize(), + contentAlignment = Alignment.Center + ) { + AestheticEmptyState( + icon = Icons.Default.Public, + title = translation["no_repos_added"], + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 22.dp) + ) + } + } else { + LazyColumn( + modifier = Modifier.fillMaxSize(), + contentPadding = PaddingValues( + start = 12.dp, + top = topBarHeight + 12.dp, + end = 12.dp, + bottom = 18.dp + routes.bottomPadding + ), + verticalArrangement = Arrangement.spacedBy(10.dp) + ) { + items(repositories) { url -> + val (repoName, author) = remember(url) { extractRepoInfo(url) } + var showRemoveDialog by remember { mutableStateOf(false) } + + Surface( + modifier = Modifier.fillMaxWidth(), + shape = RoundedCornerShape(20.dp), + color = PurrfectPalette.cardOverlayColor, + tonalElevation = 0.dp, + shadowElevation = 10.dp, + border = BorderStroke( + 1.dp, + Brush.linearGradient( + listOf( + PurrfectPalette.glowPrimary.copy(alpha = 0.45f), + PurrfectPalette.glowSecondary.copy(alpha = 0.35f) + ) + ) + ) + ) { + Row( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 14.dp, vertical = 12.dp), + horizontalArrangement = Arrangement.spacedBy(12.dp), + verticalAlignment = Alignment.CenterVertically + ) { + Surface( + shape = CircleShape, + color = PurrfectPalette.glowPrimary.copy(alpha = 0.18f) + ) { + Icon( + Icons.Default.Public, + contentDescription = null, + modifier = Modifier.padding(10.dp), + tint = Color.White + ) + } + Column( + modifier = Modifier.weight(1f), + verticalArrangement = Arrangement.spacedBy(2.dp) + ) { + Text( + text = repoName, + fontWeight = FontWeight.SemiBold, + fontSize = 16.sp, + color = Color.White + ) + Text( + text = author, + fontSize = 13.sp, + color = PurrfectPalette.textSecondary + ) + } + + Button( + onClick = { showRemoveDialog = true }, + colors = ButtonDefaults.buttonColors( + containerColor = PurrfectPalette.glowPrimary.copy(alpha = 0.22f), + contentColor = Color.White + ) + ) { + Text(translation["remove_button"]) + } + + AnimatedVisibility(visible = showRemoveDialog) { + AestheticDialog( + onDismissRequest = { showRemoveDialog = false }, + title = translation["remove_repo_dialog_title"], + text = translation["remove_repo_dialog_text"], + icon = Icons.Default.Error, + confirmButtonText = translation["remove_button"], + dismissButtonText = translation["button.cancel"], + onDismiss = { showRemoveDialog = false }, + onConfirm = { + context.database.removeRepo("script", url) + showRemoveDialog = false + refreshTrigger.value++ + }, + showCloseButton = false + ) + } + } + } + } + } + } + } + } +} diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/scripting/ScriptCatalog.kt b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/scripting/ScriptCatalog.kt similarity index 62% rename from app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/scripting/ScriptCatalog.kt rename to app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/scripting/ScriptCatalog.kt index 4407c853..50ec029f 100644 --- a/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/scripting/ScriptCatalog.kt +++ b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/scripting/ScriptCatalog.kt @@ -1,17 +1,25 @@ @file:OptIn(androidx.compose.foundation.ExperimentalFoundationApi::class) -package me.rhunk.snapenhance.ui.manager.pages.scripting +package me.eternal.purrfectsnap.ui.manager.pages.scripting import androidx.compose.foundation.clickable +import androidx.compose.foundation.background +import androidx.compose.foundation.BorderStroke import androidx.compose.foundation.layout.* import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items import androidx.compose.animation.animateContentSize +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.automirrored.filled.OpenInNew import androidx.compose.material.icons.filled.Code +import androidx.compose.material.icons.filled.Public import androidx.compose.material3.* import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Brush +import androidx.compose.ui.graphics.Color import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextOverflow @@ -19,8 +27,10 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.core.net.toUri import kotlinx.coroutines.* -import me.rhunk.snapenhance.common.util.ktx.openLink -import me.rhunk.snapenhance.storage.getRepositories +import me.eternal.purrfectsnap.common.util.ktx.openLink +import me.eternal.purrfectsnap.storage.getRepositories +import me.eternal.purrfectsnap.ui.manager.components.AestheticEmptyState +import me.eternal.purrfectsnap.ui.manager.theme.PurrfectPalette import okhttp3.OkHttpClient import okhttp3.Request @@ -163,39 +173,30 @@ fun ScriptCatalog(root: ScriptingRootSection) { modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center ) { - Column( - horizontalAlignment = Alignment.CenterHorizontally, - modifier = Modifier.padding(16.dp) - ) { - Text( - text = translation["no_repos_added"], - style = MaterialTheme.typography.headlineSmall, - fontWeight = FontWeight.Bold, - textAlign = TextAlign.Center, - color = MaterialTheme.colorScheme.onSurface - ) - Row( - modifier = Modifier.padding(top = 8.dp), - horizontalArrangement = Arrangement.Center, - verticalAlignment = Alignment.CenterVertically - ) { - Text( - text = translation["repo_list_info"], - style = MaterialTheme.typography.bodyLarge, - color = MaterialTheme.colorScheme.onSurfaceVariant - ) - Text( - text = translation["link_text"], - style = MaterialTheme.typography.bodyLarge, - color = MaterialTheme.colorScheme.primary, - modifier = Modifier.clickable { + AestheticEmptyState( + icon = Icons.Default.Public, + title = translation["no_repos_added"], + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 22.dp), + actions = { + Button( + onClick = { context.androidContext.openLink( - "https://github.com/particle-box/PurrfectSnap/blob/dev/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/scripting/ScriptRepos.md" + "https://github.com/particle-box/PurrfectSnap/blob/dev/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/scripting/ScriptRepos.md" ) - } - ) + }, + colors = ButtonDefaults.buttonColors( + containerColor = PurrfectPalette.glowPrimary.copy(alpha = 0.34f), + contentColor = Color.White + ) + ) { + Icon(Icons.AutoMirrored.Filled.OpenInNew, contentDescription = null) + Spacer(modifier = Modifier.width(8.dp)) + Text(translation["link_text"]) + } } - } + ) } } else { LazyColumn( @@ -208,16 +209,20 @@ fun ScriptCatalog(root: ScriptingRootSection) { CircularProgressIndicator() } } else if (allScripts.isEmpty() && repositories.isNotEmpty()) { - Text( - text = translation["no_scripts_available"], + Box( modifier = Modifier - .padding(16.dp) - .fillMaxWidth(), - textAlign = TextAlign.Center, - fontSize = 15.sp, - fontWeight = FontWeight.Light, - color = MaterialTheme.colorScheme.onSurfaceVariant - ) + .fillMaxWidth() + .padding(vertical = 28.dp, horizontal = 6.dp), + contentAlignment = Alignment.Center + ) { + AestheticEmptyState( + icon = Icons.Default.Code, + title = translation["no_scripts_available"], + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 22.dp) + ) + } } } items(allScripts) { (repoUrl, entry) -> @@ -228,53 +233,90 @@ fun ScriptCatalog(root: ScriptingRootSection) { isAlreadyInstalled = isScriptInstalled(entry.name) } - ElevatedCard(Modifier.padding(bottom = 8.dp).animateContentSize()) { + val shape = RoundedCornerShape(20.dp) + val border = remember { + Brush.linearGradient( + listOf( + PurrfectPalette.glowPrimary.copy(alpha = 0.45f), + PurrfectPalette.glowSecondary.copy(alpha = 0.35f) + ) + ) + } + Surface( + modifier = Modifier + .fillMaxWidth() + .animateContentSize(), + shape = shape, + color = PurrfectPalette.cardOverlayColor, + tonalElevation = 0.dp, + shadowElevation = 10.dp, + border = BorderStroke(1.dp, border) + ) { Row( modifier = Modifier .fillMaxWidth() - .padding(8.dp), - verticalAlignment = Alignment.CenterVertically + .background(PurrfectPalette.cardOverlay, shape) + .padding(horizontal = 14.dp, vertical = 12.dp), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(12.dp) ) { - Icon( - Icons.Default.Code, null, Modifier.padding(end = 12.dp) - ) - Column( - Modifier.weight(1f), - verticalArrangement = Arrangement.Center + Surface( + shape = CircleShape, + color = PurrfectPalette.glowPrimary.copy(alpha = 0.18f), + tonalElevation = 0.dp, + shadowElevation = 0.dp ) { - Row( - horizontalArrangement = Arrangement.spacedBy(4.dp), - verticalAlignment = Alignment.Bottom - ) { + Icon( + Icons.Default.Code, + contentDescription = null, + modifier = Modifier.padding(10.dp), + tint = Color.White + ) + } + Column( + modifier = Modifier.weight(1f), + verticalArrangement = Arrangement.spacedBy(4.dp) + ) { + Text( + text = entry.name, + maxLines = 1, + overflow = TextOverflow.Ellipsis, + fontWeight = FontWeight.ExtraBold, + color = Color.White + ) + entry.author?.let { Text( - text = entry.name, + text = translation.format("by_author", "author" to it), maxLines = 1, overflow = TextOverflow.Ellipsis, - fontWeight = FontWeight.Bold + fontSize = 12.sp, + color = PurrfectPalette.textSecondary ) - entry.author?.let { - Text( - text = translation.format("by_author", "author" to it), - maxLines = 1, - fontSize = 10.sp, - fontWeight = FontWeight.Light, - overflow = TextOverflow.Ellipsis - ) - } } - entry.description?.let { + entry.description?.takeIf { it.isNotBlank() }?.let { Text( text = it, fontSize = 12.sp, maxLines = 3, - overflow = TextOverflow.Ellipsis + overflow = TextOverflow.Ellipsis, + color = PurrfectPalette.textSecondary + ) + } + Surface( + shape = RoundedCornerShape(50), + color = Color.White.copy(alpha = 0.06f), + tonalElevation = 0.dp, + shadowElevation = 0.dp, + border = BorderStroke(1.dp, Color.White.copy(alpha = 0.12f)) + ) { + Text( + text = translation.format("version", "version" to (entry.version ?: "N/A")), + modifier = Modifier.padding(horizontal = 10.dp, vertical = 6.dp), + fontWeight = FontWeight.Medium, + fontSize = 11.sp, + color = Color.White ) } - Text( - text = translation.format("version", "version" to (entry.version ?: "N/A")), - fontWeight = FontWeight.Light, - fontSize = 11.sp - ) } Button( enabled = !isDownloading && !isAlreadyInstalled, @@ -286,14 +328,20 @@ fun ScriptCatalog(root: ScriptingRootSection) { isDownloading = false isAlreadyInstalled = isScriptInstalled(entry.name) } - } + }, + colors = ButtonDefaults.buttonColors( + containerColor = PurrfectPalette.glowPrimary.copy(alpha = 0.34f), + contentColor = Color.White, + disabledContainerColor = Color.White.copy(alpha = 0.08f), + disabledContentColor = PurrfectPalette.textSecondary + ) ) { when { isAlreadyInstalled -> Text(translation["installed_button"]) isDownloading -> CircularProgressIndicator( modifier = Modifier.size(18.dp), strokeWidth = 2.dp, - color = MaterialTheme.colorScheme.onPrimary + color = Color.White ) else -> Text(translation["download_button"]) } diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/scripting/ScriptRepos.md b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/scripting/ScriptRepos.md similarity index 100% rename from app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/scripting/ScriptRepos.md rename to app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/scripting/ScriptRepos.md diff --git a/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/scripting/ScriptingRootSection.kt b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/scripting/ScriptingRootSection.kt new file mode 100644 index 00000000..5ea96975 --- /dev/null +++ b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/scripting/ScriptingRootSection.kt @@ -0,0 +1,945 @@ +package me.eternal.purrfectsnap.ui.manager.pages.scripting + +import android.content.Intent +import androidx.compose.foundation.BorderStroke +import androidx.compose.foundation.background +import androidx.compose.foundation.border +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.automirrored.filled.ArrowForward +import androidx.compose.material.icons.filled.* +import androidx.compose.material3.* +import androidx.compose.runtime.* +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.focus.FocusRequester +import androidx.compose.ui.focus.focusRequester +import androidx.compose.ui.graphics.Brush +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.SolidColor +import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.layout.onGloballyPositioned +import androidx.compose.ui.text.font.FontStyle +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.text.style.TextOverflow +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import androidx.documentfile.provider.DocumentFile +import kotlinx.coroutines.* +import me.eternal.purrfectsnap.common.scripting.type.ModuleInfo +import me.eternal.purrfectsnap.common.scripting.ui.EnumScriptInterface +import me.eternal.purrfectsnap.common.scripting.ui.InterfaceManager +import me.eternal.purrfectsnap.common.scripting.ui.ScriptInterface +import me.eternal.purrfectsnap.common.ui.AsyncUpdateDispatcher +import me.eternal.purrfectsnap.common.ui.rememberAsyncMutableState +import me.eternal.purrfectsnap.common.ui.rememberAsyncUpdateDispatcher +import me.eternal.purrfectsnap.common.util.ktx.getUrlFromClipboard +import me.eternal.purrfectsnap.common.util.ktx.openLink +import me.eternal.purrfectsnap.storage.isScriptEnabled +import me.eternal.purrfectsnap.storage.setScriptEnabled +import me.eternal.purrfectsnap.ui.manager.Routes +import me.eternal.purrfectsnap.ui.manager.components.AestheticDialog +import me.eternal.purrfectsnap.ui.manager.components.AestheticEmptyState +import me.eternal.purrfectsnap.ui.manager.theme.PurrfectPalette +import me.eternal.purrfectsnap.ui.util.ActivityLauncherHelper +import me.eternal.purrfectsnap.ui.util.Dialog +import me.eternal.purrfectsnap.ui.util.chooseFolder +import me.eternal.purrfectsnap.ui.util.purrfectSwitchColors +import me.eternal.purrfectsnap.ui.util.pullrefresh.PullRefreshIndicator +import me.eternal.purrfectsnap.ui.util.pullrefresh.pullRefresh +import me.eternal.purrfectsnap.ui.util.pullrefresh.rememberPullRefreshState + +class ScriptingRootSection : Routes.Route() { + override val translation by lazy { context.translation.getCategory("manager.scripting") } + private lateinit var activityLauncherHelper: ActivityLauncherHelper + val reloadDispatcher = AsyncUpdateDispatcher(updateOnFirstComposition = false) + private var selectedTab by mutableStateOf(0) + + override val init: () -> Unit = { + activityLauncherHelper = ActivityLauncherHelper(context.activity!!) + } + + suspend fun isScriptInstalledByUrl(scriptUrl: String): Boolean { + return try { + val installedScripts = context.scriptManager.getSyncedModules() + installedScripts.any { module -> + module.updateUrl?.equals(scriptUrl, ignoreCase = true) == true + } + } catch (e: Exception) { + false + } + } + + fun downloadScript(scriptUrl: String, onComplete: () -> Unit) { + context.coroutineScope.launch { + if (isScriptInstalledByUrl(scriptUrl)) { + context.shortToast(translation["script_already_installed"]) + return@launch + } + + runCatching { + context.shortToast(translation["downloading_script"]) + val moduleInfo = context.scriptManager.importFromUrl(scriptUrl) + context.shortToast(translation.format("script_downloaded", "name" to moduleInfo.name)) + reloadDispatcher.dispatch() + onComplete() + }.onFailure { + context.log.error("Failed to download script", it) + context.shortToast(translation["download_script_failed"]) + } + } + } + + @Composable + private fun ImportRemoteScript( + dismiss: () -> Unit + ) { + var url by remember { mutableStateOf("") } + val focusRequester = remember { FocusRequester() } + var isLoading by remember { mutableStateOf(false) } + + LaunchedEffect(Unit) { + context.androidContext.getUrlFromClipboard()?.let { url = it } + } + + AestheticDialog( + onDismissRequest = dismiss, + title = translation["import_script_from_url_title"], + text = translation["import_script_warning"], + icon = Icons.Default.Link, + confirmButtonText = translation["import_button"], + dismissButtonText = translation["button.cancel"], + onDismiss = dismiss, + loading = isLoading, + confirmEnabled = url.isNotBlank(), + showCloseButton = false, + onConfirm = { + isLoading = true + context.coroutineScope.launch { + runCatching { + if (isScriptInstalledByUrl(url)) { + context.shortToast(translation["script_already_installed"]) + withContext(Dispatchers.Main) { + dismiss() + } + return@launch + } + + val moduleInfo = context.scriptManager.importFromUrl(url) + context.shortToast(translation.format("script_imported", "name" to moduleInfo.name)) + reloadDispatcher.dispatch() + withContext(Dispatchers.Main) { + dismiss() + } + return@launch + }.onFailure { + context.log.error("Failed to import script", it) + context.shortToast(translation.format("import_failed", "message" to (it.message ?: "Unknown"))) + } + isLoading = false + } + }, + customContent = { + OutlinedTextField( + value = url, + onValueChange = { url = it }, + label = { Text(text = translation["enter_url_label"]) }, + modifier = Modifier + .fillMaxWidth() + .focusRequester(focusRequester) + .onGloballyPositioned { focusRequester.requestFocus() }, + singleLine = true, + colors = TextFieldDefaults.colors( + focusedContainerColor = Color.White.copy(alpha = 0.06f), + unfocusedContainerColor = Color.White.copy(alpha = 0.05f), + focusedIndicatorColor = PurrfectPalette.glowSecondary.copy(alpha = 0.5f), + unfocusedIndicatorColor = Color.White.copy(alpha = 0.12f), + cursorColor = PurrfectPalette.glowSecondary, + focusedTextColor = Color.White, + unfocusedTextColor = Color.White, + focusedLabelColor = Color.White, + unfocusedLabelColor = PurrfectPalette.textSecondary + ) + ) + } + ) + } + + @Composable + private fun ModuleActions( + script: ModuleInfo, + canUpdate: Boolean, + dismiss: () -> Unit + ) { + Dialog(onDismissRequest = dismiss) { + ElevatedCard(modifier = Modifier.fillMaxWidth().padding(2.dp)) { + val actions = remember { + mutableMapOf, suspend () -> Unit>().apply { + if (canUpdate) { + put(translation["update_module_button"] to Icons.Default.Download) { + dismiss() + context.shortToast(translation.format("updating_script", "name" to script.name)) + runCatching { + val modulePath = context.scriptManager.getModulePath(script.name) ?: throw Exception(translation["module_not_found"]) + context.scriptManager.unloadScript(modulePath) + val moduleInfo = context.scriptManager.importFromUrl(script.updateUrl!!, filepath = modulePath) + context.shortToast(translation.format("updated_script", "name" to script.name, "version" to moduleInfo.version)) + context.database.setScriptEnabled(script.name, false) + withContext(context.database.executor.asCoroutineDispatcher()) { + reloadDispatcher.dispatch() + } + }.onFailure { + context.log.error("Failed to update module", it) + context.shortToast(translation["update_module_failed"]) + } + } + } + put(translation["edit_module_button"] to Icons.Default.Edit) { + runCatching { + val modulePath = context.scriptManager.getModulePath(script.name)!! + context.androidContext.startActivity( + Intent(Intent.ACTION_VIEW).apply { + data = context.scriptManager.getScriptsFolder()!!.findFile(modulePath)!!.uri + flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION + } + ) + dismiss() + }.onFailure { + context.log.error("Failed to open module file", it) + context.shortToast(translation["open_module_failed"]) + } + } + put(translation["clear_module_data_button"] to Icons.Default.Save) { + runCatching { + context.scriptManager.getModuleDataFolder(script.name).deleteRecursively() + context.shortToast(translation["module_data_cleared"]) + dismiss() + }.onFailure { + context.log.error("Failed to clear module data", it) + context.shortToast(translation["clear_module_data_failed"]) + } + } + put(translation["delete_module_button"] to Icons.Default.DeleteOutline) { + context.scriptManager.apply { + runCatching { + val modulePath = getModulePath(script.name)!! + unloadScript(modulePath) + getScriptsFolder()?.findFile(modulePath)?.delete() + reloadDispatcher.dispatch() + context.shortToast(translation.format("deleted_script", "name" to script.name)) + dismiss() + }.onFailure { + context.log.error("Failed to delete module", it) + context.shortToast(translation["delete_module_failed"]) + } + } + } + }.toMap() + } + LazyColumn(modifier = Modifier.fillMaxWidth()) { + item { + Text( + text = translation["actions_title"], + fontSize = 22.sp, + fontWeight = FontWeight.Bold, + modifier = Modifier.padding(16.dp).fillMaxWidth(), + textAlign = TextAlign.Center, + ) + } + items(actions.size) { index -> + val action = actions.entries.elementAt(index) + ListItem( + modifier = Modifier + .clickable { context.coroutineScope.launch { action.value(); dismiss() } } + .fillMaxWidth(), + leadingContent = { + Icon(action.key.second, action.key.first) + }, + headlineContent = { Text(action.key.first) } + ) + } + } + } + } + } + + @Composable + fun ModuleItem(script: ModuleInfo) { + var enabled by rememberAsyncMutableState(defaultValue = false, keys = arrayOf(script)) { + context.database.isScriptEnabled(script.name) + } + var openSettings by remember(script) { mutableStateOf(false) } + var openActions by remember { mutableStateOf(false) } + + val dispatcher = rememberAsyncUpdateDispatcher() + val reloadCallback = remember { suspend { dispatcher.dispatch() } } + val latestUpdate by rememberAsyncMutableState(defaultValue = null, updateDispatcher = dispatcher, keys = arrayOf(script)) { + context.scriptManager.checkForUpdate(script) + } + + LaunchedEffect(Unit) { + reloadDispatcher.addCallback(reloadCallback) + } + DisposableEffect(Unit) { + onDispose { reloadDispatcher.removeCallback(reloadCallback) } + } + + val cardShape = RoundedCornerShape(20.dp) + Surface( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 10.dp, vertical = 8.dp), + shape = cardShape, + color = Color.Transparent, + tonalElevation = 0.dp, + shadowElevation = 8.dp, + border = BorderStroke( + 1.dp, + if (enabled) Brush.linearGradient(listOf(PurrfectPalette.glowPrimary, PurrfectPalette.glowSecondary)) + else SolidColor(Color.White.copy(alpha = 0.08f)) + ) + ) { + Column( + modifier = Modifier + .fillMaxWidth() + .clickable(enabled = enabled) { if (enabled) openSettings = !openSettings } + .background(PurrfectPalette.cardOverlay, cardShape) + .padding(horizontal = 14.dp, vertical = 12.dp), + verticalArrangement = Arrangement.spacedBy(10.dp) + ) { + Row( + modifier = Modifier.fillMaxWidth(), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(10.dp) + ) { + Box( + modifier = Modifier + .size(46.dp) + .clip(RoundedCornerShape(14.dp)) + .background( + Brush.radialGradient( + listOf( + PurrfectPalette.glowPrimary.copy(alpha = 0.35f), + Color.Transparent + ) + ) + ) + .border(1.dp, Color.White.copy(alpha = 0.16f), RoundedCornerShape(14.dp)), + contentAlignment = Alignment.Center + ) { + Icon( + imageVector = Icons.Default.Extension, + contentDescription = null, + tint = Color.White + ) + } + Column( + modifier = Modifier.weight(1f), + verticalArrangement = Arrangement.spacedBy(6.dp) + ) { + Text( + text = script.displayName ?: script.name, + fontSize = 18.sp, + fontWeight = FontWeight.SemiBold, + color = Color.White, + maxLines = 1, + overflow = TextOverflow.Ellipsis + ) + Text( + text = script.description ?: translation["no_description"], + fontSize = 13.sp, + color = PurrfectPalette.textSecondary, + maxLines = 2, + overflow = TextOverflow.Ellipsis + ) + Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) { + latestUpdate?.let { + AssistChip( + onClick = { }, + enabled = false, + leadingIcon = { Icon(Icons.Default.Star, contentDescription = null, tint = PurrfectPalette.glowSecondary) }, + label = { Text(translation.format("update_available", "version" to it.version)) }, + colors = AssistChipDefaults.assistChipColors( + containerColor = Color.White.copy(alpha = 0.08f), + labelColor = Color.White + ) + ) + } + if (openSettings && enabled) { + AssistChip( + onClick = {}, + enabled = false, + label = { Text(translation["actions_button"]) }, + leadingIcon = { Icon(Icons.Default.Settings, contentDescription = null) }, + colors = AssistChipDefaults.assistChipColors( + containerColor = Color.White.copy(alpha = 0.06f), + labelColor = Color.White + ) + ) + } + } + } + IconButton(onClick = { openActions = !openActions }) { + Icon(Icons.Default.Build, translation["actions_button"], tint = Color.White) + } + Switch( + checked = enabled, + onCheckedChange = { isChecked -> + openSettings = false + context.coroutineScope.launch(Dispatchers.IO) { + runCatching { + val modulePath = context.scriptManager.getModulePath(script.name)!! + context.scriptManager.unloadScript(modulePath) + if (isChecked) { + context.scriptManager.loadScript(modulePath) + context.scriptManager.runtime.getModuleByName(script.name) + ?.callFunction("module.onPurrfectSnapLoad") + context.shortToast(translation.format("loaded_script", "name" to script.name)) + } else { + context.shortToast(translation.format("unloaded_script", "name" to script.name)) + } + context.database.setScriptEnabled(script.name, isChecked) + withContext(Dispatchers.Main) { enabled = isChecked } + }.onFailure { throwable -> + withContext(Dispatchers.Main) { enabled = !isChecked } + context.log.error("Failed to ${if (isChecked) "enable" else "disable"} script", throwable) + context.shortToast(translation.format(if (isChecked) "enable_script_failed" else "disable_script_failed")) + } + } + }, + colors = purrfectSwitchColors() + ) + } + if (openSettings) { + Divider(color = Color.White.copy(alpha = 0.08f)) + ScriptSettings(script) + } + } + } + if (openActions) { + ModuleActions(script = script, canUpdate = latestUpdate != null) { openActions = false } + } + } + + override val floatingActionButton: @Composable () -> Unit = {} + + @Composable + private fun SelectFolderButton(onClick: () -> Unit) { + val label = translation.getOrNull("select_folder_button") ?: "Select folder" + Box( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 16.dp, vertical = 4.dp), + contentAlignment = Alignment.Center + ) { + Surface( + modifier = Modifier.size(68.dp), + shape = CircleShape, + color = Color.White.copy(alpha = 0.1f), + tonalElevation = 0.dp, + shadowElevation = 10.dp, + border = BorderStroke( + 1.dp, + Brush.linearGradient( + listOf( + PurrfectPalette.glowPrimary.copy(alpha = 0.7f), + PurrfectPalette.glowSecondary.copy(alpha = 0.65f) + ) + ) + ) + ) { + Box( + modifier = Modifier + .fillMaxSize() + .clip(CircleShape) + .background( + Brush.radialGradient( + colors = listOf( + PurrfectPalette.glowPrimary.copy(alpha = 0.335f), + PurrfectPalette.glowSecondary.copy(alpha = 0.25f), + Color.Transparent + ) + ) + ) + .clickable(onClick = onClick), + contentAlignment = Alignment.Center + ) { + Icon( + imageVector = Icons.AutoMirrored.Filled.ArrowForward, + contentDescription = label, + tint = Color.White, + modifier = Modifier.size(32.dp) + ) + } + } + } + } + + @Composable + fun ScriptSettings(script: ModuleInfo) { + val settingsInterface = remember { + val module = + context.scriptManager.runtime.getModuleByName(script.name) ?: return@remember null + (module.getBinding(InterfaceManager::class))?.buildInterface(EnumScriptInterface.SETTINGS) + } + if (settingsInterface == null) { + Text( + text = translation["no_settings_for_module"], + style = MaterialTheme.typography.bodySmall, + modifier = Modifier.padding(8.dp) + ) + } else { + ScriptInterface(interfaceBuilder = settingsInterface) + } + } + + override val content: @Composable (androidx.navigation.NavBackStackEntry) -> Unit = { + val scriptingFolder by rememberAsyncMutableState( + defaultValue = null, + updateDispatcher = reloadDispatcher + ) { context.scriptManager.getScriptsFolder() } + val tabTitles = listOf(translation["installed_scripts_tab"], translation["catalog_tab"]) + var showImportDialog by remember { mutableStateOf(false) } + var showToast by remember { mutableStateOf(false) } + + LaunchedEffect(scriptingFolder) { + if (scriptingFolder == null && selectedTab != 0) { + selectedTab = 0 + } + } + + if (showImportDialog) { + ImportRemoteScript { showImportDialog = false } + } + if (showToast) { + LaunchedEffect(showToast) { + context.shortToast(translation["select_scripts_folder_toast"]) + showToast = false + } + } + + Column( + modifier = Modifier + .fillMaxSize() + .background(PurrfectPalette.backgroundGradient) + ) { + ScriptingHeader( + titles = tabTitles, + selectedTab = selectedTab, + onTabSelected = { index -> + if (index == 1 && scriptingFolder == null) { + showToast = true + } else { + selectedTab = index + } + }, + onImport = { + if (scriptingFolder == null) showToast = true else showImportDialog = true + }, + onOpenFolder = { + if (scriptingFolder == null) showToast = true else scriptingFolder?.let { context.androidContext.openLink(it.uri.toString()) } + }, + onManageRepos = { routes.manageScriptRepos.navigate() }, + onDocs = { context.androidContext.openLink("https://github.com/SnapEnhance/scripting-docs") }, + folderSelected = scriptingFolder != null + ) + Spacer(Modifier.height(12.dp)) + when (selectedTab) { + 0 -> InstalledTabContent( + scriptingFolder = scriptingFolder + ) + 1 -> CatalogTabContent( + scriptingFolder = scriptingFolder + ) + } + } + } + + @Composable + private fun InstalledTabContent( + scriptingFolder: DocumentFile? + ) { + val scriptModules by rememberAsyncMutableState( + defaultValue = emptyList(), + updateDispatcher = reloadDispatcher + ) { context.scriptManager.sync(); context.scriptManager.getSyncedModules() } + val coroutineScope = rememberCoroutineScope() + var refreshing by remember { mutableStateOf(false) } + + LaunchedEffect(Unit) { + refreshing = true + withContext(Dispatchers.IO) { + reloadDispatcher.dispatch() + refreshing = false + } + } + val pullRefreshState = rememberPullRefreshState(refreshing, onRefresh = { + refreshing = true + coroutineScope.launch(Dispatchers.IO) { + reloadDispatcher.dispatch() + refreshing = false + } + }) + + Box( + modifier = Modifier + .fillMaxSize() + .padding(horizontal = 12.dp) + ) { + Surface( + shape = RoundedCornerShape(22.dp), + color = Color.White.copy(alpha = 0.04f), + tonalElevation = 0.dp, + shadowElevation = 0.dp, + border = BorderStroke(1.dp, Color.White.copy(alpha = 0.08f)) + ) { + Box(modifier = Modifier.fillMaxSize()) { + LazyColumn( + modifier = Modifier + .fillMaxSize() + .pullRefresh(pullRefreshState), + contentPadding = PaddingValues(bottom = routes.bottomPadding + 28.dp, start = 8.dp, end = 8.dp, top = 12.dp), + horizontalAlignment = Alignment.Start, + verticalArrangement = Arrangement.spacedBy(12.dp) + ) { + item { + if (scriptingFolder == null && !refreshing) { + Box( + modifier = Modifier + .fillMaxWidth() + .height(260.dp), + contentAlignment = Alignment.Center + ) { + Surface( + modifier = Modifier.fillMaxWidth(), + shape = RoundedCornerShape(24.dp), + color = Color.White.copy(alpha = 0.05f), + border = BorderStroke( + 1.dp, + Brush.linearGradient( + listOf( + PurrfectPalette.glowPrimary.copy(alpha = 0.6f), + PurrfectPalette.glowSecondary.copy(alpha = 0.45f) + ) + ) + ) + ) { + Column( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 20.dp, vertical = 22.dp), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.spacedBy(14.dp) + ) { + Box( + modifier = Modifier + .size(58.dp) + .clip(RoundedCornerShape(18.dp)) + .background(Color.White.copy(alpha = 0.08f)), + contentAlignment = Alignment.Center + ) { + Icon( + imageVector = Icons.Default.FolderOpen, + contentDescription = null, + tint = PurrfectPalette.glowSecondary, + modifier = Modifier.size(28.dp) + ) + } + Text( + text = translation["no_scripts_folder_selected_title"], + style = MaterialTheme.typography.headlineSmall, + fontWeight = FontWeight.ExtraBold, + textAlign = TextAlign.Center, + color = Color.White + ) + Text( + text = translation["select_scripts_folder_toast"], + style = MaterialTheme.typography.bodyMedium, + textAlign = TextAlign.Center, + color = PurrfectPalette.textSecondary, + lineHeight = 18.sp + ) + SelectFolderButton( + onClick = { + activityLauncherHelper.chooseFolder { + context.config.root.scripting.moduleFolder.set(it) + context.config.writeConfig() + coroutineScope.launch { reloadDispatcher.dispatch() } + } + } + ) + } + } + } + } else if (scriptModules.isEmpty()) { + Box( + modifier = Modifier + .fillMaxWidth() + .height(220.dp), + contentAlignment = Alignment.Center + ) { + AestheticEmptyState( + icon = Icons.Default.DataObject, + title = translation["no_scripts_found_title"], + subtitle = translation["use_catalog_to_add_scripts"], + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 22.dp) + ) + } + } + } + items(scriptModules.size, key = { scriptModules[it].hashCode() }) { index -> + ModuleItem(scriptModules[index]) + } + } + PullRefreshIndicator( + refreshing = refreshing, + state = pullRefreshState, + modifier = Modifier + .align(Alignment.TopCenter) + .padding(top = 8.dp) + ) + } + } + } + var scriptingWarning by remember { + mutableStateOf(context.sharedPreferences.run { + getBoolean("scripting_warning", true).also { + edit().putBoolean("scripting_warning", false).apply() + } + }) + } + if (scriptingWarning) { + var timeout by remember { mutableIntStateOf(10) } + LaunchedEffect(Unit) { + while (timeout > 0) { + delay(1000) + timeout-- + } + } + AestheticDialog( + onDismissRequest = { if (timeout == 0) scriptingWarning = false }, + title = context.translation["manager.dialogs.scripting_warning.title"], + text = context.translation["manager.dialogs.scripting_warning.content"], + icon = Icons.Default.Warning, + confirmButtonText = translation["button.ok"] ?: "OK", + onConfirm = { if (timeout == 0) scriptingWarning = false }, + loading = timeout > 0, + showCloseButton = false, + customContent = { + Surface( + shape = RoundedCornerShape(14.dp), + color = PurrfectPalette.cardOverlayColor, + tonalElevation = 0.dp, + shadowElevation = 0.dp, + border = BorderStroke( + 1.dp, + Brush.linearGradient( + listOf( + PurrfectPalette.glowPrimary.copy(alpha = 0.55f), + PurrfectPalette.glowSecondary.copy(alpha = 0.35f) + ) + ) + ) + ) { + Column( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 14.dp, vertical = 12.dp), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.spacedBy(8.dp) + ) { + Box( + modifier = Modifier + .size(64.dp) + .background( + Brush.radialGradient( + listOf( + PurrfectPalette.glowPrimary.copy(alpha = 0.25f), + PurrfectPalette.glowSecondary.copy(alpha = 0.18f) + ) + ), + shape = RoundedCornerShape(18.dp) + ), + contentAlignment = Alignment.Center + ) { + Text( + text = timeout.toString(), + color = Color.White, + fontWeight = FontWeight.Bold, + fontSize = 20.sp + ) + } + } + } + } + ) + } + } + + @Composable + private fun CatalogTabContent( + scriptingFolder: DocumentFile? + ) { + val coroutineScope = rememberCoroutineScope() + Box( + modifier = Modifier + .fillMaxSize() + .padding(horizontal = 12.dp) + ) { + Surface( + shape = RoundedCornerShape(22.dp), + color = Color.White.copy(alpha = 0.04f), + tonalElevation = 0.dp, + shadowElevation = 0.dp, + border = BorderStroke(1.dp, Color.White.copy(alpha = 0.08f)) + ) { + if (scriptingFolder == null) { + AestheticEmptyState( + icon = Icons.Default.FolderOpen, + title = translation["no_scripts_folder_selected_title"], + subtitle = translation["select_scripts_folder_toast"], + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 22.dp) + ) + } else { + ScriptCatalog(this@ScriptingRootSection) + } + } + } + } + + @Composable + private fun ScriptingHeader( + titles: List, + selectedTab: Int, + onTabSelected: (Int) -> Unit, + onImport: () -> Unit, + onOpenFolder: () -> Unit, + onManageRepos: () -> Unit, + onDocs: () -> Unit, + folderSelected: Boolean + ) { + Surface( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 14.dp, vertical = 12.dp) + .padding(top = WindowInsets.statusBars.asPaddingValues().calculateTopPadding()), + shape = RoundedCornerShape(26.dp), + color = Color.White.copy(alpha = 0.07f), + tonalElevation = 0.dp, + shadowElevation = 0.dp, + border = BorderStroke( + 1.dp, + Brush.linearGradient( + listOf( + PurrfectPalette.glowPrimary.copy(alpha = 0.55f), + PurrfectPalette.glowSecondary.copy(alpha = 0.35f) + ) + ) + ) + ) { + Column( + modifier = Modifier.padding(horizontal = 16.dp, vertical = 14.dp), + verticalArrangement = Arrangement.spacedBy(12.dp) + ) { + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.spacedBy(12.dp), + verticalAlignment = Alignment.CenterVertically + ) { + Column( + modifier = Modifier.weight(1f), + verticalArrangement = Arrangement.spacedBy(4.dp) + ) { + Text( + text = translation["manager.routes.scripts"] ?: "Scripts", + color = Color.White, + fontWeight = FontWeight.ExtraBold, + fontSize = 18.sp + ) + } + Row( + modifier = Modifier.wrapContentWidth(), + horizontalArrangement = Arrangement.spacedBy(8.dp), + verticalAlignment = Alignment.CenterVertically + ) { + IconButton(onClick = onDocs) { + Icon(Icons.Default.CollectionsBookmark, contentDescription = translation["documentation_button"], tint = Color.White) + } + IconButton(onClick = onManageRepos) { + Icon(Icons.Default.Public, contentDescription = translation["manage_repos_button"], tint = Color.White) + } + IconButton(onClick = onOpenFolder) { + Icon(Icons.Default.FolderOpen, contentDescription = translation["open_scripts_folder_button"], tint = Color.White) + } + IconButton(onClick = onImport, enabled = folderSelected) { + Icon(Icons.Default.Link, contentDescription = translation["import_from_url_button"], tint = if (folderSelected) Color.White else Color.White.copy(alpha = 0.4f)) + } + } + } + ScriptingTabSwitcher( + titles = titles, + selectedTab = selectedTab, + onTabSelected = onTabSelected + ) + } + } + } + + @Composable + private fun ScriptingTabSwitcher( + titles: List, + selectedTab: Int, + onTabSelected: (Int) -> Unit + ) { + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.spacedBy(10.dp) + ) { + titles.forEachIndexed { index, title -> + val isSelected = selectedTab == index + Surface( + shape = RoundedCornerShape(18.dp), + color = if (isSelected) Color.White.copy(alpha = 0.12f) else Color.White.copy(alpha = 0.06f), + border = if (isSelected) BorderStroke( + 1.dp, + Brush.linearGradient(listOf(PurrfectPalette.glowPrimary, PurrfectPalette.glowSecondary)) + ) else BorderStroke(1.dp, Color.White.copy(alpha = 0.12f)), + modifier = Modifier.weight(1f) + ) { + Row( + modifier = Modifier + .clickable { onTabSelected(index) } + .padding(horizontal = 12.dp, vertical = 10.dp), + horizontalArrangement = Arrangement.spacedBy(8.dp), + verticalAlignment = Alignment.CenterVertically + ) { + Icon( + imageVector = if (index == 0) Icons.Default.Extension else Icons.Default.Public, + contentDescription = null, + tint = Color.White + ) + Text( + text = title, + color = Color.White, + maxLines = 1, + overflow = TextOverflow.Ellipsis, + fontWeight = FontWeight.Medium + ) + } + } + } + } + } + + override val topBarActions: @Composable() (RowScope.() -> Unit) = {} +} diff --git a/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/social/AddFriendDialog.kt b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/social/AddFriendDialog.kt new file mode 100644 index 00000000..1a5d8c5f --- /dev/null +++ b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/social/AddFriendDialog.kt @@ -0,0 +1,370 @@ +package me.eternal.purrfectsnap.ui.manager.pages.social + +import androidx.compose.foundation.BorderStroke +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.foundation.text.KeyboardOptions +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Search +import androidx.compose.material3.* +import androidx.compose.runtime.* +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Brush +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.SolidColor +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.input.ImeAction +import androidx.compose.ui.text.input.KeyboardType +import androidx.compose.ui.text.style.TextOverflow +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import kotlinx.coroutines.* +import me.eternal.purrfectsnap.RemoteSideContext +import me.eternal.purrfectsnap.common.ReceiversConfig +import me.eternal.purrfectsnap.common.data.MessagingFriendInfo +import me.eternal.purrfectsnap.common.data.MessagingGroupInfo +import me.eternal.purrfectsnap.common.ui.rememberAsyncMutableState +import me.eternal.purrfectsnap.common.util.snap.BitmojiSelfie +import me.eternal.purrfectsnap.common.util.snap.SnapWidgetBroadcastReceiverHelper +import me.eternal.purrfectsnap.ui.manager.theme.PurrfectPalette +import me.eternal.purrfectsnap.ui.util.coil.BitmojiImage + +class AddFriendDialog( + private val context: RemoteSideContext, + private val actionHandler: Actions, + private val pinnedIds: List? = null +) { + class Actions( + val onFriendState: (friend: MessagingFriendInfo, state: Boolean) -> Unit, + val onGroupState: (group: MessagingGroupInfo, state: Boolean) -> Unit, + val getFriendState: (friend: MessagingFriendInfo) -> Boolean, + val getGroupState: (group: MessagingGroupInfo) -> Boolean, + ) + + private val stateCache = mutableMapOf() + private val translation by lazy { context.translation.getCategory("manager.dialogs.add_friend")} + + @Composable + private fun ListCardEntry( + id: String, + bitmoji: String? = null, + name: String, + participantsCount: Int? = null, + getCurrentState: () -> Boolean, + onState: (Boolean) -> Unit = {}, + ) { + var currentState by rememberAsyncMutableState(defaultValue = stateCache[id] ?: false) { + getCurrentState().also { stateCache[id] = it } + } + val coroutineScope = rememberCoroutineScope() + + val cardShape = RoundedCornerShape(18.dp) + Surface( + modifier = Modifier + .fillMaxWidth() + .padding(vertical = 6.dp) + .clickable { + currentState = !currentState + stateCache[id] = currentState + coroutineScope.launch(Dispatchers.IO) { onState(currentState) } + }, + shape = cardShape, + color = Color.Transparent, + tonalElevation = 0.dp, + shadowElevation = 0.dp, + border = BorderStroke( + 1.dp, + if (currentState) Brush.linearGradient(listOf(PurrfectPalette.glowPrimary, PurrfectPalette.glowSecondary)) + else SolidColor(Color.White.copy(alpha = 0.08f)) + ) + ) { + Row( + modifier = Modifier + .fillMaxWidth() + .background(PurrfectPalette.cardOverlay, cardShape) + .padding(horizontal = 12.dp, vertical = 10.dp), + horizontalArrangement = Arrangement.spacedBy(10.dp), + verticalAlignment = Alignment.CenterVertically + ) { + BitmojiImage( + context = this@AddFriendDialog.context, + url = bitmoji, + modifier = Modifier + .padding(end = 2.dp), + size = 40, + ) + + Column( + modifier = Modifier + .weight(1f), + verticalArrangement = Arrangement.spacedBy(4.dp) + ) { + Text( + text = name, + fontSize = 15.sp, + fontWeight = FontWeight.SemiBold, + maxLines = 1, + overflow = TextOverflow.Ellipsis, + color = Color.White + ) + + participantsCount?.let { + Text( + text = translation.format("participants_text", "count" to it.toString()), + fontSize = 12.sp, + lineHeight = 12.sp, + color = PurrfectPalette.textSecondary + ) + } + } + + Switch( + checked = currentState, + onCheckedChange = { + currentState = it + stateCache[id] = currentState + coroutineScope.launch(Dispatchers.IO) { onState(currentState) } + }, + colors = SwitchDefaults.colors( + checkedThumbColor = Color.White, + checkedTrackColor = PurrfectPalette.glowPrimary.copy(alpha = 0.6f), + uncheckedThumbColor = Color.White.copy(alpha = 0.8f), + uncheckedTrackColor = Color.White.copy(alpha = 0.2f) + ) + ) + } + } + } + + @Composable + private fun DialogHeader(searchKeyword: MutableState) { + Box( + modifier = Modifier + .fillMaxWidth() + .background( + brush = Brush.linearGradient( + listOf( + PurrfectPalette.glowPrimary.copy(alpha = 0.4f), + PurrfectPalette.glowSecondary.copy(alpha = 0.35f) + ) + ), + shape = RoundedCornerShape(topStart = 24.dp, topEnd = 24.dp) + ) + .padding(horizontal = 16.dp, vertical = 18.dp) + ) { + Column(verticalArrangement = Arrangement.spacedBy(6.dp)) { + Text( + text = translation["title"], + fontSize = 22.sp, + fontWeight = FontWeight.ExtraBold, + color = Color.White + ) + Text( + text = translation["search_hint"], + fontSize = 13.sp, + color = Color.White.copy(alpha = 0.85f) + ) + } + } + + Surface( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 16.dp, vertical = 14.dp), + shape = RoundedCornerShape(18.dp), + color = PurrfectPalette.cardOverlayColor, + border = BorderStroke(1.dp, Color.White.copy(alpha = 0.12f)), + tonalElevation = 0.dp, + shadowElevation = 0.dp + ) { + TextField( + value = searchKeyword.value, + onValueChange = { searchKeyword.value = it }, + placeholder = { + Text(text = translation["search_hint"]) + }, + modifier = Modifier + .fillMaxWidth(), + keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Text, imeAction = ImeAction.Done), + leadingIcon = { + Icon(Icons.Filled.Search, contentDescription = translation["search_icon_description"]) + }, + colors = TextFieldDefaults.colors( + focusedContainerColor = PurrfectPalette.cardOverlayColor.copy(alpha = 0.9f), + unfocusedContainerColor = PurrfectPalette.cardOverlayColor.copy(alpha = 0.8f), + focusedIndicatorColor = Color.Transparent, + unfocusedIndicatorColor = Color.Transparent, + cursorColor = Color.White + ) + ) + } + } + + + @Composable + fun Content(dismiss: () -> Unit = { }) { + var cachedFriends by remember { mutableStateOf(null as List?) } + var cachedGroups by remember { mutableStateOf(null as List?) } + + val coroutineScope = rememberCoroutineScope() + + var timeoutJob: Job? = null + var hasFetchError by remember { mutableStateOf(false) } + + LaunchedEffect(Unit) { + context.database.receiveMessagingDataCallback = { friends, groups -> + cachedFriends = friends.run { + if (pinnedIds != null) { + sortedBy { -pinnedIds.indexOf(it.userId) } + } else friends + } + cachedGroups = groups.run { + if (pinnedIds != null) { + sortedBy { -pinnedIds.indexOf(it.conversationId) } + } else groups + } + timeoutJob?.cancel() + hasFetchError = false + } + SnapWidgetBroadcastReceiverHelper.create(ReceiversConfig.BRIDGE_SYNC_ACTION) {}.also { + runCatching { + context.androidContext.sendBroadcast(it) + }.onFailure { + context.log.error("Failed to send broadcast", it) + hasFetchError = true + } + } + timeoutJob = coroutineScope.launch { + withContext(Dispatchers.IO) { + delay(20000) + hasFetchError = true + } + } + } + + me.eternal.purrfectsnap.ui.util.Dialog( + onDismissRequest = { + timeoutJob?.cancel() + dismiss() + }, + properties = me.eternal.purrfectsnap.ui.util.DialogProperties(usePlatformDefaultWidth = false) + ) { + val dialogShape = RoundedCornerShape(24.dp) + Surface( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 12.dp, vertical = 6.dp), + shape = dialogShape, + color = PurrfectPalette.cardOverlayColor, + tonalElevation = 0.dp, + shadowElevation = 12.dp, + border = BorderStroke(1.dp, Color.White.copy(alpha = 0.12f)) + ) { + Column { + if (cachedGroups == null || cachedFriends == null) { + Box( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 18.dp, vertical = 22.dp), + contentAlignment = Alignment.Center + ) { + if (hasFetchError) { + Text( + text = translation["fetch_error"], + fontSize = 20.sp, + fontWeight = FontWeight.Bold, + modifier = Modifier.padding(bottom = 10.dp, top = 10.dp), + color = Color.White + ) + } else { + CircularProgressIndicator( + modifier = Modifier + .size(32.dp), + strokeWidth = 3.dp, + color = PurrfectPalette.glowSecondary + ) + } + } + return@Surface + } + + val searchKeyword = remember { mutableStateOf("") } + + val filteredGroups = cachedGroups!!.takeIf { searchKeyword.value.isNotBlank() }?.filter { + it.name.contains(searchKeyword.value, ignoreCase = true) + } ?: cachedGroups!! + + val filteredFriends = cachedFriends!!.takeIf { searchKeyword.value.isNotBlank() }?.filter { + it.mutableUsername.contains(searchKeyword.value, ignoreCase = true) || + it.displayName?.contains(searchKeyword.value, ignoreCase = true) == true + } ?: cachedFriends!! + + DialogHeader(searchKeyword) + + LazyColumn( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 16.dp, vertical = 6.dp) + ) { + item { + if (filteredGroups.isNotEmpty()) { + Text( + text = translation["category_groups"], + fontSize = 16.sp, + fontWeight = FontWeight.SemiBold, + modifier = Modifier + .padding(bottom = 8.dp, top = 8.dp), + color = Color.White + ) + } + } + + items(filteredGroups.size) { + val group = filteredGroups[it] + ListCardEntry( + id = group.conversationId, + name = group.name, + participantsCount = group.participantsCount, + getCurrentState = { actionHandler.getGroupState(group) } + ) { state -> + actionHandler.onGroupState(group, state) + } + } + + item { + if (filteredFriends.isNotEmpty()) { + Text( + text = translation["category_friends"], + fontSize = 16.sp, + fontWeight = FontWeight.SemiBold, + modifier = Modifier + .padding(bottom = 8.dp, top = 14.dp), + color = Color.White + ) + } + } + + items(filteredFriends.size) { index -> + val friend = filteredFriends[index] + + ListCardEntry( + id = friend.userId, + bitmoji = friend.takeIf { it.bitmojiId != null }?.let { + BitmojiSelfie.getBitmojiSelfie(it.selfieId, it.bitmojiId, BitmojiSelfie.BitmojiSelfieType.NEW_THREE_D) + }, + name = friend.displayName?.takeIf { name -> name.isNotBlank() } ?: friend.mutableUsername, + getCurrentState = { actionHandler.getFriendState(friend) } + ) { state -> + actionHandler.onFriendState(friend, state) + } + } + } + } + } + } + } +} diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/social/LoggedStories.kt b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/social/LoggedStories.kt similarity index 94% rename from app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/social/LoggedStories.kt rename to app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/social/LoggedStories.kt index ed39e0ec..1384cc5c 100644 --- a/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/social/LoggedStories.kt +++ b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/social/LoggedStories.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.ui.manager.pages.social +package me.eternal.purrfectsnap.ui.manager.pages.social import android.content.Intent import androidx.compose.foundation.Image @@ -25,16 +25,16 @@ import androidx.navigation.compose.currentBackStackEntryAsState import androidx.compose.ui.text.style.TextOverflow import coil.annotation.ExperimentalCoilApi import coil.compose.rememberAsyncImagePainter -import me.rhunk.snapenhance.bridge.DownloadCallback -import me.rhunk.snapenhance.common.data.FileType -import me.rhunk.snapenhance.common.data.StoryData -import me.rhunk.snapenhance.common.data.download.* -import me.rhunk.snapenhance.common.util.ktx.longHashCode -import me.rhunk.snapenhance.download.DownloadProcessor -import me.rhunk.snapenhance.storage.getFriendInfo -import me.rhunk.snapenhance.ui.manager.Routes -import me.rhunk.snapenhance.ui.util.Dialog -import me.rhunk.snapenhance.ui.util.coil.ImageRequestHelper +import me.eternal.purrfectsnap.bridge.DownloadCallback +import me.eternal.purrfectsnap.common.data.FileType +import me.eternal.purrfectsnap.common.data.StoryData +import me.eternal.purrfectsnap.common.data.download.* +import me.eternal.purrfectsnap.common.util.ktx.longHashCode +import me.eternal.purrfectsnap.download.DownloadProcessor +import me.eternal.purrfectsnap.storage.getFriendInfo +import me.eternal.purrfectsnap.ui.manager.Routes +import me.eternal.purrfectsnap.ui.util.Dialog +import me.eternal.purrfectsnap.ui.util.coil.ImageRequestHelper import java.io.File import java.text.DateFormat import java.util.Date @@ -151,7 +151,7 @@ class LoggedStories : Routes.Route() { setDataAndType( FileProvider.getUriForFile( context.androidContext, - "me.rhunk.snapenhance.fileprovider", + "me.eternal.purrfectsnap.fileprovider", targetFile ), FileType.fromFile(targetFile).mimeType @@ -267,4 +267,4 @@ class LoggedStories : Routes.Route() { } } } -} \ No newline at end of file +} diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/social/ManageScope.kt b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/social/ManageScope.kt similarity index 70% rename from app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/social/ManageScope.kt rename to app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/social/ManageScope.kt index fb5e4b68..54874fa0 100644 --- a/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/social/ManageScope.kt +++ b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/social/ManageScope.kt @@ -1,8 +1,12 @@ -package me.rhunk.snapenhance.ui.manager.pages.social +package me.eternal.purrfectsnap.ui.manager.pages.social import android.content.Intent +import androidx.compose.foundation.BorderStroke import androidx.compose.foundation.layout.* +import androidx.compose.foundation.background import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.verticalScroll import androidx.compose.material.icons.Icons import androidx.compose.material.icons.rounded.DeleteForever @@ -10,50 +14,42 @@ import androidx.compose.material3.* import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Brush import androidx.compose.ui.graphics.Color +import androidx.compose.ui.layout.onGloballyPositioned +import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp +import androidx.compose.ui.zIndex import androidx.navigation.NavBackStackEntry -import androidx.navigation.compose.currentBackStackEntryAsState import androidx.compose.ui.text.style.TextOverflow import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch -import me.rhunk.snapenhance.common.data.FriendStreaks -import me.rhunk.snapenhance.common.data.MessagingFriendInfo -import me.rhunk.snapenhance.common.data.MessagingGroupInfo -import me.rhunk.snapenhance.common.data.MessagingRuleType -import me.rhunk.snapenhance.common.data.SocialScope -import me.rhunk.snapenhance.common.ui.AutoClearKeyboardFocus -import me.rhunk.snapenhance.common.ui.EditNoteTextField -import me.rhunk.snapenhance.common.ui.rememberAsyncMutableState -import me.rhunk.snapenhance.common.ui.rememberAsyncMutableStateList -import me.rhunk.snapenhance.common.util.snap.BitmojiSelfie -import me.rhunk.snapenhance.storage.* -import me.rhunk.snapenhance.ui.manager.Routes -import me.rhunk.snapenhance.ui.util.AlertDialogs -import me.rhunk.snapenhance.ui.util.Dialog -import me.rhunk.snapenhance.ui.util.coil.BitmojiImage +import me.eternal.purrfectsnap.common.data.FriendStreaks +import me.eternal.purrfectsnap.common.data.MessagingFriendInfo +import me.eternal.purrfectsnap.common.data.MessagingGroupInfo +import me.eternal.purrfectsnap.common.data.MessagingRuleType +import me.eternal.purrfectsnap.common.data.SocialScope +import me.eternal.purrfectsnap.common.ui.AutoClearKeyboardFocus +import me.eternal.purrfectsnap.common.ui.EditNoteTextField +import me.eternal.purrfectsnap.common.ui.rememberAsyncMutableState +import me.eternal.purrfectsnap.common.ui.rememberAsyncMutableStateList +import me.eternal.purrfectsnap.common.util.snap.BitmojiSelfie +import me.eternal.purrfectsnap.storage.* +import me.eternal.purrfectsnap.ui.manager.Routes +import me.eternal.purrfectsnap.ui.manager.components.AestheticDialog +import me.eternal.purrfectsnap.ui.manager.components.FloatingTopBar +import me.eternal.purrfectsnap.ui.manager.theme.PurrfectPalette +import me.eternal.purrfectsnap.ui.util.AlertDialogs +import me.eternal.purrfectsnap.ui.util.Dialog +import me.eternal.purrfectsnap.ui.util.purrfectSwitchColors +import me.eternal.purrfectsnap.ui.util.coil.BitmojiImage import kotlin.io.encoding.Base64 import kotlin.io.encoding.ExperimentalEncodingApi class ManageScope: Routes.Route() { - override val title: @Composable () -> Unit = { - val navBackStackEntry by routes.navController.currentBackStackEntryAsState() - val text by rememberAsyncMutableState(null, keys = arrayOf(navBackStackEntry)) { - val scope = navBackStackEntry?.arguments?.getString("scope")?.let { SocialScope.getByName(it) } - val id = navBackStackEntry?.arguments?.getString("id") - if (scope == null || id == null) return@rememberAsyncMutableState null - - when (scope) { - SocialScope.FRIEND -> context.database.getFriendInfo(id)?.displayName - SocialScope.GROUP -> context.database.getGroupInfo(id)?.name - } - } - text?.let { Text(it, maxLines = 1, overflow = TextOverflow.Ellipsis) } - } - private val dialogs by lazy { AlertDialogs(context.translation) } private fun deleteScope(scope: SocialScope, id: String, coroutineScope: CoroutineScope) { @@ -68,47 +64,66 @@ class ManageScope: Routes.Route() { } } - override val topBarActions: @Composable (RowScope.() -> Unit) = topBarActions@{ - val navBackStackEntry by routes.navController.currentBackStackEntryAsState() - var deleteConfirmDialog by remember { mutableStateOf(false) } - val coroutineScope = rememberCoroutineScope() - - if (deleteConfirmDialog) { - val scope = navBackStackEntry?.arguments?.getString("scope")?.let { SocialScope.getByName(it) } ?: return@topBarActions - val id = navBackStackEntry?.arguments?.getString("id")!! - - Dialog(onDismissRequest = { - deleteConfirmDialog = false - }) { - remember { AlertDialogs(context.translation) }.ConfirmDialog( - title = translation.format("delete_scope_confirm_dialog_title", "scope" to context.translation["scopes.${scope.key}"]), - onDismiss = { deleteConfirmDialog = false }, - onConfirm = { - deleteScope(scope, id, coroutineScope); deleteConfirmDialog = false - } - ) - } - } - - IconButton( - onClick = { deleteConfirmDialog = true }, - ) { - Icon( - imageVector = Icons.Rounded.DeleteForever, - contentDescription = null - ) - } - } - override val content: @Composable (NavBackStackEntry) -> Unit = content@{ navBackStackEntry -> val scope = SocialScope.getByName(navBackStackEntry.arguments?.getString("scope")!!) val id = navBackStackEntry.arguments?.getString("id")!! + val density = LocalDensity.current + var topBarHeight by remember { mutableStateOf(96.dp) } + var deleteConfirmDialog by remember { mutableStateOf(false) } + val coroutineScope = rememberCoroutineScope() - Column( + val titleText by rememberAsyncMutableState(null, keys = arrayOf(id, scope)) { + when (scope) { + SocialScope.FRIEND -> context.database.getFriendInfo(id)?.displayName + SocialScope.GROUP -> context.database.getGroupInfo(id)?.name + } + } + + if (deleteConfirmDialog) { + AestheticDialog( + onDismissRequest = { deleteConfirmDialog = false }, + title = translation.format("delete_scope_confirm_dialog_title", "scope" to context.translation["scopes.${scope.key}"]), + text = "", + icon = Icons.Rounded.DeleteForever, + confirmButtonText = translation["delete_button"] ?: "Delete", + dismissButtonText = context.translation["button.cancel"], + onDismiss = { deleteConfirmDialog = false }, + onConfirm = { + deleteScope(scope, id, coroutineScope) + deleteConfirmDialog = false + }, + opaque = true, + showCloseButton = false + ) + } + + Box( modifier = Modifier - .verticalScroll(rememberScrollState()) .fillMaxSize() + .background(PurrfectPalette.backgroundGradient) ) { + FloatingTopBar( + title = titleText ?: "Manage", + onBack = { routes.navController.popBackStack() }, + actions = { + IconButton(onClick = { deleteConfirmDialog = true }) { + Icon(Icons.Rounded.DeleteForever, contentDescription = null, tint = Color.White) + } + }, + modifier = Modifier + .zIndex(2f) + .onGloballyPositioned { + val newHeight = with(density) { it.size.height.toDp() } + if (newHeight != topBarHeight) topBarHeight = newHeight + } + ) + + Column( + modifier = Modifier + .fillMaxSize() + .padding(top = topBarHeight + 8.dp) + .verticalScroll(rememberScrollState()) + ) { var bottomComposable by remember { mutableStateOf(null as (@Composable () -> Unit)?) } @@ -156,11 +171,13 @@ class ManageScope: Routes.Route() { Text( text = translation["not_found"], fontSize = 20.sp, - fontWeight = FontWeight.Bold + fontWeight = FontWeight.Bold, + color = Color.White ) } } Spacer(modifier = Modifier.height(routes.bottomPadding)) + } } } @@ -222,14 +239,17 @@ class ManageScope: Routes.Route() { } else context.translation["rules.properties.${ruleType.key}.name"], modifier = Modifier .weight(1f) - .padding(start = 5.dp, end = 5.dp) + .padding(start = 5.dp, end = 5.dp), + color = Color.White ) - Switch(checked = ruleEnabled, + Switch( + checked = ruleEnabled, enabled = if (ruleType.listMode) ruleState != null else true, onCheckedChange = { context.database.setRule(id, ruleType.key, it) ruleEnabled = it - } + }, + colors = purrfectSwitchColors() ) } } @@ -238,18 +258,35 @@ class ManageScope: Routes.Route() { @Composable private fun ContentCard(modifier: Modifier = Modifier, content: @Composable () -> Unit) { - ElevatedCard( + val shape = RoundedCornerShape(22.dp) + Surface( modifier = Modifier - .padding(10.dp) + .padding(horizontal = 12.dp, vertical = 8.dp) .fillMaxWidth() + .then(modifier), + shape = shape, + color = Color.White.copy(alpha = 0.04f), + tonalElevation = 0.dp, + shadowElevation = 0.dp, + border = BorderStroke( + 1.dp, + Brush.linearGradient( + listOf( + PurrfectPalette.glowPrimary.copy(alpha = 0.4f), + PurrfectPalette.glowSecondary.copy(alpha = 0.3f) + ) + ) + ) ) { - Column( - modifier = Modifier - .padding(10.dp) - .fillMaxWidth() - .then(modifier) - ) { - content() + CompositionLocalProvider(LocalContentColor provides Color.White) { + Column( + modifier = Modifier + .background(PurrfectPalette.cardOverlay, shape) + .padding(12.dp) + .fillMaxWidth() + ) { + content() + } } } } @@ -262,8 +299,8 @@ class ManageScope: Routes.Route() { fontSize = 20.sp, fontWeight = FontWeight.Bold, modifier = Modifier - .offset(x = 20.dp) - .padding(bottom = 10.dp) + .padding(start = 18.dp, top = 10.dp, bottom = 6.dp), + color = Color.White ) } @@ -384,8 +421,10 @@ class ManageScope: Routes.Route() { } Column( modifier = Modifier - .padding(5.dp) - .fillMaxWidth(), + .padding(horizontal = 12.dp, vertical = 8.dp) + .fillMaxWidth() + .background(Color.White.copy(alpha = 0.04f), RoundedCornerShape(22.dp)) + .padding(horizontal = 12.dp, vertical = 12.dp), horizontalAlignment = Alignment.CenterHorizontally ) { val bitmojiUrl = BitmojiSelfie.getBitmojiSelfie( @@ -396,13 +435,15 @@ class ManageScope: Routes.Route() { text = friend.displayName ?: friend.mutableUsername, maxLines = 1, fontSize = 20.sp, - fontWeight = FontWeight.Bold + fontWeight = FontWeight.Bold, + color = Color.White ) Text( text = friend.mutableUsername, maxLines = 1, fontSize = 12.sp, - fontWeight = FontWeight.Light + fontWeight = FontWeight.Light, + color = PurrfectPalette.textSecondary ) } @@ -415,7 +456,7 @@ class ManageScope: Routes.Route() { routes.loggedStories.navigate { put("id", id) } - }) { + }, colors = ButtonDefaults.buttonColors(containerColor = PurrfectPalette.glowPrimary.copy(alpha = 0.34f), contentColor = Color.White)) { Text(translation["logged_stories_button"]) } } @@ -456,10 +497,14 @@ class ManageScope: Routes.Route() { maxLines = 1, modifier = Modifier.padding(end = 10.dp) ) - Switch(checked = shouldNotify, onCheckedChange = { - context.database.setFriendStreaksNotify(id, it) - shouldNotify = it - }) + Switch( + checked = shouldNotify, + onCheckedChange = { + context.database.setFriendStreaksNotify(id, it) + shouldNotify = it + }, + colors = purrfectSwitchColors() + ) } } } @@ -474,18 +519,29 @@ class ManageScope: Routes.Route() { ) { Column( modifier = Modifier - .padding(10.dp) - .fillMaxWidth(), + .padding(horizontal = 12.dp, vertical = 8.dp) + .fillMaxWidth() + .background(Color.White.copy(alpha = 0.04f), RoundedCornerShape(22.dp)) + .padding(horizontal = 14.dp, vertical = 14.dp), horizontalAlignment = Alignment.CenterHorizontally ) { Text( - text = group.name, maxLines = 1, fontSize = 20.sp, fontWeight = FontWeight.Bold + text = group.name, + maxLines = 1, + overflow = TextOverflow.Ellipsis, + fontSize = 20.sp, + fontWeight = FontWeight.Bold, + color = Color.White ) Text( text = translation.format( "participants_text", "count" to group.participantsCount.toString() - ), maxLines = 1, fontSize = 12.sp, fontWeight = FontWeight.Light + ), + maxLines = 1, + fontSize = 12.sp, + fontWeight = FontWeight.Light, + color = PurrfectPalette.textSecondary ) } } -} \ No newline at end of file +} diff --git a/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/social/MessagingPreview.kt b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/social/MessagingPreview.kt new file mode 100644 index 00000000..2004f7d4 --- /dev/null +++ b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/social/MessagingPreview.kt @@ -0,0 +1,960 @@ +package me.eternal.purrfectsnap.ui.manager.pages.social + +import android.content.Intent +import androidx.compose.animation.AnimatedVisibility +import androidx.compose.animation.fadeIn +import androidx.compose.animation.fadeOut +import androidx.compose.foundation.background +import androidx.compose.foundation.BorderStroke +import androidx.compose.foundation.border +import androidx.compose.foundation.gestures.detectTapGestures +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.LazyListState +import androidx.compose.foundation.lazy.items +import androidx.compose.foundation.lazy.rememberLazyListState +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Close +import androidx.compose.material.icons.rounded.BookmarkAdded +import androidx.compose.material.icons.rounded.BookmarkBorder +import androidx.compose.material.icons.rounded.DeleteForever +import androidx.compose.material.icons.rounded.MoreVert +import androidx.compose.material.icons.rounded.RemoveRedEye +import androidx.compose.material3.* +import androidx.compose.runtime.* +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.draw.shadow +import androidx.compose.ui.graphics.Brush +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.input.pointer.pointerInput +import androidx.compose.ui.layout.onGloballyPositioned +import androidx.compose.ui.platform.LocalDensity +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextOverflow +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import androidx.compose.ui.zIndex +import androidx.navigation.NavBackStackEntry +import kotlinx.coroutines.* +import me.eternal.purrfectsnap.bridge.snapclient.MessagingBridge +import me.eternal.purrfectsnap.bridge.snapclient.SessionStartListener +import me.eternal.purrfectsnap.bridge.snapclient.types.Message +import me.eternal.purrfectsnap.common.Constants +import me.eternal.purrfectsnap.common.ReceiversConfig +import me.eternal.purrfectsnap.common.data.ContentType +import me.eternal.purrfectsnap.common.data.SocialScope +import me.eternal.purrfectsnap.common.messaging.MessagingConstraints +import me.eternal.purrfectsnap.common.messaging.MessagingTask +import me.eternal.purrfectsnap.common.messaging.MessagingTaskConstraint +import me.eternal.purrfectsnap.common.messaging.MessagingTaskType +import me.eternal.purrfectsnap.common.ui.rememberAsyncMutableState +import me.eternal.purrfectsnap.common.util.protobuf.ProtoReader +import me.eternal.purrfectsnap.common.util.snap.SnapWidgetBroadcastReceiverHelper +import me.eternal.purrfectsnap.storage.getFriendInfo +import me.eternal.purrfectsnap.storage.getGroupInfo +import me.eternal.purrfectsnap.ui.manager.Routes +import me.eternal.purrfectsnap.ui.manager.components.FloatingTopBar +import me.eternal.purrfectsnap.ui.manager.theme.PurrfectPalette +import me.eternal.purrfectsnap.ui.util.Dialog +import me.eternal.purrfectsnap.ui.util.purrfectSwitchColors + +class MessagingPreview: Routes.Route() { + override val translation by lazy { context.translation.getCategory("manager.sections.social.messaging_preview.messaging_preview") } + private lateinit var coroutineScope: CoroutineScope + private lateinit var previewScrollState: LazyListState + + private val contentTypeTranslation by lazy { context.translation.getCategory("content_type") } + private val messagingBridge: MessagingBridge? get() = context.bridgeService?.messagingBridge + + private var messages = mutableStateListOf() + private var conversationId by mutableStateOf(null) + private val selectedMessages = mutableStateListOf() // client message id + + private fun toggleSelectedMessage(messageId: Long) { + if (selectedMessages.contains(messageId)) selectedMessages.remove(messageId) + else selectedMessages.add(messageId) + } + + private fun tr(key: String, fallback: String? = null): String { + fun normalizeCandidate(candidate: String?): String? { + if (candidate.isNullOrBlank()) return null + if (candidate == key) return null + if (candidate.endsWith(".$key")) return null + return candidate + } + + return normalizeCandidate(translation.getOrNull(key)) + ?: normalizeCandidate(context.translation.getOrNull("manager.sections.social.messaging_preview.$key")) + ?: normalizeCandidate(context.translation.getOrNull("manager.social.messaging_preview.$key")) + ?: fallback + ?: key + } + + @Composable + private fun ActionsSheetItem( + title: String, + subtitle: String?, + icon: ImageVector, + danger: Boolean = false, + onClick: () -> Unit, + ) { + val shape = RoundedCornerShape(18.dp) + val border = if (danger) { + Brush.linearGradient( + listOf( + Color(0xFFFF5C8A).copy(alpha = 0.7f), + PurrfectPalette.glowSecondary.copy(alpha = 0.35f) + ) + ) + } else { + Brush.linearGradient( + listOf( + PurrfectPalette.glowPrimary.copy(alpha = 0.55f), + PurrfectPalette.glowSecondary.copy(alpha = 0.35f) + ) + ) + } + + Surface( + onClick = onClick, + shape = shape, + color = PurrfectPalette.cardOverlayColor.copy(alpha = 0.85f), + border = BorderStroke(1.dp, border), + tonalElevation = 0.dp, + shadowElevation = 0.dp, + modifier = Modifier.fillMaxWidth() + ) { + Row( + modifier = Modifier.padding(horizontal = 14.dp, vertical = 12.dp), + horizontalArrangement = Arrangement.spacedBy(12.dp), + verticalAlignment = Alignment.CenterVertically + ) { + Box( + modifier = Modifier + .size(42.dp) + .background( + Brush.linearGradient( + listOf( + (if (danger) Color(0xFFFF5C8A) else PurrfectPalette.glowPrimary).copy(alpha = 0.32f), + PurrfectPalette.glowSecondary.copy(alpha = 0.18f) + ) + ), + RoundedCornerShape(14.dp) + ) + .border(1.dp, Color.White.copy(alpha = 0.12f), RoundedCornerShape(14.dp)), + contentAlignment = Alignment.Center + ) { + Icon( + imageVector = icon, + contentDescription = null, + tint = Color.White, + modifier = Modifier.size(20.dp) + ) + } + + Column(modifier = Modifier.weight(1f)) { + Text( + text = title, + color = Color.White, + fontWeight = FontWeight.Bold, + maxLines = 1, + overflow = TextOverflow.Ellipsis + ) + if (!subtitle.isNullOrBlank()) { + Spacer(Modifier.height(2.dp)) + Text( + text = subtitle, + color = PurrfectPalette.textSecondary, + fontSize = 12.sp, + maxLines = 1, + overflow = TextOverflow.Ellipsis + ) + } + } + } + } + } + + @Composable + private fun ConstraintsSelectionDialog( + onChoose: (Array) -> Unit, + onDismiss: () -> Unit + ) { + val selectedTypes = remember { mutableStateListOf() } + var selectAllState by remember { mutableStateOf(false) } + val availableTypes = remember { arrayOf( + ContentType.CHAT, + ContentType.NOTE, + ContentType.SNAP, + ContentType.STICKER, + ContentType.EXTERNAL_MEDIA + ) } + + fun toggleContentType(contentType: ContentType) { + if (selectAllState) return + if (selectedTypes.contains(contentType)) { + selectedTypes.remove(contentType) + } else { + selectedTypes.add(contentType) + } + } + + Surface( + modifier = Modifier + .fillMaxWidth() + .background(PurrfectPalette.cardOverlayColor) + .border(1.dp, Color.White.copy(alpha = 0.12f), RoundedCornerShape(22.dp)), + shape = RoundedCornerShape(22.dp), + color = Color.Transparent + ) { + Column( + modifier = Modifier.padding(15.dp), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.spacedBy(5.dp) + ) { + Text(context.translation["manager.dialogs.messaging_action.title"], color = Color.White) + Spacer(modifier = Modifier.height(5.dp)) + availableTypes.forEach { contentType -> + Row( + modifier = Modifier + .fillMaxWidth() + .padding(2.dp) + .pointerInput(Unit) { + detectTapGestures(onTap = { toggleContentType(contentType) }) + }, + horizontalArrangement = Arrangement.spacedBy(8.dp), + verticalAlignment = Alignment.CenterVertically + ) { + Checkbox( + checked = selectedTypes.contains(contentType), + enabled = !selectAllState, + onCheckedChange = { toggleContentType(contentType) }, + colors = CheckboxDefaults.colors( + checkedColor = PurrfectPalette.glowSecondary, + uncheckedColor = Color.White.copy(alpha = 0.85f), + checkmarkColor = Color.Black + ) + ) + Text(text = contentTypeTranslation[contentType.name], color = Color.White) + } + } + Row( + modifier = Modifier + .fillMaxWidth() + .padding(5.dp), + horizontalArrangement = Arrangement.spacedBy(10.dp), + verticalAlignment = Alignment.CenterVertically + ) { + Switch( + checked = selectAllState, + onCheckedChange = { + selectAllState = it + }, + colors = purrfectSwitchColors() + ) + Text(text = context.translation["manager.dialogs.messaging_action.select_all_button"], color = Color.White) + } + Row( + modifier = Modifier + .fillMaxWidth(), + horizontalArrangement = Arrangement.SpaceEvenly, + ) { + Button( + onClick = { onDismiss() }, + colors = ButtonDefaults.buttonColors( + containerColor = Color.White.copy(alpha = 0.08f), + contentColor = Color.White + ) + ) { + Text(context.translation["button.cancel"], color = Color.White) + } + Button( + onClick = { + onChoose( + if (selectAllState) ContentType.entries.toTypedArray() + else selectedTypes.toTypedArray() + ) + }, + colors = ButtonDefaults.buttonColors( + containerColor = PurrfectPalette.glowPrimary.copy(alpha = 0.34f), + contentColor = Color.White + ) + ) { + Text(context.translation["button.ok"], color = Color.White) + } + } + } + } + } + + @Composable + private fun ConversationPreview( + messages: List, + scope: SocialScope, + scopeId: String, + myUserId: String?, + friendDisplayName: String?, + fetchNewMessages: () -> Unit, + ) { + DisposableEffect(Unit) { + onDispose { + selectedMessages.clear() + } + } + + LazyColumn( + reverseLayout = true, + modifier = Modifier + .fillMaxWidth(), + state = previewScrollState, + contentPadding = PaddingValues(top = 10.dp, bottom = routes.bottomPadding + 18.dp) + ) { + items(messages, key = { it.serverMessageId }) {message -> + val messageReader = remember(message.contentType) { ProtoReader(message.content) } + val contentType = ContentType.fromMessageContainer(messageReader) + val senderId = message.senderId + val isMine = senderId != null && senderId == myUserId + + val isSelected = selectedMessages.contains(message.clientMessageId) + val borderBrush = if (isSelected) { + Brush.linearGradient( + listOf( + PurrfectPalette.glowPrimary.copy(alpha = 0.85f), + PurrfectPalette.glowSecondary.copy(alpha = 0.75f) + ) + ) + } else { + Brush.linearGradient( + listOf( + Color.White.copy(alpha = 0.08f), + Color.White.copy(alpha = 0.08f) + ) + ) + } + + val senderDisplayName by rememberAsyncMutableState(null, keys = arrayOf(senderId, myUserId, scope.key, scopeId, friendDisplayName)) { + when { + senderId == null -> "Unknown" + senderId == myUserId -> "You" + scope == SocialScope.FRIEND -> friendDisplayName + ?: context.database.getFriendInfo(scopeId)?.displayName + ?: context.database.getFriendInfo(scopeId)?.mutableUsername + ?: "Friend" + else -> context.database.getFriendInfo(senderId)?.displayName + ?: context.database.getFriendInfo(senderId)?.mutableUsername + ?: "Unknown" + } + } + + val contentTypeLabel = remember(contentType) { + contentType?.let { contentTypeTranslation.getOrNull(it.name) ?: it.name } ?: "Unknown" + } + val bodyText = remember(message.contentType) { messageReader.getString(2, 1)?.trim().orEmpty() } + + if (contentType == ContentType.STATUS) { + Row( + modifier = Modifier + .fillMaxWidth() + .padding(vertical = 10.dp), + horizontalArrangement = Arrangement.Center + ) { + Box( + modifier = Modifier + .clip(RoundedCornerShape(999.dp)) + .background(Color.White.copy(alpha = 0.08f)) + .border(1.dp, Color.White.copy(alpha = 0.10f), RoundedCornerShape(999.dp)) + .padding(horizontal = 12.dp, vertical = 8.dp) + ) { + Text( + text = "[$contentTypeLabel] ${bodyText.ifBlank { "—" }}", + color = PurrfectPalette.textSecondary, + fontSize = 12.sp, + maxLines = 2, + overflow = TextOverflow.Ellipsis + ) + } + } + return@items + } + + Row( + modifier = Modifier + .fillMaxWidth() + .padding(vertical = 6.dp), + horizontalArrangement = if (isMine) Arrangement.End else Arrangement.Start + ) { + val bubbleShape = if (isMine) { + RoundedCornerShape(topStart = 22.dp, topEnd = 22.dp, bottomStart = 22.dp, bottomEnd = 8.dp) + } else { + RoundedCornerShape(topStart = 22.dp, topEnd = 22.dp, bottomStart = 8.dp, bottomEnd = 22.dp) + } + + Column( + modifier = Modifier + .fillMaxWidth(0.86f) + .widthIn(max = 360.dp) + .pointerInput(Unit) { + detectTapGestures( + onLongPress = { toggleSelectedMessage(message.clientMessageId) }, + onTap = { + if (selectedMessages.isNotEmpty()) toggleSelectedMessage(message.clientMessageId) + } + ) + }, + horizontalAlignment = if (isMine) Alignment.End else Alignment.Start + ) { + Text( + text = senderDisplayName ?: "Unknown", + color = Color.White.copy(alpha = 0.82f), + fontSize = 12.sp, + fontWeight = FontWeight.SemiBold, + maxLines = 1, + overflow = TextOverflow.Ellipsis, + modifier = Modifier.padding(horizontal = 12.dp) + ) + Spacer(Modifier.height(4.dp)) + + Box( + modifier = Modifier + .shadow( + elevation = if (isSelected) 10.dp else 6.dp, + shape = bubbleShape, + clip = true, + ambientColor = PurrfectPalette.glowSecondary.copy(alpha = 0.18f), + spotColor = PurrfectPalette.glowPrimary.copy(alpha = 0.16f), + ) + .clip(bubbleShape) + .background( + brush = if (isMine) { + Brush.linearGradient( + listOf( + PurrfectPalette.glowPrimary.copy(alpha = 0.30f), + PurrfectPalette.glowSecondary.copy(alpha = 0.16f) + ) + ) + } else { + Brush.linearGradient( + listOf( + Color.White.copy(alpha = 0.10f), + Color.White.copy(alpha = 0.06f) + ) + ) + }, + shape = bubbleShape + ) + .border(BorderStroke(1.dp, borderBrush), bubbleShape) + ) { + Column(modifier = Modifier.padding(horizontal = 12.dp, vertical = 10.dp)) { + if (contentType != ContentType.CHAT) { + Box( + modifier = Modifier + .clip(RoundedCornerShape(999.dp)) + .background(Color.White.copy(alpha = 0.10f)) + .border(1.dp, Color.White.copy(alpha = 0.10f), RoundedCornerShape(999.dp)) + .padding(horizontal = 10.dp, vertical = 4.dp) + ) { + Text( + text = contentTypeLabel, + color = PurrfectPalette.textSecondary, + fontSize = 11.sp, + fontWeight = FontWeight.SemiBold, + maxLines = 1, + overflow = TextOverflow.Ellipsis + ) + } + Spacer(Modifier.height(6.dp)) + } + + Text( + text = bodyText.ifBlank { contentTypeLabel }, + color = Color.White, + fontSize = 14.sp + ) + } + } + } + } + } + item { + if (messages.isEmpty()) { + Row( + modifier = Modifier + .fillMaxWidth() + .padding(40.dp), + horizontalArrangement = Arrangement.Center + ) { + Text(tr("no_message_hint", "No messages"), color = PurrfectPalette.textSecondary) + } + } + Spacer(modifier = Modifier.height(20.dp)) + + LaunchedEffect(Unit) { + if (messages.isNotEmpty()) { + fetchNewMessages() + } + } + } + } + } + + + @Composable + private fun LoadingRow() { + Row( + modifier = Modifier + .fillMaxWidth() + .padding(40.dp), + horizontalArrangement = Arrangement.Center + ) { + CircularProgressIndicator( + modifier = Modifier + .padding() + .size(30.dp), + strokeWidth = 3.dp, + color = PurrfectPalette.glowSecondary + ) + } + } + + @OptIn(ExperimentalMaterial3Api::class) + override val content: @Composable (NavBackStackEntry) -> Unit = { navBackStackEntry -> + val scope = remember { SocialScope.getByName(navBackStackEntry.arguments?.getString("scope")!!) } + val id = remember { navBackStackEntry.arguments?.getString("id")!! } + + previewScrollState = rememberLazyListState() + coroutineScope = rememberCoroutineScope() + val density = LocalDensity.current + var topBarHeight by remember { mutableStateOf(96.dp) } + + val titleText by rememberAsyncMutableState(null, keys = arrayOf(scope.key, id)) { + when (scope) { + SocialScope.FRIEND -> context.database.getFriendInfo(id)?.displayName + ?: context.database.getFriendInfo(id)?.mutableUsername + SocialScope.GROUP -> context.database.getGroupInfo(id)?.name + } + } + + var lastMessageId by remember { mutableLongStateOf(Long.MAX_VALUE) } + var isBridgeConnected by remember { mutableStateOf(false) } + var hasBridgeError by remember { mutableStateOf(false) } + var actionsOpen by remember { mutableStateOf(false) } + var selectConstraintsDialog by remember { mutableStateOf(false) } + var activeTask by remember { mutableStateOf(null as MessagingTask?) } + var activeJob by remember { mutableStateOf(null as Job?) } + val processMessageCount = remember { mutableIntStateOf(0) } + + fun runCurrentTask() { + activeJob = coroutineScope.launch(Dispatchers.IO) { + activeTask?.run() + withContext(Dispatchers.Main) { + activeTask = null + activeJob = null + } + }.also { job -> + job.invokeOnCompletion { + if (it != null) { + context.log.verbose("Failed to process messages: ${it.message}") + return@invokeOnCompletion + } + val toastText = translation.getOrNull("processed_message_toast")?.let { + translation.format("processed_message_toast", "count" to processMessageCount.intValue.toString()) + } ?: translation.getOrNull("processed_messages_toast")?.let { + translation.format("processed_messages_toast", "count" to processMessageCount.intValue.toString()) + } ?: "Processed ${processMessageCount.intValue} messages" + context.longToast(toastText) + } + } + } + + fun launchMessagingTask( + taskType: MessagingTaskType, + constraints: List = listOf(), + onSuccess: (Message) -> Unit = {}, + ) { + if (messagingBridge == null) { + context.longToast( + translation.getOrNull("bridge_connection_error") + ?: translation.getOrNull("bridge_connection_failed") + ?: "Failed to connect to bridge" + ) + return + } + actionsOpen = false + processMessageCount.intValue = 0 + activeTask = MessagingTask( + messagingBridge!!, + conversationId!!, + taskType, + constraints, + overrideClientMessageIds = selectedMessages.takeIf { it.isNotEmpty() }?.toList(), + processedMessageCount = processMessageCount, + onSuccess = onSuccess, + onFailure = { message, reason -> + context.log.verbose("Failed to process message ${message.clientMessageId}: $reason") + } + ) + selectedMessages.clear() + } + + if (selectConstraintsDialog && activeTask != null) { + Dialog(onDismissRequest = { + selectConstraintsDialog = false + activeTask = null + }) { + ConstraintsSelectionDialog( + onChoose = { contentTypes -> + launchMessagingTask( + taskType = activeTask!!.taskType, + constraints = activeTask!!.constraints + MessagingConstraints.CONTENT_TYPE(contentTypes), + onSuccess = activeTask!!.onSuccess + ) + runCurrentTask() + selectConstraintsDialog = false + }, + onDismiss = { + selectConstraintsDialog = false + activeTask = null + } + ) + } + } + + if (activeJob != null) { + Dialog(onDismissRequest = { + activeJob?.cancel() + activeJob = null + activeTask = null + }) { + Column( + modifier = Modifier + .fillMaxWidth() + .background(MaterialTheme.colorScheme.surface) + .padding(15.dp) + .border(1.dp, MaterialTheme.colorScheme.onSurface, RoundedCornerShape(20.dp)), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.spacedBy(5.dp) + ) { + val processedText = translation.getOrNull("processed_messages_text")?.let { + translation.format("processed_messages_text", "count" to processMessageCount.intValue.toString()) + } ?: "Processed ${processMessageCount.intValue}" + Text(processedText) + if (activeTask?.hasFixedGoal() == true) { + LinearProgressIndicator( + progress = { processMessageCount.intValue.toFloat() / selectedMessages.size.toFloat() }, + modifier = Modifier + .fillMaxWidth() + .padding(5.dp), + color = MaterialTheme.colorScheme.primary, + ) + } else { + CircularProgressIndicator( + modifier = Modifier + .padding() + .size(30.dp), + strokeWidth = 3.dp, + color = MaterialTheme.colorScheme.primary + ) + } + } + } + } + + fun fetchNewMessages() { + coroutineScope.launch(Dispatchers.IO) cs@{ + runCatching { + val queriedMessages = messagingBridge!!.fetchConversationWithMessagesPaginated( + conversationId!!, + 20, + lastMessageId + )?.reversed() ?: throw IllegalStateException("Failed to fetch messages. Bridge returned null") + + withContext(Dispatchers.Main) { + messages.addAll(queriedMessages) + lastMessageId = queriedMessages.lastOrNull()?.clientMessageId ?: lastMessageId + } + }.onFailure { + context.log.error("Failed to fetch messages", it) + context.shortToast( + translation.getOrNull("message_fetch_failed") ?: "Failed to fetch messages" + ) + } + } + } + + fun onMessagingBridgeReady(scope: SocialScope, scopeId: String) { + context.log.verbose("onMessagingBridgeReady: $scope $scopeId") + + runCatching { + conversationId = (if (scope == SocialScope.FRIEND) messagingBridge!!.getOneToOneConversationId(scopeId) else scopeId) ?: throw IllegalStateException("Failed to get conversation id") + if (runCatching { !messagingBridge!!.isSessionStarted }.getOrDefault(true)) { + context.androidContext.packageManager.getLaunchIntentForPackage( + Constants.SNAPCHAT_PACKAGE_NAME + )?.let { + val mainIntent = Intent.makeMainActivity(it.component).apply { + putExtra(ReceiversConfig.MESSAGING_PREVIEW_EXTRA, true) + addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + } + context.androidContext.startActivity(mainIntent) + } + messagingBridge!!.registerSessionStartListener(object: SessionStartListener.Stub() { + override fun onConnected() { + fetchNewMessages() + } + }) + return + } + fetchNewMessages() + }.onFailure { + context.longToast( + translation.getOrNull("bridge_init_failed") ?: "Failed to initialize messaging bridge" + ) + context.log.error("Failed to initialize messaging bridge", it) + } + } + + LaunchedEffect(Unit) { + messages.clear() + conversationId = null + + isBridgeConnected = context.hasMessagingBridge() + if (isBridgeConnected) { + withContext(Dispatchers.IO) { + onMessagingBridgeReady(scope, id) + } + } else { + coroutineScope.launch(Dispatchers.IO) { + SnapWidgetBroadcastReceiverHelper.create("wakeup") {}.also { + context.androidContext.sendBroadcast(it) + } + withTimeout(10000) { + while (!context.hasMessagingBridge()) { + delay(100) + } + isBridgeConnected = true + onMessagingBridgeReady(scope, id) + } + }.invokeOnCompletion { + if (it != null) { + hasBridgeError = true + } + } + } + } + + Box( + modifier = Modifier + .fillMaxSize() + .background(PurrfectPalette.backgroundGradient) + ) { + FloatingTopBar( + title = titleText ?: translation["title"] ?: "Preview", + subtitle = if (selectedMessages.isNotEmpty()) { + "${selectedMessages.size} selected" + } else { + tr("subtitle", "Hold to select") + .substringBefore("•") + .substringBefore("·") + .substringBefore("|") + .trim() + }, + onBack = { routes.navController.popBackStack() }, + actions = { + AnimatedVisibility( + visible = selectedMessages.isNotEmpty(), + enter = fadeIn(), + exit = fadeOut() + ) { + IconButton(onClick = { selectedMessages.clear() }) { + Icon( + imageVector = Icons.Filled.Close, + contentDescription = translation.getOrNull("close_button_description"), + tint = Color.White + ) + } + } + IconButton(onClick = { if (messages.isNotEmpty()) actionsOpen = true }) { + Icon(imageVector = Icons.Rounded.MoreVert, contentDescription = null, tint = Color.White) + } + }, + modifier = Modifier + .zIndex(2f) + .onGloballyPositioned { + val newHeight = with(density) { it.size.height.toDp() } + if (newHeight != topBarHeight) topBarHeight = newHeight + } + ) + + Column( + modifier = Modifier + .fillMaxSize() + .padding(top = topBarHeight + 6.dp) + .padding(horizontal = 14.dp) + ) { + if (hasBridgeError) { + Text( + translation.getOrNull("bridge_connection_error") + ?: translation.getOrNull("bridge_connection_failed") + ?: "Failed to connect to bridge", + modifier = Modifier.padding(16.dp), + color = Color.White + ) + } + + if (!isBridgeConnected && !hasBridgeError) { + LoadingRow() + } + + if (isBridgeConnected && !hasBridgeError) { + ConversationPreview( + messages = messages, + scope = scope, + scopeId = id, + myUserId = messagingBridge?.myUserId, + friendDisplayName = titleText, + fetchNewMessages = ::fetchNewMessages + ) + } + } + + if (actionsOpen) { + ModalBottomSheet( + onDismissRequest = { actionsOpen = false }, + sheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true), + containerColor = Color.Transparent, + dragHandle = null + ) { + val hasSelection = selectedMessages.isNotEmpty() + val selectionSubtitle = if (hasSelection) { + "${selectedMessages.size} selected" + } else { + "Choose message types" + } + + Column( + modifier = Modifier + .fillMaxWidth() + .background( + brush = PurrfectPalette.cardOverlay, + shape = RoundedCornerShape(topStart = 28.dp, topEnd = 28.dp) + ) + .border( + 1.dp, + Brush.linearGradient( + listOf( + PurrfectPalette.glowPrimary.copy(alpha = 0.5f), + PurrfectPalette.glowSecondary.copy(alpha = 0.3f) + ) + ), + RoundedCornerShape(topStart = 28.dp, topEnd = 28.dp) + ) + .padding(horizontal = 16.dp, vertical = 16.dp) + ) { + Box( + modifier = Modifier + .align(Alignment.CenterHorizontally) + .size(width = 42.dp, height = 5.dp) + .clip(RoundedCornerShape(999.dp)) + .background(Color.White.copy(alpha = 0.14f)) + ) + Spacer(Modifier.height(14.dp)) + Text( + text = tr("actions_title", "Conversation Actions"), + color = Color.White, + fontWeight = FontWeight.ExtraBold, + fontSize = 18.sp, + maxLines = 1, + overflow = TextOverflow.Ellipsis + ) + Spacer(Modifier.height(2.dp)) + Text( + text = selectionSubtitle, + color = PurrfectPalette.textSecondary, + fontSize = 12.sp, + maxLines = 1, + overflow = TextOverflow.Ellipsis + ) + Spacer(Modifier.height(14.dp)) + + Column(verticalArrangement = Arrangement.spacedBy(10.dp)) { + val saveKey = if (hasSelection) "save_selection_option" else "save_all_option" + val unsaveKey = if (hasSelection) "unsave_selection_option" else "unsave_all_option" + val markKey = if (hasSelection) "mark_selection_as_seen_option" else "mark_all_as_seen_option" + val deleteKey = if (hasSelection) "delete_selection_option" else "delete_all_option" + + ActionsSheetItem( + title = tr(saveKey, if (hasSelection) "Save Selection" else "Save All"), + subtitle = if (hasSelection) "Save selected messages" else "Save by content type", + icon = Icons.Rounded.BookmarkAdded + ) { + launchMessagingTask(MessagingTaskType.SAVE) + if (hasSelection) runCurrentTask() else selectConstraintsDialog = true + } + ActionsSheetItem( + title = tr(unsaveKey, if (hasSelection) "Unsave Selection" else "Unsave All"), + subtitle = if (hasSelection) "Unsave selected messages" else "Unsave by content type", + icon = Icons.Rounded.BookmarkBorder + ) { + launchMessagingTask(MessagingTaskType.UNSAVE) + if (hasSelection) runCurrentTask() else selectConstraintsDialog = true + } + ActionsSheetItem( + title = tr(markKey, if (hasSelection) "Mark selected as seen" else "Mark all as seen"), + subtitle = "Marks snaps as seen", + icon = Icons.Rounded.RemoveRedEye + ) { + if (messagingBridge == null) { + context.longToast( + translation.getOrNull("bridge_connection_error") + ?: translation.getOrNull("bridge_connection_failed") + ?: "Failed to connect to bridge" + ) + return@ActionsSheetItem + } + launchMessagingTask( + MessagingTaskType.READ, + listOf( + MessagingConstraints.NO_USER_ID(messagingBridge!!.myUserId), + MessagingConstraints.CONTENT_TYPE(arrayOf(ContentType.SNAP)) + ) + ) + runCurrentTask() + } + ActionsSheetItem( + title = tr(deleteKey, if (hasSelection) "Delete Selection" else "Delete All"), + subtitle = if (hasSelection) "Delete selected messages" else "Delete by content type", + icon = Icons.Rounded.DeleteForever, + danger = true + ) { + if (messagingBridge == null) { + context.longToast( + translation.getOrNull("bridge_connection_error") + ?: translation.getOrNull("bridge_connection_failed") + ?: "Failed to connect to bridge" + ) + return@ActionsSheetItem + } + launchMessagingTask( + MessagingTaskType.DELETE, + listOf( + MessagingConstraints.USER_ID(messagingBridge!!.myUserId), + { contentType != ContentType.STATUS.id } + ) + ) { message -> + coroutineScope.launch { message.contentType = ContentType.STATUS.id } + } + if (hasSelection) runCurrentTask() else selectConstraintsDialog = true + } + } + + Spacer(Modifier.height(12.dp)) + Spacer(Modifier.windowInsetsBottomHeight(WindowInsets.navigationBars)) + } + } + } + } + } +} diff --git a/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/social/SocialRootSection.kt b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/social/SocialRootSection.kt new file mode 100644 index 00000000..ac28c28f --- /dev/null +++ b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/social/SocialRootSection.kt @@ -0,0 +1,562 @@ +package me.eternal.purrfectsnap.ui.manager.pages.social + +import androidx.compose.foundation.BorderStroke +import androidx.compose.foundation.ExperimentalFoundationApi +import androidx.compose.foundation.background +import androidx.compose.foundation.border +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.pager.HorizontalPager +import androidx.compose.foundation.pager.rememberPagerState +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Groups +import androidx.compose.material.icons.filled.People +import androidx.compose.material.icons.filled.RemoveRedEye +import androidx.compose.material.icons.rounded.Add +import androidx.compose.material3.* +import androidx.compose.runtime.* +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.shadow +import androidx.compose.ui.graphics.Brush +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.res.vectorResource +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.text.style.TextOverflow +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import androidx.navigation.NavBackStackEntry +import kotlinx.coroutines.launch +import me.eternal.purrfectsnap.R +import me.eternal.purrfectsnap.common.data.MessagingFriendInfo +import me.eternal.purrfectsnap.common.data.MessagingGroupInfo +import me.eternal.purrfectsnap.common.data.SocialScope +import me.eternal.purrfectsnap.common.ui.rememberAsyncMutableState +import me.eternal.purrfectsnap.common.util.snap.BitmojiSelfie +import me.eternal.purrfectsnap.storage.* +import me.eternal.purrfectsnap.ui.manager.Routes +import me.eternal.purrfectsnap.ui.manager.theme.PurrfectPalette +import me.eternal.purrfectsnap.ui.util.coil.BitmojiImage + +class SocialRootSection : Routes.Route() { + private var friendList: List by mutableStateOf(emptyList()) + private var groupList: List by mutableStateOf(emptyList()) + + private fun updateScopeLists() { + context.coroutineScope.launch { + friendList = context.database.getFriends(descOrder = true) + groupList = context.database.getGroups() + } + } + + @Composable + private fun ScopeList(scope: SocialScope) { + val remainingHours = remember { context.config.root.streaksReminder.remainingHours.get() } + + LazyColumn( + modifier = Modifier + .fillMaxSize(), + contentPadding = PaddingValues(start = 10.dp, end = 10.dp, bottom = routes.bottomPadding + 12.dp), + verticalArrangement = Arrangement.spacedBy(10.dp) + ) { + //check if scope list is empty + val listSize = when (scope) { + SocialScope.GROUP -> groupList.size + SocialScope.FRIEND -> friendList.size + } + + if (listSize == 0) { + item { + EmptyState(scope) + } + } + + items(listSize) { index -> + val id = when (scope) { + SocialScope.GROUP -> groupList[index].conversationId + SocialScope.FRIEND -> friendList[index].userId + } + + SocialCard( + scope = scope, + index = index, + onManage = { + routes.manageScope.navigate { + put("id", id) + put("scope", scope.key) + } + }, + onPreview = { + routes.messagingPreview.navigate { + put("id", id) + put("scope", scope.key) + } + }, + remainingHours = remainingHours + ) + } + } + } + + override val floatingActionButton: @Composable () -> Unit = { + var addFriendDialog by remember { mutableStateOf(null as AddFriendDialog?) } + + if (addFriendDialog != null) { + addFriendDialog?.Content { + addFriendDialog = null + } + DisposableEffect(Unit) { + onDispose { + updateScopeLists() + } + } + } + + FloatingActionButton( + onClick = { + addFriendDialog = AddFriendDialog( + context, + AddFriendDialog.Actions( + onFriendState = { friend, state -> + if (state) { + context.bridgeService?.triggerScopeSync( + SocialScope.FRIEND, + friend.userId + ) + } else { + context.database.deleteFriend(friend.userId) + } + }, + onGroupState = { group, state -> + if (state) { + context.bridgeService?.triggerScopeSync( + SocialScope.GROUP, + group.conversationId + ) + } else { + context.database.deleteGroup(group.conversationId) + } + }, + getFriendState = { friend -> context.database.getFriendInfo(friend.userId) != null }, + getGroupState = { group -> context.database.getGroupInfo(group.conversationId) != null } + ), + pinnedIds = (friendList.map { it.userId } + groupList.map { it.conversationId }).reversed(), + ) + }, + modifier = Modifier + .padding(10.dp) + .shadow(14.dp, RoundedCornerShape(20.dp), clip = false), + containerColor = Color.Transparent, + contentColor = MaterialTheme.colorScheme.onPrimary, + shape = RoundedCornerShape(20.dp), + elevation = FloatingActionButtonDefaults.elevation(defaultElevation = 0.dp, pressedElevation = 0.dp) + ) { + Box( + modifier = Modifier + .size(64.dp) + .background( + brush = Brush.linearGradient(listOf(PurrfectPalette.glowPrimary, PurrfectPalette.glowSecondary)), + shape = RoundedCornerShape(18.dp) + ) + .border(1.dp, Color.White.copy(alpha = 0.22f), RoundedCornerShape(18.dp)), + contentAlignment = Alignment.Center + ) { + Icon( + imageVector = Icons.Rounded.Add, + contentDescription = null, + tint = Color.White, + modifier = Modifier.size(28.dp) + ) + } + } + } + + @OptIn(ExperimentalFoundationApi::class) + override val content: @Composable (NavBackStackEntry) -> Unit = { + val titles = remember { + listOf(translation["friends_tab"], translation["groups_tab"]) + } + val coroutineScope = rememberCoroutineScope() + val pagerState = rememberPagerState { titles.size } + + LaunchedEffect(Unit) { + updateScopeLists() + } + + Column( + modifier = Modifier + .fillMaxSize() + .background(PurrfectPalette.backgroundGradient) + ) { + SocialHeader( + titles = titles, + pagerState = pagerState, + onTabSelected = { index -> + coroutineScope.launch { pagerState.animateScrollToPage(index) } + }, + friendCount = friendList.size, + groupCount = groupList.size + ) + Spacer(Modifier.height(12.dp)) + HorizontalPager( + modifier = Modifier + .fillMaxSize(), + state = pagerState + ) { page -> + when (page) { + 0 -> ScopeList(SocialScope.FRIEND) + 1 -> ScopeList(SocialScope.GROUP) + } + } + } + } + + @Composable + private fun SocialCard( + scope: SocialScope, + index: Int, + onManage: () -> Unit, + onPreview: () -> Unit, + remainingHours: Int + ) { + val cardGradient = Brush.linearGradient( + listOf( + PurrfectPalette.glowPrimary.copy(alpha = 0.22f), + PurrfectPalette.glowSecondary.copy(alpha = 0.16f) + ) + ) + ElevatedCard( + modifier = Modifier + .fillMaxWidth() + .heightIn(min = 88.dp) + .border(1.dp, cardGradient, RoundedCornerShape(20.dp)), + shape = RoundedCornerShape(20.dp), + onClick = onManage, + colors = CardDefaults.elevatedCardColors( + containerColor = Color.Transparent + ) + ) { + Row( + modifier = Modifier + .background(PurrfectPalette.cardOverlay, RoundedCornerShape(20.dp)) + .padding(horizontal = 12.dp, vertical = 12.dp), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(12.dp) + ) { + when (scope) { + SocialScope.GROUP -> { + val group = groupList[index] + Surface( + shape = RoundedCornerShape(12.dp), + color = Color.White.copy(alpha = 0.08f), + border = BorderStroke(1.dp, Color.White.copy(alpha = 0.16f)) + ) { + Icon( + imageVector = Icons.Filled.Groups, + contentDescription = null, + tint = Color.White, + modifier = Modifier.padding(12.dp) + ) + } + Column( + modifier = Modifier.weight(1f), + verticalArrangement = Arrangement.spacedBy(4.dp) + ) { + Text( + text = group.name, + maxLines = 1, + overflow = TextOverflow.Ellipsis, + fontWeight = FontWeight.SemiBold, + color = Color.White, + fontSize = 15.sp + ) + Text( + text = translation["groups_tab"], + color = PurrfectPalette.textSecondary, + fontSize = 12.sp + ) + } + } + + SocialScope.FRIEND -> { + val friend = friendList[index] + val streaks by rememberAsyncMutableState(defaultValue = friend.streaks) { + context.database.getFriendStreaks(friend.userId) + } + + BitmojiImage( + context = context, + url = BitmojiSelfie.getBitmojiSelfie( + friend.selfieId, + friend.bitmojiId, + BitmojiSelfie.BitmojiSelfieType.NEW_THREE_D + ) + ) + + Column( + modifier = Modifier.weight(1f), + verticalArrangement = Arrangement.spacedBy(4.dp) + ) { + Text( + text = friend.displayName ?: friend.mutableUsername, + maxLines = 1, + overflow = TextOverflow.Ellipsis, + fontWeight = FontWeight.SemiBold, + color = Color.White, + fontSize = 15.sp + ) + Text( + text = friend.mutableUsername, + maxLines = 1, + fontSize = 12.sp, + fontWeight = FontWeight.Light, + color = PurrfectPalette.textSecondary + ) + Row(verticalAlignment = Alignment.CenterVertically) { + streaks?.takeIf { it.notify }?.let { streaks -> + Icon( + imageVector = ImageVector.vectorResource(id = R.drawable.streak_icon), + contentDescription = null, + modifier = Modifier.height(18.dp), + tint = if (streaks.isAboutToExpire(remainingHours)) + Color(0xFFFF6B9B) + else PurrfectPalette.glowSecondary + ) + Spacer(Modifier.width(6.dp)) + Text( + text = translation.format( + "streaks_expiration_short", + "hours" to (((streaks.expirationTimestamp - System.currentTimeMillis()) / 3600000).toInt().takeIf { it > 0 } ?: 0) + .toString() + ), + maxLines = 1, + fontWeight = FontWeight.Medium, + color = PurrfectPalette.textSecondary, + fontSize = 12.sp + ) + } + } + } + } + } + + Surface( + onClick = onPreview, + shape = RoundedCornerShape(16.dp), + color = Color.White.copy(alpha = 0.08f), + tonalElevation = 0.dp, + shadowElevation = 0.dp, + border = BorderStroke(1.dp, Color.White.copy(alpha = 0.16f)) + ) { + Box( + modifier = Modifier + .size(44.dp) + .background( + Brush.linearGradient( + listOf( + PurrfectPalette.glowPrimary.copy(alpha = 0.22f), + PurrfectPalette.glowSecondary.copy(alpha = 0.2f) + ) + ), + RoundedCornerShape(16.dp) + ), + contentAlignment = Alignment.Center + ) { + Icon( + imageVector = Icons.Filled.RemoveRedEye, + contentDescription = null, + tint = Color.White + ) + } + } + } + } + } + + @Composable + private fun SocialHeader( + titles: List, + pagerState: androidx.compose.foundation.pager.PagerState, + onTabSelected: (Int) -> Unit, + friendCount: Int, + groupCount: Int + ) { + Surface( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 14.dp, vertical = 12.dp) + .padding(top = WindowInsets.statusBars.asPaddingValues().calculateTopPadding()), + shape = RoundedCornerShape(26.dp), + color = Color.White.copy(alpha = 0.07f), + tonalElevation = 0.dp, + shadowElevation = 0.dp, + border = BorderStroke( + 1.dp, + Brush.linearGradient( + listOf( + PurrfectPalette.glowPrimary.copy(alpha = 0.55f), + PurrfectPalette.glowSecondary.copy(alpha = 0.35f) + ) + ) + ) + ) { + Column( + modifier = Modifier.padding(horizontal = 16.dp, vertical = 14.dp), + verticalArrangement = Arrangement.spacedBy(12.dp) + ) { + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.spacedBy(12.dp), + verticalAlignment = Alignment.CenterVertically + ) { + Column( + modifier = Modifier.weight(1f), + verticalArrangement = Arrangement.spacedBy(4.dp) + ) { + Text( + text = translation["manager.routes.social"] ?: "Social", + color = Color.White, + fontWeight = FontWeight.ExtraBold, + fontSize = 18.sp + ) + } + Row( + modifier = Modifier.wrapContentWidth(), + horizontalArrangement = Arrangement.spacedBy(8.dp), + verticalAlignment = Alignment.CenterVertically + ) { + StatPill(label = "Friends", value = friendCount) + StatPill(label = "Groups", value = groupCount) + } + } + SocialTabSwitcher( + titles = titles, + pagerState = pagerState, + onTabSelected = onTabSelected + ) + } + } + } + + @Composable + private fun SocialTabSwitcher( + titles: List, + pagerState: androidx.compose.foundation.pager.PagerState, + onTabSelected: (Int) -> Unit + ) { + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.spacedBy(10.dp) + ) { + titles.forEachIndexed { index, title -> + val selected = pagerState.currentPage == index + Surface( + shape = RoundedCornerShape(18.dp), + color = if (selected) Color.White.copy(alpha = 0.12f) else Color.White.copy(alpha = 0.06f), + border = if (selected) BorderStroke(1.dp, Brush.linearGradient(listOf(PurrfectPalette.glowPrimary, PurrfectPalette.glowSecondary))) else BorderStroke( + 1.dp, + Color.White.copy(alpha = 0.12f) + ), + modifier = Modifier.weight(1f) + ) { + Row( + modifier = Modifier + .clickable { onTabSelected(index) } + .padding(horizontal = 12.dp, vertical = 10.dp), + horizontalArrangement = Arrangement.spacedBy(8.dp), + verticalAlignment = Alignment.CenterVertically + ) { + Icon( + imageVector = if (index == 0) Icons.Filled.People else Icons.Filled.Groups, + contentDescription = null, + tint = Color.White + ) + Text( + text = title, + color = Color.White, + maxLines = 1, + overflow = TextOverflow.Ellipsis, + fontWeight = FontWeight.Medium + ) + } + } + } + } + } + + @Composable + private fun EmptyState(scope: SocialScope) { + val title = when (scope) { + SocialScope.FRIEND -> translation.getOrNull("friends_empty_title") ?: translation["empty_hint"] + SocialScope.GROUP -> translation.getOrNull("groups_empty_title") ?: translation["empty_hint"] + } + Surface( + modifier = Modifier + .fillMaxWidth() + .padding(top = 8.dp), + shape = RoundedCornerShape(20.dp), + color = Color.White.copy(alpha = 0.05f), + tonalElevation = 0.dp, + shadowElevation = 0.dp, + border = BorderStroke(1.dp, Color.White.copy(alpha = 0.12f)) + ) { + Column( + modifier = Modifier.padding(horizontal = 18.dp, vertical = 16.dp), + verticalArrangement = Arrangement.spacedBy(8.dp), + horizontalAlignment = Alignment.Start + ) { + Icon( + imageVector = if (scope == SocialScope.FRIEND) Icons.Filled.People else Icons.Filled.Groups, + contentDescription = null, + tint = PurrfectPalette.glowSecondary, + modifier = Modifier.size(26.dp) + ) + Text( + text = title, + color = Color.White, + fontWeight = FontWeight.SemiBold, + fontSize = 15.sp + ) + Text( + text = translation["social_empty_hint"] ?: "Tap the + button to sync friends or groups.", + color = PurrfectPalette.textSecondary, + fontSize = 12.sp + ) + } + } + } + + @Composable + private fun StatPill(label: String, value: Int) { + Surface( + shape = RoundedCornerShape(50), + color = Color.White.copy(alpha = 0.08f), + border = BorderStroke(1.dp, Color.White.copy(alpha = 0.16f)), + tonalElevation = 0.dp, + shadowElevation = 0.dp + ) { + Row( + modifier = Modifier.padding(horizontal = 10.dp, vertical = 6.dp), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(6.dp) + ) { + Text( + text = value.toString(), + color = Color.White, + fontWeight = FontWeight.ExtraBold + ) + Text( + text = label, + color = PurrfectPalette.textSecondary, + fontSize = 12.sp, + maxLines = 1, + overflow = TextOverflow.Ellipsis + ) + } + } + } +} diff --git a/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/tracker/EditRule.kt b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/tracker/EditRule.kt new file mode 100644 index 00000000..ecdafe12 --- /dev/null +++ b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/tracker/EditRule.kt @@ -0,0 +1,781 @@ +@file:OptIn( + androidx.compose.material3.ExperimentalMaterial3Api::class, + androidx.compose.foundation.layout.ExperimentalLayoutApi::class +) +package me.eternal.purrfectsnap.ui.manager.pages.tracker + +import androidx.compose.animation.animateContentSize +import androidx.compose.foundation.ExperimentalFoundationApi +import androidx.compose.foundation.BorderStroke +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.layout.ColumnScope +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.foundation.verticalScroll +import androidx.compose.foundation.interaction.MutableInteractionSource +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.automirrored.filled.ArrowBack +import androidx.compose.material.icons.filled.Add +import androidx.compose.material.icons.filled.DeleteOutline +import androidx.compose.material.icons.filled.ExpandLess +import androidx.compose.material.icons.filled.ExpandMore +import androidx.compose.material.icons.filled.Info +import androidx.compose.material.icons.filled.Save +import androidx.compose.material.icons.filled.Warning +import androidx.activity.compose.BackHandler +import androidx.compose.material3.* +import androidx.compose.runtime.* +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.Brush +import androidx.compose.ui.graphics.Color +import androidx.compose.material3.LocalTextStyle +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.text.style.TextOverflow +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import androidx.compose.ui.window.Dialog +import androidx.compose.ui.window.DialogProperties +import androidx.navigation.NavBackStackEntry +import kotlinx.coroutines.launch +import me.eternal.purrfectsnap.common.data.* +import me.eternal.purrfectsnap.common.ui.rememberAsyncMutableState +import me.eternal.purrfectsnap.common.ui.rememberAsyncMutableStateList +import me.eternal.purrfectsnap.storage.* +import me.eternal.purrfectsnap.ui.manager.Routes +import me.eternal.purrfectsnap.ui.manager.components.AestheticDialog +import me.eternal.purrfectsnap.ui.manager.theme.PurrfectPalette +import me.eternal.purrfectsnap.ui.manager.pages.social.AddFriendDialog + +class EditRule : Routes.Route() { + override val translation by lazy { context.translation.getCategory("manager.friend_tracker") } + + @Composable + private fun RuleCard( + modifier: Modifier = Modifier, + contentPadding: PaddingValues = PaddingValues(16.dp), + content: @Composable ColumnScope.() -> Unit + ) { + val shape = RoundedCornerShape(22.dp) + val border = remember { + Brush.linearGradient( + listOf( + PurrfectPalette.glowPrimary.copy(alpha = 0.5f), + PurrfectPalette.glowSecondary.copy(alpha = 0.42f) + ) + ) + } + Surface( + modifier = modifier, + shape = shape, + color = Color.White.copy(alpha = 0.04f), + tonalElevation = 0.dp, + shadowElevation = 14.dp, + border = BorderStroke(1.dp, border) + ) { + Box( + modifier = Modifier + .background(PurrfectPalette.cardOverlay, shape) + .padding(contentPadding) + ) { + Column(content = content) + } + } + } + + @Composable + fun ActionCheckbox( + text: String, + checked: MutableState, + onChanged: (Boolean) -> Unit = {} + ) { + Row( + modifier = Modifier.clickable { + checked.value = !checked.value + onChanged(checked.value) + }, + horizontalArrangement = Arrangement.spacedBy(2.dp), + verticalAlignment = Alignment.CenterVertically + ) { + Checkbox( + modifier = Modifier.height(30.dp), + checked = checked.value, + onCheckedChange = { checked.value = it; onChanged(it) }, + colors = CheckboxDefaults.colors( + checkedColor = PurrfectPalette.glowPrimary, + uncheckedColor = Color.White.copy(alpha = 0.8f), + checkmarkColor = Color.Black + ) + ) + Text(text, fontSize = 12.sp, color = Color.White) + } + } + @Composable + fun ConditionCheckboxes( + params: TrackerRuleActionParams + ) { + ActionCheckbox( + text = translation["condition_only_inside_conversation"], + checked = remember { mutableStateOf(params.onlyInsideConversation) }, + onChanged = { params.onlyInsideConversation = it } + ) + ActionCheckbox( + text = translation["condition_only_outside_conversation"], + checked = remember { mutableStateOf(params.onlyOutsideConversation) }, + onChanged = { params.onlyOutsideConversation = it } + ) + ActionCheckbox( + text = translation["condition_only_when_app_active"], + checked = remember { mutableStateOf(params.onlyWhenAppActive) }, + onChanged = { params.onlyWhenAppActive = it } + ) + ActionCheckbox( + text = translation["condition_only_when_app_inactive"], + checked = remember { mutableStateOf(params.onlyWhenAppInactive) }, + onChanged = { params.onlyWhenAppInactive = it } + ) + ActionCheckbox( + text = translation["condition_no_push_notification_when_app_active"], + checked = remember { mutableStateOf(params.noPushNotificationWhenAppActive) }, + onChanged = { params.noPushNotificationWhenAppActive = it } + ) + } + @Composable + fun AddEventDialog( + onDismissRequest: () -> Unit, + onEventAdd: (TrackerRuleEvent) -> Unit + ) { + val expanded = remember { mutableStateOf(false) } + val currentEventType = remember { mutableStateOf(TrackerEventType.CONVERSATION_ENTER.key) } + val addEventActions = remember { mutableStateOf(emptySet()) } + val addEventActionParams = remember { TrackerRuleActionParams() } + Dialog( + onDismissRequest = onDismissRequest, + properties = DialogProperties(dismissOnClickOutside = true, usePlatformDefaultWidth = false) + ) { + RuleCard( + modifier = Modifier + .padding(horizontal = 10.dp) + .widthIn(max = 420.dp), + contentPadding = PaddingValues(18.dp) + ) { + Column( + horizontalAlignment = Alignment.Start, + verticalArrangement = Arrangement.spacedBy(12.dp) + ) { + Text( + translation["add_event_dialog_title"], + style = MaterialTheme.typography.titleLarge.copy(fontWeight = FontWeight.ExtraBold), + color = Color.White, + textAlign = TextAlign.Center, + modifier = Modifier.fillMaxWidth() + ) + ExposedDropdownMenuBox( + expanded = expanded.value, + onExpandedChange = { expanded.value = !expanded.value }, + modifier = Modifier.fillMaxWidth() + ) { + val eventLabel = context.translation["tracker_events.${currentEventType.value}"] + Box( + modifier = Modifier.fillMaxWidth(), + contentAlignment = Alignment.Center + ) { + OutlinedTextField( + modifier = Modifier + .menuAnchor() + .widthIn(min = 240.dp), + value = eventLabel, + onValueChange = {}, + readOnly = true, + textStyle = LocalTextStyle.current.copy(textAlign = TextAlign.Center, color = Color.White), + trailingIcon = { ExposedDropdownMenuDefaults.TrailingIcon(expanded = expanded.value) }, + colors = TextFieldDefaults.colors( + focusedContainerColor = PurrfectPalette.cardOverlayColor, + unfocusedContainerColor = PurrfectPalette.cardOverlayColor, + focusedIndicatorColor = Color.White.copy(alpha = 0.18f), + unfocusedIndicatorColor = Color.White.copy(alpha = 0.14f), + cursorColor = Color.Transparent, + focusedTextColor = Color.White, + unfocusedTextColor = Color.White + ) + ) + } + ExposedDropdownMenu( + expanded = expanded.value, + onDismissRequest = { expanded.value = false }, + modifier = Modifier.widthIn(min = 240.dp), + containerColor = Color(0xFF121528), + shape = RoundedCornerShape(14.dp) + ) { + TrackerEventType.entries.forEach { eventType -> + DropdownMenuItem( + onClick = { + currentEventType.value = eventType.key + expanded.value = false + }, + text = { Text(context.translation["tracker_events.${eventType.key}"], color = Color.White) } + ) + } + } + } + Text( + translation["triggers_title"], + style = MaterialTheme.typography.titleMedium, + color = Color.White, + textAlign = TextAlign.Center, + modifier = Modifier.fillMaxWidth() + ) + FlowRow( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.spacedBy(8.dp) + ) { + TrackerRuleAction.entries.forEach { action -> + ActionCheckbox( + context.translation["tracker_actions.${action.key}"], + checked = remember { mutableStateOf(addEventActions.value.contains(action)) } + ) { + if (it) addEventActions.value += action else addEventActions.value -= action + } + } + } + Text( + translation["conditions_title"], + style = MaterialTheme.typography.titleMedium, + color = Color.White, + textAlign = TextAlign.Center, + modifier = Modifier.fillMaxWidth() + ) + ConditionCheckboxes(addEventActionParams) + Button( + onClick = { + onEventAdd( + TrackerRuleEvent( + id = -1, + enabled = true, + eventType = currentEventType.value, + params = addEventActionParams.copy(), + actions = addEventActions.value.toList() + ) + ) + }, + modifier = Modifier.align(Alignment.CenterHorizontally), + colors = ButtonDefaults.buttonColors( + containerColor = PurrfectPalette.glowPrimary.copy(alpha = 0.35f), + contentColor = Color.White + ) + ) { Text(translation["add_button"]) } + } + } + } + } + override val title: @Composable () -> Unit = {} + @OptIn(ExperimentalFoundationApi::class) + override val content: @Composable (NavBackStackEntry) -> Unit = { navBackStackEntry -> + val coroutineScope = rememberCoroutineScope() + val currentRuleId = navBackStackEntry.arguments?.getString("rule_id")?.toIntOrNull() + val events = rememberAsyncMutableStateList(defaultValue = emptyList()) { + currentRuleId?.let { ruleId -> context.database.getTrackerEvents(ruleId) } ?: emptyList() + } + val eventsToDelete = remember { mutableStateListOf() } + var currentScopeType by remember { mutableStateOf(TrackerScopeType.BLACKLIST) } + val scopes = rememberAsyncMutableStateList(defaultValue = emptyList()) { + currentRuleId?.let { ruleId -> + context.database.getRuleTrackerScopes(ruleId).also { map -> + currentScopeType = if (map.isEmpty()) TrackerScopeType.WHITELIST else map.values.first() + }.map { entry -> entry.key } + } ?: emptyList() + } + val ruleName = rememberAsyncMutableState(defaultValue = "", keys = arrayOf(currentRuleId)) { + currentRuleId?.let { ruleId -> context.database.getTrackerRule(ruleId)?.name ?: translation["default_rule_name"] } ?: translation["default_rule_name"] + } + val authorName = rememberAsyncMutableState(defaultValue = "", keys = arrayOf(currentRuleId)) { + currentRuleId?.let { ruleId -> context.database.getTrackerRule(ruleId)?.author ?: "" } ?: "" + } + val initialRuleState by remember(ruleName.value.isNotBlank() || events.isNotEmpty() || scopes.isNotEmpty()) { + mutableStateOf( + mapOf( + "name" to ruleName.value, + "author" to authorName.value, + "scopes" to scopes.toList(), + "events" to events.toList(), + "scopeType" to currentScopeType + ) + ) + } + val isDirty by remember { + derivedStateOf { + initialRuleState["name"] != ruleName.value || + initialRuleState["author"] != authorName.value || + initialRuleState["scopes"] != scopes.toList() || + initialRuleState["events"] != events.toList() || + initialRuleState["scopeType"] != currentScopeType + } + } + var deleteConfirmation by remember { mutableStateOf(false) } + var showDuplicateNameDialog by remember { mutableStateOf(false) } + var showEventsEmptyDialog by remember { mutableStateOf(false) } + var showDiscardDialog by remember { mutableStateOf(false) } + var addFriendDialog by remember { mutableStateOf(null) } + var addEventDialogVisible by remember { mutableStateOf(false) } + if (showDiscardDialog) { + AestheticDialog( + onDismissRequest = { showDiscardDialog = false }, + title = translation["discard_changes_dialog_title"], + text = translation["discard_changes_dialog_text"], + icon = Icons.Default.Warning, + confirmButtonText = translation["discard_button"], + onConfirm = { + showDiscardDialog = false + routes.navController.popBackStack() + }, + dismissButtonText = translation["button.cancel"], + onDismiss = { showDiscardDialog = false }, + opaque = true, + showCloseButton = false + ) + } + BackHandler(enabled = isDirty) { + showDiscardDialog = true + } + if (showEventsEmptyDialog) { + AestheticDialog( + onDismissRequest = { showEventsEmptyDialog = false }, + title = translation["cannot_save_rule_dialog_title"], + text = translation["cannot_save_rule_dialog_text"], + icon = Icons.Default.Info, + confirmButtonText = translation["button.ok"], + onConfirm = { showEventsEmptyDialog = false }, + opaque = true, + showCloseButton = false + ) + } + if (showDuplicateNameDialog) { + AestheticDialog( + onDismissRequest = { showDuplicateNameDialog = false }, + title = translation["duplicate_rule_name_dialog_title"], + text = translation["duplicate_rule_name_dialog_text"], + icon = Icons.Default.Warning, + confirmButtonText = translation["button.ok"], + onConfirm = { showDuplicateNameDialog = false } + ) + } + if (deleteConfirmation) { + AestheticDialog( + onDismissRequest = { deleteConfirmation = false }, + title = translation["delete_rule_dialog_title"], + text = translation["delete_rule_dialog_text"], + icon = Icons.Default.DeleteOutline, + confirmButtonText = translation["delete_button"], + onConfirm = { + if (currentRuleId != null) context.database.deleteTrackerRule(currentRuleId) + routes.navController.popBackStack() + }, + dismissButtonText = translation["button.cancel"], + onDismiss = { deleteConfirmation = false }, + opaque = true, + showCloseButton = false + ) + } + Scaffold( + modifier = Modifier + .fillMaxSize() + .systemBarsPadding() + .navigationBarsPadding(), + containerColor = Color.Transparent, + topBar = { + val topShape = RoundedCornerShape(26.dp) + Surface( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 14.dp, vertical = 12.dp), + shape = topShape, + color = PurrfectPalette.cardOverlayColor, + shadowElevation = 12.dp, + border = BorderStroke(1.dp, Color.White.copy(alpha = 0.12f)) + ) { + Row( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 14.dp, vertical = 12.dp), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(12.dp) + ) { + IconButton(onClick = { + if (isDirty) { + showDiscardDialog = true + } else { + routes.navController.popBackStack() + } + }) { + Icon(Icons.AutoMirrored.Filled.ArrowBack, contentDescription = translation["back_button_description"], tint = Color.White) + } + Column(modifier = Modifier.weight(1f)) { + Text( + translation[if (currentRuleId == null) "new_rule_title" else "edit_rule_title"], + color = Color.White, + fontWeight = FontWeight.ExtraBold, + fontSize = 18.sp + ) + Text( + translation["rule_subtitle"] ?: "", + color = PurrfectPalette.textSecondary, + fontSize = 12.sp + ) + } + IconButton(onClick = { + if (events.isEmpty()) { + showEventsEmptyDialog = true + return@IconButton + } + if (currentRuleId == null && context.database.getTrackerRuleByName(ruleName.value.trim()) != null) { + showDuplicateNameDialog = true + return@IconButton + } + val ruleId = currentRuleId ?: context.database.newTrackerRule() + eventsToDelete.forEach { event -> context.database.deleteTrackerRuleEvent(event.id.takeIf { it > -1 } ?: return@forEach) } + events.forEach { event -> + context.database.addOrUpdateTrackerRuleEvent( + event.id.takeIf { it > -1 }, + ruleId, + event.eventType, + event.params, + event.actions + ) + } + context.database.setTrackerRuleName(ruleId, ruleName.value.trim()) + context.database.setTrackerRuleAuthor(ruleId, authorName.value.trim()) + context.database.setRuleTrackerScopes(ruleId, currentScopeType, scopes) + routes.navController.popBackStack() + }) { Icon(Icons.Filled.Save, contentDescription = translation["save_button_description"], tint = Color.White) } + if (currentRuleId != null) { + IconButton(onClick = { deleteConfirmation = true }) { + Icon(Icons.Default.DeleteOutline, contentDescription = translation["delete_button_description"], tint = Color.White) + } + } + } + } + } + ) { padding -> + Box( + modifier = Modifier + .fillMaxSize() + .background(PurrfectPalette.backgroundGradient) + .padding(padding) + ) { + Column( + modifier = Modifier + .fillMaxSize() + .verticalScroll(rememberScrollState()), + verticalArrangement = Arrangement.spacedBy(16.dp) + ) { + RuleCard( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 12.dp, vertical = 4.dp) + ) { + Text( + translation["general_section_title"], + style = MaterialTheme.typography.titleMedium, + color = Color.White, + textAlign = TextAlign.Center, + modifier = Modifier.fillMaxWidth() + ) + TextField( + value = ruleName.value, + onValueChange = { ruleName.value = it }, + label = { Text(translation["rule_name_label"], color = PurrfectPalette.textSecondary) }, + modifier = Modifier.fillMaxWidth(), + singleLine = true, + colors = TextFieldDefaults.colors( + focusedContainerColor = Color.White.copy(alpha = 0.05f), + unfocusedContainerColor = Color.White.copy(alpha = 0.04f), + focusedIndicatorColor = Color.Transparent, + unfocusedIndicatorColor = Color.Transparent, + cursorColor = PurrfectPalette.glowPrimary, + focusedLabelColor = Color.White, + unfocusedLabelColor = PurrfectPalette.textSecondary + ), + textStyle = LocalTextStyle.current.copy(color = Color.White) + ) + Spacer(modifier = Modifier.height(8.dp)) + TextField( + value = authorName.value, + onValueChange = { authorName.value = it }, + label = { Text(translation["author_name_label"], color = PurrfectPalette.textSecondary) }, + modifier = Modifier.fillMaxWidth(), + singleLine = true, + colors = TextFieldDefaults.colors( + focusedContainerColor = Color.White.copy(alpha = 0.05f), + unfocusedContainerColor = Color.White.copy(alpha = 0.04f), + focusedIndicatorColor = Color.Transparent, + unfocusedIndicatorColor = Color.Transparent, + cursorColor = PurrfectPalette.glowPrimary, + focusedLabelColor = Color.White, + unfocusedLabelColor = PurrfectPalette.textSecondary + ), + textStyle = LocalTextStyle.current.copy(color = Color.White) + ) + } + RuleCard( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 12.dp, vertical = 4.dp) + ) { + Text( + translation["scope_section_title"], + style = MaterialTheme.typography.titleMedium, + color = Color.White, + textAlign = TextAlign.Center, + modifier = Modifier.fillMaxWidth() + ) + val friendDialogActions = remember { + AddFriendDialog.Actions( + onFriendState = { friend, state -> + if (state) scopes.add(friend.userId) else scopes.remove(friend.userId) + }, + onGroupState = { group, state -> + if (state) scopes.add(group.conversationId) else scopes.remove(group.conversationId) + }, + getFriendState = { friend -> friend.userId in scopes }, + getGroupState = { group -> group.conversationId in scopes } + ) + } + val scopeOptions = listOf( + 0 to translation["scope_all"], + 1 to translation["scope_whitelist"], + 2 to translation["scope_blacklist"] + ) + val selectedScopeIndex = when { + scopes.isEmpty() -> 0 + currentScopeType == TrackerScopeType.WHITELIST -> 1 + else -> 2 + } + Row( + modifier = Modifier + .fillMaxWidth() + .padding(top = 10.dp, bottom = 12.dp), + horizontalArrangement = Arrangement.spacedBy(10.dp) + ) { + scopeOptions.forEach { (index, label) -> + val selected = selectedScopeIndex == index + val optionShape = RoundedCornerShape(16.dp) + val optionBrush = remember { + Brush.linearGradient( + listOf( + PurrfectPalette.glowPrimary.copy(alpha = if (selected) 0.22f else 0.12f), + PurrfectPalette.glowSecondary.copy(alpha = if (selected) 0.18f else 0.1f) + ) + ) + } + Surface( + modifier = Modifier + .weight(1f) + .heightIn(min = 46.dp), + shape = optionShape, + color = Color.Transparent, + border = BorderStroke( + 1.dp, + if (selected) PurrfectPalette.glowPrimary.copy(alpha = 0.5f) else Color.White.copy(alpha = 0.12f) + ), + tonalElevation = 0.dp, + shadowElevation = if (selected) 10.dp else 0.dp + ) { + Box( + modifier = Modifier + .fillMaxSize() + .background(optionBrush, optionShape) + .clickable( + indication = null, + interactionSource = remember { MutableInteractionSource() } + ) { + when (index) { + 0 -> scopes.clear() + 1 -> { + currentScopeType = TrackerScopeType.WHITELIST + if (scopes.isEmpty()) { + addFriendDialog = AddFriendDialog(context, friendDialogActions, pinnedIds = scopes) + } + } + 2 -> { + currentScopeType = TrackerScopeType.BLACKLIST + if (scopes.isEmpty()) { + addFriendDialog = AddFriendDialog(context, friendDialogActions, pinnedIds = scopes) + } + } + } + }, + contentAlignment = Alignment.Center + ) { + Text( + text = label, + color = Color.White, + fontWeight = FontWeight.SemiBold, + textAlign = TextAlign.Center + ) + } + } + } + } + if (scopes.isNotEmpty()) { + val selectorShape = RoundedCornerShape(18.dp) + val selectorBrush = remember { + Brush.linearGradient( + listOf( + PurrfectPalette.glowPrimary.copy(alpha = 0.32f), + PurrfectPalette.glowSecondary.copy(alpha = 0.28f) + ) + ) + } + Surface( + onClick = { + addFriendDialog = AddFriendDialog(context, friendDialogActions, pinnedIds = scopes) + }, + modifier = Modifier + .fillMaxWidth() + .padding(vertical = 4.dp), + shape = selectorShape, + color = Color.Transparent, + tonalElevation = 0.dp, + shadowElevation = 10.dp, + border = BorderStroke(1.dp, Color.White.copy(alpha = 0.14f)) + ) { + Row( + modifier = Modifier + .background(selectorBrush, selectorShape) + .padding(horizontal = 16.dp, vertical = 12.dp), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.Center + ) { + Text( + translation.format("select_friends_groups_button", "count" to scopes.size.toString()), + color = Color.White, + fontWeight = FontWeight.SemiBold + ) + } + } + } + addFriendDialog?.Content { addFriendDialog = null } + } + RuleCard( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 12.dp, vertical = 4.dp) + ) { + Column(Modifier.animateContentSize()) { + Box( + modifier = Modifier.fillMaxWidth(), + contentAlignment = Alignment.Center + ) { + Text( + translation["events_section_title"], + fontSize = 16.sp, + fontWeight = FontWeight.Bold, + color = Color.White, + textAlign = TextAlign.Center + ) + IconButton( + onClick = { addEventDialogVisible = true }, + modifier = Modifier.align(Alignment.CenterEnd) + ) { + Icon(Icons.Default.Add, contentDescription = translation["add_event_button"], modifier = Modifier.size(28.dp), tint = Color.White) + } + } + if (addEventDialogVisible) { + AddEventDialog( + onDismissRequest = { addEventDialogVisible = false }, + onEventAdd = { event -> + events.add(0, event) + addEventDialogVisible = false + } + ) + } + if (events.isEmpty()) { + Text( + translation["no_events_text"], + fontSize = 12.sp, + fontWeight = FontWeight.Light, + modifier = Modifier + .padding(10.dp) + .fillMaxWidth(), + textAlign = TextAlign.Center, + color = PurrfectPalette.textSecondary + ) + } + events.forEach { event -> + var expanded by remember { mutableStateOf(false) } + Surface( + modifier = Modifier + .fillMaxWidth() + .animateContentSize() + .padding(vertical = 4.dp) + .clickable { expanded = !expanded }, + shape = RoundedCornerShape(18.dp), + color = Color.White.copy(alpha = 0.04f), + border = BorderStroke(1.dp, Color.White.copy(alpha = 0.1f)) + ) { + Column(Modifier.padding(8.dp)) { + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.CenterVertically + ) { + Row( + modifier = Modifier.weight(1f, fill = false), + horizontalArrangement = Arrangement.spacedBy(8.dp), + verticalAlignment = Alignment.CenterVertically + ) { + Icon( + if (expanded) Icons.Filled.ExpandLess else Icons.Filled.ExpandMore, + contentDescription = null, + tint = Color.White + ) + Column { + Text( + context.translation["tracker_events.${event.eventType}"], + lineHeight = 20.sp, + fontSize = 18.sp, + fontWeight = FontWeight.Bold, + color = Color.White + ) + Text( + text = event.actions.joinToString(", ") { context.translation["tracker_actions.${it.key}"] }, + fontSize = 10.sp, + fontWeight = FontWeight.Light, + overflow = TextOverflow.Ellipsis, + maxLines = 1, + lineHeight = 14.sp, + color = PurrfectPalette.textSecondary + ) + } + } + OutlinedIconButton( + onClick = { + if (event.id > -1) { + eventsToDelete.add(event) + } + events.remove(event) + } + ) { + Icon(Icons.Default.DeleteOutline, contentDescription = translation["delete_button_description"], tint = Color.White) + } + } + if (expanded) { + Column(modifier = Modifier.padding(top = 8.dp)) { + ConditionCheckboxes(event.params) + } + } + } + } + } + } + } + Spacer(Modifier.height(routes.bottomPadding)) + } + } + } + } +} diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/tracker/FriendTrackerCatalog.kt b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/tracker/FriendTrackerCatalog.kt similarity index 53% rename from app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/tracker/FriendTrackerCatalog.kt rename to app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/tracker/FriendTrackerCatalog.kt index 13c5f5c7..c15a78b4 100644 --- a/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/tracker/FriendTrackerCatalog.kt +++ b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/tracker/FriendTrackerCatalog.kt @@ -1,13 +1,21 @@ @file:OptIn(androidx.compose.foundation.ExperimentalFoundationApi::class) -package me.rhunk.snapenhance.ui.manager.pages.tracker +package me.eternal.purrfectsnap.ui.manager.pages.tracker +import androidx.compose.foundation.BorderStroke +import androidx.compose.foundation.background +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.WindowInsets +import androidx.compose.foundation.layout.asPaddingValues +import androidx.compose.foundation.layout.statusBars import androidx.compose.material.icons.Icons import androidx.compose.material.icons.automirrored.filled.ArrowBack import androidx.compose.material3.* import androidx.compose.runtime.* +import androidx.compose.ui.platform.LocalDensity import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.PaddingValues @@ -22,18 +30,26 @@ import androidx.compose.material.icons.filled.Public import androidx.compose.material.icons.automirrored.filled.Rule import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Brush +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.layout.onGloballyPositioned import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextOverflow +import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp +import androidx.compose.ui.zIndex import androidx.navigation.NavBackStackEntry import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import kotlinx.coroutines.withContext -import me.rhunk.snapenhance.storage.getRepositories -import me.rhunk.snapenhance.storage.getTrackerRuleByName -import me.rhunk.snapenhance.ui.manager.Routes +import me.eternal.purrfectsnap.storage.getRepositories +import me.eternal.purrfectsnap.storage.getTrackerRuleByName +import me.eternal.purrfectsnap.ui.manager.Routes +import me.eternal.purrfectsnap.ui.manager.components.AestheticEmptyState +import me.eternal.purrfectsnap.ui.manager.components.FloatingTopBar +import me.eternal.purrfectsnap.ui.manager.theme.PurrfectPalette import okhttp3.OkHttpClient import okhttp3.Request @@ -53,7 +69,7 @@ class FriendTrackerCatalog : Routes.Route() { override val translation by lazy { context.translation.getCategory("manager.friend_tracker_catalog") } @Composable - private fun AvailableRulesTab() { + private fun AvailableRulesTab(topBarHeight: Dp) { val coroutineScope = rememberCoroutineScope() val okHttpClient = remember { OkHttpClient() } val gson = remember { context.gson } @@ -113,6 +129,33 @@ class FriendTrackerCatalog : Routes.Route() { manifest.rules.map { repoUrl to it } } + if (repositories.isEmpty() && !isLoading) { + Box( + modifier = Modifier.fillMaxSize(), + contentAlignment = Alignment.Center + ) { + AestheticEmptyState( + icon = Icons.Default.Public, + title = translation["no_repos_added"], + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 22.dp), + actions = { + Button( + onClick = { routes.manageFriendTrackerRepos.navigate() }, + colors = ButtonDefaults.buttonColors( + containerColor = PurrfectPalette.glowPrimary.copy(alpha = 0.34f), + contentColor = Color.White + ) + ) { + Text(translation["manage_repos_description"] ?: (context.translation["manager.routes.manage_friend_tracker_repos"] ?: "Manage repositories")) + } + } + ) + } + return + } + fun importRule(repoUrl: String, entry: FriendTrackerRepoEntry) { coroutineScope.launch(Dispatchers.IO) { val rawUrl = if (repoUrl.endsWith("/")) repoUrl + entry.path else repoUrl + "/" + entry.path @@ -153,31 +196,40 @@ class FriendTrackerCatalog : Routes.Route() { ) } } else { - LazyColumn( - modifier = Modifier.fillMaxSize(), - contentPadding = PaddingValues(start = 8.dp, top = 8.dp, end = 8.dp, bottom = 8.dp + routes.bottomPadding) - ) { - item { - if (isLoading) { - Box( - modifier = Modifier - .fillMaxWidth() + LazyColumn( + modifier = Modifier.fillMaxSize(), + contentPadding = PaddingValues( + start = 8.dp, + top = topBarHeight + 12.dp, + end = 8.dp, + bottom = 8.dp + routes.bottomPadding + ) + ) { + item { + if (isLoading) { + Box( + modifier = Modifier + .fillMaxWidth() .padding(8.dp), contentAlignment = Alignment.Center ) { CircularProgressIndicator() } } else if (allRules.isEmpty() && repositories.isNotEmpty()) { - Text( - text = translation["no_rules_available"], + Box( modifier = Modifier - .padding(16.dp) - .fillMaxWidth(), - textAlign = TextAlign.Center, - fontSize = 15.sp, - fontWeight = FontWeight.Light, - color = MaterialTheme.colorScheme.onSurfaceVariant - ) + .fillMaxWidth() + .padding(vertical = 28.dp, horizontal = 6.dp), + contentAlignment = Alignment.Center + ) { + AestheticEmptyState( + icon = Icons.AutoMirrored.Filled.Rule, + title = translation["no_rules_available"], + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 22.dp) + ) + } } } items(allRules) { (repoUrl, entry) -> @@ -189,54 +241,85 @@ class FriendTrackerCatalog : Routes.Route() { value = exists } - ElevatedCard(Modifier.padding(bottom = 8.dp).animateContentSize()) { + val shape = RoundedCornerShape(20.dp) + Surface( + modifier = Modifier + .fillMaxWidth() + .animateContentSize(), + shape = shape, + color = PurrfectPalette.cardOverlayColor, + tonalElevation = 0.dp, + shadowElevation = 10.dp, + border = BorderStroke( + 1.dp, + Brush.linearGradient( + listOf( + PurrfectPalette.glowPrimary.copy(alpha = 0.45f), + PurrfectPalette.glowSecondary.copy(alpha = 0.35f) + ) + ) + ) + ) { Row( modifier = Modifier .fillMaxWidth() - .padding(8.dp), - verticalAlignment = Alignment.CenterVertically + .background(PurrfectPalette.cardOverlay, shape) + .padding(horizontal = 14.dp, vertical = 12.dp), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(12.dp) ) { - Icon( - Icons.AutoMirrored.Filled.Rule, null, Modifier.padding(end = 12.dp) - ) - Column( - Modifier.weight(1f), - verticalArrangement = Arrangement.Center + Surface( + shape = CircleShape, + color = PurrfectPalette.glowPrimary.copy(alpha = 0.18f), + tonalElevation = 0.dp, + shadowElevation = 0.dp ) { - Row( - horizontalArrangement = Arrangement.spacedBy(4.dp), - verticalAlignment = Alignment.Bottom - ) { + Icon( + Icons.AutoMirrored.Filled.Rule, + contentDescription = null, + modifier = Modifier.padding(10.dp), + tint = Color.White + ) + } + Column( + modifier = Modifier.weight(1f), + verticalArrangement = Arrangement.spacedBy(4.dp) + ) { + Text( + text = entry.name, + maxLines = 1, + overflow = TextOverflow.Ellipsis, + fontWeight = FontWeight.ExtraBold, + color = Color.White + ) + entry.author?.let { Text( - text = entry.name, + text = translation.format("by_author", "author" to it), maxLines = 1, overflow = TextOverflow.Ellipsis, - fontWeight = FontWeight.Bold + fontSize = 12.sp, + color = PurrfectPalette.textSecondary ) - entry.author?.let { - Text( - text = translation.format("by_author", "author" to it), - maxLines = 1, - fontSize = 10.sp, - fontWeight = FontWeight.Light, - overflow = TextOverflow.Ellipsis - ) - } } - entry.description?.let { + entry.description?.takeIf { it.isNotBlank() }?.let { Text( text = it, fontSize = 12.sp, maxLines = 3, - overflow = TextOverflow.Ellipsis + overflow = TextOverflow.Ellipsis, + color = PurrfectPalette.textSecondary ) } } Button( - onClick = { - importRule(repoUrl, entry) - }, - enabled = !isImported + onClick = { importRule(repoUrl, entry) }, + enabled = !isImported, + colors = ButtonDefaults.buttonColors( + containerColor = PurrfectPalette.glowPrimary.copy(alpha = 0.34f), + contentColor = Color.White, + disabledContainerColor = Color.White.copy(alpha = 0.08f), + disabledContentColor = PurrfectPalette.textSecondary + ) ) { Text(if (isImported) translation["imported_button"] else translation["import_button"]) } @@ -247,14 +330,32 @@ class FriendTrackerCatalog : Routes.Route() { } } - override val title: @Composable () -> Unit = { Text(translation["title"]) } - override val topBarActions: @Composable RowScope.() -> Unit = { - IconButton(onClick = { routes.manageFriendTrackerRepos.navigate() }) { - Icon(Icons.Default.Public, contentDescription = translation["manage_repos_description"]) + override val content: @Composable (NavBackStackEntry) -> Unit = { + val density = LocalDensity.current + val statusBarTopPadding = WindowInsets.statusBars.asPaddingValues().calculateTopPadding() + var topBarHeight by remember { mutableStateOf(statusBarTopPadding + 96.dp) } + + Box( + modifier = Modifier + .fillMaxSize() + .background(PurrfectPalette.backgroundGradient) + ) { + FloatingTopBar( + title = translation["title"] ?: (routeInfo.translatedKey?.value ?: "Catalog"), + onBack = { routes.navController.popBackStack() }, + actions = { + IconButton(onClick = { routes.manageFriendTrackerRepos.navigate() }) { + Icon(Icons.Default.Public, contentDescription = translation["manage_repos_description"], tint = Color.White) + } + }, + modifier = Modifier + .zIndex(2f) + .onGloballyPositioned { + val newHeight = with(density) { it.size.height.toDp() } + if (newHeight != topBarHeight) topBarHeight = newHeight + } + ) + AvailableRulesTab(topBarHeight = topBarHeight) } } - override val content: @Composable (NavBackStackEntry) -> Unit = { - AvailableRulesTab() - } } - diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/tracker/FriendTrackerConfigExportScreen.kt b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/tracker/FriendTrackerConfigExportScreen.kt similarity index 74% rename from app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/tracker/FriendTrackerConfigExportScreen.kt rename to app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/tracker/FriendTrackerConfigExportScreen.kt index f36d01ef..37bfcbee 100644 --- a/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/tracker/FriendTrackerConfigExportScreen.kt +++ b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/tracker/FriendTrackerConfigExportScreen.kt @@ -1,7 +1,8 @@ -package me.rhunk.snapenhance.ui.manager.pages.tracker +package me.eternal.purrfectsnap.ui.manager.pages.tracker import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.core.animateFloatAsState +import androidx.compose.foundation.BorderStroke import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column @@ -18,6 +19,7 @@ import androidx.compose.foundation.lazy.items import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.icons.Icons import androidx.compose.material.icons.automirrored.filled.ArrowBack +import androidx.compose.material.icons.filled.ArrowDownward import androidx.compose.material.icons.filled.KeyboardArrowDown import androidx.compose.material3.Card import androidx.compose.material3.ExperimentalMaterial3Api @@ -26,8 +28,8 @@ import androidx.compose.material3.Icon import androidx.compose.material3.IconButton import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Scaffold +import androidx.compose.material3.Surface import androidx.compose.material3.Text -import androidx.compose.material3.TextButton import androidx.compose.material3.TopAppBar import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect @@ -38,6 +40,8 @@ import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Brush +import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.graphicsLayer import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextAlign @@ -45,12 +49,13 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch -import me.rhunk.snapenhance.common.data.ExportedTrackerData -import me.rhunk.snapenhance.common.data.ExportType -import me.rhunk.snapenhance.storage.getTrackerRule -import me.rhunk.snapenhance.storage.getTrackerRulesDesc -import me.rhunk.snapenhance.ui.manager.Routes -import me.rhunk.snapenhance.ui.util.saveFile +import me.eternal.purrfectsnap.common.data.ExportedTrackerData +import me.eternal.purrfectsnap.common.data.ExportType +import me.eternal.purrfectsnap.storage.getTrackerRule +import me.eternal.purrfectsnap.storage.getTrackerRulesDesc +import me.eternal.purrfectsnap.ui.manager.Routes +import me.eternal.purrfectsnap.ui.manager.theme.PurrfectPalette +import me.eternal.purrfectsnap.ui.util.saveFile import org.json.JSONArray class FriendTrackerConfigExportScreen : Routes.Route() { @@ -85,21 +90,41 @@ class FriendTrackerConfigExportScreen : Routes.Route() { } }, actions = { - TextButton(onClick = { - routes.activityLauncher.saveFile("friend_tracker_config.json", "application/json") { uri -> - runCatching { - context.androidContext.contentResolver.openOutputStream(android.net.Uri.parse(uri))?.use { - trackerData?.let { data -> - context.gson.toJson(data).byteInputStream().copyTo(it) - context.shortToast(translation["exported_toast"]) + Surface( + shape = RoundedCornerShape(12.dp), + color = PurrfectPalette.glowPrimary.copy(alpha = 0.22f), + tonalElevation = 0.dp, + shadowElevation = 10.dp, + border = BorderStroke( + 1.dp, + Brush.linearGradient( + listOf( + PurrfectPalette.glowPrimary.copy(alpha = 0.55f), + PurrfectPalette.glowSecondary.copy(alpha = 0.4f) + ) + ) + ) + ) { + IconButton(onClick = { + routes.activityLauncher.saveFile("friend_tracker_config.json", "application/json") { uri -> + runCatching { + context.androidContext.contentResolver.openOutputStream(android.net.Uri.parse(uri))?.use { + trackerData?.let { data -> + context.gson.toJson(data).byteInputStream().copyTo(it) + context.shortToast(translation["exported_toast"]) + } } + }.onFailure { + context.longToast(translation.format("export_failed_toast", "message" to (it.message ?: "Unknown"))) } - }.onFailure { - context.longToast(translation.format("export_failed_toast", "message" to (it.message ?: "Unknown"))) } + }) { + Icon( + imageVector = Icons.Default.ArrowDownward, + contentDescription = translation["save_button"], + tint = Color.White + ) } - }) { - Text(translation["save_button"]) } } ) diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/tracker/FriendTrackerConfigImportScreen.kt b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/tracker/FriendTrackerConfigImportScreen.kt similarity index 97% rename from app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/tracker/FriendTrackerConfigImportScreen.kt rename to app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/tracker/FriendTrackerConfigImportScreen.kt index 0a82649a..fd52855e 100644 --- a/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/tracker/FriendTrackerConfigImportScreen.kt +++ b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/tracker/FriendTrackerConfigImportScreen.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.ui.manager.pages.tracker +package me.eternal.purrfectsnap.ui.manager.pages.tracker import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.core.animateFloatAsState @@ -43,8 +43,8 @@ import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import kotlinx.coroutines.launch -import me.rhunk.snapenhance.common.data.ExportedTrackerData -import me.rhunk.snapenhance.ui.manager.Routes +import me.eternal.purrfectsnap.common.data.ExportedTrackerData +import me.eternal.purrfectsnap.ui.manager.Routes import org.json.JSONArray class FriendTrackerConfigImportScreen : Routes.Route() { diff --git a/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/tracker/FriendTrackerManagerRoot.kt b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/tracker/FriendTrackerManagerRoot.kt new file mode 100644 index 00000000..a24145b7 --- /dev/null +++ b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/tracker/FriendTrackerManagerRoot.kt @@ -0,0 +1,907 @@ +package me.eternal.purrfectsnap.ui.manager.pages.tracker + +import androidx.compose.foundation.BorderStroke +import androidx.compose.foundation.ExperimentalFoundationApi +import androidx.compose.foundation.background +import androidx.compose.foundation.border +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items +import androidx.compose.foundation.pager.HorizontalPager +import androidx.compose.foundation.pager.rememberPagerState +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.icons.Icons +import androidx.compose.material3.SingleChoiceSegmentedButtonRow +import androidx.compose.material.icons.filled.Add +import androidx.compose.material.icons.filled.AutoGraph +import androidx.compose.material.icons.filled.DeleteOutline +import androidx.compose.material.icons.filled.FolderOpen +import androidx.compose.material.icons.filled.Rule +import androidx.compose.material.icons.filled.SaveAlt +import androidx.compose.material.icons.filled.UploadFile +import androidx.compose.material.icons.filled.FileOpen +import androidx.compose.material.icons.filled.Store +import androidx.compose.ui.window.Dialog +import androidx.compose.material3.* +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableIntStateOf +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.Brush +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.text.style.TextOverflow +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import androidx.navigation.NavBackStackEntry +import kotlinx.coroutines.launch +import me.eternal.purrfectsnap.common.ui.rememberAsyncMutableState +import me.eternal.purrfectsnap.common.ui.rememberAsyncMutableStateList +import me.eternal.purrfectsnap.common.ui.rememberAsyncUpdateDispatcher +import me.eternal.purrfectsnap.common.util.snap.BitmojiSelfie +import me.eternal.purrfectsnap.storage.* +import me.eternal.purrfectsnap.ui.manager.Routes +import me.eternal.purrfectsnap.ui.manager.components.AestheticDialog +import me.eternal.purrfectsnap.ui.manager.theme.PurrfectPalette +import me.eternal.purrfectsnap.ui.util.ActivityLauncherHelper +import me.eternal.purrfectsnap.ui.util.coil.BitmojiImage +import me.eternal.purrfectsnap.ui.util.openFile +import me.eternal.purrfectsnap.ui.util.purrfectSwitchColors +import me.eternal.purrfectsnap.ui.util.pagerTabIndicatorOffset + + +@OptIn(ExperimentalFoundationApi::class) +class FriendTrackerManagerRoot : Routes.Route() { + enum class FilterType { + CONVERSATION, USERNAME, EVENT + } + + override val translation by lazy { context.translation.getCategory("manager.friend_tracker") } + private val titles by lazy { + listOf( + translation["rules_tab"], + translation["logs_tab"] + ) + } + private var currentPage by mutableIntStateOf(0) + private lateinit var logDeleteAction : () -> Unit + private lateinit var exportAction : () -> Unit + + @Composable + private fun TrackerIconButton( + icon: ImageVector, + contentDescription: String?, + modifier: Modifier = Modifier, + onClick: () -> Unit + ) { + val shape = RoundedCornerShape(14.dp) + val backgroundBrush = remember { + Brush.linearGradient( + listOf( + PurrfectPalette.glowPrimary.copy(alpha = 0.28f), + PurrfectPalette.glowSecondary.copy(alpha = 0.24f) + ) + ) + } + Surface( + onClick = onClick, + shape = shape, + color = Color.White.copy(alpha = 0.06f), + tonalElevation = 0.dp, + shadowElevation = 12.dp, + border = BorderStroke(1.dp, Color.White.copy(alpha = 0.12f)), + modifier = modifier.size(46.dp) + ) { + Box( + modifier = Modifier + .background(backgroundBrush, shape) + .fillMaxSize(), + contentAlignment = Alignment.Center + ) { + Icon(icon, contentDescription = contentDescription, tint = Color.White) + } + } + } + + @Composable + private fun TrackerActionButton( + label: String, + icon: ImageVector, + onClick: () -> Unit, + modifier: Modifier = Modifier + ) { + val shape = RoundedCornerShape(22.dp) + val backgroundBrush = remember { + Brush.linearGradient( + listOf( + PurrfectPalette.glowPrimary.copy(alpha = 0.34f), + PurrfectPalette.glowSecondary.copy(alpha = 0.3f) + ) + ) + } + Surface( + onClick = onClick, + shape = shape, + color = Color.Transparent, + tonalElevation = 0.dp, + shadowElevation = 16.dp, + border = BorderStroke(1.dp, Color.White.copy(alpha = 0.14f)), + modifier = modifier + ) { + Box( + modifier = Modifier + .background(backgroundBrush, shape) + .padding(horizontal = 18.dp, vertical = 12.dp), + contentAlignment = Alignment.Center + ) { + Row( + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(10.dp) + ) { + Icon(icon, contentDescription = label, tint = Color.White) + Text(label, color = Color.White, fontWeight = FontWeight.SemiBold) + } + } + } + } + + @Composable + private fun TrackerPillButton( + label: String, + icon: ImageVector, + onClick: () -> Unit, + modifier: Modifier = Modifier + ) { + val shape = RoundedCornerShape(18.dp) + val backgroundBrush = remember { + Brush.linearGradient( + listOf( + PurrfectPalette.glowPrimary.copy(alpha = 0.32f), + PurrfectPalette.glowSecondary.copy(alpha = 0.26f) + ) + ) + } + Surface( + onClick = onClick, + shape = shape, + color = Color.Transparent, + tonalElevation = 0.dp, + shadowElevation = 12.dp, + border = BorderStroke(1.dp, Color.White.copy(alpha = 0.12f)), + modifier = modifier + ) { + Row( + modifier = Modifier + .background(backgroundBrush, shape) + .padding(horizontal = 14.dp, vertical = 10.dp), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(8.dp) + ) { + Icon(icon, contentDescription = label, tint = Color.White) + Text(label, color = Color.White, fontWeight = FontWeight.SemiBold) + } + } + } + + override val topBarActions: @Composable RowScope.() -> Unit = { + var showExportDialog by remember { mutableStateOf(false) } + var showSingleExportDialog by remember { mutableStateOf(false) } + var showImportDialog by remember { mutableStateOf(false) } + var showInvalidImportTypeDialog by remember { mutableStateOf(false) } + + if (showExportDialog) { + AestheticDialog( + onDismissRequest = { showExportDialog = false }, + title = translation["export_dialog_title"], + text = translation["export_logs_dialog_confirm_text"], + icon = Icons.Default.SaveAlt, + confirmButtonText = translation["export_button"], + onConfirm = { + showExportDialog = false + routes.friendTrackerConfigExport.navigate() + }, + dismissButtonText = translation["button.cancel"], + onDismiss = { showExportDialog = false }, + opaque = true, + showCloseButton = false + ) + } + + if (showSingleExportDialog) { + val rules = rememberAsyncMutableStateList(defaultValue = emptyList()) { + context.database.getTrackerRulesDesc() + } + SelectRuleDialog( + onDismissRequest = { showSingleExportDialog = false }, + rules = rules, + onRuleSelected = { rule -> + showSingleExportDialog = false + routes.friendTrackerConfigExport.navigate { + this["rule_id"] = rule.id.toString() + } + }, + translation = translation + ) + } + + fun handleImport(type: me.eternal.purrfectsnap.common.data.ExportType) { + routes.activityLauncher.openFile("application/json") { uri -> + runCatching { + val content = context.androidContext.contentResolver.openInputStream(android.net.Uri.parse(uri))?.use { + it.readBytes().toString(Charsets.UTF_8) + } ?: return@runCatching + val exportedData = context.gson.fromJson(content, me.eternal.purrfectsnap.common.data.ExportedTrackerData::class.java) + if (exportedData.type != type) { + showInvalidImportTypeDialog = true + return@runCatching + } + routes.friendTrackerConfigJsonForImport = content + routes.friendTrackerConfigImport.navigate() + }.onFailure { + context.longToast("Failed to read file: ${it.message}") + } + } + } + + if (showInvalidImportTypeDialog) { + AlertDialog( + onDismissRequest = { showInvalidImportTypeDialog = false }, + title = { Text(translation["invalid_import_type_dialog_title"]) }, + text = { Text(translation["invalid_import_type_dialog_text"]) }, + confirmButton = { + Button(onClick = { showInvalidImportTypeDialog = false }) { + Text(translation["button.ok"]) + } + } + ) + } + + if (showImportDialog) { + AestheticDialog( + onDismissRequest = { showImportDialog = false }, + title = translation["import_dialog_title"], + text = translation["import_dialog_subtitle"] ?: translation["import_dialog_title"], + icon = Icons.Default.FolderOpen, + confirmButtonText = translation["bulk_import_button"], + onConfirm = { + showImportDialog = false + handleImport(me.eternal.purrfectsnap.common.data.ExportType.BULK) + }, + dismissButtonText = translation["individual_import_button"], + onDismiss = { + showImportDialog = false + handleImport(me.eternal.purrfectsnap.common.data.ExportType.SINGLE) + }, + opaque = true, + showCloseButton = false + ) + } + + if (currentPage == 0) { + TrackerIconButton( + icon = Icons.Default.FolderOpen, + contentDescription = translation["import_button_description"], + onClick = { showImportDialog = true } + ) + Spacer(Modifier.width(8.dp)) + TrackerIconButton( + icon = Icons.Default.SaveAlt, + contentDescription = translation["export_button_description"], + onClick = { showExportDialog = true } + ) + } + } + + private lateinit var activityLauncherHelper: ActivityLauncherHelper + + override val init: () -> Unit = { + activityLauncherHelper = ActivityLauncherHelper(context.activity!!) + } + + override val floatingActionButton: @Composable () -> Unit = { + when (currentPage) { + 1 -> { + Column( + verticalArrangement = Arrangement.spacedBy(10.dp), + horizontalAlignment = Alignment.End + ) { + TrackerActionButton( + label = translation["export_button"], + icon = Icons.Default.SaveAlt, + onClick = { context.coroutineScope.launch { exportAction() } } + ) + TrackerActionButton( + label = translation["delete_button"], + icon = Icons.Default.DeleteOutline, + onClick = { context.coroutineScope.launch { logDeleteAction() } } + ) + } + } + 0 -> { + Column(verticalArrangement = Arrangement.spacedBy(10.dp), horizontalAlignment = Alignment.End) { + TrackerActionButton( + label = translation["catalog_button"], + icon = Icons.Default.Store, + onClick = { routes.friendTrackerCatalog.navigate() } + ) + TrackerActionButton( + label = translation["add_rule_button"], + icon = Icons.Default.Add, + onClick = { routes.editRule.navigate() } + ) + } + } + } + } + + @Composable + private fun ConfigRulesTab() { + val updateRules = rememberAsyncUpdateDispatcher() + val rules = rememberAsyncMutableStateList(defaultValue = listOf(), updateDispatcher = updateRules) { + context.database.getTrackerRulesDesc() + } + @Composable + fun EmptyState(text: String) { + Column( + modifier = Modifier + .fillMaxWidth() + .padding(top = 50.dp), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.spacedBy(10.dp) + ) { + Surface( + shape = CircleShape, + color = Color.White.copy(alpha = 0.08f), + tonalElevation = 0.dp, + shadowElevation = 0.dp, + border = BorderStroke(1.dp, Color.White.copy(alpha = 0.12f)) + ) { + Box( + modifier = Modifier + .size(62.dp) + .background( + Brush.linearGradient( + listOf( + PurrfectPalette.glowPrimary.copy(alpha = 0.32f), + PurrfectPalette.glowSecondary.copy(alpha = 0.28f) + ) + ), + CircleShape + ), + contentAlignment = Alignment.Center + ) { + Icon(Icons.Filled.AutoGraph, contentDescription = text, tint = Color.White) + } + } + Text(text, color = Color.White, fontWeight = FontWeight.ExtraBold) + } + } + + Column( + modifier = Modifier.fillMaxSize() + ) { + LazyColumn( + modifier = Modifier.weight(1f), + contentPadding = PaddingValues(bottom = routes.bottomPadding) + ) { + item { + if (rules.isEmpty()) { + EmptyState(translation["no_rules_found"]) + } + } + items(rules, key = { it.id }) { rule -> + val ruleName by rememberAsyncMutableState(defaultValue = rule.name) { + context.database.getTrackerRule(rule.id)?.name ?: translation["empty_rule_name"] + } + val eventCount by rememberAsyncMutableState(defaultValue = 0) { + context.database.getTrackerEvents(rule.id).size + } + val scopeCount by rememberAsyncMutableState(defaultValue = 0) { + context.database.getRuleTrackerScopes(rule.id).size + } + var enabled by rememberAsyncMutableState(defaultValue = rule.enabled) { + context.database.getTrackerRule(rule.id)?.enabled ?: false + } + + val ruleShape = RoundedCornerShape(20.dp) + Surface( + modifier = Modifier + .fillMaxWidth() + .clickable { + routes.editRule.navigate { + this["rule_id"] = rule.id.toString() + } + } + .padding(8.dp), + shape = ruleShape, + color = Color.Transparent, + tonalElevation = 0.dp, + shadowElevation = 12.dp, + border = BorderStroke( + 1.dp, + Brush.linearGradient( + listOf( + PurrfectPalette.glowPrimary.copy(alpha = 0.5f), + PurrfectPalette.glowSecondary.copy(alpha = 0.4f) + ) + ) + ) + ) { + Row( + modifier = Modifier + .fillMaxWidth() + .background(PurrfectPalette.cardOverlay, ruleShape) + .padding(horizontal = 14.dp, vertical = 12.dp), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(12.dp) + ) { + Surface( + shape = CircleShape, + color = Color.White.copy(alpha = 0.08f), + tonalElevation = 0.dp, + shadowElevation = 0.dp, + border = BorderStroke(1.dp, Color.White.copy(alpha = 0.18f)) + ) { + Box( + modifier = Modifier + .size(54.dp) + .background( + Brush.linearGradient( + listOf( + PurrfectPalette.glowPrimary.copy(alpha = 0.35f), + PurrfectPalette.glowSecondary.copy(alpha = 0.3f) + ) + ), + CircleShape + ), + contentAlignment = Alignment.Center + ) { + Icon(Icons.Default.Rule, contentDescription = null, tint = Color.White) + } + } + Column( + modifier = Modifier.weight(1f), + verticalArrangement = Arrangement.spacedBy(4.dp) + ) { + Text(ruleName, fontSize = 18.sp, fontWeight = FontWeight.ExtraBold, color = Color.White) + Text( + buildString { + append(eventCount) + append(" ") + append(translation["events_suffix"]) + if (scopeCount > 0) { + append(" • ") + append(scopeCount) + append(" ") + append(translation["scopes_suffix"]) + } + }, + fontSize = 12.sp, + fontWeight = FontWeight.SemiBold, + color = PurrfectPalette.textSecondary + ) + if (scopeCount > 0) { + val scopesBitmoji = rememberAsyncMutableStateList(defaultValue = emptyList()) { + context.database.getRuleTrackerScopes(rule.id, limit = 8).mapNotNull { + context.database.getFriendInfo(it.key)?.let { friend -> + friend.selfieId to friend.bitmojiId + } + } + } + Row( + horizontalArrangement = Arrangement.spacedBy((-10).dp), + verticalAlignment = Alignment.CenterVertically + ) { + scopesBitmoji.take(4).forEach { friend -> + BitmojiImage( + size = 34, + modifier = Modifier + .border(BorderStroke(1.dp, Color.White), CircleShape) + .background(Color.White, CircleShape) + .clip(CircleShape), + context = context, + url = BitmojiSelfie.getBitmojiSelfie(friend.first, friend.second, BitmojiSelfie.BitmojiSelfieType.NEW_THREE_D), + ) + } + if (scopeCount > scopesBitmoji.size) { + Surface( + shape = CircleShape, + color = Color.White.copy(alpha = 0.08f), + tonalElevation = 0.dp, + shadowElevation = 0.dp, + border = BorderStroke(1.dp, Color.White.copy(alpha = 0.12f)) + ) { + Text( + text = "+${scopeCount - scopesBitmoji.size}", + color = Color.White, + fontWeight = FontWeight.Bold, + modifier = Modifier + .padding(horizontal = 10.dp, vertical = 6.dp) + ) + } + } + } + } + } + Column( + horizontalAlignment = Alignment.End, + verticalArrangement = Arrangement.spacedBy(6.dp) + ) { + Surface( + shape = RoundedCornerShape(12.dp), + color = Color.White.copy(alpha = 0.06f), + border = BorderStroke(1.dp, Color.White.copy(alpha = 0.1f)) + ) { + Text( + text = translation[if (enabled) "enabled_label" else "disabled_label"], + color = Color.White, + fontSize = 11.sp, + fontWeight = FontWeight.SemiBold, + modifier = Modifier.padding(horizontal = 10.dp, vertical = 6.dp) + ) + } + Switch( + checked = enabled, + onCheckedChange = { + enabled = it + context.database.setTrackerRuleState(rule.id, it) + }, + colors = purrfectSwitchColors() + ) + } + } + } + } + } + } + } + + + @OptIn(ExperimentalFoundationApi::class) + override val content: @Composable (NavBackStackEntry) -> Unit = { + val coroutineScope = rememberCoroutineScope() + val pagerState = rememberPagerState(initialPage = 0) { titles.size } + currentPage = pagerState.currentPage + var showExportDialog by remember { mutableStateOf(false) } + var showSingleExportDialog by remember { mutableStateOf(false) } + var showImportDialog by remember { mutableStateOf(false) } + var showInvalidImportTypeDialog by remember { mutableStateOf(false) } + + fun handleImport(type: me.eternal.purrfectsnap.common.data.ExportType) { + routes.activityLauncher.openFile("application/json") { uri -> + runCatching { + val content = context.androidContext.contentResolver.openInputStream(android.net.Uri.parse(uri))?.use { + it.readBytes().toString(Charsets.UTF_8) + } ?: return@runCatching + val exportedData = context.gson.fromJson(content, me.eternal.purrfectsnap.common.data.ExportedTrackerData::class.java) + if (exportedData.type != type) { + showInvalidImportTypeDialog = true + return@runCatching + } + routes.friendTrackerConfigJsonForImport = content + routes.friendTrackerConfigImport.navigate() + }.onFailure { + context.longToast("Failed to read file: ${it.message}") + } + } + } + + Box( + modifier = Modifier + .fillMaxSize() + .background(PurrfectPalette.backgroundGradient) + ) { + Column(modifier = Modifier.fillMaxSize()) { + Surface( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 14.dp, vertical = 12.dp) + .padding(top = WindowInsets.statusBars.asPaddingValues().calculateTopPadding()), + shape = RoundedCornerShape(26.dp), + color = PurrfectPalette.cardOverlayColor, + tonalElevation = 0.dp, + shadowElevation = 10.dp, + border = BorderStroke( + 1.dp, + Brush.linearGradient( + listOf( + PurrfectPalette.glowPrimary.copy(alpha = 0.55f), + PurrfectPalette.glowSecondary.copy(alpha = 0.35f) + ) + ) + ) + ) { + Row( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 16.dp, vertical = 14.dp), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.SpaceBetween + ) { + Column(verticalArrangement = Arrangement.spacedBy(6.dp)) { + Text( + text = context.translation["manager.routes.friend_tracker"], + color = Color.White, + fontWeight = FontWeight.ExtraBold, + fontSize = 20.sp + ) + Text( + text = titles.getOrNull(pagerState.currentPage) ?: "", + color = PurrfectPalette.textSecondary, + fontSize = 14.sp + ) + } + if (pagerState.currentPage == 0) { + Column( + verticalArrangement = Arrangement.spacedBy(8.dp), + horizontalAlignment = Alignment.End + ) { + TrackerPillButton( + label = translation["import_button"], + icon = Icons.Default.FolderOpen, + onClick = { showImportDialog = true } + ) + TrackerPillButton( + label = translation["export_button"], + icon = Icons.Default.SaveAlt, + onClick = { showExportDialog = true } + ) + } + } + } + } + + Spacer(modifier = Modifier.height(8.dp)) + + Surface( + modifier = Modifier + .weight(1f) + .fillMaxWidth() + .padding(horizontal = 12.dp), + shape = RoundedCornerShape(22.dp), + color = Color.White.copy(alpha = 0.04f), + tonalElevation = 0.dp, + shadowElevation = 0.dp, + border = BorderStroke(1.dp, Color.White.copy(alpha = 0.08f)) + ) { + Column(modifier = Modifier.fillMaxSize()) { + Row( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 12.dp, vertical = 12.dp), + horizontalArrangement = Arrangement.spacedBy(10.dp) + ) { + titles.forEachIndexed { i, text -> + val selected = pagerState.currentPage == i + Surface( + modifier = Modifier.weight(1f).clip(RoundedCornerShape(18.dp)).clickable { + coroutineScope.launch { pagerState.animateScrollToPage(i) } + }, + shape = RoundedCornerShape(18.dp), + color = if (selected) Color.White.copy(alpha = 0.14f) else Color.White.copy(alpha = 0.06f), + border = if (selected) BorderStroke(1.dp, Brush.linearGradient(listOf(PurrfectPalette.glowPrimary, PurrfectPalette.glowSecondary))) else BorderStroke(1.dp, Color.White.copy(alpha = 0.16f)), + tonalElevation = 0.dp, + shadowElevation = 0.dp + ) { + Row( + modifier = Modifier.padding(horizontal = 14.dp, vertical = 10.dp), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.Center + ) { + Text(text = text, color = Color.White, fontWeight = FontWeight.SemiBold) + } + } + } + } + + HorizontalPager( + modifier = Modifier + .weight(1f) + .padding(horizontal = 4.dp, vertical = 4.dp), + state = pagerState + ) { page -> + when (page) { + 1 -> LogsTab( + context = context, + activityLauncherHelper = activityLauncherHelper, + deleteAction = { logDeleteAction = it }, + exportAction = { exportAction = it }, + bottomPadding = routes.bottomPadding + ) + 0 -> ConfigRulesTab() + } + } + } + } + } + } + + if (showExportDialog) { + ChoiceDialog( + onDismissRequest = { showExportDialog = false }, + title = translation["export_dialog_title"], + choices = listOf( + translation["bulk_export_button"] to { Icon(Icons.Default.UploadFile, translation["bulk_export_button"]) }, + translation["individual_export_button"] to { Icon(Icons.Default.FileOpen, translation["individual_export_button"]) } + ), + onChoiceSelected = { index -> + showExportDialog = false + when (index) { + 0 -> routes.friendTrackerConfigExport.navigate() + 1 -> showSingleExportDialog = true + } + } + ) + } + + if (showSingleExportDialog) { + val rules = rememberAsyncMutableStateList(defaultValue = emptyList()) { + context.database.getTrackerRulesDesc() + } + SelectRuleDialog( + onDismissRequest = { showSingleExportDialog = false }, + rules = rules, + onRuleSelected = { rule -> + showSingleExportDialog = false + routes.friendTrackerConfigExport.navigate { + this["rule_id"] = rule.id.toString() + } + }, + translation = translation + ) + } + + if (showInvalidImportTypeDialog) { + AlertDialog( + onDismissRequest = { showInvalidImportTypeDialog = false }, + title = { Text(translation["invalid_import_type_dialog_title"]) }, + text = { Text(translation["invalid_import_type_dialog_text"]) }, + confirmButton = { + Button(onClick = { showInvalidImportTypeDialog = false }) { + Text(translation["button.ok"]) + } + } + ) + } + + if (showImportDialog) { + ChoiceDialog( + onDismissRequest = { showImportDialog = false }, + title = translation["import_dialog_title"], + choices = listOf( + translation["bulk_import_button"] to { Icon(Icons.Default.UploadFile, translation["bulk_import_button"]) }, + translation["individual_import_button"] to { Icon(Icons.Default.FileOpen, translation["individual_import_button"]) } + ), + onChoiceSelected = { index -> + showImportDialog = false + when (index) { + 0 -> handleImport(me.eternal.purrfectsnap.common.data.ExportType.BULK) + 1 -> handleImport(me.eternal.purrfectsnap.common.data.ExportType.SINGLE) + } + } + ) + } + } +} + +@Composable +private fun SelectRuleDialog( + onDismissRequest: () -> Unit, + rules: List, + onRuleSelected: (me.eternal.purrfectsnap.common.data.TrackerRule) -> Unit, + translation: me.eternal.purrfectsnap.common.bridge.wrapper.LocaleWrapper +) { + Dialog(onDismissRequest = onDismissRequest) { + Card( + shape = RoundedCornerShape(16.dp), + ) { + Column( + modifier = Modifier.padding(16.dp), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.spacedBy(10.dp) + ) { + Text(translation["manager.friend_tracker.select_rule_to_export_title"], style = MaterialTheme.typography.headlineSmall) + LazyColumn( + verticalArrangement = Arrangement.spacedBy(8.dp) + ) { + items(rules) { rule -> + ElevatedCard( + onClick = { onRuleSelected(rule) }, + modifier = Modifier.fillMaxWidth() + ) { + Text( + text = rule.name, + modifier = Modifier.padding(16.dp), + fontWeight = FontWeight.SemiBold + ) + } + } + } + TextButton(onClick = onDismissRequest) { + Text(translation["button.cancel"]) + } + } + } + } +} + +@Composable +private fun ChoiceDialog( + onDismissRequest: () -> Unit, + title: String, + choices: List Unit>>, + onChoiceSelected: (Int) -> Unit +) { + Dialog(onDismissRequest = onDismissRequest) { + val shape = RoundedCornerShape(20.dp) + Surface( + shape = shape, + color = Color.Transparent, + shadowElevation = 20.dp, + border = BorderStroke( + 1.dp, + Brush.linearGradient( + listOf( + PurrfectPalette.glowPrimary.copy(alpha = 0.6f), + PurrfectPalette.glowSecondary.copy(alpha = 0.5f) + ) + ) + ) + ) { + Column( + modifier = Modifier + .background(PurrfectPalette.cardOverlay, shape) + .padding(horizontal = 18.dp, vertical = 16.dp), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.spacedBy(12.dp) + ) { + Text( + text = title, + style = MaterialTheme.typography.titleLarge.copy(fontWeight = FontWeight.ExtraBold), + color = Color.White, + textAlign = TextAlign.Center + ) + choices.forEachIndexed { index, (text, icon) -> + SelectButton( + onClick = { onChoiceSelected(index) }, + text = text, + leadingIcon = icon + ) + } + } + } + } +} + +@Composable +private fun SelectButton( + onClick: () -> Unit, + text: String, + leadingIcon: @Composable (() -> Unit)? = null, +) { + OutlinedButton( + onClick = onClick, + modifier = Modifier.fillMaxWidth(), + contentPadding = PaddingValues(16.dp) + ) { + Row( + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(10.dp) + ) { + if (leadingIcon != null) { + leadingIcon() + } + Text(text = text, modifier = Modifier.weight(1f)) + } + } +} diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/tracker/FriendTrackerRepos.md b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/tracker/FriendTrackerRepos.md similarity index 85% rename from app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/tracker/FriendTrackerRepos.md rename to app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/tracker/FriendTrackerRepos.md index 1c0e9971..58b526e2 100644 --- a/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/tracker/FriendTrackerRepos.md +++ b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/tracker/FriendTrackerRepos.md @@ -1,6 +1,6 @@ # Friend Tracker Rule Repositories -Friend Tracker Rule Repositories are a way to share your custom friend tracker rules with others. You can create a repository with your rules and share the URL with others to import them into SnapEnhance. +Friend Tracker Rule Repositories are a way to share your custom friend tracker rules with others. You can create a repository with your rules and share the URL with others to import them into PurrfectSnap. ## Repository Structure @@ -34,4 +34,4 @@ Here is an example of an `index.json` file: ### Rule File -The rule file itself is a standard SnapEnhance friend tracker rule JSON file. You can export an existing rule from SnapEnhance to get a template. The file must be a valid JSON file. +The rule file itself is a standard PurrfectSnap friend tracker rule JSON file. You can export an existing rule from PurrfectSnap to get a template. The file must be a valid JSON file. diff --git a/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/tracker/LogsTab.kt b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/tracker/LogsTab.kt new file mode 100644 index 00000000..95c5e075 --- /dev/null +++ b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/tracker/LogsTab.kt @@ -0,0 +1,808 @@ +package me.eternal.purrfectsnap.ui.manager.pages.tracker + +import android.net.Uri +import androidx.compose.foundation.BorderStroke +import androidx.compose.foundation.background +import androidx.compose.foundation.border +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Clear +import androidx.compose.material.icons.filled.DeleteOutline +import androidx.compose.material.icons.filled.FolderOpen +import androidx.compose.material.icons.filled.History +import androidx.compose.material.icons.filled.FilterList +import androidx.compose.material.icons.filled.SaveAlt +import androidx.compose.ui.unit.DpOffset +import androidx.compose.material3.* +import androidx.compose.runtime.* +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Brush +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.text.TextStyle +import androidx.compose.material3.LocalTextStyle +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.text.style.TextOverflow +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import androidx.compose.ui.window.Dialog +import java.util.Date +import androidx.compose.ui.unit.Dp +import androidx.compose.ui.window.PopupProperties +import com.google.gson.stream.JsonWriter +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.Job +import kotlinx.coroutines.delay +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext +import me.eternal.purrfectsnap.RemoteSideContext +import me.eternal.purrfectsnap.ui.manager.theme.PurrfectPalette +import me.eternal.purrfectsnap.common.bridge.wrapper.TrackerLog +import me.eternal.purrfectsnap.common.data.MessagingFriendInfo +import me.eternal.purrfectsnap.common.data.TrackerEventType +import me.eternal.purrfectsnap.common.util.snap.BitmojiSelfie +import me.eternal.purrfectsnap.storage.getFriendInfo +import me.eternal.purrfectsnap.ui.manager.components.AestheticDialog +import me.eternal.purrfectsnap.ui.util.ActivityLauncherHelper +import me.eternal.purrfectsnap.ui.util.coil.BitmojiImage +import me.eternal.purrfectsnap.ui.util.saveFile +import me.eternal.purrfectsnap.ui.util.purrfectSwitchColors +import java.text.DateFormat + + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun LogsTab( + context: RemoteSideContext, + activityLauncherHelper: ActivityLauncherHelper, + deleteAction: (() -> Unit) -> Unit, + exportAction: (() -> Unit) -> Unit, + bottomPadding: Dp, +) { + val translation = remember { context.translation.getCategory("manager.friend_tracker") } + val trackerTranslation = remember { context.translation.getCategory("tracker") } + val coroutineScope = rememberCoroutineScope() + + val logs = remember { mutableStateListOf() } + var isLoading by remember { mutableStateOf(false) } + var pageIndex by remember { mutableIntStateOf(0) } + var filterType by remember { mutableStateOf(FriendTrackerManagerRoot.FilterType.USERNAME) } + var reverseSortOrder by remember { mutableStateOf(true) } + val sinceDatePickerState = rememberDatePickerState( + initialDisplayMode = DisplayMode.Picker + ) + + var filter by remember { mutableStateOf("") } + var searchTimeoutJob by remember { mutableStateOf(null) } + + fun getPaginatedLogs(pageIndex: Int) = context.messageLogger.getLogs( + pageIndex = pageIndex, + pageSize = 30, + timestamp = sinceDatePickerState.selectedDateMillis, + reverseOrder = reverseSortOrder, + filter = { + when (filterType) { + FriendTrackerManagerRoot.FilterType.USERNAME -> it.username.contains(filter, ignoreCase = true) + FriendTrackerManagerRoot.FilterType.CONVERSATION -> it.conversationTitle?.contains(filter, ignoreCase = true) == true || (it.username == filter && !it.isGroup) + FriendTrackerManagerRoot.FilterType.EVENT -> it.eventType.contains(filter, ignoreCase = true) + } + }) + + fun formatICanSeeYouDuration(value: Long?): String { + if (value == null || value < 0) return trackerTranslation.get("logs.log_entry.i_can_see_you_not_available") + val totalSeconds = (value / 1000).coerceAtLeast(0) + val hours = totalSeconds / 3600 + val minutes = (totalSeconds % 3600) / 60 + val seconds = totalSeconds % 60 + val hourUnit = trackerTranslation.get("logs.log_entry.i_can_see_you_unit_hour") + val minuteUnit = trackerTranslation.get("logs.log_entry.i_can_see_you_unit_minute") + val secondUnit = trackerTranslation.get("logs.log_entry.i_can_see_you_unit_second") + val parts = mutableListOf() + if (hours > 0) parts.add("${hours}${hourUnit}") + if (minutes > 0 || hours > 0) parts.add("${minutes}${minuteUnit}") + parts.add("${seconds}${secondUnit}") + return parts.joinToString(" ") + } + + fun formatICanSeeYouTime(value: Long?): String { + if (value == null || value < 0) return trackerTranslation.get("logs.log_entry.i_can_see_you_not_available") + return DateFormat.getTimeInstance(DateFormat.MEDIUM).format(Date(value)) + } + + fun buildICanSeeYouDetails(data: String): String { + val values = data.split("|").map { it.toLongOrNull() ?: -1L }.let { + if (it.size >= 3) it else it + List(3 - it.size) { -1L } + } + val entered = values[0].takeIf { it >= 0 } + val exited = values[1].takeIf { it >= 0 } + val duration = values[2].takeIf { it >= 0 } + val enteredLabel = trackerTranslation.get("logs.log_entry.i_can_see_you_entered") + val leftLabel = trackerTranslation.get("logs.log_entry.i_can_see_you_left") + val durationLabel = trackerTranslation.get("logs.log_entry.i_can_see_you_duration") + return listOf( + "$enteredLabel: ${formatICanSeeYouTime(entered)}", + "$durationLabel: ${formatICanSeeYouDuration(duration)}", + "$leftLabel: ${formatICanSeeYouTime(exited)}" + ).joinToString(" • ") + } + + suspend fun loadNewLogs() { + withContext(Dispatchers.IO) { + getPaginatedLogs(pageIndex).let { + withContext(Dispatchers.Main) { + logs.addAll(it) + pageIndex += 1 + } + } + } + } + + suspend fun resetAndLoadLogs() { + isLoading = true + logs.clear() + pageIndex = 0 + loadNewLogs() + isLoading = false + } + + var showDeleteDialog by remember { mutableStateOf(false) } + var showExportSelectionDialog by remember { mutableStateOf(false) } + + LaunchedEffect(Unit) { + deleteAction { showDeleteDialog = true } + exportAction { showExportSelectionDialog = true } + } + + if (showDeleteDialog) { + val deleteCoroutineScope = rememberCoroutineScope { Dispatchers.IO } + var deleteLogsTask by remember { mutableStateOf(null) } + var deletedLogsCount by remember { mutableIntStateOf(0) } + + fun deleteLogs() { + deleteLogsTask = deleteCoroutineScope.launch { + var index = 0 + while (true) { + val newLogs = getPaginatedLogs(index++) + if (newLogs.isEmpty()) { + break + } + newLogs.forEach { + context.messageLogger.deleteTrackerLog(it.id) + deletedLogsCount++ + } + } + + withContext(Dispatchers.Main) { + delay(500) + resetAndLoadLogs() + context.shortToast(translation.format("deleted_logs_toast", "count" to deletedLogsCount.toString())) + showDeleteDialog = false + } + } + } + + DisposableEffect(Unit) { + onDispose { + deleteLogsTask?.cancel() + } + } + + AestheticDialog( + onDismissRequest = { showDeleteDialog = false }, + title = translation["delete_logs_dialog_title"], + text = if (deleteLogsTask != null) translation.format("deleting_logs_dialog_text", "count" to deletedLogsCount.toString()) else translation["delete_logs_dialog_confirm_text"], + icon = Icons.Default.DeleteOutline, + confirmButtonText = translation["delete_button"], + onConfirm = { if (deleteLogsTask == null) deleteLogs() }, + dismissButtonText = context.translation["button.cancel"], + onDismiss = { showDeleteDialog = false }, + loading = deleteLogsTask != null, + opaque = true, + showCloseButton = false + ) + } + + if (showExportSelectionDialog) { + val exportCoroutineScope = rememberCoroutineScope { Dispatchers.IO } + var exportTask by remember { mutableStateOf(null) } + var exportType by remember { mutableStateOf("json") } + + fun exportLogs() { + activityLauncherHelper.saveFile("tracker_logs_${System.currentTimeMillis()}.$exportType") { uri -> + exportTask = exportCoroutineScope.launch { + context.androidContext.contentResolver.openOutputStream(Uri.parse(uri))?.use { + val writer = it.writer() + val jsonWriter by lazy { + JsonWriter(writer).apply { + setIndent(" ") + beginArray() + } + } + + var index = 0 + while (true) { + val newLogs = getPaginatedLogs(index++) + if (newLogs.isEmpty()) { + break + } + newLogs.forEach { log -> + when (exportType) { + "json" -> { + jsonWriter.jsonValue(log.toJson().toString()) + } + "csv" -> { + writer.write(log.toCsv()) + writer.write("\n") + } + } + writer.flush() + } + } + when (exportType) { + "json" -> { + jsonWriter.endArray() + jsonWriter.close() + } + "csv" -> writer.close() + } + } + }.apply { + invokeOnCompletion { + exportTask = null + showExportSelectionDialog = false + if (it == null) { + context.shortToast(translation["exported_logs_toast"]) + } else { + context.log.error("Failed to export logs", it) + context.shortToast(translation["export_logs_failed_toast"]) + } + } + } + } + } + + AestheticDialog( + onDismissRequest = { showExportSelectionDialog = false }, + title = translation["export_logs_dialog_title"], + text = translation["export_logs_dialog_confirm_text"], + icon = Icons.Default.SaveAlt, + customContent = { + var expanded by remember { mutableStateOf(false) } + ExposedDropdownMenuBox( + expanded = expanded, + onExpandedChange = { expanded = it }, + ) { + Surface( + modifier = Modifier + .menuAnchor(MenuAnchorType.PrimaryNotEditable) + .padding(vertical = 8.dp), + shape = RoundedCornerShape(12.dp), + color = Color.White.copy(alpha = 0.06f), + border = BorderStroke(1.dp, Color.White.copy(alpha = 0.12f)) + ) { + Row( + modifier = Modifier.padding(horizontal = 12.dp, vertical = 8.dp), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(8.dp) + ) { + Text(translation.format("export_as_button", "type" to exportType.uppercase()), color = Color.White) + ExposedDropdownMenuDefaults.TrailingIcon(expanded = expanded) + } + } + DropdownMenu(expanded = expanded, onDismissRequest = { expanded = false }) { + listOf("json", "csv").forEach { type -> + DropdownMenuItem(onClick = { + exportType = type + expanded = false + }, text = { + Text(type.uppercase(), color = Color.White) + }) + } + } + } + }, + confirmButtonText = translation["export_button"], + onConfirm = { if (exportTask == null) exportLogs() }, + dismissButtonText = context.translation["button.cancel"], + onDismiss = { + exportTask?.cancel() + exportTask = null + showExportSelectionDialog = false + }, + loading = exportTask != null, + opaque = true, + showCloseButton = false + ) + } + + + @Composable + fun FilterSelection( + selectionExpanded: MutableState + ) { + var dropDownExpanded by remember { mutableStateOf(false) } + var showDatePicker by remember { mutableStateOf(false) } + + if (showDatePicker) { + Dialog(onDismissRequest = { showDatePicker = false }) { + val dialogShape = RoundedCornerShape(22.dp) + Surface( + shape = dialogShape, + color = Color.Transparent, + border = BorderStroke(1.dp, Color.White.copy(alpha = 0.14f)), + shadowElevation = 16.dp + ) { + Column( + modifier = Modifier + .background(PurrfectPalette.cardOverlay, dialogShape) + .padding(16.dp), + verticalArrangement = Arrangement.spacedBy(12.dp), + horizontalAlignment = Alignment.CenterHorizontally + ) { + Text( + translation["pick_a_date_button"], + color = Color.White, + fontWeight = FontWeight.ExtraBold, + fontSize = 18.sp, + textAlign = TextAlign.Center + ) + DatePicker( + state = sinceDatePickerState, + modifier = Modifier + .fillMaxWidth() + .background(Color.White.copy(alpha = 0.02f), RoundedCornerShape(18.dp)), + colors = DatePickerDefaults.colors( + containerColor = Color.Transparent, + titleContentColor = Color.White, + headlineContentColor = Color.White, + weekdayContentColor = Color.White.copy(alpha = 0.9f), + subheadContentColor = PurrfectPalette.textSecondary, + selectedDayContainerColor = PurrfectPalette.glowPrimary.copy(alpha = 0.4f), + selectedDayContentColor = Color.Black, + todayContentColor = Color.White, + todayDateBorderColor = PurrfectPalette.glowSecondary, + dayContentColor = Color.White.copy(alpha = 0.85f), + disabledDayContentColor = Color.White.copy(alpha = 0.35f), + dividerColor = Color.White.copy(alpha = 0.14f), + navigationContentColor = Color.White + ) + ) + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.spacedBy(10.dp, Alignment.End) + ) { + Surface( + onClick = { + showDatePicker = false + sinceDatePickerState.selectedDateMillis = null + }, + shape = RoundedCornerShape(14.dp), + color = Color.White.copy(alpha = 0.08f), + border = BorderStroke(1.dp, Color.White.copy(alpha = 0.12f)) + ) { + Text( + context.translation["button.cancel"], + color = Color.White, + modifier = Modifier.padding(horizontal = 12.dp, vertical = 8.dp) + ) + } + Surface( + onClick = { showDatePicker = false }, + shape = RoundedCornerShape(14.dp), + color = PurrfectPalette.glowPrimary.copy(alpha = 0.32f), + border = BorderStroke(1.dp, Color.White.copy(alpha = 0.14f)) + ) { + Text( + context.translation["button.ok"], + color = Color.White, + modifier = Modifier.padding(horizontal = 12.dp, vertical = 8.dp) + ) + } + } + } + } + } + } + + DropdownMenu( + expanded = selectionExpanded.value, + onDismissRequest = { selectionExpanded.value = false }, + shape = RoundedCornerShape(18.dp), + containerColor = Color.Transparent, + tonalElevation = 0.dp + ) { + Box( + modifier = Modifier + .padding(8.dp) + .background(PurrfectPalette.cardOverlay, RoundedCornerShape(16.dp)) + .border(1.dp, Color.White.copy(alpha = 0.12f), RoundedCornerShape(16.dp)) + .padding(horizontal = 16.dp, vertical = 14.dp) + ) { + Column( + verticalArrangement = Arrangement.spacedBy(12.dp) + ) { + val rowHSpacing = 10.dp + + Text( + translation["filters_title"], + fontWeight = FontWeight.ExtraBold, + fontSize = 18.sp, + color = Color.White + ) + + Row( + horizontalArrangement = Arrangement.spacedBy(rowHSpacing), + verticalAlignment = Alignment.CenterVertically, + ) { + Text(translation["search_by_label"], color = Color.White) + ExposedDropdownMenuBox( + expanded = dropDownExpanded, + onExpandedChange = { dropDownExpanded = it }, + modifier = Modifier.weight(1f) + ) { + Surface( + modifier = Modifier + .menuAnchor() + .fillMaxWidth() + .border(1.dp, Color.White.copy(alpha = 0.2f), RoundedCornerShape(12.dp)), + shape = RoundedCornerShape(12.dp), + color = Color.White.copy(alpha = 0.06f) + ) { + Text( + filterType.name, + modifier = Modifier.padding(horizontal = 10.dp, vertical = 8.dp), + color = Color.White + ) + } + ExposedDropdownMenu( + expanded = dropDownExpanded, + onDismissRequest = { dropDownExpanded = false }, + containerColor = Color(0xFF101220), + shape = RoundedCornerShape(14.dp) + ) { + FriendTrackerManagerRoot.FilterType.entries.forEach { type -> + DropdownMenuItem( + onClick = { + filter = "" + filterType = type + dropDownExpanded = false + coroutineScope.launch { resetAndLoadLogs() } + }, + text = { Text(type.name, color = Color.White) } + ) + } + } + } + } + + Row( + horizontalArrangement = Arrangement.spacedBy(rowHSpacing), + verticalAlignment = Alignment.CenterVertically, + ) { + Text(translation["reverse_order_checkbox"], color = Color.White) + Switch( + checked = reverseSortOrder, + onCheckedChange = { + reverseSortOrder = it + selectionExpanded.value = false + }, + colors = purrfectSwitchColors() + ) + } + Row( + horizontalArrangement = Arrangement.spacedBy(rowHSpacing), + verticalAlignment = Alignment.CenterVertically, + ) { + Text(translation[if (reverseSortOrder) "since_label" else "until_label"], color = Color.White) + val dateLabel = remember(showDatePicker) { + sinceDatePickerState.selectedDateMillis?.let { + DateFormat.getDateInstance().format(it) + } ?: translation["pick_a_date_button"] + } + Surface( + onClick = { showDatePicker = true }, + shape = RoundedCornerShape(14.dp), + color = Color.Transparent, + border = BorderStroke(1.dp, Color.White.copy(alpha = 0.14f)), + tonalElevation = 0.dp, + shadowElevation = 6.dp + ) { + Row( + modifier = Modifier + .background( + Brush.linearGradient( + listOf( + PurrfectPalette.glowPrimary.copy(alpha = 0.3f), + PurrfectPalette.glowSecondary.copy(alpha = 0.26f) + ) + ), + RoundedCornerShape(14.dp) + ) + .padding(horizontal = 12.dp, vertical = 8.dp), + horizontalArrangement = Arrangement.spacedBy(8.dp), + verticalAlignment = Alignment.CenterVertically + ) { + Icon(Icons.Default.FolderOpen, contentDescription = null, tint = Color.White.copy(alpha = 0.9f)) + Text(dateLabel, color = Color.White, fontWeight = FontWeight.SemiBold) + } + } + } + } + } + } + } + + Column( + modifier = Modifier.fillMaxSize() + ) { + Row( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 8.dp, vertical = 6.dp), + verticalAlignment = Alignment.CenterVertically, + ) { + var showAutoComplete by remember { mutableStateOf(false) } + val showFilterSelection = remember { mutableStateOf(false) } + val inputShape = RoundedCornerShape(18.dp) + + ExposedDropdownMenuBox( + expanded = showAutoComplete, + onExpandedChange = { showAutoComplete = it }, + ) { + Surface( + modifier = Modifier + .fillMaxWidth() + .menuAnchor(MenuAnchorType.PrimaryNotEditable), + shape = inputShape, + color = Color.Transparent, + shadowElevation = 0.dp, + tonalElevation = 0.dp, + border = BorderStroke(1.dp, Color.White.copy(alpha = 0.12f)) + ) { + Row( + modifier = Modifier + .background(PurrfectPalette.cardOverlay, inputShape) + ) { + IconButton( + onClick = { showFilterSelection.value = !showFilterSelection.value }, + modifier = Modifier + .padding(start = 6.dp) + .size(46.dp) + ) { + Icon(Icons.Default.FilterList, contentDescription = translation["filter_button_description"], tint = Color.White) + } + FilterSelection(showFilterSelection) + if (showFilterSelection.value) { + DisposableEffect(Unit) { + onDispose { + coroutineScope.launch { resetAndLoadLogs() } + } + } + } + TextField( + value = filter, + onValueChange = { + filter = it + coroutineScope.launch { + searchTimeoutJob?.cancel() + searchTimeoutJob = coroutineScope.launch { + delay(200) + showAutoComplete = true + resetAndLoadLogs() + } + } + }, + placeholder = { Text(translation["search_placeholder"], color = PurrfectPalette.textSecondary) }, + colors = TextFieldDefaults.colors( + focusedContainerColor = Color.Transparent, + unfocusedContainerColor = Color.Transparent, + focusedIndicatorColor = Color.Transparent, + unfocusedIndicatorColor = Color.Transparent, + cursorColor = Color.White + ), + singleLine = true, + modifier = Modifier + .weight(1f) + .padding(end = 8.dp), + textStyle = LocalTextStyle.current.copy(color = Color.White), + trailingIcon = { + if (filter.isNotEmpty()) { + IconButton(onClick = { + filter = "" + coroutineScope.launch { resetAndLoadLogs() } + }) { + Icon(Icons.Default.Clear, contentDescription = translation["clear_button_description"], tint = Color.White) + } + } + } + ) + } + } + + DropdownMenu( + expanded = showAutoComplete, + onDismissRequest = { showAutoComplete = false }, + properties = PopupProperties(focusable = false), + containerColor = Color(0xFF161821), + shape = RoundedCornerShape(14.dp), + tonalElevation = 12.dp + ) { + val suggestedEntries = remember(filter) { mutableStateListOf() } + + LaunchedEffect(filter) { + suggestedEntries.clear() + launch(Dispatchers.IO) { + suggestedEntries.addAll( + when (filterType) { + FriendTrackerManagerRoot.FilterType.USERNAME -> context.messageLogger.findUsername(filter) + FriendTrackerManagerRoot.FilterType.CONVERSATION -> context.messageLogger.findConversation(filter) + context.messageLogger.findUsername(filter) + FriendTrackerManagerRoot.FilterType.EVENT -> TrackerEventType.entries.filter { it.name.contains(filter, ignoreCase = true) }.map { it.key } + }.take(5) + ) + } + } + + suggestedEntries.forEach { entry -> + DropdownMenuItem( + onClick = { + filter = entry + coroutineScope.launch { resetAndLoadLogs() } + showAutoComplete = false + }, + text = { Text(entry, color = Color.White) } + ) + } + } + } + } + + LazyColumn( + modifier = Modifier.weight(1f), + contentPadding = PaddingValues(bottom = bottomPadding) + ) { + item { + Row( + modifier = Modifier + .fillMaxWidth(), + horizontalArrangement = Arrangement.Center + ) { + if (logs.isEmpty() && !isLoading) { + Column( + modifier = Modifier.padding(top = 40.dp), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.spacedBy(10.dp) + ) { + Surface( + shape = CircleShape, + color = Color.White.copy(alpha = 0.08f), + tonalElevation = 0.dp, + shadowElevation = 0.dp, + border = BorderStroke(1.dp, Color.White.copy(alpha = 0.12f)) + ) { + Box( + modifier = Modifier + .size(58.dp) + .background( + Brush.linearGradient( + listOf( + PurrfectPalette.glowPrimary.copy(alpha = 0.32f), + PurrfectPalette.glowSecondary.copy(alpha = 0.28f) + ) + ), + CircleShape + ), + contentAlignment = Alignment.Center + ) { + Icon(Icons.Filled.History, contentDescription = translation["no_logs_found"], tint = Color.White) + } + } + Text( + translation["no_logs_found"], + color = Color.White, + fontWeight = FontWeight.ExtraBold + ) + } + } + } + } + items(logs, key = { it.userId + it.id }) { log -> + var databaseFriend by remember { mutableStateOf(null) } + LaunchedEffect(Unit) { + launch(Dispatchers.IO) { + databaseFriend = context.database.getFriendInfo(log.userId) + } + } + val cardShape = RoundedCornerShape(18.dp) + Surface( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 6.dp, vertical = 4.dp), + shape = cardShape, + color = Color.Transparent, + tonalElevation = 0.dp, + shadowElevation = 10.dp, + border = BorderStroke(1.dp, Color.White.copy(alpha = 0.08f)) + ) { + Row( + modifier = Modifier + .background(PurrfectPalette.cardOverlay, cardShape) + .padding(horizontal = 10.dp, vertical = 8.dp), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(10.dp) + ) { + + BitmojiImage( + modifier = Modifier + .padding(4.dp) + .size(58.dp), + size = 58, + context = context, + url = databaseFriend?.takeIf { it.bitmojiId != null }?.let { + BitmojiSelfie.getBitmojiSelfie(it.selfieId, it.bitmojiId, BitmojiSelfie.BitmojiSelfieType.NEW_THREE_D) + }, + ) + + Column( + modifier = Modifier + .weight(1f), + verticalArrangement = Arrangement.spacedBy(4.dp) + ) { + val eventLabel = trackerTranslation["logs.log_entry.events.${log.eventType}"] + val conversationLabel = log.conversationTitle ?: trackerTranslation["logs.log_entry.unknown_conversation"] + val eventTextTemplate = trackerTranslation["logs.log_entry.event_text"] + val eventText = eventTextTemplate + .replace("{friend}", databaseFriend?.displayName ?: log.username) + .replace("{event}", eventLabel) + .replace("{conversation}", conversationLabel) + + Text(databaseFriend?.displayName?.let { + "$it (${log.username})" + } ?: log.username, lineHeight = 20.sp, fontWeight = FontWeight.ExtraBold, maxLines = 1, overflow = TextOverflow.Ellipsis, fontSize = 15.sp, color = Color.White) + Text(eventText, fontSize = 11.sp, fontWeight = FontWeight.SemiBold, lineHeight = 15.sp, maxLines = 2, overflow = TextOverflow.Ellipsis, color = PurrfectPalette.textSecondary) + if (log.eventType == TrackerEventType.I_CAN_SEE_YOU.key) { + Text( + buildICanSeeYouDetails(log.data), + fontSize = 10.sp, + fontWeight = FontWeight.Medium, + lineHeight = 15.sp, + maxLines = 2, + overflow = TextOverflow.Ellipsis, + color = Color.White + ) + } + Text( + DateFormat.getDateTimeInstance().format(log.timestamp), + fontSize = 11.sp, + fontWeight = FontWeight.Medium, + lineHeight = 15.sp, + color = Color.White.copy(alpha = 0.82f) + ) + } + + IconButton( + onClick = { + context.messageLogger.deleteTrackerLog(log.id) + logs.remove(log) + } + ) { + Icon(Icons.Default.DeleteOutline, contentDescription = translation["delete_button_description"], tint = Color.White) + } + } + } + } + item { + Spacer(modifier = Modifier.height(16.dp)) + + LaunchedEffect(pageIndex) { + loadNewLogs() + } + } + + } + } +} diff --git a/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/tracker/ManageFriendTrackerReposSection.kt b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/tracker/ManageFriendTrackerReposSection.kt new file mode 100644 index 00000000..7ea8833e --- /dev/null +++ b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/tracker/ManageFriendTrackerReposSection.kt @@ -0,0 +1,400 @@ +package me.eternal.purrfectsnap.ui.manager.pages.tracker + +import androidx.compose.animation.AnimatedVisibility +import androidx.compose.foundation.BorderStroke +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.WindowInsets +import androidx.compose.foundation.layout.asPaddingValues +import androidx.compose.foundation.layout.statusBars +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Error +import androidx.compose.material.icons.filled.Public +import androidx.compose.material3.Button +import androidx.compose.material3.ButtonDefaults +import androidx.compose.material3.CircularProgressIndicator +import androidx.compose.material3.ExtendedFloatingActionButton +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.OutlinedTextField +import androidx.compose.material3.Surface +import androidx.compose.material3.Text +import androidx.compose.material3.TextButton +import androidx.compose.material3.TextFieldDefaults +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalDensity +import androidx.compose.ui.focus.FocusRequester +import androidx.compose.ui.focus.focusRequester +import androidx.compose.ui.graphics.Brush +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.layout.onGloballyPositioned +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import androidx.compose.ui.zIndex +import androidx.core.net.toUri +import androidx.compose.ui.window.Dialog +import com.google.gson.JsonParser +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import kotlinx.coroutines.runBlocking +import me.eternal.purrfectsnap.common.util.ktx.getUrlFromClipboard +import me.eternal.purrfectsnap.storage.addRepo +import me.eternal.purrfectsnap.storage.getRepositories +import me.eternal.purrfectsnap.storage.removeRepo +import me.eternal.purrfectsnap.ui.manager.Routes +import me.eternal.purrfectsnap.ui.manager.components.AestheticDialog +import me.eternal.purrfectsnap.ui.manager.components.AestheticEmptyState +import me.eternal.purrfectsnap.ui.manager.components.FloatingTopBar +import me.eternal.purrfectsnap.ui.manager.theme.PurrfectPalette +import okhttp3.OkHttpClient + +class ManageFriendTrackerReposSection: Routes.Route() { + override val translation by lazy { context.translation.getCategory("manager.friend_tracker_repos") } + private val refreshTrigger = mutableStateOf(0) + private val okHttpClient by lazy { OkHttpClient() } + + override val floatingActionButton: @Composable () -> Unit = { + var showAddDialog by remember { mutableStateOf(false) } + var showErrorDialog by remember { mutableStateOf(false) } + var errorDialogMessage by remember { mutableStateOf("") } + + if (showErrorDialog) { + AestheticDialog( + onDismissRequest = { showErrorDialog = false }, + title = translation["invalid_repo_title"], + text = errorDialogMessage, + icon = Icons.Default.Error, + confirmButtonText = translation["button.ok"], + onConfirm = { showErrorDialog = false }, + showCloseButton = false + ) + } + + ExtendedFloatingActionButton( + onClick = { showAddDialog = true }, + containerColor = PurrfectPalette.glowPrimary.copy(alpha = 0.34f), + contentColor = Color.White + ) { + Icon(Icons.Default.Public, contentDescription = null, tint = Color.White) + Spacer(modifier = Modifier.width(8.dp)) + Text(translation["add_repo_button"]) + } + + if (showAddDialog) { + val coroutineScope = rememberCoroutineScope { Dispatchers.IO } + + var url by remember { mutableStateOf("") } + var loading by remember { mutableStateOf(false) } + + Dialog(onDismissRequest = { showAddDialog = false }) { + val focusRequester = remember { FocusRequester() } + Surface( + shape = RoundedCornerShape(24.dp), + color = Color.Transparent, + tonalElevation = 0.dp, + shadowElevation = 16.dp, + border = BorderStroke( + 1.dp, + Brush.linearGradient( + listOf( + PurrfectPalette.glowPrimary.copy(alpha = 0.55f), + PurrfectPalette.glowSecondary.copy(alpha = 0.45f) + ) + ) + ) + ) { + Column( + modifier = Modifier + .background(PurrfectPalette.cardOverlay, RoundedCornerShape(24.dp)) + .padding(horizontal = 18.dp, vertical = 16.dp), + verticalArrangement = Arrangement.spacedBy(12.dp) + ) { + Row( + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(10.dp) + ) { + Surface( + shape = CircleShape, + color = PurrfectPalette.glowPrimary.copy(alpha = 0.18f) + ) { + Icon( + Icons.Default.Public, + contentDescription = null, + tint = Color.White, + modifier = Modifier.padding(10.dp) + ) + } + Column { + Text( + text = translation["add_repo_dialog_title"], + color = Color.White, + fontWeight = FontWeight.ExtraBold, + fontSize = 18.sp + ) + Text( + text = translation["manager.dialogs.scripting.repo_hint"] + ?: translation["repo_url_label"] + ?: "", + color = PurrfectPalette.textSecondary, + style = MaterialTheme.typography.bodySmall + ) + } + } + OutlinedTextField( + modifier = Modifier + .fillMaxWidth() + .focusRequester(focusRequester) + .onGloballyPositioned { focusRequester.requestFocus() }, + value = url, + onValueChange = { url = it }, + label = { Text(translation["repo_url_label"], color = PurrfectPalette.textSecondary) }, + singleLine = true, + colors = TextFieldDefaults.colors( + focusedIndicatorColor = Color.Transparent, + unfocusedIndicatorColor = Color.Transparent, + focusedContainerColor = Color.White.copy(alpha = 0.08f), + unfocusedContainerColor = Color.White.copy(alpha = 0.05f), + cursorColor = PurrfectPalette.glowSecondary, + focusedLabelColor = PurrfectPalette.textSecondary, + unfocusedLabelColor = PurrfectPalette.textSecondary + ) + ) + LaunchedEffect(Unit) { + context.androidContext.getUrlFromClipboard()?.let { url = it } + } + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.spacedBy(10.dp, Alignment.End) + ) { + TextButton(onClick = { showAddDialog = false }) { + Text(translation["button.cancel"], color = PurrfectPalette.textSecondary) + } + Button( + enabled = !loading && url.isNotBlank(), + onClick = { + loading = true + coroutineScope.launch { + runCatching { + var modifiedUrl = url + if (url.startsWith("https://github.com/")) { + val splitUrl = modifiedUrl.removePrefix("https://github.com/").split("/") + val repoName = splitUrl[0] + "/" + splitUrl[1] + okHttpClient.newCall( + okhttp3.Request.Builder().url("https://api.github.com/repos/$repoName").build() + ).execute().use { response -> + if (!response.isSuccessful) { + throw Exception("Failed to fetch default branch: ${response.code}") + } + val json = response.body?.string() ?: throw Exception("Empty response") + val defaultBranch = Regex("\"default_branch\":\"([^\"]+)\"").find(json)?.groupValues?.get(1) + ?: throw Exception("No default_branch field") + modifiedUrl = "https://raw.githubusercontent.com/$repoName/$defaultBranch/" + } + } + + val indexUrl = modifiedUrl.toUri().buildUpon().appendPath("index.json").build().toString() + val request = okhttp3.Request.Builder().url(indexUrl).build() + val isValid = okHttpClient.newCall(request).execute().use { response -> + if (!response.isSuccessful) throw Exception("Failed to fetch index.json: ${response.code}") + val indexJson = response.body?.string() ?: throw Exception("Empty index.json") + JsonParser.parseString(indexJson).asJsonObject.has("rules") + } + + if (isValid) { + context.database.addRepo("friend_tracker", modifiedUrl) + context.shortToast(translation["repo_added_toast"]) + showAddDialog = false + refreshTrigger.value++ + } else { + errorDialogMessage = translation["invalid_repo_error"] + showErrorDialog = true + } + }.onFailure { + context.log.error("Failed to add repository", it) + context.shortToast(translation.format("add_repo_failed_toast", "message" to (it.message ?: "Unknown"))) + } + loading = false + } + }, + colors = ButtonDefaults.buttonColors( + containerColor = PurrfectPalette.glowPrimary.copy(alpha = 0.3f), + contentColor = Color.White + ) + ) { + if (loading) { + CircularProgressIndicator(modifier = Modifier.size(24.dp), color = Color.White, strokeWidth = 2.dp) + } else { + Text(translation["add_button"]) + } + } + } + } + } + } + } + } + + override val content: @Composable (androidx.navigation.NavBackStackEntry) -> Unit = { + val repositories by remember(refreshTrigger.value) { + mutableStateOf>(runBlocking { context.database.getRepositories("friend_tracker") }) + } + val density = LocalDensity.current + val statusBarTopPadding = WindowInsets.statusBars.asPaddingValues().calculateTopPadding() + var topBarHeight by remember { mutableStateOf(statusBarTopPadding + 96.dp) } + + Box( + modifier = Modifier + .fillMaxSize() + .background(PurrfectPalette.backgroundGradient) + ) { + FloatingTopBar( + title = routeInfo.translatedKey?.value ?: (translation["title"] ?: "Repositories"), + onBack = { routes.navController.popBackStack() }, + modifier = Modifier + .zIndex(2f) + .onGloballyPositioned { + val newHeight = with(density) { it.size.height.toDp() } + if (newHeight != topBarHeight) topBarHeight = newHeight + } + ) + if (repositories.isEmpty()) { + Box( + modifier = Modifier.fillMaxSize(), + contentAlignment = Alignment.Center + ) { + AestheticEmptyState( + icon = Icons.Default.Public, + title = translation["no_repos_added"], + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 22.dp) + ) + } + } else { + LazyColumn( + modifier = Modifier.fillMaxSize(), + contentPadding = PaddingValues( + start = 12.dp, + top = topBarHeight + 12.dp, + end = 12.dp, + bottom = 18.dp + routes.bottomPadding + ), + verticalArrangement = Arrangement.spacedBy(10.dp) + ) { + items(repositories) { url -> + val (repoName, author) = remember(url) { + url.removePrefix("https://raw.githubusercontent.com/").split("/").let { it[1] to it[0] } + } + var showRemoveDialog by remember { mutableStateOf(false) } + + Surface( + modifier = Modifier.fillMaxWidth(), + shape = RoundedCornerShape(20.dp), + color = PurrfectPalette.cardOverlayColor, + tonalElevation = 0.dp, + shadowElevation = 10.dp, + border = BorderStroke( + 1.dp, + Brush.linearGradient( + listOf( + PurrfectPalette.glowPrimary.copy(alpha = 0.45f), + PurrfectPalette.glowSecondary.copy(alpha = 0.35f) + ) + ) + ) + ) { + Row( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 14.dp, vertical = 12.dp), + horizontalArrangement = Arrangement.spacedBy(12.dp), + verticalAlignment = Alignment.CenterVertically + ) { + Surface( + shape = CircleShape, + color = PurrfectPalette.glowPrimary.copy(alpha = 0.18f) + ) { + Icon( + Icons.Default.Public, + contentDescription = null, + modifier = Modifier.padding(10.dp), + tint = Color.White + ) + } + Column( + modifier = Modifier.weight(1f), + verticalArrangement = Arrangement.spacedBy(2.dp) + ) { + Text( + text = repoName, + fontWeight = FontWeight.SemiBold, + fontSize = 16.sp, + color = Color.White + ) + Text( + text = author, + fontSize = 13.sp, + color = PurrfectPalette.textSecondary + ) + } + Button( + onClick = { showRemoveDialog = true }, + colors = ButtonDefaults.buttonColors( + containerColor = PurrfectPalette.glowPrimary.copy(alpha = 0.22f), + contentColor = Color.White + ) + ) { + Text(translation["remove_button"]) + } + + AnimatedVisibility(visible = showRemoveDialog) { + AestheticDialog( + onDismissRequest = { showRemoveDialog = false }, + title = translation["remove_repo_dialog_title"], + text = translation["remove_repo_dialog_text"], + icon = Icons.Default.Error, + confirmButtonText = translation["remove_button"], + dismissButtonText = translation["button.cancel"], + onDismiss = { showRemoveDialog = false }, + onConfirm = { + context.database.removeRepo("friend_tracker", url) + showRemoveDialog = false + refreshTrigger.value++ + }, + showCloseButton = false + ) + } + } + } + } + } + } + } + } +} diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/tracker/TrackerConfigParser.kt b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/tracker/TrackerConfigParser.kt similarity index 90% rename from app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/tracker/TrackerConfigParser.kt rename to app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/tracker/TrackerConfigParser.kt index 1f83d731..a3b70d5e 100644 --- a/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/tracker/TrackerConfigParser.kt +++ b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/tracker/TrackerConfigParser.kt @@ -1,7 +1,7 @@ -package me.rhunk.snapenhance.ui.manager.pages.tracker +package me.eternal.purrfectsnap.ui.manager.pages.tracker -import me.rhunk.snapenhance.common.data.ExportedTrackerData -import me.rhunk.snapenhance.ui.manager.Routes +import me.eternal.purrfectsnap.common.data.ExportedTrackerData +import me.eternal.purrfectsnap.ui.manager.Routes import org.json.JSONArray data class ImportedFeature( diff --git a/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/theme/PurrfectPalette.kt b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/theme/PurrfectPalette.kt new file mode 100644 index 00000000..2bba7ced --- /dev/null +++ b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/theme/PurrfectPalette.kt @@ -0,0 +1,39 @@ +package me.eternal.purrfectsnap.ui.manager.theme + +import androidx.compose.ui.graphics.Brush +import androidx.compose.ui.graphics.Color + +/** + * Centralized palette for the premium PurrfectSnap look. + * Avoids relying on MaterialTheme for tinting so we can keep a consistent brand glow everywhere. + */ +object PurrfectPalette { + val backgroundGradient = Brush.verticalGradient( + listOf( + Color(0xFF261F58), + Color(0xFF302A6D), + Color(0xFF241F52) + ) + ) + + val panelGradient = Brush.linearGradient( + listOf( + Color(0xFF5C4B99), + Color(0xFF322B5E), + Color(0xFF1B1836) + ) + ) + + val glowPrimary = Color(0xFF8C7BFF) + val glowSecondary = Color(0xFF5FD8FF) + val iconTint = Color.White + val textPrimary = Color.White + val textSecondary = Color(0xFFD9D3FF) + val cardOverlayColor = Color(0xFF2A2452).copy(alpha = 0.95f) + val cardOverlay = Brush.linearGradient( + listOf( + Color(0xFF2A2452).copy(alpha = 0.95f), + Color(0xFF1A143A).copy(alpha = 0.92f) + ) + ) +} diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/ui/overlay/RemoteOverlay.kt b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/overlay/RemoteOverlay.kt similarity index 61% rename from app/src/main/kotlin/me/rhunk/snapenhance/ui/overlay/RemoteOverlay.kt rename to app/src/main/kotlin/me/eternal/purrfectsnap/ui/overlay/RemoteOverlay.kt index 618b81bc..1c550735 100644 --- a/app/src/main/kotlin/me/rhunk/snapenhance/ui/overlay/RemoteOverlay.kt +++ b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/overlay/RemoteOverlay.kt @@ -1,5 +1,5 @@ @file:OptIn(androidx.compose.animation.ExperimentalAnimationApi::class) -package me.rhunk.snapenhance.ui.overlay +package me.eternal.purrfectsnap.ui.overlay import android.app.Dialog import android.content.Intent @@ -7,27 +7,34 @@ import android.graphics.drawable.ColorDrawable import android.net.Uri import android.provider.Settings import android.view.WindowManager -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Scaffold +import androidx.compose.material3.Surface +import androidx.compose.material3.LocalContentColor +import androidx.compose.material3.LocalTextStyle import androidx.compose.runtime.Composable +import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.remember -import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color +import androidx.compose.ui.text.TextStyle import androidx.compose.ui.unit.dp import androidx.navigation.compose.rememberNavController import com.arthenica.ffmpegkit.Packages.getPackageName -import me.rhunk.snapenhance.R -import me.rhunk.snapenhance.RemoteSideContext -import me.rhunk.snapenhance.common.ui.createComposeView -import me.rhunk.snapenhance.ui.manager.Navigation -import me.rhunk.snapenhance.ui.manager.Routes +import me.eternal.purrfectsnap.R +import me.eternal.purrfectsnap.RemoteSideContext +import me.eternal.purrfectsnap.common.ui.AppMaterialTheme +import me.eternal.purrfectsnap.common.ui.ThemeMode +import me.eternal.purrfectsnap.common.ui.createComposeView +import me.eternal.purrfectsnap.ui.manager.Navigation +import me.eternal.purrfectsnap.ui.manager.Routes +import me.eternal.purrfectsnap.ui.manager.theme.PurrfectPalette class RemoteOverlay( @@ -58,7 +65,7 @@ class RemoteOverlay( val navigation = remember { Navigation(context, navHostController) } Scaffold( - containerColor = MaterialTheme.colorScheme.background, + containerColor = Color.Transparent, topBar = { navigation.TopBar() } ) { innerPadding -> navigation.NavContent( @@ -107,15 +114,33 @@ class RemoteOverlay( dialog.setContentView( createComposeView(context.androidContext) { - Column( - modifier = Modifier - .fillMaxSize() - .padding(start = 12.dp, end = 12.dp, top = 10.dp, bottom = 20.dp) - .clip(shape = MaterialTheme.shapes.large), - horizontalAlignment = Alignment.CenterHorizontally, - verticalArrangement = Arrangement.Center - ) { - OverlayContent(route) + AppMaterialTheme(themeMode = ThemeMode.DARK) { + CompositionLocalProvider( + LocalContentColor provides Color.White, + LocalTextStyle provides LocalTextStyle.current.merge(TextStyle(color = Color.White)) + ) { + val overlayShape = MaterialTheme.shapes.large + Surface( + modifier = Modifier + .fillMaxSize() + .padding(start = 12.dp, end = 12.dp) + .clip(overlayShape), + shape = overlayShape, + color = Color.Transparent, + contentColor = Color.White, + tonalElevation = 0.dp, + shadowElevation = 10.dp + ) { + Box( + modifier = Modifier + .fillMaxSize() + .clip(overlayShape) + .background(PurrfectPalette.backgroundGradient) + ) { + OverlayContent(route) + } + } + } } } ) @@ -125,4 +150,3 @@ class RemoteOverlay( } } } - diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/ui/setup/Requirements.kt b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/setup/Requirements.kt similarity index 85% rename from app/src/main/kotlin/me/rhunk/snapenhance/ui/setup/Requirements.kt rename to app/src/main/kotlin/me/eternal/purrfectsnap/ui/setup/Requirements.kt index 4d81c030..9b96e68a 100644 --- a/app/src/main/kotlin/me/rhunk/snapenhance/ui/setup/Requirements.kt +++ b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/setup/Requirements.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.ui.setup +package me.eternal.purrfectsnap.ui.setup object Requirements { const val FIRST_RUN = 0b000001 diff --git a/app/src/main/kotlin/me/eternal/purrfectsnap/ui/setup/SetupActivity.kt b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/setup/SetupActivity.kt new file mode 100644 index 00000000..cb4107ac --- /dev/null +++ b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/setup/SetupActivity.kt @@ -0,0 +1,801 @@ +@file:OptIn(androidx.compose.animation.ExperimentalAnimationApi::class) + +package me.eternal.purrfectsnap.ui.setup + +import android.app.Activity +import android.os.Bundle +import androidx.activity.ComponentActivity +import androidx.activity.compose.BackHandler +import androidx.activity.compose.setContent +import androidx.compose.animation.ExperimentalAnimationApi +import androidx.compose.animation.fadeIn +import androidx.compose.animation.fadeOut +import androidx.compose.animation.slideInHorizontally +import androidx.compose.animation.slideOutHorizontally +import androidx.compose.animation.core.LinearEasing +import androidx.compose.animation.core.RepeatMode +import androidx.compose.animation.core.animateFloat +import androidx.compose.animation.core.animateFloatAsState +import androidx.compose.animation.core.infiniteRepeatable +import androidx.compose.animation.core.rememberInfiniteTransition +import androidx.compose.animation.core.tween +import androidx.compose.foundation.Canvas +import androidx.compose.foundation.background +import androidx.compose.foundation.border +import androidx.compose.foundation.clickable +import androidx.compose.foundation.interaction.MutableInteractionSource +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.WindowInsets +import androidx.compose.foundation.layout.asPaddingValues +import androidx.compose.foundation.layout.fillMaxHeight +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.navigationBars +import androidx.compose.foundation.layout.navigationBarsPadding +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.statusBarsPadding +import androidx.compose.foundation.layout.statusBars +import androidx.compose.foundation.layout.widthIn +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.verticalScroll +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.automirrored.filled.ArrowForwardIos +import androidx.compose.material.icons.filled.AutoAwesome +import androidx.compose.material.icons.filled.Check +import androidx.compose.material.icons.filled.Download +import androidx.compose.material.icons.filled.Flag +import androidx.compose.material.icons.filled.Folder +import androidx.compose.material.icons.filled.Language +import androidx.compose.material.icons.filled.VerifiedUser +import androidx.compose.material3.Icon +import androidx.compose.material3.Surface +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.SideEffect +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.saveable.rememberSaveable +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.alpha +import androidx.compose.ui.draw.clip +import androidx.compose.ui.geometry.Offset +import androidx.compose.ui.graphics.Brush +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.toArgb +import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.platform.LocalView +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextOverflow +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import androidx.core.view.WindowCompat +import androidx.core.view.WindowInsetsControllerCompat +import androidx.navigation.compose.NavHost +import androidx.navigation.compose.composable +import androidx.navigation.compose.rememberNavController +import me.eternal.purrfectsnap.RemoteSideContext +import me.eternal.purrfectsnap.SharedContextHolder +import me.eternal.purrfectsnap.common.ui.AppMaterialTheme +import me.eternal.purrfectsnap.ui.manager.theme.PurrfectPalette +import me.eternal.purrfectsnap.ui.setup.screens.SetupScreen +import me.eternal.purrfectsnap.ui.setup.screens.impl.InstallModeScreen +import me.eternal.purrfectsnap.ui.setup.screens.impl.InstallMode +import me.eternal.purrfectsnap.ui.setup.screens.impl.MappingsScreen +import me.eternal.purrfectsnap.ui.setup.screens.impl.PermissionsScreen +import me.eternal.purrfectsnap.ui.setup.screens.impl.PickLanguageScreen +import me.eternal.purrfectsnap.ui.setup.screens.impl.PatchSnapchatScreen +import me.eternal.purrfectsnap.ui.setup.screens.impl.SaveFolderScreen +import me.eternal.purrfectsnap.ui.util.scaleOnPress + +private data class SetupStepMeta( + val route: String, + val title: String, + val subtitle: String, + val icon: ImageVector +) + +class SetupActivity : ComponentActivity() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + + val setupContext = SharedContextHolder.remote(this).apply { + activity = this@SetupActivity + } + fun endActivity() { + setupContext.reload() + finish() + } + val requirements = intent.getIntExtra("requirements", Requirements.FIRST_RUN) + val setupPrefs = setupContext.sharedPreferences + fun hasRequirement(requirement: Int) = requirements and requirement == requirement + val wasInProgress = setupPrefs.getBoolean("setup_in_progress", false) + val isFirstRunFlow = hasRequirement(Requirements.FIRST_RUN) || wasInProgress + val persistedRoute = setupPrefs.getString("setup_current_route", null) + val persistedSkipPatch = setupPrefs.getBoolean("setup_skip_patch", false) + val skipPatchChoice = mutableStateOf(persistedSkipPatch) + + fun persistProgress(route: String, skipPatch: Boolean, inProgress: Boolean = true) { + if (!isFirstRunFlow) return + setupPrefs.edit() + .putBoolean("setup_in_progress", inProgress) + .putString("setup_current_route", route) + .putBoolean("setup_skip_patch", skipPatch) + .apply() + } + + fun clearProgress() { + setupPrefs.edit() + .remove("setup_in_progress") + .remove("setup_current_route") + .remove("setup_skip_patch") + .apply() + } + + val requiredScreens = mutableListOf().apply { + if (isFirstRunFlow || hasRequirement(Requirements.LANGUAGE)) { + add(PickLanguageScreen().apply { route = "language" }) + if (isFirstRunFlow) { + add(InstallModeScreen { mode -> + skipPatchChoice.value = mode == InstallMode.ROOT + }.apply { route = "installMode" }) + } + if (isFirstRunFlow) { + add(PatchSnapchatScreen().apply { route = "patchSnapchat" }) + } + } + if (isFirstRunFlow || hasRequirement(Requirements.GRANT_PERMISSIONS)) { + add(PermissionsScreen().apply { route = "permissions" }) + } + if (isFirstRunFlow || hasRequirement(Requirements.SAVE_FOLDER)) { + add(SaveFolderScreen().apply { route = "saveFolder" }) + } + if (isFirstRunFlow || hasRequirement(Requirements.MAPPINGS)) { + add(MappingsScreen().apply { route = "mappings" }) + } + } + + if (requiredScreens.isEmpty()) { + endActivity() + return + } + requiredScreens.forEach { screen -> + screen.context = setupContext + screen.init() + } + + if (!isFirstRunFlow) { + clearProgress() + skipPatchChoice.value = false + } + + setContent { + val navController = rememberNavController() + var canGoNext by remember { mutableStateOf(false) } + var currentRoute by rememberSaveable { + mutableStateOf( + when { + requiredScreens.first().route == "language" -> requiredScreens.first().route + persistedRoute?.takeIf { route -> requiredScreens.any { it.route == route } } != null -> persistedRoute + else -> requiredScreens.first().route + } + ) + } + val skipPatch by rememberSaveable { skipPatchChoice } + val visibleScreens = remember(skipPatch) { + requiredScreens.filterNot { skipPatch && it is PatchSnapchatScreen } + } + val stepMeta = remember(skipPatch) { visibleScreens.map { it.meta(setupContext) } } + val currentStepIndex = visibleScreens.indexOfFirst { it.route == currentRoute }.let { + if (it == -1) 0 else it + } + val animatedProgress by animateFloatAsState( + targetValue = (currentStepIndex + 1f) / stepMeta.size.toFloat(), + label = "SetupProgress" + ) + LaunchedEffect(skipPatch) { + val adjustedRoute = visibleScreens.firstOrNull { it.route == currentRoute }?.route + ?: run { + val currentIndex = requiredScreens.indexOfFirst { it.route == currentRoute }.coerceAtLeast(0) + val nextVisible = requiredScreens.drop(currentIndex + 1) + .firstOrNull { screen -> visibleScreens.any { it.route == screen.route } } + nextVisible?.route ?: visibleScreens.firstOrNull()?.route + } + adjustedRoute?.let { + if (it != currentRoute) currentRoute = it + } + } + + LaunchedEffect(currentRoute, skipPatch) { + persistProgress(currentRoute, skipPatch, true) + if (navController.currentDestination?.route != currentRoute) { + navController.navigate(currentRoute) { + popUpTo(requiredScreens.first().route) { inclusive = false } + launchSingleTop = true + } + } + canGoNext = false + } + + fun nextScreen() { + if (!canGoNext) return + canGoNext = false + val currentScreen = visibleScreens.getOrNull(currentStepIndex) + val proceed = { + currentScreen?.onLeave() + if (currentStepIndex < visibleScreens.lastIndex) { + val nextRoute = visibleScreens[currentStepIndex + 1].route + currentRoute = nextRoute + } else { + clearProgress() + endActivity() + } + } + currentScreen?.onNext { proceed() } ?: proceed() + } + + AppMaterialTheme { + val view = LocalView.current + val navBarPadding = WindowInsets.navigationBars.asPaddingValues().calculateBottomPadding() + SideEffect { + val window = (view.context as Activity).window + WindowCompat.setDecorFitsSystemWindows(window, false) + window.statusBarColor = Color.Transparent.toArgb() + window.navigationBarColor = Color.Transparent.toArgb() + val insetsController = WindowInsetsControllerCompat(window, window.decorView) + insetsController.isAppearanceLightStatusBars = false + insetsController.isAppearanceLightNavigationBars = false + } + Box( + modifier = Modifier + .fillMaxSize() + .background(Color.Transparent) + ) { + SetupAuroraBackground() + SetupTopBar() + val bottomPadding = 118.dp + navBarPadding + Column( + modifier = Modifier + .fillMaxSize() + .padding( + start = 16.dp, + end = 16.dp, + top = 110.dp, + bottom = bottomPadding + ) + .statusBarsPadding(), + verticalArrangement = Arrangement.spacedBy(14.dp) + ) { + SetupHeader( + currentStep = stepMeta[currentStepIndex], + currentIndex = currentStepIndex, + total = stepMeta.size + ) + SetupProgressBar(animatedProgress) + val scrollState = rememberScrollState() + Box( + modifier = Modifier + .fillMaxWidth() + .weight(1f) + .padding(horizontal = 4.dp) + ) { + NavHost( + navController = navController, + startDestination = requiredScreens.first().route, + enterTransition = { fadeIn() }, + exitTransition = { fadeOut() }, + popEnterTransition = { fadeIn() }, + popExitTransition = { fadeOut() } + ) { + requiredScreens.forEach { screen -> + val screenRoute = screen.route + screen.allowNext = allowNext@{ canGoNextFlag -> + if (screenRoute != currentRoute) return@allowNext + canGoNext = canGoNextFlag + } + screen.goNext = goNext@{ + if (screenRoute != currentRoute) return@goNext + canGoNext = true + nextScreen() + } + composable( + screen.route, + enterTransition = { slideInHorizontally { it } }, + exitTransition = { slideOutHorizontally { -it } }, + popEnterTransition = { slideInHorizontally { -it } }, + popExitTransition = { slideOutHorizontally { it } } + ) { + BackHandler(true) {} + Box( + modifier = Modifier + .fillMaxSize() + .padding(horizontal = 10.dp, vertical = 10.dp), + contentAlignment = Alignment.Center + ) { + Column( + modifier = Modifier + .widthIn(max = 560.dp) + .verticalScroll(scrollState), + verticalArrangement = Arrangement.spacedBy(12.dp), + horizontalAlignment = Alignment.CenterHorizontally + ) { + screen.Content() + } + } + } + } + } + } + } + + NextButton( + enabled = canGoNext, + isFinalStep = currentStepIndex >= stepMeta.lastIndex, + onClick = { nextScreen() }, + modifier = Modifier + .align(Alignment.BottomCenter) + .navigationBarsPadding() + .padding(bottom = 32.dp) + ) + } + } + } + } +} + +private fun SetupScreen.meta(context: RemoteSideContext): SetupStepMeta { + val translation = context.translation + return when (this) { + is PickLanguageScreen -> SetupStepMeta( + route = route, + title = translation["setup.dialogs.select_language"] ?: "Choose your language", + subtitle = "Tune PurrfectSnap to speak your voice before anything else.", + icon = Icons.Filled.Language + ) + + is InstallModeScreen -> SetupStepMeta( + route = route, + title = "Choose your device", + subtitle = "Pick the path that matches how you'll install PurrfectSnap.", + icon = Icons.Filled.VerifiedUser + ) + + is PermissionsScreen -> SetupStepMeta( + route = route, + title = translation["setup.permissions.dialog"] ?: "Essential permissions", + subtitle = "Grant the essentials so overlays, downloads, and alerts stay reliable.", + icon = Icons.Filled.VerifiedUser + ) + + is PatchSnapchatScreen -> SetupStepMeta( + route = route, + title = "Auto Patcher", + subtitle = "Streamlined download, patch, and install with a single flow.", + icon = Icons.Filled.Download + ) + + is SaveFolderScreen -> SetupStepMeta( + route = route, + title = translation["setup.dialogs.save_folder"] ?: "Where should we save?", + subtitle = "Pick your personal vault so snaps land exactly where you expect.", + icon = Icons.Filled.Folder + ) + + is MappingsScreen -> SetupStepMeta( + route = route, + title = translation["setup.mappings.dialog"] ?: "Mapping your Snapchat", + subtitle = "We calibrate everything to your install so the magic works flawlessly.", + icon = Icons.Filled.AutoAwesome + ) + + else -> SetupStepMeta(route, route, route, Icons.Filled.Check) + } +} + +@Composable +private fun SetupAuroraBackground() { + val infiniteTransition = rememberInfiniteTransition(label = "setupAurora") + val driftX by infiniteTransition.animateFloat( + initialValue = -90f, + targetValue = 140f, + animationSpec = infiniteRepeatable( + animation = tween(durationMillis = 16000, easing = LinearEasing), + repeatMode = RepeatMode.Reverse + ), + label = "driftX" + ) + val driftY by infiniteTransition.animateFloat( + initialValue = 60f, + targetValue = -120f, + animationSpec = infiniteRepeatable( + animation = tween(durationMillis = 14000, easing = LinearEasing), + repeatMode = RepeatMode.Reverse + ), + label = "driftY" + ) + + Box( + modifier = Modifier + .fillMaxSize() + .background(PurrfectPalette.backgroundGradient) + ) { + Canvas(modifier = Modifier.fillMaxSize()) { + val primaryGlow = PurrfectPalette.glowPrimary.copy(alpha = 0.36f) + val secondaryGlow = PurrfectPalette.glowSecondary.copy(alpha = 0.28f) + drawRect( + brush = Brush.linearGradient( + colors = listOf( + Color.White.copy(alpha = 0.06f), + Color.Transparent + ), + start = Offset(x = size.width * 0.15f, y = 0f), + end = Offset(x = size.width * 0.75f, y = size.height * 0.6f) + ), + size = this.size + ) + drawRect( + brush = Brush.linearGradient( + colors = listOf( + PurrfectPalette.glowPrimary.copy(alpha = 0.12f), + Color.Transparent + ), + start = Offset(x = 0f, y = size.height * 0.72f), + end = Offset(x = size.width, y = size.height) + ), + size = this.size + ) + } + } +} + +@Composable +private fun SetupTopBar() { + val topPadding = WindowInsets.statusBars.asPaddingValues().calculateTopPadding() + Surface( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 14.dp, vertical = 12.dp) + .padding(top = topPadding), + shape = RoundedCornerShape(28.dp), + color = Color.White.copy(alpha = 0.07f), + tonalElevation = 0.dp, + shadowElevation = 0.dp, + border = androidx.compose.foundation.BorderStroke( + 1.dp, + Brush.linearGradient( + listOf( + PurrfectPalette.glowPrimary.copy(alpha = 0.6f), + PurrfectPalette.glowSecondary.copy(alpha = 0.45f) + ) + ) + ) + ) { + Row( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 18.dp, vertical = 16.dp), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.Center + ) { + Text( + text = "PurrfectSnap", + color = PurrfectPalette.textPrimary, + fontWeight = FontWeight.ExtraBold, + fontSize = 18.sp + ) + } + } +} + +@Composable +private fun SetupHeader( + currentStep: SetupStepMeta, + currentIndex: Int, + total: Int +) { + Column( + verticalArrangement = Arrangement.spacedBy(10.dp), + modifier = Modifier.fillMaxWidth(), + horizontalAlignment = Alignment.CenterHorizontally + ) { + Row( + horizontalArrangement = Arrangement.spacedBy(8.dp), + verticalAlignment = Alignment.CenterVertically + ) { + Surface( + shape = RoundedCornerShape(30), + color = Color.White.copy(alpha = 0.08f), + border = androidx.compose.foundation.BorderStroke(1.dp, Color.White.copy(alpha = 0.14f)) + ) { + Row( + modifier = Modifier.padding(horizontal = 12.dp, vertical = 8.dp), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(8.dp) + ) { + Icon( + imageVector = Icons.Filled.Flag, + contentDescription = null, + tint = Color.White + ) + Text( + text = "Step ${currentIndex + 1} of $total", + color = Color.White, + fontWeight = FontWeight.Medium, + fontSize = 13.sp + ) + } + } + Surface( + shape = RoundedCornerShape(30), + color = PurrfectPalette.glowPrimary.copy(alpha = 0.16f), + border = androidx.compose.foundation.BorderStroke(1.dp, PurrfectPalette.glowPrimary.copy(alpha = 0.35f)) + ) { + Row( + modifier = Modifier.padding(horizontal = 12.dp, vertical = 8.dp), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(8.dp) + ) { + Icon( + imageVector = currentStep.icon, + contentDescription = null, + tint = Color.White + ) + Text( + text = currentStep.title, + color = Color.White, + fontWeight = FontWeight.SemiBold, + fontSize = 13.sp, + maxLines = 1, + overflow = TextOverflow.Ellipsis + ) + } + } + } + } +} + +private enum class StepState { COMPLETE, ACTIVE, UPCOMING } + +@Composable +private fun StepBadgesRow(steps: List, currentStep: Int) { + Row( + horizontalArrangement = Arrangement.spacedBy(10.dp), + verticalAlignment = Alignment.CenterVertically, + modifier = Modifier.fillMaxWidth() + ) { + steps.forEachIndexed { index, step -> + val state = when { + index < currentStep -> StepState.COMPLETE + index == currentStep -> StepState.ACTIVE + else -> StepState.UPCOMING + } + StepBadge(step, state) + if (index < steps.lastIndex) { + Box( + modifier = Modifier + .height(3.dp) + .width(28.dp) + .background( + Brush.horizontalGradient( + listOf( + Color.White.copy(alpha = 0.05f), + PurrfectPalette.glowPrimary.copy(alpha = 0.4f), + Color.White.copy(alpha = 0.05f) + ) + ), + shape = RoundedCornerShape(20.dp) + ) + ) + } + } + } +} + +@Composable +private fun StepBadge(step: SetupStepMeta, state: StepState) { + val baseColor = when (state) { + StepState.COMPLETE -> PurrfectPalette.glowSecondary + StepState.ACTIVE -> PurrfectPalette.glowPrimary + StepState.UPCOMING -> Color.White.copy(alpha = 0.35f) + } + val background = when (state) { + StepState.UPCOMING -> Color.White.copy(alpha = 0.05f) + StepState.COMPLETE -> Color.White.copy(alpha = 0.08f) + StepState.ACTIVE -> Color.White.copy(alpha = 0.12f) + } + Surface( + shape = RoundedCornerShape(18.dp), + color = background, + border = androidx.compose.foundation.BorderStroke( + 1.dp, + baseColor.copy(alpha = 0.5f) + ) + ) { + Row( + modifier = Modifier.padding(horizontal = 12.dp, vertical = 10.dp), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(10.dp) + ) { + Surface( + modifier = Modifier + .size(32.dp) + .clip(CircleShape), + color = baseColor.copy(alpha = 0.22f) + ) { + Box(contentAlignment = Alignment.Center) { + Icon( + imageVector = step.icon, + contentDescription = null, + tint = Color.White, + modifier = Modifier.align(Alignment.Center) + ) + } + } + Column( + verticalArrangement = Arrangement.spacedBy(2.dp), + modifier = Modifier.widthIn(min = 0.dp, max = 160.dp) + ) { + Text( + text = step.title, + color = Color.White, + fontWeight = if (state == StepState.ACTIVE) FontWeight.Bold else FontWeight.SemiBold, + fontSize = 14.sp, + maxLines = 1, + overflow = TextOverflow.Ellipsis + ) + val hint = when (state) { + StepState.COMPLETE -> "Checked off" + StepState.ACTIVE -> "In progress" + StepState.UPCOMING -> "Ready next" + } + Text( + text = hint, + color = Color.White.copy(alpha = 0.7f), + fontSize = 11.sp + ) + } + } + } +} + +@Composable +private fun SetupProgressBar(progress: Float) { + val gradient = Brush.horizontalGradient( + listOf( + PurrfectPalette.glowSecondary, + PurrfectPalette.glowPrimary + ) + ) + Surface( + shape = RoundedCornerShape(18.dp), + color = Color.White.copy(alpha = 0.07f), + border = androidx.compose.foundation.BorderStroke( + 1.dp, + Color.White.copy(alpha = 0.14f) + ) + ) { + Box( + modifier = Modifier + .fillMaxWidth() + .height(14.dp) + ) { + Box( + modifier = Modifier + .fillMaxHeight() + .fillMaxWidth(progress.coerceIn(0f, 1f)) + .background(gradient) + ) + } + } +} + +@Composable +private fun SetupContentCard( + modifier: Modifier = Modifier, + content: @Composable () -> Unit +) { + Surface( + modifier = modifier, + shape = RoundedCornerShape(34.dp), + color = Color.White.copy(alpha = 0.04f), + border = androidx.compose.foundation.BorderStroke( + 1.dp, + Brush.linearGradient( + listOf( + PurrfectPalette.glowPrimary.copy(alpha = 0.45f), + PurrfectPalette.glowSecondary.copy(alpha = 0.35f) + ) + ) + ), + shadowElevation = 16.dp, + tonalElevation = 0.dp + ) { + Box( + modifier = Modifier + .background(PurrfectPalette.cardOverlay) + .border( + width = 1.dp, + brush = Brush.linearGradient( + listOf( + Color.White.copy(alpha = 0.06f), + Color.Transparent, + Color.White.copy(alpha = 0.06f) + ) + ), + shape = RoundedCornerShape(34.dp) + ) + .padding(horizontal = 16.dp, vertical = 16.dp) + ) { + content() + } + } +} + +@Composable +private fun NextButton( + enabled: Boolean, + isFinalStep: Boolean, + onClick: () -> Unit, + modifier: Modifier = Modifier +) { + val alpha by animateFloatAsState(targetValue = if (enabled) 1f else 0.6f, label = "NextButtonAlpha") + val gradient = Brush.horizontalGradient( + listOf( + PurrfectPalette.glowSecondary, + PurrfectPalette.glowPrimary + ) + ) + val interactionSource = remember { MutableInteractionSource() } + Surface( + modifier = modifier + .alpha(alpha) + .scaleOnPress(interactionSource) + .clip(RoundedCornerShape(40.dp)) + .border( + width = 1.dp, + color = Color.White.copy(alpha = 0.24f), + shape = RoundedCornerShape(40.dp) + ) + .clickable( + enabled = enabled, + interactionSource = interactionSource, + indication = null + ) { onClick() }, + color = Color.White.copy(alpha = if (enabled) 0.07f else 0.03f) + ) { + Box( + modifier = Modifier + .background(if (enabled) gradient else Brush.horizontalGradient(listOf(Color.White.copy(alpha = 0.08f), Color.White.copy(alpha = 0.08f)))) + .padding(horizontal = 28.dp, vertical = 18.dp) + ) { + Row( + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(10.dp) + ) { + Text( + text = if (isFinalStep) "Finish setup" else "Continue", + color = Color.White, + fontWeight = FontWeight.SemiBold, + fontSize = 16.sp + ) + Icon( + imageVector = if (isFinalStep) Icons.Filled.Check else Icons.AutoMirrored.Filled.ArrowForwardIos, + contentDescription = null, + tint = Color.White + ) + } + } + } +} diff --git a/app/src/main/kotlin/me/eternal/purrfectsnap/ui/setup/screens/SetupScreen.kt b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/setup/screens/SetupScreen.kt new file mode 100644 index 00000000..099ea286 --- /dev/null +++ b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/setup/screens/SetupScreen.kt @@ -0,0 +1,130 @@ +package me.eternal.purrfectsnap.ui.setup.screens + +import androidx.compose.foundation.BorderStroke +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.ColumnScope +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.Surface +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.Alignment +import androidx.compose.ui.graphics.Brush +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import me.eternal.purrfectsnap.RemoteSideContext +import me.eternal.purrfectsnap.ui.manager.theme.PurrfectPalette + +abstract class SetupScreen { + lateinit var context: RemoteSideContext + lateinit var allowNext: (canGoNext: Boolean) -> Unit + lateinit var goNext: () -> Unit + lateinit var route: String + + @Composable + fun DialogText(text: String, modifier: Modifier = Modifier) { + Text( + text = text, + fontSize = 16.sp, + fontWeight = FontWeight.Medium, + color = PurrfectPalette.textSecondary, + lineHeight = 20.sp, + modifier = Modifier.padding(horizontal = 18.dp, vertical = 8.dp).then(modifier) + ) + } + + @Composable + fun StepTitle( + title: String, + subtitle: String? = null, + modifier: Modifier = Modifier, + textAlign: TextAlign = TextAlign.Start + ) { + val horizontalAlignment = if (textAlign == TextAlign.Center) Alignment.CenterHorizontally else Alignment.Start + androidx.compose.foundation.layout.Column( + modifier = modifier.fillMaxWidth(), + verticalArrangement = Arrangement.spacedBy(6.dp), + horizontalAlignment = horizontalAlignment + ) { + Text( + text = title, + fontSize = 22.sp, + fontWeight = FontWeight.ExtraBold, + color = PurrfectPalette.textPrimary, + textAlign = textAlign + ) + if (!subtitle.isNullOrBlank()) { + Text( + text = subtitle, + fontSize = 14.sp, + fontWeight = FontWeight.Medium, + color = PurrfectPalette.textSecondary, + lineHeight = 18.sp, + textAlign = textAlign + ) + } + } + } + + @Composable + fun SetupCard( + modifier: Modifier = Modifier, + content: @Composable ColumnScope.() -> Unit + ) { + Surface( + modifier = modifier, + shape = RoundedCornerShape(28.dp), + color = Color.White.copy(alpha = 0.04f), + tonalElevation = 0.dp, + shadowElevation = 10.dp, + border = BorderStroke( + 1.dp, + Brush.linearGradient( + listOf( + PurrfectPalette.glowPrimary.copy(alpha = 0.42f), + PurrfectPalette.glowSecondary.copy(alpha = 0.32f) + ) + ) + ) + ) { + androidx.compose.foundation.layout.Column( + modifier = Modifier + .background(PurrfectPalette.cardOverlay) + .padding(horizontal = 20.dp, vertical = 18.dp), + verticalArrangement = Arrangement.spacedBy(14.dp), + horizontalAlignment = Alignment.CenterHorizontally + ) { + Box( + modifier = Modifier + .fillMaxWidth() + .height(4.dp) + .background( + Brush.horizontalGradient( + listOf( + PurrfectPalette.glowSecondary.copy(alpha = 0.4f), + PurrfectPalette.glowPrimary.copy(alpha = 0.4f) + ) + ), + shape = RoundedCornerShape(50) + ) + ) + content() + } + } + } + + open fun init() {} + open fun onLeave() {} + open fun onNext(navigate: () -> Unit) { navigate() } + + @Composable + abstract fun Content() +} diff --git a/app/src/main/kotlin/me/eternal/purrfectsnap/ui/setup/screens/impl/InstallModeScreen.kt b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/setup/screens/impl/InstallModeScreen.kt new file mode 100644 index 00000000..43860eb8 --- /dev/null +++ b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/setup/screens/impl/InstallModeScreen.kt @@ -0,0 +1,206 @@ +package me.eternal.purrfectsnap.ui.setup.screens.impl + +import androidx.compose.foundation.BorderStroke +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Shield +import androidx.compose.material.icons.filled.VerifiedUser +import androidx.compose.material3.Icon +import androidx.compose.material3.Surface +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.Brush +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import androidx.compose.foundation.interaction.MutableInteractionSource +import me.eternal.purrfectsnap.ui.manager.theme.PurrfectPalette +import me.eternal.purrfectsnap.ui.setup.screens.SetupScreen +import me.eternal.purrfectsnap.ui.util.scaleOnPress + +enum class InstallMode { ROOT, NON_ROOT } + +class InstallModeScreen( + private val onModeChosen: (InstallMode) -> Unit +) : SetupScreen() { + private var selectedMode: InstallMode? = null + + override fun init() { + selectedMode = null + } + + override fun onLeave() { + selectedMode?.let(onModeChosen) + } + + @Composable + override fun Content() { + var choice by remember { mutableStateOf(selectedMode) } + + LaunchedEffect(choice) { + selectedMode = choice + allowNext(choice != null) + } + + SetupCard { + StepTitle( + title = "Choose your device", + subtitle = "If you don't know, select Non-rooted device and proceed.", + modifier = Modifier.align(Alignment.CenterHorizontally) + ) + Column( + modifier = Modifier.fillMaxWidth(), + verticalArrangement = Arrangement.spacedBy(12.dp) + ) { + ModeOption( + title = "Rooted device", + subtitle = "Use Lsposed and skip auto patching.", + icon = Icons.Filled.VerifiedUser, + accent = Brush.horizontalGradient( + listOf( + PurrfectPalette.glowPrimary.copy(alpha = 0.45f), + PurrfectPalette.glowSecondary.copy(alpha = 0.55f) + ) + ), + selected = choice == InstallMode.ROOT, + onClick = { choice = InstallMode.ROOT } + ) + ModeOption( + title = "Non-rooted device", + subtitle = "Use included auto patcher to install patched Snapchat.", + icon = Icons.Filled.Shield, + accent = Brush.horizontalGradient( + listOf( + Color(0xFF7DD3FC), + Color(0xFF6366F1) + ) + ), + selected = choice == InstallMode.NON_ROOT, + onClick = { choice = InstallMode.NON_ROOT } + ) + } + } + } + + @Composable + private fun ModeOption( + title: String, + subtitle: String, + icon: ImageVector, + accent: Brush, + selected: Boolean, + onClick: () -> Unit + ) { + val interactionSource = remember { MutableInteractionSource() } + val background = if (selected) { + Color.White.copy(alpha = 0.08f) + } else { + Color.White.copy(alpha = 0.04f) + } + val borderColor = if (selected) { + Color.White.copy(alpha = 0.4f) + } else { + Color.White.copy(alpha = 0.18f) + } + Surface( + modifier = Modifier + .fillMaxWidth() + .scaleOnPress(interactionSource) + .clip(RoundedCornerShape(22.dp)) + .clickable( + interactionSource = interactionSource, + indication = null + ) { onClick() }, + color = background, + shape = RoundedCornerShape(22.dp), + border = BorderStroke(1.dp, borderColor) + ) { + Row( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 16.dp, vertical = 14.dp), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(14.dp) + ) { + Surface( + modifier = Modifier.size(44.dp), + shape = RoundedCornerShape(16.dp), + color = Color.White.copy(alpha = 0.06f), + border = BorderStroke(1.dp, Color.White.copy(alpha = 0.18f)) + ) { + Box( + modifier = Modifier + .background(accent) + .clip(RoundedCornerShape(16.dp)), + contentAlignment = Alignment.Center + ) { + Icon( + imageVector = icon, + contentDescription = null, + tint = Color.White + ) + } + } + Column( + verticalArrangement = Arrangement.spacedBy(4.dp), + modifier = Modifier.weight(1f) + ) { + Text( + text = title, + fontSize = 18.sp, + fontWeight = FontWeight.Bold, + color = Color.White + ) + Text( + text = subtitle, + fontSize = 14.sp, + color = PurrfectPalette.textSecondary, + lineHeight = 18.sp + ) + } + if (selected) { + Surface( + modifier = Modifier.size(22.dp), + shape = CircleShape, + color = Color.White.copy(alpha = 0.14f), + border = BorderStroke(1.dp, Color.White.copy(alpha = 0.5f)) + ) { + Box( + modifier = Modifier + .background(accent) + .clip(CircleShape) + ) + } + } else { + Surface( + modifier = Modifier.size(22.dp), + shape = CircleShape, + color = Color.Transparent, + border = BorderStroke(1.dp, Color.White.copy(alpha = 0.2f)) + ) {} + } + } + } + } +} diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/ui/setup/screens/impl/MappingsScreen.kt b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/setup/screens/impl/MappingsScreen.kt similarity index 52% rename from app/src/main/kotlin/me/rhunk/snapenhance/ui/setup/screens/impl/MappingsScreen.kt rename to app/src/main/kotlin/me/eternal/purrfectsnap/ui/setup/screens/impl/MappingsScreen.kt index 4d761cd2..f54d73db 100644 --- a/app/src/main/kotlin/me/rhunk/snapenhance/ui/setup/screens/impl/MappingsScreen.kt +++ b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/setup/screens/impl/MappingsScreen.kt @@ -1,24 +1,40 @@ -package me.rhunk.snapenhance.ui.setup.screens.impl +package me.eternal.purrfectsnap.ui.setup.screens.impl -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size -import androidx.compose.material3.CircularProgressIndicator -import androidx.compose.material3.MaterialTheme -import androidx.compose.runtime.* -import androidx.compose.ui.Modifier -import androidx.compose.ui.unit.dp -import androidx.compose.ui.window.Dialog import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.fadeIn import androidx.compose.animation.fadeOut import androidx.compose.animation.scaleIn import androidx.compose.animation.scaleOut +import androidx.compose.foundation.BorderStroke +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.LinearProgressIndicator +import androidx.compose.material3.Surface +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Brush +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.window.Dialog +import androidx.compose.ui.unit.dp import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import kotlinx.coroutines.withContext -import me.rhunk.snapenhance.ui.setup.screens.SetupScreen -import me.rhunk.snapenhance.ui.util.AlertDialogs -import me.rhunk.snapenhance.ui.util.Motion +import me.eternal.purrfectsnap.ui.manager.theme.PurrfectPalette +import me.eternal.purrfectsnap.ui.setup.screens.SetupScreen +import me.eternal.purrfectsnap.ui.util.AlertDialogs +import me.eternal.purrfectsnap.ui.util.Motion class MappingsScreen : SetupScreen() { @Composable @@ -77,16 +93,43 @@ class MappingsScreen : SetupScreen() { } } - AnimatedVisibility(visible = isGenerating, enter = fadeIn(), exit = fadeOut()) { - androidx.compose.foundation.layout.Column(horizontalAlignment = androidx.compose.ui.Alignment.CenterHorizontally) { - DialogText(text = context.translation["setup.mappings.dialog"]) - CircularProgressIndicator( - modifier = Modifier - .padding() - .size(50.dp), - strokeWidth = 3.dp, - color = MaterialTheme.colorScheme.onPrimary + SetupCard { + StepTitle( + title = context.translation["setup.mappings.dialog"], + subtitle = null + ) + DialogText( + text = "This only takes a moment. Keep the app open while magic happens!" + ) + Spacer(modifier = Modifier.height(12.dp)) + Surface( + shape = RoundedCornerShape(20.dp), + color = Color.White.copy(alpha = 0.05f), + border = BorderStroke( + 1.dp, + Brush.linearGradient( + listOf( + PurrfectPalette.glowPrimary.copy(alpha = 0.48f), + PurrfectPalette.glowSecondary.copy(alpha = 0.36f) + ) + ) ) + ) { + Column( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 16.dp, vertical = 14.dp), + verticalArrangement = Arrangement.spacedBy(16.dp), + horizontalAlignment = Alignment.CenterHorizontally + ) { + LinearProgressIndicator( + modifier = Modifier + .fillMaxWidth() + .height(10.dp), + color = PurrfectPalette.glowPrimary, + trackColor = Color.White.copy(alpha = 0.12f) + ) + } } } } diff --git a/app/src/main/kotlin/me/eternal/purrfectsnap/ui/setup/screens/impl/PatchSnapchatScreen.kt b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/setup/screens/impl/PatchSnapchatScreen.kt new file mode 100644 index 00000000..d20d496e --- /dev/null +++ b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/setup/screens/impl/PatchSnapchatScreen.kt @@ -0,0 +1,584 @@ +package me.eternal.purrfectsnap.ui.setup.screens.impl + +import android.content.Intent +import android.net.Uri +import androidx.compose.animation.AnimatedVisibility +import androidx.compose.animation.core.FastOutSlowInEasing +import androidx.compose.animation.core.RepeatMode +import androidx.compose.animation.core.animateFloat +import androidx.compose.animation.core.infiniteRepeatable +import androidx.compose.animation.core.rememberInfiniteTransition +import androidx.compose.animation.core.tween +import androidx.compose.foundation.BorderStroke +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +import androidx.compose.foundation.interaction.MutableInteractionSource +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.CheckCircle +import androidx.compose.material.icons.filled.Download +import androidx.compose.material.icons.filled.ExpandLess +import androidx.compose.material.icons.filled.ExpandMore +import androidx.compose.material.icons.filled.Info +import androidx.compose.material.icons.filled.Verified +import androidx.compose.material3.Icon +import androidx.compose.material3.LinearProgressIndicator +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Surface +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableFloatStateOf +import androidx.compose.runtime.mutableStateListOf +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.runtime.saveable.rememberSaveable +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.geometry.Offset +import androidx.compose.ui.graphics.Brush +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import androidx.core.content.FileProvider +import java.io.File +import java.util.concurrent.TimeUnit +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.Job +import kotlinx.coroutines.delay +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext +import me.eternal.purrfectsnap.setup.patch.AutoPatchServer +import me.eternal.purrfectsnap.setup.patch.LSPatch +import me.eternal.purrfectsnap.ui.manager.theme.PurrfectPalette +import me.eternal.purrfectsnap.ui.setup.screens.SetupScreen +import me.eternal.purrfectsnap.ui.util.scaleOnPress +import okhttp3.OkHttpClient +import okhttp3.Request + +class PatchSnapchatScreen : SetupScreen() { + private val autoPatchServer = AutoPatchServer() + private val okHttpClient = OkHttpClient.Builder() + .callTimeout(1, TimeUnit.HOURS) + .connectTimeout(1, TimeUnit.HOURS) + .readTimeout(1, TimeUnit.HOURS) + .writeTimeout(1, TimeUnit.HOURS) + .build() + private val targetPackage = "com.snapchat.android" + + @Composable + override fun Content() { + val coroutineScope = rememberCoroutineScope() + val logs = remember { mutableStateListOf("Auto Patcher is ready.") } + var progress by remember { mutableFloatStateOf(-1f) } + var patchedApkPath by rememberSaveable { mutableStateOf(null) } + var downloadedApkPath by rememberSaveable { mutableStateOf(null) } + val patchedApk = remember(patchedApkPath) { patchedApkPath?.let(::File) } + val downloadedApk = remember(downloadedApkPath) { downloadedApkPath?.let(::File) } + var isRunning by remember { mutableStateOf(false) } + var error by remember { mutableStateOf(null) } + var patchStartedAt by rememberSaveable { mutableStateOf(0L) } + var installVerified by rememberSaveable { mutableStateOf(false) } + var installRequested by rememberSaveable { mutableStateOf(false) } + var installWatcher by remember { mutableStateOf(null) } + var downloadFinished by rememberSaveable { mutableStateOf(false) } + val logPulse by rememberInfiniteTransition(label = "logPulse").animateFloat( + initialValue = 0f, + targetValue = 1f, + animationSpec = infiniteRepeatable( + tween(durationMillis = 2200, easing = FastOutSlowInEasing), + RepeatMode.Reverse + ), + label = "logPulseValue" + ) + + LaunchedEffect(Unit) { allowNext(false) } + LaunchedEffect(installVerified) { allowNext(installVerified) } + + fun pushLog(message: String) { + if (logs.size > 16) logs.removeFirst() + logs.add(message) + } + + fun isSnapchatInstalledAfter(timestamp: Long): Boolean { + if (timestamp == 0L) return false + val info = runCatching { + context.androidContext.packageManager.getPackageInfo(targetPackage, 0) + }.getOrNull() ?: return false + return info.lastUpdateTime >= timestamp + } + + fun isSnapchatInstalled(): Boolean { + return runCatching { context.androidContext.packageManager.getPackageInfo(targetPackage, 0) }.isSuccess + } + + fun startInstallWatcher() { + if (patchStartedAt == 0L) return + installWatcher?.cancel() + installWatcher = coroutineScope.launch { + repeat(80) { + if (isSnapchatInstalledAfter(patchStartedAt)) { + installVerified = true + pushLog("Snapchat install confirmed. You're cleared to continue.") + return@launch + } + delay(1200) + } + } + } + + LaunchedEffect(installRequested, patchStartedAt) { + if (installRequested && patchStartedAt > 0) { + startInstallWatcher() + } + } + + LaunchedEffect(patchStartedAt) { + if (patchStartedAt > 0 && isSnapchatInstalledAfter(patchStartedAt)) { + installVerified = true + } + } + + LaunchedEffect(installVerified) { + if (installVerified) { + listOfNotNull(patchedApk, downloadedApk).forEach { runCatching { it.delete() } } + patchedApkPath = null + downloadedApkPath = null + } + } + + suspend fun pushStatus(message: String) = withContext(Dispatchers.Main) { pushLog(message) } + suspend fun setProgress(value: Float) = withContext(Dispatchers.Main) { progress = value } + + suspend fun downloadSnapchatFromAutoPatchServer(): File? = withContext(Dispatchers.IO) { + val latestApk = autoPatchServer.fetchLatestSnapchatApk() ?: return@withContext null + pushStatus("Downloading recommended Snapchat version (${latestApk.tagName})...") + + okHttpClient.newCall(Request.Builder().url(latestApk.downloadUrl).build()).execute().use { response -> + if (!response.isSuccessful) return@withContext null + val cacheDir = context.activity?.externalCacheDir ?: context.androidContext.externalCacheDir + ?: context.androidContext.cacheDir + val outputFile = File(cacheDir, latestApk.apkName) + outputFile.outputStream().use { output -> + response.body?.byteStream()?.use { input -> + val buffer = ByteArray(DEFAULT_BUFFER_SIZE) + var read: Int + var totalRead = 0L + val totalSize = response.body?.contentLength() ?: -1L + while (input.read(buffer).also { read = it } != -1) { + output.write(buffer, 0, read) + totalRead += read + if (totalSize > 0) setProgress(totalRead.toFloat() / totalSize.toFloat()) + } + } ?: return@withContext null + } + setProgress(-1f) + outputFile + } + } + + fun startPatch() { + coroutineScope.launch(Dispatchers.Main) { + isRunning = true + allowNext(false) + error = null + progress = -1f + patchedApkPath = null + downloadedApkPath = null + installVerified = false + installRequested = false + downloadFinished = false + patchStartedAt = System.currentTimeMillis() + logs.clear() + pushLog("Starting Auto Patcher for recommended Snapchat version.") + runCatching { + if (isSnapchatInstalled()) { + pushStatus("Snapchat is installed. Please uninstall it first (don't keep data), then start Auto Patcher again.") + throw IllegalStateException("Snapchat still installed. Uninstall it first, to continue.") + } + val modulePath = context.androidContext.packageManager.getPackageInfo( + context.androidContext.packageName, 0 + ).applicationInfo?.sourceDir ?: throw IllegalStateException("Module apk not found") + pushStatus("Fetching recommended Snapchat APK...") + val downloaded = downloadSnapchatFromAutoPatchServer() + ?: throw IllegalStateException("Download failed") + downloadedApkPath = downloaded.absolutePath + pushStatus("Download completed: ${downloaded.name}") + downloadFinished = true + pushStatus("Starting patch powered by Jingmatrix Lspatch") + val lsPatch = LSPatch( + context.androidContext, + mapOf(context.androidContext.packageName to File(modulePath)), + obfuscate = false, + printLog = { pushLog("[LSPatch] $it") } + ) + val outputs = withContext(Dispatchers.IO) { lsPatch.patchSplits(listOf(downloaded)) } + val patched = outputs["base.apk"] ?: outputs.values.firstOrNull() + ?: throw IllegalStateException("Patched apk not produced") + patchedApkPath = patched.absolutePath + pushStatus("Patched build ready. Install to finish.") + }.onFailure { + error = it.message ?: it.toString() + pushStatus("Failed: ${it.message}") + } + isRunning = false + progress = -1f + } + } + + fun installPatchedApk() { + val apk = patchedApk ?: return + installRequested = true + startInstallWatcher() + val uri = FileProvider.getUriForFile( + context.androidContext, + "${context.androidContext.packageName}.fileprovider", + apk + ) + val intent = Intent(Intent.ACTION_VIEW).apply { + setDataAndType(uri, "application/vnd.android.package-archive") + addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_GRANT_READ_URI_PERMISSION) + } + context.androidContext.startActivity(intent) + } + + fun markAlreadyInstalled() { + installRequested = false + installVerified = true + pushLog("Marked as installed manually. You're cleared to continue.") + } + + val accent = remember { + Brush.linearGradient( + listOf( + PurrfectPalette.glowSecondary, + PurrfectPalette.glowPrimary + ) + ) + } + + SetupCard { + StepTitle( + title = "Auto Patcher", + subtitle = null, + modifier = Modifier.align(Alignment.CenterHorizontally), + textAlign = TextAlign.Center + ) + JingmatrixBadge(accent) + Surface( + modifier = Modifier.fillMaxWidth(), + shape = RoundedCornerShape(24.dp), + color = Color.White.copy(alpha = 0.03f), + tonalElevation = 0.dp, + border = BorderStroke( + 1.dp, + Brush.linearGradient( + listOf( + PurrfectPalette.glowPrimary.copy(alpha = 0.4f), + PurrfectPalette.glowSecondary.copy(alpha = 0.35f) + ) + ) + ) + ) { + Column( + modifier = Modifier + .background(PurrfectPalette.cardOverlay) + .padding(horizontal = 18.dp, vertical = 16.dp), + verticalArrangement = Arrangement.spacedBy(16.dp) + ) { + AnimatedVisibility(visible = isRunning || progress >= 0f) { + Column( + modifier = Modifier.fillMaxWidth(), + verticalArrangement = Arrangement.spacedBy(8.dp) + ) { + Text( + text = if (progress >= 0f) { + "Downloading Snapchat ${(progress * 100).toInt()}%" + } else if (isRunning && downloadFinished) { + "Patching..." + } else { + "Initializing..." + }, + color = PurrfectPalette.textPrimary, + fontWeight = FontWeight.Medium + ) + LinearProgressIndicator( + progress = if (progress >= 0f) progress.coerceIn(0f, 1f) else 0f, + color = PurrfectPalette.glowPrimary, + trackColor = Color.White.copy(alpha = 0.12f), + modifier = Modifier + .fillMaxWidth() + .height(8.dp) + .clip(RoundedCornerShape(12.dp)) + ) + } + } + + LogsPanel( + logs = logs, + pulse = logPulse, + accent = accent + ) + + error?.let { + Text( + text = it, + color = MaterialTheme.colorScheme.error, + fontWeight = FontWeight.SemiBold + ) + } + + Column( + modifier = Modifier.fillMaxWidth(), + verticalArrangement = Arrangement.spacedBy(12.dp) + ) { + if (installVerified) { + Surface( + shape = RoundedCornerShape(14.dp), + color = Color.White.copy(alpha = 0.06f), + border = BorderStroke(1.dp, Color.White.copy(alpha = 0.18f)) + ) { + Row( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 14.dp, vertical = 12.dp), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(10.dp) + ) { + Icon( + imageVector = Icons.Filled.CheckCircle, + contentDescription = null, + tint = Color.White + ) + Text( + text = "Patched APK installed", + color = Color.White, + fontWeight = FontWeight.SemiBold + ) + } + } + } else { + if (patchedApk == null) { + GradientActionButton( + label = "Start auto patch", + icon = Icons.Filled.Download, + onClick = { startPatch() }, + enabled = !isRunning + ) + } + if (patchedApk != null) { + GradientActionButton( + label = "Install patched Snapchat", + icon = Icons.Filled.Verified, + onClick = { installPatchedApk() }, + enabled = true + ) + val manualInteraction = remember { MutableInteractionSource() } + Surface( + shape = RoundedCornerShape(14.dp), + color = Color.White.copy(alpha = 0.04f), + border = BorderStroke(1.dp, Color.White.copy(alpha = 0.14f)), + modifier = Modifier + .fillMaxWidth() + .scaleOnPress(manualInteraction) + .clickable( + interactionSource = manualInteraction, + indication = null + ) { markAlreadyInstalled() } + ) { + Row( + modifier = Modifier.padding(horizontal = 14.dp, vertical = 12.dp), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(10.dp) + ) { + Icon( + imageVector = Icons.Filled.Info, + contentDescription = null, + tint = Color.White.copy(alpha = 0.9f) + ) + Text( + text = "Already Installed?", + color = Color.White, + fontWeight = FontWeight.SemiBold + ) + } + } + } + } + } + } + } + } + } +} + +@Composable +private fun JingmatrixBadge(accent: Brush) { + Surface( + shape = RoundedCornerShape(18.dp), + color = Color.White.copy(alpha = 0.06f), + border = BorderStroke(1.dp, Color.White.copy(alpha = 0.22f)) + ) { + Row( + modifier = Modifier + .padding(horizontal = 14.dp, vertical = 10.dp), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(8.dp) + ) { + Box( + modifier = Modifier + .size(28.dp) + .clip(CircleShape) + .background(accent) + ) { + Icon( + imageVector = Icons.Filled.Info, + contentDescription = null, + tint = Color.White, + modifier = Modifier.align(Alignment.Center) + ) + } + Text( + text = "Powered by Jingmatrix Lspatch", + color = Color.White, + fontWeight = FontWeight.SemiBold + ) + } + } +} + +@Composable +private fun GradientActionButton( + label: String, + icon: ImageVector, + onClick: () -> Unit, + enabled: Boolean, + modifier: Modifier = Modifier +) { + val interaction = remember { MutableInteractionSource() } + val gradient = Brush.horizontalGradient(listOf(PurrfectPalette.glowSecondary, PurrfectPalette.glowPrimary)) + Surface( + modifier = modifier + .fillMaxWidth() + .clip(RoundedCornerShape(16.dp)) + .background(Color.Transparent) + .scaleOnPress(interaction) + .clickable( + enabled = enabled, + interactionSource = interaction, + indication = null, + onClick = onClick + ), + tonalElevation = 0.dp, + color = Color.Transparent, + border = BorderStroke(1.dp, Color.White.copy(alpha = 0.14f)) + ) { + Box( + modifier = Modifier + .background(if (enabled) gradient else Brush.horizontalGradient(listOf(Color.White.copy(alpha = 0.08f), Color.White.copy(alpha = 0.08f)))) + .padding(vertical = 14.dp, horizontal = 16.dp) + .clip(RoundedCornerShape(16.dp)) + ) { + Row( + modifier = Modifier.align(Alignment.CenterStart), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(10.dp) + ) { + Icon( + imageVector = icon, + contentDescription = null, + tint = Color.White + ) + Text( + text = label, + color = Color.White, + fontWeight = FontWeight.SemiBold, + fontSize = 16.sp + ) + } + } + } +} + +@Composable +private fun LogsPanel( + logs: List, + pulse: Float, + accent: Brush +) { + var expanded by rememberSaveable { mutableStateOf(false) } + val animatedBrush = Brush.linearGradient( + colors = listOf( + PurrfectPalette.glowPrimary.copy(alpha = 0.18f + 0.1f * pulse), + Color.Transparent, + PurrfectPalette.glowSecondary.copy(alpha = 0.12f + 0.1f * (1 - pulse)) + ), + start = Offset.Zero, + end = Offset(400f * (0.6f + pulse), 260f * (0.4f + (1 - pulse))) + ) + Surface( + modifier = Modifier.fillMaxWidth(), + shape = RoundedCornerShape(18.dp), + color = Color.White.copy(alpha = 0.03f), + border = BorderStroke(1.dp, Color.White.copy(alpha = 0.12f)) + ) { + Column( + modifier = Modifier + .background(animatedBrush) + .background(Color.Black.copy(alpha = 0.25f)) + .padding(horizontal = 14.dp, vertical = 12.dp), + verticalArrangement = Arrangement.spacedBy(6.dp) + ) { + Row( + modifier = Modifier + .fillMaxWidth() + .clickable { expanded = !expanded }, + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.CenterVertically + ) { + Text( + text = "Logs", + color = Color.White, + fontWeight = FontWeight.Bold + ) + Icon( + imageVector = if (expanded) Icons.Filled.ExpandLess else Icons.Filled.ExpandMore, + contentDescription = null, + tint = Color.White + ) + } + AnimatedVisibility(visible = expanded) { + Column(verticalArrangement = Arrangement.spacedBy(4.dp)) { + logs.forEach { line -> + Text( + text = "- $line", + color = PurrfectPalette.textPrimary, + fontSize = 13.sp, + lineHeight = 16.sp + ) + } + } + } + } + } +} + + + + diff --git a/app/src/main/kotlin/me/eternal/purrfectsnap/ui/setup/screens/impl/PermissionsScreen.kt b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/setup/screens/impl/PermissionsScreen.kt new file mode 100644 index 00000000..21c6867c --- /dev/null +++ b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/setup/screens/impl/PermissionsScreen.kt @@ -0,0 +1,317 @@ +package me.eternal.purrfectsnap.ui.setup.screens.impl + +import android.Manifest +import android.annotation.SuppressLint +import android.app.Activity +import android.content.Context +import android.content.Intent +import android.content.pm.PackageManager +import android.net.Uri +import android.os.Build +import android.os.PowerManager +import android.provider.Settings +import androidx.compose.animation.AnimatedContent +import androidx.compose.animation.fadeIn +import androidx.compose.animation.fadeOut +import androidx.compose.animation.togetherWith +import androidx.compose.animation.core.tween +import androidx.compose.foundation.BorderStroke +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.BatteryFull +import androidx.compose.material.icons.filled.Check +import androidx.compose.material.icons.filled.Layers +import androidx.compose.material.icons.filled.NotificationsActive +import androidx.compose.material3.Button +import androidx.compose.material3.ButtonDefaults +import androidx.compose.material3.Icon +import androidx.compose.material3.Surface +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.mutableStateMapOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Brush +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextOverflow +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import androidx.lifecycle.Lifecycle +import kotlinx.coroutines.delay +import kotlinx.coroutines.launch +import me.eternal.purrfectsnap.ui.manager.theme.PurrfectPalette +import me.eternal.purrfectsnap.ui.setup.screens.SetupScreen +import me.eternal.purrfectsnap.ui.util.ActivityLauncherHelper +import me.eternal.purrfectsnap.ui.util.OnLifecycleEvent +import me.eternal.purrfectsnap.ui.util.scaleOnPress + +data class PermissionData( + val translationKey: String, + val isPermissionGranted: () -> Boolean, + val requestPermission: (PermissionData) -> Unit, +) + +class PermissionsScreen : SetupScreen() { + private lateinit var activityLauncherHelper: ActivityLauncherHelper + + override fun init() { + activityLauncherHelper = ActivityLauncherHelper(context.activity!!) + } + + private fun descriptionFor(key: String): String { + return when (key) { + "notification_access" -> "Alerts you the second downloads finish." + "battery_optimization" -> "Keeps background tasks alive without being killed." + "display_over_other_apps" -> "Enables floating overlays while you are in Snapchat." + else -> "" + } + } + + @Composable + private fun PermissionRow( + label: String, + translationKey: String, + granted: Boolean, + onRequest: () -> Unit + ) { + val accent = if (granted) PurrfectPalette.glowSecondary else PurrfectPalette.glowPrimary + val buttonColors = ButtonDefaults.buttonColors( + containerColor = accent.copy(alpha = 0.28f), + contentColor = Color.White + ) + Surface( + modifier = Modifier.fillMaxWidth(), + shape = RoundedCornerShape(20.dp), + color = Color(0xFF0F1220), + border = BorderStroke(1.dp, accent.copy(alpha = 0.45f)), + tonalElevation = if (granted) 8.dp else 0.dp, + shadowElevation = 8.dp + ) { + Column( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 16.dp, vertical = 14.dp), + verticalArrangement = Arrangement.spacedBy(10.dp) + ) { + Row( + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(12.dp) + ) { + Surface( + shape = RoundedCornerShape(14.dp), + color = accent.copy(alpha = 0.2f), + modifier = Modifier.size(46.dp) + ) { + Box(contentAlignment = Alignment.Center) { + Icon( + imageVector = when (translationKey) { + "battery_optimization" -> Icons.Filled.BatteryFull + "display_over_other_apps" -> Icons.Filled.Layers + else -> Icons.Filled.NotificationsActive + }, + contentDescription = null, + tint = Color.White, + modifier = Modifier.align(Alignment.Center) + ) + } + } + Column( + modifier = Modifier.weight(1f), + verticalArrangement = Arrangement.spacedBy(4.dp) + ) { + Text( + text = label, + fontWeight = FontWeight.SemiBold, + color = Color.White, + fontSize = 16.sp, + maxLines = 1, + overflow = TextOverflow.Ellipsis + ) + val description = descriptionFor(translationKey) + if (description.isNotBlank()) { + Text( + text = description, + fontSize = 12.sp, + color = PurrfectPalette.textSecondary, + lineHeight = 16.sp + ) + } + } + } + AnimatedContent( + targetState = granted, + transitionSpec = { + fadeIn(animationSpec = tween(150)) togetherWith fadeOut(animationSpec = tween(150)) + }, label = "permState" + ) { isGranted -> + if (isGranted) { + Surface( + modifier = Modifier.fillMaxWidth(), + shape = RoundedCornerShape(14.dp), + color = PurrfectPalette.glowSecondary.copy(alpha = 0.18f), + border = BorderStroke(1.dp, PurrfectPalette.glowSecondary.copy(alpha = 0.5f)) + ) { + Row( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 12.dp, vertical = 10.dp), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.Center + ) { + Icon( + imageVector = Icons.Filled.Check, + contentDescription = null, + tint = Color.White, + modifier = Modifier.padding(end = 6.dp) + ) + Text( + text = "Granted", + color = Color.White, + fontWeight = FontWeight.SemiBold + ) + } + } + } else { + val src = remember { androidx.compose.foundation.interaction.MutableInteractionSource() } + Button( + onClick = onRequest, + interactionSource = src, + modifier = Modifier + .fillMaxWidth() + .scaleOnPress(src), + colors = buttonColors + ) { + Text(text = context.translation["setup.permissions.request_button"]) + } + } + } + } + } + } + + @SuppressLint("BatteryLife") + @Composable + override fun Content() { + val coroutineScope = rememberCoroutineScope() + val grantedPermissions = remember { + mutableStateMapOf() + } + val permissions = remember { + listOf( + PermissionData( + translationKey = "notification_access", + isPermissionGranted = { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + context.androidContext.checkSelfPermission(Manifest.permission.POST_NOTIFICATIONS) == PackageManager.PERMISSION_GRANTED + } else { + true + } + }, + requestPermission = { perm -> + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + activityLauncherHelper.requestPermission(Manifest.permission.POST_NOTIFICATIONS) { resultCode, _ -> + coroutineScope.launch { + grantedPermissions[perm.translationKey] = resultCode == Activity.RESULT_OK + } + } + } + } + ), + PermissionData( + translationKey = "battery_optimization", + isPermissionGranted = { + val powerManager = + context.androidContext.getSystemService(Context.POWER_SERVICE) as PowerManager + powerManager.isIgnoringBatteryOptimizations(context.androidContext.packageName) + }, + requestPermission = { perm -> + activityLauncherHelper.launch(Intent().apply { + action = Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS + data = Uri.parse("package:${context.androidContext.packageName}") + }) { resultCode, _ -> + coroutineScope.launch { + grantedPermissions[perm.translationKey] = resultCode == 0 + } + } + } + ), + PermissionData( + translationKey = "display_over_other_apps", + isPermissionGranted = { + Settings.canDrawOverlays(context.androidContext) + }, + requestPermission = { perm -> + activityLauncherHelper.launch(Intent().apply { + action = Settings.ACTION_MANAGE_OVERLAY_PERMISSION + data = Uri.parse("package:${context.androidContext.packageName}") + }) { resultCode, _ -> + coroutineScope.launch { + grantedPermissions[perm.translationKey] = resultCode == 0 + } + } + } + ) + ) + } + + fun updateState() { + permissions.forEach { perm -> + grantedPermissions[perm.translationKey] = perm.isPermissionGranted() + } + if (permissions.all { perm -> grantedPermissions[perm.translationKey] == true }) { + goNext() + } + } + + OnLifecycleEvent { _, event -> + if (event != Lifecycle.Event.ON_RESUME) return@OnLifecycleEvent + coroutineScope.launch { + updateState() + delay(1000) + updateState() + } + } + + LaunchedEffect(Unit) { + updateState() + } + + SetupCard { + StepTitle( + title = context.translation["setup.permissions.dialog"], + subtitle = null + ) + Spacer(modifier = Modifier.height(6.dp)) + Column( + verticalArrangement = Arrangement.spacedBy(12.dp) + ) { + permissions.forEach { perm -> + PermissionRow( + label = context.translation["setup.permissions.${perm.translationKey}"], + translationKey = perm.translationKey, + granted = grantedPermissions[perm.translationKey] == true + ) { + if (perm.isPermissionGranted()) { + grantedPermissions[perm.translationKey] = true + } else { + perm.requestPermission(perm) + } + } + } + } + } + } +} diff --git a/app/src/main/kotlin/me/eternal/purrfectsnap/ui/setup/screens/impl/PickLanguageScreen.kt b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/setup/screens/impl/PickLanguageScreen.kt new file mode 100644 index 00000000..07d0674c --- /dev/null +++ b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/setup/screens/impl/PickLanguageScreen.kt @@ -0,0 +1,266 @@ +package me.eternal.purrfectsnap.ui.setup.screens.impl + +import androidx.compose.animation.AnimatedVisibility +import androidx.compose.animation.fadeIn +import androidx.compose.animation.fadeOut +import androidx.compose.animation.scaleIn +import androidx.compose.animation.scaleOut +import androidx.compose.foundation.BorderStroke +import androidx.compose.foundation.interaction.MutableInteractionSource +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Check +import androidx.compose.material.icons.filled.Language +import androidx.compose.material3.Button +import androidx.compose.material3.ButtonDefaults +import androidx.compose.material3.Surface +import androidx.compose.material3.Text +import androidx.compose.material3.TextButton +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Brush +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextOverflow +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import androidx.compose.ui.window.Dialog +import java.util.Locale +import me.eternal.purrfectsnap.common.bridge.wrapper.LocaleWrapper +import me.eternal.purrfectsnap.ui.manager.theme.PurrfectPalette +import me.eternal.purrfectsnap.ui.setup.screens.SetupScreen +import me.eternal.purrfectsnap.ui.util.Motion +import me.eternal.purrfectsnap.ui.util.ObservableMutableState +import me.eternal.purrfectsnap.ui.util.scaleOnPress + +class PickLanguageScreen : SetupScreen() { + private val availableLocales by lazy { + LocaleWrapper.fetchAvailableLocales(context.androidContext) + } + private lateinit var selectedLocale: ObservableMutableState + private fun getLocaleDisplayName(locale: String): String { + val displayLocale = when (locale) { + "zh-Hans" -> Locale.forLanguageTag("zh-Hans") + "zh_TW" -> Locale.TRADITIONAL_CHINESE + else -> try { + Locale.forLanguageTag(locale.replace('_', '-')) + } catch (e: Exception) { + Locale.getDefault() + } + } + return displayLocale.getDisplayName(Locale.getDefault()) + } + private fun reloadTranslation(selectedLocale: String) { + context.translation.reload(selectedLocale, isSetup = true) + } + private fun setLocale(locale: String) { + with(context) { + config.locale = locale + config.writeConfig() + reloadTranslation(locale) + } + } + override fun onLeave() { + context.config.locale = selectedLocale.value + context.config.writeConfig() + } + override fun init() { + val deviceLocale = Locale.getDefault().toString() + selectedLocale = + ObservableMutableState( + defaultValue = availableLocales.firstOrNull { locale -> locale == deviceLocale } + ?: LocaleWrapper.DEFAULT_LOCALE + ) { _, newValue -> + setLocale(newValue) + }.also { reloadTranslation(it.value) } + } + + @Composable + override fun Content() { + LaunchedEffect(Unit) { allowNext(true) } + val deviceLocale = remember { Locale.getDefault().toString() } + var isDialog by remember { mutableStateOf(false) } + + fun select(locale: String) { + selectedLocale.value = locale + isDialog = false + } + + SetupCard { + StepTitle( + title = context.translation["setup.dialogs.select_language"], + subtitle = null, + modifier = Modifier.align(Alignment.CenterHorizontally), + textAlign = TextAlign.Center + ) + Surface( + modifier = Modifier.fillMaxWidth(), + shape = RoundedCornerShape(22.dp), + color = Color.White.copy(alpha = 0.05f), + border = BorderStroke( + 1.dp, + Brush.linearGradient( + listOf( + PurrfectPalette.glowPrimary.copy(alpha = 0.5f), + PurrfectPalette.glowSecondary.copy(alpha = 0.4f) + ) + ) + ) + ) { + Row( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 16.dp, vertical = 14.dp), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(12.dp) + ) { + Surface( + modifier = Modifier.size(38.dp), + shape = RoundedCornerShape(14.dp), + color = PurrfectPalette.glowPrimary.copy(alpha = 0.16f) + ) { + Box(contentAlignment = Alignment.Center) { + androidx.compose.material3.Icon( + imageVector = Icons.Filled.Language, + contentDescription = null, + tint = Color.White, + modifier = Modifier.align(Alignment.Center) + ) + } + } + Column( + verticalArrangement = Arrangement.spacedBy(2.dp), + modifier = Modifier.weight(1f) + ) { + Text( + text = "Current selection", + fontSize = 14.sp, + color = PurrfectPalette.textSecondary + ) + Text( + text = remember(selectedLocale.value) { getLocaleDisplayName(selectedLocale.value) }, + fontSize = 20.sp, + fontWeight = FontWeight.SemiBold, + color = Color.White, + maxLines = 1, + overflow = TextOverflow.Ellipsis + ) + } + } + } + + Spacer(modifier = Modifier.height(12.dp)) + val browseSrc = remember { MutableInteractionSource() } + Button( + onClick = { isDialog = true }, + interactionSource = browseSrc, + modifier = Modifier + .fillMaxWidth() + .scaleOnPress(browseSrc), + colors = ButtonDefaults.buttonColors( + containerColor = PurrfectPalette.glowPrimary.copy(alpha = 0.35f), + contentColor = Color.White + ) + ) { + Text(text = "Browse languages") + } + DialogText(text = "You can change this anytime from PurrfectSnap settings.") + } + + if (isDialog) { + Dialog(onDismissRequest = { isDialog = false }) { + AnimatedVisibility( + visible = true, + enter = fadeIn(animationSpec = Motion.tweenFloatSpec(200)) + scaleIn(animationSpec = Motion.tweenFloatSpec(220)), + exit = fadeOut(animationSpec = Motion.tweenFloatSpec(150)) + scaleOut(animationSpec = Motion.tweenFloatSpec(180)) + ) { + SetupCard( + modifier = Modifier.fillMaxWidth() + ) { + StepTitle( + title = "Available Languages", + subtitle = null, + modifier = Modifier.align(Alignment.CenterHorizontally), + textAlign = TextAlign.Center + ) + LazyColumn( + modifier = Modifier.fillMaxWidth() + ) { + items(availableLocales) { locale -> + val label = remember(locale) { getLocaleDisplayName(locale) } + val isSelected = selectedLocale.value == locale + val rowSrc = remember { MutableInteractionSource() } + Surface( + modifier = Modifier + .fillMaxWidth() + .padding(vertical = 4.dp) + .scaleOnPress(rowSrc), + shape = RoundedCornerShape(18.dp), + color = if (isSelected) PurrfectPalette.glowPrimary.copy(alpha = 0.14f) else Color.White.copy( + alpha = 0.05f + ), + border = BorderStroke( + 1.dp, + if (isSelected) PurrfectPalette.glowPrimary.copy(alpha = 0.55f) else Color.White.copy( + alpha = 0.1f + ) + ), + tonalElevation = if (isSelected) 8.dp else 0.dp, + onClick = { select(locale) } + ) { + Row( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 14.dp, vertical = 12.dp), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.SpaceBetween + ) { + Column(verticalArrangement = Arrangement.spacedBy(2.dp)) { + Text( + text = label, + fontWeight = FontWeight.Medium, + color = Color.White, + maxLines = 1, + overflow = TextOverflow.Ellipsis + ) + Text( + text = locale, + fontSize = 11.sp, + color = PurrfectPalette.textSecondary + ) + } + if (isSelected) { + androidx.compose.material3.Icon( + imageVector = Icons.Filled.Check, + contentDescription = null, + tint = PurrfectPalette.glowSecondary + ) + } + } + } + } + } + } + } + } + } + } +} diff --git a/app/src/main/kotlin/me/eternal/purrfectsnap/ui/setup/screens/impl/SaveFolderScreen.kt b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/setup/screens/impl/SaveFolderScreen.kt new file mode 100644 index 00000000..66589c3b --- /dev/null +++ b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/setup/screens/impl/SaveFolderScreen.kt @@ -0,0 +1,241 @@ +package me.eternal.purrfectsnap.ui.setup.screens.impl + +import androidx.compose.foundation.BorderStroke +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.FolderOpen +import androidx.compose.material3.Button +import androidx.compose.material3.ButtonDefaults +import androidx.compose.material3.Icon +import androidx.compose.material3.OutlinedButton +import androidx.compose.material3.Surface +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Brush +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import androidx.compose.ui.window.Dialog +import me.eternal.purrfectsnap.ui.manager.theme.PurrfectPalette +import me.eternal.purrfectsnap.ui.setup.screens.SetupScreen +import me.eternal.purrfectsnap.ui.util.ActivityLauncherHelper +import me.eternal.purrfectsnap.ui.util.chooseFolder +import me.eternal.purrfectsnap.ui.util.scaleOnPress +import androidx.compose.foundation.interaction.MutableInteractionSource + +class SaveFolderScreen : SetupScreen() { + private lateinit var activityLauncherHelper: ActivityLauncherHelper + + override fun init() { + activityLauncherHelper = ActivityLauncherHelper(context.activity!!) + } + + @Composable + override fun Content() { + var currentFolder by remember { + mutableStateOf(context.config.root.downloader.saveFolder.get().orEmpty()) + } + var showNoPickerDialog by remember { mutableStateOf(false) } + SetupCard { + StepTitle( + title = context.translation["setup.dialogs.save_folder"], + subtitle = null + ) + DialogText(text = "Please choose the location where media should be downloaded to.") + Surface( + modifier = Modifier.fillMaxWidth(), + shape = RoundedCornerShape(22.dp), + color = Color.White.copy(alpha = 0.05f), + border = BorderStroke( + 1.dp, + Brush.linearGradient( + listOf( + PurrfectPalette.glowPrimary.copy(alpha = 0.5f), + PurrfectPalette.glowSecondary.copy(alpha = 0.35f) + ) + ) + ) + ) { + Row( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 16.dp, vertical = 14.dp), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(12.dp) + ) { + Surface( + modifier = Modifier.size(42.dp), + shape = RoundedCornerShape(14.dp), + color = PurrfectPalette.glowPrimary.copy(alpha = 0.18f) + ) { + Box(contentAlignment = Alignment.Center) { + Icon( + imageVector = Icons.Filled.FolderOpen, + contentDescription = null, + tint = Color.White, + modifier = Modifier.align(Alignment.Center) + ) + } + } + Column( + verticalArrangement = Arrangement.spacedBy(2.dp), + modifier = Modifier.weight(1f) + ) { + Text( + text = "Destination", + fontSize = 13.sp, + color = PurrfectPalette.textSecondary + ) + Text( + text = if (currentFolder.isBlank()) "System default" else currentFolder, + fontSize = 15.sp, + fontWeight = FontWeight.SemiBold, + color = Color.White, + maxLines = 2 + ) + } + } + } + Spacer(modifier = Modifier.height(12.dp)) + val src = remember { MutableInteractionSource() } + Button( + onClick = { + activityLauncherHelper.chooseFolder( + onUnavailable = { showNoPickerDialog = true }, + callback = callback@{ uriString -> + if (uriString.isBlank()) { + return@callback + } + currentFolder = uriString + context.config.root.downloader.saveFolder.set(uriString) + context.sharedPreferences.edit().putBoolean("downloader_use_default_save_folder", false).apply() + context.config.writeConfig() + goNext() + } + ) + }, + interactionSource = src, + modifier = Modifier + .fillMaxWidth() + .scaleOnPress(src), + colors = ButtonDefaults.buttonColors( + containerColor = PurrfectPalette.glowPrimary.copy(alpha = 0.32f), + contentColor = Color.White + ) + ) { + Text(text = context.translation["setup.dialogs.select_save_folder_button"]) + } + + if (showNoPickerDialog) { + Dialog(onDismissRequest = { showNoPickerDialog = false }) { + Surface( + shape = RoundedCornerShape(28.dp), + color = Color.Transparent, + tonalElevation = 0.dp, + shadowElevation = 18.dp, + border = BorderStroke( + 1.dp, + Brush.linearGradient( + listOf( + PurrfectPalette.glowPrimary.copy(alpha = 0.55f), + PurrfectPalette.glowSecondary.copy(alpha = 0.35f) + ) + ) + ) + ) { + Column( + modifier = Modifier + .background(PurrfectPalette.cardOverlay) + .padding(horizontal = 20.dp, vertical = 18.dp), + verticalArrangement = Arrangement.spacedBy(14.dp), + horizontalAlignment = Alignment.CenterHorizontally + ) { + Surface( + modifier = Modifier.size(62.dp), + shape = RoundedCornerShape(20.dp), + color = PurrfectPalette.glowSecondary.copy(alpha = 0.18f) + ) { + Box(contentAlignment = Alignment.Center) { + Icon( + imageVector = Icons.Filled.FolderOpen, + contentDescription = null, + tint = Color.White, + modifier = Modifier.size(30.dp) + ) + } + } + Text( + text = "Folder picker unavailable", + fontSize = 18.sp, + fontWeight = FontWeight.ExtraBold, + color = Color.White + ) + Text( + text = "Some cloned/dual-app environments block the system folder picker. You can continue using the system default save location, or open the app outside clone mode to select a custom folder.", + fontSize = 14.sp, + lineHeight = 18.sp, + textAlign = androidx.compose.ui.text.style.TextAlign.Center, + color = PurrfectPalette.textSecondary + ) + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.spacedBy(10.dp), + verticalAlignment = Alignment.CenterVertically + ) { + OutlinedButton( + onClick = { showNoPickerDialog = false }, + modifier = Modifier.weight(1f), + shape = RoundedCornerShape(18.dp), + colors = ButtonDefaults.outlinedButtonColors( + contentColor = Color.White + ), + border = BorderStroke(1.dp, Color.White.copy(alpha = 0.14f)) + ) { + Text("Cancel") + } + Button( + onClick = { + showNoPickerDialog = false + currentFolder = "" + context.config.root.downloader.saveFolder.set("") + context.sharedPreferences.edit().putBoolean("downloader_use_default_save_folder", true).apply() + context.config.writeConfig() + goNext() + }, + modifier = Modifier.weight(1f), + shape = RoundedCornerShape(18.dp), + colors = ButtonDefaults.buttonColors( + containerColor = PurrfectPalette.glowPrimary.copy(alpha = 0.32f), + contentColor = Color.White + ) + ) { + Text("Use default") + } + } + } + } + } + } + DialogText( + text = "PurrfectSnap requires Storage permissions to download and Save Media from Snapchat." + ) + } + } +} diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/ui/util/Accompagnist.kt b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/util/Accompagnist.kt similarity index 98% rename from app/src/main/kotlin/me/rhunk/snapenhance/ui/util/Accompagnist.kt rename to app/src/main/kotlin/me/eternal/purrfectsnap/ui/util/Accompagnist.kt index 0822332b..6c1e554e 100644 --- a/app/src/main/kotlin/me/rhunk/snapenhance/ui/util/Accompagnist.kt +++ b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/util/Accompagnist.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.ui.util +package me.eternal.purrfectsnap.ui.util import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.pager.PagerState diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/ui/util/ActivityLauncherHelper.kt b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/util/ActivityLauncherHelper.kt similarity index 65% rename from app/src/main/kotlin/me/rhunk/snapenhance/ui/util/ActivityLauncherHelper.kt rename to app/src/main/kotlin/me/eternal/purrfectsnap/ui/util/ActivityLauncherHelper.kt index c3c71028..3019b841 100644 --- a/app/src/main/kotlin/me/rhunk/snapenhance/ui/util/ActivityLauncherHelper.kt +++ b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/util/ActivityLauncherHelper.kt @@ -1,11 +1,12 @@ -package me.rhunk.snapenhance.ui.util +package me.eternal.purrfectsnap.ui.util import android.app.Activity +import android.content.ActivityNotFoundException import android.content.Intent import androidx.activity.ComponentActivity import androidx.activity.result.ActivityResultLauncher import androidx.activity.result.contract.ActivityResultContracts -import me.rhunk.snapenhance.common.logger.AbstractLogger +import me.eternal.purrfectsnap.common.logger.AbstractLogger typealias ActivityLauncherCallback = (resultCode: Int, intent: Intent?) -> Unit @@ -34,11 +35,23 @@ class ActivityLauncherHelper( } fun launch(intent: Intent, callback: ActivityLauncherCallback) { + launch(intent, callback, null) + } + + fun launch(intent: Intent, callback: ActivityLauncherCallback, onFailure: ((Throwable) -> Unit)?) { if (this.callback != null) { throw IllegalStateException("Already launching an activity") } this.callback = callback - activityResultLauncher.launch(intent) + + runCatching { + activityResultLauncher.launch(intent) + }.onFailure { throwable -> + AbstractLogger.directError("Failed to launch intent", throwable) + onFailure?.invoke(throwable) + runCatching { callback(Activity.RESULT_CANCELED, null) } + this.callback = null + } } fun requestPermission(permission: String, callback: ActivityLauncherCallback) { @@ -48,25 +61,42 @@ class ActivityLauncherHelper( this.callback = callback permissionResultLauncher.launch(permission) } + + fun canLaunch(intent: Intent): Boolean = intent.resolveActivity(activity.packageManager) != null } -fun ActivityLauncherHelper.chooseFolder(callback: (uri: String) -> Unit) { +fun ActivityLauncherHelper.chooseFolder(onUnavailable: (() -> Unit)? = null, callback: (uri: String) -> Unit) { launch( - Intent(Intent.ACTION_OPEN_DOCUMENT_TREE) + intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE) .addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) .addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION) - ) { resultCode, intent -> - if (resultCode != Activity.RESULT_OK) { - return@launch + .addFlags(Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION) + .addFlags(Intent.FLAG_GRANT_PREFIX_URI_PERMISSION), + callback = { resultCode, intent -> + if (resultCode != Activity.RESULT_OK) { + callback("") + return@launch + } + val uri = intent?.data ?: return@launch + val value = uri.toString() + runCatching { + this.activity.contentResolver.takePersistableUriPermission( + uri, + Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION + ) + callback(value) + }.onFailure { + AbstractLogger.directError("Failed to persist folder permission", it) + callback("") + } + }, + onFailure = { throwable -> + if (throwable is ActivityNotFoundException) { + onUnavailable?.invoke() + } + callback("") } - val uri = intent?.data ?: return@launch - val value = uri.toString() - this.activity.contentResolver.takePersistableUriPermission( - uri, - Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION - ) - callback(value) - } + ) } fun ActivityLauncherHelper.saveFile(name: String, type: String = "*/*", callback: (uri: String) -> Unit) { @@ -106,4 +136,4 @@ fun ActivityLauncherHelper.openFile(type: String = "*/*", callback: (uri: String this.activity.contentResolver.takePersistableUriPermission(uri, Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION) callback(value) } -} \ No newline at end of file +} diff --git a/app/src/main/kotlin/me/eternal/purrfectsnap/ui/util/AlertDialogs.kt b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/util/AlertDialogs.kt new file mode 100644 index 00000000..7e4e80e0 --- /dev/null +++ b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/util/AlertDialogs.kt @@ -0,0 +1,1404 @@ +package me.eternal.purrfectsnap.ui.util + +import android.content.Context +import android.view.MotionEvent +import android.widget.Toast +import androidx.compose.foundation.BorderStroke +import androidx.compose.foundation.ScrollState +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.foundation.text.KeyboardOptions +import androidx.compose.foundation.verticalScroll +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.* +import androidx.compose.material.icons.filled.EditLocationAlt +import androidx.compose.material3.* +import androidx.compose.runtime.* +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.draw.clipToBounds +import androidx.compose.ui.focus.FocusRequester +import androidx.compose.ui.focus.focusRequester +import androidx.compose.ui.graphics.Brush +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.toArgb +import androidx.compose.ui.layout.onGloballyPositioned +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.text.TextRange +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.input.ImeAction +import androidx.compose.ui.text.input.KeyboardType +import androidx.compose.ui.text.input.TextFieldValue +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.text.style.TextOverflow +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import androidx.compose.ui.viewinterop.AndroidView +import androidx.compose.ui.window.Dialog as StandardDialog +import androidx.core.net.toUri +import com.github.skydoves.colorpicker.compose.* +import com.google.gson.JsonParser +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.delay +import kotlinx.coroutines.launch +import me.eternal.purrfectsnap.common.Constants +import me.eternal.purrfectsnap.common.bridge.wrapper.LocaleWrapper +import me.eternal.purrfectsnap.common.config.DataProcessors +import me.eternal.purrfectsnap.common.config.PropertyPair +import me.eternal.purrfectsnap.common.ui.AutoClearKeyboardFocus +import me.eternal.purrfectsnap.common.util.ktx.await +import me.eternal.purrfectsnap.ui.manager.theme.PurrfectPalette +import okhttp3.OkHttpClient +import okhttp3.Request +import org.osmdroid.config.Configuration +import org.osmdroid.tileprovider.tilesource.TileSourceFactory +import org.osmdroid.util.GeoPoint +import org.osmdroid.views.CustomZoomButtonsController +import org.osmdroid.views.MapView +import org.osmdroid.views.overlay.Marker +import org.osmdroid.views.overlay.Overlay +import java.io.File +import me.eternal.purrfectsnap.ui.util.purrfectSwitchColors + + +class AlertDialogs( + private val translation: LocaleWrapper, +){ + @Composable + fun DefaultDialogCard(modifier: Modifier = Modifier, content: @Composable ColumnScope.() -> Unit) { + val scrollState = rememberScrollState() + Surface( + shape = RoundedCornerShape(24.dp), + modifier = Modifier + .padding(horizontal = 18.dp, vertical = 12.dp) + .then(modifier), + color = Color.White.copy(alpha = 0.06f), + tonalElevation = 0.dp, + shadowElevation = 16.dp, + border = BorderStroke( + 1.dp, + Brush.linearGradient( + listOf( + PurrfectPalette.glowPrimary.copy(alpha = 0.55f), + PurrfectPalette.glowSecondary.copy(alpha = 0.45f) + ) + ) + ), + ) { + Box( + modifier = Modifier + .background(PurrfectPalette.cardOverlay) + .fillMaxWidth() + ) { + Column( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 18.dp, vertical = 16.dp) + .verticalScroll(scrollState), + verticalArrangement = Arrangement.spacedBy(14.dp) + ) { content() } + } + } + } + + @Composable + fun ConfirmDialog( + title: String, + message: String? = null, + onConfirm: () -> Unit, + onDismiss: () -> Unit, + ) { + DefaultDialogCard { + Text( + text = title, + fontSize = 21.sp, + fontWeight = FontWeight.ExtraBold, + modifier = Modifier.padding(bottom = 6.dp), + color = PurrfectPalette.textPrimary + ) + if (message != null) { + Text( + text = message, + style = MaterialTheme.typography.bodyMedium, + color = PurrfectPalette.textSecondary, + modifier = Modifier.padding(bottom = 10.dp) + ) + } + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.spacedBy(10.dp, Alignment.End), + ) { + Button( + onClick = { onDismiss() }, + colors = ButtonDefaults.buttonColors( + containerColor = Color.White.copy(alpha = 0.08f), + contentColor = Color.White + ) + ) { + Text(text = translation["button.cancel"]) + } + Button( + onClick = { onConfirm() }, + colors = ButtonDefaults.buttonColors( + containerColor = PurrfectPalette.glowPrimary.copy(alpha = 0.32f), + contentColor = Color.White + ) + ) { + Text(text = translation["button.ok"]) + } + } + } + } + + @Composable + fun InfoDialog( + title: String, + message: String? = null, + onDismiss: () -> Unit, + ) { + DefaultDialogCard { + Text( + text = title, + fontSize = 21.sp, + fontWeight = FontWeight.ExtraBold, + modifier = Modifier.padding(bottom = 6.dp), + color = PurrfectPalette.textPrimary + ) + if (message != null) { + Text( + text = message, + style = MaterialTheme.typography.bodySmall, + color = PurrfectPalette.textSecondary, + modifier = Modifier.padding(bottom = 12.dp) + ) + } + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.End, + ) { + Button( + onClick = { onDismiss() }, + colors = ButtonDefaults.buttonColors( + containerColor = PurrfectPalette.glowPrimary.copy(alpha = 0.28f), + contentColor = Color.White + ) + ) { + Text(text = translation["button.ok"]) + } + } + } + } + + @Composable + fun TranslatedText(property: PropertyPair<*>, key: String, modifier: Modifier = Modifier) { + Text( + text = property.key.propertyOption(translation, key), + modifier = Modifier + .padding(10.dp, 10.dp, 10.dp, 10.dp) + .then(modifier) + ) + } + + @Composable + @Suppress("UNCHECKED_CAST") + fun UniqueSelectionDialog(property: PropertyPair<*>) { + val keys = (property.value.defaultValues as List).toMutableList().apply { + add(0, "null") + } + + var selectedValue by remember { + mutableStateOf(property.value.getNullable()?.toString() ?: "null") + } + + DefaultDialogCard { + keys.forEachIndexed { index, item -> + fun select() { + selectedValue = item + property.value.setAny(if (index == 0) { + null + } else { + item + }) + } + + Row( + modifier = Modifier.clickable { select() }, + verticalAlignment = Alignment.CenterVertically + ) { + TranslatedText( + property = property, + key = item, + modifier = Modifier.weight(1f) + ) + RadioButton( + selected = selectedValue == item, + onClick = { select() }, + colors = RadioButtonDefaults.colors( + selectedColor = PurrfectPalette.glowSecondary, + unselectedColor = Color.White.copy(alpha = 0.6f) + ) + ) + } + } + } + } + + @Composable + fun KeyboardInputDialog(property: PropertyPair<*>, dismiss: () -> Unit = {}) { + val focusRequester = remember { FocusRequester() } + val context = LocalContext.current + + DefaultDialogCard { + var fieldValue by remember { + mutableStateOf(property.value.get().toString().let { + TextFieldValue( + text = it, + selection = TextRange(it.length) + ) + }) + } + + TextField( + modifier = Modifier + .fillMaxWidth() + .padding(all = 10.dp) + .onGloballyPositioned { + focusRequester.requestFocus() + } + .focusRequester(focusRequester), + value = fieldValue, + onValueChange = { fieldValue = it }, + keyboardOptions = when (property.key.dataType.type) { + DataProcessors.Type.INTEGER -> KeyboardOptions(keyboardType = KeyboardType.Number) + DataProcessors.Type.FLOAT -> KeyboardOptions(keyboardType = KeyboardType.Decimal) + else -> KeyboardOptions(keyboardType = KeyboardType.Text) + }, + singleLine = true, + colors = TextFieldDefaults.colors( + focusedContainerColor = Color.White.copy(alpha = 0.08f), + unfocusedContainerColor = Color.White.copy(alpha = 0.05f), + focusedIndicatorColor = Color.Transparent, + unfocusedIndicatorColor = Color.Transparent, + cursorColor = PurrfectPalette.glowSecondary + ) + ) + + Row( + modifier = Modifier + .padding(top = 10.dp) + .fillMaxWidth(), + horizontalArrangement = Arrangement.spacedBy(10.dp, Alignment.End), + ) { + Button( + onClick = { dismiss() }, + colors = ButtonDefaults.buttonColors( + containerColor = Color.White.copy(alpha = 0.08f), + contentColor = Color.White + ) + ) { + Text(text = translation["button.cancel"]) + } + Button( + onClick = { + if (fieldValue.text.isNotEmpty() && property.key.params.inputCheck?.invoke(fieldValue.text) == false) { + Toast.makeText(context, "Invalid input! Make sure you entered a valid value.", Toast.LENGTH_SHORT).show() //TODO: i18n + return@Button + } + + when (property.key.dataType.type) { + DataProcessors.Type.INTEGER -> { + runCatching { + property.value.setAny(fieldValue.text.toInt()) + }.onFailure { + property.value.setAny(0) + } + } + DataProcessors.Type.FLOAT -> { + runCatching { + property.value.setAny(fieldValue.text.toFloat()) + }.onFailure { + property.value.setAny(0f) + } + } + else -> property.value.setAny(fieldValue.text) + } + dismiss() + }, + colors = ButtonDefaults.buttonColors( + containerColor = PurrfectPalette.glowPrimary.copy(alpha = 0.32f), + contentColor = Color.White + ) + ) { + Text(text = translation["button.ok"]) + } + } + } + } + + @Composable + fun RawInputDialog(onDismiss: () -> Unit, onConfirm: (value: String) -> Unit) { + val focusRequester = remember { FocusRequester() } + + DefaultDialogCard { + val fieldValue = remember { + mutableStateOf(TextFieldValue()) + } + + TextField( + modifier = Modifier + .fillMaxWidth() + .padding(all = 10.dp) + .onGloballyPositioned { + focusRequester.requestFocus() + } + .focusRequester(focusRequester), + value = fieldValue.value, + onValueChange = { + fieldValue.value = it + }, + singleLine = true, + colors = TextFieldDefaults.colors( + focusedContainerColor = Color.White.copy(alpha = 0.08f), + unfocusedContainerColor = Color.White.copy(alpha = 0.05f), + focusedIndicatorColor = Color.Transparent, + unfocusedIndicatorColor = Color.Transparent, + cursorColor = PurrfectPalette.glowSecondary + ) + ) + + Row( + modifier = Modifier + .padding(top = 10.dp) + .fillMaxWidth(), + horizontalArrangement = Arrangement.spacedBy(10.dp, Alignment.End), + ) { + Button( + onClick = { onDismiss() }, + colors = ButtonDefaults.buttonColors( + containerColor = Color.White.copy(alpha = 0.08f), + contentColor = Color.White + ) + ) { + Text(text = translation["button.cancel"]) + } + Button( + onClick = { + onConfirm(fieldValue.value.text) + }, + colors = ButtonDefaults.buttonColors( + containerColor = PurrfectPalette.glowPrimary.copy(alpha = 0.32f), + contentColor = Color.White + ) + ) { + Text(text = translation["button.ok"]) + } + } + } + } + + @Composable + @Suppress("UNCHECKED_CAST") + fun MultipleSelectionDialog(property: PropertyPair<*>) { + val defaultItems = property.value.defaultValues as List + val toggledStates = property.value.get() as MutableList + DefaultDialogCard { + defaultItems.forEach { key -> + var state by remember { mutableStateOf(toggledStates.contains(key)) } + + fun toggle(value: Boolean? = null) { + state = value ?: !state + if (state) { + toggledStates.add(key) + } else { + toggledStates.remove(key) + } + } + + Row( + modifier = Modifier.clickable { toggle() }, + verticalAlignment = Alignment.CenterVertically + ) { + TranslatedText( + property = property, + key = key, + modifier = Modifier + .weight(1f) + ) + Switch( + checked = state, + onCheckedChange = { + toggle(it) + }, + colors = purrfectSwitchColors() + ) + } + } + } + } + + @Composable + fun ColorPickerDialog( + initialColor: Color?, + setProperty: (Color?) -> Unit, + dismiss: () -> Unit + ) { + var currentColor by remember { mutableStateOf(initialColor) } + + DefaultDialogCard { + val controller = remember { ColorPickerController().apply { + if (currentColor == null) { + setBrightness(1f, false) + } + } } + var colorHexValue by remember { + mutableStateOf(currentColor?.toArgb()?.let { Integer.toHexString(it) } ?: "") + } + + Box( + modifier = Modifier.fillMaxWidth(), + contentAlignment = Alignment.Center, + ) { + TextField( + value = colorHexValue, + onValueChange = { value -> + colorHexValue = value + runCatching { + currentColor = Color(android.graphics.Color.parseColor("#$value")).also { + controller.selectByColor(it, true) + setProperty(it) + } + }.onFailure { + currentColor = null + } + }, + label = { Text(text = "Hex Color") }, + modifier = Modifier + .fillMaxWidth() + .padding(10.dp), + singleLine = true, + colors = TextFieldDefaults.colors( + unfocusedContainerColor = Color.Transparent, + focusedContainerColor = Color.Transparent, + ) + ) + } + HsvColorPicker( + modifier = Modifier + .fillMaxWidth() + .height(300.dp) + .padding(10.dp), + initialColor = remember { currentColor }, + controller = controller, + onColorChanged = { + if (!it.fromUser) return@HsvColorPicker + currentColor = it.color + colorHexValue = Integer.toHexString(it.color.toArgb()) + setProperty(it.color) + } + ) + AlphaSlider( + modifier = Modifier + .fillMaxWidth() + .padding(10.dp) + .height(35.dp), + initialColor = remember { currentColor }, + controller = controller, + ) + BrightnessSlider( + modifier = Modifier + .fillMaxWidth() + .padding(10.dp) + .height(35.dp), + initialColor = remember { currentColor }, + controller = controller, + ) + Row( + modifier = Modifier + .fillMaxWidth() + .padding(5.dp), + horizontalArrangement = Arrangement.SpaceEvenly, + verticalAlignment = Alignment.CenterVertically, + ) { + AlphaTile( + modifier = Modifier + .size(80.dp) + .clip(RoundedCornerShape(6.dp)), + controller = controller + ) + IconButton(onClick = { + setProperty(null) + dismiss() + }) { + Icon( + modifier = Modifier.size(60.dp), + imageVector = Icons.Filled.DeleteOutline, + contentDescription = null + ) + } + } + } + } + + @Composable + fun ColorPickerPropertyDialog( + property: PropertyPair<*>, + dismiss: () -> Unit = {}, + ) { + var currentColor by remember { + mutableStateOf((property.value.getNullable() as? Int)?.let { Color(it) }) + } + + ColorPickerDialog( + initialColor = currentColor, + setProperty = setProperty@{ + currentColor = it + property.value.setAny(it?.toArgb()) + if (it == null) { + property.value.setAny(property.value.defaultValues?.firstOrNull() ?: return@setProperty) + } + }, + dismiss = dismiss + ) + } + + @Composable + fun ChooseLocationDialog( + property: PropertyPair<*>, + marker: MutableState = remember { mutableStateOf(null) }, + mapView: MutableState = remember { mutableStateOf(null) }, + saveCoordinates: (() -> Unit)? = null, + dismiss: () -> Unit = {} + ) { + val betterLocationTranslation = remember { translation.getCategory("manager.sections.better_location") } + val coordinates = remember { + (property.value.get() as Pair<*, *>).let { + it.first.toString().toDouble() to it.second.toString().toDouble() + } + } + val context = LocalContext.current + + mapView.value = remember { + Configuration.getInstance().apply { + osmdroidBasePath = File(context.cacheDir, "osmdroid") + load(context, context.getSharedPreferences("osmdroid", Context.MODE_PRIVATE)) + } + MapView(context).apply { + setMultiTouchControls(true) + zoomController.setVisibility(CustomZoomButtonsController.Visibility.NEVER) + setTileSource(TileSourceFactory.MAPNIK) + + val startPoint = GeoPoint(coordinates.first, coordinates.second) + controller.setZoom(10.0) + controller.setCenter(startPoint) + + marker.value = Marker(this).apply { + isDraggable = true + position = startPoint + setAnchor(Marker.ANCHOR_CENTER, Marker.ANCHOR_BOTTOM) + } + + overlays.add(object: Overlay() { + override fun onSingleTapConfirmed(e: MotionEvent, mapView: MapView): Boolean { + marker.value?.position = mapView.projection.fromPixels(e.x.toInt(), e.y.toInt()) as GeoPoint + mapView.invalidate() + return true + } + }) + + overlays.add(marker.value) + } + } + + DisposableEffect(Unit) { + onDispose { + mapView.value?.onDetach() + } + } + + var customCoordinatesDialog by remember { mutableStateOf(false) } + + + val coroutineScope = rememberCoroutineScope { Dispatchers.IO } + val okHttpClient by lazy { OkHttpClient() } + + Surface( + modifier = Modifier + .fillMaxWidth() + .clipToBounds() + .fillMaxHeight(fraction = 0.9f), + shape = RoundedCornerShape(26.dp), + color = Color.White.copy(alpha = 0.04f), + border = BorderStroke( + 1.dp, + Brush.linearGradient( + listOf( + PurrfectPalette.glowPrimary.copy(alpha = 0.5f), + PurrfectPalette.glowSecondary.copy(alpha = 0.45f) + ) + ) + ) + ) { + Box( + modifier = Modifier + .clip(RoundedCornerShape(26.dp)) + .background(PurrfectPalette.cardOverlay) + ) { + AndroidView( + factory = { mapView.value!! }, + modifier = Modifier.matchParentSize() + ) + Column( + modifier = Modifier + .align(Alignment.TopCenter) + .fillMaxWidth() + .padding(horizontal = 12.dp, vertical = 12.dp), + verticalArrangement = Arrangement.spacedBy(10.dp) + ) { + var locationName by remember { mutableStateOf("") } + var addressResults by remember { mutableStateOf>>(emptyList()) } + var searchJob by remember { mutableStateOf(null) } + val resultsScrollState = rememberScrollState() + + suspend fun search() { + okHttpClient.newCall(Request.Builder() + .url("https://nominatim.openstreetmap.org/search".toUri().buildUpon().appendQueryParameter("q", locationName).appendQueryParameter("format", "jsonv2").build().toString()) + .header("User-Agent", Constants.USER_AGENT) + .build() + ).await().use { response -> + if (!response.isSuccessful) { + return@use + } + + runCatching { + val body = JsonParser.parseString(response.body?.string() ?: "[]").asJsonArray + addressResults = body.take(5).map { jsonElement -> + val jsonObject = jsonElement.asJsonObject + Triple( + jsonObject.get("display_name").asString, + jsonObject.get("lat").asString, + jsonObject.get("lon").asString + ) + } + } + } + + searchJob = null + } + + Surface( + shape = RoundedCornerShape(18.dp), + color = Color(0xFF0F1024).copy(alpha = 0.9f), + tonalElevation = 0.dp, + shadowElevation = 12.dp, + border = BorderStroke( + 1.dp, + Brush.linearGradient( + listOf( + PurrfectPalette.glowPrimary.copy(alpha = 0.55f), + PurrfectPalette.glowSecondary.copy(alpha = 0.45f) + ) + ) + ), + modifier = Modifier.fillMaxWidth() + ) { + Box( + modifier = Modifier + .clip(RoundedCornerShape(18.dp)) + .background( + Brush.verticalGradient( + colors = listOf( + Color(0xFF2A2452).copy(alpha = 0.9f), + Color(0xFF1A143A).copy(alpha = 0.7f) + ) + ) + ) + ) { + Row( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 14.dp, vertical = 12.dp), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.SpaceBetween + ) { + Row( + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(10.dp) + ) { + Box( + modifier = Modifier + .size(38.dp) + .clip(RoundedCornerShape(12.dp)) + .background(Color.White.copy(alpha = 0.08f)), + contentAlignment = Alignment.Center + ) { + Icon( + imageVector = Icons.Filled.Explore, + contentDescription = null, + tint = PurrfectPalette.glowSecondary + ) + } + Column { + Text( + text = betterLocationTranslation["choose_location_button"], + fontSize = 16.sp, + fontWeight = FontWeight.ExtraBold, + color = Color.White + ) + Text( + text = "Search or tap on the map", + fontSize = 12.sp, + color = PurrfectPalette.textSecondary + ) + } + } + FilledIconButton( + onClick = dismiss, + colors = IconButtonDefaults.filledIconButtonColors( + containerColor = Color.White.copy(alpha = 0.12f), + contentColor = Color.White + ) + ) { + Icon( + imageVector = Icons.Default.Close, + contentDescription = translation["button.cancel"] + ) + } + } + } + } + + Surface( + shape = RoundedCornerShape(18.dp), + color = Color(0xFF0F1024).copy(alpha = 0.92f), + border = BorderStroke( + 1.dp, + Brush.linearGradient( + listOf( + PurrfectPalette.glowPrimary.copy(alpha = 0.4f), + PurrfectPalette.glowSecondary.copy(alpha = 0.35f) + ) + ) + ), + modifier = Modifier.fillMaxWidth() + ) { + OutlinedTextField( + modifier = Modifier + .fillMaxWidth(), + value = locationName, + onValueChange = { + locationName = it.replace("\n", "") + if (locationName == "") { + addressResults = emptyList() + searchJob?.cancel() + searchJob = null + return@OutlinedTextField + } + searchJob?.cancel() + searchJob = coroutineScope.launch { + delay(300) + search() + } + }, + placeholder = { Text(text = "Search location...") }, + leadingIcon = { + Icon( + imageVector = Icons.Filled.Search, + contentDescription = "Search", + tint = Color.White + ) + }, + trailingIcon = { + if (locationName.isNotEmpty()) { + IconButton(onClick = { + locationName = "" + addressResults = emptyList() + searchJob?.cancel() + searchJob = null + }) { + Icon( + imageVector = Icons.Filled.Clear, + contentDescription = "Clear", + tint = Color.White + ) + } + } + }, + singleLine = true, + keyboardOptions = KeyboardOptions(imeAction = ImeAction.Search), + shape = RoundedCornerShape(14.dp), + colors = OutlinedTextFieldDefaults.colors( + focusedContainerColor = Color(0xFF0F1024).copy(alpha = 0.96f), + unfocusedContainerColor = Color(0xFF0F1024).copy(alpha = 0.88f), + focusedBorderColor = PurrfectPalette.glowSecondary, + unfocusedBorderColor = Color.White.copy(alpha = 0.35f), + cursorColor = PurrfectPalette.glowSecondary, + focusedTextColor = Color.White, + unfocusedTextColor = Color.White, + focusedPlaceholderColor = PurrfectPalette.textSecondary, + unfocusedPlaceholderColor = PurrfectPalette.textSecondary + ) + ) + } + + AutoClearKeyboardFocus(onFocusClear = { + locationName = "" + addressResults = emptyList() + searchJob?.cancel() + searchJob = null + }) + + if (addressResults.isNotEmpty() || searchJob?.isActive == true) { + Surface( + modifier = Modifier.fillMaxWidth(), + shape = RoundedCornerShape(16.dp), + color = Color.Transparent, + border = BorderStroke( + 1.dp, + Brush.linearGradient( + listOf( + PurrfectPalette.glowPrimary.copy(alpha = 0.4f), + PurrfectPalette.glowSecondary.copy(alpha = 0.35f) + ) + ) + ) + ) { + Column( + modifier = Modifier + .fillMaxWidth() + .clip(RoundedCornerShape(16.dp)) + .background(PurrfectPalette.cardOverlay) + .verticalScroll(resultsScrollState), + ) { + if (addressResults.isNotEmpty()) { + addressResults.forEachIndexed { index, address -> + Row( + modifier = Modifier + .fillMaxWidth() + .clickable { + marker.value?.position = GeoPoint(address.second.toDouble(), address.third.toDouble()) + mapView.value?.controller?.setCenter(marker.value?.position) + mapView.value?.invalidate() + locationName = "" + addressResults = emptyList() + } + .padding(horizontal = 16.dp, vertical = 12.dp), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(10.dp) + ) { + Icon( + imageVector = Icons.Filled.LocationOn, + contentDescription = "Location", + tint = PurrfectPalette.glowSecondary, + modifier = Modifier.size(20.dp) + ) + Text( + text = address.first, + style = MaterialTheme.typography.bodyMedium, + modifier = Modifier.weight(1f), + maxLines = 2, + overflow = TextOverflow.Ellipsis, + color = Color.White + ) + } + if (index < addressResults.size - 1) { + HorizontalDivider( + color = Color.White.copy(alpha = 0.2f), + thickness = 0.5.dp, + modifier = Modifier.padding(horizontal = 16.dp) + ) + } + } + } else if (searchJob?.isActive == true) { + Row( + modifier = Modifier + .fillMaxWidth() + .padding(20.dp), + horizontalArrangement = Arrangement.Center, + verticalAlignment = Alignment.CenterVertically + ) { + CircularProgressIndicator( + modifier = Modifier.size(20.dp), + strokeWidth = 2.dp, + color = PurrfectPalette.glowSecondary + ) + Spacer(modifier = Modifier.width(12.dp)) + Text( + text = "Searching...", + style = MaterialTheme.typography.bodyMedium, + color = Color.White + ) + } + } + } + } + } + } + + + Surface( + modifier = Modifier + .align(Alignment.BottomCenter) + .padding(horizontal = 14.dp, vertical = 12.dp), + shape = RoundedCornerShape(20.dp), + color = Color.Transparent, + tonalElevation = 0.dp, + shadowElevation = 16.dp, + border = BorderStroke( + 1.dp, + Brush.linearGradient( + listOf( + PurrfectPalette.glowPrimary.copy(alpha = 0.38f), + PurrfectPalette.glowSecondary.copy(alpha = 0.32f) + ) + ) + ) + ) { + Row( + modifier = Modifier + .clip(RoundedCornerShape(20.dp)) + .background( + Brush.horizontalGradient( + listOf( + Color(0xFF241E46).copy(alpha = 0.92f), + Color(0xFF1B1638).copy(alpha = 0.8f) + ) + ) + ) + .padding(horizontal = 12.dp, vertical = 10.dp), + horizontalArrangement = Arrangement.spacedBy(12.dp), + verticalAlignment = Alignment.CenterVertically + ) { + FilledIconButton( + onClick = { + val lat = marker.value?.position?.latitude ?: coordinates.first + val lon = marker.value?.position?.longitude ?: coordinates.second + property.value.setAny(lat to lon) + dismiss() + }, + colors = IconButtonDefaults.filledIconButtonColors( + containerColor = PurrfectPalette.glowSecondary.copy(alpha = 0.24f), + contentColor = Color.White + ) + ) { + Icon( + modifier = Modifier.size(24.dp), + imageVector = Icons.Filled.Check, + contentDescription = null + ) + } + saveCoordinates?.let { + FilledIconButton( + onClick = { it() }, + colors = IconButtonDefaults.filledIconButtonColors( + containerColor = Color.White.copy(alpha = 0.14f), + contentColor = Color.White + ) + ) { + Icon( + modifier = Modifier.size(24.dp), + imageVector = Icons.Filled.Save, + contentDescription = null + ) + } + } + + FilledIconButton( + onClick = { customCoordinatesDialog = true }, + colors = IconButtonDefaults.filledIconButtonColors( + containerColor = PurrfectPalette.glowPrimary.copy(alpha = 0.24f), + contentColor = Color.White + ) + ) { + Icon( + modifier = Modifier.size(24.dp), + imageVector = Icons.Filled.EditLocationAlt, + contentDescription = null + ) + } + } + } + + if (customCoordinatesDialog) { + val lat = remember { mutableStateOf(coordinates.first.toString()) } + val lon = remember { mutableStateOf(coordinates.second.toString()) } + + Dialog( + onDismissRequest = { + customCoordinatesDialog = false + }, + properties = DialogProperties( + usePlatformDefaultWidth = false + ) + ) { + DefaultDialogCard( + modifier = Modifier.align(Alignment.Center) + ) { + Row( + modifier = Modifier.fillMaxWidth(), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(12.dp) + ) { + Box( + modifier = Modifier + .size(42.dp) + .clip(RoundedCornerShape(14.dp)) + .background(Color.White.copy(alpha = 0.08f)), + contentAlignment = Alignment.Center + ) { + Icon( + imageVector = Icons.Filled.EditLocationAlt, + contentDescription = null, + tint = PurrfectPalette.glowSecondary + ) + } + Column { + Text( + text = betterLocationTranslation["save_coordinates_dialog_title"], + fontSize = 18.sp, + fontWeight = FontWeight.ExtraBold, + color = Color.White + ) + Text( + text = betterLocationTranslation["manual_coordinates_hint"], + fontSize = 12.sp, + color = PurrfectPalette.textSecondary + ) + } + } + OutlinedTextField( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 6.dp), + value = lat.value, + onValueChange = { lat.value = it }, + label = { Text(text = "Latitude") }, + leadingIcon = { Icon(Icons.Filled.MyLocation, contentDescription = null) }, + singleLine = true, + shape = RoundedCornerShape(14.dp), + colors = OutlinedTextFieldDefaults.colors( + focusedContainerColor = Color.White.copy(alpha = 0.12f), + unfocusedContainerColor = Color.White.copy(alpha = 0.08f), + focusedBorderColor = PurrfectPalette.glowSecondary, + unfocusedBorderColor = Color.White.copy(alpha = 0.25f), + cursorColor = PurrfectPalette.glowSecondary, + focusedTextColor = Color.White, + unfocusedTextColor = Color.White + ) + ) + OutlinedTextField( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 6.dp), + value = lon.value, + onValueChange = { lon.value = it }, + label = { Text(text = "Longitude") }, + leadingIcon = { Icon(Icons.Filled.Navigation, contentDescription = null) }, + singleLine = true, + shape = RoundedCornerShape(14.dp), + colors = OutlinedTextFieldDefaults.colors( + focusedContainerColor = Color.White.copy(alpha = 0.12f), + unfocusedContainerColor = Color.White.copy(alpha = 0.08f), + focusedBorderColor = PurrfectPalette.glowSecondary, + unfocusedBorderColor = Color.White.copy(alpha = 0.25f), + cursorColor = PurrfectPalette.glowSecondary, + focusedTextColor = Color.White, + unfocusedTextColor = Color.White + ) + ) + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.spacedBy(10.dp, Alignment.End), + ) { + Button( + onClick = { customCoordinatesDialog = false }, + colors = ButtonDefaults.buttonColors( + containerColor = Color.White.copy(alpha = 0.08f), + contentColor = Color.White + ) + ) { Text(text = translation["button.cancel"]) } + + Button( + onClick = { + marker.value?.position = GeoPoint(lat.value.toDouble(), lon.value.toDouble()) + mapView.value?.controller?.setCenter(marker.value?.position) + mapView.value?.invalidate() + customCoordinatesDialog = false + }, + colors = ButtonDefaults.buttonColors( + containerColor = PurrfectPalette.glowPrimary.copy(alpha = 0.32f), + contentColor = Color.White + ) + ) { Text(text = translation["button.ok"]) } + } + } + } + } + } + } + + } + + @Composable + fun MessageListPropertyDialog(property: PropertyPair<*>, onDismiss: () -> Unit = {}) { + val currentValue = property.value.getNullable()?.toString() ?: "[]" + val propertyName = translation[property.key.propertyName()] + + MessageListManagerDialog( + title = propertyName, + messageListJson = currentValue, + onSave = { newValue -> + property.value.setAny(newValue) + }, + onDismiss = onDismiss + ) + } + + @Composable + fun MessageListManagerDialog( + title: String, + messageListJson: String, + onSave: (String) -> Unit, + onDismiss: () -> Unit, + ) { + var messageList by remember { + mutableStateOf( + try { + val gson = com.google.gson.Gson() + val type = object : com.google.gson.reflect.TypeToken>() {}.type + gson.fromJson(messageListJson, type) ?: listOf() + } catch (e: Exception) { + listOf() + } + ) + } + + var showAddDialog by remember { mutableStateOf(false) } + var editingIndex by remember { mutableStateOf(-1) } + var editingText by remember { mutableStateOf("") } + + DefaultDialogCard { + Column { + Text( + text = title, + fontSize = 20.sp, + fontWeight = FontWeight.Bold, + modifier = Modifier + .fillMaxWidth() + .padding(16.dp), + textAlign = TextAlign.Center + ) + + // Message list + Card( + modifier = Modifier + .fillMaxWidth() + .heightIn(min = 200.dp, max = 400.dp) + .padding(8.dp), + shape = MaterialTheme.shapes.medium + ) { + if (messageList.isEmpty()) { + Box( + modifier = Modifier + .fillMaxSize() + .padding(16.dp), + contentAlignment = Alignment.Center + ) { + Text( + text = translation["auto_reply_messages.dialog.no_messages"], + style = MaterialTheme.typography.bodyMedium, + textAlign = TextAlign.Center, + color = MaterialTheme.colorScheme.onSurfaceVariant + ) + } + } else { + LazyColumn( + modifier = Modifier.fillMaxSize(), + contentPadding = PaddingValues(8.dp) + ) { + items(messageList.size) { index -> + ElevatedCard( + modifier = Modifier + .fillMaxWidth() + .padding(vertical = 4.dp), + shape = MaterialTheme.shapes.small + ) { + Row( + modifier = Modifier + .fillMaxWidth() + .padding(12.dp), + verticalAlignment = Alignment.CenterVertically + ) { + Text( + text = messageList[index], + modifier = Modifier.weight(1f), + style = MaterialTheme.typography.bodyMedium, + maxLines = 2, + overflow = TextOverflow.Ellipsis + ) + + Row( + horizontalArrangement = Arrangement.spacedBy(4.dp) + ) { + IconButton( + onClick = { + editingIndex = index + editingText = messageList[index] + showAddDialog = true + } + ) { + Icon( + Icons.Default.Edit, + contentDescription = "Edit", + tint = MaterialTheme.colorScheme.primary + ) + } + IconButton( + onClick = { + messageList = messageList.toMutableList().apply { + removeAt(index) + } + } + ) { + Icon( + Icons.Default.Delete, + contentDescription = "Delete", + tint = MaterialTheme.colorScheme.error + ) + } + } + } + } + } + } + } + } + + // Add button + Button( + onClick = { + editingIndex = -1 + editingText = "" + showAddDialog = true + }, + modifier = Modifier + .fillMaxWidth() + .padding(8.dp), + colors = ButtonDefaults.buttonColors( + containerColor = MaterialTheme.colorScheme.primary + ) + ) { + Icon( + Icons.Default.Add, + contentDescription = null, + modifier = Modifier.size(18.dp) + ) + Spacer(modifier = Modifier.width(8.dp)) + Text(text = translation["auto_reply_messages.dialog.add_message"]) + } + + // Dialog buttons + Row( + modifier = Modifier + .fillMaxWidth() + .padding(8.dp), + horizontalArrangement = Arrangement.SpaceEvenly + ) { + Button( + onClick = { onDismiss() }, + colors = ButtonDefaults.buttonColors( + containerColor = MaterialTheme.colorScheme.surfaceVariant + ) + ) { + Text(text = translation["button.cancel"]) + } + Button( + onClick = { + val gson = com.google.gson.Gson() + val jsonString = gson.toJson(messageList) + onSave(jsonString) + onDismiss() + } + ) { + Text(text = translation["button.save"]) + } + } + } + } + + // Add/Edit message dialog + if (showAddDialog) { + Dialog( + onDismissRequest = { showAddDialog = false }, + properties = DialogProperties( + usePlatformDefaultWidth = false + ) + ) { + DefaultDialogCard { + Text( + text = if (editingIndex == -1) translation["auto_reply_messages.dialog.add_message"] else translation["auto_reply_messages.dialog.edit_message"], + fontSize = 18.sp, + fontWeight = FontWeight.Bold, + modifier = Modifier + .fillMaxWidth() + .padding(16.dp), + textAlign = TextAlign.Center + ) + + TextField( + value = editingText, + onValueChange = { editingText = it }, + label = { Text(translation["auto_reply_messages.dialog.message_label"]) }, + modifier = Modifier + .fillMaxWidth() + .padding(8.dp), + minLines = 2, + maxLines = 4, + placeholder = { Text(translation["auto_reply_messages.dialog.message_placeholder"]) } + ) + + Row( + modifier = Modifier + .fillMaxWidth() + .padding(8.dp), + horizontalArrangement = Arrangement.SpaceEvenly + ) { + Button( + onClick = { showAddDialog = false }, + colors = ButtonDefaults.buttonColors( + containerColor = MaterialTheme.colorScheme.surfaceVariant + ) + ) { + Text(text = translation["button.cancel"]) + } + Button( + onClick = { + if (editingText.isNotBlank()) { + if (editingIndex == -1) { + // Add new message + messageList = messageList.toMutableList().apply { + add(editingText) + } + } else { + // Edit existing message + messageList = messageList.toMutableList().apply { + set(editingIndex, editingText) + } + } + } + showAddDialog = false + }, + enabled = editingText.isNotBlank() + ) { + Text(text = if (editingIndex == -1) translation["auto_reply_messages.dialog.add_message"] else translation["button.save"]) + } + } + } + } + } + } +} diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/ui/util/AndroidDialogCustom.kt b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/util/AndroidDialogCustom.kt similarity index 99% rename from app/src/main/kotlin/me/rhunk/snapenhance/ui/util/AndroidDialogCustom.kt rename to app/src/main/kotlin/me/eternal/purrfectsnap/ui/util/AndroidDialogCustom.kt index 41260fe1..4e267a7e 100644 --- a/app/src/main/kotlin/me/rhunk/snapenhance/ui/util/AndroidDialogCustom.kt +++ b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/util/AndroidDialogCustom.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.ui.util +package me.eternal.purrfectsnap.ui.util import android.annotation.SuppressLint diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/ui/util/Animations.kt b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/util/Animations.kt similarity index 98% rename from app/src/main/kotlin/me/rhunk/snapenhance/ui/util/Animations.kt rename to app/src/main/kotlin/me/eternal/purrfectsnap/ui/util/Animations.kt index ba60bda8..20eeb2df 100644 --- a/app/src/main/kotlin/me/rhunk/snapenhance/ui/util/Animations.kt +++ b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/util/Animations.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.ui.util +package me.eternal.purrfectsnap.ui.util import android.content.Context import android.provider.Settings diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/ui/util/ColorPicker.kt b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/util/ColorPicker.kt similarity index 95% rename from app/src/main/kotlin/me/rhunk/snapenhance/ui/util/ColorPicker.kt rename to app/src/main/kotlin/me/eternal/purrfectsnap/ui/util/ColorPicker.kt index 6b5a5b31..11398331 100644 --- a/app/src/main/kotlin/me/rhunk/snapenhance/ui/util/ColorPicker.kt +++ b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/util/ColorPicker.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.ui.util +package me.eternal.purrfectsnap.ui.util import androidx.compose.foundation.border import androidx.compose.foundation.layout.size diff --git a/app/src/main/kotlin/me/eternal/purrfectsnap/ui/util/GlobalDialogs.kt b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/util/GlobalDialogs.kt new file mode 100644 index 00000000..659c5814 --- /dev/null +++ b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/util/GlobalDialogs.kt @@ -0,0 +1,25 @@ +package me.eternal.purrfectsnap.ui.util + +import androidx.compose.material3.AlertDialog +import androidx.compose.material3.Button +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.mutableStateOf + +var showThankYouDialog = mutableStateOf(false) + +@Composable +fun ThankYouDialog() { + if (showThankYouDialog.value) { + AlertDialog( + onDismissRequest = { showThankYouDialog.value = false }, + title = { Text("Thank You!") }, + text = { Text("The bypass feature has been successfully unlocked.") }, + confirmButton = { + Button(onClick = { showThankYouDialog.value = false }) { + Text("OK") + } + } + ) + } +} diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/ui/util/LifecycleHelper.kt b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/util/LifecycleHelper.kt similarity index 96% rename from app/src/main/kotlin/me/rhunk/snapenhance/ui/util/LifecycleHelper.kt rename to app/src/main/kotlin/me/eternal/purrfectsnap/ui/util/LifecycleHelper.kt index 49389071..821c42ca 100644 --- a/app/src/main/kotlin/me/rhunk/snapenhance/ui/util/LifecycleHelper.kt +++ b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/util/LifecycleHelper.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.ui.util +package me.eternal.purrfectsnap.ui.util import androidx.compose.runtime.Composable import androidx.compose.runtime.DisposableEffect diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/ui/util/ObservableMutableState.kt b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/util/ObservableMutableState.kt similarity index 92% rename from app/src/main/kotlin/me/rhunk/snapenhance/ui/util/ObservableMutableState.kt rename to app/src/main/kotlin/me/eternal/purrfectsnap/ui/util/ObservableMutableState.kt index 73ea1b3c..999e83b5 100644 --- a/app/src/main/kotlin/me/rhunk/snapenhance/ui/util/ObservableMutableState.kt +++ b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/util/ObservableMutableState.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.ui.util +package me.eternal.purrfectsnap.ui.util import androidx.compose.runtime.MutableState diff --git a/app/src/main/kotlin/me/eternal/purrfectsnap/ui/util/PurrfectSwitch.kt b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/util/PurrfectSwitch.kt new file mode 100644 index 00000000..70d368b6 --- /dev/null +++ b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/util/PurrfectSwitch.kt @@ -0,0 +1,21 @@ +package me.eternal.purrfectsnap.ui.util + +import androidx.compose.material3.SwitchColors +import androidx.compose.material3.SwitchDefaults +import androidx.compose.runtime.Composable +import androidx.compose.ui.graphics.Color +import me.eternal.purrfectsnap.ui.manager.theme.PurrfectPalette + +@Composable +fun purrfectSwitchColors(): SwitchColors = SwitchDefaults.colors( + checkedThumbColor = Color.White, + checkedTrackColor = PurrfectPalette.glowSecondary.copy(alpha = 0.55f), + checkedBorderColor = PurrfectPalette.glowSecondary.copy(alpha = 0.5f), + uncheckedThumbColor = Color.White.copy(alpha = 0.7f), + uncheckedTrackColor = Color.White.copy(alpha = 0.25f), + uncheckedBorderColor = Color.White.copy(alpha = 0.3f), + disabledCheckedTrackColor = PurrfectPalette.glowSecondary.copy(alpha = 0.2f), + disabledUncheckedTrackColor = Color.White.copy(alpha = 0.12f), + disabledCheckedThumbColor = Color.White.copy(alpha = 0.5f), + disabledUncheckedThumbColor = Color.White.copy(alpha = 0.35f) +) diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/ui/util/coil/CoilPreviewDecoder.kt b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/util/coil/CoilPreviewDecoder.kt similarity index 82% rename from app/src/main/kotlin/me/rhunk/snapenhance/ui/util/coil/CoilPreviewDecoder.kt rename to app/src/main/kotlin/me/eternal/purrfectsnap/ui/util/coil/CoilPreviewDecoder.kt index aad1e31c..d04702a9 100644 --- a/app/src/main/kotlin/me/rhunk/snapenhance/ui/util/coil/CoilPreviewDecoder.kt +++ b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/util/coil/CoilPreviewDecoder.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.ui.util.coil +package me.eternal.purrfectsnap.ui.util.coil import android.content.res.Resources import android.graphics.Bitmap @@ -6,12 +6,12 @@ import android.graphics.drawable.BitmapDrawable import coil.decode.DecodeResult import coil.decode.Decoder import coil.fetch.SourceResult -import me.rhunk.snapenhance.common.data.FileType -import me.rhunk.snapenhance.common.data.download.MediaEncryptionKeyPair -import me.rhunk.snapenhance.common.data.download.SplitMediaAssetType -import me.rhunk.snapenhance.common.logger.AbstractLogger -import me.rhunk.snapenhance.common.util.snap.MediaDownloaderHelper -import me.rhunk.snapenhance.core.util.media.PreviewUtils +import me.eternal.purrfectsnap.common.data.FileType +import me.eternal.purrfectsnap.common.data.download.MediaEncryptionKeyPair +import me.eternal.purrfectsnap.common.data.download.SplitMediaAssetType +import me.eternal.purrfectsnap.common.logger.AbstractLogger +import me.eternal.purrfectsnap.common.util.snap.MediaDownloaderHelper +import me.eternal.purrfectsnap.core.util.media.PreviewUtils class CoilPreviewDecoder( private val resources: Resources, diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/ui/util/coil/ComposeImageHelper.kt b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/util/coil/ComposeImageHelper.kt similarity index 91% rename from app/src/main/kotlin/me/rhunk/snapenhance/ui/util/coil/ComposeImageHelper.kt rename to app/src/main/kotlin/me/eternal/purrfectsnap/ui/util/coil/ComposeImageHelper.kt index 49ca72f1..0950bc0e 100644 --- a/app/src/main/kotlin/me/rhunk/snapenhance/ui/util/coil/ComposeImageHelper.kt +++ b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/util/coil/ComposeImageHelper.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.ui.util.coil +package me.eternal.purrfectsnap.ui.util.coil import android.content.Context import android.graphics.drawable.ColorDrawable @@ -14,9 +14,9 @@ import androidx.compose.ui.unit.dp import coil.compose.rememberAsyncImagePainter import coil.request.ImageRequest import coil.size.Precision -import me.rhunk.snapenhance.R -import me.rhunk.snapenhance.RemoteSideContext -import me.rhunk.snapenhance.common.data.download.MediaEncryptionKeyPair +import me.eternal.purrfectsnap.R +import me.eternal.purrfectsnap.RemoteSideContext +import me.eternal.purrfectsnap.common.data.download.MediaEncryptionKeyPair @Composable fun BitmojiImage(context: RemoteSideContext, modifier: Modifier = Modifier, size: Int = 48, url: String?) { diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/ui/util/pullrefresh/PullRefresh.kt b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/util/pullrefresh/PullRefresh.kt similarity index 98% rename from app/src/main/kotlin/me/rhunk/snapenhance/ui/util/pullrefresh/PullRefresh.kt rename to app/src/main/kotlin/me/eternal/purrfectsnap/ui/util/pullrefresh/PullRefresh.kt index ddafcfbe..dc4bd51f 100644 --- a/app/src/main/kotlin/me/rhunk/snapenhance/ui/util/pullrefresh/PullRefresh.kt +++ b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/util/pullrefresh/PullRefresh.kt @@ -16,7 +16,7 @@ @file:Suppress("DEPRECATION") -package me.rhunk.snapenhance.ui.util.pullrefresh +package me.eternal.purrfectsnap.ui.util.pullrefresh import androidx.compose.ui.Modifier import androidx.compose.ui.geometry.Offset diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/ui/util/pullrefresh/PullRefreshIndicator.kt b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/util/pullrefresh/PullRefreshIndicator.kt similarity index 99% rename from app/src/main/kotlin/me/rhunk/snapenhance/ui/util/pullrefresh/PullRefreshIndicator.kt rename to app/src/main/kotlin/me/eternal/purrfectsnap/ui/util/pullrefresh/PullRefreshIndicator.kt index 862f215b..2b441e80 100644 --- a/app/src/main/kotlin/me/rhunk/snapenhance/ui/util/pullrefresh/PullRefreshIndicator.kt +++ b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/util/pullrefresh/PullRefreshIndicator.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package me.rhunk.snapenhance.ui.util.pullrefresh +package me.eternal.purrfectsnap.ui.util.pullrefresh import androidx.compose.animation.Crossfade import androidx.compose.animation.core.LinearEasing diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/ui/util/pullrefresh/PullRefreshIndicatorTransform.kt b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/util/pullrefresh/PullRefreshIndicatorTransform.kt similarity index 98% rename from app/src/main/kotlin/me/rhunk/snapenhance/ui/util/pullrefresh/PullRefreshIndicatorTransform.kt rename to app/src/main/kotlin/me/eternal/purrfectsnap/ui/util/pullrefresh/PullRefreshIndicatorTransform.kt index c5398762..115fc6f4 100644 --- a/app/src/main/kotlin/me/rhunk/snapenhance/ui/util/pullrefresh/PullRefreshIndicatorTransform.kt +++ b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/util/pullrefresh/PullRefreshIndicatorTransform.kt @@ -16,7 +16,7 @@ @file:Suppress("DEPRECATION") -package me.rhunk.snapenhance.ui.util.pullrefresh +package me.eternal.purrfectsnap.ui.util.pullrefresh import androidx.compose.animation.core.LinearOutSlowInEasing import androidx.compose.ui.Modifier diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/ui/util/pullrefresh/PullRefreshState.kt b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/util/pullrefresh/PullRefreshState.kt similarity index 99% rename from app/src/main/kotlin/me/rhunk/snapenhance/ui/util/pullrefresh/PullRefreshState.kt rename to app/src/main/kotlin/me/eternal/purrfectsnap/ui/util/pullrefresh/PullRefreshState.kt index 1811f5fe..600bc936 100644 --- a/app/src/main/kotlin/me/rhunk/snapenhance/ui/util/pullrefresh/PullRefreshState.kt +++ b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/util/pullrefresh/PullRefreshState.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package me.rhunk.snapenhance.ui.util.pullrefresh +package me.eternal.purrfectsnap.ui.util.pullrefresh import androidx.compose.animation.core.animate import androidx.compose.foundation.MutatorMutex diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/Navigation.kt b/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/Navigation.kt deleted file mode 100644 index fdb802b3..00000000 --- a/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/Navigation.kt +++ /dev/null @@ -1,580 +0,0 @@ -package me.rhunk.snapenhance.ui.manager - -import androidx.compose.animation.AnimatedVisibility -import androidx.compose.animation.core.animateDpAsState -import androidx.compose.animation.core.animateFloatAsState -import androidx.compose.animation.core.Animatable -import androidx.compose.animation.core.Spring -import androidx.compose.animation.core.spring -import androidx.compose.animation.core.FastOutSlowInEasing -import androidx.compose.animation.core.tween -import androidx.compose.animation.fadeIn -import androidx.compose.animation.fadeOut -import androidx.compose.animation.scaleIn -import androidx.compose.animation.scaleOut -import androidx.compose.animation.slideInHorizontally -import androidx.compose.animation.slideInVertically -import androidx.compose.animation.slideOutHorizontally -import androidx.compose.animation.slideOutVertically -import androidx.compose.foundation.BorderStroke -import androidx.compose.foundation.background -import androidx.compose.foundation.border -import androidx.compose.foundation.gestures.detectDragGestures -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.FlowRow -import androidx.compose.foundation.layout.PaddingValues -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.RowScope -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.fillMaxHeight -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.navigationBarsPadding -import androidx.compose.foundation.layout.offset -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.width -import androidx.compose.foundation.layout.widthIn -import androidx.compose.foundation.layout.wrapContentWidth -import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.itemsIndexed -import androidx.compose.foundation.lazy.rememberLazyListState -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.automirrored.filled.ArrowBack -import androidx.compose.material.icons.filled.Close -import androidx.compose.material.icons.filled.DragHandle -import androidx.compose.material.icons.filled.Tune -import androidx.compose.material3.Button -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.ElevatedCard -import androidx.compose.material3.ExperimentalMaterial3Api -import androidx.compose.material3.Icon -import androidx.compose.material3.IconButton -import androidx.compose.material3.ModalBottomSheet -import androidx.compose.material3.NavigationBar -import androidx.compose.material3.NavigationBarItem -import androidx.compose.material3.NavigationBarItemDefaults -import androidx.compose.material3.OutlinedButton -import androidx.compose.material3.RadioButton -import androidx.compose.material3.AssistChip -import androidx.compose.material3.Surface -import androidx.compose.material3.Text -import androidx.compose.material3.TopAppBar -import androidx.compose.material3.rememberModalBottomSheetState -import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember -import androidx.compose.runtime.setValue -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.clip -import androidx.compose.ui.draw.shadow -import androidx.compose.ui.graphics.Brush -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.graphics.graphicsLayer -import androidx.compose.ui.input.pointer.PointerInputChange -import androidx.compose.ui.input.pointer.pointerInput -import androidx.compose.ui.layout.onGloballyPositioned -import androidx.compose.ui.platform.LocalHapticFeedback -import androidx.compose.ui.text.style.TextAlign -import androidx.compose.ui.text.style.TextOverflow -import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.lerp -import androidx.compose.ui.unit.sp -import androidx.compose.ui.zIndex -import androidx.compose.foundation.ExperimentalFoundationApi -import androidx.compose.foundation.layout.ExperimentalLayoutApi -import androidx.navigation.NavHostController -import androidx.navigation.compose.NavHost -import androidx.navigation.compose.composable -import androidx.navigation.compose.currentBackStackEntryAsState -import androidx.navigation.compose.navigation -import me.rhunk.snapenhance.RemoteSideContext -import kotlin.math.round -import kotlin.math.PI -import kotlin.math.sin - -@OptIn( - ExperimentalMaterial3Api::class, - ExperimentalFoundationApi::class, - ExperimentalLayoutApi::class, - androidx.compose.animation.ExperimentalAnimationApi::class -) -class Navigation( - private val context: RemoteSideContext, - private val navController: NavHostController, - val routes: Routes = Routes(context).also { it.navController = navController } -) { - private val translation by lazy { context.translation.getCategory("manager.navigation") } - var openBottomBarCustomization by mutableStateOf(false) - @Composable - fun TopBar() { - val navBackStackEntry by navController.currentBackStackEntryAsState() - val currentRoute = remember(navBackStackEntry) { routes.getCurrentRoute(navBackStackEntry) } - if (currentRoute?.routeInfo?.hasOwnTopBar == true) return - val canGoBack = remember(navBackStackEntry) { - currentRoute?.let { !it.routeInfo.primary || it.routeInfo.childIds.contains(routes.currentDestination) } == true - } - TopAppBar( - title = { - currentRoute?.apply { - title?.invoke() ?: routeInfo.translatedKey?.value?.let { - Text( - text = it, - maxLines = 1, - overflow = TextOverflow.Ellipsis - ) - } - } - }, - navigationIcon = { - val backButtonAnimation by animateFloatAsState(if (canGoBack) 1f else 0f, label = "backButton") - Box( - modifier = Modifier - .graphicsLayer { alpha = backButtonAnimation } - .width(lerp(0.dp, 48.dp, backButtonAnimation)) - .height(48.dp) - ) { - IconButton(onClick = { if (canGoBack) navController.popBackStack() }) { - Icon(Icons.AutoMirrored.Filled.ArrowBack, contentDescription = null) - } - } - }, - actions = { - currentRoute?.topBarActions?.invoke(this) - if (currentRoute?.routeInfo?.id == routes.settings.routeInfo.id) { - IconButton(onClick = { openBottomBarCustomization = true }) { - Icon(Icons.Filled.Tune, contentDescription = null) - } - } - } - ) - } - @Composable - fun FloatingBottomBar() { - val navBackStackEntry by navController.currentBackStackEntryAsState() - val currentRoute = remember(navBackStackEntry) { routes.getCurrentRoute(navBackStackEntry) } - val availableRoutes = remember { - listOf(routes.tasks, routes.features, routes.home, routes.social, routes.scripting, routes.friendTracker) - } - val availableRouteMap = remember(availableRoutes) { availableRoutes.associateBy { it.routeInfo.id } } - val prefs = remember { context.sharedPreferences } - val defaultOrder = remember { listOf("tasks", "features", "home", "social", "scripts") } - fun loadSelected(): List { - val raw = prefs.getString("manager_nav_tabs", null)?.split(',')?.map { it.trim() }?.filter { it.isNotEmpty() } ?: emptyList() - val cleaned = raw.filter { availableRouteMap.containsKey(it) } - val list = (if (cleaned.isNotEmpty()) cleaned else defaultOrder).distinct() - return list.take(5) - } - var defaultTabId by remember { mutableStateOf(prefs.getString("manager_default_tab", "home") ?: "home") } - fun saveDefault(id: String) { - defaultTabId = id - prefs.edit().putString("manager_default_tab", id).apply() - } - fun saveSelected(ids: List) { - if (defaultTabId !in ids) { - val candidate = when { - "home" in ids -> "home" - ids.isNotEmpty() -> ids.first() - else -> defaultTabId - } - saveDefault(candidate) - } - prefs.edit().putString("manager_nav_tabs", ids.joinToString(",")).apply() - } - var selectedTabIds by remember { mutableStateOf(loadSelected()) } - val selectedRoutes = remember(selectedTabIds) { selectedTabIds.mapNotNull { availableRouteMap[it] } } - Box( - Modifier - .fillMaxWidth() - .padding(start = 16.dp, end = 16.dp, bottom = 8.dp) - .navigationBarsPadding(), - contentAlignment = Alignment.BottomCenter - ) { - val baseItemWidth = 92.dp - val containerPadding = 24.dp - val targetBarWidth = if (selectedRoutes.size < 5) baseItemWidth * selectedRoutes.size.toFloat() + containerPadding else null - val animatedBarWidth by animateDpAsState(targetValue = targetBarWidth ?: 0.dp, label = "barWidth") - Surface( - shape = RoundedCornerShape(24.dp), - color = MaterialTheme.colorScheme.surface, - border = BorderStroke(1.dp, MaterialTheme.colorScheme.primary.copy(alpha = 0.1f)), - modifier = Modifier - .then(if (targetBarWidth != null) Modifier.width(animatedBarWidth) else Modifier.fillMaxWidth()) - .shadow( - elevation = 16.dp, - shape = RoundedCornerShape(24.dp), - spotColor = MaterialTheme.colorScheme.primary, - ambientColor = MaterialTheme.colorScheme.primary.copy(alpha = 0.5f) - ) - ) { - Box(Modifier.fillMaxWidth().height(80.dp)) { - var barWidthPx by remember { mutableStateOf(0f) } - val itemCount = selectedRoutes.size.coerceAtLeast(1) - val density = androidx.compose.ui.platform.LocalDensity.current - val selectedIndex = remember(currentRoute, selectedRoutes) { - val index = selectedRoutes.indexOf(currentRoute) - if (index >= 0) index else null // indexOf returns -1 when not found, replace with null - } - - selectedIndex?.let { // Null check - val itemWidthPx = - remember(barWidthPx, itemCount) { if (itemCount > 0) barWidthPx / itemCount else 0f } - val offsetAnim = remember { Animatable(0f) } - var lastSelectedIndex by remember { mutableStateOf(selectedIndex) } - LaunchedEffect(itemWidthPx) { - if (itemWidthPx > 0f) { - offsetAnim.snapTo(selectedIndex * itemWidthPx) - } - } - LaunchedEffect(selectedIndex, itemWidthPx) { - if (itemWidthPx <= 0f) return@LaunchedEffect - val dist = kotlin.math.abs(selectedIndex - lastSelectedIndex).coerceAtLeast(1) - val damping = when { - dist >= 3 -> 0.65f - dist == 2 -> 0.75f - else -> 0.90f - } - val stiffness = Spring.StiffnessMediumLow - offsetAnim.animateTo( - targetValue = selectedIndex * itemWidthPx, - animationSpec = spring(dampingRatio = damping, stiffness = stiffness) - ) - lastSelectedIndex = selectedIndex - } - val horizontalInset = 8.dp - val indicatorWidth = with(density) { itemWidthPx.toDp() } - horizontalInset * 2 - Box( - modifier = Modifier - .fillMaxSize() - .onGloballyPositioned { barWidthPx = it.size.width.toFloat() } - ) { - val motionProgress = remember { Animatable(1f) } - LaunchedEffect(selectedIndex) { - motionProgress.snapTo(0f) - val dist = kotlin.math.abs(selectedIndex - lastSelectedIndex).coerceAtLeast(1) - val dur = when { - dist >= 3 -> 440 - dist == 2 -> 380 - else -> 320 - } - motionProgress.animateTo( - 1f, - animationSpec = tween(durationMillis = dur, easing = FastOutSlowInEasing) - ) - } - val pulse = sin(PI * motionProgress.value).toFloat() - val distForScale = kotlin.math.abs(selectedIndex - lastSelectedIndex).coerceAtLeast(1) - val scaleXBase = 0.18f - val scaleXExtra = 0.06f - val scaleYBase = 0.06f - val scaleYExtra = 0.02f - val mult = (distForScale - 1).coerceAtLeast(0) - val scaleXAnim = 1f + (scaleXBase + scaleXExtra * mult) * pulse - val scaleYAnim = 1f - (scaleYBase + scaleYExtra * mult) * pulse - if (barWidthPx > 0f && itemCount > 0) { - val offsetX = with(density) { offsetAnim.value.toDp() } + horizontalInset - Box( - modifier = Modifier - .fillMaxHeight() - .width(indicatorWidth.coerceAtLeast(0.dp)) - .offset(x = offsetX) - .padding(vertical = 8.dp) - .graphicsLayer { scaleX = scaleXAnim; scaleY = scaleYAnim } - .clip(RoundedCornerShape(14.dp)) - .background(MaterialTheme.colorScheme.primary.copy(alpha = 0.10f)) - .border( - BorderStroke(1.dp, MaterialTheme.colorScheme.primary.copy(alpha = 0.30f)), - RoundedCornerShape(14.dp) - ) - ) - } - } - } - NavigationBar( - containerColor = Color.Transparent, - tonalElevation = 0.dp, - modifier = Modifier.fillMaxSize() - ) { - selectedRoutes.forEach { route -> - NavigationBarItem( - alwaysShowLabel = true, - icon = { Icon(imageVector = route.routeInfo.icon, contentDescription = null) }, - label = { - val label = context.translation["manager.routes.${route.routeInfo.key.substringBefore("/")}"] - val isLong = label.length > 11 - Text( - text = label, - textAlign = TextAlign.Center, - fontSize = 12.sp, - maxLines = if (isLong) 2 else 1, - overflow = if (isLong) TextOverflow.Ellipsis else TextOverflow.Clip, - softWrap = isLong, - modifier = if (isLong) Modifier.widthIn(max = 80.dp).wrapContentWidth(Alignment.CenterHorizontally) else Modifier.wrapContentWidth(Alignment.CenterHorizontally) - ) - }, - selected = currentRoute == route, - colors = NavigationBarItemDefaults.colors(indicatorColor = Color.Transparent), - onClick = { route.navigateReset() } - ) - } - } - } - } - if (openBottomBarCustomization) { - val sheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true) - ModalBottomSheet(onDismissRequest = { openBottomBarCustomization = false }, sheetState = sheetState) { - Column(Modifier.fillMaxWidth()) { - Box( - modifier = Modifier - .fillMaxWidth() - .height(112.dp) - .clip(RoundedCornerShape(bottomStart = 24.dp, bottomEnd = 24.dp)) - .background( - brush = Brush.linearGradient( - colors = listOf( - MaterialTheme.colorScheme.primary.copy(alpha = 0.16f), - MaterialTheme.colorScheme.tertiary.copy(alpha = 0.2f) - ) - ) - ) - .padding(horizontal = 20.dp, vertical = 16.dp) - ) { - Column(Modifier.fillMaxSize()) { - Text(text = translation["customize_bottom_bar_title"], style = MaterialTheme.typography.titleLarge, color = MaterialTheme.colorScheme.onSurface) - Spacer(Modifier.height(4.dp)) - Text(text = translation["customize_bottom_bar_subtitle"], style = MaterialTheme.typography.labelLarge, color = MaterialTheme.colorScheme.onSurfaceVariant) - } - Box( - modifier = Modifier - .align(Alignment.BottomCenter) - .padding(bottom = 8.dp) - .width(36.dp) - .height(4.dp) - .clip(RoundedCornerShape(50)) - .background(MaterialTheme.colorScheme.onSurface.copy(alpha = 0.2f)) - ) - } - Spacer(Modifier.height(8.dp)) - Text(text = translation["shown_tabs_title"], style = MaterialTheme.typography.titleSmall, modifier = Modifier.padding(horizontal = 16.dp)) - Spacer(Modifier.height(8.dp)) - if (selectedTabIds.isEmpty()) { - Text(text = translation["no_tabs_selected_text"], style = MaterialTheme.typography.bodyMedium, color = MaterialTheme.colorScheme.onSurfaceVariant) - } else { - val haptic = LocalHapticFeedback.current - var draggingId by remember { mutableStateOf(null) } - var dragDelta by remember { mutableStateOf(0f) } - var dragStartIndex by remember { mutableStateOf(-1) } - var rowHeight by remember { mutableStateOf(0) } - val listState = rememberLazyListState() - LazyColumn( - modifier = Modifier - .fillMaxWidth() - .padding(horizontal = 12.dp), - contentPadding = PaddingValues(bottom = 8.dp), - state = listState - ) { - itemsIndexed(selectedTabIds, key = { _, id -> id }) { index, id -> - val route = availableRouteMap[id] ?: return@itemsIndexed - val label = context.translation["manager.routes.${route.routeInfo.key.substringBefore("/")}"] - val isDragging = draggingId == id - ElevatedCard( - modifier = Modifier - .fillMaxWidth() - .padding(bottom = 6.dp) - .animateItem() - .zIndex(if (isDragging) 1f else 0f) - .graphicsLayer { if (isDragging) { scaleX = 1.02f; scaleY = 1.02f } } - .onGloballyPositioned { if (rowHeight == 0) rowHeight = it.size.height } - .pointerInput(id) { - detectDragGestures( - onDragStart = { - draggingId = id - dragStartIndex = selectedTabIds.indexOf(id) - dragDelta = 0f - haptic.performHapticFeedback(androidx.compose.ui.hapticfeedback.HapticFeedbackType.LongPress) - }, - onDrag = { _: PointerInputChange, dragAmount -> - dragDelta += dragAmount.y - if (rowHeight > 0 && dragStartIndex >= 0) { - val currentIndex = selectedTabIds.indexOf(id) - val deltaRows = round(dragDelta / rowHeight.toFloat()).toInt() - val targetIndex = (dragStartIndex + deltaRows).coerceIn(0, selectedTabIds.lastIndex) - if (targetIndex != currentIndex) { - val list = selectedTabIds.toMutableList() - list.removeAt(currentIndex) - list.add(targetIndex, id) - selectedTabIds = list - saveSelected(selectedTabIds) - haptic.performHapticFeedback(androidx.compose.ui.hapticfeedback.HapticFeedbackType.TextHandleMove) - } - } - }, - onDragEnd = { draggingId = null; dragDelta = 0f; dragStartIndex = -1 }, - onDragCancel = { draggingId = null; dragDelta = 0f; dragStartIndex = -1 } - ) - } - ) { - Row( - modifier = Modifier - .padding(10.dp) - .fillMaxWidth(), - verticalAlignment = Alignment.CenterVertically - ) { - Icon(Icons.Filled.DragHandle, contentDescription = null, tint = MaterialTheme.colorScheme.onSurfaceVariant) - Spacer(Modifier.width(8.dp)) - Icon(route.routeInfo.icon, contentDescription = null) - Spacer(Modifier.width(12.dp)) - Text(text = label, modifier = Modifier.weight(1f), maxLines = 1, overflow = TextOverflow.Ellipsis) - val defaultEligible = remember { setOf("tasks","features","home","social","scripts") } - RadioButton(selected = defaultTabId == id, onClick = { if (id in defaultEligible) saveDefault(id) }, enabled = id in defaultEligible) - IconButton( - onClick = { - if (selectedTabIds.size > 1 && id != defaultTabId && id != "home") { - selectedTabIds = selectedTabIds.toMutableList().also { it.removeAt(index) } - saveSelected(selectedTabIds) - } - }, - enabled = id != defaultTabId && id != "home" - ) { Icon(Icons.Filled.Close, contentDescription = null) } - } - } - } - } - } - Spacer(Modifier.height(16.dp)) - Text(text = translation["available_tabs_title"], style = MaterialTheme.typography.titleSmall, modifier = Modifier.padding(horizontal = 16.dp)) - Spacer(Modifier.height(8.dp)) - FlowRow( - modifier = Modifier - .fillMaxWidth() - .padding(horizontal = 12.dp), - horizontalArrangement = Arrangement.spacedBy(6.dp) - ) { - availableRoutes.forEach { route -> - val id = route.routeInfo.id - val already = selectedTabIds.contains(id) - val label = context.translation["manager.routes.${route.routeInfo.key.substringBefore("/")}"] - AnimatedVisibility( - visible = !already && selectedTabIds.size < 5, - enter = scaleIn(tween(160), initialScale = 0.95f) + fadeIn(tween(180)) + slideInVertically(tween(180), initialOffsetY = { it / 3 }), - exit = scaleOut(tween(120)) + fadeOut(tween(120)) + slideOutVertically(tween(120)) - ) { - AssistChip( - onClick = { - if (!already && selectedTabIds.size < 5) { - selectedTabIds = selectedTabIds + id - saveSelected(selectedTabIds) - } - }, - label = { Text(text = label) }, - leadingIcon = { Icon(route.routeInfo.icon, contentDescription = null) }, - enabled = true - ) - } - } - } - Spacer(Modifier.height(20.dp)) - Row( - Modifier - .fillMaxWidth() - .padding(horizontal = 16.dp, vertical = 8.dp), - horizontalArrangement = Arrangement.SpaceBetween - ) { - OutlinedButton(onClick = { - selectedTabIds = defaultOrder - saveSelected(selectedTabIds) - }) { Text(text = translation["reset_button"], style = MaterialTheme.typography.labelLarge) } - Button(onClick = { openBottomBarCustomization = false }) { Text(text = translation["done_button"], style = MaterialTheme.typography.labelLarge) } - } - Spacer(Modifier.height(8.dp)) - } - } - } - } - } - @Composable - fun Fab() { - val navBackStackEntry by navController.currentBackStackEntryAsState() - remember(navBackStackEntry) { routes.getCurrentRoute(navBackStackEntry) }?.floatingActionButton?.invoke() - } - @Composable - fun NavContent(paddingValues: PaddingValues, startDestination: String) { - NavHost( - navController = navController, - startDestination = startDestination, - modifier = Modifier.padding(paddingValues) - ) { - routes.getRoutes().filter { it.parentRoute == null }.forEach { route -> - val children = routes.getRoutes().filter { it.parentRoute == route } - if (children.isEmpty()) { - val isSummaryScreen = route.routeInfo.id == Routes.CONFIG_IMPORT_CONFIRMATION_ROUTE || - route.routeInfo.id == Routes.CONFIG_EXPORT_SUMMARY_ROUTE || - route.routeInfo.id == Routes.FRIEND_TRACKER_CONFIG_EXPORT_ROUTE || - route.routeInfo.id == Routes.FRIEND_TRACKER_CONFIG_IMPORT_ROUTE - val isAddRuleScreen = route.routeInfo.id.startsWith("edit_rule") - val animatedRoutes = setOf("friend_tracker_catalog", "manage_friend_tracker_repos", "manage_script_repos", "manage_repos") - val isAnimatedRoute = animatedRoutes.contains(route.routeInfo.id) - val addRuleEnterAnimation = slideInHorizontally(animationSpec = tween(400)) { it } - val addRuleExitAnimation = slideOutHorizontally(animationSpec = tween(400)) { -it } - val addRulePopEnterAnimation = slideInHorizontally(animationSpec = tween(400)) { -it } - val addRulePopExitAnimation = slideOutHorizontally(animationSpec = tween(400)) { it } - val animatedRouteEnter = slideInHorizontally(animationSpec = tween(400)) { it } - val animatedRouteExit = slideOutHorizontally(animationSpec = tween(400)) { -it } - val animatedRoutePopEnter = slideInHorizontally(animationSpec = tween(400)) { -it } - val animatedRoutePopExit = slideOutHorizontally(animationSpec = tween(400)) { it } - composable( - route.routeInfo.id, - enterTransition = { - when { - isSummaryScreen -> slideInHorizontally { it } - isAddRuleScreen -> addRuleEnterAnimation - isAnimatedRoute -> animatedRouteEnter - else -> fadeIn(tween(100)) - } - }, - exitTransition = { - when { - isSummaryScreen -> slideOutHorizontally { -it } - isAddRuleScreen -> addRuleExitAnimation - isAnimatedRoute -> animatedRouteExit - else -> fadeOut(tween(100)) - } - }, - popEnterTransition = { - when { - isSummaryScreen -> slideInHorizontally { -it } - isAddRuleScreen -> addRulePopEnterAnimation - isAnimatedRoute -> animatedRoutePopEnter - else -> fadeIn(tween(100)) - } - }, - popExitTransition = { - when { - isSummaryScreen -> slideOutHorizontally { it } - isAddRuleScreen -> addRulePopExitAnimation - isAnimatedRoute -> animatedRoutePopExit - else -> fadeOut(tween(100)) - } - } - ) { route.content.invoke(it) } - route.customComposables.invoke(this) - } else { - navigation("main_" + route.routeInfo.id, route.routeInfo.id) { - composable("main_" + route.routeInfo.id) { route.content.invoke(it) } - children.forEach { child -> composable(child.routeInfo.id) { child.content.invoke(it) } } - route.customComposables.invoke(this) - } - } - } - } - } - - @Composable fun FloatingActionButton() = Fab() - @Composable fun Content(paddingValues: PaddingValues, startDestination: String) = NavContent(paddingValues, startDestination) -} \ No newline at end of file diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/components/AestheticDialog.kt b/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/components/AestheticDialog.kt deleted file mode 100644 index 5555af10..00000000 --- a/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/components/AestheticDialog.kt +++ /dev/null @@ -1,83 +0,0 @@ -package me.rhunk.snapenhance.ui.manager.components - -import androidx.compose.animation.AnimatedVisibility -import androidx.compose.animation.fadeIn -import androidx.compose.animation.fadeOut -import androidx.compose.animation.scaleIn -import androidx.compose.animation.scaleOut -import androidx.compose.foundation.layout.* -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material3.* -import androidx.compose.runtime.* -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.vector.ImageVector -import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.text.style.TextAlign -import androidx.compose.ui.unit.dp -import androidx.compose.ui.window.Dialog -import me.rhunk.snapenhance.ui.util.Motion - -@Composable -fun AestheticDialog( - onDismissRequest: () -> Unit, - title: String, - text: String, - icon: ImageVector, - confirmButtonText: String, - onConfirm: () -> Unit, - dismissButtonText: String? = null, - onDismiss: (() -> Unit)? = null -) { - var visible by remember { mutableStateOf(false) } - LaunchedEffect(Unit) { visible = true } - - Dialog(onDismissRequest = onDismissRequest) { - AnimatedVisibility( - visible = visible, - enter = fadeIn(animationSpec = Motion.tweenFloatSpec(180)) + scaleIn(animationSpec = Motion.tweenFloatSpec(220)), - exit = fadeOut(animationSpec = Motion.tweenFloatSpec(150)) + scaleOut(animationSpec = Motion.tweenFloatSpec(180)) - ) { - Card( - shape = RoundedCornerShape(16.dp), - ) { - Column( - modifier = Modifier.padding(24.dp), - horizontalAlignment = Alignment.CenterHorizontally, - verticalArrangement = Arrangement.spacedBy(16.dp) - ) { - Icon( - imageVector = icon, - contentDescription = null, - modifier = Modifier.size(48.dp), - tint = MaterialTheme.colorScheme.primary - ) - Text( - text = title, - style = MaterialTheme.typography.headlineSmall, - fontWeight = FontWeight.Bold, - textAlign = TextAlign.Center - ) - Text( - text = text, - style = MaterialTheme.typography.bodyMedium, - textAlign = TextAlign.Center - ) - Row( - modifier = Modifier.fillMaxWidth(), - horizontalArrangement = Arrangement.spacedBy(8.dp, Alignment.CenterHorizontally) - ) { - if (dismissButtonText != null && onDismiss != null) { - Button(onClick = onDismiss) { - Text(dismissButtonText) - } - } - Button(onClick = onConfirm) { - Text(confirmButtonText) - } - } - } - } - } - } -} diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/FileImportsRoot.kt b/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/FileImportsRoot.kt deleted file mode 100644 index 241721ae..00000000 --- a/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/FileImportsRoot.kt +++ /dev/null @@ -1,156 +0,0 @@ -package me.rhunk.snapenhance.ui.manager.pages - -import android.net.Uri -import android.text.format.Formatter -import androidx.compose.foundation.layout.* -import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.items -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.AttachFile -import androidx.compose.material.icons.filled.DeleteOutline -import androidx.compose.material.icons.filled.Upload -import androidx.compose.material3.ElevatedCard -import androidx.compose.material3.ExtendedFloatingActionButton -import androidx.compose.material3.Icon -import androidx.compose.material3.IconButton -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue -import androidx.compose.runtime.rememberCoroutineScope -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.text.style.TextAlign -import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp -import androidx.documentfile.provider.DocumentFile -import androidx.navigation.NavBackStackEntry -import kotlinx.coroutines.launch -import me.rhunk.snapenhance.common.ui.AsyncUpdateDispatcher -import me.rhunk.snapenhance.common.ui.rememberAsyncMutableState -import me.rhunk.snapenhance.common.ui.rememberAsyncMutableStateList -import me.rhunk.snapenhance.ui.manager.Routes -import me.rhunk.snapenhance.ui.util.ActivityLauncherHelper -import me.rhunk.snapenhance.ui.util.openFile -import java.text.DateFormat - -class FileImportsRoot: Routes.Route() { - private lateinit var activityLauncherHelper: ActivityLauncherHelper - private val reloadDispatcher = AsyncUpdateDispatcher() - - override val init: () -> Unit = { - activityLauncherHelper = ActivityLauncherHelper(context.activity!!) - } - - override val floatingActionButton: @Composable () -> Unit = { - val coroutineScope = rememberCoroutineScope() - Row { - ExtendedFloatingActionButton( - icon = { - Icon(Icons.Default.Upload, contentDescription = null) - }, - text = { - Text(translation["import_file_button"]) - }, - onClick = { - context.coroutineScope.launch { - activityLauncherHelper.openFile { filePath -> - val fileUri = Uri.parse(filePath) - runCatching { - DocumentFile.fromSingleUri(context.activity!!, fileUri)?.let { file -> - if (!file.exists()) { - context.shortToast(translation["file_not_found"]) - return@openFile - } - context.fileHandleManager.importFile(file.name!!) { - context.androidContext.contentResolver.openInputStream(fileUri)?.use { inputStream -> - inputStream.copyTo(this) - } - } - } - }.onFailure { - context.log.error("Failed to import file", it) - context.shortToast(translation.format("file_import_failed", "error" to it.message.toString())) - }.onSuccess { - context.shortToast(translation["file_imported"]) - coroutineScope.launch { - reloadDispatcher.dispatch() - } - } - } - } - }) - } - } - - override val content: @Composable (NavBackStackEntry) -> Unit = { - val files = rememberAsyncMutableStateList(defaultValue = listOf(), updateDispatcher = reloadDispatcher) { - context.fileHandleManager.getStoredFiles() - } - - LazyColumn( - modifier = Modifier - .fillMaxSize() - .padding(2.dp), - verticalArrangement = Arrangement.spacedBy(5.dp), - contentPadding = PaddingValues(bottom = routes.bottomPadding) - ) { - item { - if (files.isEmpty()) { - Text( - text = translation["no_files_hint"], - modifier = Modifier - .padding(8.dp) - .fillMaxWidth(), - textAlign = TextAlign.Center, - fontSize = 18.sp, - fontWeight = FontWeight.Light - ) - } - } - items(files, key = { it }) { file -> - ElevatedCard( - modifier = Modifier - .fillMaxWidth() - .padding(8.dp) - ) { - val fileInfo by rememberAsyncMutableState(defaultValue = null) { - context.fileHandleManager.getFileInfo(file.name) - } - Row( - modifier = Modifier - .padding(8.dp) - .fillMaxWidth(), - verticalAlignment = Alignment.CenterVertically - ) { - Icon(Icons.Default.AttachFile, contentDescription = null, modifier = Modifier.padding(5.dp)) - Column( - modifier = Modifier.weight(1f).padding(8.dp), - ) { - Text(text = file.name, fontWeight = FontWeight.Bold, fontSize = 18.sp, lineHeight = 20.sp) - fileInfo?.let { (size, lastModified) -> - Text(text = "${Formatter.formatFileSize(context.androidContext, size)} - ${DateFormat.getDateTimeInstance().format(lastModified)}", lineHeight = 15.sp) - } - } - - Row( - horizontalArrangement = Arrangement.spacedBy(5.dp) - ) { - IconButton(onClick = { - context.coroutineScope.launch { - if (context.fileHandleManager.deleteFile(file.name)) { - files.remove(file) - } else { - context.shortToast(translation["file_delete_failed"]) - } - } - }) { - Icon(Icons.Default.DeleteOutline, contentDescription = null) - } - } - } - } - } - } - } -} \ No newline at end of file diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/LoggerHistoryRoot.kt b/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/LoggerHistoryRoot.kt deleted file mode 100644 index 79a0713b..00000000 --- a/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/LoggerHistoryRoot.kt +++ /dev/null @@ -1,415 +0,0 @@ -package me.rhunk.snapenhance.ui.manager.pages - -import androidx.compose.foundation.gestures.detectTapGestures -import androidx.compose.foundation.layout.* -import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.items -import androidx.compose.foundation.text.KeyboardActions -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.Close -import androidx.compose.material.icons.filled.Download -import androidx.compose.material.icons.filled.Search -import androidx.compose.material3.* -import androidx.compose.runtime.* -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.focus.FocusRequester -import androidx.compose.ui.focus.focusRequester -import androidx.compose.ui.input.pointer.pointerInput -import androidx.compose.ui.text.font.FontStyle -import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.text.style.TextAlign -import androidx.compose.ui.text.style.TextOverflow -import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp -import androidx.core.net.toUri -import androidx.navigation.NavBackStackEntry -import com.google.gson.JsonParser -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.launch -import kotlinx.coroutines.withContext -import me.rhunk.snapenhance.bridge.DownloadCallback -import me.rhunk.snapenhance.common.bridge.wrapper.ConversationInfo -import me.rhunk.snapenhance.common.bridge.wrapper.LoggedMessage -import me.rhunk.snapenhance.common.bridge.wrapper.LoggerWrapper -import me.rhunk.snapenhance.common.data.ContentType -import me.rhunk.snapenhance.common.data.download.DownloadMetadata -import me.rhunk.snapenhance.common.data.download.DownloadRequest -import me.rhunk.snapenhance.common.data.download.MediaDownloadSource -import me.rhunk.snapenhance.common.data.download.createNewFilePath -import me.rhunk.snapenhance.common.ui.rememberAsyncMutableState -import me.rhunk.snapenhance.common.ui.transparentTextFieldColors -import me.rhunk.snapenhance.common.util.ktx.copyToClipboard -import me.rhunk.snapenhance.common.util.ktx.longHashCode -import me.rhunk.snapenhance.common.util.protobuf.ProtoReader -import me.rhunk.snapenhance.core.features.impl.downloader.decoder.DecodedAttachment -import me.rhunk.snapenhance.core.features.impl.downloader.decoder.MessageDecoder -import me.rhunk.snapenhance.download.DownloadProcessor -import me.rhunk.snapenhance.storage.findFriend -import me.rhunk.snapenhance.ui.manager.Routes -import java.net.URLDecoder -import java.text.DateFormat -import java.util.concurrent.ConcurrentHashMap -import kotlin.math.absoluteValue - - -class LoggerHistoryRoot : Routes.Route() { - override val translation by lazy { context.translation.getCategory("manager.logger_history") } - private lateinit var loggerWrapper: LoggerWrapper - private var selectedConversation by mutableStateOf(null) - private var stringFilter by mutableStateOf("") - private var reverseOrder by mutableStateOf(true) - - private inline fun decodeMessage(message: LoggedMessage, result: (contentType: ContentType, messageReader: ProtoReader, attachments: List) -> Unit) { - runCatching { - val messageObject = JsonParser.parseString(String(message.messageData, Charsets.UTF_8)).asJsonObject - val messageContent = messageObject.getAsJsonObject("mMessageContent") - val messageReader = messageContent.getAsJsonArray("mContent").map { it.asByte }.toByteArray().let { ProtoReader(it) } - result(ContentType.fromMessageContainer(messageReader) ?: ContentType.UNKNOWN, messageReader, MessageDecoder.decode(messageContent)) - }.onFailure { - context.log.error("Failed to decode message", it) - } - } - - private fun downloadAttachment(creationTimestamp: Long, attachment: DecodedAttachment) { - context.shortToast(translation["download_started_toast"]) - val attachmentHash = attachment.mediaUniqueId!!.longHashCode().absoluteValue.toString() - - DownloadProcessor( - remoteSideContext = context, - callback = object: DownloadCallback.Default() { - override fun onSuccess(outputPath: String?) { - context.shortToast(translation.format("download_success_toast", "path" to outputPath.toString())) - } - - override fun onFailure(message: String?, throwable: String?) { - context.shortToast(translation.format("download_failed_toast", "message" to message.toString())) - } - } - ).enqueue( - DownloadRequest( - inputMedias = arrayOf(attachment.createInputMedia()!!) - ), - DownloadMetadata( - mediaIdentifier = attachmentHash, - outputPath = createNewFilePath( - context.config.root, - attachment.mediaUniqueId!!, - MediaDownloadSource.MESSAGE_LOGGER, - attachmentHash, - creationTimestamp - ), - iconUrl = null, - mediaAuthor = null, - downloadSource = MediaDownloadSource.MESSAGE_LOGGER.translate(context.translation), - ) - ) - } - - @OptIn(ExperimentalLayoutApi::class) - @Composable - private fun MessageView(message: LoggedMessage) { - var contentView by remember { mutableStateOf<@Composable () -> Unit>({ - Spacer(modifier = Modifier.height(30.dp)) - }) } - - OutlinedCard( - modifier = Modifier - .padding(2.dp) - .fillMaxWidth() - ) { - Row( - modifier = Modifier - .padding(8.dp) - .fillMaxWidth(), - verticalAlignment = Alignment.CenterVertically - ) { - contentView() - - LaunchedEffect(Unit, message) { - runCatching { - decodeMessage(message) { contentType, messageReader, attachments -> - @Composable - fun ContentHeader() { - val date = remember { DateFormat.getDateTimeInstance().format(message.sendTimestamp) } - Text(translation.format("log_header_format", "username" to message.username, "type" to contentType.toString().lowercase(), "date" to date), modifier = Modifier.padding(end = 4.dp), fontWeight = FontWeight.ExtraLight) - } - - if (contentType == ContentType.CHAT) { - val content = messageReader.getString(2, 1) ?: "[${translation["empty_message"]}]" - contentView = { - Column { - Text(content, modifier = Modifier - .fillMaxWidth() - .pointerInput(Unit) { - detectTapGestures(onLongPress = { - context.androidContext.copyToClipboard(content) - }) - }) - - val edits by rememberAsyncMutableState(defaultValue = emptyList()) { - loggerWrapper.getChatEdits(selectedConversation!!, message.messageId) - } - edits.forEach { messageEdit -> - val date = remember { - DateFormat.getDateTimeInstance().format(messageEdit.timestamp) - } - Text( - modifier = Modifier.pointerInput(Unit) { - detectTapGestures(onLongPress = { - context.androidContext.copyToClipboard(messageEdit.message) - }) - }.fillMaxWidth().padding(start = 4.dp), - text = translation.format("edited_at_text", "message" to messageEdit.message, "date" to date), - fontWeight = FontWeight.Light, - fontStyle = FontStyle.Italic, - fontSize = 12.sp - ) - } - ContentHeader() - } - } - return@runCatching - } - contentView = { - Column column@{ - if (attachments.isEmpty()) return@column - - FlowRow( - modifier = Modifier - .fillMaxWidth() - .padding(2.dp), - horizontalArrangement = Arrangement.spacedBy(4.dp), - ) { - attachments.forEachIndexed { index, attachment -> - ElevatedButton(onClick = { - context.coroutineScope.launch { - runCatching { - downloadAttachment(message.sendTimestamp, attachment) - }.onFailure { - context.log.error("Failed to download attachment", it) - context.shortToast(translation["download_attachment_failed_toast"]) - } - } - }) { - Icon( - imageVector = Icons.Default.Download, - contentDescription = translation["download_button"], - modifier = Modifier.padding(end = 4.dp) - ) - Text(translation.format("chat_attachment", "index" to (index + 1).toString())) - } - } - } - ContentHeader() - } - } - } - }.onFailure { - context.log.error("Failed to parse message", it) - contentView = { - Text(translation["message_parse_failed"]) - } - } - } - } - } - } - - - @OptIn(ExperimentalMaterial3Api::class) - override val content: @Composable (NavBackStackEntry) -> Unit = { navBackStackEntry -> - LaunchedEffect(Unit) { - val uri = navBackStackEntry.arguments?.getString("uri")?.let { - runCatching { - URLDecoder.decode(it, "UTF-8").toUri() - }.getOrNull() - } - loggerWrapper = LoggerWrapper(context.androidContext, uri) - } - - val conversationInfoCache = remember { ConcurrentHashMap() } - - Column { - var expanded by remember { mutableStateOf(false) } - - ExposedDropdownMenuBox( - expanded = expanded, - onExpandedChange = { expanded = it }, - ) { - fun formatConversationInfo(conversationInfo: ConversationInfo?): String? { - if (conversationInfo == null) return null - - return conversationInfo.groupTitle?.let { - translation.format("list_group_format", "name" to it) - } ?: conversationInfo.usernames.takeIf { it.size > 1 }?.let { - translation.format("list_friend_format", "name" to ("(" + it.joinToString(", ") + ")")) - } ?: context.database.findFriend(conversationInfo.conversationId)?.let { - translation.format("list_friend_format", "name" to "(" + (conversationInfo.usernames + listOf(it.mutableUsername)).toSet().joinToString(", ") + ")") - } ?: conversationInfo.usernames.firstOrNull()?.let { - translation.format("list_friend_format", "name" to "($it)") - } - } - - val selectedConversationInfo by rememberAsyncMutableState(defaultValue = null, keys = arrayOf(selectedConversation)) { - selectedConversation?.let { - conversationInfoCache.getOrPut(it) { - formatConversationInfo(loggerWrapper.getConversationInfo(it)) - } - } - } - - OutlinedTextField( - value = selectedConversationInfo ?: translation["select_conversation_placeholder"], - onValueChange = {}, - readOnly = true, - modifier = Modifier - .menuAnchor(MenuAnchorType.PrimaryNotEditable) - .fillMaxWidth() - ) - - val conversations by rememberAsyncMutableState(defaultValue = emptyList()) { - loggerWrapper.getAllConversations().toMutableList() - } - - ExposedDropdownMenu(expanded = expanded, onDismissRequest = { expanded = false }) { - conversations.forEach { conversationId -> - DropdownMenuItem(onClick = { - selectedConversation = conversationId - expanded = false - }, text = { - val conversationInfo by rememberAsyncMutableState(defaultValue = null, keys = arrayOf(conversationId)) { - conversationInfoCache.getOrPut(conversationId) { - formatConversationInfo(loggerWrapper.getConversationInfo(conversationId)) - } - } - - Text( - text = remember(conversationInfo) { conversationInfo ?: conversationId }, - fontWeight = if (conversationId == selectedConversation) FontWeight.Bold else FontWeight.Normal, - overflow = TextOverflow.Ellipsis - ) - }) - } - } - } - - Row( - modifier = Modifier - .fillMaxWidth() - .padding(2.dp), - horizontalArrangement = Arrangement.End - ) { - Row( - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.spacedBy(2.dp), - ) { - Text(translation["reverse_order_checkbox"]) - Checkbox(checked = reverseOrder, onCheckedChange = { - reverseOrder = it - }) - } - } - - var hasReachedEnd by remember(selectedConversation, stringFilter, reverseOrder) { mutableStateOf(false) } - var lastFetchMessageTimestamp by remember(selectedConversation, stringFilter, reverseOrder) { mutableLongStateOf(if (reverseOrder) Long.MAX_VALUE else Long.MIN_VALUE) } - val messages = remember(selectedConversation, stringFilter, reverseOrder) { mutableStateListOf() } - - LazyColumn( - contentPadding = PaddingValues(bottom = routes.bottomPadding) - ) { - items(messages) { message -> - MessageView(message) - } - item { - if (selectedConversation != null) { - if (hasReachedEnd) { - Text(translation["no_more_messages"], modifier = Modifier - .padding(8.dp) - .fillMaxWidth(), textAlign = TextAlign.Center) - } else { - Row( - horizontalArrangement = Arrangement.Center, - modifier = Modifier.fillMaxWidth() - ) { - CircularProgressIndicator( - modifier = Modifier - .height(20.dp) - .padding(8.dp) - ) - } - } - } - LaunchedEffect(Unit, selectedConversation, stringFilter, reverseOrder) { - withContext(Dispatchers.IO) { - val newMessages = loggerWrapper.fetchMessages( - selectedConversation ?: return@withContext, - lastFetchMessageTimestamp, - 30, - reverseOrder - ) { messageData -> - if (stringFilter.isEmpty()) return@fetchMessages true - var isMatch = false - decodeMessage(messageData) { contentType, messageReader, _ -> - if (contentType == ContentType.CHAT) { - val content = messageReader.getString(2, 1) ?: return@decodeMessage - isMatch = content.contains(stringFilter, ignoreCase = true) - } - } - isMatch - } - if (newMessages.isEmpty()) { - hasReachedEnd = true - return@withContext - } - lastFetchMessageTimestamp = newMessages.lastOrNull()?.sendTimestamp ?: return@withContext - withContext(Dispatchers.Main) { - messages.addAll(newMessages) - } - } - } - } - } - } - } - - override val topBarActions: @Composable (RowScope.() -> Unit) = { - val focusRequester = remember { FocusRequester() } - var showSearchTextField by remember { mutableStateOf(false) } - - if (showSearchTextField) { - var searchValue by remember { mutableStateOf("") } - - TextField( - value = searchValue, - onValueChange = { keyword -> - searchValue = keyword - stringFilter = keyword - }, - keyboardActions = KeyboardActions(onDone = { focusRequester.freeFocus() }), - modifier = Modifier - .focusRequester(focusRequester) - .weight(1f, fill = true) - .padding(end = 10.dp) - .height(70.dp), - singleLine = true, - colors = transparentTextFieldColors() - ) - - LaunchedEffect(Unit) { - focusRequester.requestFocus() - } - } - - IconButton(onClick = { - showSearchTextField = !showSearchTextField - stringFilter = "" - }) { - Icon( - imageVector = if (showSearchTextField) Icons.Filled.Close - else Icons.Filled.Search, - contentDescription = translation[if (showSearchTextField) "close_button_description" else "search_button_description"] - ) - } - } -} \ No newline at end of file diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/TasksRootSection.kt b/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/TasksRootSection.kt deleted file mode 100644 index 0c783fa4..00000000 --- a/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/TasksRootSection.kt +++ /dev/null @@ -1,519 +0,0 @@ -package me.rhunk.snapenhance.ui.manager.pages - -import android.content.Intent -import android.graphics.drawable.ColorDrawable -import androidx.compose.foundation.Image -import androidx.compose.foundation.border -import androidx.compose.foundation.clickable -import androidx.compose.foundation.gestures.detectTapGestures -import androidx.compose.foundation.layout.* -import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.items -import androidx.compose.foundation.lazy.rememberLazyListState -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.* -import androidx.compose.material3.* -import androidx.compose.runtime.* -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.clip -import androidx.compose.ui.draw.clipToBounds -import androidx.compose.ui.graphics.StrokeCap -import androidx.compose.ui.graphics.toArgb -import androidx.compose.ui.input.pointer.pointerInput -import androidx.compose.ui.layout.ContentScale -import androidx.compose.ui.unit.dp -import androidx.core.net.toUri -import androidx.documentfile.provider.DocumentFile -import androidx.lifecycle.Lifecycle -import androidx.navigation.NavBackStackEntry -import coil.compose.rememberAsyncImagePainter -import coil.request.ImageRequest -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.launch -import me.rhunk.snapenhance.bridge.DownloadCallback -import me.rhunk.snapenhance.common.data.download.DownloadMetadata -import me.rhunk.snapenhance.common.data.download.MediaDownloadSource -import me.rhunk.snapenhance.common.data.download.createNewFilePath -import me.rhunk.snapenhance.common.ui.TopBarActionButton -import me.rhunk.snapenhance.common.ui.rememberAsyncMutableState -import me.rhunk.snapenhance.common.util.ktx.longHashCode -import me.rhunk.snapenhance.download.DownloadProcessor -import me.rhunk.snapenhance.download.FFMpegProcessor -import me.rhunk.snapenhance.task.* -import me.rhunk.snapenhance.ui.manager.Routes -import me.rhunk.snapenhance.ui.util.OnLifecycleEvent -import me.rhunk.snapenhance.ui.util.coil.cacheKey -import java.io.File -import java.util.UUID -import kotlin.math.absoluteValue - -class TasksRootSection : Routes.Route() { - override val translation by lazy { context.translation.getCategory("manager.sections.tasks") } - private var activeTasks by mutableStateOf(listOf()) - private lateinit var recentTasks: MutableList - private val taskSelection = mutableStateListOf>() - - private fun fetchActiveTasks(scope: CoroutineScope = context.coroutineScope) { - scope.launch(Dispatchers.IO) { - activeTasks = context.taskManager.getActiveTasks().values.sortedByDescending { it.taskId }.toMutableList() - } - } - - private fun mergeSelection(selection: List>) { - val firstTask = selection.first().first - - val taskHash = UUID.randomUUID().toString().longHashCode().absoluteValue.toString(16) - val pendingTask = context.taskManager.createPendingTask( - Task(TaskType.DOWNLOAD, "Merge ${selection.size} files", firstTask.author, taskHash) - ) - pendingTask.status = TaskStatus.RUNNING - fetchActiveTasks() - - context.coroutineScope.launch { - val filesToMerge = mutableListOf() - - selection.forEach { (task, documentFile) -> - val tempFile = File.createTempFile(task.hash, "." + documentFile.name?.substringAfterLast("."), context.androidContext.cacheDir).also { - it.deleteOnExit() - } - - runCatching { - pendingTask.updateProgress("Copying ${documentFile.name}") - context.androidContext.contentResolver.openInputStream(documentFile.uri)?.use { inputStream -> - //copy with progress - val length = documentFile.length().toFloat() - tempFile.outputStream().use { outputStream -> - val buffer = ByteArray(16 * 1024) - var read: Int - while (inputStream.read(buffer).also { read = it } != -1) { - outputStream.write(buffer, 0, read) - pendingTask.updateProgress("Copying ${documentFile.name}", (outputStream.channel.position().toFloat() / length * 100f).toInt()) - } - outputStream.flush() - filesToMerge.add(tempFile) - } - } - }.onFailure { - pendingTask.fail("Failed to copy file $documentFile to $tempFile") - filesToMerge.forEach { it.delete() } - return@launch - } - } - - val mergedFile = File.createTempFile("merged", ".mp4", context.androidContext.cacheDir).also { - it.deleteOnExit() - } - - runCatching { - context.shortToast(translation.format("merge_files_toast", "count" to filesToMerge.size.toString())) - FFMpegProcessor.newFFMpegProcessor(context, pendingTask).execute( - FFMpegProcessor.Request(FFMpegProcessor.Action.MERGE_MEDIA, filesToMerge.map { it.absolutePath }, mergedFile) - ) - DownloadProcessor(context, object: DownloadCallback.Default() { - override fun onSuccess(outputPath: String) { - context.log.verbose("Merged files to $outputPath") - } - }).saveMediaToGallery(pendingTask, mergedFile, DownloadMetadata( - mediaIdentifier = taskHash, - outputPath = createNewFilePath( - context.config.root, - taskHash, - downloadSource = MediaDownloadSource.MERGED, - mediaAuthor = firstTask.author, - creationTimestamp = System.currentTimeMillis() - ), - mediaAuthor = firstTask.author, - downloadSource = MediaDownloadSource.MERGED.translate(context.translation), - iconUrl = null - )) - }.onFailure { - context.log.error("Failed to merge files", it) - pendingTask.fail(it.message ?: "Failed to merge files") - }.onSuccess { - pendingTask.success() - } - filesToMerge.forEach { it.delete() } - mergedFile.delete() - }.also { - pendingTask.addListener(PendingTaskListener(onCancel = { it.cancel() })) - } - } - - override val topBarActions: @Composable (RowScope.() -> Unit) = { - var showConfirmDialog by remember { mutableStateOf(false) } - val coroutineScope = rememberCoroutineScope() - - if (taskSelection.size > 1) { - val canMergeSelection by rememberAsyncMutableState(defaultValue = false, keys = arrayOf(taskSelection.size)) { - taskSelection.all { it.second?.type?.contains("video") == true } - } - - if (canMergeSelection) { - TopBarActionButton( - onClick = { - mergeSelection(taskSelection.toList().also { - taskSelection.clear() - }.map { it.first to it.second!! }) - }, - icon = Icons.Filled.Merge, - text = translation["merge_button"] - ) - } - } - - IconButton(onClick = { - showConfirmDialog = true - }) { - Icon(Icons.Filled.Delete, contentDescription = translation["clear_tasks_description"]) - } - - if (showConfirmDialog) { - var alsoDeleteFiles by remember { mutableStateOf(false) } - - AlertDialog( - onDismissRequest = { showConfirmDialog = false }, - title = { - if (taskSelection.isNotEmpty()) { - Text(translation.format("remove_selected_tasks_confirm", "count" to taskSelection.size.toString())) - } else { - Text(translation["remove_all_tasks_confirm"]) - } - }, - text = { - Column { - if (taskSelection.isNotEmpty()) { - Text(translation["remove_selected_tasks_title"]) - Row ( - modifier = Modifier - .padding(top = 10.dp) - .fillMaxWidth() - .clickable { - alsoDeleteFiles = !alsoDeleteFiles - }, - horizontalArrangement = Arrangement.spacedBy(5.dp), - verticalAlignment = Alignment.CenterVertically - ) { - Checkbox(checked = alsoDeleteFiles, onCheckedChange = { - alsoDeleteFiles = it - }) - Text(translation["delete_files_option"]) - } - } else { - Text(translation["remove_all_tasks_title"]) - } - } - }, - confirmButton = { - Button( - onClick = { - showConfirmDialog = false - if (taskSelection.isNotEmpty()) { - taskSelection.forEach { (task, documentFile) -> - coroutineScope.launch(Dispatchers.IO) { - context.taskManager.removeTask(task) - if (alsoDeleteFiles) { - documentFile?.delete() - } - } - recentTasks.remove(task) - } - activeTasks = activeTasks.filter { task -> !taskSelection.map { it.first }.contains(task.task) } - taskSelection.clear() - } else { - coroutineScope.launch(Dispatchers.IO) { - context.taskManager.clearAllTasks() - } - recentTasks.clear() - activeTasks.forEach { - runCatching { - it.cancel() - }.onFailure { throwable -> - context.log.error("Failed to cancel task $it", throwable) - } - } - activeTasks = listOf() - context.taskManager.getActiveTasks().clear() - } - } - ) { - Text(context.translation["button.positive"]) - } - }, - dismissButton = { - Button( - onClick = { - showConfirmDialog = false - } - ) { - Text(context.translation["button.negative"]) - } - } - ) - } - } - - @Composable - private fun TaskCard(modifier: Modifier, task: Task, pendingTask: PendingTask? = null) { - var taskStatus by remember { mutableStateOf(task.status) } - var taskProgressLabel by remember { mutableStateOf(null) } - var taskProgress by remember { mutableIntStateOf(-1) } - val isSelected by remember { derivedStateOf { taskSelection.any { it.first == task } } } - - var documentFileMimeType by remember { mutableStateOf("") } - var isDocumentFileReadable by remember { mutableStateOf(true) } - val documentFile by rememberAsyncMutableState(defaultValue = null, keys = arrayOf(taskStatus.key)) { - DocumentFile.fromSingleUri(context.androidContext, task.extra?.toUri() ?: return@rememberAsyncMutableState null)?.apply { - documentFileMimeType = type ?: "" - isDocumentFileReadable = canRead() - } - } - - - val listener = remember { PendingTaskListener( - onStateChange = { - taskStatus = it - }, - onProgress = { label, progress -> - taskProgressLabel = label - taskProgress = progress - } - ) } - - LaunchedEffect(Unit) { - pendingTask?.addListener(listener) - } - - DisposableEffect(Unit) { - onDispose { - pendingTask?.removeListener(listener) - } - } - - fun toggleSelection() { - if (isSelected) { - taskSelection.removeIf { it.first == task } - return - } - taskSelection.add(task to documentFile) - } - - fun openFile() { - if (!isDocumentFileReadable || documentFile == null) return - runCatching { - context.androidContext.startActivity(Intent(Intent.ACTION_VIEW).apply { - setDataAndType(documentFile!!.uri, documentFile!!.type) - flags = Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_ACTIVITY_NEW_TASK - }) - }.onFailure { - context.log.error("Failed to open file ${documentFile?.uri}", it) - context.shortToast(translation["failed_to_open_file"]) - } - } - - OutlinedCard(modifier = modifier - .pointerInput(Unit) { - detectTapGestures( - onTap = { - if (taskSelection.isNotEmpty()) { - toggleSelection() - return@detectTapGestures - } - openFile() - }, - onLongPress = { - if (taskSelection.isNotEmpty()) { - openFile() - return@detectTapGestures - } - toggleSelection() - } - ) - } - .let { - if (isSelected) { - it - .border(2.dp, MaterialTheme.colorScheme.primary) - .clip(MaterialTheme.shapes.medium) - } else it - } - ) { - Row( - modifier = Modifier.padding(12.dp), - verticalAlignment = Alignment.CenterVertically - ) { - Box( - modifier = Modifier - .padding(end = 15.dp) - .size(50.dp) - .clipToBounds(), - contentAlignment = Alignment.Center - ) { - var loadFailed by remember { mutableStateOf(false) } - documentFile?.let { - if (taskStatus.isFinalStage() && isDocumentFileReadable && !loadFailed && (documentFileMimeType.contains("image") || documentFileMimeType.contains("video"))) { - Image( - painter = rememberAsyncImagePainter( - model = ImageRequest.Builder(context.androidContext) - .data(it.uri) - .cacheKey(it.uri.toString()) - .placeholder(ColorDrawable(MaterialTheme.colorScheme.surfaceVariant.toArgb())) - .build(), - imageLoader = context.imageLoader, - onError = { loadFailed = true } - ), - contentDescription = null, - contentScale = ContentScale.FillWidth, - modifier = Modifier - .size(50.dp) - .clip(MaterialTheme.shapes.medium) - ) - } else { - when { - !isDocumentFileReadable -> Icon(Icons.Filled.DeleteOutline, contentDescription = translation["file_not_found_icon_description"]) - documentFileMimeType.contains("image") -> Icon(Icons.Filled.Image, contentDescription = translation["image_icon_description"]) - documentFileMimeType.contains("video") -> Icon(Icons.Filled.Videocam, contentDescription = translation["video_icon_description"]) - documentFileMimeType.contains("audio") -> Icon(Icons.Filled.MusicNote, contentDescription = translation["audio_icon_description"]) - else -> Icon(Icons.Filled.FileCopy, contentDescription = translation["file_icon_description"]) - } - } - } ?: run { - when (task.type) { - TaskType.DOWNLOAD -> Icon(Icons.Filled.Download, contentDescription = translation["download_icon_description"]) - TaskType.CHAT_ACTION -> Icon(Icons.Filled.ChatBubble, contentDescription = translation["chat_action_icon_description"]) - } - } - } - Column( - modifier = Modifier.weight(1f), - ) { - Row( - modifier = Modifier.fillMaxWidth(), - verticalAlignment = Alignment.CenterVertically - ) { - Text(task.title, style = MaterialTheme.typography.bodyMedium) - task.author?.takeIf { it != "null" }?.let { - Spacer(modifier = Modifier.width(5.dp)) - Text(it, style = MaterialTheme.typography.bodySmall, color = MaterialTheme.colorScheme.onSurfaceVariant) - } - } - Text(task.hash, style = MaterialTheme.typography.labelSmall) - Column( - modifier = Modifier.padding(top = 5.dp), - verticalArrangement = Arrangement.spacedBy(5.dp) - ) { - if (taskStatus.isFinalStage()) { - if (taskStatus != TaskStatus.SUCCESS) { - val statusKey = "task_status_${taskStatus.name.lowercase()}" - Text(translation.getOrNull(statusKey) ?: "$taskStatus", style = MaterialTheme.typography.bodySmall) - } - } else { - taskProgressLabel?.let { - Text(it, style = MaterialTheme.typography.bodySmall) - } - if (taskProgress != -1) { - LinearProgressIndicator( - progress = { taskProgress.toFloat() / 100f }, - strokeCap = StrokeCap.Round, - ) - } else { - task.extra?.let { - Text(it, style = MaterialTheme.typography.bodySmall) - } - } - } - } - } - - Column { - if (pendingTask != null && !taskStatus.isFinalStage()) { - FilledIconButton(onClick = { - runCatching { - pendingTask.cancel() - }.onFailure { throwable -> - context.log.error("Failed to cancel task $pendingTask", throwable) - } - }) { - Icon(Icons.Filled.Close, contentDescription = translation["cancel_icon_description"]) - } - } else { - when (taskStatus) { - TaskStatus.SUCCESS -> Icon(Icons.Filled.Check, contentDescription = translation["success_icon_description"], tint = MaterialTheme.colorScheme.primary) - TaskStatus.FAILURE -> Icon(Icons.Filled.Error, contentDescription = translation["failure_icon_description"], tint = MaterialTheme.colorScheme.error) - TaskStatus.CANCELLED -> Icon(Icons.Filled.Cancel, contentDescription = translation["cancelled_icon_description"], tint = MaterialTheme.colorScheme.error) - else -> {} - } - } - } - } - } - } - - override val content: @Composable (NavBackStackEntry) -> Unit = { - val scrollState = rememberLazyListState() - val scope = rememberCoroutineScope() - recentTasks = remember { mutableStateListOf() } - var lastFetchedTaskId by remember { mutableStateOf(null as Long?) } - - fun fetchNewRecentTasks() { - scope.launch(Dispatchers.IO) { - val tasks = context.taskManager.fetchStoredTasks(lastFetchedTaskId ?: Long.MAX_VALUE, limit = 20) - if (tasks.isNotEmpty()) { - lastFetchedTaskId = tasks.keys.last() - val activeTaskIds = activeTasks.map { it.taskId } - recentTasks.addAll(tasks.filter { it.key !in activeTaskIds }.values) - } - } - } - - LaunchedEffect(Unit) { - fetchActiveTasks(this) - } - - DisposableEffect(Unit) { - onDispose { - taskSelection.clear() - } - } - - OnLifecycleEvent { _, event -> - if (event == Lifecycle.Event.ON_RESUME) { - fetchActiveTasks(scope) - } - } - - LazyColumn( - state = scrollState, - modifier = Modifier.fillMaxSize(), - contentPadding = PaddingValues(bottom = routes.bottomPadding) - ) { - item { - if (activeTasks.isEmpty() && recentTasks.isEmpty()) { - Column( - modifier = Modifier.fillMaxSize(), - horizontalAlignment = Alignment.CenterHorizontally, - verticalArrangement = Arrangement.Center - ) { - translation["no_tasks"].let { - Icon(Icons.Filled.CheckCircle, contentDescription = it, tint = MaterialTheme.colorScheme.primary) - Text(it, style = MaterialTheme.typography.bodyLarge) - } - } - } - } - items(activeTasks, key = { it.taskId }) {pendingTask -> - TaskCard(modifier = Modifier.padding(8.dp), pendingTask.task, pendingTask = pendingTask) - } - items(recentTasks, key = { it.hash }) { task -> - TaskCard(modifier = Modifier.padding(8.dp), task) - } - item { - Spacer(modifier = Modifier.height(40.dp)) - LaunchedEffect(remember { derivedStateOf { scrollState.firstVisibleItemIndex } }) { - fetchNewRecentTasks() - } - } - } - } -} \ No newline at end of file diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/features/ConfigExportSummaryScreen.kt b/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/features/ConfigExportSummaryScreen.kt deleted file mode 100644 index fe1326e8..00000000 --- a/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/features/ConfigExportSummaryScreen.kt +++ /dev/null @@ -1,244 +0,0 @@ -package me.rhunk.snapenhance.ui.manager.pages.features - -import androidx.compose.animation.AnimatedVisibility -import androidx.compose.animation.core.animateFloatAsState -import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.* -import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.items -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.automirrored.filled.ArrowBack -import androidx.compose.material.icons.filled.KeyboardArrowDown -import androidx.compose.material3.* -import androidx.compose.runtime.* -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.graphicsLayer -import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.text.style.TextAlign -import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp -import androidx.compose.ui.window.Dialog -import me.rhunk.snapenhance.ui.manager.Routes -import me.rhunk.snapenhance.ui.util.saveFile -import org.json.JSONArray -import org.json.JSONObject - -class ConfigExportSummaryScreen : Routes.Route() { - override val translation by lazy { context.translation.getCategory("manager.features.config_export") } - - private data class ImportedFeature( - val category: String, - val name: String, - val key: String, - val value: Any, - val indentation: Int - ) - - private inner class ConfigParser { - fun parse(configJson: String): Map> { - val featureList = mutableListOf() - val json = JSONObject(configJson) - fun parseProperties(categoryKey: String, niceCategoryName: String, properties: JSONObject, prefix: String, indent: Int) { - for (key in properties.keys()) { - val value = properties.get(key) - val currentPrefix = if (prefix.isEmpty()) key else "$prefix.$key" - if (value is JSONObject && value.has("state") && value.has("properties")) { - val featureNameKey = "features.properties.$categoryKey.properties.${currentPrefix.split('.').joinToString(".properties.")}.name" - val featureName = context.translation[featureNameKey] ?: key - featureList.add(ImportedFeature(niceCategoryName, featureName, key, value.getBoolean("state"), indent)) - parseProperties(categoryKey, niceCategoryName, value.getJSONObject("properties"), currentPrefix, indent + 1) - } else if (value is JSONObject && value.has("properties")) { - parseProperties(categoryKey, niceCategoryName, value.getJSONObject("properties"), currentPrefix, indent) - } else { - val featureNameKey = "features.properties.$categoryKey.properties.${currentPrefix.split('.').joinToString(".properties.")}.name" - var featureName = context.translation[featureNameKey] ?: key - if (key == "save_folder") { - featureName = "Save Folder" - } - featureList.add(ImportedFeature(niceCategoryName, featureName, key, value, indent)) - } - } - } - for (categoryKey in json.keys()) { - val value = json.get(categoryKey) - if (value is JSONObject) { - val niceCategoryName = context.translation["features.properties.$categoryKey.name"] ?: categoryKey.replaceFirstChar { it.uppercase() } - if (value.has("state") && !value.has("properties")) { - featureList.add(ImportedFeature(niceCategoryName, translation["enable_feature"], categoryKey, value.getBoolean("state"), 0)) - } else if (value.has("properties")) { - parseProperties(categoryKey, niceCategoryName, value.getJSONObject("properties"), "", 0) - } - } - } - return featureList.groupBy { it.category } - } - - fun parseValue(featureKey: String, value: Any): Any { - fun innerParse(v: Any): String { - if (v is String) { - val translationKey = "features.options.$featureKey.$v" - val translated = context.translation[translationKey] - return translated!! - } - return v.toString() - } - return when (value) { - is Boolean -> if (value) translation["enabled"] else translation["disabled"] - is JSONArray -> { - val list = mutableListOf() - for (i in 0 until value.length()) { - list.add(innerParse(value.get(i))) - } - list - } - else -> innerParse(value) - } - } - } - - @OptIn(ExperimentalMaterial3Api::class) - override val content: @Composable (androidx.navigation.NavBackStackEntry) -> Unit = { - val exportSensitiveData = it.arguments?.getBoolean("exportSensitiveData") ?: false - val parser = remember { ConfigParser() } - val featuresByCategory = remember { - parser.parse(context.config.exportToString(exportSensitiveData)) - } - val expandedState = remember { mutableStateMapOf() } - - Scaffold( - topBar = { - TopAppBar( - title = { Text(translation["title"]) }, - navigationIcon = { - IconButton(onClick = { routes.navController.popBackStack() }) { - Icon(Icons.AutoMirrored.Filled.ArrowBack, contentDescription = translation["back_button_description"]) - } - }, - actions = { - TextButton(onClick = { - routes.activityLauncher.saveFile("config.json", "application/json") { uri -> - runCatching { - context.androidContext.contentResolver.openOutputStream(android.net.Uri.parse(uri))?.use { - context.config.writeConfig() - context.config.exportToString(exportSensitiveData).byteInputStream().copyTo(it) - context.shortToast(context.translation["manager.sections.features.config_export_success_toast"]) - } - }.onFailure { - context.longToast( - context.translation.format( - "manager.sections.features.config_export_failure_toast", - "error" to it.message.toString() - ) - ) - } - } - }) { - Text(translation["save_button"]) - } - } - ) - } - ) { padding -> - LazyColumn( - modifier = Modifier - .padding(padding) - .fillMaxSize(), - contentPadding = PaddingValues( - start = 16.dp, - top = 16.dp, - end = 16.dp, - bottom = 16.dp + routes.bottomPadding - ), - verticalArrangement = Arrangement.spacedBy(8.dp) - ) { - items(featuresByCategory.toList()) { (category, features) -> - val isExpanded = expandedState[category] ?: false - val rotationState by animateFloatAsState(targetValue = if (isExpanded) 180f else 0f) - Card( - modifier = Modifier - .fillMaxWidth() - .clickable { expandedState[category] = !isExpanded }, - shape = RoundedCornerShape(16.dp) - ) { - Column(modifier = Modifier.padding(12.dp)) { - Row(verticalAlignment = Alignment.CenterVertically) { - Text( - text = category, - fontWeight = FontWeight.Bold, - fontSize = 18.sp, - modifier = Modifier.weight(1f) - ) - IconButton(onClick = { expandedState[category] = !isExpanded }) { - Icon( - imageVector = Icons.Default.KeyboardArrowDown, - contentDescription = translation["expand_button_description"], - modifier = Modifier.graphicsLayer(rotationZ = rotationState) - ) - } - } - AnimatedVisibility(visible = isExpanded) { - Column { - HorizontalDivider(modifier = Modifier.padding(vertical = 8.dp)) - features.forEachIndexed { index, feature -> - when (val parsedValue = parser.parseValue(feature.key, feature.value)) { - is List<*> -> { - Column(modifier = Modifier.padding(start = (feature.indentation * 16).dp, top = 4.dp, bottom = 4.dp)) { - Text( - text = feature.name, - fontWeight = FontWeight.SemiBold, - ) - Spacer(modifier = Modifier.height(4.dp)) - Column(modifier = Modifier.padding(start = 16.dp)) { - parsedValue.forEach { item -> - Row { - Text( - text = "•", - color = MaterialTheme.colorScheme.primary, - modifier = Modifier.padding(end = 8.dp) - ) - Text( - text = item.toString(), - color = MaterialTheme.colorScheme.primary, - ) - } - } - } - } - } - is String -> { - Row( - modifier = Modifier - .fillMaxWidth() - .padding(vertical = 4.dp) - .padding(start = (feature.indentation * 16).dp), - verticalAlignment = Alignment.Top - ) { - Text( - text = feature.name, - modifier = Modifier.weight(1f), - fontWeight = FontWeight.SemiBold, - ) - Spacer(modifier = Modifier.width(16.dp)) - Text( - text = parsedValue, - color = MaterialTheme.colorScheme.primary, - textAlign = TextAlign.End, - ) - } - } - } - if (index < features.size - 1) { - HorizontalDivider(modifier = Modifier.padding(vertical = 4.dp)) - } - } - } - } - } - } - } - } - } - } -} diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/features/ConfigImportConfirmationScreen.kt b/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/features/ConfigImportConfirmationScreen.kt deleted file mode 100644 index 1264d89d..00000000 --- a/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/features/ConfigImportConfirmationScreen.kt +++ /dev/null @@ -1,331 +0,0 @@ -package me.rhunk.snapenhance.ui.manager.pages.features - -import androidx.compose.animation.AnimatedVisibility -import androidx.compose.animation.core.animateFloatAsState -import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.PaddingValues -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.width -import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.items -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.automirrored.filled.ArrowBack -import androidx.compose.material.icons.filled.KeyboardArrowDown -import androidx.compose.material3.Card -import androidx.compose.material3.ExperimentalMaterial3Api -import androidx.compose.material3.HorizontalDivider -import androidx.compose.material3.Icon -import androidx.compose.material3.IconButton -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Scaffold -import androidx.compose.material3.Text -import androidx.compose.material3.TextButton -import androidx.compose.material3.TopAppBar -import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateMapOf -import androidx.compose.runtime.remember -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.graphicsLayer -import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.text.style.TextAlign -import androidx.compose.ui.text.style.TextOverflow -import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.launch -import me.rhunk.snapenhance.ui.manager.Routes -import org.json.JSONArray -import org.json.JSONObject - -class ConfigImportConfirmationScreen : Routes.Route() { - override val translation by lazy { context.translation.getCategory("manager.features.config_import") } - - private data class ImportedFeature( - val category: String, - val name: String, - val key: String, - val value: Any, - val indentation: Int - ) - - private inner class ConfigParser { - fun parse(configJson: String): Map> { - val featureList = mutableListOf() - val json = JSONObject(configJson) - fun parseProperties( - categoryKey: String, - niceCategoryName: String, - properties: JSONObject, - prefix: String, - indent: Int - ) { - for (key in properties.keys()) { - val value = properties.get(key) - val currentPrefix = if (prefix.isEmpty()) key else "$prefix.$key" - if (value is JSONObject && value.has("state") && value.has("properties")) { - val featureNameKey = - "features.properties.$categoryKey.properties.${currentPrefix.split('.') - .joinToString(".properties.")}.name" - val featureName = context.translation[featureNameKey] ?: key - featureList.add( - ImportedFeature( - niceCategoryName, - featureName, - key, - value.getBoolean("state"), - indent - ) - ) - parseProperties( - categoryKey, - niceCategoryName, - value.getJSONObject("properties"), - currentPrefix, - indent + 1 - ) - } else if (value is JSONObject && value.has("properties")) { - parseProperties( - categoryKey, - niceCategoryName, - value.getJSONObject("properties"), - currentPrefix, - indent - ) - } else { - val featureNameKey = - "features.properties.$categoryKey.properties.${currentPrefix.split('.') - .joinToString(".properties.")}.name" - val featureName = context.translation[featureNameKey] ?: key - featureList.add( - ImportedFeature( - niceCategoryName, - featureName, - key, - value, - indent - ) - ) - } - } - } - for (categoryKey in json.keys()) { - val value = json.get(categoryKey) - if (value is JSONObject) { - val niceCategoryName = - context.translation["features.properties.$categoryKey.name"] - ?: categoryKey.replaceFirstChar { it.uppercase() } - if (value.has("state") && !value.has("properties")) { - featureList.add( - ImportedFeature( - niceCategoryName, - translation["enable_feature"], - categoryKey, - value.getBoolean("state"), - 0 - ) - ) - } else if (value.has("properties")) { - parseProperties( - categoryKey, - niceCategoryName, - value.getJSONObject("properties"), - "", - 0 - ) - } - } - } - return featureList.groupBy { it.category } - } - - fun parseValue(featureKey: String, value: Any): Any { - fun innerParse(v: Any): String { - if (v is String) { - val translationKey = "features.options.$featureKey.$v" - val translated = context.translation[translationKey] - return translated!! - } - return v.toString() - } - return when (value) { - is Boolean -> if (value) translation["enabled"] else translation["disabled"] - is JSONArray -> { - val list = mutableListOf() - for (i in 0 until value.length()) { - list.add(innerParse(value.get(i))) - } - list - } - else -> innerParse(value) - } - } - } - - @OptIn(ExperimentalMaterial3Api::class) - override val content: @Composable (androidx.navigation.NavBackStackEntry) -> Unit = { - val parser = remember { ConfigParser() } - val featuresByCategory = remember { - routes.configJsonForImport?.let { parser.parse(it) } ?: emptyMap() - } - val expandedState = remember { mutableStateMapOf() } - - Scaffold( - topBar = { - TopAppBar( - title = { Text(translation["title"]) }, - navigationIcon = { - IconButton(onClick = { routes.navController.popBackStack() }) { - Icon( - Icons.AutoMirrored.Filled.ArrowBack, - contentDescription = translation["back_button_description"] - ) - } - }, - actions = { - TextButton(onClick = { - routes.configJsonForImport?.let { - runCatching { - context.config.loadFromString(it) - }.onFailure { err -> - context.longToast( - context.translation.format( - "config_import_failure_toast", - "error" to (err.message ?: "Unknown error") - ) - ) - // Return is not needed since last statement in lambda - } - context.shortToast(translation["config_imported_toast"]) - context.coroutineScope.launch(Dispatchers.Main) { - routes.features.navigateReload() - } - } - }) { - Text(translation["confirm_button"]) - } - } - ) - } - ) { padding -> - LazyColumn( - modifier = Modifier - .padding(padding) - .fillMaxSize(), - contentPadding = PaddingValues( - start = 16.dp, - top = 16.dp, - end = 16.dp, - bottom = 16.dp + routes.bottomPadding - ), - verticalArrangement = Arrangement.spacedBy(8.dp) - ) { - items(featuresByCategory.toList()) { (category, features) -> - val isExpanded = expandedState[category] ?: false - val rotationState by animateFloatAsState(targetValue = if (isExpanded) 180f else 0f) - - Card( - modifier = Modifier - .fillMaxWidth() - .clickable { expandedState[category] = !isExpanded }, - shape = RoundedCornerShape(16.dp) - ) { - Column(modifier = Modifier.padding(12.dp)) { - Row(verticalAlignment = Alignment.CenterVertically) { - Text( - text = category, - fontWeight = FontWeight.Bold, - fontSize = 18.sp, - modifier = Modifier.weight(1f) - ) - IconButton(onClick = { expandedState[category] = !isExpanded }) { - Icon( - imageVector = Icons.Default.KeyboardArrowDown, - contentDescription = translation["expand_button_description"], - modifier = Modifier.graphicsLayer(rotationZ = rotationState) - ) - } - } - - AnimatedVisibility(visible = isExpanded) { - Column { - HorizontalDivider(modifier = Modifier.padding(vertical = 8.dp)) - features.forEachIndexed { index, feature -> - when (val parsedValue = parser.parseValue(feature.key, feature.value)) { - is List<*> -> { - Column( - modifier = Modifier - .padding( - start = (feature.indentation * 16).dp, - top = 4.dp, - bottom = 4.dp - ) - ) { - Text( - text = feature.name, - fontWeight = FontWeight.SemiBold, - ) - Spacer(modifier = Modifier.height(4.dp)) - Column(modifier = Modifier.padding(start = 16.dp)) { - parsedValue.forEach { item -> - Row { - Text( - text = "•", - color = MaterialTheme.colorScheme.primary, - modifier = Modifier.padding(end = 8.dp) - ) - Text( - text = item.toString(), - color = MaterialTheme.colorScheme.primary, - ) - } - } - } - } - } - - is String -> { - Row( - modifier = Modifier - .fillMaxWidth() - .padding(vertical = 4.dp) - .padding(start = (feature.indentation * 16).dp), - verticalAlignment = Alignment.Top - ) { - Text( - text = feature.name, - modifier = Modifier.weight(1f), - fontWeight = FontWeight.SemiBold, - ) - Spacer(modifier = Modifier.width(16.dp)) - Text( - text = parsedValue, - color = MaterialTheme.colorScheme.primary, - textAlign = TextAlign.End, - ) - } - } - } - // Always show divider only when there are more features to follow - if (index < features.size - 1) { - HorizontalDivider(modifier = Modifier.padding(vertical = 4.dp)) - } - } - } - } - } - } - } - } - } - } -} diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/features/FeaturesRootSection.kt b/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/features/FeaturesRootSection.kt deleted file mode 100644 index b826864e..00000000 --- a/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/features/FeaturesRootSection.kt +++ /dev/null @@ -1,758 +0,0 @@ -package me.rhunk.snapenhance.ui.manager.pages.features - -import android.content.Intent -import android.net.Uri -import androidx.compose.animation.AnimatedContentTransitionScope -import androidx.compose.animation.core.tween -import androidx.compose.foundation.background -import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.* -import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.items -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.foundation.text.KeyboardActions -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.automirrored.filled.ArrowBack -import androidx.compose.material.icons.automirrored.filled.OpenInNew -import androidx.compose.material.icons.filled.* -import androidx.compose.material3.* -import androidx.compose.runtime.* -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.focus.FocusRequester -import androidx.compose.ui.focus.focusRequester -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.hapticfeedback.HapticFeedbackType -import androidx.compose.ui.platform.LocalHapticFeedback -import androidx.compose.ui.graphics.graphicsLayer -import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.text.style.TextAlign -import androidx.compose.ui.text.style.TextOverflow -import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp -import androidx.compose.ui.window.Dialog -import androidx.lifecycle.Lifecycle -import androidx.navigation.NavBackStackEntry -import androidx.navigation.NavGraph.Companion.findStartDestination -import androidx.navigation.NavGraphBuilder -import androidx.navigation.NavOptions -import androidx.navigation.compose.composable -import androidx.navigation.compose.currentBackStackEntryAsState -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.Job -import kotlinx.coroutines.delay -import kotlinx.coroutines.launch -import me.rhunk.snapenhance.common.config.* -import me.rhunk.snapenhance.common.ui.TopBarActionButton -import me.rhunk.snapenhance.common.ui.rememberAsyncMutableStateList -import me.rhunk.snapenhance.common.ui.transparentTextFieldColors -import me.rhunk.snapenhance.ui.manager.MainActivity -import me.rhunk.snapenhance.ui.manager.Routes -import me.rhunk.snapenhance.ui.util.* -import org.json.JSONArray -import org.json.JSONObject - -class FeaturesRootSection : Routes.Route() { - override val title: @Composable (() -> Unit)? = @Composable { - val navBackStackEntry by routes.navController.currentBackStackEntryAsState() - val currentDestination = navBackStackEntry?.destination - - val titleText = when (currentDestination?.route) { - FEATURE_CONTAINER_ROUTE -> { - navBackStackEntry?.arguments?.getString("name")?.let { containerName -> - allContainers[containerName]?.let { - context.translation[it.key.propertyName()] - } - } ?: routeInfo.translatedKey?.value - } - SEARCH_FEATURE_ROUTE -> { - translation["search_button"] ?: "Search" - } - else -> { - routeInfo.translatedKey?.value - } - } - Text(titleText ?: "", maxLines = 1, overflow = TextOverflow.Ellipsis) - } - - private val alertDialogs by lazy { AlertDialogs(context.translation) } - - companion object { - const val FEATURE_CONTAINER_ROUTE = "feature_container/{name}" - const val SEARCH_FEATURE_ROUTE = "search_feature/{keyword}" - } - - private var activityLauncherHelper: ActivityLauncherHelper? = null - - private val allContainers by lazy { - val containers = mutableMapOf>() - fun queryContainerRecursive(container: ConfigContainer) { - container.properties.forEach { - if (it.key.dataType.type == DataProcessors.Type.CONTAINER) { - containers[it.key.name] = PropertyPair(it.key, it.value) - queryContainerRecursive(it.value.get() as ConfigContainer) - } - } - } - queryContainerRecursive(context.config.root) - containers - } - - private val allProperties by lazy { - val properties = mutableMapOf, PropertyValue<*>>() - allContainers.values.forEach { - val container = it.value.get() as ConfigContainer - container.properties.forEach { property -> - properties[property.key] = property.value - } - } - properties - } - - private fun navigateToMainRoot() { - routes.navController.navigate(routeInfo.id, NavOptions.Builder() - .setPopUpTo(routes.navController.graph.findStartDestination().id, false) - .setLaunchSingleTop(true) - .build() - ) - } - - private fun activityLauncher(block: ActivityLauncherHelper.() -> Unit) { - routes.activityLauncher.let(block) - } - - override val content: @Composable (NavBackStackEntry) -> Unit = { - Container(context.config.root) - } - - override val customComposables: NavGraphBuilder.() -> Unit = { - routeInfo.childIds.addAll(listOf(FEATURE_CONTAINER_ROUTE, SEARCH_FEATURE_ROUTE)) - - composable(FEATURE_CONTAINER_ROUTE, enterTransition = { - slideIntoContainer(AnimatedContentTransitionScope.SlideDirection.Left, animationSpec = tween(100)) - }, exitTransition = { - slideOutOfContainer(AnimatedContentTransitionScope.SlideDirection.Right, animationSpec = tween(300)) - }) { backStackEntry -> - backStackEntry.arguments?.getString("name")?.let { containerName -> - allContainers[containerName]?.let { - Container(it.value.get() as ConfigContainer) - } - } - } - - composable(SEARCH_FEATURE_ROUTE) { backStackEntry -> - backStackEntry.arguments?.getString("keyword")?.let { keyword -> - val properties = allProperties.filter { - it.key.name.contains(keyword, ignoreCase = true) || - context.translation[it.key.propertyName()].contains(keyword, ignoreCase = true) || - context.translation[it.key.propertyDescription()].contains(keyword, ignoreCase = true) - }.map { PropertyPair(it.key, it.value) } - - PropertiesView(properties) - } - } - } - - @Composable - private fun PropertyAction(property: PropertyPair<*>, registerClickCallback: RegisterClickCallback) { - var showDialog by remember { mutableStateOf(false) } - var dialogComposable by remember { mutableStateOf<@Composable () -> Unit>({}) } - - fun registerDialogOnClickCallback() = registerClickCallback { showDialog = true } - - if (showDialog) { - Dialog( - properties = DialogProperties( - usePlatformDefaultWidth = false - ), - onDismissRequest = { showDialog = false }, - ) { - dialogComposable() - } - } - - val propertyValue = property.value - - if (property.key.params.flags.contains(ConfigFlag.USER_IMPORT)) { - registerDialogOnClickCallback() - dialogComposable = { - var isEmpty by remember { mutableStateOf(false) } - val files = rememberAsyncMutableStateList(defaultValue = listOf()) { - context.fileHandleManager.getStoredFiles { - property.key.params.filenameFilter?.invoke(it.name) == true - }.also { - isEmpty = it.isEmpty() - if (isEmpty) { - propertyValue.setAny(null) - } - } - } - var selectedFile by remember(files.size) { mutableStateOf(files.firstOrNull { it.name == propertyValue.getNullable() }.also { - if (files.isNotEmpty() && it == null) propertyValue.setAny(null) - }?.name) } - - Card( - shape = MaterialTheme.shapes.large, - modifier = Modifier - .fillMaxWidth(), - ) { - LazyColumn( - modifier = Modifier - .fillMaxWidth() - .padding(4.dp), - ) { - item { - Column( - modifier = Modifier - .fillMaxWidth() - .padding(16.dp), - horizontalAlignment = Alignment.CenterHorizontally - ) { - Text( - text = context.translation["manager.dialogs.file_imports.settings_select_file_hint"], - fontSize = 18.sp, - fontWeight = FontWeight.Bold, - ) - if (isEmpty) { - Text( - text = context.translation["manager.dialogs.file_imports.no_files_settings_hint"], - fontSize = 16.sp, - modifier = Modifier.padding(top = 10.dp), - ) - } - } - } - items(files, key = { it.name }) { file -> - Row( - modifier = Modifier - .clickable { - selectedFile = - if (selectedFile == file.name) null else file.name - propertyValue.setAny(selectedFile) - } - .padding(5.dp), - verticalAlignment = Alignment.CenterVertically - ) { - Icon(Icons.Filled.AttachFile, contentDescription = null, modifier = Modifier.padding(5.dp)) - Text( - text = file.name, - modifier = Modifier - .padding(3.dp) - .weight(1f), - fontSize = 14.sp, - lineHeight = 16.sp - ) - if (selectedFile == file.name) { - Icon(Icons.Filled.Check, contentDescription = null, modifier = Modifier.padding(5.dp)) - } - } - } - } - } - } - - Icon(Icons.Filled.AttachFile, contentDescription = null) - return - } - - if (property.key.params.flags.contains(ConfigFlag.FOLDER)) { - IconButton(onClick = registerClickCallback { - activityLauncher { - chooseFolder { uri -> - propertyValue.setAny(uri) - } - } - }.let { { it.invoke(true) } }) { - Icon(Icons.Filled.FolderOpen, contentDescription = null) - } - return - } - - when (val dataType = remember { property.key.dataType.type }) { - DataProcessors.Type.BOOLEAN -> { - var state by remember { mutableStateOf(propertyValue.get() as Boolean) } - val hapticFeedback = LocalHapticFeedback.current - Switch( - checked = state, - onCheckedChange = registerClickCallback { - if (context.config.root.global.uiSettings.hapticFeedback.get()) { - hapticFeedback.performHapticFeedback(HapticFeedbackType.LongPress) - } - state = state.not() - propertyValue.setAny(state) - } - ) - } - - DataProcessors.Type.MAP_COORDINATES -> { - registerDialogOnClickCallback() - dialogComposable = { - alertDialogs.ChooseLocationDialog(property) { - showDialog = false - } - } - - Text( - overflow = TextOverflow.Ellipsis, - maxLines = 1, - modifier = Modifier.widthIn(0.dp, 120.dp), - text = (propertyValue.get() as Pair<*, *>).let { - "${it.first.toString().toFloatOrNull() ?: 0F}, ${it.second.toString().toFloatOrNull() ?: 0F}" - } - ) - } - - DataProcessors.Type.STRING_UNIQUE_SELECTION -> { - registerDialogOnClickCallback() - - dialogComposable = { - alertDialogs.UniqueSelectionDialog(property) - } - - Text( - overflow = TextOverflow.Ellipsis, - maxLines = 1, - modifier = Modifier.widthIn(0.dp, 120.dp), - text = (propertyValue.getNullable() as? String ?: "null").let { - property.key.propertyOption(context.translation, it) - } - ) - } - - DataProcessors.Type.STRING_MULTIPLE_SELECTION, DataProcessors.Type.STRING, DataProcessors.Type.INTEGER, DataProcessors.Type.FLOAT -> { - dialogComposable = { - when (dataType) { - DataProcessors.Type.STRING_MULTIPLE_SELECTION -> { - alertDialogs.MultipleSelectionDialog(property) - } - DataProcessors.Type.STRING, DataProcessors.Type.INTEGER, DataProcessors.Type.FLOAT -> { - alertDialogs.KeyboardInputDialog(property) { showDialog = false } - } - else -> {} - } - } - - registerDialogOnClickCallback().let { { it.invoke(true) } }.also { - if (dataType == DataProcessors.Type.INTEGER || - dataType == DataProcessors.Type.FLOAT) { - FilledIconButton(onClick = it) { - Text( - text = propertyValue.get().toString(), - modifier = Modifier.wrapContentWidth(), - overflow = TextOverflow.Ellipsis - ) - } - } else { - IconButton(onClick = it) { - Icon(Icons.AutoMirrored.Filled.OpenInNew, contentDescription = null) - } - } - } - } - - DataProcessors.Type.INT_COLOR -> { - dialogComposable = { - alertDialogs.ColorPickerPropertyDialog(property) { - showDialog = false - } - } - - registerDialogOnClickCallback().let { { it.invoke(true) } }.also { - CircularAlphaTile(selectedColor = (propertyValue.getNullable() as? Int)?.let { Color(it) }) - } - } - - DataProcessors.Type.CONTAINER -> { - val container = propertyValue.get() as ConfigContainer - - registerClickCallback { - routes.navController.navigate(FEATURE_CONTAINER_ROUTE.replace("{name}", property.name)) - } - - if (!container.hasGlobalState) return - - var state by remember { mutableStateOf(container.globalState ?: false) } - - Box( - modifier = Modifier - .padding(end = 15.dp), - ) { - - Box(modifier = Modifier - .height(50.dp) - .width(1.dp) - .background( - color = MaterialTheme.colorScheme.primary.copy(alpha = 0.12f), - shape = RoundedCornerShape(5.dp) - )) - } - - val hapticFeedback = LocalHapticFeedback.current - Switch( - checked = state, - onCheckedChange = { - if (context.config.root.global.uiSettings.hapticFeedback.get()) { - hapticFeedback.performHapticFeedback(HapticFeedbackType.LongPress) - } - state = state.not() - container.globalState = state - } - ) - } - } - - } - - @Composable - private fun PropertyCard(property: PropertyPair<*>) { - var clickCallback by remember { mutableStateOf(null) } - val noticeColorMap = mapOf( - FeatureNotice.UNSTABLE.key to Color(0xFFFFFB87), - FeatureNotice.BAN_RISK.key to Color(0xFFFF8585), - FeatureNotice.INTERNAL_BEHAVIOR.key to Color(0xFFFFFB87), - ) - - val versionCheck = remember { property.key.params.versionCheck } - val versionCheckPair = remember(property) { versionCheck?.checkVersion(context.installationSummary.snapchatInfo?.versionCode ?: return@remember null)} - val isComponentDisabled = remember { versionCheckPair != null && versionCheck?.isDisabled == true } - - ElevatedCard( - modifier = Modifier - .fillMaxWidth() - .then( - if (isComponentDisabled) Modifier.graphicsLayer(alpha = 0.5f) - else Modifier - ) - .padding(start = 10.dp, end = 10.dp, top = 5.dp, bottom = 5.dp) - ) { - Row( - modifier = Modifier - .fillMaxSize() - .clickable { - clickCallback?.invoke(true) - } - .padding(all = 4.dp), - horizontalArrangement = Arrangement.SpaceBetween - ) { - property.key.params.icon?.let { icon -> - Icon( - imageVector = icon, - contentDescription = null, - modifier = Modifier - .align(Alignment.CenterVertically) - .padding(start = 10.dp) - ) - } - - Column( - modifier = Modifier - .align(Alignment.CenterVertically) - .weight(1f, fill = true) - .padding(all = 10.dp) - ) { - Text( - text = context.translation[property.key.propertyName()], - fontSize = 16.sp, - lineHeight = 16.sp, - fontWeight = FontWeight.Bold - ) - Text( - text = context.translation[property.key.propertyDescription()], - fontSize = 12.sp, - lineHeight = 15.sp - ) - property.key.params.notices.also { - if (it.isNotEmpty()) Spacer(modifier = Modifier.height(5.dp)) - }.forEach { - Text( - text = context.translation["features.notices.${it.key}"], - color = noticeColorMap[it.key] ?: Color(0xFFFFFB87), - fontSize = 12.sp, - lineHeight = 15.sp - ) - } - - if (versionCheckPair != null) { - Spacer(modifier = Modifier.height(2.dp)) - Text( - text = context.translation.format( - "manager.sections.features.${versionCheckPair.second.key}", - "version" to versionCheckPair.first.first - ), - color = Color(0xFFFF8585), - fontSize = 12.sp, - lineHeight = 15.sp - ) - } - } - - Row( - modifier = Modifier - .align(Alignment.CenterVertically) - .padding(all = 10.dp), - verticalAlignment = Alignment.CenterVertically - ) { - PropertyAction(property, registerClickCallback = { callback -> - if (property.key.propertyTranslationPath().startsWith("rules.properties")) { - clickCallback = { - routes.manageRuleFeature.navigate { - put("rule_type", property.key.name) - } - } - return@PropertyAction clickCallback!! - } - clickCallback = callback - callback - }) - } - } - } - } - - @Composable - private fun FeatureSearchBar(rowScope: RowScope, focusRequester: FocusRequester) { - var searchValue by remember { mutableStateOf("") } - val scope = rememberCoroutineScope() - var currentSearchJob by remember { mutableStateOf(null) } - - rowScope.apply { - TextField( - value = searchValue, - onValueChange = { keyword -> - searchValue = keyword - if (keyword.isEmpty()) { - navigateToMainRoot() - return@TextField - } - currentSearchJob?.cancel() - scope.launch { - delay(300) - routes.navController.navigate(SEARCH_FEATURE_ROUTE.replace("{keyword}", keyword), NavOptions.Builder() - .setLaunchSingleTop(true) - .setPopUpTo(routeInfo.id, false) - .build() - ) - }.also { currentSearchJob = it } - }, - - keyboardActions = KeyboardActions(onDone = { - focusRequester.freeFocus() - }), - modifier = Modifier - .focusRequester(focusRequester) - .weight(1f, fill = true) - .padding(end = 10.dp) - .height(70.dp), - singleLine = true, - colors = transparentTextFieldColors() - ) - } - } - - @Composable - private fun SensitiveDataDialog( - onDismiss: () -> Unit, - onConfirm: (exportSensitiveData: Boolean) -> Unit - ) { - Dialog(onDismissRequest = onDismiss) { - Card(shape = RoundedCornerShape(16.dp)) { - Column(modifier = Modifier.padding(24.dp), horizontalAlignment = Alignment.CenterHorizontally) { - Text( - text = context.translation["manager.dialogs.export_config.title"], - style = MaterialTheme.typography.titleLarge, - modifier = Modifier.padding(bottom = 16.dp) - ) - Text( - text = context.translation["manager.dialogs.export_config.content"], - style = MaterialTheme.typography.bodyMedium, - textAlign = TextAlign.Center, - modifier = Modifier.padding(bottom = 24.dp) - ) - Row( - modifier = Modifier.fillMaxWidth(), - horizontalArrangement = Arrangement.spacedBy(8.dp, Alignment.End) - ) { - TextButton(onClick = { onConfirm(false) }) { - Text(context.translation["button.negative"]) - } - TextButton(onClick = { onConfirm(true) }) { - Text(context.translation["button.positive"]) - } - } - } - } - } - } - - override val topBarActions: @Composable (RowScope.() -> Unit) = topBarActions@{ - var showSearchBar by remember { mutableStateOf(false) } - val focusRequester = remember { FocusRequester() } - - if (showSearchBar) { - FeatureSearchBar(this, focusRequester) - LaunchedEffect(true) { - focusRequester.requestFocus() - } - } - - - if (showSearchBar) { - IconButton(onClick = { - showSearchBar = false - if (routes.currentDestination == SEARCH_FEATURE_ROUTE) { - navigateToMainRoot() - } - }) { - Icon( - imageVector = Icons.Filled.Close, - contentDescription = null - ) - } - } else { - TopBarActionButton( - onClick = { - showSearchBar = true - }, - icon = Icons.Filled.Search, - text = translation["search_button"] - ) - } - - if (showSearchBar) return@topBarActions - - var showExportDropdownMenu by remember { mutableStateOf(false) } - var showResetConfirmationDialog by remember { mutableStateOf(false) } - var showExportDialog by remember { mutableStateOf(false) } - - if (showResetConfirmationDialog) { - AlertDialog( - title = { Text(text = context.translation["manager.dialogs.reset_config.title"]) }, - text = { Text(text = context.translation["manager.dialogs.reset_config.content"]) }, - onDismissRequest = { showResetConfirmationDialog = false }, - confirmButton = { - Button( - onClick = { - context.config.reset() - context.shortToast(context.translation["manager.dialogs.reset_config.success_toast"]) - showResetConfirmationDialog = false - } - ) { - Text(text = context.translation["button.positive"]) - } - }, - dismissButton = { - Button( - onClick = { - showResetConfirmationDialog = false - } - ) { - Text(text = context.translation["button.negative"]) - } - } - ) - } - - if (showExportDialog) { - SensitiveDataDialog( - onDismiss = { showExportDialog = false }, - onConfirm = { exportSensitiveData -> - showExportDialog = false - routes.configExportSummary.navigate { - put("exportSensitiveData", exportSensitiveData.toString()) - } - } - ) - } - - val actions = remember { - mapOf( - translation["export_option"] to { showExportDialog = true }, - translation["import_option"] to { - activityLauncher { - openFile("application/json") { uri -> - context.androidContext.contentResolver.openInputStream(Uri.parse(uri))?.use { - routes.configJsonForImport = it.readBytes().toString(Charsets.UTF_8) - routes.navController.navigate(Routes.CONFIG_IMPORT_CONFIRMATION_ROUTE) - } - } - } - }, - translation["reset_option"] to { showResetConfirmationDialog = true } - ) - } - - if (context.activity != null) { - IconButton(onClick = { showExportDropdownMenu = !showExportDropdownMenu}) { - Icon( - imageVector = Icons.Filled.MoreVert, - contentDescription = null - ) - } - } - - if (showExportDropdownMenu) { - DropdownMenu(expanded = true, onDismissRequest = { showExportDropdownMenu = false }) { - actions.forEach { (name, action) -> - DropdownMenuItem( - text = { - Text(text = name) - }, - onClick = { - action() - showExportDropdownMenu = false - } - ) - } - } - } - } - - @Composable - private fun PropertiesView( - properties: List> - ) { - LazyColumn( - modifier = Modifier.fillMaxSize(), - verticalArrangement = Arrangement.Top, - contentPadding = PaddingValues(bottom = routes.bottomPadding) - ) { - items(properties, key = { it.key.propertyName() }) { - PropertyCard(it) - } - } - } - - override val floatingActionButton: @Composable () -> Unit = { - fun saveConfig() { - context.coroutineScope.launch(Dispatchers.IO) { - context.config.writeConfig() - context.log.verbose("saved config!") - } - } - - OnLifecycleEvent { _, event -> - if (event == Lifecycle.Event.ON_PAUSE || event == Lifecycle.Event.ON_STOP) { - saveConfig() - } - } - - DisposableEffect(Unit) { - onDispose { - saveConfig() - } - } - } - - - - @Composable - private fun Container( - configContainer: ConfigContainer - ) { - PropertiesView(remember { - configContainer.properties.map { PropertyPair(it.key, it.value) }.filter { - !it.key.params.flags.contains(ConfigFlag.HIDDEN) - } - }) - } -} diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/features/ManageRuleFeature.kt b/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/features/ManageRuleFeature.kt deleted file mode 100644 index f1377e90..00000000 --- a/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/features/ManageRuleFeature.kt +++ /dev/null @@ -1,231 +0,0 @@ -package me.rhunk.snapenhance.ui.manager.pages.features - -import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.* -import androidx.compose.material3.Button -import androidx.compose.material3.OutlinedButton -import androidx.compose.material3.RadioButton -import androidx.compose.material3.Text -import androidx.compose.runtime.* -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.text.style.TextOverflow -import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp -import androidx.navigation.NavBackStackEntry -import androidx.navigation.compose.currentBackStackEntryAsState -import kotlinx.coroutines.asCoroutineDispatcher -import kotlinx.coroutines.launch -import me.rhunk.snapenhance.common.data.MessagingRuleType -import me.rhunk.snapenhance.common.data.RuleState -import me.rhunk.snapenhance.common.ui.rememberAsyncMutableState -import me.rhunk.snapenhance.common.ui.rememberAsyncUpdateDispatcher -import me.rhunk.snapenhance.storage.clearRuleIds -import me.rhunk.snapenhance.storage.getRuleIds -import me.rhunk.snapenhance.storage.setRule -import me.rhunk.snapenhance.ui.manager.Routes -import me.rhunk.snapenhance.ui.manager.pages.social.AddFriendDialog -import me.rhunk.snapenhance.ui.manager.pages.social.AddFriendDialog.Actions -import me.rhunk.snapenhance.ui.util.AlertDialogs -import me.rhunk.snapenhance.ui.util.Dialog - -class ManageRuleFeature : Routes.Route() { - override val title: @Composable () -> Unit = { - val navBackStackEntry by routes.navController.currentBackStackEntryAsState() - val text = remember(navBackStackEntry) { - navBackStackEntry?.arguments?.getString("rule_type")?.let { ruleType -> - MessagingRuleType.getByName(ruleType)?.let { - context.config.root.rules.getPropertyPair(it.key).let { - context.translation[it.key.propertyName()] - } - } - } - } - text?.let { Text(it, maxLines = 1, overflow = TextOverflow.Ellipsis) } - } - - @Composable - fun SelectRuleTypeRadio( - checked: Boolean, - text: String, - onStateChanged: (Boolean) -> Unit, - selectedBlock: @Composable () -> Unit = {}, - ) { - Box(modifier = Modifier.clickable { - onStateChanged(!checked) - }) { - Column( - modifier = Modifier - .padding(10.dp), - verticalArrangement = Arrangement.spacedBy(4.dp), - ) { - Row( - modifier = Modifier - .fillMaxWidth(), - horizontalArrangement = Arrangement.spacedBy(4.dp), - verticalAlignment = Alignment.CenterVertically, - ) { - RadioButton(selected = checked, onClick = null) - Text(text) - } - if (checked) { - Column(modifier = Modifier - .offset(x = 15.dp) - .padding(4.dp), verticalArrangement = Arrangement.spacedBy(4.dp)) { - selectedBlock() - } - } - } - } - } - - override val content: @Composable (NavBackStackEntry) -> Unit = content@{ navBackStackEntry -> - val currentRuleType = navBackStackEntry.arguments?.getString("rule_type")?.let { - MessagingRuleType.getByName(it) - } ?: return@content - - var ruleState by remember { - mutableStateOf(context.config.root.rules.getRuleState(currentRuleType)) - } - - val propertyKeyPair = remember { - context.config.root.rules.getPropertyPair(currentRuleType.key) - } - - val updateDispatcher = rememberAsyncUpdateDispatcher() - val currentRuleIds by rememberAsyncMutableState(defaultValue = mutableListOf(), updateDispatcher = updateDispatcher) { - context.database.getRuleIds(currentRuleType.key) - } - - fun setRuleState(newState: RuleState?) { - ruleState = newState - propertyKeyPair.value.setAny(newState?.key) - context.coroutineScope.launch { - context.config.writeConfig(dispatchConfigListener = false) - } - } - - var addFriendDialog by remember { mutableStateOf(null as AddFriendDialog?) } - - LaunchedEffect(addFriendDialog) { - if (addFriendDialog == null) { - updateDispatcher.dispatch() - } - } - - fun showAddFriendDialog() { - addFriendDialog = AddFriendDialog( - context = context, - pinnedIds = currentRuleIds, - actionHandler = Actions( - onFriendState = { friend, state -> - context.database.setRule(friend.userId, currentRuleType.key, state) - if (state) { - currentRuleIds.add(friend.userId) - } else { - currentRuleIds.remove(friend.userId) - } - }, - onGroupState = { group, state -> - context.database.setRule(group.conversationId, currentRuleType.key, state) - if (state) { - currentRuleIds.add(group.conversationId) - } else { - currentRuleIds.remove(group.conversationId) - } - }, - getFriendState = { friend -> - currentRuleIds.contains(friend.userId) - }, - getGroupState = { group -> - currentRuleIds.contains(group.conversationId) - } - ) - ) - } - - if (addFriendDialog != null) { - addFriendDialog?.Content { - addFriendDialog = null - } - } - - Column( - modifier = Modifier.fillMaxSize() - ) { - Column( - modifier = Modifier.padding(10.dp), - verticalArrangement = Arrangement.spacedBy(4.dp), - ) { - Text( - text = remember { - context.translation[propertyKeyPair.key.propertyName()] - }, - fontSize = 20.sp, - ) - Text( - text = remember { - context.translation[propertyKeyPair.key.propertyDescription()] - }, - fontWeight = FontWeight.Light, - fontSize = 12.sp, - lineHeight = 16.sp, - ) - } - - SelectRuleTypeRadio(checked = ruleState == null, text = translation["disable_state_option"], onStateChanged = { - setRuleState(null) - }) { - Text(text = translation["disable_state_subtext"], fontWeight = FontWeight.Light, fontSize = 12.sp) - } - SelectRuleTypeRadio(checked = ruleState == RuleState.WHITELIST, text = translation["whitelist_state_option"], onStateChanged = { - setRuleState(RuleState.WHITELIST) - }) { - Text(text = translation.format("whitelist_state_subtext", "count" to currentRuleIds.size.toString()), fontWeight = FontWeight.Light, fontSize = 12.sp) - OutlinedButton(onClick = { - showAddFriendDialog() - }) { - Text(text = translation["whitelist_state_button"]) - } - } - SelectRuleTypeRadio(checked = ruleState == RuleState.BLACKLIST, text = translation["blacklist_state_option"], onStateChanged = { - setRuleState(RuleState.BLACKLIST) - }) { - Text(text = translation.format("blacklist_state_subtext", "count" to currentRuleIds.size.toString()), fontWeight = FontWeight.Light, fontSize = 12.sp) - OutlinedButton(onClick = { showAddFriendDialog() }) { - Text(text = translation["blacklist_state_button"]) - } - } - - Row( - modifier = Modifier.fillMaxWidth().padding(5.dp), - horizontalArrangement = Arrangement.SpaceEvenly - ) { - var confirmationDialog by remember { mutableStateOf(false) } - - if (confirmationDialog) { - Dialog(onDismissRequest = { - confirmationDialog = false - }) { - remember { AlertDialogs(context.translation) }.ConfirmDialog( - title = translation["dialog_clear_confirmation_text"], - onDismiss = { confirmationDialog = false }, - onConfirm = { - context.database.clearRuleIds(currentRuleType.key) - context.coroutineScope.launch(context.database.executor.asCoroutineDispatcher()) { - updateDispatcher.dispatch() - } - confirmationDialog = false - } - ) - } - } - - Button(onClick = { confirmationDialog = true }) { - Text(text = translation["clear_list_button"]) - } - } - } - } -} \ No newline at end of file diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/home/HomeLogs.kt b/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/home/HomeLogs.kt deleted file mode 100644 index d8b91c8a..00000000 --- a/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/home/HomeLogs.kt +++ /dev/null @@ -1,250 +0,0 @@ -@file:OptIn(androidx.compose.foundation.ExperimentalFoundationApi::class) -package me.rhunk.snapenhance.ui.manager.pages.home - -import android.net.Uri -import androidx.compose.foundation.ScrollState -import androidx.compose.foundation.background -import androidx.compose.foundation.gestures.detectTapGestures -import androidx.compose.foundation.horizontalScroll -import androidx.compose.foundation.layout.* -import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.LazyListState -import androidx.compose.foundation.ExperimentalFoundationApi -import androidx.compose.animation.animateContentSize -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.KeyboardDoubleArrowDown -import androidx.compose.material.icons.filled.KeyboardDoubleArrowUp -import androidx.compose.material.icons.filled.MoreVert -import androidx.compose.material.icons.outlined.BugReport -import androidx.compose.material.icons.outlined.Info -import androidx.compose.material.icons.outlined.Report -import androidx.compose.material.icons.outlined.Warning -import androidx.compose.material3.* -import androidx.compose.runtime.* -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.input.pointer.pointerInput -import androidx.compose.ui.platform.ClipboardManager -import androidx.compose.ui.platform.LocalClipboardManager -import androidx.compose.ui.text.AnnotatedString -import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.text.style.TextOverflow -import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp -import androidx.navigation.NavBackStackEntry -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.delay -import kotlinx.coroutines.launch -import kotlinx.coroutines.runBlocking -import kotlinx.coroutines.withContext -import me.rhunk.snapenhance.LogReader -import me.rhunk.snapenhance.common.logger.LogChannel -import me.rhunk.snapenhance.common.logger.LogLevel -import me.rhunk.snapenhance.ui.manager.Routes -import me.rhunk.snapenhance.ui.util.ActivityLauncherHelper -import me.rhunk.snapenhance.ui.util.pullrefresh.PullRefreshIndicator -import me.rhunk.snapenhance.ui.util.pullrefresh.rememberPullRefreshState -import me.rhunk.snapenhance.ui.util.saveFile - -class HomeLogs : Routes.Route() { - private val logListState by lazy { LazyListState(0) } - private lateinit var activityLauncherHelper: ActivityLauncherHelper - override val init: () -> Unit = { - activityLauncherHelper = ActivityLauncherHelper(context.activity!!) - } - override val topBarActions: @Composable (RowScope.() -> Unit) = { - var showDropDown by remember { mutableStateOf(false) } - IconButton(onClick = { - showDropDown = true - }) { - Icon(Icons.Filled.MoreVert, contentDescription = null) - } - DropdownMenu( - expanded = showDropDown, - onDismissRequest = { showDropDown = false }, - modifier = Modifier.align(Alignment.CenterVertically) - ) { - DropdownMenuItem(onClick = { - context.coroutineScope.launch { - context.log.clearLogs() - } - navigateReload() - showDropDown = false - }, text = { - Text(translation["clear_logs_button"]) - }) - DropdownMenuItem(onClick = { - activityLauncherHelper.saveFile("purrfectsnap-logs-${System.currentTimeMillis()}.zip", "application/zip") { uri -> - context.coroutineScope.launch { - context.shortToast(translation["saving_logs_toast"]) - context.androidContext.contentResolver.openOutputStream(Uri.parse(uri))?.use { - runCatching { - context.log.exportLogsToZip(it) - context.longToast(translation["saved_logs_success_toast"]) - }.onFailure { - context.longToast(translation["saved_logs_failure_toast"]) - context.log.error("Failed to save logs to ${'$'}uri!", it) - } - } - } - } - showDropDown = false - }, text = { - Text(translation["export_logs_button"]) - }) - } - } - @Suppress("DEPRECATION") - override val content: @Composable (NavBackStackEntry) -> Unit = { - val coroutineScope = rememberCoroutineScope() - val clipboard: ClipboardManager = LocalClipboardManager.current - var lineCount by remember { mutableIntStateOf(0) } - var logReader by remember { mutableStateOf(null) } - var isRefreshing by remember { mutableStateOf(false) } - fun refreshLogs() { - coroutineScope.launch(Dispatchers.IO) { - runCatching { - logReader = context.log.newReader { - lineCount++ - } - lineCount = logReader!!.lineCount - }.onFailure { - context.longToast("Failed to read logs!") - } - delay(300) - isRefreshing = false - withContext(Dispatchers.Main) { - logListState.scrollToItem((logListState.layoutInfo.totalItemsCount - 1).takeIf { it >= 0 } ?: return@withContext) - } - } - } - val pullRefreshState = rememberPullRefreshState(isRefreshing, onRefresh = { - refreshLogs() - }) - LaunchedEffect(Unit) { - isRefreshing = true - refreshLogs() - } - Box( - modifier = Modifier - .fillMaxSize() - ) { - LazyColumn( - modifier = Modifier - .background(MaterialTheme.colorScheme.surface) - .horizontalScroll(ScrollState(0)), - state = logListState, - contentPadding = PaddingValues(bottom = routes.bottomPadding) - ) { - item { - if (lineCount == 0 && logReader != null) { - Text( - text = translation["no_logs_hint"], - modifier = Modifier.padding(16.dp), - fontSize = 12.sp, - fontWeight = FontWeight.Light - ) - } - } - items(lineCount) { index -> - val logLine by remember(index) { - mutableStateOf(runBlocking(Dispatchers.IO) { - logReader?.getLogLine(index) - }) - } - logLine?.let { line -> - Box( - modifier = Modifier - .fillMaxWidth() - .animateContentSize() - .pointerInput(Unit) { - detectTapGestures( - onLongPress = { - coroutineScope.launch { - clipboard.setText( - AnnotatedString(line.message) - ) - } - } - ) - } - ) { - Column( - modifier = Modifier - .padding(4.dp) - .fillMaxWidth() - .defaultMinSize(minHeight = 30.dp), - ) { - Row( - verticalAlignment = Alignment.CenterVertically, - ) { - Icon( - imageVector = when (line.logLevel) { - LogLevel.DEBUG -> Icons.Outlined.BugReport - LogLevel.ERROR, LogLevel.ASSERT -> Icons.Outlined.Report - LogLevel.INFO, LogLevel.VERBOSE -> Icons.Outlined.Info - LogLevel.WARN -> Icons.Outlined.Warning - }, - modifier = Modifier.size(16.dp), - contentDescription = null, - ) - Text( - text = LogChannel.fromChannel(line.tag)?.shortName ?: line.tag, - modifier = Modifier.padding(start = 4.dp), - fontWeight = FontWeight.Bold, - fontSize = 12.sp, - ) - Text( - text = line.dateTime, - modifier = Modifier.padding(start = 4.dp, end = 4.dp), - fontSize = 10.sp - ) - } - Text( - text = line.message.trimIndent(), - lineHeight = 10.sp, - fontSize = 9.sp, - maxLines = Int.MAX_VALUE, - ) - } - } - } - } - } - PullRefreshIndicator( - refreshing = isRefreshing, - state = pullRefreshState, - modifier = Modifier.align(Alignment.TopCenter) - ) - } - } - override val floatingActionButton: @Composable () -> Unit = { - val coroutineScope = rememberCoroutineScope() - Column( - verticalArrangement = Arrangement.spacedBy(5.dp), - ) { - val firstVisibleItem by remember { derivedStateOf { logListState.firstVisibleItemIndex } } - val layoutInfo by remember { derivedStateOf { logListState.layoutInfo } } - FilledIconButton( - onClick = { - coroutineScope.launch { - logListState.scrollToItem(0) - } - }, - enabled = firstVisibleItem != 0 - ) { - Icon(Icons.Filled.KeyboardDoubleArrowUp, contentDescription = null) - } - FilledIconButton( - onClick = { - coroutineScope.launch { - logListState.scrollToItem((logListState.layoutInfo.totalItemsCount - 1).takeIf { it >= 0 } ?: return@launch) - } - }, - enabled = layoutInfo.visibleItemsInfo.lastOrNull()?.index != layoutInfo.totalItemsCount - 1 - ) { - Icon(Icons.Filled.KeyboardDoubleArrowDown, contentDescription = null) - } - } - } -} \ No newline at end of file diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/home/HomeRootSection.kt b/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/home/HomeRootSection.kt deleted file mode 100644 index d1a44260..00000000 --- a/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/home/HomeRootSection.kt +++ /dev/null @@ -1,849 +0,0 @@ -package me.rhunk.snapenhance.ui.manager.pages.home - -import androidx.compose.animation.AnimatedContent -import androidx.compose.animation.ExperimentalAnimationApi -import androidx.compose.animation.core.Spring -import androidx.compose.animation.core.animateFloatAsState -import androidx.compose.animation.core.spring -import androidx.compose.animation.core.tween -import androidx.compose.foundation.ExperimentalFoundationApi -import androidx.compose.foundation.LocalIndication -import androidx.compose.foundation.clickable -import androidx.compose.foundation.gestures.detectDragGestures -import androidx.compose.foundation.interaction.MutableInteractionSource -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.BoxWithConstraints -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.ColumnScope -import androidx.compose.foundation.layout.ExperimentalLayoutApi -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.RowScope -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.offset -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size -import androidx.compose.foundation.layout.width -import androidx.compose.foundation.rememberScrollState -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.foundation.verticalScroll -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.automirrored.filled.Help -import androidx.compose.material.icons.filled.Add -import androidx.compose.material.icons.filled.BugReport -import androidx.compose.material.icons.filled.Check -import androidx.compose.material.icons.filled.Close -import androidx.compose.material.icons.filled.Download -import androidx.compose.material.icons.filled.Download -import androidx.compose.material.icons.filled.DragHandle -import androidx.compose.material.icons.filled.Settings -import androidx.compose.material.icons.outlined.Widgets -import androidx.compose.material3.Button -import androidx.compose.material3.CardDefaults -import androidx.compose.material3.CircularProgressIndicator -import androidx.compose.material3.ElevatedCard -import androidx.compose.material3.ExperimentalMaterial3Api -import androidx.compose.material3.FilterChip -import androidx.compose.material3.Icon -import androidx.compose.material3.IconButton -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.OutlinedCard -import androidx.compose.material3.Surface -import androidx.compose.material3.Text -import androidx.compose.runtime.* -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.clip -import androidx.compose.ui.geometry.Offset -import androidx.compose.ui.geometry.Rect -import androidx.compose.ui.geometry.Size -import androidx.compose.ui.graphics.vector.ImageVector -import androidx.compose.ui.input.pointer.pointerInput -import androidx.compose.ui.platform.LocalDensity -import androidx.compose.ui.res.vectorResource -import androidx.compose.ui.text.LinkAnnotation -import androidx.compose.ui.text.SpanStyle -import androidx.compose.ui.text.buildAnnotatedString -import androidx.compose.ui.text.font.Font -import androidx.compose.ui.text.font.FontFamily -import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.text.style.TextAlign -import androidx.compose.ui.text.style.TextOverflow -import androidx.compose.ui.text.withLink -import androidx.compose.ui.text.withStyle -import androidx.compose.ui.unit.Dp -import androidx.compose.ui.unit.IntOffset -import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp -import androidx.navigation.NavBackStackEntry -import kotlinx.coroutines.launch -import me.rhunk.snapenhance.R -import me.rhunk.snapenhance.action.EnumQuickActions -import me.rhunk.snapenhance.common.BuildConfig -import me.rhunk.snapenhance.common.action.EnumAction -import me.rhunk.snapenhance.common.ui.TopBarActionButton -import me.rhunk.snapenhance.common.ui.rememberAsyncMutableState -import me.rhunk.snapenhance.common.ui.rememberAsyncMutableStateList -import me.rhunk.snapenhance.common.util.ktx.openLink - -import me.rhunk.snapenhance.storage.getQuickTiles -import me.rhunk.snapenhance.storage.setQuickTiles -import me.rhunk.snapenhance.ui.manager.Routes -import me.rhunk.snapenhance.ui.manager.data.UpdateDownloader -import me.rhunk.snapenhance.ui.manager.data.Updater -import me.rhunk.snapenhance.ui.util.ActivityLauncherHelper -import me.rhunk.snapenhance.ui.util.AlertDialogs -import me.rhunk.snapenhance.ui.util.scaleOnPress -import java.text.DateFormat -import kotlin.math.roundToInt - -class HomeRootSection : Routes.Route() { - override val translation by lazy { context.translation.getCategory("manager.sections.home") } - - companion object { - val cardMargin = 10.dp - } - private lateinit var activityLauncherHelper: ActivityLauncherHelper - data class QaCard(val id: String, val name: String, val icon: ImageVector, val action: (Routes) -> Unit) - private val cardEntries by lazy { - val list = mutableListOf() - EnumQuickActions.entries.forEach { q -> - val name = context.translation["actions.${q.key}.name"] - list.add(QaCard(id = "quick.${q.key}", name = name, icon = q.icon, action = q.action)) - } - EnumAction.entries.forEach { a -> - val name = context.translation["actions.${a.key}.name"] - list.add(QaCard(id = "action.${a.key}", name = name, icon = a.icon, action = { context.launchActionIntent(a) })) - } - list - } - private val cards by lazy { - EnumQuickActions.entries.map { - (context.translation["actions.${it.key}.name"] to it.icon) to it.action - }.associate { - it.first to it.second - }.toMutableMap().apply { - EnumAction.entries.forEach { action -> - this[context.translation["actions.${action.key}.name"] to action.icon] = { - context.launchActionIntent(action) - } - } - } - } - @Composable - private fun InfoCard(content: @Composable ColumnScope.() -> Unit) { - OutlinedCard( - modifier = Modifier - .padding(start = cardMargin, end = cardMargin) - .fillMaxWidth(), - colors = CardDefaults.cardColors( - containerColor = MaterialTheme.colorScheme.surfaceVariant, - contentColor = MaterialTheme.colorScheme.onSurfaceVariant - ) - ) { - Column( - modifier = Modifier - .fillMaxWidth() - .padding(all = 10.dp) - ) { - content() - } - } - } - @Composable - fun ExternalLinkIcon( - modifier: Modifier = Modifier, - size: Dp = 32.dp, - imageVector: ImageVector, - onClick: (() -> Unit)? = null, - ) { - val interactionSource = remember { MutableInteractionSource() } - Icon( - imageVector = imageVector, - contentDescription = null, - tint = MaterialTheme.colorScheme.onSurfaceVariant, - modifier = Modifier - .size(size) - .clip(RoundedCornerShape(50)) - .scaleOnPress(interactionSource) - .then( - if (onClick != null) - Modifier.clickable(interactionSource = interactionSource, indication = LocalIndication.current) { onClick() } - else Modifier - ) - .then(modifier) - ) - } - private fun resolveTileKey(name: String): String { - val entry = cardEntries.firstOrNull { it.name == name } - return entry?.id ?: name - } - private fun getTileSpan(name: String): Pair { - val prefs = context.sharedPreferences - val key = resolveTileKey(name) - val raw = prefs.getString("quick_tile_size_$key", null) ?: "1x1" - val parts = raw.split('x') - val w = parts.getOrNull(0)?.toIntOrNull()?.coerceIn(1, 3) ?: 1 - val h = parts.getOrNull(1)?.toIntOrNull()?.coerceIn(1, 3) ?: 1 - return w to h - } - private fun setTileSpan(name: String, w: Int, h: Int) { - val prefs = context.sharedPreferences - val key = resolveTileKey(name) - prefs.edit().putString("quick_tile_size_$key", "${w.coerceIn(1,3)}x${h.coerceIn(1,3)}").apply() - } - private fun clearTileSpan(name: String) { - val prefs = context.sharedPreferences - val key = resolveTileKey(name) - prefs.edit().remove("quick_tile_size_$key").apply() - } - - private fun getTileOffset(name: String): Pair { - val prefs = context.sharedPreferences - val key = resolveTileKey(name) - val raw = prefs.getString("quick_tile_offset_$key", null) - if (raw == null) return 0f to 0f - val parts = raw.split(',') - val x = parts.getOrNull(0)?.toFloatOrNull() ?: 0f - val y = parts.getOrNull(1)?.toFloatOrNull() ?: 0f - return x to y - } - - private fun setTileOffset(name: String, x: Float, y: Float) { - val prefs = context.sharedPreferences - val key = resolveTileKey(name) - prefs.edit().putString("quick_tile_offset_$key", "$x,$y").apply() - } - - private fun clearTileOffset(name: String) { - val prefs = context.sharedPreferences - val key = resolveTileKey(name) - prefs.edit().remove("quick_tile_offset_$key").apply() - } - - override val title: @Composable (() -> Unit)? = {} - override val init: () -> Unit = { - activityLauncherHelper = ActivityLauncherHelper(context.activity!!) - } - override val topBarActions: @Composable (RowScope.() -> Unit) = { - TopBarActionButton( - onClick = { - routes.homeLogs.navigate() - }, - icon = Icons.Filled.BugReport, - text = context.translation["manager.routes.home_logs"] - ) - Spacer(modifier = Modifier.width(8.dp)) - TopBarActionButton( - onClick = { - routes.settings.navigate() - }, - icon = Icons.Filled.Settings, - text = context.translation["manager.routes.home_settings"] - ) - } - - @OptIn(ExperimentalLayoutApi::class, ExperimentalAnimationApi::class, ExperimentalFoundationApi::class, ExperimentalMaterial3Api::class) - override val content: @Composable (NavBackStackEntry) -> Unit = { - val avenirNext = remember { - FontFamily(Font(R.font.avenir_next_medium, FontWeight.Medium)) - } - val selectedTiles = rememberAsyncMutableStateList(defaultValue = listOf()) { - context.database.getQuickTiles().filter { it.isNotBlank() } - } - val latestUpdate by rememberAsyncMutableState(defaultValue = null) { Updater.latestRelease } - var showQuickActionsMenu by remember { mutableStateOf(false) } - var editMode by remember { mutableStateOf(false) } - val scrollState = rememberScrollState() - Column( - modifier = Modifier - .fillMaxSize() - .verticalScroll(scrollState, enabled = !editMode) - ) { - Text( - "PurrfectSnap", - modifier = Modifier - .fillMaxWidth() - .padding(all = 8.dp) - .align(Alignment.CenterHorizontally), - color = MaterialTheme.colorScheme.onSurfaceVariant, - fontSize = 48.sp, - fontWeight = FontWeight.Bold, - fontFamily = avenirNext, - textAlign = TextAlign.Center - ) - Text( - text = translation.format( - "version_title", - "versionName" to BuildConfig.VERSION_NAME - ), - fontSize = 14.sp, - fontFamily = avenirNext, - modifier = Modifier.align(Alignment.CenterHorizontally), - ) - Row( - horizontalArrangement = Arrangement.spacedBy(15.dp, Alignment.CenterHorizontally), - verticalAlignment = Alignment.CenterVertically, - modifier = Modifier - .fillMaxWidth() - .padding(all = 5.dp) - ) { - ExternalLinkIcon( - onClick = { context.androidContext.openLink("https://t.me/purrfectsnap") }, - imageVector = ImageVector.vectorResource(id = R.drawable.ic_telegram), - ) - ExternalLinkIcon( - onClick = { context.androidContext.openLink("https://github.com/particle-box/PurrfectSnap") }, - imageVector = ImageVector.vectorResource(id = R.drawable.ic_github), - ) - ExternalLinkIcon( - onClick = { context.androidContext.openLink("https://github.com/particle-box/PurrfectSnap/wiki") }, - modifier = Modifier.offset(x = (-3).dp), - size = 40.dp, - imageVector = Icons.AutoMirrored.Filled.Help, - ) - } - if (latestUpdate != null) { - Spacer(modifier = Modifier.height(10.dp)) - InfoCard { - Row( - modifier = Modifier.fillMaxWidth(), - horizontalArrangement = Arrangement.SpaceBetween, - verticalAlignment = Alignment.CenterVertically - ) { - Column { - Text( - text = translation["update_title"], - fontSize = 14.sp, - fontWeight = FontWeight.Bold, - ) - Text( - fontSize = 12.sp, - text = translation.format( - "update_content", - "version" to (latestUpdate?.versionName ?: "unknown") - ), - lineHeight = 20.sp, - overflow = TextOverflow.Ellipsis, - ) - } - val downloadState by UpdateDownloader.downloadState.collectAsState() - val downloadProgress by UpdateDownloader.downloadProgress.collectAsState() - val coroutineScope = rememberCoroutineScope() - - AnimatedContent( - targetState = downloadState, - modifier = Modifier.height(40.dp) - ) { state -> - when (state) { - UpdateDownloader.DownloadState.IDLE -> { - IconButton( - onClick = { - val latest = latestUpdate ?: return@IconButton - if (latest.workflowId == null) { - context.androidContext.openLink(latest.releaseUrl) - return@IconButton - } - val supportedAbis = android.os.Build.SUPPORTED_ABIS - var abiName: String? = null - for (abi in supportedAbis) { - when (abi) { - "arm64-v8a" -> { - abiName = "armv8" - break - } - "armeabi-v7a" -> { - abiName = "armv7" - break - } - } - } - - if (abiName != null) { - val artifactName = "purrfectsnap-${abiName}-debug" - val downloadUrl = "https://nightly.link/particle-box/PurrfectSnap/actions/runs/${latest.workflowId}/$artifactName.zip" - UpdateDownloader.downloadAndInstall(context.androidContext, downloadUrl, "$artifactName.zip", coroutineScope) - } else { - android.widget.Toast.makeText(context.androidContext, "Your device architecture is not supported for automatic updates.", android.widget.Toast.LENGTH_LONG).show() - } - }, - modifier = Modifier.scaleOnPress(remember { MutableInteractionSource() }) - ) { - Icon(imageVector = Icons.Default.Download, contentDescription = translation["download_icon_description"]) - } - } - UpdateDownloader.DownloadState.DOWNLOADING -> { - CircularProgressIndicator(progress = { downloadProgress }) - } - UpdateDownloader.DownloadState.COMPLETED -> { - Icon(imageVector = Icons.Default.Check, contentDescription = translation["completed_icon_description"]) - } - UpdateDownloader.DownloadState.FAILED -> { - Icon(imageVector = Icons.Default.Close, contentDescription = translation["failed_icon_description"]) - } - } - } - } - } - } - if (BuildConfig.DEBUG) { - Spacer(modifier = Modifier.height(10.dp)) - InfoCard { - Text( - text = translation["debug_build_summary_title"], - fontSize = 14.sp, - fontWeight = FontWeight.Bold, - ) - val buildSummary = buildAnnotatedString { - withStyle( - style = SpanStyle( - fontSize = 13.sp, - color = MaterialTheme.colorScheme.onSurfaceVariant, - fontWeight = FontWeight.Light - ) - ) { - append( - remember { - translation.format( - "debug_build_summary_content", - "versionName" to BuildConfig.VERSION_NAME, - "versionCode" to BuildConfig.VERSION_CODE.toString(), - ) - } - ) - append(" - ") - } - withLink( - LinkAnnotation.Clickable( - "git_hash", - linkInteractionListener = { - context.androidContext.openLink("https://github.com/particle-box/PurrfectSnap/commit/${BuildConfig.GIT_HASH}") - } - ) - ) { - withStyle( - style = SpanStyle( - fontSize = 13.sp, fontWeight = FontWeight.Bold, - color = MaterialTheme.colorScheme.primary - ) - ) { - append(BuildConfig.GIT_HASH.substring(0, 7)) - } - } - } - Text(text = buildSummary) - Text( - fontSize = 12.sp, - text = remember { - translation.format( - "debug_build_summary_date", - "date" to DateFormat.getDateTimeInstance().format(BuildConfig.BUILD_TIMESTAMP), - "days" to ((System.currentTimeMillis() - BuildConfig.BUILD_TIMESTAMP) / 86400000).toInt().toString() - ) - }, - lineHeight = 20.sp, - fontWeight = FontWeight.Light - ) - } - } - Spacer(modifier = Modifier.height(12.dp)) - AnimatedContent(targetState = selectedTiles.isNotEmpty(), label = "QuickActionsAnim") { hasQuickActions -> - Column(horizontalAlignment = Alignment.CenterHorizontally) { - if (!hasQuickActions) { - Box( - modifier = Modifier - .fillMaxWidth() - .padding(bottom = 4.dp) - ) { - Surface( - shape = RoundedCornerShape(50), - color = MaterialTheme.colorScheme.secondaryContainer, - tonalElevation = 2.dp, - shadowElevation = 4.dp, - modifier = Modifier.align(Alignment.Center) - ) { - Text( - translation["quick_actions_title"], - fontSize = 18.sp, - fontWeight = FontWeight.Medium, - color = MaterialTheme.colorScheme.onSecondaryContainer, - textAlign = TextAlign.Center, - modifier = Modifier.padding(horizontal = 14.dp, vertical = 4.dp) - ) - } - } - Box( - modifier = Modifier - .fillMaxWidth() - .height(260.dp), - contentAlignment = Alignment.Center - ) { - Column( - horizontalAlignment = Alignment.CenterHorizontally, - verticalArrangement = Arrangement.Center - ) { - Icon( - imageVector = Icons.Outlined.Widgets, - contentDescription = translation["quick_actions_icon_description"], - modifier = Modifier.size(64.dp), - tint = MaterialTheme.colorScheme.primary - ) - Spacer(modifier = Modifier.height(10.dp)) - Text( - text = "No quick actions added yet", - style = MaterialTheme.typography.bodyMedium, - color = MaterialTheme.colorScheme.onSurfaceVariant - ) - Spacer(modifier = Modifier.height(10.dp)) - Button( - onClick = { showQuickActionsMenu = true }, - modifier = Modifier.align(Alignment.CenterHorizontally) - ) { - Icon( - imageVector = Icons.Default.Add, - contentDescription = translation["add_quick_action_description"], - modifier = Modifier.size(22.dp) - ) - Spacer(modifier = Modifier.width(6.dp)) - Text(text = "Add") - } - } - } - } else { - Row( - modifier = Modifier - .fillMaxWidth() - .padding(horizontal = 20.dp, vertical = 4.dp), - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.SpaceBetween - ) { - Text( - translation["quick_actions_title"], - fontSize = 20.sp, - fontWeight = FontWeight.SemiBold, - textAlign = TextAlign.Start, - color = MaterialTheme.colorScheme.onBackground, - modifier = Modifier.weight(1f) - ) - IconButton( - onClick = { showQuickActionsMenu = true }, - modifier = Modifier.align(Alignment.CenterVertically) - ) { - Icon( - imageVector = ImageVector.vectorResource(id = R.drawable.ic_manage), - contentDescription = translation["manage_quick_actions_description"] - ) - } - FilterChip( - selected = editMode, - onClick = { editMode = !editMode }, - label = { Text(if (editMode) "Done" else "Edit") }, - leadingIcon = { Icon(Icons.Filled.DragHandle, contentDescription = null) } - ) - } - val spacing = 6.dp - var spanTick by remember { mutableIntStateOf(0) } - - BoxWithConstraints( - modifier = Modifier - .fillMaxWidth() - .padding(horizontal = cardMargin) - ) { - val density = LocalDensity.current - val baseCell = remember { (maxWidth - (spacing * 2)) / 3f } - val baseCellPx = with(density) { baseCell.toPx() } - - val (tilePositions, totalHeight) = remember(selectedTiles.size, spanTick) { - val positions = mutableMapOf() - var currentX = 0f - var currentY = 0f - var rowMaxHeight = 0f - val screenWidthPx = with(density) { maxWidth.toPx() } - - selectedTiles.forEach { tileName -> - cards.entries.find { entry -> entry.key.first == tileName }?.let { - val card = it.key - val (wSpan, hSpan) = getTileSpan(card.first) - val tileWidthPx = with(density) { (baseCell * wSpan + spacing * (wSpan - 1)).toPx() } - val tileHeightPx = with(density) { (baseCell * hSpan + spacing * (hSpan - 1)).toPx() } - - if (currentX + tileWidthPx > screenWidthPx) { - currentX = 0f - currentY += rowMaxHeight - rowMaxHeight = 0f - } - - positions[tileName] = Offset(currentX, currentY) - currentX += tileWidthPx + with(density) { spacing.toPx() } - if (tileHeightPx > rowMaxHeight) { - rowMaxHeight = tileHeightPx - } - } - } - positions to (currentY + rowMaxHeight) - } - - Box(modifier = Modifier.height(with(density) { totalHeight.toDp() })) { - remember(selectedTiles.size, context.translation.loadedLocale) { - selectedTiles.mapNotNull { - cards.entries.find { entry -> entry.key.first == it } - } - }.forEach { (card, action) -> - val interactionSource = remember { MutableInteractionSource() } - val _tick = spanTick - val (wSpan, hSpan) = getTileSpan(card.first) - val tileWidth = baseCell * wSpan + spacing * (wSpan - 1) - val tileHeight = baseCell * hSpan + spacing * (hSpan - 1) - val tileWidthPx = with(density) { tileWidth.toPx() } - val tileHeightPx = with(density) { tileHeight.toPx() } - - var offsetX by remember(card.first) { mutableStateOf(0f) } - var offsetY by remember(card.first) { mutableStateOf(0f) } - var isDragging by remember { mutableStateOf(false) } - - LaunchedEffect(card.first, spanTick) { - val (x, y) = getTileOffset(card.first) - if (x != 0f || y != 0f) { - offsetX = x - offsetY = y - } else { - val pos = tilePositions[card.first] - if (pos != null) { - offsetX = pos.x - offsetY = pos.y - setTileOffset(card.first, offsetX, offsetY) - } - } - } - - val animatedOffsetX by animateFloatAsState( - targetValue = offsetX, - animationSpec = spring( - dampingRatio = Spring.DampingRatioMediumBouncy, - stiffness = Spring.StiffnessLow - ), - label = "offsetX" - ) - val animatedOffsetY by animateFloatAsState( - targetValue = offsetY, - animationSpec = spring( - dampingRatio = Spring.DampingRatioMediumBouncy, - stiffness = Spring.StiffnessLow - ), - label = "offsetY" - ) - - val currentOffsetX = if (isDragging) offsetX else animatedOffsetX - val currentOffsetY = if (isDragging) offsetY else animatedOffsetY - - val baseModifier = Modifier - .offset { IntOffset(currentOffsetX.roundToInt(), currentOffsetY.roundToInt()) } - .width(tileWidth) - .height(tileHeight) - .padding(all = 6.dp) - - val editModifier = baseModifier.then( - Modifier.pointerInput(card.first, tileWidthPx, tileHeightPx) { - var originalOffsetX = 0f - var originalOffsetY = 0f - detectDragGestures( - onDragStart = { - isDragging = true - originalOffsetX = offsetX - originalOffsetY = offsetY - }, - onDrag = { change, dragAmount -> - change.consume() - offsetX += dragAmount.x - offsetY += dragAmount.y - }, - onDragEnd = { - isDragging = false - var targetTile: String? = null - var maxOverlap = 0f - val tileRect = Rect(Offset(offsetX, offsetY), Size(tileWidthPx, tileHeightPx)) - - for (otherTileName in selectedTiles) { - if (otherTileName == card.first) continue - val (otherOffsetX, otherOffsetY) = getTileOffset(otherTileName) - val (otherWSpan, otherHSpan) = getTileSpan(otherTileName) - val otherTileWidth = baseCell * otherWSpan + spacing * (otherWSpan - 1) - val otherTileHeight = baseCell * otherHSpan + spacing * (otherHSpan - 1) - val otherRect = Rect(Offset(otherOffsetX, otherOffsetY), Size(with(density) { otherTileWidth.toPx() }, with(density) { otherTileHeight.toPx() })) - val intersectRect = tileRect.intersect(otherRect) - val overlapArea = intersectRect.width * intersectRect.height - if (overlapArea > maxOverlap) { - maxOverlap = overlapArea - targetTile = otherTileName - } - } - - if (targetTile != null) { - val (wSpan, hSpan) = getTileSpan(card.first) - val (targetWSpan, targetHSpan) = getTileSpan(targetTile!!) - if (wSpan == targetWSpan && hSpan == targetHSpan) { - // swap - val (targetOffsetX, targetOffsetY) = getTileOffset(targetTile!!) - setTileOffset(card.first, targetOffsetX, targetOffsetY) - setTileOffset(targetTile!!, originalOffsetX, originalOffsetY) - spanTick++ // this will trigger recomposition for all tiles - } else { - // revert - offsetX = originalOffsetX - offsetY = originalOffsetY - } - } else { - setTileOffset(card.first, offsetX, offsetY) - } - } - ) - } - ) - val viewModifier = baseModifier.then(Modifier.scaleOnPress(interactionSource)) - - if (editMode) { - ElevatedCard( - modifier = editModifier - ) { - Box(Modifier.fillMaxSize()) { - Column( - modifier = Modifier - .fillMaxSize() - .padding(all = 5.dp), - horizontalAlignment = Alignment.CenterHorizontally, - verticalArrangement = Arrangement.SpaceEvenly, - ) { - Icon( - imageVector = card.second, contentDescription = null, - tint = MaterialTheme.colorScheme.onSurfaceVariant, - modifier = Modifier.size(50.dp) - ) - Text( - text = card.first, - lineHeight = 16.sp, - fontSize = 14.sp, - fontWeight = FontWeight.Bold, - textAlign = TextAlign.Center, - overflow = TextOverflow.Ellipsis, - ) - } - // Drag handle for resizing - var dxAccResize by remember(card.first, spanTick) { mutableStateOf(0f) } - var dyAccResize by remember(card.first, spanTick) { mutableStateOf(0f) } - Box( - modifier = Modifier - .align(Alignment.BottomEnd) - .size(28.dp) - .pointerInput(card.first, spanTick) { - detectDragGestures( - onDragStart = { - dxAccResize = 0f - dyAccResize = 0f - }, - onDrag = { change, dragAmount -> - change.consume() - dxAccResize += dragAmount.x - dyAccResize += dragAmount.y - - var newW = wSpan - var newH = hSpan - val step = baseCellPx / 2f - - while (dxAccResize > step) { - newW = (wSpan + 1).coerceIn(1, 3) - dxAccResize -= step - } - while (dxAccResize < -step) { - newW = (wSpan - 1).coerceIn(1, 3) - dxAccResize += step - } - while (dyAccResize > step) { - newH = (hSpan + 1).coerceIn(1, 3) - dyAccResize -= step - } - while (dyAccResize < -step) { - newH = (hSpan - 1).coerceIn(1, 3) - dyAccResize += step - } - - if (newW != wSpan || newH != hSpan) { - setTileSpan(card.first, newW, newH) - spanTick++ - selectedTiles.forEach { clearTileOffset(it) } - } - } - ) - }, - contentAlignment = Alignment.Center - ) { - Icon(Icons.Filled.DragHandle, contentDescription = null, tint = MaterialTheme.colorScheme.onSurfaceVariant) - } - } - } - } else { - ElevatedCard( - modifier = viewModifier, - onClick = { action(routes) }, - interactionSource = interactionSource - ) { - Box(Modifier.fillMaxSize()) { - Column( - modifier = Modifier - .fillMaxSize() - .padding(all = 5.dp), - horizontalAlignment = Alignment.CenterHorizontally, - verticalArrangement = Arrangement.SpaceEvenly, - ) { - Icon( - imageVector = card.second, contentDescription = null, - tint = MaterialTheme.colorScheme.onSurfaceVariant, - modifier = Modifier.size(50.dp) - ) - Text( - text = card.first, - lineHeight = 16.sp, - fontSize = 14.sp, - fontWeight = FontWeight.Bold, - textAlign = TextAlign.Center, - overflow = TextOverflow.Ellipsis, - ) - } - } - } - } - } - } - } - } - } - } - if (showQuickActionsMenu) { - QuickActionsDialog( - quickActions = cards, - selectedQuickActions = selectedTiles, - onDismiss = { showQuickActionsMenu = false }, - onSave = { newList -> - val previous = selectedTiles.toList() - val removed = previous.filter { it !in newList } - removed.forEach { clearTileSpan(it); clearTileOffset(it) } - newList.forEach { clearTileOffset(it) } - selectedTiles.clear() - selectedTiles.addAll(newList) - if (newList.isEmpty()) { - editMode = false - } - context.coroutineScope.launch { - context.database.setQuickTiles(selectedTiles) - } - showQuickActionsMenu = false - }, - translation = translation - ) - } - Spacer(modifier = Modifier.height(routes.bottomPadding)) - } - } -} diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/home/HomeSettings.kt b/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/home/HomeSettings.kt deleted file mode 100644 index 5a36081a..00000000 --- a/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/home/HomeSettings.kt +++ /dev/null @@ -1,594 +0,0 @@ -package me.rhunk.snapenhance.ui.manager.pages.home - -import android.content.SharedPreferences -import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.* -import androidx.compose.foundation.rememberScrollState -import androidx.compose.foundation.verticalScroll -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.automirrored.filled.OpenInNew -import androidx.compose.material.icons.filled.Brightness4 -import androidx.compose.material.icons.filled.MoreVert -import androidx.compose.material3.* -import androidx.compose.runtime.* -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.alpha -import androidx.compose.ui.hapticfeedback.HapticFeedbackType -import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.platform.LocalHapticFeedback -import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp -import androidx.compose.ui.window.Dialog -import androidx.core.content.edit -import androidx.core.net.toUri -import androidx.navigation.NavBackStackEntry -import androidx.work.Constraints -import androidx.work.Data -import androidx.work.ExistingPeriodicWorkPolicy -import androidx.work.NetworkType -import androidx.work.PeriodicWorkRequestBuilder -import androidx.work.WorkManager -import kotlinx.coroutines.launch -import me.rhunk.snapenhance.common.action.EnumAction -import me.rhunk.snapenhance.common.bridge.InternalFileHandleType -import me.rhunk.snapenhance.common.ui.ThemeChooserDialog -import me.rhunk.snapenhance.common.ui.ThemeMode -import me.rhunk.snapenhance.common.ui.ThemePreferences -import me.rhunk.snapenhance.common.ui.rememberAsyncMutableState -import me.rhunk.snapenhance.storage.getAllScopeNotes -import me.rhunk.snapenhance.storage.setAllScopeNotes -import me.rhunk.snapenhance.task.UpdateCheckWorker -import me.rhunk.snapenhance.ui.manager.Routes -import me.rhunk.snapenhance.ui.setup.Requirements -import me.rhunk.snapenhance.ui.util.ActivityLauncherHelper -import me.rhunk.snapenhance.ui.util.AlertDialogs -import me.rhunk.snapenhance.ui.util.openFile -import me.rhunk.snapenhance.ui.util.saveFile -import java.io.File -import java.io.FileOutputStream -import java.net.URLEncoder -import java.util.concurrent.TimeUnit - -class HomeSettings : Routes.Route() { - override val translation by lazy { context.translation.getCategory("manager.sections.home_settings") } - private lateinit var activityLauncherHelper: ActivityLauncherHelper - private val dialogs by lazy { AlertDialogs(context.translation) } - - private fun scheduleUpdateCheck() { - val workManager = WorkManager.getInstance(context.androidContext) - if (context.config.root.global.updateSettings.autoUpdateCheck.get()) { - val frequency = context.config.root.global.updateSettings.updateCheckFrequency.get() - val repeatInterval = when (frequency) { - "daily" -> 1L - "weekly" -> 7L - "monthly" -> 30L - else -> 1L - } - - val constraints = Constraints.Builder() - .setRequiredNetworkType(NetworkType.CONNECTED) - .build() - - val inputData = Data.Builder() - .putString("channel_name", translation["update_notification_channel_name"]) - .putString("channel_description", translation["update_notification_channel_description"]) - .putString("notification_title", translation["update_notification_title"]) - .putString("notification_text", translation["update_notification_text"]) - .build() - - val workRequest = PeriodicWorkRequestBuilder(repeatInterval, TimeUnit.DAYS) - .setConstraints(constraints) - .setInputData(inputData) - .build() - - workManager.enqueueUniquePeriodicWork( - "snapenhance_update_check", - ExistingPeriodicWorkPolicy.REPLACE, - workRequest - ) - } else { - workManager.cancelUniqueWork("snapenhance_update_check") - } - } - override val init: () -> Unit = { - activityLauncherHelper = ActivityLauncherHelper(context.activity!!) - } - @Composable - private fun RowTitle(title: String) { - Text(text = title, modifier = Modifier.padding(16.dp), fontSize = 20.sp, fontWeight = FontWeight.Bold) - } - @Composable - private fun PreferenceToggle(sharedPreferences: SharedPreferences, key: String, text: String) { - val realKey = "debug_$key" - var value by remember { mutableStateOf(sharedPreferences.getBoolean(realKey, false)) } - val hapticFeedback = LocalHapticFeedback.current - Row( - modifier = Modifier - .fillMaxWidth() - .heightIn(min = 55.dp) - .clickable { - if (context.config.root.global.uiSettings.hapticFeedback.get()) { - hapticFeedback.performHapticFeedback(HapticFeedbackType.LongPress) - } - value = !value - sharedPreferences - .edit() { - putBoolean(realKey, value) - } - }, - horizontalArrangement = Arrangement.SpaceBetween, - verticalAlignment = Alignment.CenterVertically - ) { - Text(text = text, modifier = Modifier.padding(end = 16.dp), fontSize = 14.sp) - Switch(checked = value, onCheckedChange = { - if (context.config.root.global.uiSettings.hapticFeedback.get()) { - hapticFeedback.performHapticFeedback(HapticFeedbackType.LongPress) - } - value = it - sharedPreferences.edit().putBoolean(realKey, it).apply() - }, modifier = Modifier.padding(end = 26.dp)) - } - } - @Composable - private fun RowAction(key: String, requireConfirmation: Boolean = false, action: () -> Unit) { - var confirmationDialog by remember { - mutableStateOf(false) - } - fun takeAction() { - if (requireConfirmation) { - confirmationDialog = true - } else { - action() - } - } - if (requireConfirmation && confirmationDialog) { - Dialog(onDismissRequest = { confirmationDialog = false }) { - dialogs.ConfirmDialog(title = context.translation["manager.dialogs.action_confirm.title"], onConfirm = { - action() - confirmationDialog = false - }, onDismiss = { - confirmationDialog = false - }) - } - } - ShiftedRow( - modifier = Modifier - .fillMaxWidth() - .heightIn(min = 55.dp) - .clickable { - takeAction() - }, - horizontalArrangement = Arrangement.SpaceBetween, - verticalAlignment = Alignment.CenterVertically - ) { - Column( - modifier = Modifier.weight(1f), - ) { - Text(text = context.translation["actions.$key.name"], fontSize = 16.sp, fontWeight = FontWeight.Bold, lineHeight = 20.sp) - context.translation.getOrNull("actions.$key.description")?.let { Text(text = it, fontSize = 12.sp, fontWeight = FontWeight.Light, lineHeight = 15.sp) } - } - IconButton(onClick = { takeAction() }, - modifier = Modifier.padding(end = 2.dp) - ) { - Icon( - imageVector = Icons.AutoMirrored.Filled.OpenInNew, - contentDescription = context.translation.getOrNull("actions.$key.name"), - modifier = Modifier.size(24.dp) - ) - } - } - } - @Composable - private fun ShiftedRow( - modifier: Modifier = Modifier, - horizontalArrangement: Arrangement.Horizontal = Arrangement.Start, - verticalAlignment: Alignment.Vertical = Alignment.Top, - content: @Composable RowScope.() -> Unit - ) { - Row( - modifier = modifier.padding(start = 26.dp), - horizontalArrangement = horizontalArrangement, - verticalAlignment = verticalAlignment - ) { content(this) } - } - - @OptIn(ExperimentalMaterial3Api::class) - override val content: @Composable (NavBackStackEntry) -> Unit = { - val contextC = LocalContext.current - val scope = rememberCoroutineScope() - val themeMode by ThemePreferences.getThemeModeFlow(contextC).collectAsState(initial = ThemeMode.SYSTEM) - var showThemeDialog by remember { mutableStateOf(false) } - - Column( - modifier = Modifier - .fillMaxSize() - .verticalScroll(rememberScrollState()) - ) { - // APP THEME (Popup) - Spacer(Modifier.height(20.dp)) - Card( - modifier = Modifier - .fillMaxWidth() - .padding(horizontal = 16.dp) - .clickable { showThemeDialog = true }, - shape = MaterialTheme.shapes.medium, - elevation = CardDefaults.cardElevation(defaultElevation = 4.dp) - ) { - Row( - Modifier - .fillMaxWidth() - .padding(22.dp), - verticalAlignment = Alignment.CenterVertically - ) { - Icon( - imageVector = Icons.Filled.Brightness4, - contentDescription = translation["theme_icon_description"], - tint = MaterialTheme.colorScheme.primary, - modifier = Modifier.size(26.dp) - ) - Spacer(modifier = Modifier.width(18.dp)) - Column(Modifier.weight(1f)) { - Text(translation["app_theme_title"], fontWeight = FontWeight.Medium, fontSize = 16.sp) - Text(when (themeMode) { - ThemeMode.SYSTEM -> translation["theme_mode_system"] - ThemeMode.LIGHT -> translation["theme_mode_light"] - ThemeMode.DARK -> translation["theme_mode_dark"] - ThemeMode.AMOLED -> translation["theme_mode_dark"] + " (AMOLED)" - }, color = MaterialTheme.colorScheme.primary, fontSize = 14.sp) - } - } - } - if (showThemeDialog) { - ThemeChooserDialog( - selected = themeMode, - onSelect = { mode -> - scope.launch { - ThemePreferences.setThemeMode(contextC, mode) - } - }, - onDismiss = { showThemeDialog = false } - ) - } - Spacer(Modifier.height(20.dp)) - - RowTitle(title = translation["actions_title"]) - EnumAction.entries.forEach { enumAction -> - RowAction(key = enumAction.key) { - context.launchActionIntent(enumAction) - } - } - RowAction(key = "regen_mappings") { - context.checkForRequirements(Requirements.MAPPINGS) - } - RowAction(key = "change_language") { - context.checkForRequirements(Requirements.LANGUAGE) - } - - RowTitle(title = translation["ui_settings_title"]) - ShiftedRow { - Row( - modifier = Modifier - .fillMaxWidth() - .heightIn(min = 55.dp), - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.SpaceBetween - ) { - Text(text = translation["haptic_feedback_label"]) - var hapticFeedbackEnabled by remember { mutableStateOf(context.config.root.global.uiSettings.hapticFeedback.getNullable() ?: true) } - val hapticFeedback = LocalHapticFeedback.current - Switch( - checked = hapticFeedbackEnabled, - onCheckedChange = { - if (it) { - hapticFeedback.performHapticFeedback(HapticFeedbackType.LongPress) - } - hapticFeedbackEnabled = it - context.config.root.global.uiSettings.hapticFeedback.set(it) - context.config.writeConfig() - }, - modifier = Modifier.padding(end = 26.dp) - ) - } - } - - RowTitle(title = translation["updates_title"]) - ShiftedRow { - Column( - verticalArrangement = Arrangement.spacedBy(4.dp), - ) { - var autoUpdateCheck by remember { mutableStateOf(context.config.root.global.updateSettings.autoUpdateCheck.getNullable() ?: true) } - var selectedFrequency by remember { mutableStateOf(context.config.root.global.updateSettings.updateCheckFrequency.getNullable() ?: "weekly") } - var frequencyMenuExpanded by remember { mutableStateOf(false) } - - Row( - modifier = Modifier - .fillMaxWidth() - .heightIn(min = 55.dp), - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.SpaceBetween - ) { - Column { - Text(text = translation["auto_update_check"]) - if (autoUpdateCheck) { - Text( - text = translation["update_check_frequency_" + selectedFrequency], - fontSize = 12.sp, - fontWeight = FontWeight.Light - ) - } - } - - Row(verticalAlignment = Alignment.CenterVertically) { - Box { - IconButton( - onClick = { frequencyMenuExpanded = true }, - enabled = autoUpdateCheck, - modifier = Modifier.alpha(if (autoUpdateCheck) 1f else 0f) - ) { - Icon( - imageVector = Icons.Default.MoreVert, - contentDescription = translation["update_check_frequency"] - ) - } - if (autoUpdateCheck) { - DropdownMenu( - expanded = frequencyMenuExpanded, - onDismissRequest = { frequencyMenuExpanded = false } - ) { - val frequencies = remember { listOf("daily", "weekly", "monthly") } - frequencies.forEach { frequency -> - DropdownMenuItem( - text = { Text(text = translation["update_check_frequency_" + frequency]) }, - onClick = { - selectedFrequency = frequency - context.config.root.global.updateSettings.updateCheckFrequency.set(frequency) - context.config.writeConfig() - scheduleUpdateCheck() - frequencyMenuExpanded = false - } - ) - } - } - } - } - - val hapticFeedback = LocalHapticFeedback.current - Switch( - checked = autoUpdateCheck, - onCheckedChange = { - if (context.config.root.global.uiSettings.hapticFeedback.get()) { - hapticFeedback.performHapticFeedback(HapticFeedbackType.LongPress) - } - autoUpdateCheck = it - context.config.root.global.updateSettings.autoUpdateCheck.set(it) - if (it && context.config.root.global.updateSettings.updateCheckFrequency.getNullable() == null) { - context.config.root.global.updateSettings.updateCheckFrequency.set("weekly") - } - context.config.writeConfig() - scheduleUpdateCheck() - }, - modifier = Modifier.padding(end = 26.dp) - ) - } - } - } - } - - RowTitle(title = translation["message_logger_title"]) - ShiftedRow { - Column( - verticalArrangement = Arrangement.spacedBy(4.dp), - ) { - var storedMessagesCount by rememberAsyncMutableState(defaultValue = 0) { - context.messageLogger.getStoredMessageCount() - } - var storedStoriesCount by rememberAsyncMutableState(defaultValue = 0) { - context.messageLogger.getStoredStoriesCount() - } - Row( - horizontalArrangement = Arrangement.spacedBy(10.dp), - verticalAlignment = Alignment.CenterVertically, - modifier = Modifier - .fillMaxWidth() - .padding(5.dp) - ) { - Column( - modifier = Modifier.weight(1f), - verticalArrangement = Arrangement.spacedBy(2.dp), - ) { - Text( - translation.format("message_logger_summary", - "messageCount" to storedMessagesCount.toString(), - "storyCount" to storedStoriesCount.toString() - ), maxLines = 2) - } - Button(onClick = { - runCatching { - activityLauncherHelper.saveFile("message_logger.db", "application/octet-stream") { uri -> - context.androidContext.contentResolver.openOutputStream(uri.toUri())?.use { outputStream -> - context.messageLogger.databaseFile.inputStream().use { inputStream -> - inputStream.copyTo(outputStream) - } - } - } - }.onFailure { - context.log.error("Failed to export database", it) - context.longToast(translation.format("export_database_failed_toast", "message" to (it.localizedMessage ?: ""))) - } - }) { - Text(text = translation["export_button"]) - } - Button(onClick = { - runCatching { - activityLauncherHelper.openFile("application/octet-stream") { uri -> - val tempFile = File(context.androidContext.cacheDir, "view_message_logger.db") - context.androidContext.contentResolver.openInputStream(uri.toUri())?.use { inputStream -> - FileOutputStream(tempFile).use { outputStream -> - inputStream.copyTo(outputStream) - } - } - routes.viewLoggerHistory.navigate { - put("uri", URLEncoder.encode(tempFile.toUri().toString(), "UTF-8")) - } - } - }.onFailure { - context.log.error("Failed to open file", it) - context.longToast("Failed to open file! ${it.localizedMessage}") - } - }) { - Text(text = translation["view_button"]) - } - Button(onClick = { - runCatching { - context.messageLogger.purgeAll() - storedMessagesCount = 0 - storedStoriesCount = 0 - }.onFailure { - context.log.error("Failed to clear messages", it) - context.longToast(translation.format("clear_messages_failed_toast", "message" to (it.localizedMessage ?: ""))) - }.onSuccess { - context.shortToast(translation["success_toast"]) - } - }) { - Text(text = translation["clear_button"]) - } - } - OutlinedButton( - modifier = Modifier - .fillMaxWidth() - .padding(5.dp), - onClick = { - routes.loggerHistory.navigate() - } - ) { - Text(translation["view_logger_history_button"]) - } - } - } - - RowTitle(title = translation["friend_notes_title"]) - ShiftedRow { - Column( - verticalArrangement = Arrangement.spacedBy(4.dp), - ) { - Row( - horizontalArrangement = Arrangement.SpaceBetween, - verticalAlignment = Alignment.CenterVertically, - modifier = Modifier - .fillMaxWidth() - .padding(5.dp) - ) { - Text( - text = translation["friend_notes_description"], - modifier = Modifier.weight(1f) - ) - Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) { - Button(onClick = { - runCatching { - val notes = context.database.getAllScopeNotes() - if (notes.isEmpty()) { - context.shortToast(translation["friend_notes_no_notes_to_backup"]) - return@runCatching - } - val json = context.gson.toJson(notes) - activityLauncherHelper.saveFile("friend_notes_backup.json", "application/json") { uri -> - context.androidContext.contentResolver.openOutputStream(uri.toUri())?.use { - it.write(json.toByteArray()) - } - context.shortToast(translation["friend_notes_backup_success"]) - } - }.onFailure { - context.log.error("Failed to backup notes", it) - context.longToast(translation.format("friend_notes_backup_failure", "error" to (it.localizedMessage ?: ""))) - } - }) { - Text(text = translation["backup_button"]) - } - Button(onClick = { - runCatching { - activityLauncherHelper.openFile("application/json") { uri -> - context.androidContext.contentResolver.openInputStream(uri.toUri())?.use { - val json = it.reader().readText() - val notes = context.gson.fromJson>(json, object : com.google.gson.reflect.TypeToken>() {}.type) - context.database.setAllScopeNotes(notes) - context.shortToast(translation["friend_notes_restore_success"]) - } - } - }.onFailure { - context.log.error("Failed to restore notes", it) - context.longToast(translation.format("friend_notes_restore_failure", "error" to (it.localizedMessage ?: ""))) - } - }) { - Text(text = translation["restore_button"]) - } - } - } - } - } - - RowTitle(title = translation["debug_title"]) - Row( - horizontalArrangement = Arrangement.SpaceBetween, - verticalAlignment = Alignment.CenterVertically, - ) { - var selectedFileType by remember { mutableStateOf(InternalFileHandleType.entries.first()) } - Box( - modifier = Modifier - .weight(1f) - .padding(start = 26.dp) - ) { - var expanded by remember { mutableStateOf(false) } - ExposedDropdownMenuBox( - expanded = expanded, - onExpandedChange = { expanded = it }, - modifier = Modifier.fillMaxWidth(0.7f) - ) { - TextField( - value = translation.getOrNull("debug_file_${selectedFileType.name.lowercase()}") ?: selectedFileType.fileName, - onValueChange = {}, - readOnly = true, - modifier = Modifier.menuAnchor(MenuAnchorType.PrimaryNotEditable) - ) - ExposedDropdownMenu(expanded = expanded, onDismissRequest = { expanded = false }) { - InternalFileHandleType.entries.forEach { fileType -> - DropdownMenuItem(onClick = { - expanded = false - selectedFileType = fileType - }, text = { - Text(text = translation.getOrNull("debug_file_${fileType.name.lowercase()}") ?: fileType.fileName) - }) - } - } - } - } - Button(onClick = { - runCatching { - context.coroutineScope.launch { - selectedFileType.resolve(context.androidContext).delete() - } - }.onFailure { - context.log.error("Failed to clear file", it) - context.longToast(translation.format("clear_file_failed_toast", "message" to (it.localizedMessage ?: ""))) - }.onSuccess { - context.shortToast(translation["success_toast"]) - } - }) { - Text(translation["clear_button"]) - } - } - ShiftedRow { - Column( - verticalArrangement = Arrangement.spacedBy(4.dp), - ) { - PreferenceToggle(context.sharedPreferences, key = "test_mode", text = translation["test_mode_label"]) - PreferenceToggle(context.sharedPreferences, key = "disable_feature_loading", text = translation["disable_feature_loading_label"]) - PreferenceToggle(context.sharedPreferences, key = "disable_mapper", text = translation["disable_auto_mapper_label"]) - PreferenceToggle(context.sharedPreferences, key = "disable_bypass_indicator", text = translation["disable_bypass_indicator_label"]) - } - } - Spacer(modifier = Modifier.height(routes.bottomPadding)) - } - } -} diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/home/QuickActionsDialog.kt b/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/home/QuickActionsDialog.kt deleted file mode 100644 index 9e640eef..00000000 --- a/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/home/QuickActionsDialog.kt +++ /dev/null @@ -1,103 +0,0 @@ -package me.rhunk.snapenhance.ui.manager.pages.home - -import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.* -import androidx.compose.foundation.rememberScrollState -import androidx.compose.foundation.verticalScroll -import androidx.compose.material3.* -import androidx.compose.runtime.Composable -import androidx.compose.runtime.mutableStateListOf -import androidx.compose.runtime.remember -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.vector.ImageVector -import androidx.compose.ui.unit.dp -import androidx.compose.ui.text.style.TextAlign -import me.rhunk.snapenhance.common.bridge.wrapper.LocaleWrapper - -@Composable -fun QuickActionsDialog( - quickActions: Map, Any>, - selectedQuickActions: List, - onDismiss: () -> Unit, - onSave: (List) -> Unit, - translation: LocaleWrapper -) { - val selected = remember { mutableStateListOf(*selectedQuickActions.toTypedArray()) } - - AlertDialog( - onDismissRequest = onDismiss, - title = { - Text( - text = translation["manager.dialogs.quick_actions_dialog.title"], - style = MaterialTheme.typography.headlineSmall, - textAlign = TextAlign.Center, - modifier = Modifier - .fillMaxWidth() - ) - }, - text = { - Column( - modifier = Modifier - .verticalScroll(rememberScrollState()) - ) { - Text( - text = translation["manager.dialogs.quick_actions_dialog.subtitle"], - style = MaterialTheme.typography.bodyMedium, - textAlign = TextAlign.Center, - modifier = Modifier - .padding(bottom = 16.dp) - .fillMaxWidth() - ) - quickActions.keys.forEach { (name, icon) -> - val isSelected = selected.contains(name) - ListItem( - modifier = Modifier - .clickable { - if (isSelected) selected.remove(name) else selected.add(name) - } - .fillMaxWidth(), - headlineContent = { - Text( - name, - color = MaterialTheme.colorScheme.onSurface - ) - }, - leadingContent = { - Icon( - imageVector = icon, - contentDescription = name, - tint = MaterialTheme.colorScheme.primary - ) - }, - trailingContent = { - Checkbox( - checked = isSelected, - onCheckedChange = { isChecked -> - if (isChecked) selected.add(name) else selected.remove(name) - } - ) - } - ) - } - } - }, - confirmButton = { - Button( - onClick = { onSave(selected.toList()) }, - shape = MaterialTheme.shapes.medium - ) { - Text(translation["button.save"]) - } - }, - dismissButton = { - TextButton( - onClick = onDismiss, - shape = MaterialTheme.shapes.medium - ) { - Text(translation["button.cancel"]) - } - }, - containerColor = MaterialTheme.colorScheme.surface - ) -} diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/scripting/ManageScriptReposSection.kt b/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/scripting/ManageScriptReposSection.kt deleted file mode 100644 index 1e89a616..00000000 --- a/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/scripting/ManageScriptReposSection.kt +++ /dev/null @@ -1,247 +0,0 @@ -package me.rhunk.snapenhance.ui.manager.pages.scripting - -import androidx.compose.ui.Alignment -import androidx.compose.foundation.layout.* -import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.items -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.Public -import androidx.compose.material3.* -import androidx.compose.runtime.* -import androidx.compose.ui.Modifier -import androidx.compose.ui.focus.FocusRequester -import androidx.compose.ui.focus.focusRequester -import androidx.compose.ui.layout.onGloballyPositioned -import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.text.style.TextAlign -import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp -import androidx.compose.animation.AnimatedVisibility -import androidx.compose.material.icons.filled.Error -import androidx.core.net.toUri -import com.google.gson.JsonParser -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.launch -import kotlinx.coroutines.runBlocking -import me.rhunk.snapenhance.common.util.ktx.getUrlFromClipboard -import me.rhunk.snapenhance.storage.addRepo -import me.rhunk.snapenhance.storage.getRepositories -import me.rhunk.snapenhance.storage.removeRepo -import me.rhunk.snapenhance.ui.manager.Routes -import me.rhunk.snapenhance.ui.manager.components.AestheticDialog -import okhttp3.OkHttpClient - -class ManageScriptReposSection : Routes.Route() { - override val translation by lazy { context.translation.getCategory("manager.scripting.repos") } - private val refreshTrigger = mutableStateOf(0) - private val okHttpClient by lazy { OkHttpClient() } - - private fun extractRepoInfo(url: String): Pair { - if (url.contains("raw.githubusercontent.com")) { - val parts = url.removePrefix("https://raw.githubusercontent.com/").split("/") - if (parts.size >= 2) { - return parts[1] to parts[0] - } - } - return url.substringAfterLast("/").substringBeforeLast(".") to url.substringAfter("://").substringBefore("/") - } - - override val floatingActionButton: @Composable () -> Unit = { - var showAddDialog by remember { mutableStateOf(false) } - var showErrorDialog by remember { mutableStateOf(false) } - var errorDialogMessage by remember { mutableStateOf("") } - - if (showErrorDialog) { - AestheticDialog( - onDismissRequest = { showErrorDialog = false }, - title = translation["invalid_repo_title"], - text = errorDialogMessage, - icon = Icons.Default.Error, - confirmButtonText = translation["button.ok"], - onConfirm = { showErrorDialog = false } - ) - } - - ExtendedFloatingActionButton(onClick = { showAddDialog = true }) { - Text(translation["add_repo_button"]) - } - - if (showAddDialog) { - val coroutineScope = rememberCoroutineScope { Dispatchers.IO } - - var url by remember { mutableStateOf("") } - var loading by remember { mutableStateOf(false) } - - AlertDialog( - onDismissRequest = { showAddDialog = false }, - title = { Text(translation["add_repo_dialog_title"]) }, - text = { - val focusRequester = remember { FocusRequester() } - OutlinedTextField( - modifier = Modifier - .fillMaxWidth() - .focusRequester(focusRequester) - .onGloballyPositioned { focusRequester.requestFocus() }, - value = url, - onValueChange = { url = it }, - label = { Text(translation["repo_url_label"]) } - ) - LaunchedEffect(Unit) { - context.androidContext.getUrlFromClipboard()?.let { url = it } - } - }, - confirmButton = { - Button( - enabled = !loading && url.isNotBlank(), - onClick = { - loading = true - coroutineScope.launch { - runCatching { - var modifiedUrl = url - if (url.startsWith("https://github.com/")) { - val splitUrl = modifiedUrl.removePrefix("https://github.com/").split("/") - val repoName = splitUrl[0] + "/" + splitUrl[1] - okHttpClient.newCall( - okhttp3.Request.Builder().url("https://api.github.com/repos/$repoName").build() - ).execute().use { response -> - if (!response.isSuccessful) { - throw Exception("Failed to fetch default branch: ${response.code}") - } - val json = response.body?.string() ?: throw Exception("Empty response") - val defaultBranch = Regex("\"default_branch\":\"([^\"]+)\"").find(json)?.groupValues?.get(1) - ?: throw Exception("No default_branch field") - modifiedUrl = "https://raw.githubusercontent.com/$repoName/$defaultBranch/" - } - } - - val indexUrl = modifiedUrl.toUri().buildUpon().appendPath("index.json").build().toString() - val request = okhttp3.Request.Builder().url(indexUrl).build() - val isValid = okHttpClient.newCall(request).execute().use { response -> - if (!response.isSuccessful) throw Exception("Failed to fetch index.json: ${response.code}") - val indexJson = response.body?.string() ?: throw Exception("Empty index.json") - JsonParser.parseString(indexJson).asJsonObject.has("scripts") - } - - if (isValid) { - context.database.addRepo("script", modifiedUrl) - context.shortToast(translation["repo_added_toast"]) - showAddDialog = false - refreshTrigger.value++ - } else { - errorDialogMessage = translation["invalid_repo_error"] - showErrorDialog = true - } - }.onFailure { - context.log.error("Failed to add repository", it) - context.shortToast(translation.format("add_repo_failed_toast", "message" to (it.message ?: "Unknown"))) - } - loading = false - } - } - ) { - if (loading) { - CircularProgressIndicator(modifier = Modifier.size(24.dp)) - } else { - Text(translation["add_button"]) - } - } - } - ) - } - } - - override val content: @Composable (androidx.navigation.NavBackStackEntry) -> Unit = { - val repositories by remember(refreshTrigger.value) { - mutableStateOf>(runBlocking { context.database.getRepositories("script") }) - } - - if (repositories.isEmpty()) { - Box( - modifier = Modifier.fillMaxSize(), - contentAlignment = Alignment.Center - ) { - Text( - text = translation["no_repos_added"], - style = MaterialTheme.typography.headlineSmall, - fontWeight = FontWeight.Bold, - textAlign = TextAlign.Center, - color = MaterialTheme.colorScheme.onSurface - ) - } - } else { - LazyColumn( - modifier = Modifier.fillMaxSize(), - contentPadding = PaddingValues(start = 8.dp, top = 8.dp, end = 8.dp, bottom = 8.dp + routes.bottomPadding), - ) { - items(repositories) { url -> - val (repoName, author) = remember(url) { extractRepoInfo(url) } - - ElevatedCard( - modifier = Modifier.padding(bottom = 8.dp) - ) { - Row( - modifier = Modifier - .fillMaxWidth() - .padding(12.dp), - horizontalArrangement = Arrangement.spacedBy(8.dp), - verticalAlignment = Alignment.CenterVertically - ) { - Icon( - Icons.Default.Public, - contentDescription = null, - modifier = Modifier.size(40.dp), - tint = MaterialTheme.colorScheme.primary - ) - Column( - modifier = Modifier.weight(1f), - verticalArrangement = Arrangement.spacedBy(2.dp) - ) { - Text( - text = repoName, - fontWeight = FontWeight.SemiBold, - fontSize = 16.sp - ) - Text( - text = author, - fontSize = 14.sp, - color = MaterialTheme.colorScheme.onSurfaceVariant - ) - } - var showRemoveDialog by remember { mutableStateOf(false) } - - Button( - onClick = { showRemoveDialog = true } - ) { - Text(translation["remove_button"]) - } - - AnimatedVisibility(visible = showRemoveDialog) { - AlertDialog( - onDismissRequest = { showRemoveDialog = false }, - title = { Text(translation["remove_repo_dialog_title"]) }, - text = { Text(translation["remove_repo_dialog_text"]) }, - confirmButton = { - Button( - onClick = { - context.database.removeRepo("script", url) - showRemoveDialog = false - refreshTrigger.value++ - } - ) { - Text(translation["remove_button"]) - } - }, - dismissButton = { - Button(onClick = { showRemoveDialog = false }) { - Text(translation["button.cancel"]) - } - } - ) - } - } - } - } - } - } - } -} diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/scripting/ScriptingRootSection.kt b/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/scripting/ScriptingRootSection.kt deleted file mode 100644 index d8082f6a..00000000 --- a/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/scripting/ScriptingRootSection.kt +++ /dev/null @@ -1,616 +0,0 @@ -package me.rhunk.snapenhance.ui.manager.pages.scripting - -import android.content.Intent -import androidx.compose.foundation.background -import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.* -import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.* -import androidx.compose.material3.* -import androidx.compose.runtime.* -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.focus.FocusRequester -import androidx.compose.ui.focus.focusRequester -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.graphics.vector.ImageVector -import androidx.compose.ui.layout.onGloballyPositioned -import androidx.compose.ui.text.font.FontStyle -import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.text.style.TextAlign -import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp -import kotlinx.coroutines.* -import me.rhunk.snapenhance.common.scripting.type.ModuleInfo -import me.rhunk.snapenhance.common.scripting.ui.EnumScriptInterface -import me.rhunk.snapenhance.common.scripting.ui.InterfaceManager -import me.rhunk.snapenhance.common.scripting.ui.ScriptInterface -import me.rhunk.snapenhance.common.ui.AsyncUpdateDispatcher -import me.rhunk.snapenhance.common.ui.TopBarActionButton -import me.rhunk.snapenhance.common.ui.rememberAsyncMutableState -import me.rhunk.snapenhance.common.ui.rememberAsyncUpdateDispatcher -import me.rhunk.snapenhance.common.util.ktx.getUrlFromClipboard -import me.rhunk.snapenhance.common.util.ktx.openLink -import me.rhunk.snapenhance.storage.isScriptEnabled -import me.rhunk.snapenhance.storage.setScriptEnabled -import me.rhunk.snapenhance.ui.manager.Routes -import me.rhunk.snapenhance.ui.util.ActivityLauncherHelper -import me.rhunk.snapenhance.ui.util.Dialog -import me.rhunk.snapenhance.ui.util.chooseFolder -import me.rhunk.snapenhance.ui.util.pullrefresh.PullRefreshIndicator -import me.rhunk.snapenhance.ui.util.pullrefresh.pullRefresh -import me.rhunk.snapenhance.ui.util.pullrefresh.rememberPullRefreshState -import java.io.File - -class ScriptingRootSection : Routes.Route() { - override val translation by lazy { context.translation.getCategory("manager.scripting") } - private lateinit var activityLauncherHelper: ActivityLauncherHelper - val reloadDispatcher = AsyncUpdateDispatcher(updateOnFirstComposition = false) - private var selectedTab by mutableStateOf(0) - - override val init: () -> Unit = { - activityLauncherHelper = ActivityLauncherHelper(context.activity!!) - } - - suspend fun isScriptInstalledByUrl(scriptUrl: String): Boolean { - return try { - val installedScripts = context.scriptManager.getSyncedModules() - installedScripts.any { module -> - module.updateUrl?.equals(scriptUrl, ignoreCase = true) == true - } - } catch (e: Exception) { - false - } - } - - fun downloadScript(scriptUrl: String, onComplete: () -> Unit) { - context.coroutineScope.launch { - if (isScriptInstalledByUrl(scriptUrl)) { - context.shortToast(translation["script_already_installed"]) - return@launch - } - - runCatching { - context.shortToast(translation["downloading_script"]) - val moduleInfo = context.scriptManager.importFromUrl(scriptUrl) - context.shortToast(translation.format("script_downloaded", "name" to moduleInfo.name)) - reloadDispatcher.dispatch() - onComplete() - }.onFailure { - context.log.error("Failed to download script", it) - context.shortToast(translation["download_script_failed"]) - } - } - } - - @Composable - private fun ImportRemoteScript( - dismiss: () -> Unit - ) { - Dialog(onDismissRequest = dismiss) { - var url by remember { mutableStateOf("") } - val focusRequester = remember { FocusRequester() } - var isLoading by remember { mutableStateOf(false) } - ElevatedCard( - modifier = Modifier.fillMaxWidth() - ) { - Column( - modifier = Modifier - .fillMaxWidth() - .padding(16.dp), - horizontalAlignment = Alignment.CenterHorizontally - ) { - Text( - text = translation["import_script_from_url_title"], - fontSize = 22.sp, - fontWeight = FontWeight.Bold, - modifier = Modifier.padding(8.dp), - ) - Text( - text = translation["import_script_warning"], - fontSize = 14.sp, - fontWeight = FontWeight.Light, - fontStyle = FontStyle.Italic, - modifier = Modifier.padding(8.dp), - textAlign = TextAlign.Center, - ) - TextField( - value = url, - onValueChange = { url = it }, - label = { Text(text = translation["enter_url_label"]) }, - modifier = Modifier - .fillMaxWidth() - .focusRequester(focusRequester) - .onGloballyPositioned { focusRequester.requestFocus() } - ) - LaunchedEffect(Unit) { - context.androidContext.getUrlFromClipboard()?.let { url = it } - } - Spacer(modifier = Modifier.height(8.dp)) - Button( - enabled = url.isNotBlank(), - onClick = { - isLoading = true - context.coroutineScope.launch { - runCatching { - if (isScriptInstalledByUrl(url)) { - context.shortToast(translation["script_already_installed"]) - withContext(Dispatchers.Main) { - dismiss() - } - return@launch - } - - val moduleInfo = context.scriptManager.importFromUrl(url) - context.shortToast(translation.format("script_imported", "name" to moduleInfo.name)) - reloadDispatcher.dispatch() - withContext(Dispatchers.Main) { - dismiss() - } - return@launch - }.onFailure { - context.log.error("Failed to import script", it) - context.shortToast(translation.format("import_failed", "message" to (it.message ?: "Unknown"))) - } - isLoading = false - } - }, - ) { - if (isLoading) { - CircularProgressIndicator( - modifier = Modifier.size(30.dp), - strokeWidth = 3.dp, - color = MaterialTheme.colorScheme.onPrimary - ) - } else { - Text(text = translation["import_button"]) - } - } - } - } - } - } - - @Composable - private fun ModuleActions( - script: ModuleInfo, - canUpdate: Boolean, - dismiss: () -> Unit - ) { - Dialog(onDismissRequest = dismiss) { - ElevatedCard(modifier = Modifier.fillMaxWidth().padding(2.dp)) { - val actions = remember { - mutableMapOf, suspend () -> Unit>().apply { - if (canUpdate) { - put(translation["update_module_button"] to Icons.Default.Download) { - dismiss() - context.shortToast(translation.format("updating_script", "name" to script.name)) - runCatching { - val modulePath = context.scriptManager.getModulePath(script.name) ?: throw Exception(translation["module_not_found"]) - context.scriptManager.unloadScript(modulePath) - val moduleInfo = context.scriptManager.importFromUrl(script.updateUrl!!, filepath = modulePath) - context.shortToast(translation.format("updated_script", "name" to script.name, "version" to moduleInfo.version)) - context.database.setScriptEnabled(script.name, false) - withContext(context.database.executor.asCoroutineDispatcher()) { - reloadDispatcher.dispatch() - } - }.onFailure { - context.log.error("Failed to update module", it) - context.shortToast(translation["update_module_failed"]) - } - } - } - put(translation["edit_module_button"] to Icons.Default.Edit) { - runCatching { - val modulePath = context.scriptManager.getModulePath(script.name)!! - context.androidContext.startActivity( - Intent(Intent.ACTION_VIEW).apply { - data = context.scriptManager.getScriptsFolder()!!.findFile(modulePath)!!.uri - flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION - } - ) - dismiss() - }.onFailure { - context.log.error("Failed to open module file", it) - context.shortToast(translation["open_module_failed"]) - } - } - put(translation["clear_module_data_button"] to Icons.Default.Save) { - runCatching { - context.scriptManager.getModuleDataFolder(script.name).deleteRecursively() - context.shortToast(translation["module_data_cleared"]) - dismiss() - }.onFailure { - context.log.error("Failed to clear module data", it) - context.shortToast(translation["clear_module_data_failed"]) - } - } - put(translation["delete_module_button"] to Icons.Default.DeleteOutline) { - context.scriptManager.apply { - runCatching { - val modulePath = getModulePath(script.name)!! - unloadScript(modulePath) - getScriptsFolder()?.findFile(modulePath)?.delete() - reloadDispatcher.dispatch() - context.shortToast(translation.format("deleted_script", "name" to script.name)) - dismiss() - }.onFailure { - context.log.error("Failed to delete module", it) - context.shortToast(translation["delete_module_failed"]) - } - } - } - }.toMap() - } - LazyColumn(modifier = Modifier.fillMaxWidth()) { - item { - Text( - text = translation["actions_title"], - fontSize = 22.sp, - fontWeight = FontWeight.Bold, - modifier = Modifier.padding(16.dp).fillMaxWidth(), - textAlign = TextAlign.Center, - ) - } - items(actions.size) { index -> - val action = actions.entries.elementAt(index) - ListItem( - modifier = Modifier - .clickable { context.coroutineScope.launch { action.value(); dismiss() } } - .fillMaxWidth(), - leadingContent = { - Icon(action.key.second, action.key.first) - }, - headlineContent = { Text(action.key.first) } - ) - } - } - } - } - } - - @Composable - fun ModuleItem(script: ModuleInfo) { - var enabled by rememberAsyncMutableState(defaultValue = false, keys = arrayOf(script)) { - context.database.isScriptEnabled(script.name) - } - var openSettings by remember(script) { mutableStateOf(false) } - var openActions by remember { mutableStateOf(false) } - - val dispatcher = rememberAsyncUpdateDispatcher() - val reloadCallback = remember { suspend { dispatcher.dispatch() } } - val latestUpdate by rememberAsyncMutableState(defaultValue = null, updateDispatcher = dispatcher, keys = arrayOf(script)) { - context.scriptManager.checkForUpdate(script) - } - - LaunchedEffect(Unit) { - reloadDispatcher.addCallback(reloadCallback) - } - DisposableEffect(Unit) { - onDispose { reloadDispatcher.removeCallback(reloadCallback) } - } - - Card( - modifier = Modifier.fillMaxWidth().padding(8.dp), - elevation = CardDefaults.cardElevation() - ) { - Row( - modifier = Modifier - .fillMaxWidth() - .clickable { if (enabled) openSettings = !openSettings } - .padding(8.dp), - verticalAlignment = Alignment.CenterVertically - ) { - if (enabled) { - Icon( - imageVector = if (openSettings) Icons.Default.ExpandLess else Icons.Default.ExpandMore, - contentDescription = null, - modifier = Modifier.padding(end = 8.dp).size(32.dp), - ) - } - Column( - modifier = Modifier.weight(1f).padding(end = 8.dp) - ) { - Text(text = script.displayName ?: script.name, fontSize = 20.sp) - Text(text = script.description ?: translation["no_description"], fontSize = 14.sp) - latestUpdate?.let { - Text( - text = translation.format("update_available", "version" to it.version), - fontSize = 14.sp, - fontStyle = FontStyle.Italic, - color = MaterialTheme.colorScheme.onSurfaceVariant - ) - } - } - IconButton(onClick = { openActions = !openActions }) { - Icon(Icons.Default.Build, translation["actions_button"]) - } - Switch( - checked = enabled, - onCheckedChange = { isChecked -> - openSettings = false - context.coroutineScope.launch(Dispatchers.IO) { - runCatching { - val modulePath = context.scriptManager.getModulePath(script.name)!! - context.scriptManager.unloadScript(modulePath) - if (isChecked) { - context.scriptManager.loadScript(modulePath) - context.scriptManager.runtime.getModuleByName(script.name) - ?.callFunction("module.onSnapEnhanceLoad") - context.shortToast(translation.format("loaded_script", "name" to script.name)) - } else { - context.shortToast(translation.format("unloaded_script", "name" to script.name)) - } - context.database.setScriptEnabled(script.name, isChecked) - withContext(Dispatchers.Main) { enabled = isChecked } - }.onFailure { throwable -> - withContext(Dispatchers.Main) { enabled = !isChecked } - context.log.error("Failed to ${if (isChecked) "enable" else "disable"} script", throwable) - context.shortToast(translation.format(if (isChecked) "enable_script_failed" else "disable_script_failed")) - } - } - } - ) - } - if (openSettings) { - ScriptSettings(script) - } - } - if (openActions) { - ModuleActions(script = script, canUpdate = latestUpdate != null) { openActions = false } - } - } - - override val floatingActionButton: @Composable () -> Unit = { - val tab = selectedTab - var showImportDialog by remember { mutableStateOf(false) } - var showToast by remember { mutableStateOf(false) } - val scriptingFolder = context.scriptManager.getScriptsFolder() - - if (showImportDialog) { - ImportRemoteScript { showImportDialog = false } - } - if (showToast) { - LaunchedEffect(Unit) { - context.shortToast(translation["select_scripts_folder_toast"]) - showToast = false - } - } - - if (tab == 1) { - Column(verticalArrangement = Arrangement.spacedBy(8.dp), horizontalAlignment = Alignment.End) { - ExtendedFloatingActionButton( - onClick = { routes.manageScriptRepos.navigate() }, - icon = { Icon(Icons.Default.Public, contentDescription = null) }, - text = { Text(translation["manage_repos_button"]) } - ) - } - } else { - Column(verticalArrangement = Arrangement.spacedBy(8.dp), horizontalAlignment = Alignment.End) { - ExtendedFloatingActionButton( - onClick = { - if (scriptingFolder == null) { - showToast = true - } else { - showImportDialog = true - } - }, - icon = { Icon(imageVector = Icons.Default.Link, contentDescription = translation["import_from_url_button"]) }, - text = { Text(text = translation["import_from_url_button"]) } - ) - ExtendedFloatingActionButton( - onClick = { - if (scriptingFolder == null) { - showToast = true - } else { - scriptingFolder.let { - context.androidContext.openLink(it.uri.toString()) - } - } - }, - icon = { Icon(imageVector = Icons.Default.FolderOpen, contentDescription = translation["open_scripts_folder_button"]) }, - text = { Text(text = translation["open_scripts_folder_button"]) } - ) - } - } - } - - @Composable - fun ScriptSettings(script: ModuleInfo) { - val settingsInterface = remember { - val module = - context.scriptManager.runtime.getModuleByName(script.name) ?: return@remember null - (module.getBinding(InterfaceManager::class))?.buildInterface(EnumScriptInterface.SETTINGS) - } - if (settingsInterface == null) { - Text( - text = translation["no_settings_for_module"], - style = MaterialTheme.typography.bodySmall, - modifier = Modifier.padding(8.dp) - ) - } else { - ScriptInterface(interfaceBuilder = settingsInterface) - } - } - - override val content: @Composable (androidx.navigation.NavBackStackEntry) -> Unit = { - val scriptingFolder by rememberAsyncMutableState( - defaultValue = null, - updateDispatcher = reloadDispatcher - ) { context.scriptManager.getScriptsFolder() } - val tab = selectedTab - val tabTitles = listOf(translation["installed_scripts_tab"], translation["catalog_tab"]) - - Column(Modifier.fillMaxSize()) { - SingleChoiceSegmentedButtonRow( - modifier = Modifier - .fillMaxWidth() - .padding(horizontal = 8.dp) - ) { - tabTitles.forEachIndexed { i, text -> - val shape = when (i) { - 0 -> RoundedCornerShape(topStart = 24.dp, bottomStart = 24.dp) - tabTitles.lastIndex -> RoundedCornerShape(topEnd = 24.dp, bottomEnd = 24.dp) - else -> RoundedCornerShape(0.dp) - } - SegmentedButton( - selected = tab == i, - onClick = { - if (i == 1 && scriptingFolder == null) { - context.shortToast(translation["select_scripts_folder_toast"]) - } else { - selectedTab = i - } - }, - shape = shape, - modifier = Modifier.weight(1f), - icon = {}, - label = { Text(text) } - ) - } - } - when (tab) { - 0 -> { - val scriptModules by rememberAsyncMutableState( - defaultValue = emptyList(), - updateDispatcher = reloadDispatcher - ) { context.scriptManager.sync(); context.scriptManager.getSyncedModules() } - val coroutineScope = rememberCoroutineScope() - var refreshing by remember { mutableStateOf(false) } - - LaunchedEffect(Unit) { - refreshing = true - withContext(Dispatchers.IO) { - reloadDispatcher.dispatch() - refreshing = false - } - } - val pullRefreshState = rememberPullRefreshState(refreshing, onRefresh = { - refreshing = true - coroutineScope.launch(Dispatchers.IO) { - reloadDispatcher.dispatch() - refreshing = false - } - }) - - Box(modifier = Modifier.fillMaxSize()) { - LazyColumn( - modifier = Modifier.fillMaxSize().pullRefresh(pullRefreshState), - contentPadding = PaddingValues(bottom = routes.bottomPadding), - horizontalAlignment = Alignment.CenterHorizontally - ) { - item { - if (scriptingFolder == null && !refreshing) { - Box( - modifier = Modifier.fillMaxWidth().height(320.dp), - contentAlignment = Alignment.Center - ) { - Column(horizontalAlignment = Alignment.CenterHorizontally) { - Text( - text = translation["no_scripts_folder_selected_title"], - style = MaterialTheme.typography.headlineSmall, - fontWeight = FontWeight.Bold, - textAlign = TextAlign.Center, - modifier = Modifier.padding(bottom = 16.dp) - ) - Button( - onClick = { - activityLauncherHelper.chooseFolder { - context.config.root.scripting.moduleFolder.set(it) - context.config.writeConfig() - coroutineScope.launch { reloadDispatcher.dispatch() } - } - }, - contentPadding = PaddingValues(horizontal = 28.dp, vertical = 10.dp) - ) { - Text( - text = translation["select_folder_button"], - fontSize = 18.sp - ) - } - } - } - } else if (scriptModules.isEmpty()) { - Box( - modifier = Modifier.fillMaxWidth().height(320.dp), - contentAlignment = Alignment.Center - ) { - Column(horizontalAlignment = Alignment.CenterHorizontally) { - Text( - text = translation["no_scripts_found_title"], - style = MaterialTheme.typography.headlineSmall, - fontWeight = FontWeight.Bold, - textAlign = TextAlign.Center, - color = MaterialTheme.colorScheme.onSurface - ) - Text( - text = translation["use_catalog_to_add_scripts"], - style = MaterialTheme.typography.bodyLarge, - textAlign = TextAlign.Center, - color = MaterialTheme.colorScheme.onSurfaceVariant, - modifier = Modifier.padding(top = 8.dp) - ) - } - } - } - } - items(scriptModules.size, key = { scriptModules[it].hashCode() }) { index -> - ModuleItem(scriptModules[index]) - } - } - PullRefreshIndicator( - refreshing = refreshing, - state = pullRefreshState, - modifier = Modifier.align(Alignment.TopCenter) - ) - } - var scriptingWarning by remember { - mutableStateOf(context.sharedPreferences.run { - getBoolean("scripting_warning", true).also { - edit().putBoolean("scripting_warning", false).apply() - } - }) - } - if (scriptingWarning) { - var timeout by remember { mutableIntStateOf(10) } - LaunchedEffect(Unit) { - while (timeout > 0) { - delay(1000) - timeout-- - } - } - AlertDialog(onDismissRequest = { - if (timeout == 0) scriptingWarning = false - }, title = { - Text(text = context.translation["manager.dialogs.scripting_warning.title"]) - }, text = { - Text(text = context.translation["manager.dialogs.scripting_warning.content"]) - }, confirmButton = { - TextButton( - onClick = { scriptingWarning = false }, - enabled = timeout == 0 - ) { - Text(text = translation.format("ok_button_timeout", "timeout" to timeout.toString())) - } - }) - } - } - 1 -> { - ScriptCatalog(this@ScriptingRootSection) - } - } - } - } - - override val topBarActions: @Composable() (RowScope.() -> Unit) = { - TopBarActionButton( - onClick = { - context.androidContext.openLink("https://github.com/SnapEnhance/scripting-docs") - }, - icon = Icons.Default.CollectionsBookmark, - text = translation["documentation_button"], - ) - } -} diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/social/AddFriendDialog.kt b/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/social/AddFriendDialog.kt deleted file mode 100644 index 7865e5cd..00000000 --- a/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/social/AddFriendDialog.kt +++ /dev/null @@ -1,299 +0,0 @@ -package me.rhunk.snapenhance.ui.manager.pages.social - -import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.* -import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.text.KeyboardOptions -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.Search -import androidx.compose.material3.* -import androidx.compose.runtime.* -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.text.input.ImeAction -import androidx.compose.ui.text.input.KeyboardType -import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp -import kotlinx.coroutines.* -import me.rhunk.snapenhance.RemoteSideContext -import me.rhunk.snapenhance.common.ReceiversConfig -import me.rhunk.snapenhance.common.data.MessagingFriendInfo -import me.rhunk.snapenhance.common.data.MessagingGroupInfo -import me.rhunk.snapenhance.common.ui.rememberAsyncMutableState -import me.rhunk.snapenhance.common.util.snap.BitmojiSelfie -import me.rhunk.snapenhance.common.util.snap.SnapWidgetBroadcastReceiverHelper -import me.rhunk.snapenhance.ui.util.coil.BitmojiImage - -class AddFriendDialog( - private val context: RemoteSideContext, - private val actionHandler: Actions, - private val pinnedIds: List? = null -) { - class Actions( - val onFriendState: (friend: MessagingFriendInfo, state: Boolean) -> Unit, - val onGroupState: (group: MessagingGroupInfo, state: Boolean) -> Unit, - val getFriendState: (friend: MessagingFriendInfo) -> Boolean, - val getGroupState: (group: MessagingGroupInfo) -> Boolean, - ) - - private val stateCache = mutableMapOf() - private val translation by lazy { context.translation.getCategory("manager.dialogs.add_friend")} - - @Composable - private fun ListCardEntry( - id: String, - bitmoji: String? = null, - name: String, - participantsCount: Int? = null, - getCurrentState: () -> Boolean, - onState: (Boolean) -> Unit = {}, - ) { - var currentState by rememberAsyncMutableState(defaultValue = stateCache[id] ?: false) { - getCurrentState().also { stateCache[id] = it } - } - val coroutineScope = rememberCoroutineScope() - - Row( - modifier = Modifier - .fillMaxWidth() - .clickable { - currentState = !currentState - stateCache[id] = currentState - coroutineScope.launch(Dispatchers.IO) { - onState(currentState) - } - } - .padding(4.dp), - horizontalArrangement = Arrangement.spacedBy(4.dp), - verticalAlignment = Alignment.CenterVertically - ) { - BitmojiImage( - context = this@AddFriendDialog.context, - url = bitmoji, - modifier = Modifier.padding(end = 2.dp), - size = 32, - ) - - Column( - modifier = Modifier - .weight(1f) - ) { - Text( - text = name, - fontSize = 15.sp, - ) - - participantsCount?.let { - Text( - text = translation.format("participants_text", "count" to it.toString()), - fontSize = 12.sp, - lineHeight = 12.sp, - color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.6f) - ) - } - } - - Checkbox( - checked = currentState, - onCheckedChange = { - currentState = it - stateCache[id] = currentState - coroutineScope.launch(Dispatchers.IO) { - onState(currentState) - } - } - ) - } - } - - @Composable - private fun DialogHeader(searchKeyword: MutableState) { - Column( - modifier = Modifier - .fillMaxWidth() - .padding(10.dp), - ) { - Text( - text = translation["title"], - fontSize = 23.sp, - fontWeight = FontWeight.ExtraBold, - modifier = Modifier - .align(alignment = Alignment.CenterHorizontally) - ) - } - - Row( - modifier = Modifier - .fillMaxWidth() - .padding(10.dp), - verticalAlignment = Alignment.CenterVertically - ) { - TextField( - value = searchKeyword.value, - onValueChange = { searchKeyword.value = it }, - label = { - Text(text = translation["search_hint"]) - }, - modifier = Modifier - .weight(1f) - .padding(end = 10.dp), - keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Text, imeAction = ImeAction.Done), - leadingIcon = { - Icon(Icons.Filled.Search, contentDescription = translation["search_icon_description"]) - } - ) - } - } - - - @Composable - fun Content(dismiss: () -> Unit = { }) { - var cachedFriends by remember { mutableStateOf(null as List?) } - var cachedGroups by remember { mutableStateOf(null as List?) } - - val coroutineScope = rememberCoroutineScope() - - var timeoutJob: Job? = null - var hasFetchError by remember { mutableStateOf(false) } - - LaunchedEffect(Unit) { - context.database.receiveMessagingDataCallback = { friends, groups -> - cachedFriends = friends.run { - if (pinnedIds != null) { - sortedBy { -pinnedIds.indexOf(it.userId) } - } else friends - } - cachedGroups = groups.run { - if (pinnedIds != null) { - sortedBy { -pinnedIds.indexOf(it.conversationId) } - } else groups - } - timeoutJob?.cancel() - hasFetchError = false - } - SnapWidgetBroadcastReceiverHelper.create(ReceiversConfig.BRIDGE_SYNC_ACTION) {}.also { - runCatching { - context.androidContext.sendBroadcast(it) - }.onFailure { - context.log.error("Failed to send broadcast", it) - hasFetchError = true - } - } - timeoutJob = coroutineScope.launch { - withContext(Dispatchers.IO) { - delay(20000) - hasFetchError = true - } - } - } - - me.rhunk.snapenhance.ui.util.Dialog( - onDismissRequest = { - timeoutJob?.cancel() - dismiss() - }, - properties = me.rhunk.snapenhance.ui.util.DialogProperties(usePlatformDefaultWidth = false) - ) { - Card( - colors = CardDefaults.elevatedCardColors(), - modifier = Modifier - .fillMaxSize() - .fillMaxWidth() - .padding(all = 20.dp) - ) { - if (cachedGroups == null || cachedFriends == null) { - Column( - modifier = Modifier - .fillMaxSize() - .padding(10.dp), - verticalArrangement = Arrangement.Center, - horizontalAlignment = Alignment.CenterHorizontally - ) { - if (hasFetchError) { - Text( - text = translation["fetch_error"], - fontSize = 20.sp, - fontWeight = FontWeight.Bold, - modifier = Modifier.padding(bottom = 10.dp, top = 10.dp) - ) - return@Card - } - CircularProgressIndicator( - modifier = Modifier - .padding() - .size(30.dp), - strokeWidth = 3.dp, - color = MaterialTheme.colorScheme.primary - ) - } - return@Card - } - - val searchKeyword = remember { mutableStateOf("") } - - val filteredGroups = cachedGroups!!.takeIf { searchKeyword.value.isNotBlank() }?.filter { - it.name.contains(searchKeyword.value, ignoreCase = true) - } ?: cachedGroups!! - - val filteredFriends = cachedFriends!!.takeIf { searchKeyword.value.isNotBlank() }?.filter { - it.mutableUsername.contains(searchKeyword.value, ignoreCase = true) || - it.displayName?.contains(searchKeyword.value, ignoreCase = true) == true - } ?: cachedFriends!! - - DialogHeader(searchKeyword) - - LazyColumn( - modifier = Modifier - .fillMaxSize() - .padding(10.dp) - ) { - item { - if (filteredGroups.isEmpty()) return@item - Text(text = translation["category_groups"], - fontSize = 20.sp, - fontWeight = FontWeight.Bold, - modifier = Modifier.padding(bottom = 10.dp, top = 10.dp) - ) - } - - items(filteredGroups.size) { - val group = filteredGroups[it] - ListCardEntry( - id = group.conversationId, - name = group.name, - participantsCount = group.participantsCount, - getCurrentState = { actionHandler.getGroupState(group) } - ) { state -> - actionHandler.onGroupState(group, state) - } - } - - item { - if (filteredFriends.isEmpty()) return@item - Text(text = translation["category_friends"], - fontSize = 20.sp, - fontWeight = FontWeight.Bold, - modifier = Modifier.padding(bottom = 10.dp, top = 10.dp) - ) - } - - items(filteredFriends.size) { index -> - val friend = filteredFriends[index] - - ListCardEntry( - id = friend.userId, - bitmoji = friend.takeIf { it.bitmojiId != null }?.let { - BitmojiSelfie.getBitmojiSelfie(it.selfieId, it.bitmojiId, BitmojiSelfie.BitmojiSelfieType.NEW_THREE_D) - }, - name = friend.displayName?.takeIf { name -> name.isNotBlank() } ?: friend.mutableUsername, - getCurrentState = { actionHandler.getFriendState(friend) } - ) { state -> - actionHandler.onFriendState(friend, state) - } - } - } - } - } - } -} \ No newline at end of file diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/social/MessagingPreview.kt b/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/social/MessagingPreview.kt deleted file mode 100644 index 0bde88f4..00000000 --- a/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/social/MessagingPreview.kt +++ /dev/null @@ -1,535 +0,0 @@ -package me.rhunk.snapenhance.ui.manager.pages.social - -import android.content.Intent -import androidx.compose.foundation.background -import androidx.compose.foundation.border -import androidx.compose.foundation.gestures.detectTapGestures -import androidx.compose.foundation.layout.* -import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.LazyListState -import androidx.compose.foundation.lazy.items -import androidx.compose.foundation.lazy.rememberLazyListState -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.Close -import androidx.compose.material.icons.filled.MoreVert -import androidx.compose.material.icons.rounded.BookmarkAdded -import androidx.compose.material.icons.rounded.BookmarkBorder -import androidx.compose.material.icons.rounded.DeleteForever -import androidx.compose.material.icons.rounded.RemoveRedEye -import androidx.compose.material3.* -import androidx.compose.runtime.* -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.vector.ImageVector -import androidx.compose.ui.input.pointer.pointerInput -import androidx.compose.ui.unit.dp -import androidx.navigation.NavBackStackEntry -import kotlinx.coroutines.* -import me.rhunk.snapenhance.bridge.snapclient.MessagingBridge -import me.rhunk.snapenhance.bridge.snapclient.SessionStartListener -import me.rhunk.snapenhance.bridge.snapclient.types.Message -import me.rhunk.snapenhance.common.Constants -import me.rhunk.snapenhance.common.ReceiversConfig -import me.rhunk.snapenhance.common.data.ContentType -import me.rhunk.snapenhance.common.data.SocialScope -import me.rhunk.snapenhance.common.messaging.MessagingConstraints -import me.rhunk.snapenhance.common.messaging.MessagingTask -import me.rhunk.snapenhance.common.messaging.MessagingTaskConstraint -import me.rhunk.snapenhance.common.messaging.MessagingTaskType -import me.rhunk.snapenhance.common.util.protobuf.ProtoReader -import me.rhunk.snapenhance.common.util.snap.SnapWidgetBroadcastReceiverHelper -import me.rhunk.snapenhance.ui.manager.Routes -import me.rhunk.snapenhance.ui.util.Dialog - -class MessagingPreview: Routes.Route() { - override val translation by lazy { context.translation.getCategory("manager.social.messaging_preview") } - private lateinit var coroutineScope: CoroutineScope - private lateinit var previewScrollState: LazyListState - - private val contentTypeTranslation by lazy { context.translation.getCategory("content_type") } - private val messagingBridge: MessagingBridge? get() = context.bridgeService?.messagingBridge - - private var messages = mutableStateListOf() - private var conversationId by mutableStateOf(null) - private val selectedMessages = mutableStateListOf() // client message id - - private fun toggleSelectedMessage(messageId: Long) { - if (selectedMessages.contains(messageId)) selectedMessages.remove(messageId) - else selectedMessages.add(messageId) - } - - @Composable - private fun ActionButton( - text: String, - icon: ImageVector, - onClick: () -> Unit, - ) { - DropdownMenuItem( - onClick = onClick, - text = { - Row( - modifier = Modifier.padding(5.dp), - horizontalArrangement = Arrangement.spacedBy(8.dp), - verticalAlignment = Alignment.CenterVertically - ) { - Icon( - imageVector = icon, - contentDescription = null - ) - Text(text = text) - } - } - ) - } - - @Composable - private fun ConstraintsSelectionDialog( - onChoose: (Array) -> Unit, - onDismiss: () -> Unit - ) { - val selectedTypes = remember { mutableStateListOf() } - var selectAllState by remember { mutableStateOf(false) } - val availableTypes = remember { arrayOf( - ContentType.CHAT, - ContentType.NOTE, - ContentType.SNAP, - ContentType.STICKER, - ContentType.EXTERNAL_MEDIA - ) } - - fun toggleContentType(contentType: ContentType) { - if (selectAllState) return - if (selectedTypes.contains(contentType)) { - selectedTypes.remove(contentType) - } else { - selectedTypes.add(contentType) - } - } - - Surface( - modifier = Modifier - .fillMaxWidth() - .background(MaterialTheme.colorScheme.surface) - ) { - Column( - modifier = Modifier.padding(15.dp), - horizontalAlignment = Alignment.CenterHorizontally, - verticalArrangement = Arrangement.spacedBy(5.dp) - ) { - Text(context.translation["manager.dialogs.messaging_action.title"]) - Spacer(modifier = Modifier.height(5.dp)) - availableTypes.forEach { contentType -> - Row( - modifier = Modifier - .fillMaxWidth() - .padding(2.dp) - .pointerInput(Unit) { - detectTapGestures(onTap = { toggleContentType(contentType) }) - }, - horizontalArrangement = Arrangement.spacedBy(8.dp), - verticalAlignment = Alignment.CenterVertically - ) { - Checkbox( - checked = selectedTypes.contains(contentType), - enabled = !selectAllState, - onCheckedChange = { toggleContentType(contentType) } - ) - Text(text = contentTypeTranslation[contentType.name]) - } - } - Row( - modifier = Modifier - .fillMaxWidth() - .padding(5.dp), - horizontalArrangement = Arrangement.spacedBy(10.dp), - verticalAlignment = Alignment.CenterVertically - ) { - Switch(checked = selectAllState, onCheckedChange = { - selectAllState = it - }) - Text(text = context.translation["manager.dialogs.messaging_action.select_all_button"]) - } - Row( - modifier = Modifier - .fillMaxWidth(), - horizontalArrangement = Arrangement.SpaceEvenly, - ) { - Button(onClick = { onDismiss() }) { - Text(context.translation["button.cancel"]) - } - Button(onClick = { - onChoose(if (selectAllState) ContentType.entries.toTypedArray() - else selectedTypes.toTypedArray()) - }) { - Text(context.translation["button.ok"]) - } - } - } - } - } - - override val topBarActions: @Composable (RowScope.() -> Unit) = { - var taskSelectionDropdown by remember { mutableStateOf(false) } - var selectConstraintsDialog by remember { mutableStateOf(false) } - var activeTask by remember { mutableStateOf(null as MessagingTask?) } - var activeJob by remember { mutableStateOf(null as Job?) } - val processMessageCount = remember { mutableIntStateOf(0) } - - fun runCurrentTask() { - activeJob = coroutineScope.launch(Dispatchers.IO) { - activeTask?.run() - withContext(Dispatchers.Main) { - activeTask = null - activeJob = null - } - }.also { job -> - job.invokeOnCompletion { - if (it != null) { - context.log.verbose("Failed to process messages: ${it.message}") - return@invokeOnCompletion - } - context.longToast(translation.format("processed_messages_toast", "count" to processMessageCount.intValue.toString())) - } - } - } - - fun launchMessagingTask(taskType: MessagingTaskType, constraints: List = listOf(), onSuccess: (Message) -> Unit = {}) { - if (messagingBridge == null) { - context.longToast(translation["bridge_connection_failed"]) - return - } - taskSelectionDropdown = false - processMessageCount.intValue = 0 - activeTask = MessagingTask( - messagingBridge!!, conversationId!!, taskType, constraints, - overrideClientMessageIds = selectedMessages.takeIf { it.isNotEmpty() }?.toList(), - processedMessageCount = processMessageCount, - onSuccess = onSuccess, - onFailure = { message, reason -> - context.log.verbose("Failed to process message ${message.clientMessageId}: $reason") - } - ) - selectedMessages.clear() - } - - if (selectConstraintsDialog && activeTask != null) { - Dialog(onDismissRequest = { - selectConstraintsDialog = false - activeTask = null - }) { - ConstraintsSelectionDialog( - onChoose = { contentTypes -> - launchMessagingTask( - taskType = activeTask!!.taskType, - constraints = activeTask!!.constraints + MessagingConstraints.CONTENT_TYPE(contentTypes), - onSuccess = activeTask!!.onSuccess - ) - runCurrentTask() - selectConstraintsDialog = false - }, - onDismiss = { - selectConstraintsDialog = false - activeTask = null - } - ) - } - } - - if (activeJob != null) { - Dialog(onDismissRequest = { - activeJob?.cancel() - activeJob = null - activeTask = null - }) { - Column(modifier = Modifier - .fillMaxWidth() - .background(MaterialTheme.colorScheme.surface) - .padding(15.dp) - .border(1.dp, MaterialTheme.colorScheme.onSurface, RoundedCornerShape(20.dp)), - horizontalAlignment = Alignment.CenterHorizontally, - verticalArrangement = Arrangement.spacedBy(5.dp)) - { - Text(translation.format("processed_messages_text", "count" to processMessageCount.intValue.toString())) - if (activeTask?.hasFixedGoal() == true) { - LinearProgressIndicator( - progress = { processMessageCount.intValue.toFloat() / selectedMessages.size.toFloat() }, - modifier = Modifier - .fillMaxWidth() - .padding(5.dp), - color = MaterialTheme.colorScheme.primary, - ) - } else { - CircularProgressIndicator( - modifier = Modifier - .padding() - .size(30.dp), - strokeWidth = 3.dp, - color = MaterialTheme.colorScheme.primary - ) - } - } - } - } - - IconButton(onClick = { taskSelectionDropdown = !taskSelectionDropdown }) { - Icon(imageVector = Icons.Filled.MoreVert, contentDescription = null) - } - - if (selectedMessages.isNotEmpty()) { - IconButton(onClick = { selectedMessages.clear() }) { - Icon(imageVector = Icons.Filled.Close, contentDescription = translation["close_button_description"]) - } - } - - MaterialTheme( - colorScheme = MaterialTheme.colorScheme.copy( - surface = MaterialTheme.colorScheme.inverseSurface, - onSurface = MaterialTheme.colorScheme.inverseOnSurface - ), - shapes = MaterialTheme.shapes.copy(medium = RoundedCornerShape(50.dp)) - ) { - DropdownMenu( - expanded = taskSelectionDropdown && messages.isNotEmpty(), onDismissRequest = { taskSelectionDropdown = false } - ) { - val hasSelection = selectedMessages.isNotEmpty() - ActionButton(text = translation[if (hasSelection) "save_selection_option" else "save_all_option"], icon = Icons.Rounded.BookmarkAdded) { - launchMessagingTask(MessagingTaskType.SAVE) - if (hasSelection) runCurrentTask() - else selectConstraintsDialog = true - } - ActionButton(text = translation[if (hasSelection) "unsave_selection_option" else "unsave_all_option"], icon = Icons.Rounded.BookmarkBorder) { - launchMessagingTask(MessagingTaskType.UNSAVE) - if (hasSelection) runCurrentTask() - else selectConstraintsDialog = true - } - ActionButton(text = translation[if (hasSelection) "mark_selection_as_seen_option" else "mark_all_as_seen_option"], icon = Icons.Rounded.RemoveRedEye) { - if (messagingBridge == null) { - context.longToast(translation["bridge_connection_failed"]) - return@ActionButton - } - launchMessagingTask( - MessagingTaskType.READ, listOf( - MessagingConstraints.NO_USER_ID(messagingBridge!!.myUserId), - MessagingConstraints.CONTENT_TYPE(arrayOf(ContentType.SNAP)) - )) - runCurrentTask() - } - ActionButton(text = translation[if (hasSelection) "delete_selection_option" else "delete_all_option"], icon = Icons.Rounded.DeleteForever) { - if (messagingBridge == null) { - context.longToast(translation["bridge_connection_failed"]) - return@ActionButton - } - launchMessagingTask(MessagingTaskType.DELETE, listOf(MessagingConstraints.USER_ID(messagingBridge!!.myUserId), { - contentType != ContentType.STATUS.id - })) { message -> - coroutineScope.launch { - message.contentType = ContentType.STATUS.id - } - } - if (hasSelection) runCurrentTask() - else selectConstraintsDialog = true - } - } - } - } - - @Composable - private fun ConversationPreview( - messages: List, - fetchNewMessages: () -> Unit - ) { - DisposableEffect(Unit) { - onDispose { - selectedMessages.clear() - } - } - - LazyColumn( - reverseLayout = true, - modifier = Modifier - .fillMaxWidth(), - state = previewScrollState, - contentPadding = PaddingValues(bottom = routes.bottomPadding) - ) { - items(messages, key = { it.serverMessageId }) {message -> - val messageReader = remember(message.contentType) { ProtoReader(message.content) } - val contentType = ContentType.fromMessageContainer(messageReader) - - Card( - modifier = Modifier - .padding(5.dp) - .pointerInput(Unit) { - if (contentType == ContentType.STATUS) return@pointerInput - detectTapGestures( - onLongPress = { - toggleSelectedMessage(message.clientMessageId) - }, - onTap = { - if (selectedMessages.isNotEmpty()) { - toggleSelectedMessage(message.clientMessageId) - } - } - ) - }, - colors = CardDefaults.cardColors( - containerColor = if (selectedMessages.contains(message.clientMessageId)) MaterialTheme.colorScheme.primaryContainer else MaterialTheme.colorScheme.surfaceVariant - ), - ) { - val contentMessage = remember(message.contentType) { "[${contentType?.let { contentTypeTranslation.getOrNull(it.name) ?: it.name } }] ${messageReader.getString(2, 1) ?: "" }" } - Row( - modifier = Modifier - .padding(5.dp) - ) { - Text(contentMessage) - } - } - } - item { - if (messages.isEmpty()) { - Row( - modifier = Modifier - .fillMaxWidth() - .padding(40.dp), - horizontalArrangement = Arrangement.Center - ) { - Text(translation["no_message_hint"]) - } - } - Spacer(modifier = Modifier.height(20.dp)) - - LaunchedEffect(Unit) { - if (messages.isNotEmpty()) { - fetchNewMessages() - } - } - } - } - } - - - @Composable - private fun LoadingRow() { - Row( - modifier = Modifier - .fillMaxWidth() - .padding(40.dp), - horizontalArrangement = Arrangement.Center - ) { - CircularProgressIndicator( - modifier = Modifier - .padding() - .size(30.dp), - strokeWidth = 3.dp, - color = MaterialTheme.colorScheme.primary - ) - } - } - - override val content: @Composable (NavBackStackEntry) -> Unit = { navBackStackEntry -> - val scope = remember { SocialScope.getByName(navBackStackEntry.arguments?.getString("scope")!!) } - val id = remember { navBackStackEntry.arguments?.getString("id")!! } - - previewScrollState = rememberLazyListState() - coroutineScope = rememberCoroutineScope() - - var lastMessageId by remember { mutableLongStateOf(Long.MAX_VALUE) } - var isBridgeConnected by remember { mutableStateOf(false) } - var hasBridgeError by remember { mutableStateOf(false) } - - fun fetchNewMessages() { - coroutineScope.launch(Dispatchers.IO) cs@{ - runCatching { - val queriedMessages = messagingBridge!!.fetchConversationWithMessagesPaginated( - conversationId!!, - 20, - lastMessageId - )?.reversed() ?: throw IllegalStateException("Failed to fetch messages. Bridge returned null") - - withContext(Dispatchers.Main) { - messages.addAll(queriedMessages) - lastMessageId = queriedMessages.lastOrNull()?.clientMessageId ?: lastMessageId - } - }.onFailure { - context.log.error("Failed to fetch messages", it) - context.shortToast(translation["message_fetch_failed"]) - } - } - } - - fun onMessagingBridgeReady(scope: SocialScope, scopeId: String) { - context.log.verbose("onMessagingBridgeReady: $scope $scopeId") - - runCatching { - conversationId = (if (scope == SocialScope.FRIEND) messagingBridge!!.getOneToOneConversationId(scopeId) else scopeId) ?: throw IllegalStateException("Failed to get conversation id") - if (runCatching { !messagingBridge!!.isSessionStarted }.getOrDefault(true)) { - context.androidContext.packageManager.getLaunchIntentForPackage( - Constants.SNAPCHAT_PACKAGE_NAME - )?.let { - val mainIntent = Intent.makeMainActivity(it.component).apply { - putExtra(ReceiversConfig.MESSAGING_PREVIEW_EXTRA, true) - addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) - } - context.androidContext.startActivity(mainIntent) - } - messagingBridge!!.registerSessionStartListener(object: SessionStartListener.Stub() { - override fun onConnected() { - fetchNewMessages() - } - }) - return - } - fetchNewMessages() - }.onFailure { - context.longToast(translation["bridge_init_failed"]) - context.log.error("Failed to initialize messaging bridge", it) - } - } - - LaunchedEffect(Unit) { - messages.clear() - conversationId = null - - isBridgeConnected = context.hasMessagingBridge() - if (isBridgeConnected) { - withContext(Dispatchers.IO) { - onMessagingBridgeReady(scope, id) - } - } else { - coroutineScope.launch(Dispatchers.IO) { - SnapWidgetBroadcastReceiverHelper.create("wakeup") {}.also { - context.androidContext.sendBroadcast(it) - } - withTimeout(10000) { - while (!context.hasMessagingBridge()) { - delay(100) - } - isBridgeConnected = true - onMessagingBridgeReady(scope, id) - } - }.invokeOnCompletion { - if (it != null) { - hasBridgeError = true - } - } - } - } - - Column( - modifier = Modifier - .fillMaxSize() - ) { - if (hasBridgeError) { - Text(translation["bridge_connection_failed"]) - } - - if (!isBridgeConnected && !hasBridgeError) { - LoadingRow() - } - - if (isBridgeConnected && !hasBridgeError) { - ConversationPreview(messages, ::fetchNewMessages) - } - } - } -} \ No newline at end of file diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/social/SocialRootSection.kt b/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/social/SocialRootSection.kt deleted file mode 100644 index 3dac0de0..00000000 --- a/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/social/SocialRootSection.kt +++ /dev/null @@ -1,297 +0,0 @@ -package me.rhunk.snapenhance.ui.manager.pages.social - -import androidx.compose.foundation.ExperimentalFoundationApi -import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.* -import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.pager.HorizontalPager -import androidx.compose.foundation.pager.rememberPagerState -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.RemoveRedEye -import androidx.compose.material.icons.rounded.Add -import androidx.compose.material3.* -import androidx.compose.runtime.* -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.vector.ImageVector -import androidx.compose.ui.res.vectorResource -import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.text.style.TextAlign -import androidx.compose.ui.text.style.TextOverflow -import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp -import androidx.navigation.NavBackStackEntry -import kotlinx.coroutines.launch -import me.rhunk.snapenhance.R -import me.rhunk.snapenhance.common.data.MessagingFriendInfo -import me.rhunk.snapenhance.common.data.MessagingGroupInfo -import me.rhunk.snapenhance.common.data.SocialScope -import me.rhunk.snapenhance.common.ui.rememberAsyncMutableState -import me.rhunk.snapenhance.common.util.snap.BitmojiSelfie -import me.rhunk.snapenhance.storage.* -import me.rhunk.snapenhance.ui.manager.Routes -import me.rhunk.snapenhance.ui.util.coil.BitmojiImage - -class SocialRootSection : Routes.Route() { - private var friendList: List by mutableStateOf(emptyList()) - private var groupList: List by mutableStateOf(emptyList()) - - private fun updateScopeLists() { - context.coroutineScope.launch { - friendList = context.database.getFriends(descOrder = true) - groupList = context.database.getGroups() - } - } - - @Composable - private fun ScopeList(scope: SocialScope) { - val remainingHours = remember { context.config.root.streaksReminder.remainingHours.get() } - - LazyColumn( - modifier = Modifier - .fillMaxSize(), - contentPadding = PaddingValues(start = 8.dp, end = 8.dp, bottom = routes.bottomPadding), - verticalArrangement = Arrangement.spacedBy(8.dp) - ) { - //check if scope list is empty - val listSize = when (scope) { - SocialScope.GROUP -> groupList.size - SocialScope.FRIEND -> friendList.size - } - - if (listSize == 0) { - item { - Text( - text = translation["empty_hint"], modifier = Modifier - .fillMaxWidth() - .padding(10.dp), textAlign = TextAlign.Center - ) - } - } - - items(listSize) { index -> - val id = when (scope) { - SocialScope.GROUP -> groupList[index].conversationId - SocialScope.FRIEND -> friendList[index].userId - } - - ElevatedCard( - modifier = Modifier - .fillMaxWidth() - .height(70.dp), - onClick = { - routes.manageScope.navigate { - put("id", id) - put("scope", scope.key) - } - } - ) { - Row( - modifier = Modifier - .padding(10.dp) - .fillMaxSize(), - verticalAlignment = Alignment.CenterVertically - ) { - when (scope) { - SocialScope.GROUP -> { - val group = groupList[index] - Column( - modifier = Modifier - .padding(start = 7.dp) - .fillMaxWidth() - .weight(1f) - ) { - Text( - text = group.name, - maxLines = 1, - fontWeight = FontWeight.Bold - ) - } - } - - SocialScope.FRIEND -> { - val friend = friendList[index] - val streaks by rememberAsyncMutableState(defaultValue = friend.streaks) { - context.database.getFriendStreaks(friend.userId) - } - - BitmojiImage( - context = context, - url = BitmojiSelfie.getBitmojiSelfie( - friend.selfieId, - friend.bitmojiId, - BitmojiSelfie.BitmojiSelfieType.NEW_THREE_D - ) - ) - - Column( - modifier = Modifier - .padding(start = 7.dp) - .fillMaxWidth() - .weight(1f) - ) { - Text( - text = friend.displayName ?: friend.mutableUsername, - maxLines = 1, - fontWeight = FontWeight.Bold - ) - Text( - text = friend.mutableUsername, - maxLines = 1, - fontSize = 12.sp, - fontWeight = FontWeight.Light - ) - } - Row(verticalAlignment = Alignment.CenterVertically) { - streaks?.takeIf { it.notify }?.let { streaks -> - Icon( - imageVector = ImageVector.vectorResource(id = R.drawable.streak_icon), - contentDescription = null, - modifier = Modifier.height(40.dp), - tint = if (streaks.isAboutToExpire(remainingHours)) - MaterialTheme.colorScheme.error - else MaterialTheme.colorScheme.primary - ) - Text( - text = translation.format( - "streaks_expiration_short", - "hours" to (((streaks.expirationTimestamp - System.currentTimeMillis()) / 3600000).toInt().takeIf { it > 0 } ?: 0) - .toString() - ), - maxLines = 1, - fontWeight = FontWeight.Bold - ) - } - } - } - } - - FilledIconButton(onClick = { - routes.messagingPreview.navigate { - put("id", id) - put("scope", scope.key) - } - }) { - Icon(imageVector = Icons.Filled.RemoveRedEye, contentDescription = null) - } - } - } - } - } - } - - override val floatingActionButton: @Composable () -> Unit = { - var addFriendDialog by remember { mutableStateOf(null as AddFriendDialog?) } - - if (addFriendDialog != null) { - addFriendDialog?.Content { - addFriendDialog = null - } - DisposableEffect(Unit) { - onDispose { - updateScopeLists() - } - } - } - - FloatingActionButton( - onClick = { - addFriendDialog = AddFriendDialog( - context, - AddFriendDialog.Actions( - onFriendState = { friend, state -> - if (state) { - context.bridgeService?.triggerScopeSync( - SocialScope.FRIEND, - friend.userId - ) - } else { - context.database.deleteFriend(friend.userId) - } - }, - onGroupState = { group, state -> - if (state) { - context.bridgeService?.triggerScopeSync( - SocialScope.GROUP, - group.conversationId - ) - } else { - context.database.deleteGroup(group.conversationId) - } - }, - getFriendState = { friend -> context.database.getFriendInfo(friend.userId) != null }, - getGroupState = { group -> context.database.getGroupInfo(group.conversationId) != null } - ), - pinnedIds = (friendList.map { it.userId } + groupList.map { it.conversationId }).reversed(), - ) - }, - modifier = Modifier.padding(10.dp), - containerColor = MaterialTheme.colorScheme.primary, - contentColor = MaterialTheme.colorScheme.onPrimary, - shape = RoundedCornerShape(16.dp), - ) { - Icon( - imageVector = Icons.Rounded.Add, - contentDescription = null - ) - } - } - - @OptIn(ExperimentalFoundationApi::class) - override val content: @Composable (NavBackStackEntry) -> Unit = { - val titles = remember { - listOf(translation["friends_tab"], translation["groups_tab"]) - } - val coroutineScope = rememberCoroutineScope() - val pagerState = rememberPagerState { titles.size } - - LaunchedEffect(Unit) { - updateScopeLists() - } - - Column(modifier = Modifier.fillMaxSize()) { - SingleChoiceSegmentedButtonRow( - modifier = Modifier - .fillMaxWidth() - .padding(horizontal = 8.dp) - ) { - titles.forEachIndexed { index, title -> - val shape = when (index) { - 0 -> RoundedCornerShape(topStart = 24.dp, bottomStart = 24.dp) - titles.lastIndex -> RoundedCornerShape(topEnd = 24.dp, bottomEnd = 24.dp) - else -> RoundedCornerShape(0.dp) - } - SegmentedButton( - selected = pagerState.currentPage == index, - onClick = { - coroutineScope.launch { - pagerState.animateScrollToPage(index) - } - }, - shape = shape, - modifier = Modifier.weight(1f), - icon = {}, - label = { - Text( - text = title, - maxLines = 2, - overflow = TextOverflow.Ellipsis - ) - } - ) - } - } - - HorizontalPager( - modifier = Modifier.fillMaxSize(), - state = pagerState - ) { page -> - when (page) { - 0 -> ScopeList(SocialScope.FRIEND) - 1 -> ScopeList(SocialScope.GROUP) - } - } - } - } -} diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/tracker/EditRule.kt b/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/tracker/EditRule.kt deleted file mode 100644 index a7415b95..00000000 --- a/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/tracker/EditRule.kt +++ /dev/null @@ -1,562 +0,0 @@ -@file:OptIn( - androidx.compose.material3.ExperimentalMaterial3Api::class, - androidx.compose.foundation.layout.ExperimentalLayoutApi::class -) -package me.rhunk.snapenhance.ui.manager.pages.tracker - -import androidx.compose.animation.animateContentSize -import androidx.compose.foundation.ExperimentalFoundationApi -import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.* -import androidx.compose.foundation.rememberScrollState -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.foundation.verticalScroll -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.automirrored.filled.ArrowBack -import androidx.compose.material.icons.filled.Add -import androidx.compose.material.icons.filled.DeleteOutline -import androidx.compose.material.icons.filled.ExpandLess -import androidx.compose.material.icons.filled.ExpandMore -import androidx.compose.material.icons.filled.Info -import androidx.compose.material.icons.filled.Save -import androidx.compose.material.icons.filled.Warning -import androidx.activity.compose.BackHandler -import androidx.compose.material3.* -import androidx.compose.runtime.* -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.text.style.TextAlign -import androidx.compose.ui.text.style.TextOverflow -import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp -import androidx.compose.ui.window.Dialog -import androidx.compose.ui.window.DialogProperties -import androidx.navigation.NavBackStackEntry -import kotlinx.coroutines.launch -import me.rhunk.snapenhance.common.data.* -import me.rhunk.snapenhance.common.ui.rememberAsyncMutableState -import me.rhunk.snapenhance.common.ui.rememberAsyncMutableStateList -import me.rhunk.snapenhance.storage.* -import me.rhunk.snapenhance.ui.manager.Routes -import me.rhunk.snapenhance.ui.manager.components.AestheticDialog -import me.rhunk.snapenhance.ui.manager.pages.social.AddFriendDialog - -class EditRule : Routes.Route() { - override val translation by lazy { context.translation.getCategory("manager.friend_tracker") } - @Composable - fun ActionCheckbox( - text: String, - checked: MutableState, - onChanged: (Boolean) -> Unit = {} - ) { - Row( - modifier = Modifier.clickable { - checked.value = !checked.value - onChanged(checked.value) - }, - horizontalArrangement = Arrangement.spacedBy(2.dp), - verticalAlignment = Alignment.CenterVertically - ) { - Checkbox( - modifier = Modifier.height(30.dp), - checked = checked.value, - onCheckedChange = { checked.value = it; onChanged(it) } - ) - Text(text, fontSize = 12.sp) - } - } - @Composable - fun ConditionCheckboxes( - params: TrackerRuleActionParams - ) { - ActionCheckbox( - text = translation["condition_only_inside_conversation"], - checked = remember { mutableStateOf(params.onlyInsideConversation) }, - onChanged = { params.onlyInsideConversation = it } - ) - ActionCheckbox( - text = translation["condition_only_outside_conversation"], - checked = remember { mutableStateOf(params.onlyOutsideConversation) }, - onChanged = { params.onlyOutsideConversation = it } - ) - ActionCheckbox( - text = translation["condition_only_when_app_active"], - checked = remember { mutableStateOf(params.onlyWhenAppActive) }, - onChanged = { params.onlyWhenAppActive = it } - ) - ActionCheckbox( - text = translation["condition_only_when_app_inactive"], - checked = remember { mutableStateOf(params.onlyWhenAppInactive) }, - onChanged = { params.onlyWhenAppInactive = it } - ) - ActionCheckbox( - text = translation["condition_no_push_notification_when_app_active"], - checked = remember { mutableStateOf(params.noPushNotificationWhenAppActive) }, - onChanged = { params.noPushNotificationWhenAppActive = it } - ) - } - @Composable - fun AddEventDialog( - onDismissRequest: () -> Unit, - onEventAdd: (TrackerRuleEvent) -> Unit - ) { - val expanded = remember { mutableStateOf(false) } - val currentEventType = remember { mutableStateOf(TrackerEventType.CONVERSATION_ENTER.key) } - val addEventActions = remember { mutableStateOf(emptySet()) } - val addEventActionParams = remember { TrackerRuleActionParams() } - Dialog( - onDismissRequest = onDismissRequest, - properties = DialogProperties(dismissOnClickOutside = true, usePlatformDefaultWidth = false) - ) { - Card { - Column( - Modifier - .padding(16.dp)) { - Row(verticalAlignment = Alignment.CenterVertically) { - Text(translation["add_event_dialog_title"], style = MaterialTheme.typography.titleLarge, modifier = Modifier.weight(1f)) - IconButton(onClick = onDismissRequest) { - Icon(Icons.Default.DeleteOutline, contentDescription = translation["button.close"]) - } - } - Spacer(Modifier.height(16.dp)) - ExposedDropdownMenuBox( - expanded = expanded.value, - onExpandedChange = { expanded.value = !expanded.value }, - modifier = Modifier.fillMaxWidth() - ) { - OutlinedTextField( - modifier = Modifier.fillMaxWidth(), - value = context.translation["tracker_events.${currentEventType.value}"], - onValueChange = {}, - readOnly = true, - label = { Text(translation["event_type_label"]) }, - trailingIcon = { ExposedDropdownMenuDefaults.TrailingIcon(expanded = expanded.value) }, - ) - ExposedDropdownMenu( - expanded = expanded.value, - onDismissRequest = { expanded.value = false } - ) { - TrackerEventType.entries.forEach { eventType -> - DropdownMenuItem( - onClick = { - currentEventType.value = eventType.key - expanded.value = false - }, - text = { Text(context.translation["tracker_events.${eventType.key}"]) } - ) - } - } - } - Spacer(Modifier.height(12.dp)) - Text(translation["triggers_title"], style = MaterialTheme.typography.titleMedium) - FlowRow( - modifier = Modifier.fillMaxWidth(), - horizontalArrangement = Arrangement.spacedBy(8.dp) - ) { - TrackerRuleAction.entries.forEach { action -> - ActionCheckbox( - context.translation["tracker_actions.${action.key}"], - checked = remember { mutableStateOf(addEventActions.value.contains(action)) } - ) { - if (it) addEventActions.value += action else addEventActions.value -= action - } - } - } - Spacer(Modifier.height(12.dp)) - Text(translation["conditions_title"], style = MaterialTheme.typography.titleMedium) - ConditionCheckboxes(addEventActionParams) - Spacer(Modifier.height(16.dp)) - Button( - onClick = { - onEventAdd( - TrackerRuleEvent( - id = -1, - enabled = true, - eventType = currentEventType.value, - params = addEventActionParams.copy(), - actions = addEventActions.value.toList() - ) - ) - }, - modifier = Modifier.align(Alignment.End) - ) { Text(translation["add_button"]) } - } - } - } - } - override val title: @Composable () -> Unit = {} - @OptIn(ExperimentalFoundationApi::class) - override val content: @Composable (NavBackStackEntry) -> Unit = { navBackStackEntry -> - val coroutineScope = rememberCoroutineScope() - val currentRuleId = navBackStackEntry.arguments?.getString("rule_id")?.toIntOrNull() - val events = rememberAsyncMutableStateList(defaultValue = emptyList()) { - currentRuleId?.let { ruleId -> context.database.getTrackerEvents(ruleId) } ?: emptyList() - } - val eventsToDelete = remember { mutableStateListOf() } - var currentScopeType by remember { mutableStateOf(TrackerScopeType.BLACKLIST) } - val scopes = rememberAsyncMutableStateList(defaultValue = emptyList()) { - currentRuleId?.let { ruleId -> - context.database.getRuleTrackerScopes(ruleId).also { map -> - currentScopeType = if (map.isEmpty()) TrackerScopeType.WHITELIST else map.values.first() - }.map { entry -> entry.key } - } ?: emptyList() - } - val ruleName = rememberAsyncMutableState(defaultValue = "", keys = arrayOf(currentRuleId)) { - currentRuleId?.let { ruleId -> context.database.getTrackerRule(ruleId)?.name ?: translation["default_rule_name"] } ?: translation["default_rule_name"] - } - val authorName = rememberAsyncMutableState(defaultValue = "", keys = arrayOf(currentRuleId)) { - currentRuleId?.let { ruleId -> context.database.getTrackerRule(ruleId)?.author ?: "" } ?: "" - } - val initialRuleState by remember(ruleName.value.isNotBlank() || events.isNotEmpty() || scopes.isNotEmpty()) { - mutableStateOf( - mapOf( - "name" to ruleName.value, - "author" to authorName.value, - "scopes" to scopes.toList(), - "events" to events.toList(), - "scopeType" to currentScopeType - ) - ) - } - val isDirty by remember { - derivedStateOf { - initialRuleState["name"] != ruleName.value || - initialRuleState["author"] != authorName.value || - initialRuleState["scopes"] != scopes.toList() || - initialRuleState["events"] != events.toList() || - initialRuleState["scopeType"] != currentScopeType - } - } - var deleteConfirmation by remember { mutableStateOf(false) } - var showDuplicateNameDialog by remember { mutableStateOf(false) } - var showEventsEmptyDialog by remember { mutableStateOf(false) } - var showDiscardDialog by remember { mutableStateOf(false) } - var addFriendDialog by remember { mutableStateOf(null) } - var addEventDialogVisible by remember { mutableStateOf(false) } - if (showDiscardDialog) { - AestheticDialog( - onDismissRequest = { showDiscardDialog = false }, - title = translation["discard_changes_dialog_title"], - text = translation["discard_changes_dialog_text"], - icon = Icons.Default.Warning, - confirmButtonText = translation["discard_button"], - onConfirm = { - showDiscardDialog = false - routes.navController.popBackStack() - }, - dismissButtonText = translation["button.cancel"], - onDismiss = { showDiscardDialog = false } - ) - } - BackHandler(enabled = isDirty) { - showDiscardDialog = true - } - if (showEventsEmptyDialog) { - Dialog(onDismissRequest = { showEventsEmptyDialog = false }) { - Card( - shape = RoundedCornerShape(16.dp), - ) { - Column( - modifier = Modifier.padding(24.dp), - horizontalAlignment = Alignment.CenterHorizontally, - verticalArrangement = Arrangement.spacedBy(16.dp) - ) { - Icon( - imageVector = Icons.Default.Info, - contentDescription = null, - modifier = Modifier.size(48.dp), - tint = MaterialTheme.colorScheme.primary - ) - Text( - text = translation["cannot_save_rule_dialog_title"], - style = MaterialTheme.typography.headlineSmall, - fontWeight = FontWeight.Bold - ) - Text( - text = translation["cannot_save_rule_dialog_text"], - style = MaterialTheme.typography.bodyMedium, - textAlign = TextAlign.Center - ) - Button( - onClick = { showEventsEmptyDialog = false }, - modifier = Modifier.fillMaxWidth() - ) { - Text(translation["button.ok"]) - } - } - } - } - } - if (showDuplicateNameDialog) { - AlertDialog( - onDismissRequest = { showDuplicateNameDialog = false }, - title = { Text(translation["duplicate_rule_name_dialog_title"]) }, - text = { Text(translation["duplicate_rule_name_dialog_text"]) }, - confirmButton = { - Button(onClick = { showDuplicateNameDialog = false }) { - Text(translation["button.ok"]) - } - } - ) - } - if (deleteConfirmation) { - AlertDialog( - onDismissRequest = { deleteConfirmation = false }, - title = { Text(translation["delete_rule_dialog_title"]) }, - text = { Text(translation["delete_rule_dialog_text"]) }, - confirmButton = { - Button( - onClick = { - if (currentRuleId != null) context.database.deleteTrackerRule(currentRuleId) - routes.navController.popBackStack() - } - ) { Text(translation["delete_button"]) } - }, - dismissButton = { - Button(onClick = { deleteConfirmation = false }) { Text(translation["button.cancel"]) } - } - ) - } - Scaffold( - modifier = Modifier - .fillMaxSize() - .systemBarsPadding() - .navigationBarsPadding(), - topBar = { - TopAppBar( - title = { Text(translation[if (currentRuleId == null) "new_rule_title" else "edit_rule_title"]) }, - navigationIcon = { - IconButton(onClick = { - if (isDirty) { - showDiscardDialog = true - } else { - routes.navController.popBackStack() - } - }) { - Icon(Icons.AutoMirrored.Filled.ArrowBack, contentDescription = translation["back_button_description"]) - } - }, - actions = { - IconButton(onClick = { - if (events.isEmpty()) { - showEventsEmptyDialog = true - return@IconButton - } - if (currentRuleId == null && context.database.getTrackerRuleByName(ruleName.value.trim()) != null) { - showDuplicateNameDialog = true - return@IconButton - } - val ruleId = currentRuleId ?: context.database.newTrackerRule() - eventsToDelete.forEach { event -> context.database.deleteTrackerRuleEvent(event.id.takeIf { it > -1 } ?: return@forEach) } - events.forEach { event -> - context.database.addOrUpdateTrackerRuleEvent( - event.id.takeIf { it > -1 }, - ruleId, - event.eventType, - event.params, - event.actions - ) - } - context.database.setTrackerRuleName(ruleId, ruleName.value.trim()) - context.database.setTrackerRuleAuthor(ruleId, authorName.value.trim()) - context.database.setRuleTrackerScopes(ruleId, currentScopeType, scopes) - routes.navController.popBackStack() - }) { Icon(Icons.Filled.Save, contentDescription = translation["save_button_description"]) } - if (currentRuleId != null) { - IconButton(onClick = { deleteConfirmation = true }) { - Icon(Icons.Default.DeleteOutline, contentDescription = translation["delete_button_description"]) - } - } - } - ) - } - ) { padding -> - Column( - modifier = Modifier - .fillMaxSize() - .padding(padding) - .verticalScroll(rememberScrollState()), - verticalArrangement = Arrangement.spacedBy(12.dp) - ) { - Card(Modifier.fillMaxWidth().padding(12.dp)) { - Column(Modifier.padding(16.dp)) { - Text(translation["general_section_title"], style = MaterialTheme.typography.titleMedium) - OutlinedTextField( - value = ruleName.value, - onValueChange = { ruleName.value = it }, - label = { Text(translation["rule_name_label"]) }, - modifier = Modifier.fillMaxWidth(), - singleLine = true - ) - Spacer(modifier = Modifier.height(8.dp)) - OutlinedTextField( - value = authorName.value, - onValueChange = { authorName.value = it }, - label = { Text(translation["author_name_label"]) }, - modifier = Modifier.fillMaxWidth(), - singleLine = true - ) - } - } - Card(Modifier.fillMaxWidth().padding(horizontal = 12.dp)) { - Column(Modifier.padding(16.dp)) { - Text(translation["scope_section_title"], style = MaterialTheme.typography.titleMedium) - val friendDialogActions = remember { - AddFriendDialog.Actions( - onFriendState = { friend, state -> - if (state) scopes.add(friend.userId) else scopes.remove(friend.userId) - }, - onGroupState = { group, state -> - if (state) scopes.add(group.conversationId) else scopes.remove(group.conversationId) - }, - getFriendState = { friend -> friend.userId in scopes }, - getGroupState = { group -> group.conversationId in scopes } - ) - } - val scopeOptions = listOf(translation["scope_all"], translation["scope_whitelist"], translation["scope_blacklist"]) - val selectedScopeIndex = when { - scopes.isEmpty() -> 0 - currentScopeType == TrackerScopeType.WHITELIST -> 1 - else -> 2 - } - SingleChoiceSegmentedButtonRow( - modifier = Modifier.fillMaxWidth().padding(top = 10.dp, bottom = 12.dp) - ) { - scopeOptions.forEachIndexed { index, label -> - SegmentedButton( - shape = SegmentedButtonDefaults.itemShape(index, scopeOptions.size), - onClick = { - when (index) { - 0 -> scopes.clear() - 1 -> { - currentScopeType = TrackerScopeType.WHITELIST - if (scopes.isEmpty()) { - addFriendDialog = AddFriendDialog(context, friendDialogActions, pinnedIds = scopes) - } - } - 2 -> { - currentScopeType = TrackerScopeType.BLACKLIST - if (scopes.isEmpty()) { - addFriendDialog = AddFriendDialog(context, friendDialogActions, pinnedIds = scopes) - } - } - } - }, - selected = index == selectedScopeIndex - ) { Text(label) } - } - } - if (scopes.isNotEmpty()) { - Button( - onClick = { - addFriendDialog = AddFriendDialog(context, friendDialogActions, pinnedIds = scopes) - }, - modifier = Modifier.fillMaxWidth().padding(vertical = 4.dp) - ) { Text(translation.format("select_friends_groups_button", "count" to scopes.size.toString())) } - } - addFriendDialog?.Content { addFriendDialog = null } - } - } - Card(Modifier.fillMaxWidth().padding(12.dp)) { - Column( - Modifier - .padding(16.dp) - .animateContentSize()) { - Row( - modifier = Modifier.fillMaxWidth(), - horizontalArrangement = Arrangement.SpaceBetween, - verticalAlignment = Alignment.CenterVertically - ) { - Text(translation["events_section_title"], fontSize = 16.sp, fontWeight = FontWeight.Bold) - IconButton(onClick = { addEventDialogVisible = true }) { - Icon(Icons.Default.Add, contentDescription = translation["add_event_button"], modifier = Modifier.size(28.dp)) - } - } - if (addEventDialogVisible) { - AddEventDialog( - onDismissRequest = { addEventDialogVisible = false }, - onEventAdd = { event -> - events.add(0, event) - addEventDialogVisible = false - } - ) - } - if (events.isEmpty()) { - Text( - translation["no_events_text"], - fontSize = 12.sp, - fontWeight = FontWeight.Light, - modifier = Modifier - .padding(10.dp) - .fillMaxWidth(), - textAlign = TextAlign.Center - ) - } - events.forEach { event -> - var expanded by remember { mutableStateOf(false) } - ElevatedCard( - modifier = Modifier - .fillMaxWidth() - .animateContentSize() - .padding(vertical = 4.dp) - .clickable { expanded = !expanded } - ) { - Column(Modifier.padding(8.dp)) { - Row( - modifier = Modifier.fillMaxWidth(), - horizontalArrangement = Arrangement.SpaceBetween, - verticalAlignment = Alignment.CenterVertically - ) { - Row( - modifier = Modifier.weight(1f, fill = false), - horizontalArrangement = Arrangement.spacedBy(8.dp), - verticalAlignment = Alignment.CenterVertically - ) { - Icon( - if (expanded) Icons.Filled.ExpandLess else Icons.Filled.ExpandMore, - contentDescription = null - ) - Column { - Text( - context.translation["tracker_events.${event.eventType}"], - lineHeight = 20.sp, - fontSize = 18.sp, - fontWeight = FontWeight.Bold - ) - Text( - text = event.actions.joinToString(", ") { context.translation["tracker_actions.${it.key}"] }, - fontSize = 10.sp, - fontWeight = FontWeight.Light, - overflow = TextOverflow.Ellipsis, - maxLines = 1, - lineHeight = 14.sp - ) - } - } - OutlinedIconButton( - onClick = { - if (event.id > -1) { - eventsToDelete.add(event) - } - events.remove(event) - } - ) { - Icon(Icons.Default.DeleteOutline, contentDescription = translation["delete_button_description"]) - } - } - if (expanded) { - Column(modifier = Modifier.padding(top = 8.dp)) { - ConditionCheckboxes(event.params) - } - } - } - } - } - } - } - Spacer(Modifier.height(routes.bottomPadding)) - } - } - } -} diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/tracker/FriendTrackerManagerRoot.kt b/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/tracker/FriendTrackerManagerRoot.kt deleted file mode 100644 index f51d1af6..00000000 --- a/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/tracker/FriendTrackerManagerRoot.kt +++ /dev/null @@ -1,503 +0,0 @@ -package me.rhunk.snapenhance.ui.manager.pages.tracker - -import androidx.compose.foundation.BorderStroke -import androidx.compose.foundation.ExperimentalFoundationApi -import androidx.compose.foundation.background -import androidx.compose.foundation.border -import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.* -import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.items -import androidx.compose.foundation.pager.HorizontalPager -import androidx.compose.foundation.pager.rememberPagerState -import androidx.compose.foundation.shape.CircleShape -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material.icons.Icons -import androidx.compose.material3.SingleChoiceSegmentedButtonRow -import androidx.compose.material.icons.filled.Add -import androidx.compose.material.icons.filled.DeleteOutline -import androidx.compose.material.icons.filled.FolderOpen -import androidx.compose.material.icons.filled.SaveAlt -import androidx.compose.material.icons.filled.UploadFile -import androidx.compose.material.icons.filled.FileOpen -import androidx.compose.material.icons.filled.Store -import androidx.compose.foundation.layout.padding -import androidx.compose.ui.unit.dp -import androidx.compose.ui.window.Dialog -import androidx.compose.material3.* -import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableIntStateOf -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember -import androidx.compose.runtime.rememberCoroutineScope -import androidx.compose.runtime.setValue -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.clip -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.text.style.TextAlign -import androidx.compose.ui.text.style.TextOverflow -import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp -import androidx.navigation.NavBackStackEntry -import kotlinx.coroutines.launch -import me.rhunk.snapenhance.common.ui.rememberAsyncMutableState -import me.rhunk.snapenhance.common.ui.rememberAsyncMutableStateList -import me.rhunk.snapenhance.common.ui.rememberAsyncUpdateDispatcher -import me.rhunk.snapenhance.common.util.snap.BitmojiSelfie -import me.rhunk.snapenhance.storage.* -import me.rhunk.snapenhance.ui.manager.Routes -import me.rhunk.snapenhance.ui.util.ActivityLauncherHelper -import me.rhunk.snapenhance.ui.util.coil.BitmojiImage -import me.rhunk.snapenhance.ui.util.openFile -import me.rhunk.snapenhance.ui.util.pagerTabIndicatorOffset - - -@OptIn(ExperimentalFoundationApi::class) -class FriendTrackerManagerRoot : Routes.Route() { - enum class FilterType { - CONVERSATION, USERNAME, EVENT - } - - override val translation by lazy { context.translation.getCategory("manager.friend_tracker") } - private val titles by lazy { - listOf( - translation["rules_tab"], - translation["logs_tab"] - ) - } - private var currentPage by mutableIntStateOf(0) - private lateinit var logDeleteAction : () -> Unit - private lateinit var exportAction : () -> Unit - - override val topBarActions: @Composable RowScope.() -> Unit = { - var showExportDialog by remember { mutableStateOf(false) } - var showSingleExportDialog by remember { mutableStateOf(false) } - var showImportDialog by remember { mutableStateOf(false) } - var showInvalidImportTypeDialog by remember { mutableStateOf(false) } - - if (showExportDialog) { - ChoiceDialog( - onDismissRequest = { showExportDialog = false }, - title = translation["export_dialog_title"], - choices = listOf( - translation["bulk_export_button"] to { Icon(Icons.Default.UploadFile, translation["bulk_export_button"]) }, - translation["individual_export_button"] to { Icon(Icons.Default.FileOpen, translation["individual_export_button"]) } - ), - onChoiceSelected = { index -> - showExportDialog = false - when (index) { - 0 -> routes.friendTrackerConfigExport.navigate() - 1 -> showSingleExportDialog = true - } - } - ) - } - - if (showSingleExportDialog) { - val rules = rememberAsyncMutableStateList(defaultValue = emptyList()) { - context.database.getTrackerRulesDesc() - } - SelectRuleDialog( - onDismissRequest = { showSingleExportDialog = false }, - rules = rules, - onRuleSelected = { rule -> - showSingleExportDialog = false - routes.friendTrackerConfigExport.navigate { - this["rule_id"] = rule.id.toString() - } - }, - translation = translation - ) - } - - fun handleImport(type: me.rhunk.snapenhance.common.data.ExportType) { - routes.activityLauncher.openFile("application/json") { uri -> - runCatching { - val content = context.androidContext.contentResolver.openInputStream(android.net.Uri.parse(uri))?.use { - it.readBytes().toString(Charsets.UTF_8) - } ?: return@runCatching - val exportedData = context.gson.fromJson(content, me.rhunk.snapenhance.common.data.ExportedTrackerData::class.java) - if (exportedData.type != type) { - showInvalidImportTypeDialog = true - return@runCatching - } - routes.friendTrackerConfigJsonForImport = content - routes.friendTrackerConfigImport.navigate() - }.onFailure { - context.longToast("Failed to read file: ${it.message}") - } - } - } - - if (showInvalidImportTypeDialog) { - AlertDialog( - onDismissRequest = { showInvalidImportTypeDialog = false }, - title = { Text(translation["invalid_import_type_dialog_title"]) }, - text = { Text(translation["invalid_import_type_dialog_text"]) }, - confirmButton = { - Button(onClick = { showInvalidImportTypeDialog = false }) { - Text(translation["button.ok"]) - } - } - ) - } - - if (showImportDialog) { - ChoiceDialog( - onDismissRequest = { showImportDialog = false }, - title = translation["import_dialog_title"], - choices = listOf( - translation["bulk_import_button"] to { Icon(Icons.Default.UploadFile, translation["bulk_import_button"]) }, - translation["individual_import_button"] to { Icon(Icons.Default.FileOpen, translation["individual_import_button"]) } - ), - onChoiceSelected = { index -> - showImportDialog = false - when (index) { - 0 -> handleImport(me.rhunk.snapenhance.common.data.ExportType.BULK) - 1 -> handleImport(me.rhunk.snapenhance.common.data.ExportType.SINGLE) - } - } - ) - } - - if (currentPage == 0) { - IconButton(onClick = { - showImportDialog = true - }) { - Icon(Icons.Default.FolderOpen, contentDescription = translation["import_button_description"]) - } - IconButton(onClick = { - showExportDialog = true - }) { - Icon(Icons.Default.SaveAlt, contentDescription = translation["export_button_description"]) - } - } - } - - private lateinit var activityLauncherHelper: ActivityLauncherHelper - - override val init: () -> Unit = { - activityLauncherHelper = ActivityLauncherHelper(context.activity!!) - } - - override val floatingActionButton: @Composable () -> Unit = { - when (currentPage) { - 1 -> { - Column( - verticalArrangement = Arrangement.spacedBy(6.dp), - ) { - ExtendedFloatingActionButton( - icon = { Icon(Icons.Default.SaveAlt, contentDescription = translation["export_button_description"]) }, - expanded = true, - text = { Text(translation["export_button"]) }, - onClick = { - context.coroutineScope.launch { exportAction() } - } - ) - ExtendedFloatingActionButton( - icon = { Icon(Icons.Default.DeleteOutline, contentDescription = translation["delete_button_description"]) }, - expanded = true, - text = { Text(translation["delete_button"]) }, - onClick = { - context.coroutineScope.launch { logDeleteAction() } - } - ) - } - } - 0 -> { - Column(verticalArrangement = Arrangement.spacedBy(6.dp), horizontalAlignment = Alignment.End) { - ExtendedFloatingActionButton( - icon = { Icon(Icons.Default.Store, contentDescription = translation["catalog_button_description"]) }, - expanded = true, - text = { Text(translation["catalog_button"]) }, - onClick = { routes.friendTrackerCatalog.navigate() } - ) - ExtendedFloatingActionButton( - icon = { Icon(Icons.Default.Add, contentDescription = translation["add_rule_button_description"]) }, - expanded = true, - text = { Text(translation["add_rule_button"]) }, - onClick = { routes.editRule.navigate() } - ) - } - } - } - } - - @Composable - private fun ConfigRulesTab() { - val updateRules = rememberAsyncUpdateDispatcher() - val rules = rememberAsyncMutableStateList(defaultValue = listOf(), updateDispatcher = updateRules) { - context.database.getTrackerRulesDesc() - } - - Column( - modifier = Modifier.fillMaxSize() - ) { - LazyColumn( - modifier = Modifier.weight(1f), - contentPadding = PaddingValues(bottom = routes.bottomPadding) - ) { - item { - if (rules.isEmpty()) { - Text(translation["no_rules_found"], modifier = Modifier - .padding(16.dp) - .fillMaxWidth(), textAlign = TextAlign.Center, fontWeight = FontWeight.Light) - } - } - items(rules, key = { it.id }) { rule -> - val ruleName by rememberAsyncMutableState(defaultValue = rule.name) { - context.database.getTrackerRule(rule.id)?.name ?: translation["empty_rule_name"] - } - val eventCount by rememberAsyncMutableState(defaultValue = 0) { - context.database.getTrackerEvents(rule.id).size - } - val scopeCount by rememberAsyncMutableState(defaultValue = 0) { - context.database.getRuleTrackerScopes(rule.id).size - } - var enabled by rememberAsyncMutableState(defaultValue = rule.enabled) { - context.database.getTrackerRule(rule.id)?.enabled ?: false - } - - ElevatedCard( - modifier = Modifier - .fillMaxWidth() - .clickable { - routes.editRule.navigate { - this["rule_id"] = rule.id.toString() - } - } - .padding(5.dp) - ) { - Row( - modifier = Modifier - .fillMaxWidth(), - verticalAlignment = Alignment.CenterVertically - ) { - Column( - modifier = Modifier - .fillMaxWidth() - .padding(16.dp) - .weight(1f), - verticalArrangement = Arrangement.spacedBy(2.dp) - ) { - Text(ruleName, fontSize = 20.sp, fontWeight = FontWeight.Bold) - Text(buildString { - append(eventCount) - append(" ") - append(translation["events_suffix"]) - if (scopeCount > 0) { - append(", ") - append(scopeCount) - append(" ") - append(translation["scopes_suffix"]) - } - }, fontSize = 13.sp, fontWeight = FontWeight.Light) - } - - Row( - modifier = Modifier.padding(10.dp), - horizontalArrangement = Arrangement.spacedBy(10.dp) - ) { - val scopesBitmoji = rememberAsyncMutableStateList(defaultValue = emptyList()) { - context.database.getRuleTrackerScopes(rule.id, limit = 10).mapNotNull { - context.database.getFriendInfo(it.key)?.let { friend -> - friend.selfieId to friend.bitmojiId - } - }.take(3) - } - - Row { - scopesBitmoji.forEachIndexed { index, friend -> - Box( - modifier = Modifier - .offset(x = (-index * 20).dp + (scopesBitmoji.size * 20).dp - 20.dp) - ) { - BitmojiImage( - size = 50, - modifier = Modifier - .border( - BorderStroke(1.dp, Color.White), - CircleShape - ) - .background(Color.White, CircleShape) - .clip(CircleShape), - context = context, - url = BitmojiSelfie.getBitmojiSelfie(friend.first, friend.second, BitmojiSelfie.BitmojiSelfieType.NEW_THREE_D), - ) - } - } - } - - Box(modifier = Modifier - .padding(start = 5.dp, end = 5.dp) - .height(50.dp) - .width(1.dp) - .background( - color = MaterialTheme.colorScheme.primary.copy(alpha = 0.12f), - shape = RoundedCornerShape(5.dp) - ) - ) - - Switch( - checked = enabled, - onCheckedChange = { - enabled = it - context.database.setTrackerRuleState(rule.id, it) - } - ) - } - } - } - } - } - } - } - - - @OptIn(ExperimentalFoundationApi::class) - override val content: @Composable (NavBackStackEntry) -> Unit = { - val coroutineScope = rememberCoroutineScope() - val pagerState = rememberPagerState(initialPage = 0) { titles.size } - currentPage = pagerState.currentPage - - Column { - SingleChoiceSegmentedButtonRow( - modifier = Modifier - .fillMaxWidth() - .padding(horizontal = 8.dp) - ) { - titles.forEachIndexed { i, text -> - val shape = when (i) { - 0 -> RoundedCornerShape(topStart = 24.dp, bottomStart = 24.dp) - titles.lastIndex -> RoundedCornerShape(topEnd = 24.dp, bottomEnd = 24.dp) - else -> RoundedCornerShape(0.dp) - } - SegmentedButton( - selected = pagerState.currentPage == i, - onClick = { - coroutineScope.launch { - pagerState.animateScrollToPage(i) - } - }, - shape = shape, - modifier = Modifier.weight(1f), - icon = {}, - label = { Text(text) } - ) - } - } - - HorizontalPager( - modifier = Modifier.weight(1f), - state = pagerState - ) { page -> - when (page) { - 1 -> LogsTab( - context = context, - activityLauncherHelper = activityLauncherHelper, - deleteAction = { logDeleteAction = it }, - exportAction = { exportAction = it }, - bottomPadding = routes.bottomPadding - ) - 0 -> ConfigRulesTab() - } - } - } - } -} - -@Composable -private fun SelectRuleDialog( - onDismissRequest: () -> Unit, - rules: List, - onRuleSelected: (me.rhunk.snapenhance.common.data.TrackerRule) -> Unit, - translation: me.rhunk.snapenhance.common.bridge.wrapper.LocaleWrapper -) { - Dialog(onDismissRequest = onDismissRequest) { - Card( - shape = RoundedCornerShape(16.dp), - ) { - Column( - modifier = Modifier.padding(16.dp), - horizontalAlignment = Alignment.CenterHorizontally, - verticalArrangement = Arrangement.spacedBy(10.dp) - ) { - Text(translation["manager.friend_tracker.select_rule_to_export_title"], style = MaterialTheme.typography.headlineSmall) - LazyColumn( - verticalArrangement = Arrangement.spacedBy(8.dp) - ) { - items(rules) { rule -> - ElevatedCard( - onClick = { onRuleSelected(rule) }, - modifier = Modifier.fillMaxWidth() - ) { - Text( - text = rule.name, - modifier = Modifier.padding(16.dp), - fontWeight = FontWeight.SemiBold - ) - } - } - } - TextButton(onClick = onDismissRequest) { - Text(translation["button.cancel"]) - } - } - } - } -} - -@Composable -private fun ChoiceDialog( - onDismissRequest: () -> Unit, - title: String, - choices: List Unit>>, - onChoiceSelected: (Int) -> Unit -) { - Dialog(onDismissRequest = onDismissRequest) { - Card( - shape = RoundedCornerShape(16.dp), - ) { - Column( - modifier = Modifier.padding(16.dp), - horizontalAlignment = Alignment.CenterHorizontally, - verticalArrangement = Arrangement.spacedBy(10.dp) - ) { - Text(text = title, style = MaterialTheme.typography.headlineSmall) - choices.forEachIndexed { index, (text, icon) -> - SelectButton( - onClick = { onChoiceSelected(index) }, - text = text, - leadingIcon = icon - ) - } - } - } - } -} - -@Composable -private fun SelectButton( - onClick: () -> Unit, - text: String, - leadingIcon: @Composable (() -> Unit)? = null, -) { - OutlinedButton( - onClick = onClick, - modifier = Modifier.fillMaxWidth(), - contentPadding = PaddingValues(16.dp) - ) { - Row( - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.spacedBy(10.dp) - ) { - if (leadingIcon != null) { - leadingIcon() - } - Text(text = text, modifier = Modifier.weight(1f)) - } - } -} diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/tracker/LogsTab.kt b/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/tracker/LogsTab.kt deleted file mode 100644 index 4781109c..00000000 --- a/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/tracker/LogsTab.kt +++ /dev/null @@ -1,601 +0,0 @@ -package me.rhunk.snapenhance.ui.manager.pages.tracker - -import android.net.Uri -import androidx.compose.foundation.layout.* -import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.items -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.Clear -import androidx.compose.material.icons.filled.DeleteOutline -import androidx.compose.material.icons.filled.FilterList -import androidx.compose.material3.* -import androidx.compose.runtime.* -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.text.style.TextAlign -import androidx.compose.ui.text.style.TextOverflow -import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp -import androidx.compose.ui.unit.Dp -import androidx.compose.ui.window.PopupProperties -import com.google.gson.stream.JsonWriter -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.Job -import kotlinx.coroutines.delay -import kotlinx.coroutines.launch -import kotlinx.coroutines.withContext -import me.rhunk.snapenhance.RemoteSideContext -import me.rhunk.snapenhance.common.bridge.wrapper.TrackerLog -import me.rhunk.snapenhance.common.data.MessagingFriendInfo -import me.rhunk.snapenhance.common.data.TrackerEventType -import me.rhunk.snapenhance.common.util.snap.BitmojiSelfie -import me.rhunk.snapenhance.storage.getFriendInfo -import me.rhunk.snapenhance.ui.util.ActivityLauncherHelper -import me.rhunk.snapenhance.ui.util.coil.BitmojiImage -import me.rhunk.snapenhance.ui.util.saveFile -import java.text.DateFormat - - -@OptIn(ExperimentalMaterial3Api::class) -@Composable -fun LogsTab( - context: RemoteSideContext, - activityLauncherHelper: ActivityLauncherHelper, - deleteAction: (() -> Unit) -> Unit, - exportAction: (() -> Unit) -> Unit, - bottomPadding: Dp, -) { - val translation = remember { context.translation.getCategory("manager.friend_tracker") } - val coroutineScope = rememberCoroutineScope() - - val logs = remember { mutableStateListOf() } - var isLoading by remember { mutableStateOf(false) } - var pageIndex by remember { mutableIntStateOf(0) } - var filterType by remember { mutableStateOf(FriendTrackerManagerRoot.FilterType.USERNAME) } - var reverseSortOrder by remember { mutableStateOf(true) } - val sinceDatePickerState = rememberDatePickerState( - initialDisplayMode = DisplayMode.Picker - ) - - var filter by remember { mutableStateOf("") } - var searchTimeoutJob by remember { mutableStateOf(null) } - - fun getPaginatedLogs(pageIndex: Int) = context.messageLogger.getLogs( - pageIndex = pageIndex, - pageSize = 30, - timestamp = sinceDatePickerState.selectedDateMillis, - reverseOrder = reverseSortOrder, - filter = { - when (filterType) { - FriendTrackerManagerRoot.FilterType.USERNAME -> it.username.contains(filter, ignoreCase = true) - FriendTrackerManagerRoot.FilterType.CONVERSATION -> it.conversationTitle?.contains(filter, ignoreCase = true) == true || (it.username == filter && !it.isGroup) - FriendTrackerManagerRoot.FilterType.EVENT -> it.eventType.contains(filter, ignoreCase = true) - } - }) - - suspend fun loadNewLogs() { - withContext(Dispatchers.IO) { - getPaginatedLogs(pageIndex).let { - withContext(Dispatchers.Main) { - logs.addAll(it) - pageIndex += 1 - } - } - } - } - - suspend fun resetAndLoadLogs() { - isLoading = true - logs.clear() - pageIndex = 0 - loadNewLogs() - isLoading = false - } - - var showDeleteDialog by remember { mutableStateOf(false) } - var showExportSelectionDialog by remember { mutableStateOf(false) } - - LaunchedEffect(Unit) { - deleteAction { showDeleteDialog = true } - exportAction { showExportSelectionDialog = true } - } - - if (showDeleteDialog) { - val deleteCoroutineScope = rememberCoroutineScope { Dispatchers.IO } - var deleteLogsTask by remember { mutableStateOf(null) } - var deletedLogsCount by remember { mutableIntStateOf(0) } - - fun deleteLogs() { - deleteLogsTask = deleteCoroutineScope.launch { - var index = 0 - while (true) { - val newLogs = getPaginatedLogs(index++) - if (newLogs.isEmpty()) { - break - } - newLogs.forEach { - context.messageLogger.deleteTrackerLog(it.id) - deletedLogsCount++ - } - } - - withContext(Dispatchers.Main) { - delay(500) - resetAndLoadLogs() - context.shortToast(translation.format("deleted_logs_toast", "count" to deletedLogsCount.toString())) - showDeleteDialog = false - } - } - } - - DisposableEffect(Unit) { - onDispose { - deleteLogsTask?.cancel() - } - } - - AlertDialog( - onDismissRequest = { showDeleteDialog = false }, - title = { Text(translation["delete_logs_dialog_title"]) }, - text = { - if (deleteLogsTask != null) { - Text(translation.format("deleting_logs_dialog_text", "count" to deletedLogsCount.toString())) - } else { - Text(translation["delete_logs_dialog_confirm_text"]) - } - }, - confirmButton = { - Button( - enabled = deleteLogsTask == null, - onClick = { - deleteLogs() - } - ) { - if (deleteLogsTask != null) { - CircularProgressIndicator(modifier = Modifier - .size(30.dp), - strokeWidth = 3.dp - ) - } else { - Text(translation["delete_button"]) - } - } - }, - dismissButton = { - Button(onClick = { showDeleteDialog = false }) { - Text(context.translation["button.cancel"]) - } - } - ) - } - - if (showExportSelectionDialog) { - val exportCoroutineScope = rememberCoroutineScope { Dispatchers.IO } - var exportTask by remember { mutableStateOf(null) } - var exportType by remember { mutableStateOf("json") } - - fun exportLogs() { - activityLauncherHelper.saveFile("tracker_logs_${System.currentTimeMillis()}.$exportType") { uri -> - exportTask = exportCoroutineScope.launch { - context.androidContext.contentResolver.openOutputStream(Uri.parse(uri))?.use { - val writer = it.writer() - val jsonWriter by lazy { - JsonWriter(writer).apply { - setIndent(" ") - beginArray() - } - } - - var index = 0 - while (true) { - val newLogs = getPaginatedLogs(index++) - if (newLogs.isEmpty()) { - break - } - newLogs.forEach { log -> - when (exportType) { - "json" -> { - jsonWriter.jsonValue(log.toJson().toString()) - } - "csv" -> { - writer.write(log.toCsv()) - writer.write("\n") - } - } - writer.flush() - } - } - when (exportType) { - "json" -> { - jsonWriter.endArray() - jsonWriter.close() - } - "csv" -> writer.close() - } - } - }.apply { - invokeOnCompletion { - exportTask = null - showExportSelectionDialog = false - if (it == null) { - context.shortToast(translation["exported_logs_toast"]) - } else { - context.log.error("Failed to export logs", it) - context.shortToast(translation["export_logs_failed_toast"]) - } - } - } - } - } - - AlertDialog( - onDismissRequest = { showExportSelectionDialog = false }, - title = { Text(translation["export_logs_dialog_title"]) }, - text = { - Column( - modifier = Modifier.fillMaxWidth(), - horizontalAlignment = Alignment.CenterHorizontally, - ) { - if (exportTask != null) { - Text(translation["exporting_logs_dialog_text"]) - } else { - Text(translation["export_logs_dialog_confirm_text"]) - Spacer(modifier = Modifier.height(10.dp)) - var expanded by remember { mutableStateOf(false) } - ExposedDropdownMenuBox( - expanded = expanded, - onExpandedChange = { expanded = it }, - ) { - Card( - modifier = Modifier - .menuAnchor(MenuAnchorType.PrimaryNotEditable) - .padding(2.dp) - ) { - Text(translation.format("export_as_button", "type" to exportType), modifier = Modifier.padding(8.dp)) - } - DropdownMenu(expanded = expanded, onDismissRequest = { - expanded = false - }) { - listOf("json", "csv").forEach { type -> - DropdownMenuItem(onClick = { - exportType = type - expanded = false - }, text = { - Text(type) - }) - } - } - } - } - } - }, - confirmButton = { - Button( - enabled = exportTask == null, - onClick = { - exportLogs() - } - ) { - if (exportTask != null) { - CircularProgressIndicator(modifier = Modifier - .size(30.dp), - strokeWidth = 3.dp - ) - } else { - Text(translation["export_button"]) - } - } - }, - dismissButton = { - Button(onClick = { showExportSelectionDialog = false }) { - Text(context.translation["button.cancel"]) - } - } - ) - } - - - @Composable - fun FilterSelection( - selectionExpanded: MutableState - ) { - var dropDownExpanded by remember { mutableStateOf(false) } - var showDatePicker by remember { mutableStateOf(false) } - - if (showDatePicker) { - DatePickerDialog(onDismissRequest = { - showDatePicker = false - }, confirmButton = {}) { - DatePicker( - state = sinceDatePickerState, - modifier = Modifier.weight(1f), - ) - Row( - modifier = Modifier - .fillMaxWidth() - .padding(8.dp), - horizontalArrangement = Arrangement.SpaceEvenly - ) { - Button(onClick = { - showDatePicker = false - sinceDatePickerState.selectedDateMillis = null - }) { - Text(context.translation["button.cancel"]) - } - Button(onClick = { - showDatePicker = false - }) { - Text(context.translation["button.ok"]) - } - } - } - } - - DropdownMenu(expanded = selectionExpanded.value, onDismissRequest = { - selectionExpanded.value = false - }) { - Column( - modifier = Modifier - .padding(16.dp), - verticalArrangement = Arrangement.spacedBy(4.dp), - ) { - val rowHSpacing = 10.dp - - Text(translation["filters_title"], fontWeight = FontWeight.Bold, fontSize = 20.sp) - Row( - horizontalArrangement = Arrangement.spacedBy(rowHSpacing), - verticalAlignment = Alignment.CenterVertically, - ) { - Text(translation["search_by_label"]) - ExposedDropdownMenuBox( - expanded = dropDownExpanded, - onExpandedChange = { dropDownExpanded = it }, - ) { - Card( - modifier = Modifier - .menuAnchor(MenuAnchorType.PrimaryNotEditable) - .padding(2.dp) - ) { - Text(filterType.name, modifier = Modifier.padding(8.dp)) - } - DropdownMenu(expanded = dropDownExpanded, onDismissRequest = { - dropDownExpanded = false - }) { - FriendTrackerManagerRoot.FilterType.entries.forEach { type -> - DropdownMenuItem(onClick = { - filter = "" - filterType = type - dropDownExpanded = false - coroutineScope.launch { - resetAndLoadLogs() - } - }, text = { - Text(type.name) - }) - } - } - } - } - Row( - horizontalArrangement = Arrangement.spacedBy(rowHSpacing), - verticalAlignment = Alignment.CenterVertically, - ) { - Text(translation["newest_first_label"]) - Switch( - checked = reverseSortOrder, - onCheckedChange = { - reverseSortOrder = it - selectionExpanded.value = false - } - ) - } - Row( - horizontalArrangement = Arrangement.spacedBy(rowHSpacing), - verticalAlignment = Alignment.CenterVertically, - ) { - Text(translation[if (reverseSortOrder) "since_label" else "until_label"]) - Button(onClick = { - showDatePicker = true - }) { - Text(remember(showDatePicker) { - sinceDatePickerState.selectedDateMillis?.let { - DateFormat.getDateInstance().format(it) - } ?: translation["pick_a_date_button"] - }) - } - } - } - } - } - - Column( - modifier = Modifier.fillMaxSize() - ) { - Row( - modifier = Modifier.fillMaxWidth(), - verticalAlignment = Alignment.CenterVertically, - ) { - var showAutoComplete by remember { mutableStateOf(false) } - val showFilterSelection = remember { mutableStateOf(false) } - - ExposedDropdownMenuBox( - expanded = showAutoComplete, - onExpandedChange = { showAutoComplete = it }, - ) { - TextField( - value = filter, - modifier = Modifier - .fillMaxWidth() - .menuAnchor(MenuAnchorType.PrimaryNotEditable) - .padding(8.dp), - onValueChange = { - filter = it - coroutineScope.launch { - searchTimeoutJob?.cancel() - searchTimeoutJob = coroutineScope.launch { - delay(200) - showAutoComplete = true - resetAndLoadLogs() - } - } - }, - placeholder = { Text(translation["search_placeholder"]) }, - colors = TextFieldDefaults.colors( - focusedContainerColor = Color.Transparent, - unfocusedContainerColor = Color.Transparent - ), - maxLines = 1, - leadingIcon = { - IconButton( - onClick = { - showFilterSelection.value = !showFilterSelection.value - }, - modifier = Modifier - .padding(2.dp) - ) { - Icon(Icons.Default.FilterList, contentDescription = translation["filter_button_description"]) - } - FilterSelection(showFilterSelection) - if (showFilterSelection.value) { - DisposableEffect(Unit) { - onDispose { - coroutineScope.launch { - resetAndLoadLogs() - } - } - } - } - }, - trailingIcon = { - if (filter != "") { - IconButton(onClick = { - filter = "" - coroutineScope.launch { - resetAndLoadLogs() - } - }) { - Icon(Icons.Default.Clear, contentDescription = translation["clear_button_description"]) - } - } - - DropdownMenu( - expanded = showAutoComplete, - onDismissRequest = { - showAutoComplete = false - }, - properties = PopupProperties(focusable = false), - ) { - val suggestedEntries = remember(filter) { - mutableStateListOf() - } - - LaunchedEffect(filter) { - launch(Dispatchers.IO) { - suggestedEntries.addAll(when (filterType) { - FriendTrackerManagerRoot.FilterType.USERNAME -> context.messageLogger.findUsername(filter) - FriendTrackerManagerRoot.FilterType.CONVERSATION -> context.messageLogger.findConversation(filter) + context.messageLogger.findUsername(filter) - FriendTrackerManagerRoot.FilterType.EVENT -> TrackerEventType.entries.filter { it.name.contains(filter, ignoreCase = true) }.map { it.key } - }.take(5)) - } - } - - suggestedEntries.forEach { entry -> - DropdownMenuItem(onClick = { - filter = entry - coroutineScope.launch { - resetAndLoadLogs() - } - showAutoComplete = false - }, text = { - Text(entry) - }) - } - } - }, - ) - } - } - - LazyColumn( - modifier = Modifier.weight(1f), - contentPadding = PaddingValues(bottom = bottomPadding) - ) { - item { - Row( - modifier = Modifier - .fillMaxWidth(), - horizontalArrangement = Arrangement.Center - ) { - if (logs.isEmpty() && !isLoading) { - Text(translation["no_logs_found"], modifier = Modifier.padding(16.dp), fontWeight = FontWeight.Light, textAlign = TextAlign.Center) - } - } - } - items(logs, key = { it.userId + it.id }) { log -> - var databaseFriend by remember { mutableStateOf(null) } - LaunchedEffect(Unit) { - launch(Dispatchers.IO) { - databaseFriend = context.database.getFriendInfo(log.userId) - } - } - ElevatedCard( - modifier = Modifier - .fillMaxWidth() - .padding(3.dp) - ) { - Row( - modifier = Modifier - .fillMaxWidth() - .padding(4.dp), - verticalAlignment = Alignment.CenterVertically - ) { - - BitmojiImage( - modifier = Modifier.padding(5.dp), - size = 55, - context = context, - url = databaseFriend?.takeIf { it.bitmojiId != null }?.let { - BitmojiSelfie.getBitmojiSelfie(it.selfieId, it.bitmojiId, BitmojiSelfie.BitmojiSelfieType.NEW_THREE_D) - }, - ) - - Column( - modifier = Modifier - .weight(1f), - ) { - Text(databaseFriend?.displayName?.let { - "$it (${log.username})" - } ?: log.username, lineHeight = 20.sp, fontWeight = FontWeight.Bold, maxLines = 1, overflow = TextOverflow.Ellipsis, fontSize = 14.sp) - Text(translation.format("log_event_format", "event" to log.eventType, "conversation" to log.conversationTitle.toString()), fontSize = 10.sp, fontWeight = FontWeight.Light, lineHeight = 15.sp, maxLines = 1, overflow = TextOverflow.Ellipsis) - Text( - DateFormat.getDateTimeInstance().format(log.timestamp), - fontSize = 10.sp, - fontWeight = FontWeight.Light, - lineHeight = 15.sp, - ) - } - - IconButton( - onClick = { - context.messageLogger.deleteTrackerLog(log.id) - logs.remove(log) - } - ) { - Icon(Icons.Default.DeleteOutline, contentDescription = translation["delete_button_description"]) - } - } - } - } - item { - Spacer(modifier = Modifier.height(16.dp)) - - LaunchedEffect(pageIndex) { - loadNewLogs() - } - } - - } - } -} \ No newline at end of file diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/tracker/ManageFriendTrackerReposSection.kt b/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/tracker/ManageFriendTrackerReposSection.kt deleted file mode 100644 index 7b968632..00000000 --- a/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/tracker/ManageFriendTrackerReposSection.kt +++ /dev/null @@ -1,239 +0,0 @@ -package me.rhunk.snapenhance.ui.manager.pages.tracker - -import androidx.compose.ui.Alignment -import androidx.compose.foundation.layout.* -import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.items -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.Public -import androidx.compose.material3.* -import androidx.compose.runtime.* -import androidx.compose.ui.Modifier -import androidx.compose.ui.focus.FocusRequester -import androidx.compose.ui.focus.focusRequester -import androidx.compose.ui.layout.onGloballyPositioned -import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.text.style.TextAlign -import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp -import androidx.compose.animation.AnimatedVisibility -import androidx.compose.material.icons.filled.Error -import androidx.core.net.toUri -import com.google.gson.JsonParser -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.launch -import kotlinx.coroutines.runBlocking -import me.rhunk.snapenhance.common.util.ktx.getUrlFromClipboard -import me.rhunk.snapenhance.storage.addRepo -import me.rhunk.snapenhance.storage.getRepositories -import me.rhunk.snapenhance.storage.removeRepo -import me.rhunk.snapenhance.ui.manager.Routes -import me.rhunk.snapenhance.ui.manager.components.AestheticDialog -import okhttp3.OkHttpClient - -class ManageFriendTrackerReposSection: Routes.Route() { - override val translation by lazy { context.translation.getCategory("manager.friend_tracker_repos") } - private val refreshTrigger = mutableStateOf(0) - private val okHttpClient by lazy { OkHttpClient() } - - override val floatingActionButton: @Composable () -> Unit = { - var showAddDialog by remember { mutableStateOf(false) } - var showErrorDialog by remember { mutableStateOf(false) } - var errorDialogMessage by remember { mutableStateOf("") } - - if (showErrorDialog) { - AestheticDialog( - onDismissRequest = { showErrorDialog = false }, - title = translation["invalid_repo_title"], - text = errorDialogMessage, - icon = Icons.Default.Error, - confirmButtonText = translation["button.ok"], - onConfirm = { showErrorDialog = false } - ) - } - - ExtendedFloatingActionButton(onClick = { showAddDialog = true }) { - Text(translation["add_repo_button"]) - } - - if (showAddDialog) { - val coroutineScope = rememberCoroutineScope { Dispatchers.IO } - - var url by remember { mutableStateOf("") } - var loading by remember { mutableStateOf(false) } - - AlertDialog( - onDismissRequest = { showAddDialog = false }, - title = { Text(translation["add_repo_dialog_title"]) }, - text = { - val focusRequester = remember { FocusRequester() } - OutlinedTextField( - modifier = Modifier - .fillMaxWidth() - .focusRequester(focusRequester) - .onGloballyPositioned { focusRequester.requestFocus() }, - value = url, - onValueChange = { url = it }, - label = { Text(translation["repo_url_label"]) } - ) - LaunchedEffect(Unit) { - context.androidContext.getUrlFromClipboard()?.let { url = it } - } - }, - confirmButton = { - Button( - enabled = !loading && url.isNotBlank(), - onClick = { - loading = true - coroutineScope.launch { - runCatching { - var modifiedUrl = url - if (url.startsWith("https://github.com/")) { - val splitUrl = modifiedUrl.removePrefix("https://github.com/").split("/") - val repoName = splitUrl[0] + "/" + splitUrl[1] - okHttpClient.newCall( - okhttp3.Request.Builder().url("https://api.github.com/repos/$repoName").build() - ).execute().use { response -> - if (!response.isSuccessful) { - throw Exception("Failed to fetch default branch: ${response.code}") - } - val json = response.body?.string() ?: throw Exception("Empty response") - val defaultBranch = Regex("\"default_branch\":\"([^\"]+)\"").find(json)?.groupValues?.get(1) - ?: throw Exception("No default_branch field") - modifiedUrl = "https://raw.githubusercontent.com/$repoName/$defaultBranch/" - } - } - - val indexUrl = modifiedUrl.toUri().buildUpon().appendPath("index.json").build().toString() - val request = okhttp3.Request.Builder().url(indexUrl).build() - val isValid = okHttpClient.newCall(request).execute().use { response -> - if (!response.isSuccessful) throw Exception("Failed to fetch index.json: ${response.code}") - val indexJson = response.body?.string() ?: throw Exception("Empty index.json") - JsonParser.parseString(indexJson).asJsonObject.has("rules") - } - - if (isValid) { - context.database.addRepo("friend_tracker", modifiedUrl) - context.shortToast(translation["repo_added_toast"]) - showAddDialog = false - refreshTrigger.value++ - } else { - errorDialogMessage = translation["invalid_repo_error"] - showErrorDialog = true - } - }.onFailure { - context.log.error("Failed to add repository", it) - context.shortToast(translation.format("add_repo_failed_toast", "message" to (it.message ?: "Unknown"))) - } - loading = false - } - } - ) { - if (loading) { - CircularProgressIndicator(modifier = Modifier.size(24.dp)) - } else { - Text(translation["add_button"]) - } - } - } - ) - } - } - - override val content: @Composable (androidx.navigation.NavBackStackEntry) -> Unit = { - val repositories by remember(refreshTrigger.value) { - mutableStateOf>(runBlocking { context.database.getRepositories("friend_tracker") }) - } - - if (repositories.isEmpty()) { - Box( - modifier = Modifier.fillMaxSize(), - contentAlignment = Alignment.Center - ) { - Text( - text = translation["no_repos_added"], - style = MaterialTheme.typography.headlineSmall, - fontWeight = FontWeight.Bold, - textAlign = TextAlign.Center, - color = MaterialTheme.colorScheme.onSurface - ) - } - } else { - LazyColumn( - modifier = Modifier.fillMaxSize(), - contentPadding = PaddingValues(start = 8.dp, top = 8.dp, end = 8.dp, bottom = 8.dp + routes.bottomPadding), - ) { - items(repositories) { url -> - val (repoName, author) = remember(url) { - url.removePrefix("https://raw.githubusercontent.com/").split("/").let { it[1] to it[0] } - } - - ElevatedCard( - modifier = Modifier.padding(bottom = 8.dp) - ) { - Row( - modifier = Modifier - .fillMaxWidth() - .padding(12.dp), - horizontalArrangement = Arrangement.spacedBy(8.dp), - verticalAlignment = Alignment.CenterVertically - ) { - Icon( - Icons.Default.Public, - contentDescription = null, - modifier = Modifier.size(40.dp), - tint = MaterialTheme.colorScheme.primary - ) - Column( - modifier = Modifier.weight(1f), - verticalArrangement = Arrangement.spacedBy(2.dp) - ) { - Text( - text = repoName, - fontWeight = FontWeight.SemiBold, - fontSize = 16.sp - ) - Text( - text = author, - fontSize = 14.sp, - color = MaterialTheme.colorScheme.onSurfaceVariant - ) - } - var showRemoveDialog by remember { mutableStateOf(false) } - - Button( - onClick = { showRemoveDialog = true } - ) { - Text(translation["remove_button"]) - } - - AnimatedVisibility(visible = showRemoveDialog) { - AlertDialog( - onDismissRequest = { showRemoveDialog = false }, - title = { Text(translation["remove_repo_dialog_title"]) }, - text = { Text(translation["remove_repo_dialog_text"]) }, - confirmButton = { - Button( - onClick = { - context.database.removeRepo("friend_tracker", url) - showRemoveDialog = false - refreshTrigger.value++ - } - ) { - Text(translation["remove_button"]) - } - }, - dismissButton = { - Button(onClick = { showRemoveDialog = false }) { - Text(translation["button.cancel"]) - } - } - ) - } - } - } - } - } - } - } -} diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/ui/setup/SetupActivity.kt b/app/src/main/kotlin/me/rhunk/snapenhance/ui/setup/SetupActivity.kt deleted file mode 100644 index 9e84a267..00000000 --- a/app/src/main/kotlin/me/rhunk/snapenhance/ui/setup/SetupActivity.kt +++ /dev/null @@ -1,192 +0,0 @@ -@file:OptIn(androidx.compose.animation.ExperimentalAnimationApi::class) - -package me.rhunk.snapenhance.ui.setup - -import android.app.Activity -import android.os.Bundle -import androidx.activity.ComponentActivity -import androidx.activity.compose.BackHandler -import androidx.activity.compose.setContent -import androidx.compose.animation.core.animateFloatAsState -import androidx.compose.foundation.background -import androidx.compose.foundation.layout.* -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.automirrored.filled.ArrowForwardIos -import androidx.compose.material.icons.filled.Check -import androidx.compose.material3.FilledIconButton -import androidx.compose.material3.Icon -import androidx.compose.material3.MaterialTheme -import androidx.compose.runtime.SideEffect -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember -import androidx.compose.runtime.setValue -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.alpha -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.graphics.luminance -import androidx.compose.ui.graphics.toArgb -import androidx.compose.ui.platform.LocalView -import androidx.compose.ui.unit.dp -import androidx.core.view.WindowCompat -import androidx.core.view.WindowInsetsControllerCompat -import androidx.compose.foundation.layout.WindowInsets -import androidx.compose.foundation.layout.asPaddingValues -import androidx.compose.foundation.layout.navigationBars -import androidx.navigation.compose.NavHost -import androidx.navigation.compose.composable -import androidx.navigation.compose.rememberNavController -import androidx.compose.animation.slideInHorizontally -import androidx.compose.animation.slideOutHorizontally -import androidx.compose.animation.fadeIn -import androidx.compose.animation.fadeOut -import me.rhunk.snapenhance.ui.util.scaleOnPress -import me.rhunk.snapenhance.SharedContextHolder -import me.rhunk.snapenhance.common.ui.AppMaterialTheme -import me.rhunk.snapenhance.ui.setup.screens.SetupScreen -import me.rhunk.snapenhance.ui.setup.screens.impl.MappingsScreen -import me.rhunk.snapenhance.ui.setup.screens.impl.PermissionsScreen -import me.rhunk.snapenhance.ui.setup.screens.impl.PickLanguageScreen -import me.rhunk.snapenhance.ui.setup.screens.impl.SaveFolderScreen - -class SetupActivity : ComponentActivity() { - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - val setupContext = SharedContextHolder.remote(this).apply { - activity = this@SetupActivity - } - fun endActivity() { - setupContext.reload() - finish() - } - val requirements = intent.getIntExtra("requirements", Requirements.FIRST_RUN) - fun hasRequirement(requirement: Int) = requirements and requirement == requirement - val requiredScreens = mutableListOf() - with(requiredScreens) { - val isFirstRun = hasRequirement(Requirements.FIRST_RUN) - if (isFirstRun || hasRequirement(Requirements.LANGUAGE)) { - add(PickLanguageScreen().apply { route = "language" }) - } - if (isFirstRun || hasRequirement(Requirements.GRANT_PERMISSIONS)) { - add(PermissionsScreen().apply { route = "permissions" }) - } - if (isFirstRun || hasRequirement(Requirements.SAVE_FOLDER)) { - add(SaveFolderScreen().apply { route = "saveFolder" }) - } - if (isFirstRun || hasRequirement(Requirements.MAPPINGS)) { - add(MappingsScreen().apply { route = "mappings" }) - } - } - - if (requiredScreens.isEmpty()) { - endActivity() - return - } - requiredScreens.forEach { screen -> - screen.context = setupContext - screen.init() - } - setContent { - val navController = rememberNavController() - var canGoNext by remember { mutableStateOf(false) } - fun nextScreen() { - if (!canGoNext) return - requiredScreens.firstOrNull()?.onLeave() - if (requiredScreens.size > 1) { - canGoNext = false - requiredScreens.removeAt(0) - navController.navigate(requiredScreens.first().route) - } else { - endActivity() - } - } - AppMaterialTheme { - val background = MaterialTheme.colorScheme.background - val isLight = background.luminance() > 0.5f - val view = LocalView.current - @Suppress("DEPRECATION") - SideEffect { - val window = (view.context as Activity).window - WindowCompat.setDecorFitsSystemWindows(window, false) - // Set transparent system bars and light/dark icons - window.statusBarColor = Color.Transparent.toArgb() - window.navigationBarColor = Color.Transparent.toArgb() - val insetsController = WindowInsetsControllerCompat(window, window.decorView) - insetsController.isAppearanceLightStatusBars = isLight - insetsController.isAppearanceLightNavigationBars = isLight - } - Box( - modifier = Modifier - .fillMaxSize() - .background(background) - ) { - val bottomPadding = 110.dp + - WindowInsets.navigationBars.asPaddingValues().calculateBottomPadding() - Column( - modifier = Modifier - .fillMaxSize() - .padding(bottom = bottomPadding) - ) { - NavHost( - navController = navController, - startDestination = requiredScreens.first().route, - enterTransition = { fadeIn() }, - exitTransition = { fadeOut() }, - popEnterTransition = { fadeIn() }, - popExitTransition = { fadeOut() } - ) { - requiredScreens.forEach { screen -> - screen.allowNext = { canGoNext = it } - screen.goNext = { - canGoNext = true - nextScreen() - } - composable( - screen.route, - enterTransition = { slideInHorizontally { it } }, - exitTransition = { slideOutHorizontally { -it } }, - popEnterTransition = { slideInHorizontally { -it } }, - popExitTransition = { slideOutHorizontally { it } } - ) { - BackHandler(true) {} - Column( - modifier = Modifier.fillMaxSize(), - verticalArrangement = Arrangement.Center, - horizontalAlignment = Alignment.CenterHorizontally - ) { - screen.Content() - } - } - } - } - } - val alpha: Float by animateFloatAsState(if (canGoNext) 1f else 0f, - label = "NextButton" - ) - val nextSrc = remember { androidx.compose.foundation.interaction.MutableInteractionSource() } - FilledIconButton( - onClick = { nextScreen() }, - modifier = Modifier - .align(Alignment.BottomCenter) - .navigationBarsPadding() - .padding(bottom = 50.dp) - .size(60.dp) - .alpha(alpha) - .scaleOnPress(nextSrc), - interactionSource = nextSrc - ) { - Icon( - imageVector = if (requiredScreens.size <= 1 && canGoNext) { - Icons.Default.Check - } else { - Icons.AutoMirrored.Filled.ArrowForwardIos - }, - contentDescription = null - ) - } - } - } - } - } -} diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/ui/setup/screens/SetupScreen.kt b/app/src/main/kotlin/me/rhunk/snapenhance/ui/setup/screens/SetupScreen.kt deleted file mode 100644 index ec93045c..00000000 --- a/app/src/main/kotlin/me/rhunk/snapenhance/ui/setup/screens/SetupScreen.kt +++ /dev/null @@ -1,35 +0,0 @@ -package me.rhunk.snapenhance.ui.setup.screens - -import androidx.compose.foundation.layout.padding -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp -import me.rhunk.snapenhance.RemoteSideContext - -abstract class SetupScreen { - lateinit var context: RemoteSideContext - lateinit var allowNext: (canGoNext: Boolean) -> Unit - lateinit var goNext: () -> Unit - lateinit var route: String - - @Composable - fun DialogText(text: String, modifier: Modifier = Modifier) { - Text( - text = text, - fontSize = 16.sp, - fontWeight = FontWeight.Normal, - color = MaterialTheme.colorScheme.onSurface, - modifier = Modifier.padding(16.dp).then(modifier) - ) - } - - open fun init() {} - open fun onLeave() {} - - @Composable - abstract fun Content() -} diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/ui/setup/screens/impl/PermissionsScreen.kt b/app/src/main/kotlin/me/rhunk/snapenhance/ui/setup/screens/impl/PermissionsScreen.kt deleted file mode 100644 index b16c6f37..00000000 --- a/app/src/main/kotlin/me/rhunk/snapenhance/ui/setup/screens/impl/PermissionsScreen.kt +++ /dev/null @@ -1,201 +0,0 @@ -package me.rhunk.snapenhance.ui.setup.screens.impl - -import android.Manifest -import android.annotation.SuppressLint -import android.app.Activity -import android.content.Context -import android.content.Intent -import android.content.pm.PackageManager -import android.net.Uri -import android.os.Build -import android.os.PowerManager -import android.provider.Settings -import androidx.compose.foundation.layout.* -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.Check -import androidx.compose.material3.Button -import androidx.compose.material3.Icon -import androidx.compose.material3.OutlinedCard -import androidx.compose.material3.Text -import androidx.compose.runtime.* -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.unit.dp -import androidx.lifecycle.Lifecycle -import androidx.compose.animation.AnimatedContent -import androidx.compose.animation.fadeIn -import androidx.compose.animation.fadeOut -import androidx.compose.animation.togetherWith -import androidx.compose.animation.core.tween -import androidx.compose.foundation.interaction.MutableInteractionSource -import me.rhunk.snapenhance.ui.util.scaleOnPress -import me.rhunk.snapenhance.ui.util.Motion -import kotlinx.coroutines.delay -import kotlinx.coroutines.launch -import me.rhunk.snapenhance.ui.setup.screens.SetupScreen -import me.rhunk.snapenhance.ui.util.ActivityLauncherHelper -import me.rhunk.snapenhance.ui.util.OnLifecycleEvent - -data class PermissionData( - val translationKey: String, - val isPermissionGranted: () -> Boolean, - val requestPermission: (PermissionData) -> Unit, -) - -class PermissionsScreen : SetupScreen() { - private lateinit var activityLauncherHelper: ActivityLauncherHelper - - override fun init() { - activityLauncherHelper = ActivityLauncherHelper(context.activity!!) - } - - @Composable - private fun RequestButton(onClick: () -> Unit) { - val src = remember { MutableInteractionSource() } - Button(onClick = onClick, interactionSource = src, modifier = Modifier.scaleOnPress(src)) { - Text(text = context.translation["setup.permissions.request_button"]) - } - } - - @Composable - private fun GrantedIcon() { - Icon( - imageVector = Icons.Filled.Check, - contentDescription = null, - modifier = Modifier - .size(24.dp) - .padding(5.dp) - ) - } - - @SuppressLint("BatteryLife") - @Composable - override fun Content() { - val coroutineScope = rememberCoroutineScope() - val grantedPermissions = remember { - mutableStateMapOf() - } - val permissions = remember { - listOf( - PermissionData( - translationKey = "notification_access", - isPermissionGranted = { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { - context.androidContext.checkSelfPermission(Manifest.permission.POST_NOTIFICATIONS) == PackageManager.PERMISSION_GRANTED - } else { - true - } - }, - requestPermission = { perm -> - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { - activityLauncherHelper.requestPermission(Manifest.permission.POST_NOTIFICATIONS) { resultCode, _ -> - coroutineScope.launch { - grantedPermissions[perm.translationKey] = resultCode == Activity.RESULT_OK - } - } - } - } - ), - PermissionData( - translationKey = "battery_optimization", - isPermissionGranted = { - val powerManager = - context.androidContext.getSystemService(Context.POWER_SERVICE) as PowerManager - powerManager.isIgnoringBatteryOptimizations(context.androidContext.packageName) - }, - requestPermission = { perm -> - activityLauncherHelper.launch(Intent().apply { - action = Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS - data = Uri.parse("package:${context.androidContext.packageName}") - }) { resultCode, _ -> - coroutineScope.launch { - grantedPermissions[perm.translationKey] = resultCode == 0 - } - } - } - ), - PermissionData( - translationKey = "display_over_other_apps", - isPermissionGranted = { - Settings.canDrawOverlays(context.androidContext) - }, - requestPermission = { perm -> - activityLauncherHelper.launch(Intent().apply { - action = Settings.ACTION_MANAGE_OVERLAY_PERMISSION - data = Uri.parse("package:${context.androidContext.packageName}") - }) { resultCode, _ -> - coroutineScope.launch { - grantedPermissions[perm.translationKey] = resultCode == 0 - } - } - } - ) - ) - } - - fun updateState() { - permissions.forEach { perm -> - grantedPermissions[perm.translationKey] = perm.isPermissionGranted() - } - if (permissions.all { perm -> grantedPermissions[perm.translationKey] == true }) { - goNext() - } - } - - OnLifecycleEvent { _, event -> - if (event != Lifecycle.Event.ON_RESUME) return@OnLifecycleEvent - coroutineScope.launch { - updateState() - delay(1000) - updateState() - } - } - - LaunchedEffect(Unit) { - updateState() - } - - DialogText(text = context.translation["setup.permissions.dialog"]) - - OutlinedCard( - modifier = Modifier - .fillMaxWidth(), - ) { - Column( - verticalArrangement = Arrangement.spacedBy(16.dp), - modifier = Modifier - .padding(all = 16.dp), - ) { - permissions.forEach { perm -> - Row( - verticalAlignment = Alignment.CenterVertically, - ) { - DialogText( - text = context.translation["setup.permissions.${perm.translationKey}"], - modifier = Modifier.weight(1f) - ) - val granted = grantedPermissions[perm.translationKey] == true - AnimatedContent( - targetState = granted, - transitionSpec = { - fadeIn(animationSpec = tween(150)) togetherWith fadeOut(animationSpec = tween(150)) - }, label = "permState" - ) { isGranted -> - if (isGranted) { - GrantedIcon() - } else { - RequestButton { - if (perm.isPermissionGranted()) { - grantedPermissions[perm.translationKey] = true - } else { - perm.requestPermission(perm) - } - } - } - } - } - } - } - } - } -} diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/ui/setup/screens/impl/PickLanguageScreen.kt b/app/src/main/kotlin/me/rhunk/snapenhance/ui/setup/screens/impl/PickLanguageScreen.kt deleted file mode 100644 index 3042b353..00000000 --- a/app/src/main/kotlin/me/rhunk/snapenhance/ui/setup/screens/impl/PickLanguageScreen.kt +++ /dev/null @@ -1,148 +0,0 @@ -package me.rhunk.snapenhance.ui.setup.screens.impl - -import androidx.compose.animation.AnimatedVisibility -import androidx.compose.animation.fadeIn -import androidx.compose.animation.fadeOut -import androidx.compose.animation.scaleIn -import androidx.compose.animation.scaleOut -import androidx.compose.foundation.clickable -import androidx.compose.foundation.gestures.Orientation -import androidx.compose.foundation.gestures.scrollable -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.items -import androidx.compose.foundation.rememberScrollState -import androidx.compose.material3.Button -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Surface -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember -import androidx.compose.runtime.setValue -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp -import androidx.compose.ui.window.Dialog -import me.rhunk.snapenhance.common.bridge.wrapper.LocaleWrapper -import me.rhunk.snapenhance.ui.setup.screens.SetupScreen -import me.rhunk.snapenhance.ui.util.ObservableMutableState -import me.rhunk.snapenhance.ui.util.Motion -import me.rhunk.snapenhance.ui.util.scaleOnPress -import androidx.compose.foundation.interaction.MutableInteractionSource -import java.util.Locale - -class PickLanguageScreen : SetupScreen() { - private val availableLocales by lazy { - LocaleWrapper.fetchAvailableLocales(context.androidContext) - } - private lateinit var selectedLocale: ObservableMutableState - private fun getLocaleDisplayName(locale: String): String { - val displayLocale = when (locale) { - "zh-Hans" -> Locale.forLanguageTag("zh-Hans") - "zh_TW" -> Locale.TRADITIONAL_CHINESE - else -> try { - Locale.forLanguageTag(locale.replace('_', '-')) - } catch (e: Exception) { - Locale.getDefault() - } - } - return displayLocale.getDisplayName(Locale.getDefault()) - } - private fun reloadTranslation(selectedLocale: String) { - context.translation.reload(selectedLocale, isSetup = true) - } - private fun setLocale(locale: String) { - with(context) { - config.locale = locale - config.writeConfig() - reloadTranslation(locale) - } - } - override fun onLeave() { - context.config.locale = selectedLocale.value - context.config.writeConfig() - } - override fun init() { - val deviceLocale = Locale.getDefault().toString() - selectedLocale = - ObservableMutableState( - defaultValue = availableLocales.firstOrNull { locale -> locale == deviceLocale } - ?: LocaleWrapper.DEFAULT_LOCALE - ) { _, newValue -> - setLocale(newValue) - }.also { reloadTranslation(it.value) } - } - @Composable - override fun Content() { - allowNext(true) - DialogText(text = context.translation["setup.dialogs.select_language"]) - var isDialog by remember { mutableStateOf(false) } - if (isDialog) { - var visible by remember { mutableStateOf(false) } - androidx.compose.runtime.LaunchedEffect(Unit) { visible = true } - Dialog(onDismissRequest = { isDialog = false }) { - AnimatedVisibility( - visible = visible, - enter = fadeIn(animationSpec = Motion.tweenFloatSpec(180)) + scaleIn(animationSpec = Motion.tweenFloatSpec(200)), - exit = fadeOut(animationSpec = Motion.tweenFloatSpec(150)) + scaleOut(animationSpec = Motion.tweenFloatSpec(180)) - ) { - Surface( - modifier = Modifier - .padding(10.dp) - .fillMaxWidth(), - shape = MaterialTheme.shapes.medium - ) { - LazyColumn( - modifier = Modifier.scrollable(rememberScrollState(), orientation = Orientation.Vertical) - ) { - items(availableLocales) { locale -> - Box( - modifier = Modifier - .height(70.dp) - .fillMaxWidth() - .clickable { - selectedLocale.value = locale - isDialog = false - }, - contentAlignment = Alignment.Center - ) { - Text( - text = remember(locale) { getLocaleDisplayName(locale) }, - fontSize = 16.sp, - fontWeight = FontWeight.Light, - ) - } - } - } - } - } - } - } - Box( - modifier = Modifier - .padding(top = 40.dp) - .fillMaxWidth(), - contentAlignment = Alignment.Center - ) { - val btnSrc = remember { MutableInteractionSource() } - Button( - onClick = { isDialog = true }, - interactionSource = btnSrc, - modifier = Modifier.scaleOnPress(btnSrc) - ) { - Text( - text = remember(selectedLocale.value) { getLocaleDisplayName(selectedLocale.value) }, - fontSize = 16.sp, - fontWeight = FontWeight.Normal - ) - } - } - } -} diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/ui/setup/screens/impl/SaveFolderScreen.kt b/app/src/main/kotlin/me/rhunk/snapenhance/ui/setup/screens/impl/SaveFolderScreen.kt deleted file mode 100644 index 1cadce0e..00000000 --- a/app/src/main/kotlin/me/rhunk/snapenhance/ui/setup/screens/impl/SaveFolderScreen.kt +++ /dev/null @@ -1,40 +0,0 @@ -package me.rhunk.snapenhance.ui.setup.screens.impl - -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.height -import androidx.compose.material3.Button -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.runtime.remember -import androidx.compose.ui.Modifier -import androidx.compose.ui.unit.dp -import me.rhunk.snapenhance.ui.setup.screens.SetupScreen -import me.rhunk.snapenhance.ui.util.ActivityLauncherHelper -import me.rhunk.snapenhance.ui.util.chooseFolder -import androidx.compose.foundation.interaction.MutableInteractionSource -import me.rhunk.snapenhance.ui.util.scaleOnPress - -class SaveFolderScreen : SetupScreen() { - private lateinit var activityLauncherHelper: ActivityLauncherHelper - - override fun init() { - activityLauncherHelper = ActivityLauncherHelper(context.activity!!) - } - - @Composable - override fun Content() { - DialogText(text = context.translation["setup.dialogs.save_folder"]) - Spacer(modifier = Modifier.height(16.dp)) - val src = remember { MutableInteractionSource() } - Button(onClick = { - activityLauncherHelper.chooseFolder { - if (it.isBlank()) return@chooseFolder - context.config.root.downloader.saveFolder.set(it) - context.config.writeConfig() - goNext() - } - }, interactionSource = src, modifier = Modifier.scaleOnPress(src)) { - Text(text = context.translation["setup.dialogs.select_save_folder_button"]) - } - } -} diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/ui/util/AlertDialogs.kt b/app/src/main/kotlin/me/rhunk/snapenhance/ui/util/AlertDialogs.kt deleted file mode 100644 index a15f3db7..00000000 --- a/app/src/main/kotlin/me/rhunk/snapenhance/ui/util/AlertDialogs.kt +++ /dev/null @@ -1,705 +0,0 @@ -package me.rhunk.snapenhance.ui.util - -import android.content.Context -import android.view.MotionEvent -import android.widget.Toast -import androidx.compose.foundation.ScrollState -import androidx.compose.foundation.background -import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.* -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.foundation.text.KeyboardOptions -import androidx.compose.foundation.verticalScroll -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.Check -import androidx.compose.material.icons.filled.DeleteOutline -import androidx.compose.material.icons.filled.Edit -import androidx.compose.material.icons.filled.Save -import androidx.compose.material3.* -import androidx.compose.runtime.* -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.clip -import androidx.compose.ui.draw.clipToBounds -import androidx.compose.ui.focus.FocusRequester -import androidx.compose.ui.focus.focusRequester -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.graphics.toArgb -import androidx.compose.ui.layout.onGloballyPositioned -import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.text.TextRange -import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.text.input.ImeAction -import androidx.compose.ui.text.input.KeyboardType -import androidx.compose.ui.text.input.TextFieldValue -import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp -import androidx.compose.ui.viewinterop.AndroidView -import androidx.core.net.toUri -import com.github.skydoves.colorpicker.compose.* -import com.google.gson.JsonParser -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.delay -import kotlinx.coroutines.launch -import me.rhunk.snapenhance.common.Constants -import me.rhunk.snapenhance.common.bridge.wrapper.LocaleWrapper -import me.rhunk.snapenhance.common.config.DataProcessors -import me.rhunk.snapenhance.common.config.PropertyPair -import me.rhunk.snapenhance.common.ui.AutoClearKeyboardFocus -import me.rhunk.snapenhance.common.util.ktx.await -import okhttp3.OkHttpClient -import okhttp3.Request -import org.osmdroid.config.Configuration -import org.osmdroid.tileprovider.tilesource.TileSourceFactory -import org.osmdroid.util.GeoPoint -import org.osmdroid.views.CustomZoomButtonsController -import org.osmdroid.views.MapView -import org.osmdroid.views.overlay.Marker -import org.osmdroid.views.overlay.Overlay -import java.io.File - -class AlertDialogs( - private val translation: LocaleWrapper, -) { - @Composable - fun DefaultDialogCard(modifier: Modifier = Modifier, content: @Composable ColumnScope.() -> Unit) { - Card( - shape = MaterialTheme.shapes.large, - modifier = Modifier - .padding(16.dp) - .then(modifier), - ) { - Column( - modifier = Modifier - .padding(10.dp, 10.dp, 10.dp, 10.dp) - .verticalScroll(ScrollState(0)), - ) { content() } - } - } - - @Composable - fun ConfirmDialog( - title: String, - message: String? = null, - onConfirm: () -> Unit, - onDismiss: () -> Unit, - ) { - DefaultDialogCard { - Text( - text = title, - fontSize = 20.sp, - fontWeight = FontWeight.Bold, - modifier = Modifier.padding(start = 5.dp, bottom = 10.dp) - ) - if (message != null) { - Text( - text = message, - style = MaterialTheme.typography.bodyMedium, - modifier = Modifier.padding(bottom = 15.dp) - ) - } - Row( - modifier = Modifier.fillMaxWidth(), - horizontalArrangement = Arrangement.SpaceEvenly, - ) { - Button(onClick = { onDismiss() }) { - Text(text = translation["button.cancel"]) - } - Button(onClick = { onConfirm() }) { - Text(text = translation["button.ok"]) - } - } - } - } - - @Composable - fun InfoDialog( - title: String, - message: String? = null, - onDismiss: () -> Unit, - ) { - DefaultDialogCard { - Text( - text = title, - fontSize = 20.sp, - modifier = Modifier.padding(start = 5.dp, bottom = 10.dp) - ) - if (message != null) { - Text( - text = message, - style = MaterialTheme.typography.bodySmall, - modifier = Modifier.padding(bottom = 15.dp) - ) - } - Row( - modifier = Modifier.fillMaxWidth(), - horizontalArrangement = Arrangement.SpaceEvenly, - ) { - Button(onClick = { onDismiss() }) { - Text(text = translation["button.ok"]) - } - } - } - } - - @Composable - fun TranslatedText(property: PropertyPair<*>, key: String, modifier: Modifier = Modifier) { - Text( - text = property.key.propertyOption(translation, key), - modifier = Modifier - .padding(10.dp, 10.dp, 10.dp, 10.dp) - .then(modifier) - ) - } - - @Composable - @Suppress("UNCHECKED_CAST") - fun UniqueSelectionDialog(property: PropertyPair<*>) { - val keys = (property.value.defaultValues as List).toMutableList().apply { - add(0, "null") - } - var selectedValue by remember { - mutableStateOf(property.value.getNullable()?.toString() ?: "null") - } - DefaultDialogCard { - keys.forEachIndexed { index, item -> - fun select() { - selectedValue = item - property.value.setAny(if (index == 0) { - null - } else { - item - }) - } - Row( - modifier = Modifier.clickable { select() }, - verticalAlignment = Alignment.CenterVertically - ) { - TranslatedText( - property = property, - key = item, - modifier = Modifier.weight(1f) - ) - RadioButton( - selected = selectedValue == item, - onClick = { select() } - ) - } - } - } - } - - @Composable - fun KeyboardInputDialog(property: PropertyPair<*>, dismiss: () -> Unit = {}) { - val focusRequester = remember { FocusRequester() } - val context = LocalContext.current - DefaultDialogCard { - var fieldValue by remember { - mutableStateOf(property.value.get().toString().let { - TextFieldValue( - text = it, - selection = TextRange(it.length) - ) - }) - } - TextField( - modifier = Modifier - .fillMaxWidth() - .padding(all = 10.dp) - .onGloballyPositioned { - focusRequester.requestFocus() - } - .focusRequester(focusRequester), - value = fieldValue, - onValueChange = { fieldValue = it }, - keyboardOptions = when (property.key.dataType.type) { - DataProcessors.Type.INTEGER -> KeyboardOptions(keyboardType = KeyboardType.Number) - DataProcessors.Type.FLOAT -> KeyboardOptions(keyboardType = KeyboardType.Decimal) - else -> KeyboardOptions(keyboardType = KeyboardType.Text) - }, - singleLine = true - ) - Row( - modifier = Modifier - .padding(top = 10.dp) - .fillMaxWidth(), - horizontalArrangement = Arrangement.SpaceEvenly, - ) { - Button(onClick = { dismiss() }) { - Text(text = translation["button.cancel"]) - } - Button(onClick = { - if (fieldValue.text.isNotEmpty() && property.key.params.inputCheck?.invoke(fieldValue.text) == false) { - Toast.makeText(context, translation["invalid_input_toast"], Toast.LENGTH_SHORT).show() - return@Button - } - when (property.key.dataType.type) { - DataProcessors.Type.INTEGER -> { - runCatching { - property.value.setAny(fieldValue.text.toInt()) - }.onFailure { - property.value.setAny(0) - } - } - DataProcessors.Type.FLOAT -> { - runCatching { - property.value.setAny(fieldValue.text.toFloat()) - }.onFailure { - property.value.setAny(0f) - } - } - else -> property.value.setAny(fieldValue.text) - } - dismiss() - }) { - Text(text = translation["button.ok"]) - } - } - } - } - - @Composable - fun RawInputDialog(onDismiss: () -> Unit, onConfirm: (value: String) -> Unit) { - val focusRequester = remember { FocusRequester() } - DefaultDialogCard { - val fieldValue = remember { - mutableStateOf(TextFieldValue()) - } - TextField( - modifier = Modifier - .fillMaxWidth() - .padding(all = 10.dp) - .onGloballyPositioned { - focusRequester.requestFocus() - } - .focusRequester(focusRequester), - value = fieldValue.value, - onValueChange = { - fieldValue.value = it - }, - singleLine = true - ) - Row( - modifier = Modifier - .padding(top = 10.dp) - .fillMaxWidth(), - horizontalArrangement = Arrangement.SpaceEvenly, - ) { - Button(onClick = { onDismiss() }) { - Text(text = translation["button.cancel"]) - } - Button(onClick = { - onConfirm(fieldValue.value.text) - }) { - Text(text = translation["button.ok"]) - } - } - } - } - - @Composable - @Suppress("UNCHECKED_CAST") - fun MultipleSelectionDialog(property: PropertyPair<*>) { - val defaultItems = property.value.defaultValues as List - val toggledStates = property.value.get() as MutableList - DefaultDialogCard { - defaultItems.forEach { key -> - var state by remember { mutableStateOf(toggledStates.contains(key)) } - fun toggle(value: Boolean? = null) { - state = value ?: !state - if (state) { - toggledStates.add(key) - } else { - toggledStates.remove(key) - } - } - Row( - modifier = Modifier.clickable { toggle() }, - verticalAlignment = Alignment.CenterVertically - ) { - TranslatedText( - property = property, - key = key, - modifier = Modifier - .weight(1f) - ) - Switch( - checked = state, - onCheckedChange = { - toggle(it) - } - ) - } - } - } - } - - @Composable - fun ColorPickerDialog( - initialColor: Color?, - setProperty: (Color?) -> Unit, - dismiss: () -> Unit - ) { - var currentColor by remember { mutableStateOf(initialColor ?: Color.White.copy(alpha = 1f)) } - DefaultDialogCard { - val controller = remember { ColorPickerController() } - var colorHexValue by remember { - mutableStateOf(currentColor?.toArgb()?.let { Integer.toHexString(it) } ?: "") - } - Box( - modifier = Modifier.fillMaxWidth(), - contentAlignment = Alignment.Center, - ) { - TextField( - value = colorHexValue, - onValueChange = { value -> - colorHexValue = value - runCatching { - currentColor = Color(android.graphics.Color.parseColor("#$value")).also { - controller.selectByColor(it, true) - setProperty(it) - } - }.onFailure { - currentColor = Color.White - } - }, - label = { Text(text = "Hex Color") }, - modifier = Modifier - .fillMaxWidth() - .padding(10.dp), - singleLine = true, - colors = TextFieldDefaults.colors( - unfocusedContainerColor = Color.Transparent, - focusedContainerColor = Color.Transparent, - ) - ) - } - HsvColorPicker( - modifier = Modifier - .fillMaxWidth() - .height(300.dp) - .padding(10.dp), - initialColor = remember { currentColor }, - controller = controller, - onColorChanged = { - if (!it.fromUser) return@HsvColorPicker - currentColor = it.color - colorHexValue = Integer.toHexString(it.color.toArgb()) - setProperty(it.color) - } - ) - AlphaSlider( - modifier = Modifier - .fillMaxWidth() - .padding(10.dp) - .height(35.dp), - initialColor = remember { currentColor }, - controller = controller, - ) - BrightnessSlider( - modifier = Modifier - .fillMaxWidth() - .padding(10.dp) - .height(35.dp), - initialColor = remember { currentColor }, - controller = controller, - ) - Row( - modifier = Modifier - .fillMaxWidth() - .padding(5.dp), - horizontalArrangement = Arrangement.SpaceEvenly, - verticalAlignment = Alignment.CenterVertically, - ) { - AlphaTile( - modifier = Modifier - .size(80.dp) - .clip(RoundedCornerShape(6.dp)), - controller = controller - ) - IconButton(onClick = { - setProperty(Color.White) - dismiss() - }) { - Icon( - modifier = Modifier.size(60.dp), - imageVector = Icons.Filled.DeleteOutline, - contentDescription = null - ) - } - } - } - } - - @Composable - fun ColorPickerPropertyDialog( - property: PropertyPair<*>, - dismiss: () -> Unit = {}, - ) { - var currentColor by remember { - mutableStateOf((property.value.getNullable() as? Int)?.let { Color(it) }) - } - ColorPickerDialog( - initialColor = currentColor, - setProperty = setProperty@{ - currentColor = it - property.value.setAny(it?.toArgb()) - if (it == null) { - property.value.setAny(property.value.defaultValues?.firstOrNull() ?: return@setProperty) - } - }, - dismiss = dismiss - ) - } - - @Composable - fun ChooseLocationDialog( - property: PropertyPair<*>, - marker: MutableState = remember { mutableStateOf(null) }, - mapView: MutableState = remember { mutableStateOf(null) }, - saveCoordinates: (() -> Unit)? = null, - dismiss: () -> Unit = {} - ) { - val coordinates = remember { - (property.value.get() as Pair<*, *>).let { - it.first.toString().toDouble() to it.second.toString().toDouble() - } - } - val context = LocalContext.current - mapView.value = remember { - Configuration.getInstance().apply { - osmdroidBasePath = File(context.cacheDir, "osmdroid") - load(context, context.getSharedPreferences("osmdroid", Context.MODE_PRIVATE)) - } - MapView(context).apply { - setMultiTouchControls(true) - zoomController.setVisibility(CustomZoomButtonsController.Visibility.NEVER) - setTileSource(TileSourceFactory.MAPNIK) - val startPoint = GeoPoint(coordinates.first, coordinates.second) - controller.setZoom(10.0) - controller.setCenter(startPoint) - marker.value = Marker(this).apply { - isDraggable = true - position = startPoint - setAnchor(Marker.ANCHOR_CENTER, Marker.ANCHOR_BOTTOM) - } - overlays.add(object: Overlay() { - override fun onSingleTapConfirmed(e: MotionEvent, mapView: MapView): Boolean { - marker.value?.position = mapView.projection.fromPixels(e.x.toInt(), e.y.toInt()) as GeoPoint - mapView.invalidate() - return true - } - }) - overlays.add(marker.value) - } - } - DisposableEffect(Unit) { - onDispose { - mapView.value?.onDetach() - } - } - var customCoordinatesDialog by remember { mutableStateOf(false) } - val coroutineScope = rememberCoroutineScope { Dispatchers.IO } - val okHttpClient by lazy { OkHttpClient() } - Box( - modifier = Modifier - .fillMaxWidth() - .clipToBounds() - .fillMaxHeight(fraction = 0.9f), - ) { - AndroidView( - factory = { mapView.value!! }, - ) - Column( - modifier = Modifier - .align(Alignment.TopCenter) - .fillMaxWidth() - ) { - var locationName by remember { mutableStateOf("") } - var addressResults by remember { mutableStateOf>>(emptyList()) } - var searchJob by remember { mutableStateOf(null) } - suspend fun search() { - okHttpClient.newCall(Request.Builder() - .url("https://nominatim.openstreetmap.org/search".toUri().buildUpon().appendQueryParameter("q", locationName).appendQueryParameter("format", "jsonv2").build().toString()) - .header("User-Agent", Constants.USER_AGENT) - .build() - ).await().use { response -> - if (!response.isSuccessful) { - return@use - } - runCatching { - val body = JsonParser.parseString(response.body?.string()).asJsonArray - addressResults = body.take(5).map { jsonElement -> - val jsonObject = jsonElement.asJsonObject - Triple( - jsonObject.get("display_name").asString, - jsonObject.get("lat").asString, - jsonObject.get("lon").asString - ) - } - } - } - searchJob = null - } - TextField( - modifier = Modifier - .fillMaxWidth(), - value = locationName, - onValueChange = { - locationName = it.replace("\n", "") - if (locationName == "") { - addressResults = emptyList() - searchJob?.cancel() - searchJob = null - return@TextField - } - searchJob?.cancel() - searchJob = coroutineScope.launch { - delay(500) - search() - } - }, - label = { Text(text = "Search") }, - singleLine = true, - keyboardOptions = KeyboardOptions(imeAction = ImeAction.None) - ) - AutoClearKeyboardFocus(onFocusClear = { - locationName = "" - addressResults = emptyList() - searchJob?.cancel() - searchJob = null - }) - Column( - modifier = Modifier - .fillMaxWidth() - .background(MaterialTheme.colorScheme.background) - .verticalScroll(ScrollState(0)), - ) { - if (addressResults.isNotEmpty()) { - addressResults.forEach { address -> - Row( - modifier = Modifier - .fillMaxWidth() - .clickable { - marker.value?.position = GeoPoint(address.second.toDouble(), address.third.toDouble()) - mapView.value?.controller?.setCenter(marker.value?.position) - mapView.value?.invalidate() - } - ) { - Text( - text = address.first, - modifier = Modifier - .padding(10.dp) - .fillMaxWidth(), - ) - } - } - } else if (searchJob?.isActive == true) { - Row( - modifier = Modifier - .fillMaxWidth() - .padding(10.dp), - horizontalArrangement = Arrangement.Center - ) { - CircularProgressIndicator() - } - } - } - } - Row( - modifier = Modifier - .align(Alignment.BottomEnd) - .padding(10.dp), - horizontalArrangement = Arrangement.spacedBy(10.dp), - ) { - FilledIconButton( - onClick = { - val lat = marker.value?.position?.latitude ?: coordinates.first - val lon = marker.value?.position?.longitude ?: coordinates.second - property.value.setAny(lat to lon) - dismiss() - }) { - Icon( - modifier = Modifier - .size(60.dp) - .padding(5.dp), - imageVector = Icons.Filled.Check, - contentDescription = null - ) - } - saveCoordinates?.let { - FilledIconButton( - onClick = { it() }) { - Icon( - modifier = Modifier - .size(60.dp) - .padding(5.dp), - imageVector = Icons.Filled.Save, - contentDescription = null - ) - } - } - FilledIconButton( - onClick = { - customCoordinatesDialog = true - }) { - Icon( - modifier = Modifier - .size(60.dp) - .padding(5.dp), - imageVector = Icons.Filled.Edit, - contentDescription = null - ) - } - } - if (customCoordinatesDialog) { - val lat = remember { mutableStateOf(coordinates.first.toString()) } - val lon = remember { mutableStateOf(coordinates.second.toString()) } - Dialog(onDismissRequest = { - customCoordinatesDialog = false - }) { - DefaultDialogCard( - modifier = Modifier.align(Alignment.Center) - ) { - TextField( - modifier = Modifier - .fillMaxWidth() - .padding(all = 10.dp), - value = lat.value, - onValueChange = { lat.value = it }, - label = { Text(text = "Latitude") }, - singleLine = true - ) - TextField( - modifier = Modifier - .fillMaxWidth() - .padding(all = 10.dp), - value = lon.value, - onValueChange = { lon.value = it }, - label = { Text(text = "Longitude") }, - singleLine = true - ) - Row( - modifier = Modifier.fillMaxWidth(), - horizontalArrangement = Arrangement.SpaceEvenly, - ) { - Button(onClick = { - customCoordinatesDialog = false - }) { - Text(text = translation["button.cancel"]) - } - Button(onClick = { - marker.value?.position = GeoPoint(lat.value.toDouble(), lon.value.toDouble()) - mapView.value?.controller?.setCenter(marker.value?.position) - mapView.value?.invalidate() - customCoordinatesDialog = false - }) { - Text(text = translation["button.ok"]) - } - } - } - } - } - } - } -} diff --git a/app/src/main/res/drawable/howtomen_logo.jpg b/app/src/main/res/drawable/howtomen_logo.jpg new file mode 100644 index 0000000000000000000000000000000000000000..577ff0576e3e8148c1e25eae87a76f04f3660e9c GIT binary patch literal 11102 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 literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 00000000..42e6d6f6 --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 00000000..42e6d6f6 --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/launcher_icon.xml b/app/src/main/res/mipmap-anydpi-v26/launcher_icon.xml deleted file mode 100644 index 85f088e5..00000000 --- a/app/src/main/res/mipmap-anydpi-v26/launcher_icon.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/launcher_icon_round.xml b/app/src/main/res/mipmap-anydpi-v26/launcher_icon_round.xml deleted file mode 100644 index 85f088e5..00000000 --- a/app/src/main/res/mipmap-anydpi-v26/launcher_icon_round.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.png b/app/src/main/res/mipmap-hdpi/ic_launcher.png index 4ea23f57d49fbfa54e09322272ba7c93f70f12e0..dcef5dd29536e5968f506490c7c4afd43c997cb0 100644 GIT binary patch literal 8691 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 V7Eeo@W$=6jpaRlV_$Fr+{y$EebNv7S literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_monochrome.png b/app/src/main/res/mipmap-hdpi/ic_launcher_monochrome.png new file mode 100644 index 0000000000000000000000000000000000000000..d539a16b744bd9408bf3091fe998ed467f00cd0e GIT binary patch literal 33344 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 literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/app/src/main/res/mipmap-hdpi/ic_launcher_round.png new file mode 100644 index 0000000000000000000000000000000000000000..154fbab5fb5f9dcb8031e24d1a34be10da860442 GIT binary patch literal 10478 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 literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-hdpi/launcher_icon_foreground.png b/app/src/main/res/mipmap-hdpi/launcher_icon_foreground.png deleted file mode 100644 index d592742cff933e8d5bacb1907c9c26a15cc36e6a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 21795 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 diff --git a/app/src/main/res/mipmap-hdpi/launcher_icon_round.png b/app/src/main/res/mipmap-hdpi/launcher_icon_round.png deleted file mode 100644 index ed9a370326692cc23b1dabebd40184c42c8fe2c0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8597 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 literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-ldpi/ic_launcher_round.png b/app/src/main/res/mipmap-ldpi/ic_launcher_round.png new file mode 100644 index 0000000000000000000000000000000000000000..f88a6aa7bcd4a1a79644fa58d936700eb7f5344d GIT binary patch literal 3111 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

~`2Qp8PK1Eo(FxY{#jcvzP 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 Y5o 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 literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png b/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..ebdae6b50d4c6bbc7ebfb29bbeee358177a48eb3 GIT binary patch literal 44388 zcmXt;Wl$W?*R~-92p&90aQ7g=-4};l2(mzM4Z+ zJs)PKs_Q;|q-N@LUp*1(s`6Oqr056;2v~{=GMfLMi~n8kQ2yN`sMwDY5Z)sw%18n| z5RW=hJJ_M1wa2Q1laFd`fbmC7(^tdyoU3O(V8L;i&)|1B69j*iK*W%P)_OSO0(V zzxNmu=ggb`nI^uw4E^zB=DG2vM@%=n`}?{Y+JE{InN&`ZZN?EKVuTy$#Z&0x%j*P^ z{|{UvgvIqpZ^-KgP=diI8Pt{ zi`O5u1Z;J|FZx~bvf2Bew->i=gGs})p7p5zra2vmAr@-g2<-mzpU39MouHe4MKt`M zA?LS_N$9_6j{nQA`wypo&N7CtFZzFzh=m6GZ%(~#ivCyZGqJAkKh(bdFZ}OkoFWh6 z9sjHL+7R){8S_z~8uvfF=s*4cFJKPd*RHd;9Jc@Tj3bxCCy)OsQiimc)L!p#oy}&5 z1ny+)uec5K7+YgAZ0C%cSR($5bw+k$dESc3(spi4EONi zart{AUsoa{q|S$QwyuZe_eS1eA|rQjc#Xemc#fZMc#b2|+gIf~vTvB@Sp1=Pa(nf; z6RpfqIS`NV*X`Z+;;+f?yEl^AUX0H8|DbpC_4EHp9^n6zJ-`{#HN5Ys`}7xXd9IYp z>FXD6bmJ4{;FmX0;}btn$+jmhR}+K&J<diux^@B+U&uc{8%X;qiBJ^e2C^4vY<*ztc!K-hptPT?liaEC^f*9p?#hjes z&>xG8`ib9cr{r-5YDFYbJaMxIxuc@x=ghfGat1BU%P$?}9>P=GGg~8?9ou;sST+pd zz8cTn@h=mp#dohct#hx-;Cx{hlgMy_9c+SD#(TmkNe(ZA=ty;vc65`AIPXX^6kJr5 z^g>UWOas<*7-Q&4OO;x(S$N>#Hj1J`3YxpEGE9J4t(t#p|(JHuFN z-x)mK8M4iH zmFZjxS%OaBGFBU3a&NT_-7dI_*BD`Fm+c;|KZTS2#!Q1Lb@$Az?Fj>bbByj+Lu{XKV2vQ6u9Ojc0xmy z_%2ut36{P3Ydq_n=FTb$F|GuCH|COOqy+sWPLNunjF3Z~i!Mx*){l$x@ek{ik}76| z8%LfR)IPIAeV>-d5O4MPxix>CC&qXrOb^9&F;%Ae-~#2F4wh6IP2&K%x1*;K6qBS% zpH}oy5nNHuobQfYpsX6{)x?gRaHuKIA&__JCZ@>N$cu*D%0uGcR~W7EF{19)?ja)u zQRnMkY{KA)oS_0gsEq~G&q8Q!5oh+727^Nu%@u}6Oz84~T4jl_*iHn}%vI1AvF)@T z!ODS5eMYPY2~ZjdChd;Lp6;Nzylmhly!h05vp`DU{mEqe_iI<|b?W11z5U z5O0PhInV-831UQ-vIRqYKcV#*|E{Uc7D-5!J&Ch;K}>9KyF?)h7MfB-RUNg%T!u!# zQ~Nsx#wLP`aDk!^ptMot{n&lo6#Y%2qBV0DyICHyQ#pd2phLO^7BEOKLJK0w)5c7a zuz6y`l;q6EjK9V1Ug1=z7?euCoiG9fI^_~jH_Sqm49i(|bgo8SzvGnn8+cbpEI~ZM z+}xbnx5b>CB(A&5z|+1EO~Kx7O|A%^RaFzah(x{Om#40LwbpOb^J58s>hB5L0F~%}Db??$X2_0#=!svhiw`zG}rXp{Y!Jp$%P~zc;0)h2GbH)Q1eV$;F z^nJj7TCt772^ZyiYzTfGbXe50G&7MmMENB-(Wt>$kXt{q9j22fLy*8OQhG45;rA}k zCZWS<_;G2PO8yAXj7AHwyxc%K@S&XTUR`AlTLio_NFT4@Hj*BrbQb4K$xEks|dj+=gmqQR@}mz97k7C1H6DZl31>Xe@wGbDm{SCyuws7gXIH zNw&ZQ=})+#s@ZdJg!~NHC~q$q#Nd7gGYBZ=0;vhAAY}+tm}FzTlF(JZW2A#_eM-{s z(1iJzv>FTfr+N0;vx3falaI>l;L47EN$2~!P1R*be|TNtH^3t9IcyHk&_aM4hfvSE zUF+!(FHU<6ki*~D2x}Dku@5b2U#(_Y=13B5Pi+e1Tn_4VNL{O)c7;mH4Pr#+OgZ__ zB2I0dESB5U)zAJ=Cg`gNCJH&lsw<;?6uCIV&IUS>E$5@y;RkxRZiA{B0q6mvIw=w# z#}#SM+hjh${I|Ip0_EuFYt>1nG>%o6L?Pqrlu7ouTii#U2!b<-U@cUxdYJU?8h46l z6vz8Gs+yYNYt^!Hbd+&bslOB^0A|gJMUW`S9OsMTCE$mBk(^dzlEJ1nhb(|YSVI*e zXOM(dmGmu&5Ec>LZ|wVq8cl;k*d0&BHz=50&?AJqlt67i--kf|2606qEP~sHn^T$& zfHD;t3(bsTmC9y0ImTp_PBII@4CFAkh!`%tHp>>3cG;9ryWXczj6e7&Qbs9T)U|D2 z1ye!alVv{3Wq>}G4VxEK9&l4%Zuhp*!Inu=TH^k6pZFTh$@EH(D7a)##|A8_YW#I9 zw&KMc$O`2QePxP&R|n`trVQ2}i$ zst7Uz_$z<6#)u=3#TO*jImkg7A5*qa#bYs(Ox^}2o9)NOA}=MCbEH$}GS+AlHD3kc zbAtl2`?S5`d)t2SxV}+)D*hh{6ekR-e_NTe)shQSDOle!Z(z3dpc|#@|K195t^v@v ziz8Kr*AJD&?!!D1_etY~LC`=@b}da_?}*oYXuXzolp5Pp)u~rKOiYEhFA=ba#{hWC zz&xz*?UbO*-B1Jc72*d@DIcSMcj8MOU%J$0bkJ{Ru_sR5itbCQ^%sC&Ru_5kt3)Ut zFE{$fkg|Ua*A0kTX1UGIBwgN)MV+**oHB)Ow=7y5LU*dfAgFfhhYq$c;atLb3# zugOJmTI_IKf&xB?zd95X8ux)9KZvP?nx&PEqej9~5)j~u&-wegi~DWDhwn~#A(6kr zM^14-FK)Dg(M#EVO5v7FSxuzVW_ozB!tBy%(X{A8@hXugs*Id}O)cYWYpFFnv@go8 z7b4M}^cQd`ntv#)_FpT|<7`R>N z?l-B@(9#QcyVscpwSdoVIHE8Lc+ay?BUpwp^qndnBnWe>9wOUgpoM5@2AtialsUhO z#VW*v^fkTKoA#RUL1*OksQTx`J88%uQFM`uCmZm0F z!jzE!j(fs7@%la7S_6zIp!%wFy;bL_1i?dyX~HAbNaiNJZ;p)^;bD|fLuBRoJ^qNd zI;p%(r9r>I1Xj>Uq%YsVby~tpF=EIWip%4<4<$PbP*RT2U{uPB~XfJKESSss4W~pf>Pb zU7U}8-^XpUux$Rup+&@a4ToJJs7_wM(Kz-h)I3r_gF$lQJ2LN;sRjD*HaCWp5}{|( z_N@yy&q1_P(v#tb;-EC>s3P|%#-zSP6M(Th&a>q}w=**vtGDAel80QQP`xNM)izU8 z(t<-8JESm@WuG;u0Vc-0BQ6URa%y(fOq8!X=rgyQf+QGb%TJ8ai#mJi?y*p4p{AE( zxW9JBz)y>4-CYjCY1jI-!rbw1?UZiv9H9CT>c2+{y<8#hahbeT5tEeg8KOm@-gqh9 zjuEcYY4Bp+bIhgD23LDUvGY_0JlE<==-~#sOR5`4c&P+q`;jJJc4@UJ2lGKCLG3czXMqs;b~HvVF?e|t@G%r60YVu4FC`V?Bn)jE%p+q(59l2B(L&2s$!KO z7!bNm*8>9=MRH>qPox?(Y%sgL-L1Q8UYHgwX5GZGNERJi`YI08Hw*O8gcW-@}Cc#+6=F8hS z(SogbpAxjo$9}V|wATLCc78?fu=ZS)HAgxUM`2=g-KRi$h?&K#Y)ec2Ho%CaL#>6<>jT8dV>Px6>trB$ zJ({~l9v4ARB5g|Nggk>S9+8TX*+URgCz6i=t91tF#*C0$dulHcot0BU(iHz~X18CQ zcI~$Z)N(g=fPoX5h&X5DC;Fb!2iIsR3$jm8$d><6XLgXIS`EIgO_=I_Wqkq-Iojs|Z!@({vUO-Cj^Rx-U584;KxmX!UvHv_hKn|C zpbK@QB-iDJ$4q2Yz(~PYYFFkou6U!*)`u5FX&RK}c=`E`{0!g_vuggdG>p}LGljr9 zerRUFyZ8A%eF7gwm8&t#6e@X9)DxNbdsPCl$=OIg>k?@S?sFgTXrUmREr1C2ji4NV zh7!$Cn~)ZvfmyKCoc{W~rycV&v)!~1Dl}bOBJ;t3rUL`U8VKGO=9T1A_4d@K#3O4m zdVcp^k+NUTx@A-mbtGvm#uf}b!%>j1_@As!p&G#>JFAH&DcgnF>6kStV_&8vn%*=b zqw2H?4_ItCTpH~dLPzP#>O%DsZ#TK3^D#XEJ1_$M=I>Sb7cveFygH5(v+TZ~hIZ<- z$}cc!@toPTT`OhaaO!M6qpWPKH_@GFpVKikF4;ev;Jqd$s4Qwd~ zd~{f?N`+RK@(;wsP&TIA2_{Q?!4N8G;@nYXNlhw@#E*7}OL5PLqm|_;P)R)vdRr%r zd=3eb`oq+#1Y4-Jkz%?5?odW)m`+{M8`=BNi3lmLO-Fb@B*$=>C0qidW``FqA~78g zgF3Y~@OO9u+|aE6ke$4mW34xsFu2L#1V@9nl5YYGah9i}Smi$bO5(Vr(jpRBiilj z@8<<~`hqSHrl=e-xsROd*jX-eBb_{C1({fLNrA@tW@)QkyG@2}*gIE;8?e2U6{ep0 zjUH#sH^q+PjI-!zW-lgO0;UASCJA_qQG2UK<31QEK5D(C&eBGrnd(scEPx3$qXu9# z#`FyaDSuUXTRHh3%?s6YaT^#Yrh{2XrJAL@pF8PS-r7*oQNlMbZUa%#;3ZNt4yAF| z6vlKJ-nL6dISY?D^BN@sIASv&Ng~H7BG&Fr<-0pkO+H;-ZpJTj5ybgVM5-rr5Kne9 z1=VnlG=kLrZ}3EhCbX>5&T0+jjjLP44>iJevXn7{ zFSlv#Xe0g%%$(Fp*tj~zR2xCV@?mYQvdsg=bE6kp4ouL3G;d5_tCHcZw-chBMN!G$ zw6CK`d4h{ML#@d)ow6;VffJ+@Ki!GFlJI5Sh$!%a5=9K4FCxjyZEMir02B+uv|$#E z9GS2;U31Hia*%|PUiLqOXjR>!S#`X870soT@$L3uDzeEoJc)rfh}pWvbr{@C6-?5o z5|N{UZwUE%v{03?hIfLvJ9fA07Fscfnohi0kT?+Ex1J;-DL=UM%<1mi^de-fW1wrk zLsS?1;o}pO5vMFCDs@q68RqchsiOHN7vo|i6c2HzjXFAH+w1mS7o$QFHcw3+ODgEJ zHo?~EB1P46RTibBE!)GxWu;}i&+g6z6!p+7V z8BEZFEQk952D>7H3(`SBPRb$VNQl>X+)%2xvbRhRd`DbV{K#5uJ~ZZ%)_B~MBIQZh zs|iKaQzgyvSBm?_PWldqB5}xeJS@&k7{zRFca-lklZu(pwK+-*__pQVDCIG9Bn|IK zRe50xI?%0E&dpV7eVd)DUYNC+WtP_Woov!5!JI?TuPQA|Mp|R5%?~|zN&7^!<%wiK znC7t-{_U_ezn>>j==Dyamgd7C@bPX{xc-oEIDh1izk{Rv+bQ0nOCChQ>X#p=X} zw0LJICq`*v_H~zFj}fFbIBnZsRm5VN3$$wExLt6GVTu_HK8RR(kG9Z%~=RK=-`dL7w;dUiZHs7K^yEsxfntKaXhEZhkI5mMGV@xXP?**<`o%0K2vWd(tLA$dYda0i=-F6engu*$z>p z79hFCouq#J&HY=&V3-at$1+eUx66oA-h+M0u_Zh*iAd)(3wlHT?U1F0dCH4bYKLXm zN`5T)<8?fMas4w5V0Ce5WBXw?C%Q>NL(6j$W=*csZ}0DHu$!xR0xVZkO)(N!>csxi zK_L1&==-Oof>(NEjgWkw(61D|D*I|O>|aaD?SweJy?;xS1Y*VM-`T)R9MTj?*txH$ zQw@G7=$pM=5ZvI#xByiQ2S?IqRV5>q_LM^^=GbQ4Y~~PD;wtXix%vU#rsV_sG13KJOWmY8jcFZhuzA zhSd>l;JJsaW`pJXwHIv;>$*8STy0Kmh&TKw7lHJ*n?Nik&n0=6wLF3*@^Br~1TDEQ zu3~S+5M?ZGj>3lN1g)JsJMm#v5Kd{g4PeMei5+bK{+NAh7Ou-B3nxai;EzCV!Iste z-sI4pjP=wW&0e?KVP}aXo~bC_%^CFH+YY}D8mLjHGm+5JQJLyh5zO71szQ%3mb+|A z+>ZWKee}Muf*V?`X9L&5{QMp}cHt}OIri3Hi<1!eQQv=bLHiz1g&dGkX@`ZN?atyf zsHHXLX~;F+$FS&5OatQT{uX{_dH8@_LJ<~^F(do6Ei5=T|2c+w(~|ti z)o|xp?nAz29M(s*O=HI?MP}(!=4(rkH>WfO9zUXdq5^*JqmtJfc??gjZui_HG8(u= zv6*~^aY8U`bR&t}%nmhpnx$7#8o8EqgJn8$&Sq}bVtRu69&TY1kUwrSH`&)D7*H?$ zqozY;Mo z;ON{TI_^Hw>}ip9zTy#HNknqBXeuTNSg|7n%rYT(#Sk_im|^{6zf~hcsr7vpx(Id* z=OT25w8MC^S`SL21mM#`7i0}ZV<338y_=j(Mn0cS8E?p_`YeeJ#+i~y))UATiSJaE z&*X`U%W^T94XLHva`M*f7>4HN2qGECQ!(<~P;9d$AtK29(b z1rk_Z5!zo$Av2}TA%p-RUvbT~Mg0mBf!~m9Oh5{)I3$~(2vjwok3(m`At*t@FzpPKkJKMGeC+2pV zSBs;*btnqsP)@J*1zCJSTdA~BX^K-hS%16X8Zd8Mp=T*uLD=fV*o9U9wvH`u)Pv$& z1ls+yXKO*wtdQUtN$3~H*Sb0o5Afd<454{YXe|tyL?h03l$&UXD%(y|0s;SUY~mt9 zc#%6~>m=a5@(%=wJ<97))fxBDeKJiEaXJ$g&)gki4!V0(P#qVi^3}Ll;92XL|FUW# z@0r9fCks=tKs$%)RvKi%VXDxZ=WW7<@ee3t6DV1`k_w)z&1M9>cn=(LzAvs=en*%sYabnLT*>o&~R1zOd- z*E6SM^L4>3VE)ZEpZ1j3o6g|Mag5yL(&Buk#QMKTohxJi#{w*<&!Qz?*aA`AxCLS- zW>~-k`0ijlO%&q<9rh#$@os<jrhCruH`&Qt@^2z{tkR(lz$+67mfzRXTYbRymjyge5+a(l5w zLfBIOn!};7%!}z)QpcKEM-er;*wUNKe!2!3>bHXT$+g26+Ep|v8$|j&Z`qmxd5)!c zDh*a{?G^@f42vtO+a>E8k*hxH&!u^*?Oz33x}NM4vS%4Cz?{@4?a{X&9NB6Vm zvirSx`k$s;i*^o5eT)r$64N)NtY13+Yx512#hDI6A{Zj;A#B4rf?mZi=@+SU6B?H= zHBnF_lLAUB#~_^|*SevtlPoEI{A>tInkNN*>|&vG{0C1(xl;?N*?t%{8fzJgpu3`$ zYiJoMRxlbA{I0Nye?6Ht)Rgv`OZFi22-=#`e6*7ijO|Z`BDaL5ZO{KMeMO6Y_h&R9 zAzD1&`S)a8XOwZmioor!`{r=Zth6^9EKt z8&w9^+)EvM&t){+s_qdQ6^hn8;q8qyJc3?lr66a1PAg9w@=7kip{wfWRMDlrN zv9Y9xlkA;Z<{pZoDmI67_3-6z)1QQ@1*I=C-_2Bq&or5+06;P#hVG6-mk(0CI-k1( zHI(89>C!=;@zcaQ#!XMXQc5Dq;W@>)_A#NpV6!?0Lc;UP2@e7Vr<@WSPC9OvxbhK| z9M99%@x#p3#cc=8UChyrd>qQs}!~U2=DQ|S$ta|@1~lh>av2i-I_Llj_-rz!62sx zdzh-wpK0t6NiLR3qBDHPb0&pBfgMMK_A-qTz%AFfq353-^- z)V$d8!f}omAH(7}3dd~S{^I1j|3((RHu$emGL^82j%fM&n&ng`1oxfgr$r?GH5dD! z(^uBlnVrKaLVKoNBymB+@Cq@J!AMLr^{P)`o@{NM#)<>O&D|AbD5t!a*o;|qYa?^I*@doPHPh8P&pZRP{I*37%Lb=b9bMHeUFB2zvW*vQ)n2_AU&d}mdUvR7 zo$7RJ>LYi$ya-{J(N!kc$mYF@`}e_V3aeWEC~BJ}Km`(}r3*d~=9l>O-~9q(hY;-E zu}mx5@4?=LqMC}|9H*n6AY{lkehkzp>#JsanY^vFx7e8s>DFJr>Y-djZ1tFzj>1L9 zfq(D*fR%db3N4@Z&Ho*K77^2+tPSqWqS^a6r8+BsHhmhYr$P*ri#@uQ89`z5qlvl* zU*0?13PEZOM|Q*ynwD(FYDq_>R(6-$_J-+gLjJTpa{fGoqH4Q7Y)e=s%aJw{x%{ax zD%bHJusp0ItI_V9d&|~Jvkqiw;$gHTtWs=cp3|#ajt1svl(LINHRTOeque3%r#i-L zeQ{jX5v1TMDMF}BQ?(3NiYvSDAHnE$ zlu7*k!4>4LK>z zsd{nO!sZ|?l9|Hm=H&Z8QP7bzUG+=JC%;f2zW7JzJ_*c>P9RlABHIy65Vv$e;UHRY z)PIO+Jv~kvWTl>DGEl34r@OE5HdRVKRvGUX@}~%H>SQCs4rj8LJe*%G2#em*Es04j>%yhH5Rwg89$NE3rrO;`f6K`_ruM3eQ+r z{6APO!F3Oa2Y<#3Y&8W*uk;}{m6T8O9XmAQ02gVTL2uM~yuKPjFbc;pCZ``Z| zb;WfLZaX|b%qpF>9CaMGD|F>OtMWwoJ5+@Y&+he@E$6oQ>pykp#f)c8k+Y@-SFYK> zVo%5dDzryHBUv`EdMVvxNlEH2vJ8eOe*%J&?a4!&c0yR>D1rTEr=-qW@6tlJK+MW>Rt&+L^i?qXyE}%)4foLgZ+9SXp%gQ}zaw?Zq zO&0p?R~x}(UPtHEL@CODBqyif} zVo`JIQ{8!TXSf?de@kojd`4rzvt@;t2qOZCHCA19vOh&V-h;L#Hd^0EjF5Q~AgrW* z-ua&NqBD?Cl~&MfbF0)PL6)iPrXx(sQDx&|p~1sbzwCQ%j!@alLqu5Q@Jm@XSvr8t z4E+S>8xevY3O|oxKkN^)oYYja3xOvtQ($z=(0vQtD@1m=1#g&6IK?^}Z%z@u>P~@c zpWvAz^Jd@N)B6Mr^>TAo86hk-r_$e|`h3y^jQ+&HC75e)O5vglXXkD0AnIGIIQ#dt z$=2{qtlpO;qEo1U-FuerJ8ireA#3aOH&S=|WQrI1KJoXZ2-kkl(@Mn{nP0K)j9vX0 zph+cGd}_f|&CT`O056j>*m34-=M9E~Mmy6S_~1HWkd!r*44>sfA-Hl z(2Xt`L68FL`ZlvUAP#oHHtYVLk=uLOoOT&J8s2#7)o@w`uaAYXl9A>JmSlO~Sg))h zl@lT-UeZ84cQZll>hW+GqMjI{?god&;K(~D5+vNa014^h*9XDIZG~#(ui+un+nbSB zxMi+bmD5Spc@(mWzG$%xF~dPk9`s6o{qha9JVKetA*)|C@Thwo6gU(T8G~9@%eY#J z@FnS0s~OT-YU!!p;kULzTB2!^<>Ki?1ULV2yEJU_hhl!X=5H} z8J-kOn*tm~EKFjUamrR^TiVgWy#f&FG&#F^qd_AA^bKEi4r*B3CKNNGSlTTKQ7c${ zS%=Gse9PjDLwGS(Ug1zzf86Gzj?%(gU9Zj*>)+DRXSxHipC@_%!xY!P&qpl zjzf{}KTmZJ9EdnnWi$2=V%H%|N`?6cDZeq6YU=l`IOJ^Zc^*}^*rPvyDlpJ8%KjjD zODxp)14qD6N`Xao3K#^@fN$M4G0@FU&Ec1Cm;aIBqi0iw3XJ0*rEHDjG3NLEK2hx` zE96q)Adlp)$Z!7MNRRJ{Eg`}&A(C0v7ESnTdK&4E=3w@URg{lOh%o}2L~&3AkkyGV zlGNcc-RIiomsjJV3g2P9o^I8C!EMdnQQhoT;n`VI`}OifyDp#h;200Ms!E~Y!7p@| z;##*6r86(A(qL=z{r4C`rC}XPl#a$K77}GNF2KphfkKGlcOJ-xj8Yz+Uu@7X&tGFQ>3?hB{%VYCNd{Epd-<;y0>N+@-Al}qtZD$ZL&&}-$mxG zIbsFADdeCjyYl(ciYYc=&Eq9;z$jX+ISD5P6UJQJ-pXi8?Ab33&9-Q`)Tj7kU2;Jo zO(4tk(i-gPW!nSXZjv*uq5Gsi6Y4Q*TBX_j{_Zsq zB(pRD`Y2BE<%2cRVy4o1`C1t+v`ZM$MpP4ml*Pok@p}^9g!a{;8!H#1P}yFL&DqTI z{w~b0ZYXjxycMa(tpNM09AqO( zSW1Xg7~q7|O95I}jZ{szA3nXb_=h=S^0wciA9rl==^admfb2Rtio*z({Wby)#=;`? zdZWyvxSOI7*lNlU3`mS8`rew|u}Kv2QaB0{shMf#{T~b1E;<;DMikfh93k&Yzb!YO zIr)2-eTs*B;4RexZHbIM0Hr5-$jc4PeOG9?2@wlY`w+0{b6eo7()a1yzmE4Zy)HpZ z3_4o16gl-FX9h2A)x1WM0K|o>bhkR;tG0@3;y*NC8-G1I~} zx<6$~n`MZucd9_!72I`YYm^JdkbT(IgUj!X$DP)9rj&~_&8-|&tRIiW?(vZZmi*f8 zxxghU;EfD~4w;#MAy6Ltz&27;8Q`R=4GER9;6vVyjx)_F?)8WdT;##f?g*R zOMs_fP1$fZVv6Fb?%!__8Hp_|qsoOc%oHEe(%wvblah{`v8K(7`3Ltuq`;lfknoGo zJhHivzG#?}gle0^_&~(5f}pM5vZU8D9_$s;jP{yo#+V{j^sN5UKeaz*W}^k_J%k{e+9Zz7m*%HEQ{E=Rr&W+D}sLU*9@n315H!mQ!ZsVZeADw|82Qr==1LE^8_e*3Q`P z-&u6BEBd#^Z5%7#^?Bl}a1?x^IS0|0LGKD&NLn?xFAd&^Ta}wt%e(wAqh>O7yE_08 zq}izB8#f;EHQKOWqpJM5olMsjF5XmM_V-9xyP}^+xmK#mCbP1pFXyi;>*6Z79vA{q z{`qZomwMvA4SuL)UgLS!{U!3{f`6^%w)8gev%+%(`F6_IQ+Oq&0ROOhPcPb^aR_*DBZi3yIdc$Ah};;@5`HC!DY8FK6yAnnuXRFNe3U zt$vRSrwc|MkIbUiU*w}0`CV`NBUME^OY4W!4pt)=8y#;H%?o(a?JFyYv>RHzG-Jij z!YS?+3m&4xyY$5`jb7B(ug%5tD4&)o=WG0j{HH|yFKqQZpL~}EUa0Le+w?OSPv@5* z?)y`>FV%jJ-u}wsFUQ^GuQ#W!65aP&l=C@V$6ucZynpT^QFVIBJ@jBvtb=AIBW$N&XB>E)WT`m6#udzB0j6F<9 z@e6y~BlQke7b!JNz?5Ns9*6LQY$^k@x0fKqE*l^Dw!K$Tt~2_LVq8?I=O^ZPq~YIR zrUzTO%3BB^N1e6@)m*N$fNVa&dfpZmHGv3|6@}f0{&FEsKs6O6Gr}2w86s{1Vyv!8 zuS)i#{JOI`YL<%11KL2h7M?BL**7luW95ixv@pZimigfZaatmU+l2lSf&cxB z_w|jtzjF6oJLRnZQv8SUgxPlAS#mq`!TfZW!&SM!FdE8KEZa%cXiq(p z7mNjV(va3MFj&CSF?)b+uSgG2|JQ1pgPQ&XN`=ba8iUpV6PWlgJ`(W~pi9$D9>m+u<<;~c9|o0id2Bmbdu*M-H$ zE~kv2S!=Uf4PYa(y^SctlKZHdg@+k6mXW3Ou-qPuVM*6)Hm!FIJW3);B23c6QW9`F zjl`l+y0p>4MBMhmWFtc3CK`Cf!o6UCuj^l-2nM+_>>RHV>wGSi;PYP_?c26xPPNWO zBUurQ5H^GTx*3_k=VSs%$6WSg;X5xfwz#n;jy`lHnco=9wZnlyYME>pKK|wx$6tfj z14*yLoVq%Np3}LPDMi1`m=iZ6JgJMH1^bsfyxfS-;5=RVK8%Tr*GW4nQ1PM_`t*vZX(EX@zFlu6bD6EyJTaj#D7rPsObmKJ{1|EpSio~Nl+ z<1njh+1Yi>=}xnTY{G!0KO39EuFUxAnvLaRGJHl;$q=g z>eoE$+kHtUbaUcv^&$A-=^ceK!T(5y^s8dC&OuL}@3H~seKMK#&XK}D3RQ^WvvR!J4$gQ|z3%xz z0qU+V&!|R2FqZ%iLd~irIcEkfCTYZN9Imj8Gsdgz%S)T*C{e3!^9&VU2kKuhk?nu3 z^9v){yUDfP7FfFMUP;tPw=V4O<;7CWM7};!45ItqW82pTVQH({jspCyWI5;dA722- zjM-_QP?#{}bkU6Y#LY)B=5oC>O0jENDYNQwF?$5>>H?J8+1|z@RLHzzNSij_RxNwe zyY*p8b}cPJ{mvjfJMWcDYtS{v3_WN2@wKX%pTvvtL)itTgB}pti-771xbynE01W1U zA%SqQCWqM>^6LrSKXB=mUuS;7w}Lcd5Y)Z@@=N)eMvKJax~tvW3vN`k_xsk(#e!Z( zUEjH}%_6;6yYp>0(%9IJkdJXnb^ET(AFoS$uX_x`a{jIhkPRI5dKnHbOIhmx2cl_j zNtk>=as4r9UC@ACJKt{VH)&t-$IjN5ox8W-K-}C{9i-uF5gnSb^Rt- zC%cn zC*i>+>O$%rAG=)+;w)J7`$U2^fBw8s(I63mO&OLU1##z@HoNFq2`QUcF?nZe4jU6j z8h7%R$OPz;a$EQKP#x=aHqxtT#P&>z4?%}u+?lXd3x$gZncM+yeN1Co8~E(X8cQLB z2cp9kourmQ&<2?hn@*eZ{SUc(h(@y{!R~iH5eL!{>>&x+#CJrKmIUFyZB~mOJzPcq zc-`{xV?;pQ%={&LWZ4m;V}v>?Z^XNnZtEz$aY;FFuw<5^x~Zm_4Y8#6E_dh4%+0}w z_$`g^CM)*-rIA;wq4&y8+kN@(w(Sko&cvjj|(5wtGKXbY*veM z*9|(qq9F7GKF@cFVjMVquWQpg;H_AYKNZHfQ*L)d3Qy|#2fY-@z+2yC_4Fb0kF?i_ zniz5Z=WuY5!^6SKwVK!?X^gxt*5t(Z!nISSr>9~H)-Nfbx`=AyznoRk4Rxf~zhbjy zmg=SLkqmsbr@c>g=Ua<#5g^*1-`qx$*0Wb~vXy36SvNd|aK{h^oyiAS!pIHOJGCJY zhcf+ZAgSFA+!N|#=zG$s8yT{Y+Ea4ojx zmlL6$;e-n|0!MW;sKRo&7iLgHd^b*TrbUARlj>nCX4tUdBeiMPTki7Ba64KoUeea8 zA1k(4{MkgtH^!@H!`%Mr-kAoHwflikSC!}xIhe6hYH$yV`tP`%x=p1O*yil0Iiq313i_z-x zDqIF%HFHlfxp8>CUMcK$eE+}@f4gC$V+xNH>KoSTkKIdoc9vC&RxGbZ>tXOLH@SCP zxS!09Rv)K}x5x`~3YX6RBw?ON4Z&*s(kn;qG&*~zTy8*;g$!{Uov;l}+B(wxm9G%{ z@z9#r%4(?TqmX0q?Bl87)Y6i&&{>!@BkO=ycabB~DNT1%b5{8L zNsF>I{TAs7?LO&)zrR#Ev0&q4{|;4zJJBo@s2zyil&XO zk(dVQG?FW}F*;-fDSi?lYB_i1si)c~*JV{1VAp=`APPEYu&py6nVr2TSF@TaP;gq19@eD16tf(l@RPekF#$RUzJ8<+cE7L67-C4f%@I05@@EqO#X|K@pU;T33`kFh_N?$MP^ixw7GHzuuGf5D!i5wsDPQdXb z$`pALWch^;U=BEo2&o->ic*-Ou{>)iJ{{a+nyfs?_*+~Nk%Tl+AVnt7mdlAj3P8#z zL=TjEA35o;_f&cYrI?VV-clB;6_mP=%95F>9FEoF8>Qq#ZpW@!wdZFv9OUY85?7AK zX`ESJ6PAkQNMcsRF#v;dwuX5@zbrS`U$b2SuLs6lV|A&q?b-21DrBacUU-Xk?%k_sL1w1<>~>vr?N!>f zBiESwU2@T0wOG2^+$YlK1_vE$tbWHhELrEYae?R9puhVc?Ex;v(9ij{3)-M=vn$bw z@>(YI@4BURw!bq82w4b;=MJ)>P?JNAxmH_Uz7==g_)_h<{Y@OA)HJ_s8+COx>UCBw zspsFa zTQycQ2k)NkZMB&AwY*@gg+_cgt@Xwl0u1kKnbq;hQ+J2i+U~CV?x6ue&Q_(E+ z!dJhDt=o+JGI|LBZO;|gaGxVQPtftRtGecrU7BaS15Pdd=YZACsFO=QAf73+x=!=W z_w?DZy8gnzW-yTWX-s_%MRxC!7Irl?IJcr~z;iTM!2m+Yf&$>m^IWyOP`y@{MnOYP zME!kcMN|E8p+Y7<=xEP07(-h>Fr1A;QAZRo25-hILu^4f4W5Ug-C<4Dn4boPuEXNWnR$%L-IHvDW zqQDQvAsZ=VJ@LJ-z)fZf>Bzo@PMlrQjn^F3w%J@EFg_wt!g|9o-#LXc`da5m{mjZx zeJ1XJgOHK`AkB}_1E0hSI(*F$-S)EEXwSIQm`&V5+mBqLi!a}+g}I<7kDt}v0}I-= zPy>`v!;x48`zqP$)@y|}Sd~vM_R~E|fIS|YB8NC*fR;0^?F&)Y+<1}tXV+w{l4?TVeF9#zvS`E!@+olzsW%n&FQ_M&;PO`=m#kckTwiFnf=QRLPrH33&-{16(~M}W4)QB73}Q#BeNOpM8??l9qMGu%y5 zy4>YSkZ`J~cSZ{dS$-vxNrMT3B6VgHo!caOrX0N!Y@8Xqs%E0O9K{66)#Jxr8E@?@ zY8Mlh2y4*YWGlxu5O67$SktB)G7()KDbqkXKh_58tJ#h!g7Kqp)T^JrOD(pI4?cQQ zw_U%V6{wVham4fqmZ?!RWLB_hNoASKVoh11I(-^_<|z4=?ef-Tq_!;La>tW(~c zThP&)uGiM}I}>W4n`xL)+Kt5`|KigCoz{#Z4DQO^tYS*?12iKmnlxR=qFsTp$Z zTo`EAj+TaN9gtHhWSK&}1~(`uguu%nsK|nHo^6be`u?4YKg#h22PXsd`LVmns@GkW z!uCUIAGlh>^^-dF!9V8vbEuWG=VWGyf`!DR{4&oVlb4O)I7dO*btZoy`S({u7{{pb zmVp~h356*c$1}sgukJL%SrJ!0QxRqSd8X`A^b9Lw;#4v-1f9zeK`|?JzL`lPnBK3G z{PG(?CA}z-Ffq}i3_WpEtpH%WiM_tagSK%L9?OA7-7YKGNF@_0LgvP-W(LTDhRV!o zRPow~g8~Ojq32vOub14mO~+3z>7GYU>UDQs!f9Jyc{XOtn5)Hhs|ZB}Bqnh|l$v}8 zWjO!=1U10*gKy7uPhC}%vzY9YX>bn)CW?Ya4OU4Gk@deKdX)L9?sH-7!EbjQs{ zbkTv9W^1|T8+Fyh)|6RU2W&0+Y4Gyc-Ym3_ZQDY-uLFF?z2p@)=^W$CLM8)X43gfX z%p`CHMdcwd)=d4)p}L)+;;6?r>zcn_w6VOY!TMMyPK|ZsMX!~OHnsBbhqUs@qsrPf zZLY1;7yU^xaYbm7+?_rbycmfMk#sSU*LloJVqDTP!rdlSPEkharf4*ip%`y6cbMeU zT$9V?C=YA`5hKT^xcz)J0`)O5GLi!%HE`EQS^BfZsZYryY)syNkoT!{(Z*LLlk%bf zL_rp!LRP9hTj$stVD$zX11zUB5m+6p>?_2+at-CHS7wyMkai=@>?~9;u?PJ^uYJ)0 zz2=3xb?n$V{q!$?Kr`)zu07P&3$B>c?U%H4{efK9?=N&2Z5G;@Hiw(q91Im|rqBAK zm+7*co};J{(1U;XWSIH?@y zwrlq26}RlyOZXmq!3{g~!t1x`mMiCV+5Q>LwgiMbIySA7CifvS`qkY`K&#uKegepR_B)4d#69whnYRa+gw^SqE5N(PtlmY?Cx z%Lk1jt6Iql;N*))VCB-duZ(whMSUjTKp87p5k@MSL30ON%8E>}H`1LqFX+v0+^=nO zrS7`>r2gc?r}ehGPV3J(zU!nua?g@Zo$jd3fy~X<%huEe)Ss6BE9P7rY<`;)UI7!?by-L?mcU|{OG#=$t$<%yT9pHee=J0 zqh9tE|Cd^G^GrnU&)fflfBt^`o6q?dde6_jP4~b31NyD+{W*Q}XMLT{o?KMPn6_Vi zqb_>or}4x1rTVHbxbNCCJsGNX@Je*P+^PMB3e081_c0?L8%UqHRo#D zdBtwE_b(`CPc}PO*QIO^-^jM{Yd`BsebeV(t8e+D8}uz-e3QQB3vbn{Km7(>|G96} zMK6Di>g@$?D2Z9Nwz8~W`k|jyXLUon4;|3!zvOfIae7W?A2_D}{0-l(?)plac(WH> zr^B!Ld>y>yRvo=!uio(bEA(|=dV~Jen{U*=`pR4MFaFsrdh?ra(Vd_999?qrrK&H? zDP|4Dm?@TcH7eZ?Jj*y~1afSDGsu(!EDLxFWb`@Y@c%lXztPj?*(J?ypVQ2di*?=0 zp09C#s3-0|rsEGioqUqx`#jGSGRQLAYzp|@q$G3oV^RRtuCeRxS39GFGtw$OJhL z8Yzs2GPaOrLuHMi`Aha__br!e_ia~e#|@Wh$F+yG`#A@-|CUR1>3@^)LYoIbdh zGI1M-mkEB1Ja5ED!Gbc&RD?`f2nrmMl%s}LmWNt8Inp1z^}YJ&JMYtYWm7MH?VTEP z@Ud~Or$70P_v$P^bRRn-ZEm);XWs$koN^XffM*bW(Vv+~9tGkTo&4VX{usG86;ZC{r*V4!%)~HeG6OJ62OY@j zan~;G`*6x$H|j~FKDQatnUrxNSlc~xapO%|xaL~54%cA@ylA(Y&8XY?))CXKx75+7wU8FyqL) zzH^Tn`wyvk=&)-0_p8{oQ(<;SmgkB*hj^&Ss3W8HqOW4(QOS0AEPj`e11wMA%2cO6 zi*vf~-hr01SKBVTUZ0*YEtL zz?nY%TfS8<{kH$2ZtIXX`Teb4tEmE61`n0L@x7VJujE={Qo4{7VvMFT>7y0m z(3OPV5{Zdq3QQz&#fe#-GYO3QrU@4buqZ$YZGEaa6XN1OzoDP_{7NKc)N8Z+alcjcr7Z4&3w%F}0(HWa;_FtXw0uz++x2aWGMs0;i(&IX&_CNIPzQnLg(~eXG9czkI#E_P@VH-~2y*P_O%@H*4t3l#Z@x+G`5A?o1s!{6S+mVqHEOwvJgWef1z9j6!1FT#h6k8%1w{v0DkDda zo!3uj3uF|hDut;UjSmLrY2x0PWKAxdK5=SNn6Q$9=Vm&8c_ZvZTZ5{!6By*tf%zn50voHBn9u=0Wyrp& z1wfUt>KGt$z(oIhNd7m6hdpV~Q)E?(0HDOK1bA^Yr0;o^RZM!JNoec{63L;`8d*ec$Nr&N&x0yD@*)> zJ9sR{AUQ_Id~c5XBf1(YvrGXX_}}VSJ2%!!zDu`!*2`237qxlvehtn%pt*2bx81Q< zU-EUY(eq#bd|9obo1b^R!f075Pd==>-u6D7?i3mh=CphFZori*l&T!%~Z7EFKfbd~*AfEH&9!%Vw9X(^f=WUXcDKXTQzjdIudd zzO%Zb#gk{0)pK2b%QcFOr@y(XQ%|2z&iIOU!OLf?2+$*|X{4V-tfq3}J~7cy{x|+h zem^UD1`=&(m!`Bd#^(bLFNUnxX$9l3B7q>}sx@cy(}0;U4W>^n9n}&fPVY?e?`{VrdPk^yLFkl^B$>bs4cW8jhqfKx($@a;HV! z`o>rsSS1s_WGgr5^^^m!jB*B$0zk_ER{&6vRm*=Q7Il#ygyV21L#F{Ni*qJ>1*%PO z*ii&{<;Z2oIa|VVLJ{CCom^0LGYz! zHYSh8s*Hmx!ShK0<|ZNl?(}5oI?*MClFAZJ$u$tk(S&`)qMVzIl`1IDa*anZk-yy& zz}#z03S*d#WOjZkSpj^DR-g>5RvD{R4#J_$jPwzg*Si4MTxU;yBJ z%Lt%Y%_3lm4hneb02_C8UPqsIz3ap57)LsC`4P?XO*86u)bI54`2CNlSu1q$WqVaC zMoMkHAKH{qbWrhfh*0U^;{Fb{()GL~9B52exql)r5V!FaY`||^qx93nNWoaeA=h;} zV{LA1XzYJ`!=$4(9M%_nJQEy6625>c9WsZ|TANp46*9`%dlM zR_Mfs{!&^ws~+RxhAGS?@!66innOq|A*8o1F=pSA-T?xA-bYSd2EdHTngOtk)gi!n#fupy z3sRtwe+xMY@HrXVzsL&XB({tZkU4iM9Uuv49e}>6QGb(fm=8!CK3sL()f{ltSWPblJhWf;eE5DX zpIy=Cf9V@^^_2(o=)2#iKl{<2(WRGc*SRHDV(#lZgt7BjGK45Zd~1xtV`eIePjY!# z)%oh0;*Zax>)^?FiZa4IMWbOTO!MT_%5m;alq4@JRob)aaXb^D(ns_qF z*R#OTXiMwCbBf-J0=XrUvQU-sENIXhYfJ#?gvrbnkwA`E!Ak#6I{=<>(7^6UV!}Ik zjAbpdtQj*TFj)fjt}p$snw!ZOgt5X!CUo@e8mkwl7BWC&4y-{(g5qFP<)Ev`>QFl9 zsCVF;Vu76Lu@5||a>PpC?Ww=E zq9F$`wb`hQ-}-hR+^v_r`el0Yt6!padq#ixXCKh-{`?>4J-_`Yy7cgjHa1Q}U4R@l z;=Ut%=)~eG_qoSC62Z#-QJ7G&M7TATOZJ8?3jk6vRVhr>XnZhuGb+l=T}YT=3ZGUGFdWah6BtP@?0y$mop zz!C>s@{b(f9>Pn?rJp!r``Cj|@mV!gXcfBRxtBARp8Wgk(R&`!EdAH(LBH^y|3JU? zLw}?vA3CA_=7t0~4Uici6QDCzHoqs!6Llkn1TH+lc+F*TG3Ju(u>-8%iyCp*A%6|! z4UNZ59e<*$)s-PXX!rE?Uw@xQy^#j%8|p2sYt-rLva9#&x;qZ(iks$i=#m|}=|#^0 zm{IF18=7t9+PSB$)y}%Qy`lPmeBd-1sREbqr$G|KkY5Z9hK?AO6r#tCAsdA1yd6eU zlb9h>GnQ%~CI!HSTdOjl*pj0=GI^3J3Z&#zd<~C~K~XFasv=X_p(J^IL_vZ@8j~ov z3!E(7$tWCEDxrR7Lx1!u?~?=mwpTn) zJ9f6Uxq6P3>nS~O*8|$UXOHH#&Fkrh7xfo^c#ppSn|?!o{Hq^eW!Ydn1Id8}8Tase ziF+EqZShbN;{iGFv5fJ#Zaga0>q~q>Y6!^AJh`dI?(69OkF4tBcb`lDveg~0d7)nP z%G>Eb=UGi94UALEm%rvFwdRAm1Mc1I>!Pdn>V=d_5s*Ho2=wL zXvnuAn*-qzVkW!;MW-|(2_K6UOKF5uXrgk_iSjfhX2>)RM>1YVCKE5GL=wR8vXB5? zq+$ykiBm7vVN*stjEt!w;o1sZFh(?aS~>&QgEZJMU7<`r5HuTHRRJCfnK$&)j8fT@F$P?pw&QUXiIJW(aOVnm^;cn=NxxM$ld2)N+NnCk}8H{Ek5I18l>jVMN5JcF^tGn zs-((>fK^JlBYd8_CZpiLCFQJMwLI7QdS4E(fZqQ-4&OG7d5eOFD!~37#yz~NFDZ;#J*W=}-*-xpANm8;@m<-eHgW2?2!2_uIqw zozYMJ@VnLH#s{vuNS9rIvGRPRD{j4BFZuk}>hc>8^NrZo%F_?1Zp(Vr=iH%7pLVHIC#s3JFk5Na0*3U?kUhk$I>@lH8|pQg9y8xz-`)bHs~@Q{g-kg;YmHD#t)@ zOlDHTLXg)-+V7erAB~igw8+6O9mAox@1D+THiDkSwp2| z5=Z7GzZr281y+Xijn%A6Y~@D0smJR*ZLVy}=sP`Q$v~Op2KiReSjE)usk1TCPrdan zjhO87hj;2*zW-lprqNf(GG(>4#yrR4_dKEp-+!N$&-Hcu>2>}7&;5zcJb8xtnogcr z*V?%aR+XW|iJ>`&AaNjKBS6OLA||lk*LaY~Nn>Ow9`aq)<9lcam-uw&S zp*R2FH|nZej!2uQ_#W(QJQ}N{zsNIc6xCZBY0QfBycgUc|Ibzi926bg)zpnQ&d7>Y zwvAnNd1-V3*ya|%@GI{efibxo7!ENvC_;wb&@(z-Zc%W?>3KyaGea|7DNNUJ}LPg~`5ZGK}g4$^1YPM<`GYh=ToFd>sJ`qIckx4$rzSGN?JekHJ*D%Xu z4c_j&;eA9ItI=@jjEenxHQupZW5#pt#G1|?Ur|XXB@?vt4w`%T= zD~m%d?BA{b@ZLHdlWQw5qKtuP=?q>;ZbJc`O+al5 zfGPyaCK=0Ey_T!r^}q*}(X{8lc4c^M#BueI?b49#V5vYiD9yNkDPG=e;W8~T$z(Mq zXQr|!09#OrjmETK`&Y6ZTDaqO>EIE*&Wzu$7WKhDc|gY=S=9PkUum8LR(?O$!}qS} zk$cyaH|qLgwqyqn7Sdo%zSR?lAQ51g6+E+a{N4}iy}$4adgohzN`LjszoglCN-zJM z=P9cPJ@N3WHuzyU0HzqnfM_UhD_^bH!bYA%j88mk1c(@D)E}m?40zW5V5}Zn+Rox4 zCx^?dQfu%PXi1%wbDW>_)n5r(T^uO#?bwLxy89!Ks*X>O>~CuOj#8aoM;$)sIvj*- z_6O?G=Ya3LA@?1ZQD7N@mqfQTc^ngXqS94T7$f=SM(CojfjmX@)0UVSQ#PdJC1$vL z43>)Lhv-uP4N24|CN6UcM`JJdI&~>+l@rHqD^a#&5Jc={MhOa#g`f-+1MXBmZQ zS-eR!JXh1nhgK9fR@92C^6m6P51rMv`CM0AJFoTrIc>6XZSuR{CfmXu&oJP7bI6j# z?vQb5LI#hJmrY=5LOcOUlZ(-!kBnCp2cVOxsbSLxu)oDM5uKBm%wjT6T#91@RMntn zC934=JIkHEMU~$4?8|6k^auft0IS!yk?3RSOzEYD>OIs%^Ro5`mslmHgxTTUq`)v-nSpLZdVH%hsRJj!Q4o3%>c=^y2^c z?{)Lne}yjn>^pVI>z}XNzvR_=(|3K9zUD{%r7pjMZ?@hlJGuem7--Dl#F!taN4*VB z2v<4HU)9>#Wj%fG<2rHoV_JUbVdd+O>UCfK8u=R_GI`h6x}ss~BLW~LM=4znE+2ca zES+S=5-@Z+0IL*O;2SAZXQ|NolcvtGkp{<2tH-2AK5|a0C(fxhKBI-^iuN7M^w6=h zI(~Xpd-vwL;_3yRT{@`^erVt94OqZO>H)AGtJi=%^^kFqs-X}Y+?PUL4T`X#Af=*Y z@(VM8Geo1EVefh;R8y3~6pbYfC2lz|x?@o#9&zBLjH*ghAf%l6Z>gO-y0S}p>RoT} ztz;=Gt}$9TMLDn>U|BHbAt*B?F1~A)SBK&ytGo!BovrarGGgV38uB_H0-`b@tW>>e z%5vI4A(M!@dV{F5DVwLL$F=>?c3tuE zm+B>N{$joE8@^1h{LNl^lGOy`D;rxku2De)?-0T6+4F{`42# zt>65SKhPik!e8i}{QmXiM^9)b@2lQws5dOtUEP$UCGu^>$6p#}a;~^|76WkZBjX5P z0Ib{TYQ*dxLy;F$ceAGTrA#YlN-Z5<*T%^usk5xP+OqcTA8G%kvwDh^_g#PfxMtfy z&%I$cFO)Scudi{s+GC42WCa_lKOAewvg6xBx>m^+)IqfMLN$itsf6oSdj08~)0pqw|igUreQHpbeh)T1u znlq-HRgN8)BIP_QRf5b8-*6{SN3CttwYFkRNLCPl7n)5bUI1uAjX8lEubcpAA7xc| zuZAbyqqz8f+49F^OCOh39#&j^N^yNroVrN8t|GuHH+vecchz0)X#MQEp5_PWkA3g~ z{oxg2;G0aiyNCUn8!Mr7P2-;s!n5nuCscupO|bBz`4-qF#~D+=wnXikqF@97UKRT4z%oR|0f3XzjqHD?GBvyYQpFu5@<>!QBMhXQXnCC;;=yyfJtvbaq-68vYVL6P#eet zTS@lJ6qIEq2UU>;6eT2)51)y$e7{~$c)6KwnXV!O5tNX1kjA_n{j+U?Dv)9tULtOa?|{_ zk#_AJYu|y94jmoq&}C6Oj~0r&eE#_DkLx{u^r&VV1^1uTmDeoj@h2YEDnB!9@M1~_ z8*B}SIMr9LQ5ktb32-?@`AWvEQ`uwa;PLp0Af@3Q|lQff{7dCRM@#m5?)dm~fv&IY6s{jD?wP zT3YIgmpuV5b?uFpC<3%$Z>&*&tTAt54?ay*)S_yQAa6U<3TicjBEV}FBjq9T8_!6~ zD?^<=E1g@dYiYUA%IUFI9$3`)_?il3s?E$PZ_i7ip)%$w{SD5|OMo}#NZbFSu&-F- z%>mzA16G#4{GY_$092bBeZbXM$!Wwopvz*WT{E+K{P7d|;qUnsedMkO)Mkud{Ds$O zu8qIO5-0N-kB}h-tBAu(CUE4wiX{dZfxsPV#S6oEsZpj~@P?LH8-^Ke7W-Lrb? z^iaS5KOfW2{Md)}#6wG(pAWj}mOZ-q`dxbXQGWDZTh~Un%eJr&4bQ+45e7hOq%2zRRLrY8^6GnB27;3-5F8M*(Q zyT+Y|OL4Fu_b42@WCZuRq;X@)p1iFwag>aVysC6bTmens&71+MEEr%2%Cn4BsHTwD zwaf|PfbW)Ov!;b@Z4J8vjoID}0oRa;AAJT`RJ}>R@JJs8t3<0VWlZQU+pO8vm^c5J zm29L{P6n43Gp(-7LUSBQ)U^6kU+eduQSa`@HN5vxjh{R&I|&l~|0%S%qIhmqadnLo z!VX)>O~BpPn7O~v5xWf?J++v5VZlT}*;}7e9{O(`r>8Dp!3#H!h znj^a6(ze`3CC@YhSmS}@AS*eB7r=_>eA27LY&?=U!Y=`Y_uHxm)$6%__UAsTAN!HJ z^wuA`OF!{LAJ9AA_M{g1IbfEqFT1j>7ryk67IyXZz=I#t;>wCvH@n)H9Lx9NgHg## zD^`U6BKL;LzpKV6R)L#~7)zy(30)*k{u1zExm}46As?rMGR+O|B&McQl~qqORYQ`@ zJti)e2lrV;CLzR>A-mHtaZ}Wjl8JaEJ35i;MIUl=FTqK)lFW?ni2#{03)L2pEl@oV zYSe2Sk@tA>8YgGs^suI!N!sVTYs@OqVU;LHOh6(WSgG2)wTJyu(K3F*m1<1JRwL(| zEU3fL^!$9OW@D%lz^$$IbZ)8Cx#haft+kniEw-YC&Ymi@e4?+_DR_I9Cz+h=vn(QW$N zJFn0U*DjzRh#{ucYc!B1kHEMju%r@Q33$b1ji5N9h=9TY#ydvyvzg{+3eB|PbD0hv zXy}S7W_0VVyY=!{9MQGU;k0n^F+KF)16o{O(kkCw>ufRo2jv7VzPkp1dpM444NGnl zp^~j(gct+&_0_5Z5YelW{6dscMg$Z0VoX4EJz6=r?KIKU0W7_d@Q?!q_bK|yK-rUn zNy)kH$|SftQL6JwZG;WY^#;cG zOw`5K>`}qD)v!C(0D!HpbyPA7OvdUY%`(|~n?5s*gE`3fhT~hO4#+IzT3+pG+m2G( zcMSOs>TA^NXq6Rb@oWaT=C!=GU(4%9w6t+hD;s;5mUTX1)Qk}(816D+1Rh_ZEe8v2Ya`Gb{000mGNkli+xh(bFeRYKd*(+J?WN`f_mf0BN6o zhH3RG0apZ2QQSVgkjBKVWORc3wjRrpIF7~8DEO)su@UuA)rGnOSJFk5sA)p}*V8Av z6h7Gl_#5}fOC??eSIMQKEXv6abVOE+NTsVHUXD~cmF{S_O@?IDk;}|rQRaV;gNd&$ zQ{onsg`hy8VCBl8daclGdx6zu$nQVcQg_EouJ+dH@8xZFdhlTiE;~yVwV_(GHGn8a z!sLxX{R!>l2j8MzFqwiLdje204Gtd8v~$N;_0Z9vv!4Fv4?c*iDNo*?wl4^S9w8nsOxE!@5T*&O6YM6 z+XGyE(8R%|SiqnNxS+DcHRz57kWjP4CdtWbkWoS zEcpu`mF}__lPf*gqFhns$jY}>jaT_(sOo8)6cg_36DXJgu#BytAmh|9C}Z-~icBqD z)k~`bt*np5jz-(}&1r67M!n6UM$C{6R<8jc{*eLrX=II+q0y)VxJ;!5DAU;L>WwqL zJ)(B+ZK&4F7!e>lwyt{~T++ghoUK)^ix2d)v%RQh1JG*~^O-tt*>&z)6o zX;FRT@y0n7qc!bl_jJh-)3)7FfA;=+^`{?rSU>$6cj>#n?`>K<-4#DO>Go^3YX{$b zZN|0lK%L|BIn6BO^55tz3+l6a^;wCX^LZscCspztH0&EMlpHGf&J=z(xj#o3rrhu{h)gv%QnTIO48ZL_cS-as2r2ViywBl;g{0IGat9D^YLXW)EA za_&HK9XP{(ez%zJ8DV9T41HAep`zb=)deQZJb@k!47G_HA zKLiKJ^`_)2kb$rglx%V!((MQJefv99+9I;xYS1-}N4ZAOuqQ54+9~j%mhJIw&smHf!Uk<8u9@zP&{}TWXF5Xamww>Qc1cZRbAbTK+ldP^AzLDGxfB!#TrjB!L4_Y~@NLp&CCb(2H>e@Txc=w^r}fa;t~xbSoDI@Krg9;uI~(=XU_tK z?fd^kKl>XW(^JPcWaCoX8m6NQb=`W=g5LPN{krNvL$mdWO-%U2fRuVFuGG&w~abxXy-Sa{Hgk!4bzn*uADuSPwJq*1C4D0)n)(lYLw%lO!dA(L3avaGIFv&Do80BS>>jh?Q%dZ(_tW>!ZI zW!keV@S|+d(|n)3{g0p0PyOuu`mb-jPygw^-3#5L@BX2W>-#AG((gT~k3F!em5s41 zn6|U!eBNa{^trbm(i?Byr{`Thr-fRnrj4|7XH#`fF|%CCSaAY8T2N$M)?QF=wG=xz zm1Rh)?wFT||BZ?PE81WbG%ig;w!%Ch{)!O&aL=3$VXR=Iw1RbqBlSjr3f=`deJ9Y< zM^{k^ph}_Q`6F`Fpd2Gh4l2J-SwTcMWvX< z%;db@P{``aobp_Lir8#7)aSRe!9ZGG8R_nipVrFqP?sFtrI)?rBE9I2ox0}ILPz&R z9oQ!ApB-ygbEs_`o@}d^+TN6QHiHhZQr&QPn_hnHetpKRM|9)SIW4e)@or!uMpj~R zQdw7{ohz?pP^kduEN8SiVQ#mzd2&O&PShsjDRDCMUA}Vk99*o}<1s+w^%0%QsFL5p zeA0)E{vg9=!_gR!jai+>Y!OF1+lX(hF?^^#U>g9i;kX1?P7y$rfJ>C4IQa)$k$d9C z=wu8|Y5aa4REiwZpiz2<^3zB(*BUlx8IyPcB-EoOp)VErL#;$yHDwo`pRN&AK61yK zY%;XyoTa-gTUt?XV_gHbLnW`@ERHqT9%=8vS#|h!iJ_*fsHs+K$sA}! zrsiDE0ZChH9HaMHC5D{Xal)_uAm=x*$Pck=`p{n;*YfEezgNxa)~mPag*VLV#W%F| z(i@t3`SoqxdHuXzd*dE`)@?`h`Wp`Gwj88bh`6p&Skw;Azihn%$l&158CD zQ^BfQ)TOM(w9A6ZI)#PZT6<(oo0~xc2NN@R%w#Q>L0J}5%Pg&0^`emfhn3A@UdN92w6ZDgWqSTAuhRTnP3xytwZ6El zVQp%zN&qd-GSyqA`8|b3ag^TjrIemQmMJN}O*w87CtmJu?co04_Ef3fuQ+{mB)rt&RaL_hn1l2jGJe zz!!CN8NkT!H~mm&IWnLr2SWzyJ`}??nTdOq6N^BQ3O}b}mSJ_GH?} zDdDyqO#qQ|U;qe|^Mp0pHB_&+RcjZ@8bP&Ircf`~8s^fr9b%c&nY)i`gTtF4z>3^+ z%)Q6f;-G@xPNe-ql6MT%$ zw}Zn8Pi6GcDM}H2>74edL-b0Q(Y;|16sdDN%!p}(&|~A0*U<$wu88TyYuL*P)wCtN zIc-C##uJ@I^5nQ@I~bj!%&c-Ub`hc|x7q@u>s(=m7P0_m;vgy@XHbiYzia-0?tg4m ziyLBFR%!>w?w|e{*XZ1%r?s)P#=!>QVwU9Cw>d&TeCfPE1FKI|VD+oFncTCv8go%| z2baD1HvsAk|*7o@^ zpo*Mins)CG+O`w>nOq&VbDdF5!`M)%x-8Ub)7Bh6i04gH0flx=VWzG)(^kIks5Vda zwZ2%Y*Do}RIo_+Ow7SZyrS7nz;E%*zhQw{CPCa_R(G|2oEpcP#7IpqgZQZ)W8ht7|r+-(g z%Ff$QgAk@+5YHZi2hzzS=nnL{R7Sv;5wr>K_F6ysSYEF=nw`ar(;mHmCP(r zCezND-Fo8WKu<19>-;uUG;+QE4bM?rS<@=tUOkTH$GnRDNWKja4qrT{_IzEV7?joP zYRtA&pUI)9nFCF2yKIkoo29xdrHtQ{vJhlhVBVTSj+|%8*p{Z1tXZhm&NQPM_A!RRa7tw^O09UFRM+r%oqVA8?f_6am)=idlp2u^Qh|tcGk$ z8K@j!xW?U|Rwqp^<}@#rQgMt|OS}qI02AOUAyX;?qB0^ojj3}xoS#-bMU@amQH?C_ z6XkzOZt6BEhRML|AiqD#^X;hf{yqMvCk7QuWw)Oq3R5(eG?et)hF60V(*o=e z@aM~1ztZSe4L~*E8z6P_l=G^r^83R}zY66hFSGbVIEP`|B|+2}U3_K$_rn6u%(~NS z&INT_A!$3cJQt^0d#8*SwU`{)Ts-eIy6>n5=&n z3GVY6S5{Onm87h7>t&V5+fjphGTLk0ITlFh=eh%~Mv35kKVH>O?Ao%36SFoOuvsCQ zp`WSwcqt#rXDYWra~aakiwy@=b^>coDeTr!?b~`>G;nk}$mYtW$KA_{-v(CmRWg84 zre2ji8@lX(*;QTjoTQ^;Lj?=?mxcLM%L?v|x##TQeP`TC8`!|K@U~w|G70Erxcj#k zOPnPGcY>5}w3Tkg^T^6-7Pql~^7^oJu^La#ZFY7-|& z8CN?cf4I(=DOO%ps`_bzXj-tA$FfmwQQRyzH|K!5gho9<54TvJ_mz80xt<3`8Ir^PV0Q$sQ zkoD~jD>2^Nx%oobEN{!Jv`bCImr5(=nnRQni@RKm$z{V*kAtj4<>rW9t#aU%Km=C&1eYPkJwVj*DExAr{=B8&_ z(iJ!#<_>zSJgg#A3(%a$YaTJ($7wCqH&Y!ZDmD}^exPr**t+Z*B|_tW&P#abUVIJp zJ_r#k&3RsWy5_a@P_lj6DY+pA-PC&Dnw>5@ZTM*245Eg7Y|w%%Og%TJQ} zHp$P^(p42b4$PNwnJXJ0`t?dTGyxYy`YoQrjM zz$&%ZD^?A1{rm@pb+wGe+r=lvxM-|8#_?pNEn&=Ce3!0XMU3@_IB$$9^hAmU{n`dr z)qPPov8(LJJl;LE7&S$1_7AmT975u=^STkuYR0@H#I|MN1^$h49z-o{|P$RCSNRTV%hl4rXVfrJ)E_qIQ!hw?EI@+ zq$9^eWu=BI-{DBn=kf^yD(LghF&MIOS@H0|sls>lmVT#;iY`T09eeD;MIW_sR zEv^|R#dy42&HZM&tXN`eo;M*iujKI*nNFhemt?){L|v~uWWw~3dE;HG{q7~=Fq$nfhct5wDr*O1JF8s$5VSf2E{sW!%P{oK3XT+eoxGH0$oDWy7gu-?YH_uURKRChg7IZP+avnCm^|@wSVUWKx!i zYyEE`{aH}<0+cjkmT^Gg@W&d$Zi~TPIt166Ih+wK5<_Po(dAiAZy8*gCc}zmL28!iEUU*nm zt6~JWW^7-!10JJmygIt?h&RewUj7a_9mc69b&jasvTGk5P2HAOV8H9xahWfAs$^pr z`&Q4A9=3QN8M$xh$kW@lu(z1$p71yPK21}$e)A{7KU-+FWK!jJ5duAR$U}#GHbu0! zIX8*FmaC#VnVXdrJmovv(mzCpBY|TCIt%rl)9zrnlv$3z%O#%svF-uw-mf0s@}Rdd z@@?bBMAowLyLB1*(!C8|rytqyUb}H@kFR>K4mYD{Cu_tSng!`6@h1f^;Xgq4SLBO> zhYEzz+15#w7COzPmLx|p8Us={OH_|)(=VE`Hq%Vmw7vdEvX|hW8cHhuL#de5wTZs0 zGk!{ol`T5yJYp`g#* zJ9lM{dyV&Thqs>XOZ3KU&GW%KI!n-9Lb?+0TEiKIC=z5}`Yf&D z3}@`W5>ON43`98%|V!Csw^!k2`2X&5nV{QqFxl&)GwBqi3JID zlJ8x+#lgCdox#p0C+|cBLwN~Wr;d#aN59>SBnvJZbsx6hh23U2DkQ$Jpm>n%ZQNwj zUN4-zvb~hlJdr<6_`GI3hMjq)oW4fv99Cl#*`orablh62)j?Jv&6731A$m$R4ZV4N z7CK&_fkm5dmFE-LIQfKGkOrC4$8{51gQ49Fpe5f>M9$wdt40i`(XEF4hG< zQhuFAkHU-^^!EMyA6K6891$`ia@ZSJ)5?$8t0w7XUQskRj<lPiT+mfHCz6QB3{N^01?>yqH@vw_5P6G+kVH4moE)vIbqZ>4lV7f3L3_Soc3@DD^}1+--%I41PM5QFaf1sZH@Yw^a;|mD(S8=>2%$5 zr^akIs#k1nEWYzp6eXE3GTBbqic41z^EmAXI-i^#J#aFcPe%VjL;tj$yZg_tZgf3# z_9o8s@RN>@W*%`(MVaDRsUT#|w55U!tbTlW{#s|#RXl=HH1(rnP#z9Vvs8rLq|&g# z>dRgIK-bM9_x!RBzujYGGOte6O~@gj8d={2HucG&U)o>{)T-I4O&0PI-;FK`pY-Ri zPH)sZh|M(D65W79<%bXSUty|NN+9|2teu5B)V$*7?sM4(7VS!@)mtAHJBA8(8S!a% zO`b=HBfdILGL`5T(}?jWQHLj49ne|H`eG@PDjlG~d`K`c`Zj~$*|sq|(j?07bowRh zmq799Jp+i_+T66eX6Xbd_ux+Ql>rKw!D+vP4mrNf$^$D+vNTT)SKZaeh_&ZtvFnfU z7TtNeW~K||1@p|!ZhE!xuMbns78obf=5g_x9Iu7mS5pnN{FBp~_jsl5ORtXmg|%k_ zySn4!F;bSnJXgoe{8E!F7+LR(_I0;R8M)~*|Jf}e|G&|8^fRPoP+y~uM;Sf3XxDji zdNc{sJbAT+S3?PVv$Gt1#*4}+T6=oN$zk&mF`!B~;}`x(07O6+9rO^60LYnDkajG( z@Nc=t)_inK`45(UBz1)k&_xQ_Si2j>9@L9BDi@sCD&aAi{Migr-^M~j`J4r>cdqH| z61juyop)jcXai5r*ZSe1u^F)(Ra=Uj##fK!-?pji=kz2dPd>orQDa@`bz}dT!N1%R zIp#w@aq_vDHlyVROA$_8^6PkBE%%YD^!AJ3NTX+Vp~prt_e(qe@o-lJeJ0o`6L8%s zp*fP)R`%F)Y?lluhD5N+18Pem_kM#E+721&j1?x(1+KNQ6SerBGrTyP0wPzmK~K@|e_jn)(Y?<`1y2hLnKQc^XcBv;N+liG6Zoz&$HA$5qHHu5Y7#jhlitjwX!eELnvFD{(XKQ*^C zFmwxhB_+jO>%=p;K=racVrK~k8e*Sg?dJG=AFXgW5rN%|!Be3l-?wG?<@7br&>AO3 zn-TQjzx@l7Oc#RJGrQ!r{-f0Dw`!2FZ;~@yA#*Svm7NR&p`u?SR4dr|w*WIuxb`x| z;&tE`auXLqHro}$Up54@S(fBP9dpOpf3+o% z1Mn)P{_(sDO7=9X{0DN5`eC_TZL`+cfX}+f>K?cxV&ou=-iJAw%?^_ z4PW^e44xWBGTaj|+)B`N=Z|o}m3i7{QB7iQxLP3`x#%1=Ey5jWYG5=P1H^T|j&*BN z^D%T}p`D7f8s7-tQxfg&hDuhmTnAm#AIxk}brK1HGn!V;6vCzxX3f>gGEoQ`x&UHW zfVG=ZE}X>aR=d-3O}*5Ev_Ah*jK+wVmdI^=j8|03pcL$>!g|Q8eY;PNy*z!R3$ai4 z#Gh2Pr`OWm4*F4$K~^wag_dHzl)uvB&k#OcIWkr%A&6mkQ0VW#OkT~o-R*%iWW}&N zS#Vn8rGP?Q=|2HUQhICZeH-536y1>d??q+rC@tFU&fTBLOaU1FD%^8G`~)@@f9cl` zw~I%1j)Y}HkgPK=Rnb`jgTU;pykG$X$R#Qu@U4%XA3Ot3N7~KF6BeT}E_R6o#qrFN zY}@LGTlXcgvTTG-bq9FiD>y-2an`psdq#wt2m5u`NG#G+jR*nUdKV*qZyD`UD06n{ zN1Q)UAgsEio}MLmvaOj>>rwLh+7$50`D(&jt=lAZFOqx=GmjW|&yV8(m?27eO-&+9 z{@c{qA?#dZn|m+A0JCq3vQ8n;tB07a9H-bHURdGQidkVu3*qiDSJrh9(e}-R2R`%JHB&l#B^L?=Uq^=W&y&-!e|~PF!MQSq}`2wK6G!qsriHU%m@216R3Y% ze!gnC@MYWq{JBn(&}shJoo@ZDha;9#V~r#Aj~wYJsTJo|2E?WAOz{-9TwqTCEbApB z^e@4YbP1+y^rxQ5b`7;YYSStqY%!%i;qNRYkZ=~zE#b+TcCNq&6r$YDxpM%BN7p~2 zcKf+PnM+`ir0NvqQ78bIrMX)x%#j^jHu!va?~r@tjLzrdR%vu*z0m5io%k{^)nhXo z_H^e;gScqU7Y{0YhTjJh?bzO#1?Jq{xdmcKz{$?CI{~D#9Wb^kKgj+xi>A%2ZZvJn%46s3Wn#%Z z^P`o!v>*7y`g88t`rnO_0tXfNm4C1^?k$T4FZQFV!$#JO>|N4INt@G%r+9ESXzS&V(S+igtz}MC z5C9qL+1*}B>fhx+yf+6m7;V)@9K$+~8-*Y^IB+v}9@E{*^%IY5a}WP=p@8}9O*6m- zXL&RG=zTdZpPwl@l9onvDd)VyZw3{)VSg1#k!btS%{jllcNO!SLj zeZ3H@`&o`HFj$52@MiGuSK=|34cqhG;Y-d${6T+x0#~zB1LFp@(r%hqHwM3hb6MhO z`$x-?enNHxm+wSq$4fd&ze2~hslJPS`pPszna&jfeF){1Q|%002f|bc4%iH*CA=mz z_~<_l3NH32J_px8UYUt%dThV7UpNd|Pgrr;ZX#Ks9wF2`7n3{Nnh!62-+$z`Ju*o0 zG3i@*1}~xp1Mk>bw^TV_24e;M$6pvPfsJmWJ0L@IUF1-r2Q(r*hsByA90aZ3JH@tWNj7d+ zT<3G_IYW?Yp*9C;MU`9WwmW34l9_~vCup+E0lh+@dei;A(&uAcb)cd&J(fiDUE<&e zc1Ixan#d>P1&vksp=CH)W6)Ld*w$Aa;xkrKb{?L(!C{5El)QM~Db{ix34BWz=@jce zrg0wL;(v;2uu;_kxz*^vv%4rs1pZM+`J`e0TL(2@=F*!4x%Ls*6kWDS^b!8*+V%pG z=v4E8uQs~>fOq^g7sY;u{tIku`EFV6(~SzDVk=c1P=AZTq~PX<1xp*UlqbGHVE$5% zXviQK7V9W(aJt43oru~wNN%Oyw4H^^_D`!_hkuR?+AxQWmu06FZ3ibsADYj$5X5)T zLi?UL>JhdV6v__(J0wdVP8D1aP;L5>YCJ*m~S+X~m`Y}VD?03+Yd4f4Mmrz-9SA9lX z2MXCi0H*}XrQ{nRdnjZEVMpPSx*(uU-4m0kea3lI4xxnj+wa@=d*MIb0A`54(mqq^ zwQ??Pqz%$1&bYm6FxyyMj=4s^g>C{7? zXs2u?H*#@2RDNaa&x-JCE@|M9aJkj@qh>#tzZMI^a=W6{^rnWt@&x@@(oq$GlCIe! zOLHh}# z$Z54tw>DWs`<)Sfz?w*G)qjCmxI=_$o2m6@dSM2F5gu9)D!&(M7J`MJKt4CDN_!Ym zzKjAhCKGYkWgeW|%9108%g`cikX&jT#z$d}yU*Y#IVUhlAhDd`R&b54MI@~=-AzV+ z<|%Ik#0~DASf>?c43WQ26;iLmg_@oJdzC{0=cOME(cWt4L)#MbUdD>&JO9iq;}()0 z92?PR0yW5>sTP}AUx^L*VdS&} zd>(t|{Srzl$Em+>Q`RruRcWx8hJTlhfZB*dQFfls;EDk+#?je{PmPDiZxM}IV*XKR zg>^9h?ob!FLCTA-fNn6gCEJa8n)r7!jvuCa-m6IKqrH~JV?WT!8?e<0E&b}@bj z!eVM@Bx__?XnW%5lm3@V3{Z#Zy!HHy*3TH^Z%vk$U|Q2Wz?2!Y79iS3!37HO71eydc!=MPH^6RXVL-W$|MYPNBz4CITcTMXaIYiAH^?sa(mh$#2c+o;w(hxn=$V* z@MA3Gycf;u2#hWY4F4o{Bw4R~+C!MOX_%8_iB$pd2V{m62x0izF4p$oKK1`XPe13F}8!oBXq1;3v z8Ptpl(BVwO4;7wP*(yi&9+`FK2&xaFPp=Bbkk!cQyO1=&k$WaT3GfE=a45Fe#U6H{ zy!z?`W&aR+&zu($|A4{$TeoJ7$&_)-YS?gb`%`xcrv!GH(0_m|M!+Ud=B3}ePmPb* zk~35=`#u)&$(;N+AnR3J7G)?b^V4-@?jXJoMsF@0;z^SHJ*9zF0Y!5NK-1Ibev7e=NnIC}Y*J+a6$F6$d&a3NAF58PZDiYn}JC%W{+z~94& zMZsTLpwM$e%%S2B_|$J76D#ys#K@p&XhoM%z8pt^22D}U39bozM2$<(X1|`WdeJ6FLE1y*=;kjR?#PE3ER3@`!|}1P4RkzOPh}JOcDIuk^D0`0{oTQYVqq{FgwUWh@lwQGr5DD5 zw(1Kpn5wZ&>fifR z0}NgJ?z$o0v4i^9j+i%+q1NX-P@3AJa6D7Lt}aKRnVduY*g*X2oRD%J6Tux;Q~+L2 z-%*J`2Hb@Y2Q|8gEGfzj?hn<;RH;ti$Mr!;l^P^4_yWt!{K0h(SebJPEElmSahxLD zefX2|#kQ6X%=3u_vb?G$yQyw&m}!}13#R)R!KzFbKHL$(C?HfP6f;9-agN=oU)Mf} z8D(d6ToJY10i!xJ)cDZ-jTu`wihOOwbqPYfAtqj6=7p%K=Ty008}@B1ZfBcp-K8Jg&a!Yv7zrMV z5$q)ai9qb`H;64%0t3YySC+q<2i@K>2;Td&1;|ThtG^?_mhmK7ZgLW$j%eUg%Q29) z){`v+r&*}5xrSFB3s;(X#=YUI_~|hh6yRGJ{&I?{0A@u#B$nq{h68OHt1^oB4~O-zClJtSd|<%CHDXTYM$gzVU?2rl5-hSVEY^= z)4F9-HgzbtdtRY*3AT(S@iTfGclcVzk?;qLzauc(p|{q2mDm@ssMpa!t+}&P?7hub zebcGA3t>-Z$?*+g`hzx49U{V*O!p%%T`kvF}?1n;{iyjZgK8-;n*B5q$W2(zX9rpBm?SU=&cWTrAQWdlyl^W z?Sl*JK1cQlp^@OMb`GkKM9bccLTmYY42--VVV|b#t?{KmGzV`#)oxprE^$kX|7&4{ z+@p(KX(S3H-PU9=?J`k?5Yh}D@Nt5?25IillAraX+MYcT1#6|SAgwy;@n?R^S8+@? z1JMK)JGGy}1yhi=WCFudKLx8~1Kc9d&kco-zfjSJULHIJL+QzG> zp6@lSz~!+dlaO|z@kg|n0;vA3vTcS3Xm)fvQrirN$I3o@O+_lr4pIXb16qxO97Vz@ zZw9vvGZ2S5fPw&qYv7ac>**9_ETenZ3Z;=ga6~FVvexI{^lWS8Xh4>Gq}9KZ}roX9Bq zzlN*C2pMLW!@T$3g$lF;W?*3*1|8p;JCn0hD`j*UIDQ*B+5@~Fef@{f$10Dil)#Lq zj@Ks&~nL$g5RquRxywNEA^PJ zm&GizOfvS1);!;tP7QqaZiH@{{=)9!g^OM6R#52O@Vm^_tjTqu#QIQN&h{tGJr3VL zi}ZX1Ea;Ul%O3;tBn5o0Yc39svYIk#g15TtHMf=l2#hZjwDC0c1G|yg+gO4pWVIZ+ zkC(GC<2^|(vqsruR2(GBhISZHlfF6nb6<2Bo)Kb6@0-}YaTGQP$afw`@UV&R#f6wS z#C{-P;_#!$N!}I*+2nQ9+?!uwlCK{^Yyp83%zN-Dx8z$}?1RGuKu}R1n?!nyat4@o zp$rrnd2Y@di&FbkP8uRJwE29Vt=^4u5THNM3&%*5@JY#+#-V!1J@adUB!_&D7TLh} zCBJpbyjKP2STsg>a+ni#EWM@R{S&--KsCPo#isx2Q1FeCh3r5W%r;xA?4td7RTh2> zO@OQz&az<%%*qx?RCCAumfU>0(3BIhnjd56&6Q+)kkkf9I%)Uz<}cJ= zWxFQTMRv?x0pZVyP-6*#U4M05Jpt1|Nz(6BF!(HVCP#*4*>CMIS zWEtm&Cznu$xQ`{uiDtMAH9QsHmVL?D>4GN0@ynk^6Xh}I(0OJH*kr~_qNxHOoL<^5 zo(A-AJX05hcZ)p44BCwBgF%cXqVClLfW?|3aZVYmc^*s^W!K4#m>)1w_6PWL|0L{#m#)K94E;fXEij)l+(#l(Z`z zyc?YQAf_+&!+&$jvE;%n$@1_hoQ_(SfdB3C&^j7I2XWk^BgiK=4) z!-M8JhMDBxr8>>krtH@SC^%^Sr49zxH~6t}Jgw_!68sxDD&p!^3Ia9!8; zyaseX-@U1iZ6DaiyqCba|FQz~nzs~LLU|#Udth`dh1(epE<6ggCGK{~i5o~p$>{K9 zGIRa54V927{vJglJx;H~ravA-J8Q-zP_C@2k=5ewcS(8LNY*@SYOzbet3I3zz-poV zloD#d`n?l2uF{t{f5sT55DOu*&ma4DRWt^-BV5MZ=FK<%K=m1oCI2`UJmXy8hnyQQ z#W82^;8*HnA;(7UGZ;7mH&3xa4e)I!Vs2At)`eLQ1Cjp#jo(n?S!IOpJAcrjA*xkj z95;zOrQE4#95DfGeD5;q(wckG-pV*;LnGWZ5S^UbOq1+_p{QD8_jVNt?b;*RttB9s;F#Zt_(uXDc%f1JdXL?dW+%3 z*PEQG_K5RG|1216?*31>D^W5wIu!XvYx^^UpdQ6bKhCpCmB)H2zEl9Gkn#r~KjYu2 zq8fGN8(Jf(&oKo08_=%Aq>nQ}{1qM*i)WGNf0_&LxihH*zND!lb~1lmf%Y~>bvlZG z6v$l%AMYlyU#(G@)jSv!&IhC6g;#`J711P;VX9>DRRR#Cda5vda<##KSMR3PRSl?Q zyh8*i1K06&iQg7Pw;WS;j4|-U_DkhD0{H%Z2iQ=3)NjKPuKgRZYu?+1=}gxsn2xVpufsPs^yvbd=x4Frn)2l zHhRA!X!(3W&i)E`e-iq@zCoicJ(nE^$zKJA-d?MSyx-<~5q&l{3f^AS2@l`3+}K~W z@1>(QUQA$D?$>e#9G=y$q+hj-5j`*WNOC;eqBg=okU`oU6wX>el?-@4L9lPbzm8(g`+`8WSugF$#1;~RtVfPZM|8L9i=PektJ3=YiR5qUU+ zc-})v$i3Q+b#w6r5Xig9>nCfbP-e)qVEeV(*;kj8~qTozi|J5J8km0eaF{xk+1LZ7-cgi4yv29|Mirk(K>cg z4#p@0v+D~MN~Mge`sHZ&S%SR{x0qTgUcU_2B)x3=?>i2v zugiB`rSC1z2H5pNJgbp^0dIdLfo{FLSFbK^?R$cnK`7P8ody4O8jb7`)b&;W-QR$W z{|nbu9QVHE-Fo|9s4Me-L-4R0U!=^bcyGq9zE|V55rO}ytAFVG{|{bby0HKN literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_monochrome.png b/app/src/main/res/mipmap-xhdpi/ic_launcher_monochrome.png new file mode 100644 index 0000000000000000000000000000000000000000..a51f1164c52001c33e33d1b9de6b7eef92c0e3ef GIT binary patch literal 54009 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 diff --git a/app/src/main/res/mipmap-xhdpi/launcher_icon_foreground.png b/app/src/main/res/mipmap-xhdpi/launcher_icon_foreground.png deleted file mode 100644 index eb6f39c68423c0259f1d03f5811c02d03550df92..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 30846 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 diff --git a/app/src/main/res/mipmap-xhdpi/launcher_icon_round.png b/app/src/main/res/mipmap-xhdpi/launcher_icon_round.png deleted file mode 100644 index 377ac876107eb2eaf0297bac3d9729166beb2bbb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12209 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 literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..3cc416d68e52bb89e92bad29dfea3b72d1f62d78 GIT binary patch literal 92076 zcmY& zQ#C!^_ug|(cU9l%xf83VB8!efi~<7#gDx*8r2zv2kotQ85&t|fIhCD&fx&{2my*!( z0i6Fv?!Va7Uq^l|x_f36V(?2hu2&C9;;4nF^bBKi$_S z4s5}Oc|ZFGK9>&&e7b;-k%YrAQv*p^hsmKu%t}@=@oxW|9Sy#Fcxd>r(Ay0wfW;xW zdDdX_=9}Nz?XThwFaEmTwo=zfnx0$@FN(Orn+FqP6}765w|}1f~k|D_AzqDi#uM$(f@1{KrCMEc(6P z*1s4gU4LVkbeW)@{lkUz{f`0p*HL2@r&hSvS~9)k=AAzl{oZ2u+y4xR`u`db1w6)A zvi}9Oe)-4X?RyGT=f9#ndhUd(j`R~C|446%MJ4#B&X>O+MM#f&^v3^rkpBmo#_{XO zzqYG@_nsy_6?xKcqXzSTK6w6O{KX^MKfdyhmFgu13-(v~cVYye|7ofE?H|kZQ9}Xa zzY`-$_E$JDGF2zeqkkmUE&qzYZfQuM@}Gl`e+^VWYChi;-k5j%(PiSFE)%48=B58I z2LGEbu}(?U-~X{}|Hsl}B|g#*3IDIMc7I*!ZWTuU$1`E;FUAC+%W?Dnl>dMGi>Loc z{fR#CuSxnqC2I7)7}aNgX;hz0u^xW-H#tlHV4oQFx%T{R|H}S8R4tSI$L)$h^f=3Z zR73wE50%tYGW(~^%0Kb`zX6Xlv}3BFnJiU*VE&`8+xr)M{q~Ub!@u^`U$W#y?M4lj z|9oiwowA^>h-@_faM>LH#bt9m%%1fhuCM>(zMO)z{ev0xcR2ZVxCx8PKl6p%ztk6Y z>mv{TYUMilmj>of0DD&VKN?4Wm(a`6_tlZ>!8;6=36t}o<{y7uHvd3m-~P8~ibemf zRs^41Mp_2Jn-v>)qkX+7BM~A5S@9(~}8wVac z0Y4=k>rxDUXinZ$KV`l={&St5 zF^4X|zP0KpZ*I;TEi?{XEvy_kyc`&~FLFlo=xc6%U)|h1*zExGTgdTkuxf2_;yF6| z>1qBY`<(~H@o7ENYpqLQ$4d8yo@SFr zTa&@#@yeh@#lEL;c1CgC!Tr{z7sNfqFN3(htk^HkTzvF(2hR^CDcJA$2l`ib;eYRb z=x;{vdpfu>N&3Yv_IY*pIu3F04lmFNy4oC2=5UKs`O>9(f7czT6TbVR59g^H{9GTR z`|j>te^s*yZ}{%dyr!3?^^AySU#Hr^Bd^LA%;w}Le-o3pFv|DODX%Z<@9rFSq3g|o z7ACJlBnrQaKkJ=R_-P_#JR$Ak-eC?bc9hB@24LJCWjsZTRW}DedI*=Sy#Dl1{7vn0 ziT#qja8~!_?DLZLD22abZB+B~FOAnn0vH#ktB<0C^}*+;eNP{Ew^m;)da&n zsg}Ir?1>@2q`NTRoej3YeZ|>R{lNOi$6(8f%VQa0@Kb!>Q}q}0U0X-;9sWT16_=;4 zY+qDIKfQ>nQhW+@s|^gsmB)J*81Uw* zdVt~db(;7^cMa-VYm$6U0uB64AoJVr9DO%r!NoEu_;5zyx0aH1ae^S(R>X$1dW&Q# z>k+?>G%o|KduTH;ZHqmMtrE;6ECwxWhIChCJzo>`4i>mR#M-oPse8#v$~t~%0A>R5 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�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 literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_monochrome.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher_monochrome.png new file mode 100644 index 0000000000000000000000000000000000000000..dfc99f66df6925555eadf3f0898b0bb2d6bbd924 GIT binary patch literal 104991 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 Nu{1ktT5aqR{|~hB0Av6F literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png new file mode 100644 index 0000000000000000000000000000000000000000..fedfd6f420c6001943aa86a3009a6c38b09f43b5 GIT binary patch literal 35778 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

xt4NWz~1G1W>0Z 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 diff --git a/app/src/main/res/mipmap-xxhdpi/launcher_icon_foreground.png b/app/src/main/res/mipmap-xxhdpi/launcher_icon_foreground.png deleted file mode 100644 index 7d1780fe67e829bfbcc511a505e0418193a7d30c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 72083 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 diff --git a/app/src/main/res/mipmap-xxhdpi/launcher_icon_round.png b/app/src/main/res/mipmap-xxhdpi/launcher_icon_round.png deleted file mode 100644 index ea181790ce838c1074643085c10a8f9b270e91bd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 23520 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

tM(U%M+J|s^GHzg9Hsh%p1 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 D^Ru_B literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..fef59a8ed18e905d9e7c6e72e54a27fa632482ba GIT binary patch literal 153606 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ÿ$O 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

8P#WKW@RT8^tqnWnh; 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≺!|M zx?s-FUb(Ihed-ZC{rpq9bYZM-de?b<$G4r=yT5*0Z+NKDJ?FFTKGW;fcW1rhb*=u` zH?Qk`-?F1OzJ6Py@j}mDeOi~VU+1;zoF}h2Phd-VJ-t3N#+ok|G?J_tW6fEw8O_9B zQjFuXW=*eNyQ;nYtJ+-eKd40n>@7B3<>$-gPd423NkLbDUH{#2~lyRnvJp=qjsE*T9PgzUqY}K%OY6+H_ zWkXl3$>KTKDMa#8ZiQ7Nw*`*&?$%VQJq2<}4**Sy^o?w+uk-voK~zv2_Ha z00Pq|F{v>j2!kK_1Z^i119(*5@WwnNsm0Au`xOlF2tYoJ!T_1zJ>Yx%Bn;tXKg_Vl zH^yRY2N(>@aZ3-}DZ0}NP$_p(oyxre{;Mz7m21pknG4S{gNuw3wD>k~0agJeKim|R zr~D(3y{azQs-*gdj|3rSNIjn88A8A%bXGw7EFPm+TCKbl@Sw%3k0fszJx!=b@699t zoHX00?!dMfJ2(dA%0WK7-xSz({-MbKKq47^{G#PMvp)7sIFgoLG`H`d;kCt07*naRC&3t z3uha>{^50f?b~+rO<#LP-}H66ddJ(g_3&#pw8N7~pQgHe<2gO{%;S3G3!l+rJT+aT zaosvtXy3odG1fuALZ080jz4A0L&iUbW#|sc=aA-h5c&2rwVtN4jHkCRe)%c=&L=*> z>$k`Fo$rRuUug8kH*V;iU%#tw{Dw37`mfp68{e>|v*#Kb(w-iF{%L*oi6@!Yl-I5^ z?X&KOG3J7}OV*~sl=WOSt{Hi)U>-C!UQgEh#{Qn3eEu0-x%mS1aZBfRliu{2O?~6n z?$F?O^{wA{M&Cx$ddJ&$`OR{T2E4DwpL;?d|NN(UB7aKP{dqILm|Mi|<4ebk`dPT9 zsF_+@61|kyh6>2kU;rJbP_y3LF^`QrE78OhN0sN`3zC9P0Y$#=3MfOA0N+cd6wOXP zBDUoKwh3RyOxCTyU1UWM*dok@c|;ahL&z+&!BG$h&Jv^A0`SS$87KjG2eu)QZD1K7 z01;?7t1g%zxdd~1xzh?XcT$|n>k7CyU1O_KI>IZ0qAo`?1zFv=;zi+BNj2~dgyQI| ze&`^$9?5;r1aEl|sE%;Ws1Vzt!o}cm;)X^Z{$Nyc)9Sft=s)poxYA{iOFd1jN52Fw zy!m(oWRsf%Gw9iExTmr8b)!P=-_fewGGyM!y$w-N z>9HrD)n|Az{M2VYuP;9KgueXrGkWT|XZ6$z&+5z1J)_S({+J&5;^%27Pw45(mvxz^ zi|c#)G@Av#&n;*?bNLT5;*}v|#2m>##%BC!n{`6_V)DT<>&S2Gf(LG>(A;s zPpvl(uIUDF`TC3c@(a)C(~o~ipMUa6J$?0xUZk1dq>=C2pB$!)=RDlF<`mhI9OBCm zHRVR;x(c3##;Fycra6`1eP6h#MIBSL$JqDKQ2PjN2XcAWmSJ1eE8ox|6Zd2o1?|fU zQiy%8RH#>LgEC=IaA7;JNa7r1Ub)|?^uqX<8jXh z!qV16F?$NHumYzI>=hQrDt{|1CQiVL4@@D78^$FaP=!cz;;_)bjRDGNR^TFrQCGJvH3rv*{`-eRy(NN!U8aoQV7kHUPIJ5a>&G4~o%H}u=SZcP~yaL;HB{OYUvVr%i&8&~cHD%*792$oo z@o7>XH#S^iFJi2oaR*oy&5_T5DYi5Fdh;}9Lyt|Jr-~_!;=r%>4wpQk%ynp3EAY|bz0$rrBbnHR6?^36Rq?U`;(r#ulYbifmipRkM%8N;yx z$GA&PdGcE25zPeo%s`Ga@(KugA8a(euQ%X;GS z6+L_Xrf&K#9LYc8IWB892WE^F;}T;=T(6Dgh8cR}mxrFuw68f4&!2-E{w-dOKF@eh zUA{`=ysXEc173JBa`L*}Vm@02mM7}THMOM15b5ZP6gBEP zbkpf6&e+U-Gq8D6veas!W&!RX^T&V;hEvCopncc5>Q`7b1~*FvR<_Q;_nL8bZ0m4y z9z?DUF=TLdf<_%zvj+14%%McS9={<6OY8V}6W#n*g2%TWcYLr9f*2%KG8n!9b1Ey@OQ#MA!A)EXmvf0pdRyMQn$uvMi zuV{`Q$8yHDoj1b;yuZ;ekS!R?`ONt(ZhjPV$z}|&f!Btx)FHH=EcR()dpzlQW4?8; zl$(V4eQ(6b4`>Q*9)~oKee>A+FA4X+d+7E7+Z+(jn|9r>driH0GshVlw>R(^b2T`p z1^Le5=gc?okf-SxK2!K9`YAD;um9YA>Ui+ZCB}1;nD#W^956*U!^f~7#sYp0o)c?^ z?~KN6-Hf#kyc!#yIbfN`wCxo8Lj(SY#Hn*z(yV))?&^34_#E&X}Z z1XoySN{lJCbI+Mv{MiJ!ZYa9=f&_L$TY$|+9YSZIFPTle9N$AxxGr8cZtB`L1x%@8 z#~nc}+qhtYd&nR;Eg8TF32weaFt722!0s8Wql0lA-2C9TvbN|523_#bzPEzrazr~g zvCOALTy(3`D$|LvlL>$@o)G!17_%V_nW@NS<&4?s`SL69N2-Cn{1Uvf)I~{cO58Q3 zednx7G#VA|E;iJP>VsdMwzsZCAwoq3Q=Th47~akXM=0##EHp6%Wcesu_|}KnYJ3Dv zD|~Wn45U&R56CMZK~BC2OPMB+hmB?#IMd9E=uujtn`5|eLkV5s$M~W-yk!d-i8mzk z-n?e;Q*?$Icn)v>6)Y?xj{hiRYF$7c;yG^7A~r$G3i3ij1CzrXzjot|37}%5*_lxY<4b zFgm^5aRp8r*d3RqDsmK8E$k|x#vr2Dz@qw1Q*R1@r~WKPn+7PMvmF8%R}IDpN)-I+ zqbQ+Qp-EYXaVDB$dt_Kkf#7_>o@nH0onr;&k{Q)EST16tC_u)xL=)=~RuE0A#P4HE zHlGC>-GYrNAU3~VOE$J1UFg}cya~p}Y?{q)&L$e0AoP^YZEDQMH^Xnb0yfG@*Nt@+ zv9spHoim7-Lky!4m=0L*G_xH3Vh@bW z8~2pPamZ#pV^?!`ZdsAL=jt^A z&(IqVW9*(MMguv~V4cefri?vhycz2_Wj>|@90%VSvKdcFQ({h$O&!1Zoaa2`%mLlZaTsIfH3*zFkFm)K9P>v$wXf}sfjaMA3&wZ6IiJIv&yJo)Efsm* zQD3e@>aWk4y31O!GcWm))PvpJT%VLKl`5)S)TpRYmp3(SGyoxx`-xdLc^y z-YWcKF+&d&9Il+GkA2+VRuG1Rs`}^n(uhNKj`83K;)FV9#RiA} zoXv914(H9(8|M_;nE`v-uup0MA8}%gaS#_p z%oKBFzCHQ{a)wrK?1n|H`Kba#-RcA+=u&~|Em6A^t}&29X1(n!FI)^DbfV5NQ;AEx z&kA1v(*}0uwK>xGTbc`%dOMQciJgGZR^Cshl6o4YL^Ym=K(a>HKl)RD6u`!;pDS8u|v5}ef zCK#KjR)I4!!*w65r;}bUEIpaG1 zVi;o{<9l7Qmd+hmV6(tBY#3_}y)-cYx&43z{G4&Dn-5K63Z7y=LtkO3`c&G>yvLfM zpYkeieliw0ShoOsO_t!7f_1i;6MG)MOT}2^FeR4*;{bjOgP%q&y{6btS%)dISwJS2 zUXHO~oCW#-&)dM(GiPUsSnG*q=*u>lH6l8=JK z{-$jK%ZZelfe3MszQEbm0C{v`jp=YjY18B}e6L|uXnuuU3mFwG5piOHZ31Llao90< zXxjz7vP<#55lZqA3hqU7$G~lc%(~-Ij;t}GC7L~jS6G4O6?CU6R=^8XC~OxlHHGB( zbYrtDz?WmyF-3jmC~gR_&62-a)#{CVP^$wIkFzT0QV?(x$v2E|DhaCa?NIm;$@&8A zbHGOS^QK_DGI7IN4Vjrw#?X3W_L^E*_g>0~xC zL(v?+*dW0R8q0!>YtDu@2YWL!zhIz+^&!ghXL>=Lrr^cbuM{L0Ds^w=%& zT?Ss+Df|{8>+#Q;F?MYFY^*b2>KuUBd>Lp;Lz;ozu%<&3b29gIPyhfB07*naRD-jA z8XI^oZ}Kx5#f(k-xXBE1V$I28?%aT$IYmw;0`pTc~^I`siwkA>$BR5~LEFkaY) z7z^mR#|Ea*Q*u2t?w2%^CAszCGba!G97C0__&Mv?OwPvXd24A7ICJ? zeS6V$dzn#m2^lH%B%PzG#l!JYp0!^c+pcac&384MH#M z3b-i7!nY5|l_&lZSU4YIM;=RjdTEZlZn#-fbf%|+Y#JN%l2?bBr-&8w`1HtnS#O9< zn`Sn1vtta$oD<8ij6BGZHCRB;nWymryhLXG3Kr;{C&Nb5v3@}=b7If2ofFf1tRZxa z!@ACah4t9ZaGo3N<9yJ~ksB8HEMkpwG)s>gvJ-Oi)wVFttOdR^&&f8%#9rCV&`p6E zvgrUb8t2T79Q(QL8E=lvb6b$(5*eoPdHFMP4u+mOt96vAv=Vijk#R!18f#r1$*L7~ zi=5Ig@l_2PxrM%Ghyq!F;e_PGC}CwS&4~e4w${~NfF35~2r#Jukl~0wEVO${0IaY( z29!rmD4~5HiyTQ+KCmz%7I~oeygYLQ5>X0T*_2ebU9u7(bn@`9!LN*iIlbIz1?o!P zNqZ`aSRH&onY$k~TfH=Lr(MtmC$pE2$+3Jl+u9{VhB zShnp$rpja25BBVBLleT54bU5#H}Sw(vFReNHspmXgKzJM5HAcm_Ws;1u4nS@4-=*7G_oYfgih54za&p%>UVhT|FBZh~+V|vO$W&l<%^~OGjeEhhS1hAWGeu4r%YQxSQa709qem;PaHY)Q zU?Xc`Icv<|6Lj6q5;lpzDdfHYBw%}yOEQ5z(94Wc<@m%&T;i30f`q6q@wL=BG6ed8 zV-QmYgu*>WDkfA9!c=0odhV5Eg%~Crs^Ii`hZU%w_#Kp|VpgC4FFlcQhSWv4qFuyQ z7}vPC4o&zQTcxq)w5%4qDLe@BRnioFR z*m7GNOp7gL0LIH0-w{yM23O?Gr~)+d-o9*PnT;wN153V{_trsY^tK6r_huP1n_drZ z2tVwOagpiJg`7Oe50}^=m&hDviT{#u4BkWy-r)VDvtZ+0kcau$%yC|_*;ZSg&Y)vM zMs7dT#xt7Q9NCPGe9o?H`P?+)SRTN*j=B1e(k|gEl$syB^&unH66o=dc{_K;UcxVc zCALe}Zb_~S>=w@3V0s1Q5q9uP@^d`<+BRt93&#Y9onr#9Lq5lO^^Do02w+W@@Q$&> zet~>JoVn*4bf%%Xse{SE@`ZKS&e7X1^1#P&7nY%060_%vO=e!MVWzCirPAq`W>>}( zUJ~`o1>(d>egZg82)~lFzSuvAgbR0jBa9^EnG+~dR;!^J`Lb@p%Vhr>?9WAh56-Hchq=4e2olf#7iUrm5^m>OCIBj5e zSeTXAMMPb#*ublL&T!P(%a<8W)H4>G&|CmrK%&1XT^+&7$^JTV@Wl-kHx9C@a})!a zAaE!UT5bR=O`n88fyPu=b6?_%#QBO_ZFQ5H55O!o6t z0HzdU z_T;pJ63D0|&)P7+^jpLE# zlz6!nXkJcuDmz|*Jdnn&IpaZej8IUw1Mi{(I4z*QWzfKDMH~q!RQ##dx&>h864!8e z181j4Z96m`h`XW0*F0pzv&eb%5C-2kc8{>Wz(gF3FoCP5WwlupRh$E}Pmzm)_Kn8= z1}%A`?Mqf{T*M`uYc}oL01A7EFC9< zO_P!0+b<584copR!};~(RiP-8bjXo8*B*XJq6-Wc(G+rR1_N)o^#Qg8dd67!n(m3! zGp1!rWAxehWx#9MqYpb`Rm_;!E(~-5k7;^I4$C8(5^HOj^-F9?SAFP9V5T8|4whG_ zahKTiH0bcdXc5r!TCiwIoSvF-~bz@G=<`HbPvah1Qkn6%DSXT7M|_>W}cV;gaV4Y-Pug6C4OE#xk+P8`K_ ziK{7~C?#&5N^u<`+or%q4DgAw$o7W87XQpQ$V?K)ZsdZz;8%{>TG1}D71SHJ+WJbl ztKlYa8GCVErv~d*{-z~MD_HJ+Bo17;QoBc23LHAd<3-|kWqh}g1PKL-hWn#s=paq?gulUfhNcJ;bbISM|dO5B){+{Nr zgjozBP#$D<}oH_a!!Z{9A~`& z5PCEaH&>uo!4jMio3#)e{h zAkzQ~D^g=*ElGUo#>OCh&>Cb#&b23xBk;Oo!%05O+3~&tGP-g!Lc!mV!4)#|Eb?6X z7!!MNJ_6!0z-r9w`1nSnvW2yIKD3xdmM~76HsN&HGBz;rErs<@(hHPl=z2hdO1j;6GwUp5FH6u z6cIN#g+0^KNod$BLP6sbhx5_O3Cty=6tt$uf*;E+%4Tf?`8p#KLgZT4<718yXK#@M72mfU#p# z;#6zX>~kt47eJzgc&p9Mn@pukjl+n}#rYA+oWdVrOsy~mLBofbmSrxS3c$&}p|=ka zoNF#ww(Bu6-^2Il-MA1bs#j=UK^XfV8OonMWUWFA-LuwhP& z<9rMuL(W5}tfHVF%fMW;q|Kb(TO@ zi3zqMe=&nZeRLLrSX5j~L2%QdJwd|NGh~qNBZOz%6d*o39Ub^%kWx}g6(B;JQsq;s zSPAh8AYXcVypyt%Jn5ohPDept9V_O@(;~P~)Ak`tls;JvZ0b4|JYg(8g*&c*SNM*~ zQ$<~YT8sl-k?)V7j!LWq%MBy8BL%j|4P#}q!qu`~k7Y$ERW1tHH*O(LH9NW@s&t{) zp+FenhvImnN#u}*9I-=pl#r#>$=(3&=wnRl@Pw5&q$5y5nj!>gp%ah-9IBv?n~{Yo zKwiNKd4|pfzrgk_HKxZTed~(2vEd7LhD>(G&g~fRMG^L4hcn|rl3&7`G2pGwC6i-T zZ8Ab%7_%JNI3`j?;fjMd+Z+SJgA2LZIuobbBFEdb!Hxx;^#7)NAGI6$!>Aa`!w97BK%+BGhXlS7l;j#{^MgV^`z_5KyWJX*~;TTdC9QomPPA zxs&Qt?iF}RO<4pSm9DH`0g8Gea4`lTDHNyTW`N;DedOnxl(I(ZnuZD`H-QZBp+Prb zqgvRY@*7kSqnK6wE z8DK{I65#LLS%p`Y=81*!D3<+6sc?f@<`|AwunEjs8Dl1IFzoyCtH!J{{38X8k;gWj zp?m!Or@+;th#+V`DEd$IW01*Q|SH?NQkx?0P!9P?;G3I18D;YQbwFcO663?;tQo{O~ z7kWJ9!+ZtXR4L0#JZoJXK-e2o+t3U{%xWumz2rz3*!m@6*kfrr;YV5#&k+k>1elTv zL5f!>SxQF8O^KR30x=L#k4|h8U%po2vI>lu*GQgj8$Q)vNVUo%SD~;80AXbTJp-MDTF~tQ6?t zW&&3cn*+2@+hJbAS_yCt{NOc=QILAGGp@eqaW0|vMr7$qrr0D=<2B@8@HAkylGlw? zVN>F^OyQTItIoa&y={cfG{BhIafW!1Y+}U6(m93>VF64Viq{6dU}Ny+9eOt|Na z=LX|-37?E5Mj*y671*&dyKw03Yaja)*Bd*CTqIP&OsE4qUigHq$fkt6FzzuRL(h;7 za|HGaDCmJY$7N0zz*CAZTnzZ#elJ z1}esfwvA&LEOV^laqyS1AbbKI(>5zxp|d}#fwF|4!)aTwnTHf3PIAPf0Mttf5Lees zSP^H1ZL^{kM}uVpVDtV+f;ya`(^Ads3a#BkJ#hxI5(01xgsq<7-;z{cya z0^+>V8NL`eoZRd@9=-}#DH77eppK2Db*N6yJFkF0_d9D(HL(JeRMZ*O6?j!w$2W`= zG&LuHlOj|-%mBUtEG%*~Q$Vqaixun&2O;HZ1#+l}XLish)2kSRtj5OEypscS;?3{UsJ{v#AYMqqKff5mY0zG$-_@& zj_)Bc4ckJp6{_z_o*e_IJQfh)i!9?)Pk9CS%5DhjW5`Z9b z$Btz}Mhw%)BLy7V+O|7 zv~3}WIq(@XcQIJV@e7tqVe>AQ7v>X6uuRmN60|wH7#kea_;#qAy=-g0fMbEG{41~3 z6Zw!sAs>;Op`bL72H^;nn-iZ8xn{(+F&6Yo0UaVvd?N@pCPM;on;std$urh6Y#OEX zmHLymr?jZ1(^YuI6-XzvQCBDUlcbB@_krzelc8`ipw4~&)l$Zw>XH&VUtF*zzcRKZ z+%S0h8a5u}4n=KMwP9Swsq_#76ytyihk>B9A+T+|NkhgM86v>(OdA9BBr_$D-2wP^29QAOb;~bb%bcYpiP253sDqgLC>&T7ArM8lN z#eIRIaAOpTv7ju$yC{z#a~Bx6`w=SsBCuHn4F?!*Lfv*CbIii_f{hE`urfgmX&XXT z2HrGa3ZH>u!|~|EL0-zr2Q4;^Spu8KW}q?k=#i_}z&t7tyB1fh<61BHLDV?u_D$8_ zm2mVp-h3gkBnR>^UD!?RSED8!y|xPzc#N#80E0KKF-9Rn%Zp{KvE|OhV>!Pn7q%t9 zdQ4@U@D0L(qY2jWoX=MR(QqvI1r(`xZtw~iZYdmNwZWKRgxoYB4(ApCjglB#2c5u? z3XYKEoQ9@lJXk75+eLH5TUR6>Rndl~RofUsKuRt11v zo&F4k+lrTc;5ijx^pXSrl_cf{QAZr|Z z87x9gL~q_zM^J8TVj?}(4?Hmu!!&ZUF=S+p?|265&9AV>t&mi|#ajc!e2K##C1Mbk zWMWBTGjTrHu_h&Kj)3o&e;F)XFV zs5yBI^9EMQj!fdtHrP3qV-VRfG9wX|tH@P>3pSp_Q5@R_6t0{`jAehg;q>R0>=rQ; zF}RX=m=nzQE80dS8h(Q%eq627aHNxrjRS`KG8lasiYMX{->#%Z4u#JF8+=x}6}FAR z@zXGIRt{qVq98Oh5?K2X0x1mFdRkWyTW0VI7S^sP#<>`t!TVBagfN7{2tr7?A$~$M7o*1(-s%t3k3;y4t5K2c!3ChDePR66E zkvsQ@Nem1aQUQ2)T@^ZFgNxTk*a4^KE3W{b%qtt5YBMEOiz%}hlp3bu-x#6GK;1XD?BW#IE z^5J9N8yeU*Z{fE0W@d;R2cr_;n~5OA!Zq@++&5+B1}h|&vGYci2i~#>i>_i~*k*wE zZ3&vwLt~ZLv{zn?g(Oa#J!WQX+cI-2@j<~UYatKEVB9~s?EK7`wz7&41%Ceu3g(Em@7~k>&Pw22Qoy}XIg82#v zUrY}}*@l{e!^+nrL^e`&<<{kc4;o3qm*I$qErx}rQ@|O6asni23;Hneji?<)gb~-&?b_J-YmzAFi zhZQKQMdT|rSvfP-gA2F&?bSW*^I#XT-vzAQLx# zK@N*4{xJ44*sl;ha8dl0gM|ko@1VeDQ93{Xbevq^i^nhtIA(Z3GZ<%K^TdC!@$_w< z8M9zhYynZwXUDP}ToxquoM6$NX^%D1#7(Si61RfgSU%;II>X5RGo*%#6JXx zi}{G^2*iT6VR1fgG67h_$J`1wfUUz6m55Im+>%A|ffc-^B6ovzmZC+>iLGTi!eWd7 zOaccFgYjxZ&d3Vm3pv>j;IvxAl8t4KSP~oa0Ft$`+Eezj z6|V=TtF>@mLCd}@C>~`1&#Xq^ipmz^Fs?xU4vxJ7#9>(hSMQbDV_0ZS;WITbBt{{@ zI|U#JoG`{r2FN&Xql+!DwmaIGpE0mHtumMo9L<#cH29tjXroj3iWN9*U|+E$w+o{1 zs4in`j19HKkgNzWW^&y^qM&%W+7@(lT5mhHKpFcI7>n?OIl|D^*GL!~owfkbuWr1R zstm<1u*ddhbNg6Dju(EB3^z;_S&WXjT)hE+7~Yg2wvyPOVv`|0N}B)H>AbFJrf2F;n@DcjfsCTUBL2Rb6JX>OTMg5CBO; zK~%BMp%fj>mZeR0tOTIqFsgqngDx@4OW_|_l>w0{HeMxo&_ zjd<`t2;+O9;BO(@8mO>YR(}z*V5ZQU0(@2{jKq<^6^g8cHNu7y29tr0yVEg)M}>iX zK+4?2#wEUKBaLKy!(!*SK-}#3T7`LSaD+!iXnfFdLL-ETcwl)<=HN}PD$&DRFZ9NS zh-n@*$SQywtV9-PohouT$HlNX7Hs4-&_}P-up~3C%%cF<`HauPe8h&Z5HRI=8cf?4 zG5#ycoO2=;28Hn=Z^RMPmc%S117f=P1u@tcWBUU~HkO3~!hz6vZp89Qkczlsg~4EE zYKV=>W=6u*8rimxUx713o)F;zwt?vt9z?`pe0+}A0EUyL=PI4Nud0vdIOK%D5Lk6#dv0+71e-xUz+rc*M&rzV(P}PAQ(IU>kNJSTXi^={T$(B2KbYI_8aYJ!a3Mkn7hiO7Ur8<_dH!!Actuqu~3@ZX0DPt$Rjp8rk zkbC0?F{pC_$zZyIZJndRW0)5)7&dZXe+(Qt*%u&SwXZZR8cv)!nP-wWRMW@6Trgbm zUc<-@LBu|Ri9}$|l|A`H9we1nD+8oYv6S+FTzH%!Ukph_Cjk+e;)?@jikwZLFe(_A(AkEFK|3Y}c-AWennvfpV6@Bw zTWZ>}2Erh0AVt_CSlNXtF1Dx;d1J5=7duuJR}>x>@O_AY)3Rd}<|tD_ZopOm94M|T z@E!+2rN#W9gj~Z>^#gN+>K}JhwyuvoD-TszuZUA=lZZgbD}gC~NFX?&%U}yvNFKIo zAqr3#l&9w%S0L)_j@nbjQKO1~CBsF5Bb)1E{+3y%q$b~!z z6g39&L52vGb0uD7f*0e7qo~y85%Wag(-SZrpkSM!S71I7KPARNUIqZMq~$9>*gAJI zfGlEK*i>Hx76-~PPIj2!<-oz!OM$QREBM18HV=Bqd91%(VV|n2e&(wMDas=k=2S>6 z^g+X5V&0!c1=bT;*n@qB&r!mRVIc-7*0shE^Q$)v6tOwcCO|;47OcQY0w3p>k|mb0 zTt{Nd43;sb7f7qayyZanI%i}@Iaa$&;)Vh)5tn9!DoC)L1q#pKpc6+ymw}ZWv*B}L ztcb^Wnel^0#s}X(M?=W8^R0ljS%snMOKx!frf)X19cMF?j*mW?dfp?A}}dgNbCf_$t<^QxHun!8OQV! zR@mUnsc=akujk;Y)j`f4XXU>V+uvIaZg_ZwkT7V(H^wk%u(gK5KpBWJkqcUdGABqK zLjb7fWteU-(FPfPP)wJhiYc3z;K{`Gcd<;~gI1qKuHT2Vt7F8f_CFq2l)R~z`3s_Rc0m&;4Suf0$ zd-Ehdid;b=J4G?VOT--3aQ^R@Ffz!4FUj@M7ZHqwyl+UK*qk-=lZ?_IPehJXd}8%U ztcb~Y>0m;w+?$62Nz6Bi3du7dV9Y#I1oflVW+`Gcb1sD3IHLGC;>b{!5Cd0PQORqw znopxWDPv7pbFhvy2+$4-FZJX%^Q@2T^wm~GA>~`#8fOKlvB?^h50V|heG$lDuS{Ry zx`(o%Ow@HGa*83E12K%XCS?`<2N{M+fv$n3lR*-AsZ0zs2DtKo2lpl)m3*!l)=IO7 z_Sjg=Uns|PlzIO=TpU<4V5<(Qi21+u8bSG37+Zi3J|x>d@`#Y|9N~on?*+4pNy&O@ z6YKd&2l@be(vru(++OUaV6WB2+D&saCofX!a!chHcNcpzBthQ~U-B@JJ!)v-OJHl0 zwU!c|v}`i}JP{^Qk?@$W5<(z}VIL=nlW&YO?_3{jn$B5|QE}5Y$WvKUPsw2 z9BNcKYBmOyfi&z?5CM_gbq_3(u`>^V_2@2$iYx0OFo1c+akoz3Fp37a zq$9f_9F$T8M@&ZI7;(MO>GxG{>A4QD3!Z}; z+Z`CehFc2nbCfzFF6`0_E@WmlGaFt3suuFZwfH zweU5q5-&B5x=XIX>jlCfVPPIHWL2KFCHY2!<4N9`EBxSdzr#e5IiLgCp42_2?rbNN z3smtnnSEeXv976uL}nI6Vk6O*LiNcWvIK{i{=~6*N@*i-s#FxdCTjWUg2_aU-xpbx)XvAypC23i-eXb4c3iqZ_2wSHjoW z1MI+w%0W=}A!$5Fu^h8R`2J{DPTa{zoy=9I=s<_FMwuT?Sfg@^BN%3_L=YEMrdW7k z4{O6HHqZyBxqlj*&mnlel`#yS(scHR8YII*Jn9k|kx6k5C?sv%TV@6W(q~hkOUV=w zFn{B!LRDg4__I=GP80ALOpF80z)G3u<1P-M$CD1sUHk-YV0Yj$kTT|0g4gZ}E;ll) z4EX2=BvJ%4xxzBAXMKMP-;M9Je>O)~5I`cC4LPH1k z!9uP%>Qe)-yb2rY`b%3u7A^}_ESjS;*Xn!oG%LxBmQWVR7RM2(WI=LBF9BEWO z1=c*QcF?;~RnHHqGDMC+{xR^I?v_-93OFjRY6C!Hb`T)DrGn-`GuJp+Z$?lKGU+(X z0~!DW|4AGY>gEF5iz^-|2ldI-CEeadRV#^~aDsrjAJ(g!)^n2)qcJRrL44ItoHYkE z260i>QS;n$qwdW;C0cG;O#zn;;wAww#_8lz)H49_F~_zE=~leVN(c$k$Mt^OWi&g1u~V^ij2vTfPXG^|`OH z$N>BY_F(;?9OgDIIK<%K2livz&;vp>Is)5(;+bpcwD3~|)V*{jMqG&=nHzu#sg+=4 z7MTN?aQqRRODWIg3+{l>c^GgzW#__PoHlrw~C0%mbl zGweeS2m_Uoqz)l{b&|@_2^U!U+fPgxR`;e`<-)e(uYCHFeJ*1Vq`yEdMFPgkr6&%2 zNaB`oC|`n%MMa8A&bNqGF{7dZC6j3C_Gr}M2vnRF5DQLfhkn|WCt(A$ z1{@hE(@^n>9J{0+N4_PhioV=Imk zk$Dg5cEi)tu}F*Sky)|G6~yEdABETCCY4ZVYe=L*bCACn{`jn=rjIz3i6O{Lt!$Mr zRwQmNqQksbjs(EGyog5vioz;qm?{*_cgv$LQSN31xqL>J1+>OYW^S{>O>+7y*Je*T z&UdO19TyQNzVW*Q) z$PxHmDL6E!j)exewG#4l@bAxzDIby!NGBp;vvAN=w zdEbSNnq#_bC20PA4iJXe^f8l%d#w+AZOgQ)7ZGJIhBu(x^kN5ioG;qiU(MkBMp~7KXAkUpyrpE5$k_&?}ptd+n3VCGA?PUO(dHi;rQ*vH?GI zfRwG(*imkNG9VT7SUiczWR{346THlDbxD!v@K2i3%$@O&vFeYVa`uLxf#o1k`C^qH ztmlV(J5_xc7zN=@q`Bx6iv9%9gh}-(`_|hZdK`{F3np_F*AdX3Z>3vH=0Dp%-{uL4C`( z9J3UBb}sVXxR-TDA83;XPl%Y)ac9BdnRrp*qEjhhO`|f++ROz}k7wO7EWei+{+Oyx zMQQ8sIRqj9bWCn-Q{am8w@JUazO1*h zdik?}vObk&f4xiyB_!_W!+3T11^j|RJ#K%*H7PjD$KijqhF{f~fHBaLd8mZ<5f}$( z6vevo)P@L?pPZ^QP_QO(sZC0(zyoX&)uJG4?1*au3Kgq?L;YI|y_=$+aahQsQr1 zP%}>9MNZaGq6m^q`zTD?z;wYMlS!Zyf)KGeSQNH(?Pf7Lsa?X%+UCHr9V>@Z)@s{F z$3fh{6w6W`rJG}-xWthIim-yg-jh~HoY#&6m?Ar8+)@N;xZXWYZ^Ce3U=$fFFbecu z5KvNvJ%-W+jR78zFlCZpV+%x`g)2l*e&{5ZP*jUWm^ZjwllY|%7N{k+8IQLzUaQXa zbY5%ux3TW|)0pM1%_Xaix%VG{8(UvQwxZ6lwr14j=GVQHn@L<%n;Y0XCMcbWb49ht z3245cyy?mnt01A6Pq99B1eXp_yzD9pP*rHfzD($tj63)jD1J0EGcqS(jbuvZO#N|2 zzYcVY&nrNkgAXQ%H&!@u@j0ajUU=2(i+}KO9|F*=FETe!UhwJzZlk_d2Wt#64LE+( zXQF}ML6#x0zWR(WzzGUcjrr}te{j(5Kl5;lWe@Y=rDxRTy~kQBxM~GB9*C|J#0+At za@2jP4{8Z6TtiU`lxZ7P3y&@8H(2rBnM$}%sW>NO=HOHLr~)d0*HMn zYr9giMq=jC5y$~*0ul|@4Je@?%)a18z91sjbtyh@$TSNn23p0aQ*Y^F%Z6_y@bF&I z1+hk{dm>I;I0;CE)Fzj}hU>rs8uY=QDF=Aj;89mavMs1%>*Odg6eQ{c7*j;q2P2|5 zYa}$sfJp&|DhPeVc1G~tQN_xu1aQZe@j*QxD;w-*x$di-SbDtFfw}u$vNlc!<_2>^ z6@fV1e(u>ssTWHCS)Y1mG=S+NT<^%jO2$_BGgHOi;Cmw*ZhlRM*QQ5s4XJdEQ2A;@ zhVd5FsHLs9zCzdvkVBb7vG{<3kHHwcN)V^6=LdR_xgh+t`I{tZ zL7kzos2W6qQrQdQ<&_|F7+-EobSyOMR(Mba3o($cV^}j3d~x;DzpOU66eh=D(x5NT zL{TajQ@R*{>+-opnnPSn5=ng_dqYJ)DAbEE$5LnB1e>1*;c#teKp19t2~OpqK>Jy3 zK(xzyDlo2g1I;Wx?IY&x5`&*JNkSi=NAc-QC`t7pzqSbva3t$0is0vu*q8CkVMF11 zcSO$Vce+GuVDs=&u|mjYUGH?%J_##JmP72Gvjj4j!gRyOd|TPvp1VIW<2y{SP0gR} zfE|0*(BSMqZL^xt_a0ojDkxjc8Ctl^#-1+L@}MLIEZl zI*mhB9x-jXIPf`gmLGW{l@HYWs}^C|*6E#LzD<}J3C$rs2C^hWsU9p2n=6z(>%*jYLMXRe5jEVQ{^a`{ z9ygbEUjm`x0w}HxW8oSlCQ0>4GzoS$cuh`SKNbBX<*K(PwJU8X>rRtzL1IiejE^hx zdC$t336o$eCa5j;wG(19r!Vw*KikJ2n{yDAai&Y|700>{ep^EgX@_iO6o5qmV(`3- z8n}RCPo;ry4v>s+t;{?*2y#YU_*-kqOq4=FG5Zkf!WB1^te*J28Ig6TfQ$+g*?KTVuy`&%ijSQ&%NYCs6Id6KKW?tfjDVPfM39n% z$gl_XV1V}8rI(F~G58_JzPYg6K3=E^6N5nKQ%7M`AK^7{IdcP8zv~Vk3c7&95vH9L=+NA3Xbahd}$s{sWsa`JbpBq*!LJmH+ zxJBj+SWJj-ll}ppRA5cK*v03BR|%qiP%b7{fXte~KO|#Lyp>i*QF`EF8(| zWjAzVJW(@Dh2^H;e1+8}fmH?^GpQV1!(xiin57KFlCUyLMVH$`xgK+PNRJ1W%5{h9OG5Xrqz{jYXn;v&8*y{7a_MmVra?d*ZLwNR80Z|2_0!P8Z3iy5 zO3P0>Q2U69F+bY~?AL%5&1uE4AsOdZ-LfBN8@+Y;ia1}EyF3{6DPr;`T^J}^orTAu z9iy#$6v}J)Em?MBLcP(*6}#e+ zk4xRk{9xe0I2$9VP7apC&pMRIA=3uwhD#L1x`qz)!YF)384)lqlM?i33}YbqqVhmC znhMNV2g;Vk0n3fZ5?zCk`Yp_#)aRcIXGBnow&2nRV|X|bO)>@^Ksqf-5ObQmIC@C- zxO}pL%ZAQ~ed(gSG5I8CEt5*C=|-O-xe>5cuMu5Z=CfkuvTKv9adHC6Y2Np|LxF`a z#?}yARN0W_!}LV}=g<b3n}?UmEmz(&5Nr};|EhK%N3KlbxHno9O4*1jcwIl^gI5>o;!9VfM%`KQS6E<_C5VSdP*~^CFyM>v&HQ!GJ zWqB_c|G|9>u)&Y0V~Ee{y)UUSas1-s_?!k~SS}ZpiXCU&RX10bD%J8Y9bY++Y|-PW z1vfi8a6ao3`I^GV?CuNW7Tcd{W%sn)zC7NfVp7FzCxIIhen6LRLcJfi24u$E{tCPS zi`~cEYC1^x7ObqWx$?|-O6R?RSpN>?m92y6s^h@ObZc#Nc4($|mT)@95y?N{B47zs z(#4Yx%c++S9{l^CsF;`+P-aGE`p2T;XvoZKIX|*Rv4Eg@@(uMX1WHKAQ!oGk5CBO; zK~zjY89_QIBO|JW;%FBri47bwMWZf1yt#5EdEE~h^e7@mdr^pJeV!_f6aR9h>L!`| zfxP~?@gQu_8?hj7;EO9LD=R|*P8chJJ+oXvI56tGAQ(RG3Gl!X)P|vvm;h2E2f2d_ z2PA!1DXJwx+oCL?lceUFY(y9ZT8m`(kG9IgQo%wj2b7b*s?Tc5@EXYF2M;L86qPfS zCV_KvEEZQnw2TXT>Vj;nY?IY(nnBJZGBcQ@s}4mX{o%r70K>*wYam$YqCA1D&+<$;60rJZ{hJvJGo zESHw-%eO?|lJLFKd=f^+sVdZMEKq-SN!zAnMpYW2-P*DwmZHdEFdmL6;x`gCBQxQS zn{77K7ZGpIM)0x%<@%2~26C7Kd-72k9794y`UD=uL0H23hl%p6{0OLF12J>rUUDptXj%tzC2R8F)8e(-AyJhz-^r zcy2n7=MbS5m2%9eEsz5DL>U0vkddcG4o2|YrJ-dybAvbyNDLBIwP&G#$@MB%txpJw zrUQNOaw-qxfJ!!iIMl!#Vx$IP5X+3Jut_8q7B61rDO&jhUV2T`#exI*mI4e5kA_`> zZR#&B(FQu;dkyRH&JMVDZyem{af8)fTlO1xA)Cz?d;4xbxwO6H`k4PH0R#v3Kf)X( zgXyEoE%`AqPF~*2Pj>1E#)Jvt`D-lOD06azND=4S!K;?OXh$3YM~Ct9CA!L_%$zZ( z=?j_&QB$aH&Hto2Tx^3F27cy7bg^RBDI)`IOcRVVVbp&WS9zQO2RWiB0*4zqVqRG_ z`ynAyjT}*V5(f#@Y(+rD-2>ttj@%-!8pI$Y`W(|nS`(3Y>*0OYA*?~)&6PKiY>D=v zKGaL6=q(jDom2|T2e*S6CTW)M0J)!isLRnzGTKd zJUF82nfbH~Vj`R+J9dfM180sKuNfBS^Naf{iP;D(CJ);DNedy$n!%+J%~GU923_NT zvu62N6S4?;)s-mFpf3Y%==8eY#jTF_95z5nUJeAC;8w0=_JB1DC!qZCMeOl%2l@be zxi@8DOBHu=Z@Jg}jf;IP6zaj{R%34?MaWNzdDVvwF;maE=}~KBWSG;3AqAKD6JCRb z-OmBXbu-0nu7n<3x=0#)Pvm!mag`9(x-wf8)YXE7J=0`Te;7f!oEIbDlnIGo?0Rrn$ z(hC!LRuhvNhsz z(&1sAh%k?&gbKrhQ8LrOFCe)T6y_l?0@sDZ=rg)?)j_Tm-IDP$rWiUSyss|bkDE&@G7g}jEK%9O4>*Q8&zVL?>A?l2S>3hx=_%y;#=iJL zse;RCgNu(5{-fsmEdRU24J8W<^7$@oJzaS`RO=tcU?@zfTS{ZBN!C)Nk#&sh7hOYS zNYN$9I+mFslVQh((Nn~VCb{b-AndNs5`OSal{e0i&`+c70`_B2y zIqx~csk}RW5KS+u;%4SS`@T<#)aGETtMC5MX!-DQB&=F|Ap0!ulb=cYvOSxgZ^bZ^ zT7v8KRq6FGdSo0{c8)Xf26mry=lp!j+yOhYJT;zkA4?;O<9gKcQQm*Hqfy6Ad9~+S z=F2jCtZr1Ljc>T0Of4OaUOwwCRUuyAT_So2B062Z$D}YT_^1@Gg1olScVd!aP)b&? zv!q*$E$W(k@Xxr6z|`kc= zAiqHTdl47pf$KaHDzA$vFZLe5f6Rmb2+CMB{q;8vd|%??o`{-poeyvUnlH50AXmcvWKv()o> zR4ZbC$WSxo%Zm9Ui9;DipYeUz;2BEaSqRu8a7vmTiZzemgL zHDhbUTu!ZxUbg*gn|bKD{3R}1ceQ-WZ?$zL)PA%}WXEgK!f>?ohdfyel}lGPrqr=k>BA;S+y8k%ppG;?W~auHl$n4@{l4tM(>bcM40QwQQ}1wtdq!Tt z_uMBKmn1x{Ry4nJI(6+?w>l?lulrHaPu%O&yZU(7rIc8+Zj^YUU+>v0ueju1X?3>| z+uKqx(QlU;Pkry=RGG|3mp*;!e+%*)`D}Kr{;T*|J z_s)>KQJ~k5+-7%7AvuJ1MgO~#VW|}YcvMi>$zYOan(KKKO0xCKJ1_UG zzQtb5tkCK~8d}^Ck+5Ab{QCl*5X8@k)vHl*Gw@4Padh?(h>o7dgZxOO)n_kLoVwK1 zleVWJ*vYYmR5kfq0=yxUQgn0dDLUl65T?jtp)OfTYc4|cna#nG3!*OW@sHCfM-K?H zDxwd2VUj;r?Nuqs>Kf~9jy1SCb+j$ir>i}^^DHbY=9C{?(wC)ig(ggwuYJu)W22Zok>(Bt7h)DIo}YkL zYYlO-n_Dg9Su9*bhhZC}I@ICJO&-N=Sx0B56SX9J%%p*{yC)-_TZ|~+0Pn<5Vf!+< zB`f_e85C$9AsusaKpZ%m-)SK+{@4VSYawSf8~jdnhBxn9q|b{3vx$48^ALCJ(>W4m z4Fd9Y9IBk0zr+5oR|}=j)!OTDi9RG#6hjnpO$5X?Bhk0zxo!IOj`r%Hi&d=kUm^vM z@xJQ5cyH`N1i&R|X1Q#n>j8JpqN?8#ED2Oh7rcU+QblQhl>ct9?! zL`9jwOI|88C9kFwOOn<41N!tWT%EO^bib9(iW5{pxyKx$O$mP2&2_4r{Kr|Lm=K*aT9T~b(h^g0YTC$r@vc#%PNM~# zL=f<6-qb8;U1dmlbV8vjq2)+v8;2*+&RQ)SCRO3SmN!KUB^GBQkhAb94PhOnC<_M! zY`|JoP@D2BB|(Vf^e2dM?n>?S^Hjm6FT!@Riy9QmGP3}SyeEts>EIazpfX59Xt7G-(SKC zQPXE0T;dLJ`%BI)+TI`fB?TKShtSO#MDfR3E0h$rK@&fn*n^Rk5B_2;x%sWuwcTA{ zt@(VjKip_TwtCrCpv>XS0!=TbMfMkBgJ0Ipf#m`zlghG`@g0b+4A4@mo69Y4$Q6-7 z;F$z|wu@a>l?3p9Nyr-1k13p-6V!KfBk?rjQG}@o{>v%b#wy+mccF(Zg>GM0!zZ<< z9CE!TV4Wp|a0oG<`SVTZCw-FB-YQ^^R?xiCk=9wC%KoWu*KM-(Ph|m@J%T8j<3?`c z(rlKhF?*8)dC2U+%5YAw_}J-5;anV6zG`z5Dvg-%!wgU4+-D20jnz8)6^-m9ZuOpy zm9>9#B{uz+!lO8YhBgqI zTjOtYh(8l`S;MKsLZP)I&sZKCY%Fuak#nSaF#I&pmWzvzV}jDZl%X8HRxhKwrHqQF z64x~+nkKEn_p+v>bRX%&m^HB-iPbamIUMEZ)V6;rSm>5?`xR!iQ^IVH!*}^I3}Y~c zDafFTZnBfA*bkT-#(WI3!ubb%LfASI;lj$HQxy<9o^-QiC_C= zRpI7rg*B^i|HUoAe);}z^LRvg#)r7@Z2PDT#Qv>y&JIh1f~@Jb89kU33=RlFu|eVepq$2i7_#fEm%c- zNS*4+c{tpi#JNvmC~QskjK(r~*@8^t9AFkRrtGKTGIL)O$MC{vr{)I4bO729WvFf0 zks-r(=#-A$J317d!lL2z0r-qa08}Segu%TwCE!edO~JLWpRn zGw$QVL7hpE20z>wVNMU>ve?rzb9oz54>zWW19s7nhDw4K07P(*Hc#nE-Qo%xc!b`K z5e9eK0Pn~qx6$=*xyVoO-~phL>^0ye_JxqARlvZE2)-2D65{CXAwT~cXt5MXPryE< z2kyY?k(l~Gffcaj$~B9??Od=XFl2*TyI8RUk_Zo$0XTo%YApVpYJ(rd6+c5VtOrE^ zDqaP5LCmiUx2_Nu; zAGURaT(LWX0e|OWaE*24>N{f4DL7E{#)3CN1G@#?0;k~yM?a3hgBwH`UBh=^uR$7P zuv#C|4viOJ&4z@33E16|mm123p#AHgr<|W{hXgU5qa$lVmFMeca0iB&wBu)OWmOJ2~*bV zabP}x>9(i#)K`mz0M0i3QGa08R<`)ayWR9Pp!khXb%N4%CCdgSvuJhP?Xm5Mk&mzD zOm|HMF8)LepDAdkQ|1G6F?7Jj##_#{w^ik_srp(oilUi-rv15|G8yC->JwweM0r*!Gi}+739I{4<2BY-~Zt}M)&lpyn6ZI z!LtVn;5Ql`7~40vb+mF`KXCp0S47CE-R z5u+cV5`4P}O~)?%FdH2{XpdVhXAwQp7U7Wqo0c%ECI4Nx)DqjB&H#yLr~o`@e}pIW ztnMsrz_YbC_RO#{?E6YgSg|SdAp#O{z66zQIcEe4rKOJ9abo?~B){TU<4vj>=hZOR z;#dFED136uHuc|meorXQLk-&ep48c=4)gxo_8DIda~Vrw zdfJX8eEqi}qV5T8*V$X&hFW9_G~KUobkBk>omW;(7W(IXTYwJSa}~{IjrT9xK5qEc z0#F__H8cI{ivNgZFx)f2l3%6!{y*m76jtQrJY0U_6|jW=hDnm$4}%87KPdbo^S#um z_iQ-w&5cj+?oaUykI(S#zwf?ZQ^VB~ne^{WZUU?w%+v0TEm-cqLTAuo`C|&y;!S2e zC@AUsA9>Gv@~S_UVc-7Oh4D|c0}f-!;x)mN|HllCnw&9uoZrL4 z>Fob30L?L4gek}Q@#|%i%#z%DZ1dv&(dEu0Oy}QWk~{yHi8o>Gjy0tf<@q*+mGv#L z1)A0^c*8dSKhwEZxX0gLeE{b5AKJHIN;I#|e~=$x|8HMDhW9-PYecnM&Hs0$#iG{} zW0A1^*x&Y_;kDKOGx2D2?SB(h{+alxr~2c+6VWQaHXoZo+YjZcxqD|w?5SDnFfONerEk<)c8MEhTadbwG94yp;$_KbiMyWmKQxL;gc2N ze@jY!!oTL{G?x4{Q+xU!WY;+NQbJ!F>Q(>04cu>5w55pcB2)ZRD6Eiw&|K`B-CK{} zc3ds#|0X)#?@NCg4w&fwwtP$Zy2JaX0U1HtG_eV*J-eW(fd);Qtv{-Z6{|lP zr#;29pEG{1?3aPI7yrX5=w3l@t?b$VhqBr|CHnYwZl?>_&cEPfJikYjGG_k6?0;&^ z7`j(up7TV)z54$#XgkVxjbCb1{>M4-@B1NOH$7{Y{|*I9*q55I|E#?l|C;q)68bhn z#e&Z-fG_*gM4SsVZl*FyT8`59%r7o7?k+aT{SU~C;@P!65Hr8c7fn~uB$44lIgI{N z{)@PoL0D{aUw3euZzHY;5E}0h8M>siDx~SzVfv~Xd>@DMTMh=r3hn)`^cGqTbk1s9 zZ+1TKOxNUiQQr`hHSX#ts7h4-(1(C|8=CeyOCVxa#?vH6F}gj@Oni>#g64Z2!U+x0|V}Na6pa4yU%BwL=L^=*PO&`ymg) zk0V8z_B-&3cHc!z$E@clI5=HRwEox;{Ke*cG$;f;waD>?xYa=;FHYV42=qRS&D4(X zG)O8BM0Z~}qlN}=`C33ot65?em4Q>z^frIsSqO4NRKE;qMt=zxYEesOM~=&nDEuwf z;VZHq?wN=Cx7^U4XV14N8ys$4jgUPbv7^t$ zwz{p0mjfX@%*$I{I9bIoh4-dzf*zeDugfaoJRSGA8mepB4(@jM(-VGs_H zXlWf?drqdubvEGdox7Q#jdm_MkO=UzY}V%%3XYt?Qh=K88mKI1pP9@4H&?XoKXOCG ziVIUR9!~_pWxA5)Y+^M`lS6HM<|;wD%E&EDHNC<^Z6mO`vz zaFk3)v&wS^vieth7oMptGfDw?zPHdfhl~O-XP+~>dphe9i`r58)1jw#{Lb-NAtuOL5Qgd5gVR46Bvj0Zu2svX z5dmt*+;MC_AJV8lZ{&-U&bu*rftilwNXtbGh*|^j<&En;^(S+rW*(X>{ zq2I7wMD!zphc&;#VihHQ!f_ndnZ&*yG;YBnRIQf)X6sbMhpo)>CGJfHLO`Ds5xy2! z>(Ghk(8{y5+~NxO@s%rej~NX#pNE8UHhm64%(zffxCO~Suuy32tl2d0tgO?Ia3w zcvm}0<@m#qAeEp0oL}jo?uae^W+kmipfs2j2uaSIeynnsZEg?+CC>}SWDpbeRl!f^ zG7@1?N;gc5z@cad?!yz#%WVssb8(Ipp1=vP1@s=x3107*pJP z80Ble6Y)TZonE3+vG7<_`j%XjKo?z$W*b-%8DFaNB!j*lOaGbvd4T^A%kNs`0P+m6 zTjjwZH-^=Z^+yFMY(`8K%hK{j2U8|9NxmEBrNq%#-cNSIK7D4UA!&?K8vS@3f3iMp zf5j{f27)U2=yK05Lh$VN4`0~A;%vFYFm3uSC6Y?c%(M^RD|$Nd36d&U$sPw1)5!kH zem7FU(iz~9%`td%%}ls5BC5@S<%6xKuEt8Lke>Z6`iW=NQ&{&>-6)YQM_X=Ooch-n zEIDM47qi=`>}P{dp0h0*{DMP!D6M&ZvBq$G`cjs(k~Sf)K>OpiK1=Oon_H~<%V#0{ z%zE$X_2E1rWIa7f;CCux6LGZ!WR9EVzLESEqiw&kDLUoGKoiEPuYhAaB**qr{`fE0 z>@$YO4!9xX8a(Ge`CQXTTwD=#1<# z2bY-wn}tCE>xv*43>US3+h^ks#?)h7%xE*O=+w*Tc9tre813za(70bfbdA9BbGVGa zE$5bg9U861^w_U1LoXaW$+14O|YoQv_{ORGP0!RnmmB+~+*y z>|1YOb6#7VGC>~^KXOH!*C6C4IyCfjbmL+@(5;zDoReeO;hQ17$wNUWsUB6D3Ea&^3qLp_nNP1O zx_%)KkyQGAuQ}XrS;hQXY;v`o*Ls}823ySAZCrxfJMDHiGrgx>XU=<1LOBCuOCmvnNQeEt|qsIj!D6ILo8j(Tm8s2$l%q^(xxPq&>Fxzj`ks2XZ6%J`N0H)BAj{cc2X4 z0eP=Q6nhWN=o#M-lm64~4qBEUkooO&e=;@Vb5U{s4-{ha&$2JxvbBNMeHg z7Yo==4(Em;7`jmE8KZeB5~_JB&Fm8v6_LAJkW7^cq14MYbAzf4!rG&UphZEw2!E*P zPKbaO95Hl$gvdy_nr!+wdx~vivGXUbzDjc$^=v4sGgI)Te>&v zKBC-O@3%Zl_~Y1mnrT;QJZk_89kv+?9cKSJSRRM!ga~`5{|xs zncOK%sm}D!(Zi>s>W`yGRbQ>mndrA34LRx*UtQyI4F|6vg5}O~EZ`BzUh`=Su{|UH z*XMc*^M9tQECrm`1_t`i_nVG>_2T`^HU4_sEnAEHyD^$qv2or5Z$^>SAVvQ12>&q7 zmVe3-w4Hg^|Lf`HpGYCAMT^9Z-+Ph;a`e6$P|4dmI`8cYnh*LlM*cUh4U69*Yi8;c zCXD=>=RB65N?@+3b$KLuuO(Ynd!4*=NOh4OSCvQ={4|m+_7Iq`fga0*h?qxW4=lQ^4k)~)&&&r49e zH7Q@WyXoq6I%OH}2nTX)g|1(oOhA_+n|B+mS3*~^Lg+?1$L8ZamqJ;pomLfXXX?~o z-8-%l69N892P`Kzw%*4)HX(9}o>x1yF0-x^f8bAhy-E;nMm?CmPYCF!YgVJ>=%QVX z{4Q4e8Y(8-Y=RO6tjAXbC9cbDJ;88Y0$NdyiAG2167SB-lZLg;qQBG|8(G-x5)ppF zKKK{6v8o$=>}6w#tv)$+nF!ljSNlvG+ET=6z4DMzox|53UYi>>8CypI+JUZ{2-ir~z1@*y|AhF)0k``pVYhtNdKX6rr>7h8k;v*<*gf7L z9NF^Al+ZalX*iv>b~%nT^Mb&{57(FLcVL~BcC(`AO>{a?zy8N1235MM5=R`cu}Qg# z9_=frtL>ro@5(pS>&~jzP}5GveWU)I^V6#Ho6WC=%j4EqH!!zZ-OEK!iA(v}R(K<# zX}wr3QN(s-+PZY4AU1D3q{j-CGkKIm=f90Baj|k%^O-cwMz<_7g7|8PS-1i^>2K4Y zvwz6yrZ=~^bkwj_+J9o7Sw>ZX5S`Z-Iy@d#wchx{H0{#)^h7wQGm={96WTxX5_LYL zxVi91=-F30(<$)|6kI~2E_9!A=-0g?X2$=7ll-cp2$wj7-*E}NgRE8MZrYbhKxOzF zl0ow%jlC{AEc3X8;!#*X)V=Z z?~t>iCPQEFz0yyk?eC|3C*gdCu%GfWErH>z8ZjSY>?;gOUIGhPzr}ep0ptM+QAaD^ z6lq=D%N5o) zSJ^dds{r$wxvad*q`^<-vcPHuh=<}Gv{{af;=DZEFbUFNB52K%5c##dI4@)U+6v|5 zFq8`$=}UEW@H4mg>_A%I6K}@N_i$~c$Xo;3ZCIw*i0s6c&z5Z$D)&M~JyUEV`al6r zZ5h#x0%X})20RhoV|b*k2AiPo!KOLY8Gd<*SEn8wr`~%I)>3ArB*Pjm^{C0Me6&G7 zWXq|!McUoU09W5HO_yY|O($RKuSh3T|CV#+R9>+lN5vB7YhVx zJ7w875iJ$>*;!ygEat4jT4g5Zl#w~=+3T!4DVm0;UhN5s;_00<{FPl{mh8a+d@z{6 zH^1ya*MrIOks%*Cq)zv0AjG`hx|fj*5Qbwq zmwZt_>YPrN2OjeT)d~-qfLEM&C|=V&1B?aVz_lZ)zHg6GAwnx;Ivy{Hn9V!~vWeJ# zCj-0$vJo|4QLaOAE)F0pt>83+6}@)Ex60BF~X4* z26^{J4>U!mx?rJ+G%4<0?IHuLZ?oQC`<8-V#1+j&&~gL0fh1pl#vK6YYp2d3@6?3p zLp7EaoPTV&vBGeU8SEN&2wY?{q2hZ_hfEl8BS@UALi3jaSs(dep>kljY$iEf7g-$3 z`Bz%`Up_wHc53)VX=TCR(EbLMLVa-s-TYe9K%jUVGdvJ(Vm8KH`)0>Y<+1T;+J({i z0EEJoE7pXihEep`lM%#Sk4YSkC*wqk^3><=PvD81v}UB}DtJH^BRTjuiMC0HL=8;j z84t`R<0)Vup_=VMn%xY^|JI6ApnC}5+8WaZZemy$GXZ-YXi2l;NOZIvooC@z*JLLO z;QUuHroOwkg&;ub=SUW2L{F)t(c+AK)JxCZr^h5+MH?6jpum%71@fA1w*g-Jt{#id3-I6+KUK#7s4y^l0%dFcN>f2p*B zDq_OvnQYJuH?0e9fiU?Wvxo?X9z%8JVhs>59+^r^(k?QRIon6(^k+At@Ac(anjj}_5g2#a)`o^IFw4=w42WqN>?cL|2SUXth_ZZR zl!?Vq0K}mzY9|8(CRHkr?>$U(wF-UpxPo#rtoyACO{myB5n%oFr&2E?0>V%aEP?&L zEJoTgONaV6FBUBW)d&oRj?8F7;9l>6q_tA&-lg0hoO3)rTko~^-gtq_= zd_!QUz%@bXoFgs(m+J}Bb~ugMIJs+66>ub>WFT z%uMuKh8+1lw{h|j5OLUyU3kCD3jt3+4W|l%YCjVGcq=sjC{?tibNQ#bkCYsfJwRaY z0FmxP@U(CCRHS;#+3e5ItXPdT!ft1(O0Lm;Z@ko?aiuJfjN5QPX*O3EW|RD(SUanz zv_Y|@a;D0%%x!nNWT(;X^VN{SbfbI5FV&1v(*6W!tVP3iWxwmf@YZys;nqxjtk>`k zA&87y_h(T;*>EAL)+Z*f#2o*QAl!O8Gusf0y}9NTxAsR3VLts~r2RECIt?xbr+f2d zT85svFmD9cj+aH^DeYulcX(-6l!b1Kk0MZ&bKF;cZP7KWGTe4dm2gaMBz0)_^s^^$^r^bJB!{f0(Q5_m@{WN%*Jlm0^)caGu0D zvZ$;jyWkj#gmnl{RJeqe*7;eShMkxp+HbIbH@;<0;2u>!3Y#O<;>_b_ zu>=hSTL?8ZHJoWG|A5?mISL`|UzoqCz$ZAP70stTZ@8J&?l;^Y(u=a|*JLm2TRy>r zM_rA1x$}HO=%3-{Fk022FdM{UGm;;Ib%QrwD4#BH0xGqGRTKf2CiWJ&z_Mc6O}VL&s!7om8#WWPbj z&!yl`Jb3f!WFPziC~-3bbc8@l``V4~_x9*22XDA`7unYui60M`l~c62A9_C68=6e# zXrZNJ^laDdTB%PGO&ESmIF5x)5HOXSzJ_I}--AKc^9YZtdzU?0rZ>JJKw;cnR7^W9 z_4kZVN~{8hjS?BRTJtN;?8tDJsgC}Yrt}3q)Hu`wvmpSti-!BFbie7e$ZFG3(#+}S zvr>r~iMT4iiF%6E#PTmXWM)^STKddqskQ>BdIA^vN&nYJD5IB08bx-BfaeJP*o0Z{8%QN=r!R!jN9+i6N zU=DHtR%g(!V?(5MUD_GDkrXMminyD_Hq=iX#)cgo4yz1${1*%8=N`r2Qg<6wh3|e; zuc?dFGIXqO!r`EFaAhK=9ZyGYpT5Fv?ReBT*IZW7`*wtgED;Uknlal!cU;wua;wgr z%H~w9eJfX|f3Xl!<&HCpp1D%k>pAa`slRt{H^Nu{ic&vof}8}8+%Q|q2-z=X$bHhZ`e>wG$L(%f)xF~#>{w$z4^l>lL)L70d^mpj8$f$jtQ{)x ze%JP5Tz2;~4d6~0rvJXP$gD@infeSfsg>f75* ztKS+x+epdXLXnDi^j)N4k~svO0P7Sw>vf~HK1lMpyE!}RSiL^lpD%cy=M*g@!u`Q= zC@q@2ysFdE)$KfDDD7gMFe!a{8=dRJ@-a5|c;Rm{hMH=%zf0{=`tj@uoq(`SSK&45 zb4hZPi2GDo#s)TrKh0Lp!;>7`t*W}Tem$*_o`izTXSm8<;K;N1lx_=}55_>!$`?{f zc{mqp-*;?(PE>Jf`r*Id_u%5u(WN0=A|-_JCiGZJOn2Hc+2Yn77M%_F$?KoI zj=GT8hXwZBVdeu{%hn4Ss{IDc94CcUkkvOC>YDnc|2!XyamKN8|fe}lGLPksN@#Cy{?_&?_KY@A^lz_3=N^MI!@`gcW zt`Gu$3zQ(P%~yj*rxqKN@BmQh3b#n4V{%NQLjmj920_6C>f@rT%rANsl$K512cSI; zyy=mRw{20+>(jbVkMrk~biJq+X-GFa%rMT>RBEHE;Y0RL_ zQSAlk81eJI3A3N@6OpnwSEVP%nwq}5{7N$OnmKwtTbTt9fe{(GSg?!B8)8Cn_i{NaM3xT2+g+r~hD zBba(b#m%sOknsDpgyX-OMTw(N>@B)8~k^I7#U0 z%4+&cfl6ixXDe`8EfrD&EzCLk+JxgArm6CN1`Mw0SMxD=(+|i>=;4nYJylG z&rIzg!l75aOXpvNp2&VzRR_}&4SG+l=gKo3_Chn~LmPHu6v}9fKuo#74YQ_zLBRm) z>6myudLKEG1w7oe04((m|3MQb`+AxYoWlY}AW6Xkl?>J(vtc3Gmm#l@%xzoqo;)*- zdtlti7y5N2iIY(SCPtct;}YPQPP$V|xF&pR$q3Q8?K60aRO| znLU3QN+Zn#U8plY|i`dWq5*dJzs3Zzx}MWaWpvJ6ZDyN6>u0 zS3xH=7QP38yXu^6n1nc}uBP|&kN&tP zS)L9sn~OV#b0y}3*_QLN{Gd0n{pL_;VBit(v#(0nxyQ_f3O%<<|BdREPe}CgA||_oN-FIO1EjB4A@z*akIL(-^aY5M)u*w+Ed}xw9hn_VLmuAL1rR9S=}3$I%uE3 zsO+1%Ga(O9V===A4!n=cb265#TI=r&N~5Wg0LmmBsC@Q=9gw>`lWUBWU;GL2Z||JW ztR8jWJS#~xx-vlY-oChDy1fLcFD+oxAulCNDtZCKcKl5nU8Slnuu1sCdSM;kZdTC? zLsKJLxi_BN#suAhhI06<3>Rh=K68C}e8U6z8Byl}sL93cG&j*6PEhTU&h|=VXX;B7 zrM2S>uoQHqA9+&v!;2vLiG%4Y;d$+?okMx%0E`X>yW`7|Q2MO8Qph{7l@Dd2>yKQ- zz=-930{#l*=R-lDc|`YW+62Bzh+oZ&&1zf zmz9-8qq30xru_jqo}Ss>{*=iDPp18N!}``A!Eod!vC3v~L-vY^gBUp#(o->n`p*~0 zZC--Ns>zQ=B8lSP3au>FUg+dG65ui8E)Pt-+9Q(n>ZIC*=F1rXWMC7MvP361QEB$O zDJ|8UGSP9pwIu72`B%SQ%4rmo{keH4x!PtoF%LPQrE_-G2gUf_NO1MBH`IR>!-;q49YH+u12Y2s9qU{c^)K0I=>Pn1_gh7Ci1N)q z`T;IMWX3BKdEy3xP&r>a%hT}aDyl3(MmD64 zZTok0;RlB0&Fuwq>%s{_UFWl&{;rp=$0e4;S;vvrX+3KArr4(c2+^FsRoePt!oH4R zc7k!s0;yGISYmU=hv@aOo_Z9bijm;!rKJEq@yQZE-zEW&J&)gPa_p)z`= zep1`jJr76Lo1vm?0v*ZjXrhdCukwCwW?)PUhn?8B>Y$t_Z9Pw?P$x^_+`k1Ie9_r} ziEoh;o&DczCc?Q}gnwOaSemz>D{-RzciGH@Y#ubSg|{AiEk0V#$V*3TB(+77;ChTDu2X9<3O~`UJXhS#+Bu)* zLyVuIa}{`p*=DWPpsjiNJDpbltv{C>yU@ISv$NnEkI`S$RtPvps@}vKjBt^5e1$ zyYcyi88XB2E&t7xxQ}>9YdYvATF`Eq)!D@HZjxIi1C;LnXJcw0W6LATu}b;2t-C?c zb`oN52R>u=S)r=uF2164wlmz%t)26Fzh#9wnJ|KKQajO3l(nkJ$W2~x*!sw>T~S`n zwd_FO>iaVanNCCwJe^vc?#$!e57BD_)tsyP!_gHxM}$tI$Iu|%Yt1CdT**tg8m)vI zhrg!V@w!^+1Es+vkaU&hRfwE*vWW99@vKWBRD^`n_S0s^ZHP*mha8`!@@TO07X6nK zXxJsTYsnSb72X^airOdxn|A$QCEM)+bih9J^LB0i1s6C+UrDY^B| zYgW6#RRRO?*QsxR*jGFdvWTLW763 z$p?n3kMaUBgv=WBhqQi_&YS8J8#;X5`B79~?L1`DAwu3h>e75M&O_^Ylr(2->Jhll zD(=_&kl%M2-y`V}s!9O6k-Nz%O4iHrWKGO|6&5vhn82)(l1a&zXW3-yka5{6T&E0c zzt*9-ThAfn#~$KpIhQiw7dmOIGq;vs#OwyoCIo z7Sx_`hkG5S%ZQI@UgIuA=t^)2sG_`0>(V-GcQ{ zYhN>8lhT{y%Ylti0WANjTb-)BttPyoQN6vU5;Obe_)ejDKc!tU|9Hz?3Bg~8x-X!l zUwFUL%SJ5`>%A2@$DMi+vF;18-z!J=L#ECL(?rNWGv6%GGqikZC`Q2emtZM-$$T^L zWaFML*OrrUWc5i2hk%fMpONNJ8V}#u2F+UVlrzfea^TY;6qjDa>BU)|r^qQh^>QJQ zaN|zLOurL#yg}aUK7`KM!FPp*Z`Sf>Z|#}Z24?C@_}YiZDrHOFu3L59P+ipM(g(y5|!*L88RN< zi@vM1E`Qn=emJ;Ze8|Wt`FP_fDG&UP@sXHC*GKX89=EL$4}D(Hh@eQb0y<7v7x{*k z)b-?9brts0(8t1D93#oLUxnH#n}cJ523gIZ5nPLHPC`GVz<ZJx#*#63(wBLmUZKh{g&Q;@a`33L{_>XFRn;g7Y40tkSM+sv9iV!(-D&} zTuoz%-okcEeYkffzlATCVBtg6dW~n}nu1Bp4}aloJ3cJXmo%AEd#6^JO}9lOX(cW+ zp=8C>`hNWgzqM~tG1Q5c1PmU3N}N^^YiMEMJKgqxOS*=3jl1_7Vh5Rk@5&9O?oZnDF%cqs!W2rVbZRx`C?L+YskaJR?V|5~v3 z@%byIO>9uj`WV)0hmxr#__1_t&&lEQCPv@n#aXi_lU#97*?G@<)NQE2QGhYIEQsif zu#)xF(gyHl6Zy7SR}%W33#r$hd-e5^435X~xSOVNR|m-g(ZP2iRQwpSmUF#uJ%Z?p zQEE1nmT3-4mLzQE> z15KUm+7M+;7$AwrZ@F^TE-L^gHaJP7H!FAVy>z@ufK+&>e383yptXl)z+YchM+i25 zWN3dEEt(T$v^cEO3%6Au|07KQ{GzV0DPFivn(*P`Sdfj;%0!BxVJ8wwQ>+}QhxwLnmooQKqn>bzsCjg68bRXQp+fUSAGM5`O;4+ z)VSrgxtxD2vo#PUlg28`v;@CR2?|aNA9OqOu(50uVQL)W6Vz@B0HKeBpr5^W{F4!E z6~D7Q9h~q9-st4zd~Y72)%cWMk)`n)%mIVwhb57`Y5Iouz#@_zcdP3qJ8p2?=p~2E z%^y4mTXz_C%V++~cDsy&5RAC&G>rhZirJ-?*sr!@fD2miv6F_OCr$ZdUNaehv@Zv{ z*F;fDHbu*&&1IFFi-*spE26wa1SvM%bd+RLq_G&)qiz>4Qrk4+rP+{X&ooyLHKa61 zO~AcwVVrrIq~ULk-~v+P3p56r4zJT7By7L+Wg>EuSwb5YpJ%JM8{gz|GdvC#4>QM2 zF`=dPkpz;w(b+Dat>H4>j+6kj>of~}if8SlGRTAVsG2<}l;kW@7Q&K9!VMInXXF@{+sDHF&Pj}KYA z&TzYGGT(E|6<&H7-x`)8{D%0Mq&qrSjFlNeYw3Brcb98_@Ff}TUBogg4=fpxmunOb zPsr_+gD%%2Kpns6pxn&a&WAr0a@>%m+3S5;HI|5Rw+zrt7W#5l)b)40E0lOdjIDn~ zAyxnbNf~}97GJgQLVXj3fR;6+OTph#<;@!zO|301E~=@}piQc3#9mCF3+Q3~x8Ky8 zgVAC0Oe@xjn#BS+SbLSJdWR2<*Z?`7=3Mg({#2v>+_V*n6KNdcI{gtjx21Uq=5ss* zEC1k?S+gTL@xa`ydaYf1kYIB868O7eAh7#DVJ+wf-*}Slx5f4C{5r0!SN6N^S8XqB zTs&*L)n6?p7tI(QAIP15-`R0%OyRYtWVWDY`Sd4FVe|V(BqEJ+sHs6BZ^QB|(s#f| z44mMC*{*l8MPPF;+_n#P7?2#RpCPYYDn8N$X)qyI%8!Bf}OLD$sS$L!axOI=ylqiV4g?&@nF129|U7JQQ~ z5yPPHt(T(d+mf-{h;yqozBB0p!1W@>UIgN!KS)W>D7Tk4W4jt0pkiOLGt zr=Wwslu~Cap(#Ocjct@)H_Q@*8{%48R@z6kt-jjXUQB&-BM1;1=zekRh40cRy>OW< zT|4UQdAbcze;MakZI5{>x;xym2C7cWok!FewHM6}{eCTKX_s1Xwden!-d|(4anEmO zu31iK)}=~tzEVd|(0-((cCN6@XO%q+N8+$I$7?++1jKx_W>8!<(;%bAkt&38x}9D> z=*bukBn0XAOB14aZxy$cj9LH@CyaV_BV;S++I+0DOgf(hjFt8X-<1(Le&=!gS)cyI zYR`Vvc83C?Hh+11OWR-m(DoEJF} zJ#@bKX$OtCfxjrO;6D&d0N-vGn%-1 zYCGq{w}a$BI*-VZ|8AfI=h?p6BOEqDXVY}hd6(E3$yDr{<sE=7b$`izxrOs>7W4k%0D!cj%vg=84iML34DZ25S{r&T0=$4Yu+=E-PWBVaf+WcEC<2iLuWXlzuH*18)|rQ$7UFZm6!wiTb8kb!V9 zm9Rgpu65?uAlx+M#4ao95gyscv=fQfcaj4h2T2j~laB1ReEzk)+GmOWr<=D|dpQGv z>lQ;<12+zHD($F`=m$d{oznR>!MFkzF+975~?wn^IBzr*8E?*h{1C zi_cs}uD-`=Ett*?JkrL@4g#p6{(vGFp!AEX|9KYZdi{8z?;KytQ*&JG(;t%3F=ppl zLBP#yn&CWU`j9B%2kp2{=^w=(M})2wIec#jtW&?$snZM@vHn=(+Td{dR@7i<52h`B zVH>_fOGT9(g)7L7e#o-=7EV}%_?yeJot0(hs|DGCHLd`@BRwCdM@D2Kp^}w$`{VOW zZ#g#U9ht5Hq9u(0v&f343HqhTzpu0qw++KykplAs>GO*O+(^tJi!RN^qlg;eTY%t6 zeU)kc#8G+n^GJ`tBVf@yR!t99EfxjhCsdvpe>mJ4E$bjalfn+%I2Kdw6BUAGV? zJsP)i9(9L2o)}xcp(Ur?RLpsr4k5AG=dRxx6lInO8bhGzG9aorks^~_botO60SH^Q z{)SjMkA8oU?>Ko+Wne?D8dZF-R>&78axxp}J4Imb&p&Q)ZQkbonk}ZG-dB3l^a%Y` zWa?{-TU~D$wz`ZPnQyJ|O6s*jqT!>-itxZ~dI{;iE9?n%LCq3}X58PAL zP;=oQNKZMLqFd%19|?v&FPD~HsOY{d>Aa+Jl%Rk0@ww9NdjaY6=kR%Rk3V8n*axND1)k7n zo2HIz6$QXz=UhlHP|!brWI0_X!%augrp&_#09a8homh$m!A{W?z3c2FT23mQ>qJD9 zTW+#J8cc?l?Ovv4JLK~_ty zRv}G+#^E|2@b?A4H5norSFCr8E7+cQGd32JeqcyJgvXFj#G3$1%ta6dbL0Xs0k*#g zmZYF}WZF=?c+l;G@7E6Bk*g4suXDV^(c8#LgXxIAsRc0Q;fpD|02;Dt0h#tsw(bha ze@>=^a0kPgfEs48>Mk1bHIn&G1`dBhsAJjfW!2E7_7{|te6Gn ziCJGdzn9PZJiK(W8hAZshceGR{pBpxGMVhwCOZHIvx?~`;`{kPF^KUiiR3s#so7zW z-XTSj9xlFdN0eO9;cKuQxc5`!I~VWN^%t8RWd0b~Kd+y|v`hNq zIbOx@oV=Dz`|z|l9H(TtPXCQ}DCvbsP@>RJLr_T0vzKrN@xc+~;vbrj|%KKhz)}e>EVekOkqX z_<^&PKV}onc;X4}y;0*ye)6N63_w5nMt!cNf5{83G()rgDXsED`Ve&*gRw+KZURPDh0^E^mg@f1px$I&OlQs{XxD zEgjy-p(7%ZJ%qkQie(dg%0esS@nS5K?TM*QVx(xY8Q7L^q}{NB;Y3HgZoT(b$D)}? z*aZ72hYo&j7o`~L%`-q4#HRJJ9uzOggsj|eoKOD6EAj++EZUzk4=tom$kr9*S4QD$ z5DMjR$cQ*9T+mc;JX-xt66l-q@@C&7WGCUP?|uxq%I6r5w{3DdR+zNe!`_jEGIiQP zCKmxlx-w%gfu>{6yZ>fZS%~}>3(!~a>wZvz{XV#JyzU7%On9C+ut#!JQyBP7z#`3% zH&e+4Jm$rSNvn@Rlr2SaI+Hj7sX}iATxEKUdh@} zlpo-v@YO%4-ZHyiAfU|F5-8^%pBupU)&8T6gFGPbQi{LWZPr*F z0>*=T-{uG>qk8O+*n) z3SmUiwg5d=lWL{_s^9%5@8RTZ;|5dMK6Xkpz!OaE={#Y8{~f#E+CcJ!|2QI9Lhe06Om)w1zeOcoG&hz-brbCg>0En! zIxU_`;j`r8Wmz^DQn60Uh0{%7$7P6HDEf`qM%+y_cN@w1_EsIC?|iCzE#6_GDx1w` zbDHfrMUPQN&~gK^v%!M*dmqKF*|BdmA?Wuvzv&gunOqss?<+>CKaCcg1xA$Y2xl!% z+R=_nxbN!gaCP~Gvphgo%ev}a>(A52@q3{}v~=6!JC~f} z_Kl1Iu=GABBIxfF1G~ui-Nn)j4nttB_jb|6c9nAL41eF*jh^nO(X_nZnP?imKqBOM zwnVTa+p_LdCF9am)9tQUo%AN9pt)no1i2 z=IX%T@dD4OH9F3peioCWL$tKo*YX4w%>8|4=IpE=D zc?L+{{dzwg)ZG_5U+pH>5N1zVq~1 z3)-sb7YvWLys+fG2oN=BR1sPDI+9WCGv&K$k`r{Zf8%oemnnW73Ov~_vD2}~21PzD zwsT4u%hs!I2zte$jhg-ytVKN|AL?6U@Zd7*WqaV=YhQCTzVGf)zx6KZ>>cKLN8py{ zPMdI}Ba@?tv@uap`$)iLp5hsBU9{%9!1Z>GBEwAAH~fvNiG}tvw1~!-Z+bVuVTZub z_e|&ELWs#vv>TY)2~x;ja7I&Exa&Dzo$$PQ|GLa`ean3Q2J^TnyWqXL8MKD4Q z`7I6HIT7tam$BmTUoUB=r08tRGTx^3ECXM?uWyzCury6*KEr}=j%RBu1vgziu2ugi zevU_Y?lm-+{+xOXFE=Q&bZ#x|4v*hHL_2St$tj**qx-jphzfMrJ@Kw&%W@gBi`A>& z+@OBP(MtXniEB&ml_uIy=%Rd;I%o9AKw^$TI#BR|J2@!)7|`vLN8WMvz(Sc%ySw-8 ziwam3H;#TFBmM5N#V<@N1$u~?N?-~^IlnKbqGm1J6%rrrC4+0c~#Uv zEA4g~fw%u+#;^7ILbcPODX=Z(Z0$?h?aYMFtlOmvFABV#msi;`y~tSaf@HmTV2Yn* zqfhG3zmkeE-gG4Oa+t5yBos08cA@+fSGT+ZIUngyQ>EZ;qU~5_4%%x<5bK5-Vo!|+ z$sYEyC$>|K+^RblX3agB%sZ&2MS)@WYaZJ1;0L0jOX$| z*9C@49$Hz`XmRS~PMzt8pTyc1j9HdM_4AD4GyM1y_;7`rpdql*SABP_N%;BcJNaij zO2>e%oayQ&e%m-isUWKxV?nyHaGvP(B4a4nQvy`m#_yRzf zta9Mh@*)HR1PFTMXiy^h=reLxWpMPmq9T?;sBbksT|jo*`O2`l^oizRrpGq;1itO@ zkI{te-sO!^){Hk!d!qBTU}17c{j1S-K_MXwKi0qAl&KO&6CI^2n#>1m`%~q zP;UemFnW041r@)1oyICuWr4OZlzI4A4hGe#x3u-O>{a61E`Aqcewa|3F$ZTlEqrm! z$lMn;sOr^Ml~0`FNxWe<%g`@g!etVjwz;C}6tl>nF$7uUDmtWO>P1`a1ATtaho;!g zU#bl6wz}}mK^^hSkbOSVeoN667x=dmC&H0%#Aid`PYSxacR>Z*W?2cA`}uWw`c9|- zcRozb($Tq_QK6dr=5LaN>EDdzIwvG;qv+z9;lcBk@WYW1tR;omhSNisRN%O!S_E!7 z3Pi3_!sKo|UiE*m1Wu4ku{^slQGH_cp_Z4Es{9X1>ZJUalCf&XgN7?dS_M6fg2Evf zpbgYjq2!CFqfGwHT|V?ZVeH8`_VO{QvABs`JKL`e&fGG!cFn>LrE=FL!*G&un&pV( zANj;TvQ$nOTa1%Rg0VTn$x>SXdfio;^bz!!Syl|?oqfoDLlqWCMDiq{Pa$TTcf$BO zAV%&GIhv!3SDF2+m;>^TCDUvu1Lh4{2S0C;!sNuIH#%Q`b z9Pxurpzyh-4_aUdB5H)RA|A!Bea>nYsX_mQd{jLG-@R0(_GiTlc?k?Mj)eDOBxSYC zYOJnH7lTWtKA)Iiqc4fFvH^D=m)vAb&4K{;4P4n(gV$u>+*i;ISEFlFAmLegbsMML zFH)X?H6ff8ratU?w1;o%;A@2^x;<>J>j{0DmHpN#if&>#u@D{i?IHMi7>^UYHYc^;`fZJE(3<`ah+1BzN^g{9XYKb0F3K$=@^Da0`| zZI_rpIlpPKA0>7^XUf7YS_0Neg9(}wCrMvHdKSAecy~9nPlRMuFnCG8c=Xj$9!rS7 z;*Y^-J>3wLJTKZU<%LoY6+D806}}h&7?XnJVb+FE(PXH&$f4xZ9J!+JT{2Q{-D8rc z{P{;Glb@1=X2)U6S(8hwK5CXEZwb(p|C*zhC_7<>)ic7Ho(0m!A8(Nid^3myYbn+D z9|=VuunC0wjhBjES}U&rx3;<-A9)58o+c`B2mF{f+|5ZH|4^}!>dYE{a+S2=3V9q? z@1}-5DdvtCW-$8`pMKbsNl#q+>-xhoiNL0Zm%O@LYESW{lJHIxQ+qt)i-)%Ky)At(m2)Nopj=~p|T5ss;~b%8i0-67{xU4 z;?KF{mM=r2N2nf8a?P8S__(#8y=K=%@}@uzSR8Y!xF`EUCt2#XqvFD8Mq-h;&HEAJ z<;d$i!w~zMXo1)!r)UHsVvOl=TLOYY0GC6Z46HK$;n)hpw8xpoKMXJjSO!_ltz$b) zZ%*GYGu}}XQ%}vV@Q2j=0l}H1@qPCip&a>@%T1ud-6W3J$UJDF)id2wx;|w_7MB;v zfc$r{<8|%o6vOx|73IR+k#EUk;ciPqdtOtqe-ULTRf%H@3&MMH9;QBEmo)MxIP}JI z<&V@J!u#b=@Ey(>aKw*-oZqK)^Bq(*t>Ik}P0rQ)*SMyW@X)~F#v!zQxWBt9Q$WUu zj9#ju#vrC2XkZU3GJDdtyBKYEaInFJHN^OB(;Iw>(V5#TNU@Uf&T>_#84nI2?Rw#< z=2digubxrK5GC(4IfQ4N9Ae4}kqo1|Io}&PLtqajFe$n%0nLaKg_X+IW4Eiq2cYBP zLmh;>Yd>v1rb|I#R~SV-S8u3YT->4vYkG48#B z@3s1`S~tg)pw$1N!)tEF1L^#;o)Z%NY3>j|35wl6~Esu&95LZj3sfo){9XFG+()Z^Xu zXQ!OsU;Xb{fX~5n$?z)UyjL3JUaWu!=zefLm&;kKbbm%XH$8Wl2vjk<^1h;A3ncS<+gjt_v%q^$cQm1SdTi_ zw-DGXI)}T}Suw9whL7>sIA!mWRAN ze-aMgh>wYJlttck_6<|NdTj~l%&JE=BbmRo53{mTh8_p`{JBjoi~_tYVo0SJVc z%=_=&LkarN;NXL;J#Sk2nE`M00mPSV+QvP$?VF@6FyWHv&POSE?=~IwlXVyqa-`%4 zdb2)2dQ2HwG%o2kO53;QKLShk0yz~G?!!KYBX*^<+fR=ybT+X{)XD@ZnLs<@PmTK? z|7g=mXShf`Wf^Pz=Y+EO@1(w$(1*_{K$)-ov=-W4ulrvr5yM&={|z51TUE+F zn6eFbmOmFh0cRJXL871}Zyg zWtAV}mddIFtf4mzdKaG&s)*BLRYd3hIFNU2u)N{rF@{nNM+KJ;3mfx0wm`c(RT0pT zU(bvX6df_9HU3zRh86$HRz97*;4y_}Vr?t+IetS!sx4_G_LtfWAvKTEQLj%69X}G> zcSZBT33vUU(wjVPbVLl*dl$X^?)S0nQz5+4Ftq$F+!o96F#moH-|!Wx&k(8!CxuGa zJ*?ajol32#SKetWCV))${M;IZl73e8+?f3NLNte>i=`}y`qrQJR>J&+bfPo^L#i}u ziM2cv(;Y(^m2qI}3jFL=h1p_vG-gBnUH8q= zS`t%(8Vjr>*Vn!^fZ)?NmA?|jmR?0stx}aP9x{u}<)E45}u~V8d*p=oD+jAxx^OIk{E+6vNVNuujXIwiu@>G~^ zig=FI(-8Kxi+T^~RI^?=nePQ=d$OI`?D+fb7k@Jx9rqI9m7Y*IN$?Z52D^8?DM>hL z-%eH|FRiU=PQ;b%Dno8cZ#!7NX`Sl5)4xxrFN3Om8@GL5@SJjE@K&v0FuH&aAzN7{ z!i9_D>NB9~QpG+%A?)2fYROUwq3tcAEP8+Z~sOLAF zS`S6#XZuSFH|G^dPs&xXO_-maPam9pHh+B`Si&&-8T_N&cjv}gz&b+%JlkzvxWKB& z1ZtFtImF{;9q^x6p}me%aM2bIecUI+kjy;zTLAMfd^#%*1Vbtu(>Cc8%jJUJ&iN@N|L>&g{q1kO!@RT~7;n zD==+iOjTK=VpyGB-pCalC?1~a?D}1**&4j$pK z6~WU|N?76E^*-e|-->R$OZb?1ue8PYQgpTHa&3#*tlysbaeQbJo?_h>ew}x?|@55j0oddmIYRu>FY=NI7|iKppTzDxox%rd0y)qaDcEuP?dK$pvV?xOD>P3 zgo}tDj^|%%9HH*5xBRU`h&ZWGKOu%JwfJH*+|2!FA>eY2T}la`*5JSnt0VsY)mR_D zerugOwUI>)umcq9rNV=@1A<_YD98$_L3 z|58$slR_HCr60}3lG9qsKw$HS~xHgtppt#D(Ufx|QwW@Q| z?&mYWyQ<0QlejYx{uGk79K*qskNpt4H1sojthJfejA-GR)EC z>Z0m*l%rEIBlr*l{~SoO_*8#9B0}Rum`wh`3MZ>dNq&JF*umSnoof`MP=}phkm@Vm z%Tt@aX>)D8P#|74o!|K>i=fhqq(VnUW@L-lP~QKYGiG`Lz6NugRJa`RZ!%0OQFi;b z7ai0hqTy2H>`KY*i8bUKeax9LQnHrV7EYO~#~4yKgn2_^i;kYJfx_1S_J`wU1&(Aq z^siXEd3^+;|8t!*J6Z6L1E%JyOzjkQ4)QZ&CQsJ220E=sljX?5d>{#Fmk|-Vq4cqB zW;>a&jd@`07B>z$!RSe?XHH4?M-BYviJrVw=gZ_%>wT5j4YqkY&GCh}5dLKONdIAh zK|^m|n>#z`qbK>C#p-+K;bt%I82L?Yl{&u`(~(g29MO7zl(#YgNp#M}t12*yjZvw} zub-$jmdVpHKqRL^m%K%YWyGzuI(u0Kn=HsP*uF$(Eg*mYiBl^oi+DL>CsD6UM88~< z@KJF41s~_mGy1Zo%nndJSpi0On2IEQ_^GcX0a1>EA_F+-mVq}GZ5EE?MPoRCWA-$E zb81BLKgZ+oGe0J6rtqEO?UIVML0G8G^!BI2-0(=;4j4S>>fH`8%Z zGIR=ra*PIlD_6oE83IeUDHaOOhtm-sZ$=KCF<%0mt)JJKe4@qGouWk|wATw)#4?hf zrwJ`<|A;J>)T%FiwV!dW;nBgdVTx#`NlM0RCgR~Jbm)*ndjx^&C81oJjRDPnC;^5; zOoO8&XJZ8gdOI zzCS&OwS$adcnpuYo54+F0019|;TyMSs26nt_rT2@qFr@${SCq9&l&1d5_g}40`&qSFGe!XoaBG+z>IAshcA+Eu z&H{dSn;QqH2iuXKuK|v#+v^SPBK4r+3TTG#3;VeSdq^su>F)+KkZ}<2vIowS1ARKY z50+wrT+z|K0z)6Nd@qbWs<2_7l9N(^{&~kI^HCG|4s^8xu-gT&0PvmHWu2A3jU1<5 zj5Z$3CV0|Zbm8-L-9(G~9Fx(O=kBL8$J}h&IZ&?}FTgAK0%E%Vd$u64CcOO*6KrL; ziz1sn4Bf4dX878hboYOuCJu5~S_b*hKAIhFEZ4E&Cr?S)%=%S*F=BdWQKny%DM#Db z5f1bpuH+~N%k#6U+OJDZd^X6_Y5Fhr0~CtXvIYY!+VqS)$sLt`# z>4F;)*Vwe;_BqBC)~b-tH*s0MtG$#swYq$*)w)iN{h@aN!As93sO_ilB~u|lp=g|? z{B6wte#Xe%b8q<+C4TG8Vzj>y>9qT|eM39~mZfLfMvm=nJTC%5HInDO zl&iKoSCn601@Z*8V@n(H1SPv2u3$LyI>n33qugL#2k^u~Rl(m*$QKnb-z?siOIb(1 zt3nAvyG1_1bLd2G-fR1r&u69oKBfd%v9v&jq#e&5i#H0=?}iiJF=}Lo{a0K8xXL*y z@3RDgIt!0&cJV2=$GbZ9wCQ!i3EOys9tW+gblxgMJAOvtj%0`s-TIGsH)EZg*!12X z59c&6_}@LZHkm?GWYatX*NUK)-85h^a0}W_$rg)S&M6E z74){`OMDrs*&Q`_&D%aZ>$8ITTp*I^ctojBVF{$|=m5^29Hpt%0t+=tJ(3R~6kbiO zcPqweDDs5cqHq|p;om4nFuZGcdpEC6_(qO^WRzkYZFlO-hS$#yrsS;G?kyBw4IX)) zpvH=Z3*TW=21_O)d=AGM*AzXe7VnvYfdxoxG$V?n9PWtWy1p+Sm0RI~2i#+!hG==; z9E4oqTeVW+Jp9f_2i@@pgc3M)!w%Z3qWQ9MJ_S>ZUl_2X%63C>h$c`Ct#J&kYSLLE zo}4YH&>W(`JPO{-Dj%2avCc&XiWy{}big&!$cYW=^rA3guev~ID^?`V9DJKMB@8>b zd(yT)rn-8d)s!CJ)B)x)9sb|50RJP4+Zs#fN%e--2Pv;9N`iB(Q_~PVHOt zRgO}}eVRT;=^_Uf#$5{OXS{!$!YgO=Pb`)tzvgtf?&{ymtoWGm_2Qr`<7*U(n2@m} z)^W6O#@z!K8xP_@x9vj8?je?sUl#%2_+O34(lldV2-}_rwkb*b9UO7hpW-;w>O;9r z;?RQoK>uQAjVU~RC4PtfoIU_a(AGOk{ga>3RLSIVKV;y}-ex$!f~t-@`+9@r!c)Gpe#$wa${-5Dr@lC$ngNbc zdJas+?vMih5x#NeL*)i_9^3w>lTzW(yVeud?Jdn}7uT>Fuk|hBbm{#HTLjDH;Nwd( zHG}HsrcL?>9T)VLmuK9Y;}%kAgJQ|R7f-gQ1m{nG29tdQ4N>W)Fr2vXq{um)0j&m* z9Y+)CiE}ymfHjjeeaV-eq?{9N_)n%T8D3Obg{r!GUPo+qE@Y>xqjff zhSsPx58fmX-aU(01^3PIueQw^`QTUzbR_@p^+j1CW63igBcxz4;IVMx6@rL~cFO+p zbq3?u1iXf7$y;FvwV+xt6j}D3MxGNuP`TF=N%T6rS6y)Sf{UU8UGbzHN}J0g4*sQcvqZuE0(rOB>B$coFOhoG=sD(l@Gy zRt%h!AmNCf0H-6dw_KPaTM;kc`hh}rIISNxWNoaPh{jS{3jwAao7_ym| z9(5%V@}g6}N&o}0xoZ%vbNAPSc{372K3zsS#KbdXZNPr;1E;+>N{p3i^# z&BQTsLffK4n|XdMk`MKbB>d!0Z|F)i>ytb@44lLIO|vFu83e}l*c$uQ%^!_jCujag z1<;b;^Cyng7SOzA;fqeBl6aB}lJ)wVob}IoH;p`QIM>E(R*VbA8;76PHc`|X%)Fad zJM2T8AO}IGJbSjoox;4k`bQ1qT=RscypcJYOu&wLhj=zhP?sg~dX7-tgjnX@Z0zXA z!#@t&{IBTpG=GllB&HDl>i17%I5^;XExb1F^u$s8m7`ViPS*4xMn!Y7$4>_(BA&tNO^yJAIIIohQVXmRdZG(jW#J|A9Dhhy8rvq97)sH>qQ(^m$@VEek0S6>S>m~BGg59XE%@WL%vc&4TxsZV z33&jkI)9N5IMk&st-b$yPOhLh0zaf8R>9iSuET=r?p)MNRDCw4Tw4I-zUaqjB!^CJ zBYU-Rea(xnk%}?hZcF>pe;>77ghu9Q4x(!3BmSyU3P|;smkA>56`hztIxEAG80N%= zIp4}o|5R76oZ%4e+`j#~Aue&~w-S);DJXBOx;?&;Fd>2NoT-U2Dp_A>kz9%xY~g1^ zlSj*@6qb%@THFB;WHFvJ_bXoogN=?pzF8fgH4SKdDOAq|*p+t!V%?D$O5`c$H6?b*eebOxMMt0<>9*g56~MJ4r{g64ORmlRdFEZK%uJof-3A zI4o$FO^P0s|Aoz43&EIe?64s%iP z25&+CFY2HXp)Skt!A8wz*wWvX6&Q)?36pG%y$4c^JF<23=QvrHmA(N8=u4D3T+X2Y zBEdQkT2!h73Sfmq6j&`npJd$=H5iBUGDL<1-zWC7wQ;ZE)n~NKj?1*{c!lGFYYG3D z-Rxx1!Tt zB+(ME|DdZrD4eXX9X)1$^VcFCSAl;nmBnj%a_jtBi%bDdAcO>UO~i~46M7Wd=MhG% zNPq-|C%)^D)e^}QYmw|#2tvpQvxxk^lIQ7=VL#11_Ho%!UuKeh8bB=LYb9w>=8v=U zAga10E0g9jxv!ykE@Si*mOS*BfvaCR#XX`re#gt`^@9Q?XVP_jWj_*@kg)3D7m8K7 z8%p|JC|C+__ZNE_Nzl$}Xb798cZphpP}ta|O_|n?hET$?;`h3=c-$GoVx>sIdI9Ff z&dKm9ld7?N_Ia}o<=Ozc>-4PppEvSzw-0}MDA->XA737Q@tS)DL&Jf%)3usZBu5HJQwshTDAtQ%An1CWHGslyJT7@wpg!{XmEe<(o3`bdgZuvF zsRM(+gNsvG#|`WlVs3ghsOJIDaM5w#{qZdCrApX-3ln$`2+EZm1YE%WUYxca1gKvu z2X)+%T*iUh3D41H2ao(9PVH9|SMhTJ2Ywe@fWI}WAI{ftTifo2sJQMk_TEwRSoZAC zYC)nK?FW-NuJ4u~?qb?d*?#N3^j}smOq5LXbFMaxTk!81gU;-07izCqT`snzwK^P| zGR9kSe0Mkk?$D+)!2OgU=#~P*+pk7|hOVVSjzFJ?p!+6wb5`Yp+Wd7aY=4rcaUt=+ z>{F=crSbgDxE#^;cN*t$BPep8KdnsY**UtOVcs=%LfJQ1l? z0eki>K;7f?@*-#YVg(6Xh8cQyk9c?ZHSWVMFcy6gpQtTIdA!Y|O>3nO$3w6811`3* zVFx2$&>brw__d4h185+UX8Eu6-M9Hgcx>C|q}L76^QDMI@5yj)p~sNu$|kLgrH5Px z#eF7+=8No`X_{^HD59eh(Q*E7xX@AHKd9d59rC&Yk$1CncOUD#z=3YRJFl9!@U|OB zWNFEex?Pg=M#E+;GmL%@<+~#Eoc_&p8pJ$Y&$Q=IEIqlWzmvMV+WMuw zH6*fF4n8Q5K4>xaUSad@x&jD#o)>MWcLzc09S_F-&+qp;_osk3nb-B9z3D?Kw<+5# zo@blSZbkWx--W;W#mnUz`ZJC5GSfRwDNn`owyG(S^Njzf6mHT86ND2u@B#Lq$&h{j z#`JE-u_Z~sjAp;5gWH)Qhz+q8SWf_G#HwunW93DUsrPfK;H?Mn5d>UwH&h^b--B#E z7|9Cg4O}A%-ETSJ?dvw4buVgHzV-5-VJM?Qwb%GV0Cvmb{sDse)j1E^%P{j|5!Qhd zw4AgjvV7l!5AEn0Cy)p+sjy6@~ud4);ai|m81Cy4ESum@#egU`t) zYuNS>?4XS;UKPCz^R9AgJA?0fpBthdUS#@Wcp+k3FOB_=V2ABwIZa$AN3R!yg97Ln zs(E}!?EX8~0On_LzV__Ab(tkg(ofjbTtU9Q^uR-$vk9%lv4Q3ArKzaS zM$yCT^4Y3ECF{+VO4%0KpnfHYsjqUn+&K)KmTfAF>JKNsj4D%dmHFW63P-k$Dz(e* zx)!C@gh6}tzGH-xq6Ll8u6NQC-R|e&r3Qs#Ts9C$!rsdeu09JhzE78lf(S{AEHnSY zo%r|HnUGoLN~0&7O|w1Ox!EheEtC9L?V;P|b$f0LA+jtEJ8oyQdD&_roiaq*_F-Q0 zyx~wb*9Oyq0yWO{;6;w87;to3cef1=G=BU(d)T3Q}-p^ zF2@RKy|0V)?%b;RT7W?n8tuil!baNEotB%I7ugeD%w+{$xVY~w{2x+Tn)xlOLY`BR zsvnP>%4O{GVoWAA9QTUp(lQ5pmTT}d4z|cheh7)m42hK_K>jkomO{6v>|2puf;;H;Dfj7~7M<*drc00dooeP(=QC)qAku3xbuO(GW>F;} za?xk0^%ITyw!QlrYe&{aN^XW(2jbjJhi=%T;WZWgu*&2_yNCR&Q-~---clWtWZ#j? zxm;uOn6Z^$IQ@x>W&!91{nv$oR{y%F?@ZS`2y$)Q*n5pX7%?JcXXMz;PaFH!+daz( z2aM!&yz}}$EeJ96>R^3H}3k)KU(vWUV_3%bfIIiH>%<58(Hr5k+`QD$(sIs2@EnO zqI_h;anp^)nA7{t2IW9Y?GfGRv`(MKQ%frhd^tm=uyU1Ww8P)YkYGalI={a?x9C>MC!4h^_2bqi54$q@_|zj!%w=%oSYdA&@=zX3uqi7 zA?BQzLMCKUK0^YtJocb_3Y=E4ebiH^kYdc`mGXX)!`*tkfB;?+6$(|pEnYS#u6+V1 z1e)w4<7$FsQa|u1iU(x(%oWY_5;nNjgf1;~3ZF8QLZNz-FhxW_N?yYffh*1J9&1~0G~f^Nno7!uS2V?+#Fmu%86oR3>c(_aUDET=#vGC&7O;^ zn_;OXS0Pg}jp6BuW1K(*R`;y-(?nV1B^||GV4QZoxtNIQNEJa(=2T0uT%>u6; z4!jlK`8zy_;joV@;hu(}&oE<#W+_PCdd^ChknB~4Mi&4Rlf+036W3uqAuw!oEN)qz z{a|aFzPH-Sb7IaWE@j&la#Y-c$wkswnG(q!8*Fi`^AUFzQ{xCp_p^iYtP#Rl zjYOBqx1hwwuI+TwdUp+{CojEzo@jF>vs1FyJkQObE9%SGsE^R-N&Aw`PMrqNI=cE% zu{QCsWYU^^OTqi)mU^5zluYU{1dz^~#c>XOGLfA&ig9g~bgm_7%O$ViH<8-SPj?=tHG{P@FTRJ}&fG z$f}@4S+}_Q3h-hS@<8NsaZ-+4t1Si2cHG~v{qS}`+3_-%hQ)8l7jT1INRof7wk3L^ zgmMUXOU6w#D<7LCZVO|3(%5ro4cayyB(24eJ$?U8>p1DBhDIu>O@kXDkkmV#=cYRB zC%tD08%Sa+A!HkR2wf&k%CWx53JxOfI^f?e2Bz1I7buhB2y%3Q`Qf6{7xb&mu%Mk{ zE0<>k1hH$Z?=#b+rw>ouP(&x0_uL1B<%qFCCJ<^y_}ygkfcCl|aYD|7VaJh;51})R z_5F+PcRxir5K=-yd4Y-{1U3@^-@WN=q{Pc2-pnx1zfN$m=xbT*%tfE*+fbFCA>z!J zjy%$I?7*z?7Hno6I8|ujJ}*OmsmN9i(s6KgH(P1hJCS<2K9D@>9ZEtM9U#e8}qhpO=lq!87%o zd-jg_+WW{^NuSB};Q{$;&tinNRGC#9^q;VSgwNdQN7L9bVe^iY*orGDIn%6x`1tTG zKeUG!!mL&72qtr4;l~3Vk}_WeayUgLsQ3SX$$4xy>7GG{t2lEemOM_Xa8=lF24bZe zJUwzYpK89O&_V!r%<)|8OOxv_dY5iw=|lOM{w;271A`6i-p_ZYYCri6NMT7wIm~EU znJT%NRiM9VS<~yK-?(=U5|nUDy?AT$3Ic_x2Z{5YU>s<(i&zgP?f5!n7cUh3baXRO=5Q};IzFvYYH!wbS5-j6~*7P&e#p6MUVNx*O0Ps-m? zG3d($W3=n5n$v+1&xU?>&tNI@QpFYu2#Q0j}rNrpu*g zR2a_StAwl}lDfh=B#5iJ3H)-*SPq!2=$4E zeno`b^Gw&7BYhWx9-g!S(#4u)zXSM(|E9x>q^IAD1Q-}Py?x+m+<_w6RSY}wwb|6S zJ8>BDhwlt-Q~n|2r7QpAgDs61IJJ4!-KNaE7g;VZ%JvZtYO`K+DmuGiOLn@SjGcFY ziG;T8am~vbN)j)6Ge8%Da`xLVmK?%60QBR${W{-~(_*bc<6;ZeVq+)jz3+3v@)@dV z&l{Vc(1lvD#(%37^%rHPSEaW&%y$i$0=(|a0TT#~lG}+qk7_+9IP4 zd_oKDeg`o13yZM;qJ=6s96~@W1u8d=R~kCCD`c!54b^u?r`#a+U^uPlF931jBlhK|NC%+><=wZ$*ptk;_q{`Pgi3m10$egI&6$Dw|n z%b`S8%MA}w5jn;ls|vHN3XPK@PRNScW8Faspo=5O;JxgpzORi~tJ3fACk=S|X^2Ne zbMw=n6Fh7m(_=a3=16K+I0%3xxZ8}4wmJsGc$$ZKJ_apfOU48RUbOppjy)mDy=ga! z?@%)WlBe?ywD-O=wbT#U0s$@i?I@?kCrjsFjK28413&ohw3E{aqlIsHEc^X$yh-;M z2-y0-fhUlTf|1!)toFsC{h$Y0NQdl50485$w`rT2h3okjesB643iMKgJyGECBg5t+@l0av$yhZ7o|HfvStf|<=MA_sfq+xE#I3;MV9oE1K*jqwS$D<@seM}neid_wUzlw zMn@KDUxuG+^=4(BLBd${lE{6VzxKcjZZE%y)BYwDK8ff)ze;>1&eCSJagG3`-{rK01^}!cb5NG%c8NS+vvTaf6AU9bk3Kj9bDUC zhU=fKq#h`-SxdYnrx#|Z+c*R@P`R!v<$Rqnwa_Pj2e-)?d<^7IeFJotkxqT6K1zj< z4&F&kn_`WfXB^~*6?ow5D_}6FVbv_&vE6oQH=QFV-j77jIG3VN%XIs(hnx+Q8r~6X z&q)Qt7uED+j01ISgN}{cuC}`4ZGSq}RBYyNd5{s0YsSJ4VEl+5hC>)4dMZyj1jl&6 z@(c=L3($oR^K*x>+ngkh1p%9VYsUmmm<~LWgBK}U362rCYszpwVZ`S<3WQ~(QoU

#S^5-wcjp16QBsMVn+urTFM@;K)e0ETKSV7+iY?Wa410h zBv@mV!cu&>$t0y`_%ua}qp3VMNb^~e@Y6GWv$rldb(1-$jXVjdb47J8bJWvgPWUa=c2R#9FuowEMJ?2l^2 z71}EHWrppN{2+d%z7H!4ebamFS0GHkuUr=#UoHwe)XI;(ay)uJD0?%+Zta?t+Gp~^ z=fWrM&*z95xz0iC&knEpw2E{v8FOGGEdHwc>TUq>c)AGGfg;&92m$3kb3Bl9%W;KY z_*s7$$Rz#<@ocF8Agc)o1FcezRim5}9<_+SDs+w;w19+KZ!ma*z3V}o#~M@ZK38&N zr%Wu>pF(}ec>itcZ}-IO+1<3*X=O%AeC*sX($Iz^!ySKyiB$<~m9V4Lp50xLqfRlU z{o4~G^??;HB>|trfh4RaCF;JC)VUcLdX^wW;^Fr{gd5^D%7YEhpY3?W2<=2iT(6V% zN4(MV2c@(qm5dt-XhW2~5#kTz{Lz~>&@zo2=;@@k6cFJh#Y>qrnWT?CdEweV^`i45 zhT_h7M1_3OiG7*UBVc%tLF}2p0CAomVz4|`mw7`HBnXv_C;iFaA3zmx*Sj`lwEXDc zBqF!+BS3PX{SPz&#qH<%CUNw^!!VugJn>tXqe~k_je)cb(2EHt_lL|Lv?liE%4TX3 z>_!y3=6}bX@A=HZfy7w=4BHT$Sm>N%R79ppf}9YlIn&cniPaR(zx4hM#$9b3NqM(Q zXY=AnB1i{aaUvR0X6p=K1r0FDsrdfo@`1)zpfAOi+j&$7M``?&2E}RLhRr4%ZZoK8 zK!#>Kb$~%fd0~%?8Y)|wyrW1XBTOk$-A2NOq&w=kOX?}cUBJO!uK@zx1dpEq{<4rc1! zYiOv6Wd*pH4fGV9VyhFm=cDO~(R29`PmEcaxIWSVQ`EM|EPaePXO3dIQ2bq_1j!=w zV*%N>D4lUWI&uZNc=oOS#HY2Tp1+wJ=R98^!6EF`ugLML0knoKJ+f+SG2dq(k~W58 z{9s%*5kw-he$NQX>+;UNv(qOh!1I8`T-8`fZBOM&5x>x0!_n0pxPvGSZFdo3iC5=H zppuwp5F1%K-nJnvSx@Vm@mqh~)Esx|y&$Ki3>MfmAv;!x+o{02CCHMhGl@nv>{q@3 zJ2pOaJDP?6p@E>cYgUjV`oGx${}bQ8#>}YTvEgGx=Y@er>{v@ma{jLnS8Xc>44mH< z7+!(!k!G@}AGZwW(N1}c9$t8ZZWrGl59fYxAy~?r)l!)yt_>396`pZaqjeK+QN;Ab zoDCx@ZT#r043iJ4P7UGsQ2vo@?9{$rFaAW1O*Dzz{vyq~=PDIKJ+Z8khM!0-z{o;E6`Q?MT zJb0rs6sL1!Z3VoC+Z&eOgnXv7ovURrqp&t~h)2%{nRT4EU+?@m4`_}F z61O4tqN=l<01a|a99s_wnRm%w9Z1emL`#bUHyChCsSo$;C5NB~x%g&44#&$u;%@6M z_x#ojUWN`sjPq?~ogtbu!~KIPTtWfYLUf{-Y&U2x;Oh3xT?utkg?zKB& z%@oo?IUqe(?>oYIMI-|Z_4xp>4@TUm16NPZ&@=V`kNUdM^m^+0ys@LOYWe;(Kuk8B z1RCl*4|@P**B|__$L8+nYO0nk!Eq4@;Ad|FsBfDV&!0Z%r0g}!dOZY`T%DjkPpom- zB2qlXu8#rabLvC;zrfo8|5of}C-M zwuA(lCZF*cHSr@HMq^w%GBSX*HDz6C_KrJ0h_~a`E#Po9{PJAp+QxKqbR(|q>Nf?i z(bo~Zmk_3gJs_hs4b+5i^sn7k3=S)WtwtYW7QRqL>6Z50y2d~VUSp7x>+Vza{ynXQU zjOz9MbjgL4X;VmzJCk{&bly5eGd zP|MrcnqYdC$aTVOrf4{b+3Yc=g{N~YpER_)P?81n+E6y{i=n2r4>#RZCP@$4_P^p= za9XZ0?z_1l=TVHOA8mo~n6jdcx~$xRmErP@we9x!{I(&{(G@Uuh0j|59{_Ygi@x(@ z8haC^U7Xb%A&j&JB+t2iYd5%^ay>gK=Qia9&ld~>@uIP3&u;D7jli|b?AoPuj-2G zGo<~7{{G+pyZWd9^q=Ve^FRN;!2bXAFMsF%t>65={4M>(|LXs!KlP`6QT__e3(vfH zmuTh6m0Gc4g_gpNC%**?=I0BhJ$v@Z;(oQ=o?I{ELTB01<@CS%)Us6bSd90u7;WFV z1MYTe`;ML30e`1Ye7+JLNQ**x5A>s+y zeC?nQjdMBs?}sdc?rZzDFNl`F`IUEx+X+O`clwr|GgUzqac#>(<5%N z{azTa;7;Q9+i%xj`)j|Z|Mma-zv%b=G#u5Kds%n_vqNMw-iyZP%Y=~ z?A!XQfAz2CGF}A#%3t{_`sUAkQ~u%Dd6!(Q$&)8)2>#vv#$MZOzJqqz-fnJZA@dWE z;&zx1e-Y@o+ZPep-bhJOsG<)oCGED}N^Bunug{69fajvY#i=N0Qx_S^y4^PGwclB+KkJp0BFXLRb_%5; z$#sdXkNv}ppAmnMgYVg9>#&cfl$26|B=jfI^x99r_ZbVuT3l~ncPc_TOj3crMc z^K4&*BlARJwkJi(VNfDh8m%dDc;+qzEQ}oL=&-rk^LoVP{0-^oUTid6H-bXpOI= zLAGrXTZIimoNuw+B zq9`=M{{eN%6!}j1Ti^PY{?_06oBEC4_znHmZ~d13v;XXuG@m=mty^ExKl<(eQUBFn z{8jzxulyzbjlc2h`rE(xf7RdnyMJH5{oB8-U;p)A*RTEBujO)o_wW8){k^~U_w;xE z&fn30_z%CQ-~HYHsDJnG{=I(ZU;Zl=!GEg1`Rl)-pZ%Gi)7QUtr*64rb6&)Li$%|O zv%d4Y<(8ZEU;dZ>h5p$=}ydPot(QAi^ke14AGB4)P&7wK-1_cTx zczRKe7m;MX1HYoHRT=EkK5+rW`XT~cC?e!7q7EIe>&XQv@34|{o$fx%Iy0VH=})Qg zUt3v9gSVxtE45V3YY7X#^BnQfk(A6FVUnjPGnL~TH0jBII%Eo1si^g6GRh!6mIBc_V-=G+vOlrP<`K6;oK%%i1BqDY~Rl7fGj zmAL~hjXUplhjji0Q?-7>_4?&s{x9^me&g5m_y7C9qpy5r3y%xW=wJVD|C@e+$9p%i zm|VAhgZ}g{{pb4a|M8z_>(;IMh{uWkHTHfFK5Ptn&ExpC_68s8xC!PYqEJeO3MOOQ z$m@r{+s{vf205USN?1LmB0K~^_zeDH+Ap54|4a>)t~$2 z|6KP!a1ZBq%a0?kx@raQCnw7bncGA!DWWgg=@4HyRrGBrNRuK$sVKxTb5UVH>96@L zH8HBdm_OWEwzI=sLj)!0OAWRXo-IB#E{9+uLP331*aCBcV24y0BK67Wl^WGgYS@}c ziU`h>?Q+DnapDB2kbodXEfFL{zL?8)(Erw1VOK6EDctYi*yWF2`rPptYmC@x9JUb8 zJ4RPRZ??5kSr$@dpR97W4=&@gDwVlaE?t7pdg0Rfqd3kTx43?*c3GbrS5Y{J16+jb zmLg(QV1;-^OPZ2uw@+apeM)+pJYXOq7*AD}h)`lcTMFOmGiY%;9KOQw%RI2`oC#du zpfS$>?CcijYp_{QL=4U(Kbr8VF%dDEjw<2Nx$eRf5qUY64C{;t1$O1H#}x7wQHPE< z`XcHy*K3KW&rxGomWmNpkq{Azh}^b_$nl7f+g34njd9(Uh)}adM7A>`av8B1+epM% zdPL1Fkj$?qnTYVI-wMmr~kWt7n8M`z9`6@@x1 zK3@2W)Kyic+~2lmgvYym7A(k;+i5!;nq%8wi3sI$!lK)eB^3-m&c$XtP1J`Ue5fNw zj%fS#9r~C5^S{zB|G7V}U-*ST&BFB$^xpfY^oxJ$=ksFrZ~xuD)?Ihrp$jfJU)^q3 zMKMG>6Ll2C3*v!R)gg7*raq6k9J;QOg}R_;(Pu$>zxzpi?d9 zRsaAH07*naREh{WFM%nFfEL*J7Ow7i7qGLv)&3O2<#UqZeMpHTlJ^v1`_>0k;}itBWqWIDfq07rong z`RxxR`~ukn*VxsouhN=TS83gvwOX}ml|K0J18w8Qw`DuFH24)OR$%v9blUbcvMqio z>=(?&y!`SGZQrp=FTMP-Mn=wR)yfrGLp%NMWzE`^TD@ka&I}K0C+}?hqTc1K|CLwv z>B`F&VZ$n|Ub#|hR@eHMEnBMn`}fP7Y|kGM?9i?~d-Ct}ty;Z8mes4#i>zF=f_Eds z+|BSZ8}43&lNVonk#_9NFZ6BeTH1H@+I6~S-PPE&Mmt~GqnFX^cA6XW`0l&!>Z+^Y z1OC>oUZXXu%;6f1oE?#E-M(XoUWUURg!}frmhZNH`?vq0o_XqV{nfwnt15XP_Ama$ zztGpeey9Eqf8j6cU;ID*pL*nx$McKz<8QvLRm-o^)oa%2>ecIXjcuXtr|_t8&z`;X z(Jt!PF59wg+spE!zm@Qj`LjK1-KT3tF)wXbuDeP-mCGGb=dFs zoVx}eFTAq%HTlcBS6|(yx8Hh84?XxGk1qc*k1&5l{%NJT7hR}d`lbJ!{^39TEq(Kw zKdWF;e);9?I(qmpcCX0x+F#aS%PQ>hhb=F>_<~-1@p*WE0bksTExR>y=1hEJE!@$c zgT7p|cCB{qvTtn5{F%pX+h5LKhBkaR?X>Ow?Y~`ncG34QgWskd*s&Aenl}9c{BNb! ztXZv<`0UD6EAyAQSvUG#+PRxDJ91tAD8>G{3VUnatK~ku;QaI9ZL79ze@QRz+Ae?O zu?yS$DAoRNF@7x^u3586hq$A)pX~5hcxgNB+@@W-cMSYwoz~Ky>(;H+wbx!ppUq|* zzk<%4dWkXl(#tP_e@PQ34C$&B1HXa`k7d{6cbE31?fBF-{C4Zs=e3Le@<&!{7%ywq zuF|?|*J|B0S8M))OL*V88@so ze@;v}*W<6QF1hp)EyRWe3m3@YWrTjAe(2EaI)Lr|BF}ON{THI!b}U%1kb$~Dj$g!t zYCHG&v+dXRWt(1m?N#{)Po2MTp|LfGw)@PPk7(zwi=K`@it#nS8hB-#h$g|LmXXzx%cSE-y$IUtD9& zo#ny{FU)sPwY^7l=+I&0^<0M+0%Pn`=4n1Ya547pr%(3b&x4rw3ZfdP+GCQr`3u@GOfPc7hGqB%8x{x2Tp<+XkL@Y#bp`sOiR z!q{23V7}(hzXUEX$-ETY_4@Poz2IK6zrx=k?v{Pm>AEikf64qyH6Q=IbpAXYK6(T@ z_RC|z{eJ*^4r155c^78RZTltk&85^aY04zopAKN}{{07Oqh+6plyd#%#o{uS6I^&0 zyAS*UeCy!B!}5P;n0w)DU1}SU1^D0s!VAv70FDpkwjE^59YX92zGGXk@G>o2csblG z%=MVlW5gduyfKQad*!nfKX8+!ZEtMpx7Bp9#mxEQANM(N!y&JgIx{_kFdeM*@S+x&Qa>|M%`av!_>A?W(m_ty;BK#XY-C zqljn;ZwmrM*?8Xj08mjJLXw~84jp_+#_b97Eo*h)&|svH5J`c;rAQM&CfpR>7RtOe zBxqClmIb;JZC?Zx5JLt~Y2KpCDwVjUQr6i(Su&?OSF$+J3_jC&01;HzB0^Gt#6cx1 zqfNN20zXCOL7F5W-q1D+NyIAyyd`BE%U)JF6)hW6WhY5dTRTN0p(vgKP&uhGQk`L# zA4IEEq-m-;WgTF?BoXun<3st-rL;&Fqq)v9ou6efKSNu&6-6EXdxiLi-~S%hUw=Kk zBE9LRTk(Z2d>Oy|)o;}CY>aOouS7kURi=20M^%Q3>eNd z=-an9x;J*!;M)_!h7H1~Q6n+xs3QdZl@RUZ|#M<%_Y{qntp(;eZqOqgipNS)KQ;-9zOj5ojaO*reUv#|Ky#W?BYQ*gr# zzr%Yjd>4B5=q^1&{3;@sf~6bRDa$go0g)vEne_-Y5QLf$KC_{$GlYt;+eBN2U;R{R zt00SV<+P-6+W|x>o~dLm%l={;_-u^;sg?@~)c6QR)wfWHvSh+drQb?xo9a?gITgsf zQ7i_O;&x~eL9}VwCR=S$I|)Z;Xl{d4Wn}=AEw&V0fFuAVf5^n&Hf3D%cR7H{1jvGD z)W-5eN;U6+p6>uUMm^ zcD3G9g~Eh+mZS@BWm7&%`5B-ZNQNBG452H9`76@-Ifw?rLGn7Yq=8IkqyU+WIFk+A zd2HmF9El{z9E?MM37oedl%Nlhfin8|fSim~(dby2BIYL)-DeIWh`lIcG=7l;nF$#0 zGv%7DqO%tpzRS}YGm>`uCmC_=Fp5IVJ30&F(lV%!Okpa>G81OvZJ_XJ5`{|Ahr)G2 z=Fs<%sUqzkmy<_Lub2Y?NhD#vnYk=?%Bj5Dyi_H1K0*Ydyw&tf^6ZB!b}W`zlEDC7 znPf4(JBieTj|L-ma6=CphVTF2ySU*$f2-O2VEpozzr-8f@CN+h4}ZXxEnBo@+9qm% zk}H!Qp(~9#$Ux@Yvv%GNT{r*qg;&6SO7REZ|33cmr$6E5TW-Sq`FG*&MGNtZU;GST z|HfD2!yupj%$2zE%ByhIRiDOx{_a0<%dIzK(V|7T`|d^Xo6>*xyWc7QN__m|AH{j+ zovZDviCQ`Jfd6OC&4XJct-IGLM$n&JXw&oUW*|rT2uULk6UU;F-$IglT zCuqC#iYq>;mDya>)ablUx-lU!@65>TQc?PJD7bxOP>B#hGzepjq z$1PhXS)3n~7IRD{eY%|uszA7+0e#x&uGHB2XjD1);};fPnJPT%$&`Kt`m*j|zl zkZ6Jug7Iv(8jQuOtVvv1{*W41WjHt5t$5|1m?Bjwlry_(ZreN$v3%%qdgP%vDO`pA zka^tSRdD)&VA?9Ais<92MIeb-o!2FQZRemU|FbhG z_aXzRKUqHPOg3%<>C|>mJcI-gUNlQ0+Gog-Mz_XIgi8unbjGvHhD;8g3Eu;PP$3in5kd}T z7}F$!d<+p!9YiL8t|+_YA<)@l$r;@FqO9Re0{bc;)$KQv4Cgs*!Z^gOi zo(DhH{=^ecprxfn)EOvQgMg&!ohXe0$(=E$zz5%tNs}gMh1ZBuNdu7T=K29dwcb#i zvdv6kSu2_CTeo7--FM^4tFFRzKlp*pUAN-Qvrfllmwg0B>3q`vDgd=-7C|xb%w&L4 zL2M7VOJD-Vl>~rF1`ik=pd^wo9!ZddFL%-g<9W~v(O8wEcF6>aNlJ)shMYoi(<(1h z+sC$(EoJ~rN(RI_h5&{{siIOQEw5!#ikc1u?M4(dh$ULV1O|YF2RqwdK?LQAJ4k<{{Zd?Xrpa}sZ_9cBf{t_%${0hZJ?zV@Ip6Z$N#WptcTm+I~txhdaufS zhGj6Gp{yCI<*xFLag~)M2`XB>w6=-2z(1;I{w_1}ZI{FN#bQz0I^|e)n{dnJHmzt{ z<6F|b{Zm_8k}M@{1qrlGM!Bqc`JBysb2-Y|E-FaYI+$lkcn%F^&7h;qT3z_<5r*cL zrifQ#IV5jQy>!^E3z9-1%Hhua@WT$r$3Au$&VJpQ*zo)YT>Rln@%hhPjg>1`NWL}{ ziUoBHX?%FZKjmS0T3fV5)mB#L6X5n4qBEK~b7pC;6}7SlnTFcFHLtTe{ZgqG4Yl>ro=Sxx{LkHcbSAoB;X-`= z>M!DtfA}N1cWuxB{9*CA0EZub7#d`&)^lA=4eF#%l2Jb`EzR)_6wNKI+MaAiu^`wz zDgXcw07*naR8Wv?CDgRHO});uYNdO(Pm3l3&CSixZhgk-fv86IS1TC}HR9_wHLmjw zE#hyQR0E6kS1VqY!(iMXJI;Uj(Kg;1WwL#_3-7>H88yXHlndIbYiTJ^{E^drkv~a9 zJjr4Iv_JdaGDhEN*PZ>|He4!}qK@51cx7!Ji3M6EXN&CHe$lMZxchY?dEGYtAyol7 zuY+nJ95lBxQ(Hvyv0%Z12n*FQEKuCFU0%>cVpq*3$b|dV)XCdKbAk&G{T*0Q2ZX{Es(79=eNr*+5KaGvu4fGxy+oL zX6{^VGo1u?%*MZ4GkC*-g?D4#y!lG+j@jaO(n)z8bGfJD!3Q6NJIVRtzfiKwUtn48 z!|}%-*CDrMH}pK@5X_&y01G7df`tnt`vSPE?%f-uixZWXz*~CHJo9v{!>6wJ1bX-GtIq#geDV`lssl>3!kK`XGiOBb zAmk_0?v7h|_rUG)zyl9p)v8tStA?(*=4#wE?=JjN1J}iud>A8!AA!d1JyB98n5a{9 z+mhDHBZ8^N9gh=d&BpARv!ad6o-qqYA9WNSe(2$-@6UYZ8ocREZ^z0< zAH&<;_Ey|<(?9Y4_q`vdo^o<*|5?)aw(Z-Z4O%Y?7u}5ova5w^)0s18=WQc9cRQXW z+nqLT8vMhPZkPEB=ELCvwU0aC+3k3FTh5KNeoEBsxIp%?Ks=3aotuyGW~qGBIX?Y_ z>A3H{`*D}}&DWOfJjrp7d}r^TeV8+MPK2s$&zUs`d-gPGyL3Km--ZRETYT@mm~z~4 zFh7Ikw$Gh>%85E7T!e+fSzv#VE!w^}y|gLn&AwyXGMsYqNt#&hjXJU28qC}E@N1r; zysGPobLPr^Pf}U4+x0Eo#d3UEv%>_XVnDG_jI&b9YH%42{eVTWR8XgE$Y-)8@mG(FCe0rAXtudW zE4#f-`_QD7W2$YNBnhfpj$fx)v*k*)s`4z-IL7sAv$eGu)V7Fcq;V#zm1$ADsm^(? zc*vrj?IbCxUImm2MHE7UTFruw z(l*?0Z}<@%!a(%1dWHQGk z*-?hm4J46-B0?ykSgb*h9*1a4aT2_}__x3Q9iRQ|=P+=RCdeRMaXn z)8O5vRaz_d?%RviPd=%^>s);Ls?VZUGx{s9`V`*u<~M0_(k<$~tTx`GHrczc2~B&| z?gFoRNk$#U)w*=;w#?M-En0EA4Vzk9(bU$ea$1mTRb?3r#w!+cd8}{SwcF6(xYJ0Y z*6pK}n(d`nOi-@0Y2awao;`c8*D?saQZnzFQVF#+C6sE5D5{Q>o!L%|yGM1j4O%8c zhE(+`qP9*n+6^exl#nDf@n1q*&wX0)SPt8md5~&t*_~HnhMJl>?fx;YxT-Q&L(5XF zqr*~70e-u^`RvmU%|7YSxaMseciWT-@=N(aQIM#g@OG=^&T(2|TUjTGwnS?rZ?U9y z6t3|N=)4Z9fpE~=&P-4mA`v?o8)Oxr%Lbi8MNV9i;ioUdBSqMb=T6hOy3Ie%k|RPu z66Q-X(xd%yheuL(6#q2xcbd0sNXjvj2&VNQ2_GV8KO@r~e5M2g+Aorkw`tpxVo=42 zp*k}doFjY(mf7GqARg+dT^^~pAmWS0IMp))I6c4Dw`3!8I+E~J<>k0>Ek`vZ z36dSUah`!>oY`J;%{A)C2dQ(u8t=LA{djWCQ!p(_00c?+l6X-bN_KCdop;`Oxbemt zal;Kaz_Vk&LdtR&mt>?Pt2&p^&Ugioj67eF{IXli>IBQ=@RdO3WgVDq8pDBU)wny& zp+kq_J@0uBZoc_ueBc8gz<>b*Vm8Sb9!N_v*2SHwR|VHx{ROOkVl`g>`q$xNo#pvo z7J_hsC^f#v`c!2#AJX&yfvDG1+m;b@PZFl3bV?cn@iM(kPrS;asl+srAo;Sm>8x{- zF^`l!-B4996R_RB6WKrk(7lu0;TtTY)6B;}5`hUQfPBG&MYQ)!vgjVj+ftT^>XoTH zr8}qIwz6ao02I!U8!#U>OYL0r;`Z1Mb`LO<(0j68_VdxJXLjIL{Ch zI=^011K~AuIy0gMG$f(I0ByO$K44>aM*j2=vr(E)-c@iLM;ktgQ=tGhq5ky@wMO|GD-u13`;_YvLJN(b&Z+qL@ z@gLX!2ikN#7+}q)elZYrT0yEhs3@&aYH_a4vleR$(J$JaG-*;?!NkJ#MMfgwtD?G3 zwW?4cnX;JX`&dsW9ssYF=ImQX$CTv#qk4y+@Idq*a#24e)!{k?|nCV z_w9{Vt%%I8O2a@f3DsL{-@YB+`|h`KqPqW(~Pn!N;i~JW9LtRE`n~qHl&%rkFm$sY^g2OmXV)m%+EII&}jzfA`>J* zHY|YnIXx&M@uOTp=_F-c!hv|oA2P|I!T|BjbgyKPgirw+rfkQ=E~_Ft$OM!VSF_+t zvKhzpnd;+5-=X@FjJ%9O(m@UpACe=BMWn)oodS&cne$@|!hvw4H_`jwNzA(}y;SQ@ z623@+41hyXk-py#=)4Z90cq}_`TyfH89f3BpbQfFhHO52RY0bE;Rku1oesK4M%=35 z+Q<#cLQtMNXM^!c;VL6*?=YZHEYV(Q0=H^!n7d?NCW^ifTc+7*m9^GSE<5- zt`Llu7pl;(PxuYn};D~t63bRR`a5fm?kB+?nz;4-WW zmq{|_xs1R7QnYBlEW0`;)5Ltqdg!6O;#rV?YwONC@5C3s_(eSa_~YVP|`L{5I-_6&-gBtWQPn%lJhd2fn?-ejgvVpNxa%cGV-eO zHcmC}kj(R|{G4wf>EJbiWR!!ZEaH$v$ECQMLOM?OCxK9M$Gs!Q$<*SR1_>Fe zl8i%z|N3$LU2p5yKvMiDL|MMuT!T}p0Vk6UhxR;@2(m+}T^NG!1ALj6!FJ{QkR-Cz z(4m7&##(NxprXMeHE#)OeB+Xgc$Nil`H<+TKvcpb36iK@sUyK(i0MLs%dPT5`$bZG zDLIl3APL)~0S8B?FawP;rDpRGueLgXFKjdT`OS6?5?V*tu=izHQ;shkv*)(X7$?z1R^&#qjL zTFLElGtHzcg0eaZmqQY+lW}9HbAZ~~I@qzbu#!WkNGoMj+RBP&>i7a`C4-?(^|Som zuTRxkwh6~)0zLz%XeAg3c-yY7z7{^WG8Bs?q?)<5YL;(@jv!e)Lnvu*F<;AJD8=)D z0)`D6imN|=HTD9PteNR$0@NzJY^9*EO zp5w2CDqfXWHJ@zfCj}Rh66(8j#~a`9`nbY+``h1)Ll5nV2DgpcDeAFMbY+ohfN9b> z(8@AZ{V z*ZTDTd$qQ-p|!OQO*$_&ZBc`XZLhwz4)Li+$>R1cD7~Dvp-pyc8+7|41Qc|3Rxcbs z9a&qfK|wN8^|KDrG=&E=gOZdNVBV3h>^joutd0!wflQOQ3}x9@o8&2L;Hp(#73w9o zp&;8L3G?>(aC2)*Jo_rz*Ccb4#qy|*H9D{LU|W$K+E9VclU%@sjjiLgXu^&1x5)&*jjB7M&}j^E#*o!a;L8GckMCtoWqT zEQbO=9W-v-xVRm&ZQC{&yftI!-?v}>MA)pEm^pJMOyeh!Y{Y&I&vVZ`hv%Q)fajin z9)1F9>eLe=j&UQ*maqO{^F;itv zn?4mMoNzp*PoJjqnh$FrxypW=O^2yPoFOQ>2aVx z?zk!V@>l*1#~pt>x^?T0BqZp#)X72mB#G)p=5cqHRd61er#o(_<~gk1JFJ4!N#H;o zwg3PS07*naRD#?O2j)57_pc0{_G(bYb6z#>(BL#JFgnVr)x=})puzagwco*C{`wc3 zd+xcIJzIKL``2pVxpUq;+%FT-@%%6&_g;Pz;Lcj8Xj?j5qj`Sa#S`;NG>E#uCfJsW-c^uav& z${i}-D|*9ix807Q5pvqJ6JXz&DcR@DnT?t9ja6Fh&l4}>-6gs2xZ@63Pm?B2inzv~ z)!s+=2UHh`xBVu!@4Mue3*$o@v(+ZE?8B1Zq3h}QEBgNyZ&y7H(T8roBQ|m8*K2E_ za{zm7-Nc-dW^SIrR-vR7g5xCPj1cWhe|IQ;CtOWYv#NF)uS$x#*VH%8@;nnuz0wd3 zNfZkul$2i*PlNG2oAb=E3OP+0W$~=7REctDr?Q$X3Z$K~1TMde3MzD|H#JgZ1VA zvGM=Hn75y5^lZ7Nrl=WeJ&e;uE2`OZX5oGBe-E~7*^Cc;=tFVf^5AE=%%fN+NQXsO zH|Bl#;fKeq#mg_h0{#c%no>Q01mu2GC#W>FUwb>~CVohQ{8xyX`XZ_C{6p@K=PCQY zEtg?`N**KmGX7N@ha_{P1HP;2)$o9<$mhWO7*`z=*_0puKX&pI`1i?9J@r)d=-CsY zkZ1znHdI@xJ^jR-pN4z!g_m@O_&ZIKR^X(Q=io)O9!!}}Yl}e=oYP5Q(^{PWqlr2=mtGTH~HfwpB;3x9R z+HEMvKI>#Bby}_0X~3;fIhmGyma|DR+g=PVBT;?o8|qN!)s*bjVX3Az4iJ7iwn?_? z6^-REeobvjc2$dd$xtsltgov@k|fbik0kF|cHQD?8Ne`|X^ zT~|X{tGt3_soGzyWU%dqglLh^Gz%<`qmtryZW6Nxw#?5y!%CT8H zzg}Ad;kC2=*K+=E#m=;4;6cjuvjH0_+7fVgL-@}*fCnDkBJ-adz&Kuc8J{FbMjSFA zgal+zho40-j&X6oMdmal5kiOnUEaq}<Aj=ouvPF>w*g|z>e)Z@c#FIKr6dD;y=%tjwFJ> zf~!Q~m*BUrUw--JS|QBQR$@1GPzCW05GH7OkYA=Z_|Boh@))XV2Zp3d5IBw8A2*%B z=~eLk!N7RVCv!ez9yyLN6>)m+A+uwm+y$)4c z0_x9gVcUT&H3@d^+>KxT@_H<}?}50YI_I3XqI+XEctFWydobVjFw&|mWfp2fwVrH6 zP1zpLWDiP+d^4q0w3Sy@n7Nsh>Q5HgQPCg}0UXa1&qE?pd6`osTqfp>p?GL35GtF> zb8|-f4#F30CaA~{QVoPEG}^X#!x_qxr1~brPSH#pvKWfB(iPXYKaLq>p>h$Gsc*DH zM(k&2WC5u}am&jRz6!9+sr*rQN;WruBoYl?9;_%`I#sC1RG*xyQxGqb5uaqd@BDgg z4MZDy?d;B+ss`M-8SMC;sg>oy?nD5B%)$2t<2f`ymmSTc6KBqeh7)` z6k?v`I1tFZV3EZ9v_hSarRp@G4&i@^Cgu2OU7>_ar-bg^;@&$*4P$9r&*nAqmqMNJc(rzsUTa zWW*u!dmM0?u0iK9C!c&WzW2TF!9Vv>EEQwfRry60>8T;bSKU}`%HZCnrqObu@RmmK<%T3LPe{fRA3*l%&)9B$tY)HThinrvtd>x zR5P<0Zx1OOp>RpbB0*%D-`MI@nwAloU}o&tqyUKuD( zB$0@Jq6r;c2jy2(NSo`Bra2A(+r)mLQX;b2-Mn-wOp&4>CL}=~0L~CF1SmstWpd9{ zw36WfJY^~!0{MXJAUWg~$WkIOV1M}mmf82{ybh`XY5bu1otae)WRS`ECX*AlVe7Un zI+xjkty{Oo2RSxx-i$rF_n;!Dh)yQsl%(W`(crF>(=4fXP?7*!L#e1gMT-wzP=&8r_aAzWEebnFop~nj2B>`yNVpA$3>ktd4Ap>H)>+ra4KJ#_pBIhWex2ga#d4i* znxUc@CS3on*XAu-I_%1PZ8x4E4IL_*9y$me?LT0E&aPVV>~prI=OWF94bMkA>EFMf z@CL|61_=hrZU^dqkmSz&!SyuXb+TFemF>tfTOQl&@ZpEa&r`hc!VB0SKZv;g?Jt3U z2e2xGL*qMiA7EVbUcWxCr~Q0@>ZFnvYgpj)!j|d>$u~x8a&u;A8y&Jps?!oSTd$C8M9ckIJ zW$-V-8vF~-D<69d-MV#!f8llf_+v26zodN3Xp9*>8p~EbiU%Kl7!NV~!F2xN$f}kZ4R!5qp`6OE_<19R<2wL;^R7#*@=&R^rN`-=3C$=zx?Be{^jQ};yr5AC>(j@2%L5H zY54Ycz7Cf|<^vAeFLx5{(bo(}B51};=Ix7DTqNTlXI^BEkDN(~dc2JdPPV0k$W@kw+eZrhWVH&;t+4#vc?s zjE5dx2LC$xh!IEVEOeqkHamWt!U-y8ENtI?qSs(sv>p0kpra+XdD^y*k=>4yA9>=q z?6H-2c=<9sB7caszI+Ax_34K(!XGEw_AhALCQZLa{%;?9MEK_Yi2UuP7hl5B(bwc- z@&lJ~)KN!8n|kDtW`g|0tRz0S{wm&9LoPcri$EZK~uz9~$n|7w>8VGsN z`TgI~0Lj?td3moWNNNzOprV80Oxt_zU~s_Yj)x?Iz=7X;cR%F8K> zi?&WOaZI%Z+1R6p2Ca|5PbFS@>7}^mo_pdGW!|cC3B_U&g`@z#dv5rM!!*!+0z-!m z*S+gbkVN$&_s6SguNG#~uhYqY#dlti+y>)Rfy{A9#xlt~G=3GwagyIiv&cufaj3-DDZBk0Cy7Kh zlY}J7naUOn#x+2fSb+W$u0BdhWenMVP>Mf^`3OQtBv*)hLkJ*)%9Jc3OKoog5yO0g z7)G1`nHv!T;VTnPDjUs&q>=z7J5DNs{HoqF1o*f0DE!D&1kST9X5s@Ai_CbWB2ei{ zxBXWX$^&3KXCgi-pUiQD*73)VqEeZDg3Ia7Ha?l-X7(^8 zk_0Ib&jboHbqoS14H7>fQB>)^M~JK}uk}JwWrvubDz1p?M*#%wd=zzhmWVd!#&`upn+` ztl+=-3F2i`k`7d-17wXU`IqG~wQ1pR^ye_N8{-@D+Ux$WdkFGIXH` zAAtQr5M|aaARaIdq!*=%NZH5~ddDP_OwLVJz5%)+bY%odMHoXRJ1fSk?WxT6PlCMg z_FDy+WHcz+`8kLNaw|9p!vFPI|3wAK+yF_!PGunTG#jEF$02m(c@Q3>p^|xM9E0&< zr!8-he`{qEgqsO+`;`yKj^!kB$b1mX<6Ha07J%LodfDAhOtjC+*^k#hZ zD_@1rcc}JLzYAp}mC^YBzkC+@+yD3vc!hk)C6}PFvAZ~lhw`g(WU?OJLSq#I2-DjJ zgy;MsnXBp|V@?YPdft!Aj^mM;zm#T~oMv!RE{S8E@LC!Oua(i6-mU=xHgFr04axY`VcHC#bm(e#NGht2aqKjPkR%8pQK~-5Pc@5;oxN^@jNU*}P8i@VyrKrGoN1IK zcQDZfIUjVTa+tEVC|g_0D7UqVcMwn{RHp$Hk{~`o_W-Dmcte-Vtd!f3X)rNUv!jX# z%1h;t=IJ`8a!iAg#WzT<1Y~3chJe5Xs)GDCMOg!<-$Pgy-&Cv8Af}~4K%rDXv8IG# zsT64_@)M3f4l`%YzQh(5L99?JBFHY=THAEi+ZwkL{X24Z+;KaO z)_K*r=ez?&=|2%|LG?`3K0)!^>diTm8KtPG-65My5M+CaY_EWVS9u9xT-%-P!{=vy z2qe|uLsDg{-9tQ`1yfvI*R-)iK>E)XdbLGkf*wzB*8tf7zSDHd#``RYd{ml4=+N%UW)P5_eT%^T(2?j^3f8xxFSl zBy0jA=JeNi5M*n}-cQ+n*VX-wGigQWDm8dvag1#Wcv6Vp_VG#F)HEx5;*E|4$GAx; z@Zw|$2srSIn|lW#LovYzUI~(9-to!=;(LBJS9cC3PqF;qQ|4Xg9xJOZy6cs{Ssd<$ zcX$=L^|0ltd;x=>VvqEf<@%9{c?o=fR`?;+BG$=qH{M%JSH!dou-P=*u9MkfZ=#YR z@p-dn>oyaW_q|-H4Gh>NTm6pl zl69^`L9AA5aZHj8 zG2Oe^AFbx|pBD%K5Ro|bg8P1Hm&(G0&+rkRz@sl7=NpdC9F@9jC-ML)mWogJHQ!%T zx=iR zFME{UL$y*-=hMfGeij15EdK$-J)_I($#_}u!q!i&z%2w+Rz^ouMqTtM0%~aGFg``X z5A;Cge-03s8#Kt0v7^hU?#M28I6r%2S?hQR0s^4n^w;Yrhn92tXs&e0@q&mIngv$3 zPq|&AwjHJIu3D7H5JLThnYtrY#qo9B(aZOy?UTWZ;3+8{~QGgn9FS+Zl@^ zZW{sm9j^0|r-{TLFdMg_Z2D7O0q&a6GXO0jsPT6k&$m_2$8E98095T@$G;W#t=fba z;x;cRz1zKE{oVg88i7P;9bMy78RddGgoh$+qhcTK&$TmNWy}%-oTW~_Y@LVp>qX%W zxk1P5f#-t-qoJt)9FM+m_9w?xV&2;yS5$`4u(K?6w5xdr(WhDPG%xl`rZ&~&qDYJX z%yPYtHI|!UXIwY6$TJ#sR*GK>c8B77clnPHbhBQsODS^(67fp@bXa!P@~IPN7c9e# zxdl_W^@gJK7tv+ZXeRc~?^u9|hQ4=xH1>ImjrfTUP0B2GXpt|7+s*UpM;}^mX1fxV z2CP9Z4UvcTwuePFzr6##&{*hoyr+z}q1R~-LS^VI=p})9a;I5Eq7}{Dl*embg)Uo+Qf%m95Y^JIB z_>Myic0i-cf1VCSFRV#ecp8lJ4N?@O3o}n;u4gq2NKx7 zye8FDPDM8c>Qobj5CKT`gY^UZO`-ZD*C!D=eIC&Xg-$40!<3M z6(}|)1enzh0j9s^s3k+Ppymsvp-?6Fj0zfJ2~b@K{0^p#Dr+(Vfn1|YTIsnUw26{@ zt2XNVFZfFl&anU*xVmqq>8FI^NneFe=)}TuPo*3SHAKv*X?ifVzL|;(LQuo}Y>Z03 zCRiCz`Anjc?M}NK?N*tz}B~{L(HC9vhkpZ zYv>^ecY6g#iryF!qp))s{C~nI68J4f{!c291LKL<<1iNOQr~h$K?sa+X6$s6zubD* zWV{SyF>omB8pTFRy{rF)ak2@hr5KR zfzC1>?6?BtTDj^GNyZu6LG-Xt%XYj34@%VzH}U<3n6`Hi*NDqX`BiDre{LMgx6jHJ zdg%uEXB$i5z*dpWU1Z;TSGD^mdr`6>GZ0i9alYxS^NVjo)e9e6`P?X3ut=+ z7-YB)BSonRxYTJhxwLE3gu_rA7f6a>1HU-oD&8oG$%J6h8SyqGNTKB>(GYWJ7vYiz zr+S3aUXUUrTv|`GK!!8PrlRU}x07U2ITl$e%fG!7b1Za#3KU*qcXsV{(s4? zqfLI%qtGXevV%edK+m5MMC`Ju8C?*o+jR!?RlilE)ouvDcsL*P z_7aOB@dcWCn>d?Wj{#c^G{gzD^x$eJXAawTXn|n`*J2J?#+igDPSP8+R`Fx5kGQBO zF!>RQU}KcKQyhaM-*|v|5vp`UB@02$+nS2Gc}eWGii5bQ)?@F5AF&_%&FjrZ#P8pl zg(e)?DjdaL_<-<&IJV zTO*&EPO{-i^4A71K@x#9!NMNbUvC~Dj@DBmkLBZ0#Yq)RjUx^Vb6nd*UsRF{-c|f&r06v}0Z& zvxo!>3h?HgMK?q_{>2`rlQFlki6Ip3Lx4p2^$D5tm_(cd;6u>BrH@Kt03?G|3O()++Dts{y6XUZ(|^FIQCv9%iH1bOfakR+-ou=mQk^Kwc;c70 z2XFc&{y{Q7n7evp);*^4ON%u0lcVP>?i#qr4E>X}kD%YxJ6WRYiobLtp}8HzDa88bT0-mV`C*B3vs?(a#|i39_NkGJZ);0WB?H z6JA#>48~5v7ECoEaUz(-lDejS3aXPwms@S}>9#w#+!94pd!rhlKQf$lf4w%n70{NcVH8jWwi`0CLD zIBUi*qy0!O1K`dF9h74FC3bwShn?&bwi-B`e%RjPta*L-q`5r^j_KJqPlTNh)s}Ti0y3D_}{NQyP4sAnz)m)ypT@8^-{d5{| zPUdLN8kG2Xx>EW1{IA>3{qnI-P@~QE+kyl$e<)>n71${!qM4lz#s+E!Wdk=84_fgD znM1!x5p`Wr5`rY=5rNn0>;MO#EpWI7V1aWv3B!Q z#c~>x52tDN5A4+@>*TX_@)oX@U8v=)AXK_&K0(XQ-?YTF9huAz!qOQ(p;39R;rB<+ zt>tcly_!#b7pr*ESgcaKE$H`0vaQwXO@w^a4tv_Z8g%!x8GzrfhD08|_asp#{!sIE zn2~U@-;t>Qr$%Xs?+N>5D0QDMP7Yzy`|G+BgX`&107t?D*7E8w$=hcrq>Vo_0=`>$ewM$MqWI!908`t$vr+>5Y^6 z_had4TxPKQk{f^P5A^qMaTT`RCYUBe)Js}d#4b7>cnNr(sWLswjM<-z0ef3S8vcpB zV&DH644hH)t1C0ols4tzgoK2kz3KHYf0=hEUXAiUoG<@c_i`P405@8MYRsGtx4eJ+ zrq^j3z_r%0!gsyc2mvx$1{WJVON(J4H6GnhmMBOPeNH)oyhB{G4Ra&$$j?tbVP|o&U~iib06VH z8yRBQXJMapY`Oc{_0RX0`~LKOu8ntBBs_Nb&c`Q)OMvm&pYBqdRt;`fQKy;jl5@`X z7|@u>_!r24aF9zl#&8jpb$QKQtPD8r2ejNK(B~qGp(f*W_&((G_3GMfUR14@TdBk7 zR(D1t)v9%&KcKFFFYeAo+<#4CEqf_ia{_c-btbV}rNB%X@|A5MmD6q$%+vG%_VJot zSjhiLG7iUu-28>atAA^+VG(Kz1v=T-0Om%22wqRIVSi~c< zig;P35U#jdQ#Rt=N*1n|4}Poc(h2JDdXS85`*U`ov{sGn)HW~XRrU*vv0JC7g5vdX z+D){5mb~#WGVr@$L<-|6>9s(YS4D60+jG*J@x%GLz1KywZ|&D6otr9b2EKMhJvGXV za+NHr`Ov*IJCEQ0%3)99K$ezP`W{vwr!4czAl3P4aJ`tx<69(sd10Z7J4?b}T0Feg zTwPyP^3D29F1}O~yE&=y=P<=ms&-iQY`mxD(I2`0--0TDg{BUSG!hBrQO0vIStPU8 z+!yS1OD6Ga%nCI9QRL%if7VJY`~Kc|I-jY3!>K0vjc*S{%% z{qyZ{{ld36=F#i%^?)xn*7x?$V;3A>_-FbSh@6kpgUh3G-d}RQuZ}=qFsCm$rxhco z{WZ~jRBIE^7td_i)mANdW0}qe`Q9B~S37-h)pYKT!oB*7tGd2|FF$!d_7aC~Dqk&6 z`VjHGU&Zd`9t=*poi0VD?E4HANQtvX;PR#4R*g`dbJ7%XpA6>;$9d=swcF0$ax=T2 z3}80~N)y^?oxbMiG^5m3CH85nTcGsbMiw3J4mwL(eTmex9SXM) zk-6=nXfts&A+vtCZ~|`F5RTt(dOmk7k1LDd2w=A&_IOwA8^ZT?6ni<+Qyw~~#uG!Q z)wBgjb+tZ&_m2rWd@9cy5860t)_SiqEHj&w1*wy}Gg7=!2rHJiQpHaA!CE?HL!2Zk zFR3PjwrqnsVnH^;L2~&vq9a7&fd$8w>kynNk%0S1aFu>I9J-V>SyySf@u>qN$|_wD z4b0adP0iSt>?0+ud;hb;gY#!>ImEPp$xygKt7WUuFM$U_(k_$uIt$9kfSdB%-(A*8 z1bp+iYKf#|&b}_@{CH>KZlXXS2PQp8TGhdC^whc~zZ9>^uJq+~7sq5VonJQ3Dfc@H z#@S!SeGqWcym~~ff*Q%q97&!s5p%C2NZ@GAFA*iCND^GO@HU;zI|5N7O?9qCgDg#zJ#}=nSUyKXD7JHZQnXR-iW(U z!5`2vXz!TK>#mFIwmnv(I`emU~#e`T}VNN za6vO88wZSZO`<~f_1qF(ftpU4J`9ddB;^>sD{z*-vLy&z23tsCfaxRr1Ydx{{^{q` zSBW^~ikq8iyrmq&yYtSIsJCCRWrVI|Vq^$SM#{)Fmcb*6vbLdUDYN7;+%paY_VF;( z@I*)if)Dx0Vrin(btdc3lEs;(-yFn_?r1^azIf+lunc>NOl z#QE7;<-qPq99c5%H2;A$MvY@bkhE0UAIpv;6tDzxPs+u4oD8gT6DhAai+}VIzoVID zdr(w?pDowCZ^qqkr^OnfRu^hR8mmi12(2`-Vn&qVl1rf*cq97*Z!sY1Q@+>IYofcm zU#a6FB47yQ5$66fERGqjw0pf(hZm2a0%GrV5kYHCIMsS`Fztd;GGILiRF%}_PwLM zd?D?84Dp+VxNcKF_{wUtFk(*myMfT!yPl=8+mlV%ZTTIzaZqqq;a!=ixc=x zA)dFw$nNLGf<9PiwMeTGaka&PT(w%GGTm z_zpO$G`P8%kYH1{83_?||4RH%3lM#JEo96x8={m=5Oi@<6~_n$kp%lku2vBeP&)D8 zPNMCpfQ4?zj{d=$rh2Ki&wnMKL_3je(O#T)jwb?SM2J)y?n6gi>@iG|A&7)a5sapf zI8e=7Fo^vxdFRL`x1*=otX|#Z+g%JomR@yffOdIx`g*#;yg%}|{%)0dKZYQ`!hrxs z5*9-#In~f3JSsdamv><%S+MX^Km4azbA~n1EQ?XWb?ULjE#kT{h%1RWyDU(Akvh#0 zxF9_*i!Bja%@8*wq~Q9RGF95h!?Gcao|T5pZlkO|4(oyp3UfGJgvh4Sq`zP2j`|3x zT%E?EP#OB7lL_G}CvKI-=5kiuq>?QD6G#FwL=pYd{5NWvY!JNvqj7>v-Z_ ztHz+$bIpBsv*GQ*!u#^=Vz$gQM-{hOziq-(u~Ig&A8&4+C0FzSOW=+q0tBknt&f8cX~0 z!~0SG_S}golBIuWGpJ^gyVblO9SZF!1$clSup(RgeGJL~umgI4(qiqs{hPtCf244! z(W`BO)Xi#Y`B%|?kvr>-Q|eodoLMDTjbp!}_w$I{_9@fkKq~mr1esv8*6M($p`k&9 z=WivZU>&99AHjy4gyVD|f0C46F)SoNcwO=*rZ0(la3_jMHg+`}c$zM|_nu5n!E7-{ z@t7jLR)6k+{VZIo%wH;+TLawkZAS}8HVX5vC2PmqH7DVd)qcTd@yts-RQ^`3(0s$9 zpSdrq`>}sG4L`$l#MM_$mZfG4FU+5SC9l|q)z5X#F78oaZ&597z(rkdLnx?LD=(bi zB*R=w6*4{niI)fY9Ql#b%7v(tH0$~oJP-#YW`WG+psqV#B z%u&+py(Vc_HBk*$!>m5AP^$t97a!a-KfAcDSqiiLZZz8t@yDZBaOcO{#Ul{;iUeqt zJO7kqlWqX8^vL^Z{p7%j-pBJ&z^3O(<*~Y5)K+>k@mFF-<8aPUCi3@mv&;Y{SuR4R zBH7;m!b8=5FL3YgvG`Zbey>W*YzBa1@`u~G^%ctn6Zv{+ab}<<$F$zZJKOd<&&1)I zd_Z&O^Zi-I&HPAjc`VK2QRn%3o0a_Gmu?5HKS$cci=)@L-nplg_;P%2&Y8X|7WVF; zJ6g?ly)w;f7^6%Ze73J}U)DO%n9Rm|G|WnPdw6bcXZ3+})|W5eTk!o}+K$Py)=N~v zT(-kNud%fZ<|iZN6+l}W(cnqVrk0xSx2GeSPQUXgCONS@bEl+UD@n_+X7bfM9{Z=^ z!IP>slnakZuOBwgNCYmoINGkugO`uHYPEgaODjP4}n0%m0jT}t+sidhr8VqtuH z@aptx2yyG7(BqI8FNRuZ=kt8^C6NA7Eic~OdFcGeYT}#h&KCjb9cCS!dvtc)dmEhX zhtMtOtrsH;lLP5xC+Wr6G4&>Jjg2lXZ!ui8-cN{`cdbm9@uTzugM7ZY6?%L!2WnNH zkVP>mW&0W|W@`YZ$r1|kNBdEcx!&h_SfDJU-=dCs7Wcnc4FM3ZMPGDWHMME00(QhY z`Ri?ja$I|J;%2V^mXS@?_(%G{i&m>_V-A*;inFGXHZLRccZXfRtLDzl@XpcZ z@l{3^nsrBEJ;k>P-ka~46vWy<4T1OVfa_!NzgFCvgUMJqmEXnNNKX$MW?9&38Mdi@ zL$L4koqw;2@Erzq+(#VF%1c78AT--Aw$o;4|41hR61%)597 z{*&9iLzBpYxaOeq^3#8twJo4Y$TY!EO6F-~9sDxRHXUREm`r6(_fg-$l{)3b?l17A zhmaHku-WGKY7l#u1*YLEhz?@s*m1qz3+*ujgvj6-B%pBobKU6^{n)5Q?#QUKCC1!* zxV0#7FY;(d73B@`nI}~VQ6&NuUyv3Z1@02?^p};!kqXhLe|#J$CF4t%v|3=LR?!4v zWyh}wc-uLg4#c}!hnTH?a{&9KwjK_*Jm_J1iToAeLx`Dxf^K(mW8mc{{qf>_`~ zaxIOAgp2Idb4(@yfI)Ty5}0wG9J?Wz_P0r@f`S$?p9xK?iw%|!I?^{1EM;c_ChML~ z!0jA_np|FcYxXE3Q|W#g z5Y~YF=r#R{wE5Qk;83|W$k}=QX94ITY%qN>nVVzHEg6>1OM^flg@q>--e{UsFJ>Lh zB%2=*Eemg?LF|;L>Z09`^|}6Y36V<^$tsXQ#X}vK2dmY57GB=^nA0Tb_jap z{QmwmBC&9`cQ=SE-MZ@|S4%ZRwLwsBwhlH!=!ZcM3=-F=Ju}gakg5%b=Jd>3zB~R* z1+oMwbRr^6LYd5&sSZ5Y!x*W=9`qY4iwCHXkpXpKKrw73e~;%0vw9 z950L}2Te_Mw#E4q%@`$JRW|+6%<=_gMVPxovc4(-Mlj_x-FVWl4VM8M6`mlBJ`DC` zGY?oGJ(S*p43{Gk7<17uK$bUM!W9uD9C;YIt+<=F#`MGz&bn}m{Osw83iny&T z2D^^tBu=}In%Kti&p!ekFgX0X2?0}M+pPHB57@!=Zk)wX0u0Lx@>~+QYaVCZ>hA|O zvrXY#NZ!T2lIGy1(!}J?Wa+cR z!&LSM+pj}fF8nVhD9SoPd#ZakNJPsi@>sFn=fJs{J_dLTQ$Mi-^qajZV6Zs8>;T2GM zB=d4_?thf;iRR@j>b&7`(4S-eFj?OT^dA~pM|;GJN>0vMq)ogMwCaMoL0xyu*|RGn zm3Z2y{eZA6n&0~AC;%(Fi@oUWsPh8}pcj3o!TX_opv0{8@O{If8s$RE(QXZcxzb|n zq3cJ(jbmFsrzHeUb5mYET}vIT!l*f3s>zQ^8t8rWl6V-H;j|qaRv{4^W6m2&gz7G! zkiCj->PUP}ATf#=M4r`L$$j(S5AD*#sUFU&WIr^dL9xRw+#&r}K}t*Ns^ z9^%_v%MoV=`?6{e@hSdKN)u=aB%GxEu}=s>0p7CTsPbbtXLI0V6DN09wb#|LJva9fi+_ z5*^KRnRVffzxh1Cc9n%h=)AQ?46|1zTbQ>a# zPGj}49AoN?Ug3P(j`btp@o{zp`Q|D{#wFB_(@Co-a<)+q?Z%*q2KOy6jq60XabBU8 zo=BY4ddXjg!6u*?2^Xq>CJxKTzjGAN-R*?i_T^q@>91M!>E}yHhy4nR1k#XZ`uU{V zY_gd!&2HMb%;y;5lesPYW)Bz@GVE}P?{JQomURc*jPS`&>%(8xed&AaAZHp28a5b@ z{#4u?4#5GMrH3wsN-?^$T@3x_R`IJL#-oD3I^)X`?dIH@6#;=kO3aw|cn_n8x0om2eQ ztKWfgtL3UsxGMR@kp^zUc>OP-l7{7%tAHx$4a1?IcXS2r#KEa01ju*=JLs7VW&r*P zaUmLqzx`i3?mx+%5aZ9Ssm+MrFrnh9vSjVx7!OkA8(PVZY^y z!Y#i0)KvTK(Y7dMcnEW}nweOjxDpoy`p&-MRN2~d#j*6PX;q(#@__<7d&XrWxSEH%(b&p}G z)<|rOO1x@UjvZya%_SCi;@^bvy`gix=|@D?5|plL5LOaH*@L@HLgTtQKMWrFZM4APHOdQFD`ngNSs7vPZYAS6XTKrYJymI6vp6i z{N1_$^&(qwNw^*KBw~2d?ynMsVJPCDHpo_KD;|!9*nJaIGLt?^++7SJ^qED_|FnP& z&S>)b8Nqx;jC}d;xg>ADClY&_S}d(GTP=%NYjiWs>^V?|U9&Gmd~nfDDl#S}{Q#y= zXT-w?rTNFjFM!vHhD68+AM{Bm6ltKwKxj(o<%Pk<6Je6?gL|QTm$^c#dBQdv@R#YU z7vO$x?Z%n%gJ^fz5gUp&yIe(OwOa}1_3<>C%7w&Xw$If^3q>Ic7V>1>=}*<|3q4@# zV$$se011DXknot{gW!;{aNNWTuC$=CF{`#c#^aFjnNKd3Z_u(NZZW6;#@_9*3l%U7 z1sMp*a8b>mxc=Qy`<}e@@yS#6?q`eiVx_1VN6@!f`FWqqtpFM~{iNlr%oBa}>X@Tt zvqhtuBD$-*fKA;GtM=V9JAsFDoozVCS2^&7*T>7{)1+QBzVCzA_~lolyWhogCZ>n; zFKGV(@!oj~A>W>ja-G%oYQw zQql4UDS&e?Ox2D2#qbxWHw<-BM`GkKnQA7eiOgRmj&Gmy;&- z;s8sykD~N$X5_oOt8vgp`&JfSpXd9p?Z24UyW6|~y|6O}c2w2*Y~_%HRRHy6xx%oO?xBcl-wlK!3yv3duRvzJ5Aj)$cf=e5v8<0P; z4L_ZK4I43CE1DSfF(Uuo+1+05trL2sZN~TX7x-{%uR;hG@9vLl#U@3U4g7%3AV1?! zY$$Tb5qH4P^Ba7&t-l93y+D|993OMuSn^j}E&(4Ay?8f!Iw?)mxNUV{(`sTdbcPA5#ruc`dOhWYfZdo&uUo|Es~M zWFe%kI)}CPUQP&koI>>Ag2I>;i)=InasW3&1{fTFizqzWcbRAF6iU>a;rds$X#ra60M~G*6es z`t{lMM`Cj_c_E!MFIM>=PL?NfJ{4d(OaNIWDTco=dN0RnyL|J&0?M!J04Ur6n)Za! zxDJFt(o;)I;Z74CaNzq!hTe<*`cqrzkJc*UV0D@-dY^yj>T;th6PTKiG2DhQ0~#?7 zMh;Oco?~g#@p6D#G!R1=WLQcu5yfM!;?q-q2OMm%EM>mRshA#MJ?n6qWW?fs8wo9J zrN!iXHJbCsO6Y4;GRk0S4CX*|;`v~2*4;>QtmM~GGIgSpwbxkQXLEOcqH0%M+TYWy zn`JTUk11}Y&bID?Hb0Js$jQ%Ju8e-#zT!kBzMjXueb|i#n{m~5@K9)-d5DvnPNrj< zIC0E-n#2F1)%!4d0Jg}DjW0OazNU1%ccpTwotVT*0;e&Y_LIOH`}e1V?RyWm9Tz)yOxwR_vK8`Kl^5vbq9a8E|C-qE z(@GMj|HKX)Q)YMdp4~r$uMD|v4R5kHjz1#o3OgYU4Cf3Gv2cPx>`i-hVl~!Jb>=~| zYTPtj#PmE-G3|q&-Fn=Y&mOPbZ+{+XxyRz@wf_9b;&Rg;Tl$$sqL)VU{&!<=FibfG z@xoyEGVX-RuLc!mAy>UWoho~GFuE6K`4lr@)uu(-JGJ>GhZ3skfWVJ{LYg4f2qag8 z-LmRgdTfEa#v9A`jst7K$l;J+tU_$`7TriRpFQt-jHIUneQc}C^M{FL5kf))!(~h$ zu8T=AT3Hjl5IqUEw}mD53~Cb-hA|5r-aE&_s+Takx5dj0w&&`LaDF9@9bX!Q2EUdS zE?p&^xzd3}Htg)DXe5r9Cf2|wvtwnYvr(%I=~dQ^R;rUI+Vfc}+QG+yf5;L47I0JD zg;wb`enZI0WoDBg2t3SHiGQmG0%SAFwD4EaX0W&yIknMNKs+^5^wmVM1w7&7evH^*Qj|6 z-HAC3J?#d*AzX7fpaa(RligbCUv-?(Umt6UCoYj5;<9}j*5{!cSpdMI9!nvHHwugU zko-Dhk=BQa&6#^!txBs6ZFA`aH9tu_Jz|Kzu;)Bn`a&3QXUpx3)K>9bt`|wrYPUDd zO#G(V!C=EWFR8?i<(`b4_pc^}6O~S+HrKO02EVJ566jKK8#J<(??E286(@DZSC(CM zpBlvg;rr(tt%<;7HjjK#jCK|2vEtnj=-ao78$<~NQcxM95xyt>r2c#8$_kzgJuhTu z8|wc#1Je%bHAOzIQx{LhYFTE0zs3YS@1kU@&TmA1uMXT#{}O9;ZN)mpn+qF}E0Y;V zuqDV`|FePF(Mf)l5X^L*(XP<`OF;bgD7GtERM^NeqeY}ZMHFY6piu`izdWP<75l0| z8n!rI`Ay0)Baoy8H(!=cOvE+EG+k3{%C=roP*b8WXGT7h#8VL}QiJA$Iod_3@N2&F zApECQ{siIojS1Tn;{7JYlnPvoJ#3R=kw!84dV8HJiqxh`Wv#~2bL6Vxt2|W!ucxU! z=L0d0xfm3sVG~~oMPUp?AgaW}WDLB{g98%0I1vI+Gn3Q=dhR>^@jxLmR|u3(2@Inf zQbL`=z9?l_8NA{)dqX!3&7Uz98CV#O?-t&HpnoPbaE=L)nUv9?QWzt_H&n0C7R(Vs zMb!WULdgs<*$filgY>$3Cy_oiP7fiP>NDHCjL5fvFfJ%`hU5d!gjToT0n{@U-#IxF z52L=Ok;Icz?%?ycWNO;5#LQbe%pcFYZx@aaQDt>An@n4EB^aH20eu1@{-T}Sjd?(< zyv?N>H15Co+{CsWNy``Dw{fes_R(dy=J&w^#LTOEJq|jd$wdhQ&ey#x{mVl}$;Ssx zzQzS7%pk@ybWzc!AD$MKH#vs&s8KBI9H6oY7gST{qLs7a_uzLD58H!h z3{u2(jd>R$9Lu4EBYKj1Bu2JXAS4F z^gFH3QF(C;Jp{{Czyx{G_1IyM@T&upa#HKZ?Alr&-`f)d5P*j(aiuN^0^iP{{wY8R z__W&L1_yMmNYRe@C=8Iy2nVU6eSn}3!}Le|#}wGYQ%$(FSFJX9*PE?S6^BxpQn>-OfFkOBcXe~$ysn4%{cdYpgy4o%w*RMwZ^Nq-XU!;z%y^i*qE z1>>F&Yr+|)@Rt0q*+)G3MS=;1fdZf6N6?EbVA9=%mxWK7Xs~STAPY_f9QnPOhBG7J z3V)G2zd44Nd%!D3mz6pfS&rz=P$_{XfBiCnf(*yh4TFH3$Ie>x%Y(Ey>FjzW&L)gj zgth8*&WucS4P4`w2sEBkr1{KZ%(?=-(-Xyx)T2aXavGoe{7tNAhAE_OC(V*KCN6(^ z&|#FH1F!TtL~nX*GHzHP_nM4qeGj)25fon{L=r(I#D%K(0DGvooKCP%H>yVt=IYG# zuEi33Cyk&A6J#uAC`_+TUz?0T{CVNu?XfM5{_Q zCo(+%WfzcSw)U~<~V3~QkapXNnA_O5tN{qhI2sUq0Y!n0HHdoxXk^zi@VXoe5{kdS z+(-)c_m(FD%-Pbn)~#tV;-JkR@xv%l_`+rxj4j|P6JOXHHq=2I@)~qby|^;jDz_DS zwmiNkG#5KP!+fu+FErxwa_DtD(L=Mr_#U*ukLeR4?9s-33jR~)_>is2&C;w1yXE{i z4F1j~j(wv+`Xa66;&3TS%7ok~QEdbVVrW?xI+VKv@UpQF^z@=-dRg1$79{POhGr|i z$bjQO>5HKm-ds2O@3WB>8b)jUYBNOv(b)TP%OTc2nm9<4yXfyjmr{b?X{4b_Zs7&! z%ada~Oiih<{1`bjzYDPyn8VQ19R6}P!^+Pwb7h9)2~tuY2IbmIL}J*-Sv0{1m`(iV z3q-4A3}>usz%I@Ffn8~W(v#>#=E{thsZ78)Zi$@zWguA!?E*xi)KXoD{VukF&S{6w zUeh_Dd|$e2sS39gs+`69J;wd3aW~Z}A##s+RO&yx&~*u;Pq^Itw?tc^p(M)t85xR>qGNkTudD5QR)sa*Z>{5Y#QAL0e%i;6)kQ@wg;3X7j{PCfEw!=XU7q zJTNV#L<%tr%o(YW#QSP;E2{(l#n6(;+a!y~OCQjS8PrY4U?PVXNMQ-XmNu1TTn+Ml zD3tGi-SUH~F0JkrS;?=Yo+m%7HqpZbxW%fcRx8EHLZ85jM==82Wx1>}g`<(DVF~2` z*e#;>2dGS_`J88~L7G(_-Cd3BGk@Oh_YiQ-|FnRQ7RCY#k@nFN^S0k4xhi~tKQJNc z7)XY^8!Q#LOf)ifObRq;ql$}yf1^a0h{Nk)kLF|RE$6zM7Jx9bt_zva#ny3BlR}Nh z(n(5qKgp;P;0fzn1XE}}d6o?u7PW?f#NVYMINX0yfi_MIx0BbJ`YyJ&IP4dIi$Lcnq9 zqk7B>Or}*e?7vR_4@6;F5!)jNdV*sbjK&Xh2)yF_cP|7{s3^fc>a5UNQsu-P~Qlti0cJ{&q2L_*`dfn$OGDqHl-U*sz zy(!kML6?o|pP8O3rRw$15|yH^`*-GpeA~g8bK5x~fK@*3Sh>K|(a)TaLIT4@f^jDf zh^Gvq{^c7d^zX(65%LEEoY8PPt>*4d5^Eh)Tt+mbSX{ce?1nv$sDHdW;pCTdiE`Vu zV#I@(auwZ705qs!R!+=DM(v0D50Q5Brela^o7GSNm7dz;Lv~zL>Ol-x@nRHfOMIz& zfu-mC(Pps2Zfy7C)ozVt@}(*-g^t!{tl{64Rk>W*IA6*UTMBVM%()3Cv&n(D?(@fA zcqT^iWl-ClByDwsQ5?tSjnhl;KnqncvAu_~&EFZDzm6ftPwcwh+n<(vUm?2tA`*AB zq>qoS@~s!*y9rATfT--&`?m*!ic^#8U?Yd~)s2ANhWW#5q=nV9=Jf!||6-^xS4Nln zT(Wm~#rFgZIBdR1#|fXeu-l)c$7NQXq!MGbvG*AGWbl$x6bY$M(1+%Bgg07!`b2x@6HMrDe+&J@7CT? z@uESYx2s9pMC!1q8oi&gFWZ-WEA8gCJgdd3T0%9+FMRrS*R_L&Jg6N1;tpr;Pp&M9 zN0}wxuU?(-<8FMu^PXNW8O09NccY6%^|3F{x-TaZpQjaM1p_LXLF4I>!qq)A3GF|t z^1awkGVqkLnK(~sCRagR@6)R$SCDaHwSsTslFJcCj#7uOzI4dJizA29lPop&rNy=P zrHwT~Dh8t|bU5tx5Wqq^v|9+4-0##y+*y+k??h}L*;jkvKVvp2G^`j7w>}l@9dR(& z$8-1Z!Qw8Us(!gJ0|dttql3RDH>Oua;iN*L`X%o8ufYjinT=M9JIgL7PVTlo-UQ8H zFiH?CavT!$&!yOJpJ9=Ss5T~zI_zJ~tBG-a9dFEA z^c~>muEzzJ+1%dy-)ih(wb#A|_suCMH?8hTw$B$|tiN{E;IdwSK#b&26}MjElS1}s$L!AG#~kM2$LugZ&vzjoxKE`laz^VbX4}h; z4W&$If`MKBx!pq2JGnFMcEsq^sUZEG*|=kO8}c_C-y6f zVg?`@QC;g6v(``8@W~CQ0D@*D?r|jgiVa4obflgr)x&edtsvsRtJ5~&yNSii3N1ginpHh#n;HPmr z!yHu&Xjr7EkKdODm0)hP&jLp;JFFMS^K#;DlZF6|>5^oo*^Qym%MU4qKnV80@oS?? zDkCbkL8&^37DxcrNsaqwFn%!Ln9k?qv&FbTuIO0xDiW0EuKSn0Ph>O8X9 z=)qmGBYA!}3Jb8z$mVI=Zoir62JkUjuZM%1gMd`;^ZLBVH;BLS$cY4yo&dczDqv=h z-$v@;Vo@%!Wca808JqDG3HxcWM9Ie|KwG7(74-?+E-hX(>>W7x$!~&6$SBQg)rJ=(aE*W( zGbwIX_2z@XthhpVE>~J+4@)x~fTfdvmcNALTjvW%x#(In!qzT{84IlD^ERt5Xu46vX@xxZigurOaZ zY6eg|$U+Hgnd=3laPq_V`mr_TNj3 z3GNd~@z=^H+}zPe`q?~NNGKHn2>{LbxKVo51=cj9nc|&3b6cZNZ^Q;+Fb z^iEZJH4hDXBZERhP<#RYnX#dx1=f7U3)vieuUuyQ;TBHKb2EkXb{Y+HV+J2&Q5vVpuzgS+~`F_VRVux+R z4^{&qp=do`oUmHgEDah}rcT+ygE@8F>h{@5?tcj))DhrH?$ChQ2eFyO zYCM-$%t(~mfRmDykYec8Dg*7Eck@49GgMDIn4d_PosaKso39ML48G5n?H~8H-JFMi zA`NOOv4=XD!IUY73t>hzpdfRVwSE~IHa+Fa2rt@{&Zk%xT9=d!L7$!aa7`1Dio|)7 zCakX3r)=Ik>uNMt=iCE8R3T_EC)jP1X%aX=WwWw`Zjxk2V}PUf2J9X1ce2}09i zQ!9gw=!>rpQ;GM2a>6Om9f~K2BlAYkin@}GB}uJZBitxneh`1M1%}1OjC$?iwZ^8y z-z&JksMej3i;XBZH!tA zNh7Rb4O2a-6xyB(-nQi2*qe=)g{E>Pt6%Z}fSh#~(EBwSx3Ff1E01UtDv{3_ z`u7s$(L@IN8;`TVK1obT7NO4;dM)i`YxQ9rRDQVM+p#1za41+iTX5Qt@(=fZgihwXusngMjhEbTWfz@*| zVuHBxW1%;gU8}RlNg2gp@}USpD=hoRtqITl9P`SKR`BM>1ON3dkPJ?wkeOrKaVx}b zXI6;x%zkqYBN2^~htYu~4P`ZR-+{ox=tfu04{UAK)P9MV+MZbC z(S_4;PH~y#w+(+07ZUjV@V46yz7)#aI_Lbo3ZheQwiDbCkoWGN;}QRoG_W$NR+m8< z8L0jz&+@m$*@ldkTi@^X9ToanR6#A}K6zz#1*hZLHzXT`T_X#*P%`Hc(=2B;pypF? z1o=(ucRFddYJ#N`o8uv#>p;~mDJjR>RUf1BxdET9#?zTG;FmNrw+yZ5Y{>*oT!Hjq}CviG0pf40D_RbFtiIIs?Gnre3SDcs>T;i1w!%454 zYJ16$V*3zCWJ6aCZs*9fyr*bgziz(c?+(Pw{(eBa&~RekxGQE4VA(|MHxLj+4UkmY z2Eq)}5$C+kI}vi`KR3epKY(u4HotARrZu>178g>gwnG`{6oycOrCZ8AMIy=1Xk>Sa zO#gnoyB&91<3Jih=cM&;xmUnSZPO&b#;l2G^StyQ&(}b>_~sZQLBj3PedRol%fH`0 zJh5Rvc^f`k)Gw^g7=j?7+!cwrN>Yudpj}Z1 zn&K%CDbe8_+6@4H3-no?BDWtj(r(58vq6*JExf~>koeZJhxoVWVD4h&HpVZU$)D5n zEKvJc{PBIt!lO1<@BXNyC8JCYjiB;fi)bw=iDWUv?{53b6)_t;IwAWG9Z1>MYyfk7 z!tVA!=BkD))xuJNGH7V@)AnCnZ%uRl$@$9Vbd3!@laGfHy13}|?w!Opa=o(*~$cq+C6y7^npXUm_-mcmM|5qSj@GbV`$Twx! zW2{hrbOqcPX)j^4P89dGX=UBTu&BjnL6DUtD@T(S9i9@tiE=H$>Bu+mDlujN42_=q z|7HQq>aozLg@LZMlv-5Ie$Sr-0Is4Rwu) zw&jy=jiTLC#PQQx3N^JeNiUz2=6~U{#wM5fgQoXbzvutD-HM}KQzS*udsHB*ABX&)rTL)$ z)?AxL&*_Obqts5&{f@%tXRYO$FO~XYh7P1^25ym8AnY+N^-h7Z2oaWov>FrzhwOoS zCp&JjWBIX?T=&wn*mn55C7?`xg+kfdc*T#?MlpCM8D+dkt9|Nz-3-p=Z58&$%uR1J zuh?=$_}GHs?`Co?E;67qk>&?yUbPdBw=`y($STievMq9ZRmeG`%K?-*!y-`>vH@g7>oxmrcjJqta&?-EaOql{2pHLZFn& z=!ANv{+^szuZs*%WA$VsC*a1Cy68}Q!4JHjJFrW%{BAJK_cqmM5r8&6ZhaLfl~P*_s9{@4vC(+K9(fA6FLd6(bmt_y zT3Vn`A_n+aWxd93+iy4gNBQsJ-cHoI7W`fm-+Y_u<@f=z)d!r@=>ih_y4QD~|H^8g zU59!yXaP5EHotn=U*)A(5dG>*@?iTs zrtY)C=GDm;8a&ZN97*paG!{J;@g=l${b`zWy>c>eXbnI>P_6*?X}1 z$%2Yo*L8TR6wADzw_2wyzpM-^lg+xvB+Jxly_I$5Vy#8V!Aa2d`l8x8>B2#M^fHu! zHnr!D*Yn|5EIx0%S;!IQfQ^vQ#f;9R-22#=!5lA zwa1xR==w}3LE07Kf*iHWtf2d2bu{JiUoT*zx6-?ezR9gNg;-zi;5rg=!kg~8F#oC+ zGEfz8JCwSc$k4?eqlPg^z%PR5k)?_!v((yu{#V8NFK?&*I!!nb$LgaA4NzqS(lpEcL3p5Xa(N88=HFikUXy`VWMY?{zFnaBt<$U_^HP1S%JH6YZf0b}ZcwVr-BS*HNC zt#)}niaM#_I45^@e7R}kctwe`A_{BZB0}xp^V!-x$h-`*UeZ}j;WZMY$Yv39QLkuG z1LU(NZ(E`KQ@K~)Bw72P@CWG=+9Jt0blTXu<=O{8YaJDRqAo+a?G`mu7>rI+-OUM} zPWuH%#jTxJGvrRTXISsOZ07Ijow98DI4n+>*?EO3v$D(2DdVe!nd_Qg=SRgdeq|1X zi*$d$$-;&^EfKbDqU|5eS75rFtwdX|x{6;Y-c37BaJc_a0t(pc1MpX7)f=^8dZjAnRc7hvMsj`pCHI4XIeh+k3thw=I zaS?lT$+13Ctog{*wO)GWOoQ(2VdB08vzS~3(;=N7HsWe5%^gETcZTO92_xj89E>wZ zfb1OuCwyk&3%@`(`Td3U6kUdTP5I8{k8*=?mJ$b2Yk(bV$8nqc=(*OFU%ocnyS&X&QJT}h`xBxB(QfR1_J}Yk#(SyY zvo?}RbLzwMI8GKC24)}!#}T4^o2zi-+izf=E->ZygSswl2-G6%FHY4B*mPg2tWx3E zI1w~_iCWI5Yr$TsbC0~S70H~4EF?yi=R#LxG_U$nxX*JD6bDJ#4~f=%+XgVc=ffBL zrTwI$cYxrW4a#> z5)DG#x{W54*!z8A6yKd1IllKJMvX|x0Fn$cFCLub7xv&eZ4eJ?+-*Fh`BW8uv1@6= zFGRE>`tJhwBXeacP9KW#x_eOr)-W~dJbo(F)=Ph{Ii16-ziv7cB`y)kWb=sJQ}z;z zVTni`a5;ek;BSlHy!dICZs<{$UZFLR<-$L>j5ykNSU&up7fz3+4R=&k1tA#CHDJZ{ z(pNfW7J^QFuDp3VF0j;uDoN+I4|+AJ11y+TIK~5j#o#$(7%BJhymJ zlPGXwMD{l;0zbJynuYdT1F?|NK?i}=M;eplg=qo`QyaCZmM-a*iE8e6V~6YPZ(m$c z{!f*^s7%M|>=v<1K!hrjd!&vx%V)s+svN2OG<%)f?tWfvu&G@MqU||8LGND*e*oZr z0fciuk)7g`eA@bKce`XN6ly4$hWBz1kBjH?oM{@wcUy6ooR`w~AifuwiU(LT|Bxxu zzzwoi8mO9$paUpm^Zf!$)jqVdj;D(SzMtTXlTSJg=e$xhD^Lg*3n}+(cgL#;wjQ%u zWEID}f~8xW*48hdlRQ}F*47J>ZZOo@ERrY+_e)KtH5d(4Z*u##3t$H~w1K{QXFxeK^u!jA z#KlMvP^2oPa}z`OE4PXlRY>D`l6Sa|o@7{7`+p8+qJ1H3r47jcMkMFh4o{kljO4}J zi01;%bUZBwzhaUL&&qlpzd?oo^|MB~kV>&Jwy7tDubt(j8}GEc2ZB-Puu6g`SKGW7 zIH}lmO#7e5h;|6ucNfaAUnSHbSL(YzM(eCI! z6R^V9CzYxDt4g)|er14-fia{|h+Ow2z#{5b9R}-fj6Fj^V@`(I@>o*peGF2I80;)= z@>Ue0Qt{q%bv3n`R@EIXWn=;_Y5V1jm4~<6$$qvhgx3-q$(0nZMJUXC*P2dh&F}nJ z=2|TptKpji_}1I8KkU<>Yu3%?PdEduR&rkiQU6I5Q9;S?N`+E2Y$Y!BI+94Kj(!h# z{ze*4wH}xz90Z>fhD+i9%sJ@;r8B@tS&l*yhN~F&1SSgy3s^m>{biBxwE3BeY1wth zvsYGDwjd1oS@&dfRbMyn9SZ4JR&Ay<1jWCs?95t^_gXGsh}2)K{?@*<_XMqqxLvfv zXZV+7T&wI=Zj@6sspOLsIb0-6XjnAPtCGM}(xu2({8gqbEuiW{o+9Ve)Y1ytB!|oku%48*Z+592>gdL^u(B5v6~UEpwY9bqzdRh{?2|xv z8Bc5Bd0PKOHdlid7cDK0|JOsmyZ`)4;^nsI13=v#wU;8S={A;|5=j8MOkaf26b9jX zqhJq|@x>?|sNDf7(*kLbeh##ON`maBZr;hNYz%I6K@<;cgAp*h4?PA6e0lJFz0e=dmNECsM)39qS!aZ^CW=m4=L$OW1Wj$6XG}4!*NTn# zMOIW}%pWeXj|<^#9tDo&zo*nWsZLi1HJP2ufoiC;Pfy&+l!H#q@YqL1t!Sz=u|UIv z|AU-u=eA^}H}6hx+r8oitlAEq2WZ*0p~sSugeU&rEP(fe!$dkWrlsEG@TV!gEZ;F{ zQUq)B>xD>KiDMApOYF0ITzBoOF~3QaFl=nZ}k0T zN+kvdV_08J5EkVNz|Uj2gJ?7^+HYmooELd$r`W<#{+hy>9*m_AJx>mdX)xEiU3WB_ zUVFo*ZgsxmqprpFKd#ZVwy{V}Jg>O`A=2{&Zl|O6?>_nVCbZ0l%t~(nLMxnGWum?9 zz%cv7u=(@jb@#gw(DYJtum3q}JelTSrX)8dS@Lz#){V%ff=<&Z_M}U`qLwbLxZPZ- zq%5(_GhL*G*+Zk3#%8Gfwt7dUPc66Ogf4wH;TJ5F)8zt$-usE#w%GpRSW3*>uPr#G z?Zppmuj~G19WA|!p|1=(!I+?(9vFh&Ah=!o-nm`Yr9b|_F}${eRs>3r53*VCt*itYRdD_irmLFo6&oq1Z3OAeI2PZZ<7_>nr|~ z9{B|CAkO<-ZL41oBiqdf;g5!e*k-S89RDOcdIkAo%J9% z>-7x z_p}XEHHqrgPVyvHsfII=s!EGfNjxvbD%9Qbydn{rX4R^vl{kxFbrKlc(o5oY`V0+M zL2n(*akI8u%SF+%l@={$3(>b};mN3${Z$WSm4 zt;)C9W^M)u%@7MEIVqL%)ODpGjn_R*ZHMEcr}6u)h3-Z{F3T8*jQy&r3MF1kM$-#g z-0}(KwZa-E0NNAsWCoh_)SR<{S{6ksaU=qwlFMGqdU_0azua|oazuwG?yR=1u=&Q+|bE-!B!ke|&*oB?0h z!tZyaHP1_fb^t1ra38zWY2BtuCUfOncCtdq*-{ia%s6BDREN~W1OszP$l+0tSZSW@>I0&eL(Ktr0;{&@rB5;cqHLq&5#d^r{83c zMS~C(x)dd_MI-?^zlv3;;*L|7sBlRN#nH`+T*>;mqK+BVO#D!y>k*ff_P?q$t#Lcg z^n5(;Z8_}1W3`whct0APh6a*uF+k{k(r}%zA4tDiQEreI2HofmGh{-Em6@5L&%a8+ zZ)sr>zpkwODdg1(T+%U|6PlE1i6!985`D(&MLJEcsB1L-{|M^8erYjuVT4IM)|&l~ za_Zq-jkBp+w`}3MK69Z2LQ=R~I+R0fh5()*Qqp7StT1I zCU_`h6X}gj>I2A_d+m=T=SLNZR1T>L5q2_91w=?l;XLln02S0*fhK1M)`k!AOw|x6 z0tv^5Bq3H}Ie@SAWHS4E768QVy|nFmxLL#ID}-Jeip*wR?htU;cPaQk$N*j*gTe8P zn9-p5-tK&F(r$4neK6&xl4VX$1bQquk)KhJaw1yl;nc6fndF?HUuM;6#mu#cp${j~ zC_Y!j&4Hcw3tIDnsqv-Rq%zQDP`|&(4e>m=Zv~Kl$Nxvk)BG`ZJ_#WxV(L7lLP=U% zmBB*TRBrevP_hTXH}_iw$3B9KV71em`(PpqfJ${)T&)Ds>)_S=bv1`$CN69^|6^-{8`Z#eM2+LK-L4#8*WG*DNmX`K1%S40jXH z#b!pfLZiyatL9@grF|~q^MWK*4rJkW5{BVjTqNFc z$98L!;a7n1;Y-ckoMU$-Y-zpJbde{!5hV?$iX`+5X9WIL*~ySZ%ILN))Lz$3I7`jV zeyiJp&vr1T8GCy?RR;lA4V{$hi#YdiI9zWO43bt$l zmO0s)5H3M9HM=gR`TLq^x}A(LycntwoK73d&dH=NGJ)Hqr@S5|IO5evxjf}RLCeL7 z4oXY;f*FbYPd~n;x_z>C z)y3wU#tI8Uy7^rtRsj(8-|tiqP{&QgI>i}d0?i|$aXP|kv5>n1N!vpZF z;JR7H4nGdHFo0Ab7K`6}L1~tskYe`)-s^wKKg(4+}nFuo)SeO5ZnonhhlcCY&$tj3Pu~e4-MSYARqZWLv;06 z5MU7y8G090k*N=KH#v+WB8(@>j7h3(a+M`cW+?eeoHbK$Ew&qy&*X$!Trs02d?Xoc z`=JuXLs+8V4mwIO>JJ!@l!RQRHe*{MFBQ$v^L$VaCdr zDF3*B>Wy7EDu2%J2w}@X(I95T`_r`8LDml zais5-pvZ~%PlJqKSoJ-1f9gC(;u7Dikj)JYE`qcUD#!ohY|}TuRnN{Jq=+M^KDYoc zZ~!=wEMRXP)S;Xj453j_%S1Dk4<*ZaywckvL1bN5!4=o*m)>H|r{u2{D}*Gzqx#yn zAN`ZQ!6c$Fy?^^)cK_oq@qfC14_M&02J zsdz&vX9nXHmJe+yT-**wDNkr0Ws}teZL6v$cn@)%=GlnMIl~q}7;n#$zB3oyd`~&& zuaB3JB9RyciWB)h|AguwNvRW|f`97h{xL2KP}1%~O$Z}URx8l}WS`+HIQgk${jHfG zO^QJkt$ldmx_I|>X@Xg26dmCG=B`dm3bLRgCoHCuA>AEs0&4Gje_!H!xy_BML_Hr` z&%ufFjA5HutUf6>fX3JO`T3lDw!nL-{h7>aqfUY)^RM}A zPe(u?3hR z^X^R@{m}|CTxz#wX0u(V-B_JoDu8J$6vo;9j67a{MNJER#sWIrAafj( z)tK|8PD2V{Z4*Mb3d)uBeExVZ;p@GeJ(YiAbk8BMx?ZIP*(6wLsVp2keX@N+jT1I4 zOX;i`U2%{wR{~_Fd)(#^iJ%?$|<2NSUJ|c24NutNAOXi3*&mokL zu0ZmiM`I@;l0T|!kbuG+MUY{>zGdK=Ox)Nc!ST!%Xjr?{j*EI+Lqi8O)98dtIa)3jT3=6igF-%z8Z1XJ{{K=H1{m1iV zHxRd>sNxgVk5yIAY@};-pEa@C>_lpG7P(90eK=o*@e!7mDFb)rYN9HsS|V-(jPJ|U zE}PT<1(L#J#N@3QV;4WaYEl^a81B@hcp{~`c?TX5n+I3WMY!Cl>cL}}?*-)uN6qaW z=04CHS{m#iF$;Kg`iWlMb$3&c`88f;wwt;~i*0fZrvn%3#<$$H5_MMbv~WaS=F@R- zxWsKps#p(tL}-6KAMu~)SP(F1BT#tG;?8y5_xFD=8Hvx8!Jtv8Ti0oLJcrt`Z_g>o z%~N|q;cMNOrWG9l&C55@ByjIn{i$4kapfnI=aTmqz;f6f$tBkC`Lgym)$4Dp8BjvU zxpxOv5KHy0m>@IbPUArgtCbI8kkx7-^S@#j0&eB|@3aN3Py;aobou&EVauemfP->9O=)Yo_Td)Q$6m!nth`EoBg2S$s86S zZP|8v+AeB#9rjkg>3$EpM7{f*G9%HS`3KjV6GX*j%4suVB%RFy&d~9flMl*mvqLKA z)em_wHSFUnF6)UIuICx)k4uhS0$17)WULSvd@tBY42A*T$Mw+u$Boce{ATY0U;Y1^ z1)%UD@~PJS_*B2nB2N2h&vRzvx>^6jb<>mKVmj~LVAv_g2%FmjaUd2i(%x|J_gUKX z5AGMUC{7O+K=S%yQ_WNt=;Zis9v;B(r|{J&XYGG`TDN^H9qWIj^GBJXkZbUw*y6~_ zlumc3L>>_PU(P}nasIHZcS>zyy>*05v3J!p*|D9aA8vsrb00ps`ac+bsx`-H%s%AUD8M%EceFKbkU#eni@Myf^&a{%lX8H-|P$HsI6T zb@*MXfwd70XZ|?)2cHm4{^ho(COQ(9*AI9JB*L#dCrbs$x;`yAf};R}`Xxk)@)SVB6@ z)(JHpO(pr+Q>#SY=OdOdX`_EX`3L*qV^!=Bh= zGCLT>>#C#q9)xqf@u(9vFd(`YD69)2u)B(M8I-b3B#$06THZH0E)`v^w+Y15b%O&s zz7b;h8Zlx7-iQF){-4pZ{#?%45>qsmBO1Qv8RPK_5v{LL@Dt{i9?Md(zy4lWJR#Mq z1e8V)sl?U4?{eL8{kpE}&R1;$nHdkgD93Xz9pT@`jbHu4PHVdGQPzCG95zL?WYva~6xw7njqh+q_VM0pP(Cy2&@7h%Sc$@pXwra{ZBi z!yGm@wH&hFbHZ;P(P`ASbe}EmmiwjlLLUv@Uyy$AZ>PEFWg?zBtTo%)=Q}>GKmNYn zc{Rwf>#{OAo+-K}Tk^4Rj=1CNc}d)qN#H3L{qKu9!tF-R$2AR>kDA!~IgKGKSTDnE zTTI7p%UT3u<;XG4%s2b>*KdLRbYdr!24~_&;Y^U<2$#I<{HiJT75t6{b&~wtf;22# zDF%>)FvinO)mo7^ujsD1A%b&lhRUKqYZzCUI$LZoClfAejA{_ct&fQyy#1UX>WS7$ zY7dtGHKms%p)bg^oDSUMfNSxuJaKVtWl|-r7Fr)VGfRvHP(Rk+eMwSN0Cs2qJ`b)n zP{}Hyg=K$Q)r5RE42eEmU_l56j%GuxZJVcVLg?Q_wO+gB7irY)=rI>*2JlDSv%e1U z==KBGo5K$5IG9Ox8Nt>^m)WwC>~LTdb^3JB)EQ7e!S@{k1~Fn)KG=ZqL|_~brX~V} zq12RPL|bv5rJJ z0k`lBB8x9vNL#$Ss@s5eQ_uMsntsub!)@#599mncwG?&a)jn5Y-LWzaf(f<}wV(sk zHky3WMVRJsv^?V#hJlD%`nBSAvEU7PFHN2@Z91Ofb9mS^p$7A^;cqaf0Si0b6yvLX z7~!!lT7q&|hWJnIhw0I&CATo6L_~`MhgH6IU=LWSUMu9~?|ORXcsv7ByZwB~8rMLS zEU$=@K>7>TpK!}(pvg~RRK{Zu0X`B5O`5COPUGNWD$;5- zBrC)IBkrK2KoDDFZ8wJjgA28q7yL@K>|Tw8co2+yRn)|3E_R$VF3YE{(Sd)m?EYRS zg|Sz}QYpHV7bWv85|v{j>j}y3s8vY-Vlg|C@fDlL54~pOpe+=ybo#{G8TJ>T_|{s` z>xUZfhbDe@PhdpCQBT#~@9&Mgxr+zWT59(cMn=~kjrQj7h02zquEP1xWxlTX93Q0Nit{?fa*@5aLgc$+ZA@c^vL z^>^#{N`%nQu7F(Rf@0-J{FN0ht0g;tP2k!SYxs&6=KDITXa8YoyvbK&4A6f19pzxyV>b3Utc6`B=LXjCj!>}F0e#| zy5*WF$-rzMlMfhA?tHDfc)LWB&!W;^T-GmB4y2@3%%dD z#2GCCjjS?Oks?y7>t#%yaL5jTP-pjfDj?WGSky+ct<`y$ma_Zcp6mmdom@ba{&1Is zpyfwS>s#Ve2=vhA#~{+vEWu}#C7&-6U`gwY`cKl~-PowAwh1K|2xH|Nj1*M5qFJ(Vw^O#M1KiNl;2 z;LbKS%0NdBJ3F4vjANQ}&(*v^kJAd+6{0O`I#g*Ez3rh`oKNhV4-oXaFLc`C!)sOt znhyjO(Xg222i?>66njVcF$5vg&6tDB?9s8q6Z+n8v1xO9+$KVq@fcBpW!dBAviRT) zD|z(-!U{bK-Xk<7Z7#-;ahPz60D@tgk;W=q&n#Q8bZhnqU({sGvK!bKX;2|&SyNZ|+S zD5|Y-kDMD380l9ADAKPm^h8UXO2a>H1%`LhM!#`jC&Drj{H3cfI09@?($Cga*09oG z!{U3G=*KHXo`u6oH@1tTwHD&=({MFlH+q0BS;iA;+4nSsB?p%>J+V;K)c2m_muZww zWFN3}0P=0^;FrLb=Sl*J1)z7r(Yq}Mb6mFHUWc%^f1NEE@BU8@-Ypoo<9Ge3f62df z#!-F-{`BYK(L|J!LW^_MA?}Yc=b< zJ(?brpN=YNVo(nYUp+Sjf%=vKx<_IQ-<>9L8s_qgN z3#zIelY&}OSi;aq3-0Z5%ws)6r^YT$4ZD1Fw>8?0n)ljB>^Q4;+HrNXi8hKZ)Uv6O zh;szmIX(2tArlYu3K9`{Bv`l0lgj6?Kc$>%w=I7Y{7oX$P+2fM%+TzLS2Q9NTu=5?{sNowV9+%{?n$QLu{bz@e-(n($3H?Jz~=|XgjZDoBp?3rNGLq6XALSd-DI&zdlEUN zI<~Uk6-JT{nE+0tD3;Z8vRqXp$afe-p-*s#=^AT7O|6$Qe1k*TEGmJ!hGmRdJaUfp z>Yfk&kKNF65b<2}EUQk9;{-1PVAM+fPvlVPe=T5MM9&#-%J~-1AM5+3mzVvO&AGJP zR)uc}4JB&8U)jfGC@nAp@32U0+f7k4A+7;p01aIRFewSsrtUtaF);25fQ7&DKof=H<0@T zoIv!HRLg-^&0F*wWvSk@X+;-CTmp7#A^*_Q)^k*vCI-K&j zZ7*~p_k>4l6-9qO-sm{zdW83qNz_gnS6M_nq$Cdzxhcp1D{`0*-j@g{ln|_Wr|tRB zbkxbWUDZP}dNq8w_A?$$fuhxU`H@1afs4;lqt}HGaB+hPU?=}@ey<1Gs)8_hXxO_W zDiy%?2_E2_oZkXw<5E2|3&LO{8=D(`QY7hwM?vWk(IF@yE0I3NsNkD5!TqIsJ@PCi(0UfjxhqNQN1sZL|BUTSS^rNxEWn8^s2itjRgFO5EPKHfpyAc*W^ktMb&Q znlGzZDF*LM<1*~)L5(-jz*{f?cx`n}Ay~}C+oO8V-!^Vi*e$y);n<#W-yn{FbhFqt zSvb&OEnnx)BU=fzI~L;$`TXctdHS1u=>4j-*?aW0pw?tuNxks|u2QoD-lpau**_54 zp!j|G+;f0-EQ1q<`JTrS_;nI=(7gs0yBXr2yeMSTU|+K)Cl?17&G&{BW;#SW|9+!U zA*lY|CBG}Uo>NyhCjA`qZZ(o50f>J)UQ!0HmJFr#H%I?kl@Su4pud?Ce7r!edwjl3 zyfAR=8e9CbDFs?|YJHmc*h>KRPB=6Hdq=STFi23^n^BckudK(63WGuC+g1oSK!6|1 z;FV#j|0#wS$7npFToj;Oa=!KKh9 zzbPi?2|6SLl;YoMj#HJno(q-f4xn`Gq2keLRl^qOW_0XI)iP#{+kfAGrci(GkV(~= zT_;?9=HPo9!9845S$r$ZDF44%!0#+_iYzMLde$G4J%WzN-@I$MQupofetcYPoD8ZN zMnDfOpG27qmzf@W0Wn;EI2e4`F1I?PX+!loH;vK?bm~pl{d!Z`!7YD}klv*=@%(xS zmCcHXTf*&$(5Nh8kENlZdhG<)c8xi6rV-XzJ<1EO1@o4JDJP~A=5_PYA4bSb*@?5f zMEgW=b&k1LQa@vP-oT2>ZZr72%TIiuC5sRdV!3st^aBg2125-bDwui2CiB)>+IWE$ zzY;qF%is(4^l+wO_nKXtDgIgvv%Y_0kD@)0*h=+>L;s73``_7I zcBw;7t;HdJLydAS^-4#ryEHE$=Q>Sxr}XUGmd&u%{fhcx;4R)G;joRErsxOTc&Uxp zp0!Es@A8%K-RVMTTvqbMSa!$gm;C%AYuAcJIuF+zsF=D{6o4If9E+v!z+{*L!zZyG zy=Y3%S-+?lr1sNcT0;*+h!s)mBeu4DNUSiLke9ng0?&2PlBoUQGM3-iTf)MoWo zjvBH!r1SA7d!)0oHtCSJ5~nVRL^;kGwvzC8?7EcJSbJ!XyGtT3%EW5_1C0t|G=$dqnyd#w)v0Ln zJy{Z_UHkk^Bb$gJHFtoTeoJFmYx4oR{oLBNH=2DTAN(Lvz3~QaUgoRQo;&ic#yHny z$048BxuxFV>&7cl`*F1GAiA0t2LE%-=L})P4_%3?s0YBcGZnqXtgm{I9P{~djdGPp z@J_+^j*`=zbezb#suB6AmL9S zb(FSMIPhx0DZY3EZyN7h39Tve64-lHq7pDjagf8Jtqe1cNJhMgucc+sYko*2N~I~4 zq8iLpgwvMT&1-Re%zjrh&}6B30wGbxQxoUYl1b%U)xsEs83{IT zobrjY+(kl^p#>vK$a^zV)92q38r-QdXUONA6H^3gGDjt)Pg?Nqz39~NSChiG{S%!{ zg+-@~BlKo(8zWNSMzOogxlCQhBvRdj?@J*p0RHCq1WhtwRcH+HK3upi@;DQfERz#? z;e_t}7i*)rGP782EaOCEg!nA?p&^RpzgR2cF0~qkm}|qbI;4SoW~cI5)@u!4lP!>r zTc-VYDSodlUGFgEQab#!?Rg4MoF7i@WxbaXld(2^tX@wD_bgW{5kD09`+X&2Qehb1 zH9>I00}&xU{=n_aFdCBn6rEz*1liv?Ii*EEB1Gctzm|*Hb}>Hdyevd;roXM4$hK5! zd^kTI#%=%kzFiGAUms+$PN92{F9vYJjQ@+&b>iE&IbgRuaP~J*U{+a4{YkZr)xgSj|Adcu0bVJvyDcdn_X|5Krzhf?v(vUz3D`M=Ej{# zLqj7FM!M`9K$6=n{2m*c!7ZOS4bovp`XEF~cQ#jJT{r$wYRl)EKu8sl+a6~OP4#Nz zUkWRq;e_}X`H(dXF%Hr^+y8HT*0sP9_njt0b&qbkca%DWja7(JURJ9=9I4=pQCiNH zsD(1C0A~Z(FricmnvhJ#!jPfQm-Ic{FE=E^?x;%m=-DG?L8w`AxDadL@nKpd-x810 zZn$K~^@r#Ku0-Qnh>@{`@QlQ!?Yh&(V>Hd+O7f9GQM{gyLCxG{V9Q!cgIh4G=}c%` zmZ{b{(B|tg;G_^!qoOW1na&)#N{2gB8hBhXGsC%wQP%>c1me)TyvwkPA86z{q&Q5z zvj3hXLYQ!yvXg+|XfieEb#VPxsZvw2k{qWBo;CkJ%b~c%Yk<1JW)?g#51}i=j=Ugt zf?b-eBPx`is1Q0U%DicxKn}x^g$m1y>xFD&ia%o?Qgo2S9-Pv6u3B$6=#phCa!vtq zp9O-bJ8^+1J?J@|UpAj!_;}h$|(RR`#!nI)K9mH zm_P`3NMsoH7kzuli*WhRS>&TUgg1mbO7e`fBvQ1InUi~VFf^>ml_*o8QXp#;R_*md z+^GME$G~<|ZQA}&TBz5D_mAPNF_$Cl`sB*aF)-At^W0vO5Fvy(NU=7r?Nv}Xxb zQqC^2R#~MelNiK`$?_G;aK~uE#UxR74!DR6GotkO{uMkkV#EfU*oPm)kq*iJDsv+x z;VoA7E+;s&Z&j_}jFaKp96|_s@h7dL6()U1w?8NUo|CpMS+w3`8SQaq zA0bNwI2Ss>OK@RZQ5f=|VuxZsfG(4bmrAsU7KD}>#n{>ABW!F|6ja)3vwSd=EvR-c zH(p%b492a}clqk)h`2o&v6gDSDNsbHoMzL4U z^Ih`)?0x^m1Kp;f4kcX0eo%UQ$1K+Wi==Ny#b49Tu2fRNTlTAO;E@kcy1*zR}Mv?n035rW|lV+P<$s{6CBrj?kmU35Q$yT2#3K3&sdJ@j{^c1%0HKBhA{)R2r)eY zyD`C^%X{765cZ!CC?S(KPydgow~UIiZP>PHL{dOtfFYzrKxF8lySrPYySrPEPU-IM zl$P%9knZk!&+GZty}p0&hqYj4PL5-bZC4U>IcPg=Ig(}Ay6$1>7q{-R>tf>*&Me$x z!jyai=o`gX9drxMZ(f)s0i|8F{%%)$QhS1FP3Nu$eD49$ai=}c2%Fq2tyl!ue=8WA zoRvZZ>EK94HV-f|I(ICP2%!ixb&B&iXSL&7eA24-a z1^d!lDgZZ(^mNuqx6So~Xe42_>jov2nhLuaT-QEBBd-k(QS2b$4Ns%Y|v)s2; zlLZq7kB;X-?=us7)Y*0QyNiBO%))>RuMk}evW95gMK3g;Hizwj7~6eJZ$fxv4BsTW zXVod-Jl%cw4!kre8cB@kv*H9C?W>M|>QhuXJjs@=SA8I2BP7~rB*{gkY5 z&L>IC^n)WD7XA?#x#m>HUG(31vPp&?*B{fK&pRN{adqz5>N3f-Mxnlj&riqRbNwkg z@iW`MA?RT2wf!25Wj5y#^>9>zfY?*Ale(`Kz<*fvO8fa?)pb@3wO57L&XXdAFD@*A zECT1k^7^JR&b@^hYu$A5k3$chGBRFvDzY8mDa9F@zCe7$h-v5hyIBFOz-_j6K<% z)X(eZRvhh)YE`)n8#h&GX-Ya(%W8SCcQ~(V>KHVp$_O|wUyU08u!a!Af8jIq0l;Wd^Nw**JpvwV z;GW$-JFgw^i_tp>sfvQt6+_8m700rM57AQbkIibBKmhWO>)(@I9b)0c<2Z zyQ2bYm5W5F?0f+{DGFM~bXW1q=ycx2KNO zv6!fZ%hMPZ1eHm2!X*!@fQSiHLMg6p{jx^0I+G zdIxpuKX_iqx(`?Wrv(5O%{n}DQHQiub;0dSHWdKLYQAzq|1q1@GknUA{AHGBq56um zO!p5QfR;0%%GD^Ql;ys-|HfbZ`QUS2E+NwRf0MWi^$tl$OOy9=jUAx?@8=45=lv~b zU-#R~SPnLb~Ln`72Q zT_HEM!cw=a?+mQSAIlr${pDLV_{CS?7F5B?4`KNhc8p~D`F%)U@lVgcgTEVa5C&4A z$T^<|$gN@-aM_2q>lBeP~AE z4=Vv9)zOv(2|{;-(OaDeWTO!z4DF8r36_e1;$*TG!<24@N$qAtNa2DRZSuHsbL3Mj z6XPN%Y~@H7H@$%)1B==5GL70mhjR_5Wj6xbaKs>k7Lenj|2ua(lYtJilhdv#34z;1 zw#m_Qh6e`gsJfF`v_*mKR45Jb4)U2$DSCaMUYq?&DwW8MbSSr4bcvI(L&Bj8|GO;- zSYpPakJ4pRggB8bvdSthYV5tb!48U&RANM<&8JXif!|A|B+QqP@TXM7xSgwhFEeI- z)k)Cvu`#1HSZS&r!bAMmj9YY&y!hX8rROGKJ9*u$7bcJO`4(ol6ArU_JU-5MggT5h z!>j`Up>B(7A=WrfCFWM|mf~0x!tX$)#{l_j$Fu#Yd!>kkR9uqYD~hYzI4LQIAi+x&gPi|MHvJVWnTb^+ z$xLzjUzET}Ngd{2Y_gyqjX|GN)7IU?aa|U`yF>+CEW|F07!>B`oJyk6%4vSmeG@3L z=q=-Z$I@Cfpy@fOzNV{}<|>SyOIqocG`10nTx-OIoP41-i}-W<;0l*u>2WSuL8)eu zhLVimoTzE@YO0yl#Bgqa}k9S1j;YRADpvn(}(Upw>H! zsWSR0?rPWkA1I74fH{v_#pw~LxDURdOq@`X zr~zG?oNR9_rkI4GI;+Cqk`uw$ns}6^2wee(BM}!aFE96`TX82zR`u^4UWx}h7Hg|E zYwZ8z53G4!&H~sChtKBj)@*1XhpdT;n#sDDz+s6zT$=nMSxT<0U80yBC~M`Mh}iat z2c?0=m`(H;(N0<<6GE!e^Ei4sFeDyKPYcGDL3a5G%&_5VXa3C5JS7b7!QeuxaDiZ_ zuP?5wadX)ck>$RGfSo@tb))qh7*=w5s#GzbAWPW1A5_;J`q46Mzkm~)CIs1aT4tiR zY1wozGovm33LBg46^*vHFtvm|_40)2Z*syb=1X>hlRmE~5iiNWarrZMV_f86tJ~vx z#AUBSXCb%YFSn5SFY_ALtJHObjz7PPPnJmdq8_{P+kXN`Z?$anr#Knl3%&!l>F?2j z$XSIqD`olhfhaiC|B_|2Hrk4LxMW)*jG$3)b7nJ+Tl*93R_lW`+-YhBe&3SF-7<>* z;IP&^T}6BbB&=abG@5TiiKx)kD)px?5jDN1%Xdofi{7qY^s}8d-d9ANot1U~s0;Ca z-T3|uHQlZc#PPP`aFKJx*!fHM`coUQ?Ho+Bi_X5{3vBHXzN!)Tq5C{jP|KxalgM}M zi{NiOqmFgC?WKnRTb8hmYwpP2Z%-ERz-lm5+vA2+{dzx_<0f3m?$m7$iE}u^VT_Xi z>S(GC_W+~?@Ne{7&|h7rNx#`m-OJzp*Sp>xPmn3hbc0&A9n77p1ONphaO1i+@^jy` z6@dH$&xbt!Hx9b#@RXlu^31@+C(n1*=3uzz7IC%M?v=V-iGImj2sr$BK!yrmmh)y? zKGBLx%}ti`!Ep7@?z#QM&HTErMMW#gytW6pqT|(_=iB=Gj>Uvhicg@!pOh)=HOw;3 zeGEbn4(KANB|{>Gp$TPAKs5B_l#&P@oP60&Z)mdgNa6G*=CWW|IA&}X+eKYNw{8>n zRrm7q826E5n#1X$<|~v4zvJ+u>5*EZXDw2o>_|X*<;w$p8jz3UL@g|}0*JH{rdAdx z-IO1V$=oa9m(BQz%-np#$y=-p^WxAThVxaaO=l8S!;JabKH&d6?h=MpuUFamH*-sm zQ@4Hp5O&>h=u!Chx9*_+%{i{qZY!6yfIlAQ=MSr{TM@1sT_M$tLhRfb!852AGMLHa z!;&12`-u13JES5SwJluMt>^}#==~!2?Fcqct?XM=jDN_U`+ZePNz|U&NQc$Ry5)Rs z9oqiosBQkzyZ`dv_{i)s?fqPbC;S#BHw=`jK7jDF{Z7~OjL+w%7#?HSZ@aCF+RPVh zpSB%L0%m9FCbqqFAB-`+x3-D@W)GFQ0esLVab?2UB7TL+Q~Op0m+jI4&6WtGGoLN2 z?j`mOBBL7Y zXI1Y9uAS=4R$igtcA-kv=$oMfgFwRb)$FrKPyB?9G2c95ava}qjV5^JRY?0Ud)`8c zu%v9|FWK67lI7%q+Ut-}Th6gKrX*=WjSEPdh6}t1Lt=R=r%MxMLS&JdMpeNc-E7zy zA?l3z#h5mGVAy;&TJfT2k_C7tQC+p7bwD}egb6zRMJ=?(SckWedzkR{A#%Qjem&gV zU3B*{MLUoq! z-f*BD%K$zn$4uy$eY1#EaJi;CgF#z{i5u;V=N>ueuz!Al9kyaRwn9S7f({8lw#HC| z^xPzGC%p5xbHMB^fFF$hWI%w;L)>z7B0#x-zpuEHESk+`%teGpVj=C3z6?t{a1;qE-hX+aO`@*3IlMaa z*{yC=#@=2O9RJflDG4tpMC*Zw{R}gf#|)bVqc<#Wm%{f_U_i>?r)3;QE?H=E!|{H+ z$}~-`_Wz~l&15+}JFoNWHu6g}4#SRWmvdvFM#iwqORz({ba@esJ8`rHKf_?9))40< zcK|!20df5N3s@KNKt8#Cf(`N@_3PN0HYs4OMsT`p{t=a{IG%$A_vF8aSashW#rgc0 zJ;kR*2iBk3DgmWt-|V)OP-m<1WJkm%B?M1YWRq!?Rh0Nwikh5=3i2i{w7EYaXTiZl zqfNlB(Wf#YD=0z^uE~sOCSh`Gtb%^)(}21u4+5Py@@f>|N%9%uR(X-9y?Ae`k!B>m zsaY#Vs?R708Mj;}%rq~Nywzou>>(BqQRY{4cKW@V|q zYCwi!EPpnwhzfqFiQDs}46u&<_qx;SbR9o@9r$vA&!`)o&UHsNJ`@2>X0<@7p`S}| z;@}(n27h%-srCW~vUh5K6^jxIiHv@S80b!Ez@6?f^#S1(6XVZ;gk$W$@8O^7-j>XW zFzLU*>{;Y?<`x z4Y}>@Mr1()XJ8CT$}3_D{dv3A1U6Z5V27;5>|67c|d`dW+d0@@?4RRr38S0=W%w0~F0d;Za(d!I;=ON9teTlI; zuI^to-)MWr|atI#2n(suHcU-T%c)dRKKi%9rW0)uQ9J>>4u-93{4B?V!k6% zf`vcpI#8&68RR%nUCROGW}X3VRzUcJxx4f7qyoyDzfpW59BlWvCaI67%sUDHV|pT) zRFfAR>hS)}t38A9Q;g$<3vOz;>% z-@Hx&=V0uS)=y)VUhVrq1XUQmi&O|uzen?%ZPzk*#IC24+%`ohMM!*4c zT6cR0+e!hLQf{n8c)O&)MA47sv~l^lj_*mZ-|`d?PZ&GgP(~4>2MdhN&n}F?k?c}X zE6S8D!x^~}5+j3u`4bTDtMj#|Qy~#{`U-rPK41*GbAieIYi=?MmJ@Kue|y-=?0>vD z66`ikl`&m?T8+2{jNnk!+EldfkBhC3^7V;s$8&HRdY4$)UgeDVL&0<^6EeB^RD5hhO` z+nR{>HNAM`vi`GGZ`oA%2MowALKQb1p*S=L8s}0M<8RN5u6tbTC~uuj6HfPgKCdP` zsO>1PZ#o_Ahe`i+m?j){{}OHt-7fEV zW9dV#LnBi4_c`T7#t0^d8UFkIBm75(d{x$;A1^^OJC<@PX2w8HGNjgx5O3y?A3Kj+ z#riBGhjR%K7&}?l=xU?<&a35pO8N+xjitpgNw^7K34<~p?vt)xV|{&=bLWuX!n}cq zxq$Ub6Z|*h5%ng6#&Dy|#b-1&8#g4~D`3&RD#IjPnZzKTge1z}Ck8l>E^q8`9LZ%9 zz3nUH=G#aEJ35ikr#w}sGN~B~_h|p-nb<5sjZEPI?K#LqK!^pW#tH?Q*cJwZCTj*LCJSOokJNF_U_nFTGJ&yCh*xrEoy@f`) zCAyW>%Z5XPZW5E~!_W>fN#}7@UOMv+AFJU#bH{{GFu@>Fa$X5{j)1b^dfO*+nqq_L zSA5~}X>kql;2NdJaTJ|OB6e%VJ?Q5;()rxCaplB>+3XzwkuN;~vlLO>Wl*cX02Tab zej7AOT@cjbyeDyL0Y4a=kw=H6yTK1h!yF`&fH=;OXA4d3OkfpPOW{(8p{cbJqx(p7 zdqa$82pGVa6Qi=NiMtt-itEf!K>vJwW`zffx#>bY|{W zBa4w*Bh=^FwDQY4fGwcE0=t!`=Nu0H1&_-o{|Xv!JX_F0H~ho&xL=KgH`gJvi`*HR z>G}`lHqjcQT$Y{NV@FonN1o{iyQFR734b1s2_f~1AYu!) zVbYwlc}LiA0<3}etu#Aql3I-2@}OYIr?9)(cSMUBL1B+v~P zjYPC#9V~G3PL-c7`;VN_nYLJKw{Z`@X`}N9CCwsw7pvpQA?NX=ORw985HgyI4;9l> z+5+47;I}_U>HVdM;)PpZX*y-de1GPhu^S_OtSdB3Rj`Ewx?=5*lTNDo{LSa}+4kh6 zT&9r$ldSz>vDO5i#B)P`#p~`*)6tm6rcanTY0Gs@)c3XLp7Vj8sEwZ#k-cp_m_5LY z5mxDSVgX&3NvU&%`L*LhD;0_{+LriLr=;r-DYa}`SejKy2R#}_2CW+wzy*2xfUkS6 znC5vY@w*V}xVm_D+AhXMuMx?V+y9T`A;$(c5-Q2-aSZn`Yj@eTRb{X@Hqma=dcyY5 z115h3UY#FfX^R}M_giqssHiOBOZ}&b832Yw<<&tfx>4@FR#gn_l;^p(05dnj#Oa)f7Hx5w@oWjcR6~XE~T}>(8_H=y>{gtco{oFOeW>?Zu+Kvfvq!@uBM5LCUhc;_yv1raZ&E_ff{!ZYSF@Lm-PxyjC1SI~<1>#_WPxLnL`A_4 z)0+i$NkqJ)(Y857V);QZHGa9wxEN*%mlkub9|5=PyWMdvI3Vh}z6osgcFFl%I?!u1 zDE<=;r2^bFgy!ds%=TNSItx66deS2qBZ+Sd`}4PrJgw+&&vNVX%YMioxl58yk4=P(~fZ<@u-NYm$SJ^eGply|CL70f>i zzRhjafZBX;HHP&)M|^p4BJ<~%7%o58T~^|jgX_I;W_qIR~+8!Y|O2BwZEiCc!$|mxlS?1 zBR1XM^83)=>4N>}ki&gh_VGHwTV?1M^Ct}$iP{u;}^wlfO-rd4`qHeUlMJ!K<_;2$wN@!QW4r8Bre zZg?-B2B9pM-2D^eJ)3X$=V5AXa6oMmgROaO{b}v4o0)NZsElzxF>}d2cHj^yp_G#; z#@VRx>3P=eUw7(5@D}V0)6XX|T13{_Y9sB8rc30UY-()f)Oue^3wu)cO20A}RnmS| z{+1Y&!`WIv*&%84GJY9Wv8hkyKh4v_W@p^^U6!r$qCLq67<;2IifEGueQOj#q#x=% z{0l72n@F~27Tx9yz(^8-GTC6d0|N$Rqrm1wX8$w{#A`L-1&tBrUjIJ40mnt<87{;G zy4F!OJlFHmo4}c{Qk^@eJ0G#&JzvCuWAZ4qo^R z`9v1EcI_{?>UQ~caaz^1W3=*RtmgSYyF*y)gPbhl-A*FThZMA2pXAqLEqOq2vE12xosn^g-H#4ifOEu~fh8c0neaPL&?u*V_mi zUmsJSMWZDBgUg-ox^S0-<}H()kNXDam#B<0%rkc99qOEy0~C2Qr@Zq7LRH0jZ?6Op zOO9x>b0saQ+h|-p2nc3K4%O6nDSOYnF|hFiSKZ@g{tbS|w$c5d+#3-vK7_m@R&?O0 zpj28$%Qrb~oLL7BGNjr`q-T=k#mu()<_Q+@rrOf23?`98iU8wh% z1{PpeKjWAmo=f?;P0`CUG_&=k2Pha~ zQyTDMtyvcAM5GwfC8UfEK91Zx98i8_=&eOl^fnHIbUNm0k1;teU|B8{8PW4J4%VVI zFio2#l?Gf~F%Cy8pYKw$ye~n226O$a*rkNo%P-&~}2_cL=t+h*024)OJucnvZ8MGwBlm`2dGR!4$q}2jikTYb+ zXhh)UWT{?iJk`3tk#%|bcEuSD1VPYy{)fMbU*&!AOV6}w9R~^bh~9Ba-Sltoqxet- z+L}1jcezYh-Zab4v>;YFKIh|;FJ+Ck^JhvFn;>XZ&QI?|!PtQs^+XNlpp=S27U1Uav2W!Vr5=lml8r-A#%KjNM zB`PkueZKvyfa`Nt49R>5iTCygdW|*$sU&Ws;Y#&-$(E2G6^>)+6wMm7-%RF+M^rS9 z*eyFX4=(wpS)P$r3QX7z##}&&``XU|nv4eo9(SiPJk!d%$MT6MX;eDEw|}SdhkNJ- zcr){d6aR(MWCEmeX4~Im5Ax~#&po@j`O4iXtfkeK2ax+TFWJ}5Lm;$HG0qG)4{4dA zlJm=|)X3BzMMD$uKG*O2{E+?XE22+9kv-%R$l1(fplvvT5Xw?h1NMmU^r%o-_JDAx zc*-iwV6b(p->E0LA|HoN;8;npN{eWc&f{bi-G0z)8k!7*SPmB4zTwg zoG{hldhkOh_ixEt{(lNLGMDo)+Kpn9SiB6avSVhtAqS}*e1KuJ-3plj6zd4NrgkmM z?_JrC|tx{niXf7;)u1eX;7I>qXw>n&`x%|0{l-_jK?qS%2 z;7QM@KL0;0;NVwgzvJTh!?+hlPY4F;+qgxur3QV6E~Q?*52O3G!nK8kpPpxp-f~9- zh}ro2ON&#s7aujB&X*3`_4E6!D1)#>$cz7s;n2wK{Ng{L z+^ZzI`D;kiE#p%%lR=*&Ky3T~)Brv|^9=)kZtUlkn_{K^(_Q~R^T?NL3+Ms;6)iHt z>}R)L`T5^1Ms_`7JRpYXlSG-Dr_6rcGo6o%ZmC-3T+dNgYss9FPNK#OpQ{W)t*BpYu^(9pvZ z^%|`iGIXEns@Tw)NC;N-122^ehM6t*bkV<0$B!E=iEe<@z zLJrNx688%@tvRfLbh|9s-K+tL1Tw7Qyen`SFH(k9xm}3@l~$Yn++QRZd`mYsm#hS= z?v!I3SMgc>HK$oG<$ow5Ip8v?A60DM^vdSu8mb&k1;!^7&aI zu07AI2wm>Mk>iH-DV#p3-5py6A=Ur@tqgMe1*Mg2{ZEUuXO7G%MsPgJLVh$E`<8d! zPOE#G)1#7FT0SEgoH!&{#$T@acjw1o|5@315Ustf-F-jD!qnw#)99Gwkq!3e@2i?X z_aDCs;d>;1_L?H9=pgZ#lIc`yzx?QGb_>js^#Eus_{AIH-xn`ie6JL;yblP^Pj|0i z@X5)!!?GVd@?oC^x~c`1{Y$xKv*d{j;`5e0X2Wf+S&M=UZ_dO}JAGvfu>KP6~2|Berpn|N*kU!!;@=vsOsW?MqO-8nH-T3>6 zksOf^WD9hLCFahWGP6G_{x*q4d3+apZp@Q-F^v78-gX|v3EL1wLsjsrM-6vvQ({a> zk!nei8CHqeNlybpk%3f8+4#gkr%PS(&`>R!(P$BxWWsQbmoBxvsT-iiA`(DY#y-uJ zulr)~j8qm$Cn-%bGYvmBS`^tJzMpx&Pk_?U^Rsv@Y7`Pl#3Mli9Yjh!4p04UsJLR* zbCB^pBgQo{E*+ZAHX^5At~yI^%GLfFVYAUkWHZTJ#bcWu9jN#H{yc;?Z>Owl2>Zsc z!~s*CYL*LRmbeapSk>(v#GdPY9tkU+L+I=tXc$A@n6{ESo9PR2T|d(HD)AY&cG@2wBZpbgxpR z&WC<|eLvo`24HVCv}&H_)pUZ?+WsXFKq)bF^Bjv|Ai=A{&QRD17`pq$2m@ei9;k-- zpZT0U-QPC0f7Cra4{^@)Jfw~89i+*~^E>AICPs$~JbL9W_H%z7&co?D5V4jmzwX_h z?r;^N7pdkW@!~7)911g>Ik3o>zs}6-f)_V?%Zw|Rh0vcW!Um!gtz@GWnAHW;RS;o%O^zhD z0a7qu{w#k_XHJ(eCFP5XYOJP#+Q@&)X(a(ti6O6yLR^-ZU z*+PNRJJDf3Nt}&78^(RO!s0Zt$q302_or;J4idHiENc08^X6{()I#)$meeS3RjGy} zl~~6!f_(@Q(bW!Qi?s4lF){NTA=FUNjsz0eNi_-^IPOE@eHX7=%H{)PF7F4#c*Emlp&DTI)ZB@l{?U-K7eWTA)UYAGF~9nVM6cQQj_>gz>imGN5>3i@EMo_>;(Xe?M}nTxS}r+X@J=5ZoxZc6 zJ1sGU2VJ6~1Wi%GGlCU)3(Hrnk`1HLS?b|Knvu4oh#rZJCO1RioW#sJ@veA?wbY=h$1!&TMyFg=e#R*R%%zIi<6=;mkrY!W zzL9?^8b$Kal$RrF(^b$RCHw(rT%VaQfAF(OhJK4cjlM-r;e=;EUclF?@R*;GG?bc6 z81}uE20g6dfzS*W+|%AI&xQo>JyB z-V$BoCS_u2@{u=$^^fQ=TRh~0aT3|Ie{!RFla!{L=WrWkrMRS-C1bO!M78smX+%<v^a>gWmHqTKgf>&@#B&SQmehGT;8bvVHrzzA*yU2hs6C~3XEK9+qnTj00RcGWFLsuO=(sVB)2W_#Yb2R{YMq-kuh&N0_tMvLo^$ z?PzGL*FNO8kPN!E7sNVZZQKgir%Ug}n^4tHLRM76fye+)v-JW!$tBjNoSh<5m*mvV z0ZEEUv_fKDoQ}L{9kBHZ&;AV5+G@+Whc}>i%oR9t+CPb`n=s_KADRxcb81QjWjqID z1-!RN36g4vDMg0iEknFM=Y(NAIM?Si!0agaL_Zg3M_vx0mFFQLtXDAR?!{8kHhgcj zpBM4dREPoYzlz%JI@8!?N8?Vr+@skDPq!~K{0*eKq*AOKa-GB;me0iDd^_86j1Sor zq>1Y;>t36nARnv)qg2J_K#C|1!C_E;;P@f2*YzaFzjKNzyDR3Vvo&Pf^_RQAovf#` z4!*Y0ZOq!oIHs>XEm2xkFt2wQKz!eJBK2Bp&80c9Ue+hJFPrr7$w4rYnchT;WD2d5 zQSF}LOVVc3`j6Cdbyca-w$F@0l|_Rc#s*T(`%VhHW5(j{&S=Hyf5~a5A`8nHW>{}!r+;{!94JJ zYAx;l^$}=fkdZX4yNdJPXBm?ECmBR>AHEwTt#I~sG~H`hm5O;i2=E%r46U(wQc{eg zmg!a~G003EziQf&?etvbzDK1Sd^^UEeA3Fk+8f8b9CJ8k>hH|-zLHA4Tk)!Ve)3iy zyS%*vCZsAmRA7qrvzcHTwb+}e+?_m~Z0H-+FS7%)8WA=gMq3xPvHR@=f zMat^wN#NahyFnFxgJPSb7^%%vEZYf|erO zc^fFudRa#?HpzwALA+v$LnHeFTO0Zev> z!fEc0gRX~zg*{TzJxG{6nt$it$qlJxxE|7SU(9G8FEnd4MD}s41};|Ol+@fLkEY&~ z*%@>KA7y_z41x){OWuwT1iATkj8T|GP-(9&ys|jC<$eYWQb3pC5{&{O9$ibj*Lkiu z{ri|usC)}-OdDMVXRWhm@4C(Hrw%b)GT#x6Z8@9@ov~v5X>obg2MWy|6ax5VP`&lCbDXhu6XMiGLKDX>-oxl-K!{-*`lq*od)SjgBPzD4g$rS4Uc zyfu`I3}<*7t#upL1sSS~Lhm;MVg@mU3b8D0O&4GMj=zZX)txx;#tI~D@%R}ANQ>hAHw#hGyPY zC)Cr9H(j2}N9p?*dfJMyWhnthuSLY)-}F6;kRgdGMY4kgVwiw%&b2pNO4?t@cVz~2 zzPahOUE7Sc3parQWDMs&PpfCWK5v)!n+4(@{r@XfM=y2bzwdm!A?l{vKDX+aq6`27 zN+41(n&cZ5mqgy~7h>|Bd>gL<~^io(;gj2soN$fO06gdVmnZ@+}UVO1*SlqiJz z?DBZ$ztdL_iTL(?5Gs@Bz4-k}@9krU=*3iqmHF3@5np=bqw($7Q)#JRWPbGU=#aEH zj3rd%y6rux+q~gy{Zz0fri3A!ge&u(!_*I}{OV)hc>MChhT#UrxB*E|3rNm3dyPzd z*FmS8EhsKJ!$1wH@1&3sO5Y2XZJMq$!@~YhvGMJJe?B5_!Ho>>5G!KCP}8DvHY`gB z4(3BcQ(pySmXk9wI`cij{Q*B@Lj36Kpr{6!LtIbZw?VFS{=T+igUaIE1UM%jM8)KD zkOEYS6C=d|%YH|r#`J^ur=42fbuYPO2;y4WSAV!22k(h(q!Am+lux0u*oMMCQcdz4 z@2Zl;APY!VtWIRXIZwxi^c3R`uAB?w52}0*l)Sfta{tmC#(OSMxan;#lU%9-gY-bxsmK%f7>i`&uJ)yzYPer2wl1h}p zXhdPZ^j^$?E2-Y!eqQI|p^kSzQbt&-L-igsAN6)rcz@r|>v!h!w%(;}l=WV(EM+O$ zWagEJP-QRA^~RYWdu@Q=m5Pm1k00-+l%e(2`Gv{w>$l zKi0eKKTqu1GaK6$88(Ry>g7WgVhmAd4NUuk=&-9u_Q)4SzE0UsLi_|8h4ZwWHoal( zq}&a@kl-*JM9#Du*Z_&rzWv;OLfam;A78+;AYbxLBr)JX7wu$NqS@%+M44!YG#EXP zJk-^uiYaaqM_(7TDG9|z9DH}gDquRdxUwPfNsT6re+Z8sLmA;Sq2L}UP;esCm^uO7deoD49l3unbDN?N)_QFW*!DFbP`bvC8wj_FrFmxE&-o<}nGZgAva&>|hi=zu>e1E3JZZk4Rt|hgKYrGwLzGDER*4 zstL{A=w3_vYs*m&W}`&O9~|#B_p}VPCygyYatL>3V2nkO=xh~CGI-)9f@HZ%%%{a; zWkJijPeA5JQ_g*gWYTpO^vwcZQ=Kwh++@B;85=iAmj<_V)kxDVt=MqA7%c$XKx_u25lwGm9PBx7`&tZ_W>#`^|<%jh5dfYXVx6iB11g_(Ah~@7G{(gUxYkTnGC3Py)H_t&Ho;r$M%vuD0z4Q9c|5< zk@<60h<2e${o?JdbKS7m2}ST$#TA~8*l_(pvK`;(VOkO;eTUfmDx*8Wn1N1WZ6;x& zi*9D+QLk;g^Wr}x3#(teKhhKF%vgKe6;o?;lQvuGJpX@p)^;m`y?ed*N~h8;{q&K< z!%{-MfCFe|cQc1F%klyH5l*VMxE&vE3i)1Wx9!$aZJH4Q-FOCkeSn_kyky3)yMPEV zV3*I42VV~gQqTJV*6bM}>2yuM1Pw#{TAbY>EzMS)l3V~EGYh}V_3k>QMvu{dqcH@z z$n7*zUpKbnY!A%}HvqhApj%=sI>w7}+Iqnyz-M^Bu9g-7WNA=pH9d>}Pl9W@UeHy|%SNh=?JG$!y9s@QnGZ4%~d`dYI!PP#$|f#&f2P zHVN-^!%nt{xUXMZ>q2uUeDw8dFE8~bdJ=Ds;vfsi21)$**Lwj31lLNaI`KD0nC1G- z3Nr~ac$ys?yx8VT-~6&oBzVu5$2ia#y$2ER&&7BH@z6g}_B6Lf8*`}Hi z8=~{%DUJXPyx?ksK68zWf9I)%{fYElB?)wP|4>jj8{7uELV{r<$R=RAMN{x{-g1S8 z(u=RGrZ?P{Ph2{keyrp*97Ab$j1p3$d}425^0xJ=*yrW4`;@06rX9wu01NrT0kH0A zwd1C@xvUmm0eOvRVHH)_uKZs>(KZ z9Gi0eB!T|n zW!am5+*-2(jq}M`d9qsf*Zb`Hv$|zRm$|7axLlR=1fs&Tys6c=9_Q7~OGK zZplzgB0bDaf^Bv3A#xfTp*q+Y+&YD)E_S7pbF$Q`=2DT}F{sR0Ib!E0CY}!hLrN_`I)IBz#7!xB9jBTUs9c)PkqwD$6 zzd$dM$zsk@`?=)TMf12$@x8Qs0LCE^Xnb&o$jQFQqaTMMh*AK%0dWaiXR^;aV^WSe zaJs&CpY+&0IKyJsAVu%rxjoJAF8he^r_gKVNV8G#MTt+t4#153xb_dOOA%ua!{_{0F zUe9NpinN+<5tA5+^C9>sKT}oevHk{AWMLP)yc6KWw^DCGqpdc{t{Kx^V{F*a)q-}! z`X%9gkptb}-jLDg!YqkpRDxEc*F+W1DJnP7$+}OLaRhwes~}%|-g1Y2ZMYM3eeI7& z-Iv;V^T(=8!hzeKBLe{JL+(l&kw^GNM8c!2r8CK(I11@SEr}wbgkp!Rm4u`|KL4I=KaTt*dR z1@tC%;ydIH)lPbJJBjtWnD#0RR!|Zn$RLa?k!*b49>OYX!#>7S7cz-?TAUjz0|-w8 z-2szRdA0G{!fNmVEf((}XE?AIn5Co+iZ*-)pPdwN#a5dpOJ?95i~ga8d5w%sByD~$ zoXY8Iz&Gn-*S15I%C0@$C(hMPy~s+REsOityN)Ou&n=?+JD(@DXJEeiuZ@q#$M%a+ zpQ+fn1lJup-F%Hn;kpJigo#Ccnm@oRZ+7Kmmv)@TnI3(~d1A3WLB_RH-ZOsO@>?N#+fD*FEDm8`i>L7~=PgsW+WDKPdpc8@p9b5muA_`_t@>vj;INsvAv zfWl??>TzTBW=rJfxMIE(mC7bkV>aAE0`Rt9)Hx+RC5eZJafU1Xg{-HW(xD>=flT!t0}Q&y9Jm?ACX z&09UJJLf4Oc)J9J#~)>sF1*BZqJX#=gFe}waD9NEB2y|{Dm3=g5pN%Oo&sZ3REk4R z(unozY4t&YsS#WwP0UN(8RB(}n#7Vz=Gx8pfm1(*D)LoW{fj}_>JA0#|^5OX1k ztKfQy5Gg`uy&@q6oJEvRC`W z2I3R;xzNcR5%$d|$OLcpBUF#b@ z#duIICT>q?XF*~cX^dqES?0k$AGt|)Nf@IV$8ONE1aay9uTKmI4vpEta=h7bpT&4R z7ckV85HCXZ64tws!P+Ls@H?L$R{o&v!G~`{jxXKb_4rs+%r73 zsw63BV=2^a-$<*>o0H4N6BCjF7s+kQz7EN})4BPcn)gNxlaG5xh7pO}3fzLIhe)Ey zMj5=Ew19|q$zsj}Xr8P9VRGR8p5<&p4Hc0d=N@%#cS$hucrN?Krnfhrj%bSA$<8e0Gg5x0HOz447m*o#rRvjx|{0@U)){aUJWq zoe-wW1o3IkX2D7tuCO7$14LtY$uNK6Pil{)FKHVnSPV$FS6MOEFwxo;`M2BjGFCY} z!%LZ8QM|yIU0Eb+UgsPly0TJYEs zGd0lp=Bm3WR4t3Hcdr>kl%ss4NVE7>JHYB%3s?0Wj_W{Ca4x)p@SC2E;218h7|po9 zf%)6Kw_-CMYwO1`xXnWF8`?lR%sh8Q-H$)sKTh|W#ziJ^nj-W{p7;j6X={n)zNPrn zQZ`*}Lk>_<>JC@bTR!fsa{+wpu;G)8$hXo=6n+`vA;F5-+5lAdz0f0|g`5j_GU4+K za9$hT%~o+e+@A0s-d68f-Ud120di6YtMw%U(dDuCGWINvz1nu3%-X@b`(+P)oV9+- zP{#DW&8*4IiT`d*IQ0kZ9gg5$+lS`$tG(GWb!hdpr_F5cNaoqC)zjOzDzkeHiy0lk zUm|v^uKPN&-2ue4GD40`$KF#*l26h@?qys>hYzy-m$L+4d~B){yRyJ{*2lU>H;_359u` zPZznn_K{TeY?OJNRQ$_!9cx(>nUJGt-suz%`*kxdiknxj=5APSsO8pPeMs2mL_TeAkq? zkEA^2tnWR}-j!MR5MEkQoQn#tI9{C#zpYfLGP(ISYk&M-*Zg|$kGPqJ6@cM8!M^Xx zqHIebw0Um5cvhaJNwO;~HM&>s9c6SETX7GVaY)V&L<2C}>XSqXb!+m55K1<)=K`s- z^?2}ePWvTlL1QrJmT$`q)HESSB{(TU67bL!@qm@HVMp~|uNLjzVf8zGD(Qm!agsOu z({9a=+exDrJrvSZPR|znXB?4%x=j?2;~qpe763EtNR#k>6zm~-vgt35lPwQq3NS$N>@#jpMBcMA5UAR)tf z{UzgYZgOwbM;hS*ioHm80rt1;!lm=27MX(=-wxHk0m~0U0^!r=`z;4>fM@dNLyUM) zRM}f+Gg08goZotxN7XG;LN9(O22Q>jc%I-a!y$Rmpj+G^QXV=tMcJ1vfR8t3@Ellr zY_R&lGKKn`rq==Mia}8o(7dvs75a^RUaO1XgC{Xj zwtV{?!5jgB{XL2C!@UhtCJ7c>gt3ZsQ}C~*eMrM$ck$Mrx$MD950^j9_c-IRuXDj* zuicS&-%BGhG#X<6-;Dg_Jn=4L6HzSLb;cLE9-8p$kGN#4&!s7Osk$hfh{FZ18RP|) zMD*@QA~I%_J9HPWU4fDueblV~{k`dBajti7#_SPx7gdDUK^>Oc92{$(c)xZ9ziLOf z41VW%ne+?Ce;!ASUr6d)xS(yVde$z)r>8tPuGefJk)}n9npt9W@8JElS8%LC>8+}g z;H&0<+NFQSsKsoSXu&Q@pD=p8T6LecqMC)LEwmQXzRgJA6WwsHi|USlnf!CEELN9)U-U)yu`pnJX!yIJk2^|o&V8Sy+&R;? zs#Gu6p*u>cK&AdE={&$|iLj8C_VVi1)u<~fDl#wVa2T8We)&^^zj}TPT}IFSRuW<(zW~>&}rhn z^V4bBgF&YmYJL+Hp%8$AqBUsWo`G_II?b45{(%^Y%cVPbjSG0MkL5#i+w8KgLWykI zoAHZ^Xd8ieeH+jQfeTna#PalV_uuLC&Ic~up4Vj9j#&bMowv?!oeI^=enMlOLzR6S zrLt*HrMQKUoS&%&#!ctfm(Bb)W1wJVpv@>fZ6m|Ynu@*Vfh~b)_l4g)dJhBeP~puJ zI`f}g2nqwHa1>G6WuU1TKSEB^ddviP^#NGU?J;vkv&)7SFE1?(=eydUIwsj%@f)Dy z)d0)I>XQ85T_20cW*XP#V*yf~oE*-h_L6NDU-Tnszn;rFv?KA@#H0B7eVeOR%?Z-> zCT94&Xsmf-n2*_*iY2C(0f(g=J)d`0dn-3^$CNiStN9mmGs=6?Ca`zwk0CaYnw1{~K17@pe>BQqHP_;_QfPzIKl(EJnKoFaeQ^00*F8#Jp_()nFZY#s zOy*F6AQ4bn)Y+*(&cV<_t1hLG5|H9{nBK;7I$XzadRzEXf9`!stU7tnDS0^X0}*v? zZ!|^Zzgy!RIPSb(UcdWYs@QQwLB_a$I3%i?+Ia=s6$AA$!4Q!6)LmlN)HhS^pByb& zzzJ`z9|G^LAi<-IDXj#snQ)>cF56GqoW$F$x;ItrcC_Ijc6^XrJ>{ShB3dZ0w1GuY zJgFmrfX=ZpGfy89Cj-_$L zT+b<&% z9Q|42jp-KMiURPFVqT`1sn~Ga_s59%(EH5SPf`IOA3}(DGDMH7GID&RLA<@iu+YL) zh13!~+q9pvz(REa7ws$u`sbaqc=Yz4jM)@39yok8jst$#LA4AJ?_S<_r5W6xew9*T z`c@6U1K{N}o+RgVr#n-@zLz0G%iD_&2I#ee+R&_3G{jNNUE+)bOH59=zS%IzpLS8~ zs*A*fr>~fvG1-xb3}g6(vCWeI{i0L2L>_6tv7AlM0r}lgZ1Cx9m|BW)BZ5s|Hf9#4C1$y2b+LRUq*ag zI~KsotEA{t)GJc|R5Z>(t=3K;QpDGzJ!wBv9`o^)fnuQ=ScCTCs`mRPsq9bP?6q@0 zVwvyWNLA@5*OMhP_d!>g7HKTVUu+fpFeKWQFwbH!Mg-QVFplZmsZ~~2FQqmdh!yED zD5)REq|f$I!!g-_c{0Uto%!i2v!w<~3G-dXJp?RZLG=$bI|}!jBChJii;PJLRTci} zD)|lWKbGA{=kg~fNs*-4ziY*jcwj~D6V>EhCS%?X?+%Ad-hF5G#^_ssXdaoja^k|u zRDTbQ@@_|w5qdvb9&Rp{-x=ORQ$4q3-KTq7Zt^!1Bgoh&3~zdczw~A?>hD5~Q)+SJ ztPsvnJ*pZIy-ct-3|GM__#~+ElJYCsuk67ZrrE*{@7WhN@T29eDkZDfOODYN3buhG zpl1+eCVT^W->?h4Eb4tsa(OPewZ!7yjjAZr{Wr7S>KEW}+>^5`cmSvWs2yJ7b7qA~ z&}8QS7UY^XHCx39JW5cWN5Z|X+eZ9a415-1NU|(A2P&B6Yzjq)~|RS_t2w!@wZsp zz}J6diP$XKCA3_7qZvtsjh;^0{QF8jekIVnE-TP1b*2dhEgI{Na1@$ zNug0<5HNw%t@C^}S*V?HGoKsBz+F5986*p3xg(O5ZPd8bEowhHx`kL5$hm zb(Ls|3mM>D@Tc*${b$_-n4IyiZ?=l3HcS!#q0D#&=psKUWG^*4NIitMsgBxdKb-Vc zDcQBwI$&)+xj51hBBL&uD38H}dzJEILtQZk6lKf%f@m7DiN?;hYdfMBjkM?{PDFoZ zWuVhxBQpY6sb(n1V5^baTH|c-bgtcxgWivGGQN^X3}7<}3BX&QH9*Q1b|GL0?lF%r z;tSkA9|kI`&s390Bd{&mr}W+QFU=1)rwl@+Nd*006=*Ew(WkZ&S!t{|uyF6s)S*9I z-95DaCry#ZrCObj22JIj)}{nmh>BnVUunEIE_qZ)x{1A*!q^IIVIs@6F{L6^axXnD z0sNW=pfd2;G$8X=)LyEWbQZk#z%w}8)&$CZ|GqY)h&eRlI; z`&PdUFqrkeby(xB@yzGo#;fr-<~8cEEzaxyzNz-W4-2v7F^h2(z4NEkkoPnc^j^5i zxaMZUO2g>aO#NNA{cIYWvD9T?VjQz(Uem0SMvoF@oMDw^Ft_%xYT)#9GF3z-=;bXd4iqfiqgPE;(4U_28ymh9sFi!SVW2*)x_a0DYhUL4K zH-)!z_vB1v2g6o)r+A;6G!$U9=xn!C+ISB+8jGTXDg3WPhSDMc+cOFPc4~$=NZ9ZG z4SoGsuxHu21yDtenqf(7Ugy@lx7&xDHVE<0GQwNR1%TP|)nQktp_aF(mrJ|_^amr0r5PVe*XC_h=(b|VL@ z__%2~XCL6F$^u!9l&#DwEB;Ng|I-3a*l(p`TIQ>-63iTSSZXY$Eh90@|MoUOaQCaP zHZvoX|C;277LHs+maPzFmPJM5iUV|DnNxe}32n<^8qjfV0Bs)D#$K&b%FMz!4>|EqW$7yB&XayH}L zkvzxU9S-9o(l4Z!0LH9_7awzfV=RlVAFW)R(e!bQCuJ46rrr@F1^kbZPWwCV-ZF!! z?`Bw&Hav<@+;d1I7qpYbn5^f$C*iz62e(GB;elZmC}y^77Gb8fe#7bHHhMoEi^WjG zc!OA6_K|@vb8UDFX%aBo+DTKo5DyBR$a`CbZj>#GCHeF~ zV>xeaRCZjOY9q?uBw0 zP`Z)s2c{3mkz@7@=K(w4gHLa0e7Du+WaAC;)Y_e1eh6|;7;%)9k_^;zXh`@~ho^^?I4RamR{t26m|8C$nqY||j?u=}|#9efh zlX5c<*4fj^Hc)20P1qmNNZE+(co2fo7QSTh`>&C@oDV)8a*%AvSsB)bPb98L zagwSNb5#qfg?*IL?u$&}8>#vK(I{UsF?SJ|OTi=~pP81Wil{jThpDZQY^xZ+s~?ID zvyQH+C*mQfjKsxD%_6ICW@zzA({@S=C=TDObuk4A~Hh{d01Cf8I4NV)oi&|_tqZrzlDB1L5xqRgtR`b zo~y(_{&Ja@#caw(;+lw(gSH?sPp##?jT6AKrlM%b;nRjr7xssxq>gr(HM%k!N<2HZe!~2US z0>g(HVH6S715dcXw#=N@fgr%K5DqK39}~9pa9}*I?(!p?>BhySmie*lh$9$Ugk9!M z)YI)W=fad{kB5U7A9UO1{5YqP4@_z6k;*Q3cj0vr$;blQyBQdtNS+>h3THdXBfLIF z>^F~slptexvrP*pVlQsCYux=42Jx9FqZ+nPp&v{{rpE$DJY1P*4o&qfoyC8=H7<-y z`Us*4fhC3nS8m&Y-RKYg#fcK~?8JEdYhlm$oXxZ&h2&&@`>3V3Jxkc92#Cj@%s|68 z`SmM${>6(Y<1|D{+Ul`3)p(drBY)p#)vCP#VuAh&NnD@%)>(STT--udf4|vQta^t< z{ToBM#s6+U$eI=TQg&JcgTuVrWnYm^KW zE{3(kO}tlbmhn0q0-d2yMe9N1u#pYv2>e3_`js8>4IgqbBHBAjH>>vmyc4*OZzZvY zURu`w3My`klm=(ew!b?}81lwUyB^Ou8cVyyjq^Qz(VxKn8X#hbF&@z0(HcG2>gNgs z>{>=xKvl1{&;-GWCNlZO@4lVI4t4;T3y&HGFFXJq$MwE;$vfHSe40mYNXZaB(sy`f z=MBF1E0629Z9F2mz3dWhBVRbg++Ao=9lC(0JKf;kuV4xPnPeHV6k+bpsiYC~Hpb`B_iZlu-q zLBdBVmv8yx+!EX>9d`WRvoMpNX)VY=*Kfkd%i&k8MyYGvzuD(w_?#(Em=7AJNG*HB zf6m-GU+BD#bCymm=+@bkU^c6)acj*ui>~@($`fHUD~Mw?rSH(NRw?jrWF*|O2t5Il z@+3+yRhHLAH$M>tOi?_Sz7a(_RfPO*`!5F9p|~3$s52|RfIY=HORg~k?DaWz&uiC@ zNNWE7h_{wJ)n2-)OFs7@W&Moy2$G$Ul!Qagu>1S6CQ0I&IuH9r!4vxN#24Zr>gs{-`rE zglF>s{-J@-!L2PJj(1UNu9zN@?fZ^i{s|B;$I_0x>u+8=@pMKpDc%!)zByNDRhsFl z`OZ|f(Q6*9p&xewJGUo8U3D9&A!CaCc=W06jn-6!W)h+8&@HcplZ(SpaGZfF=ytl$ zj7yMcCjRd4$I+|E!ZgE1SI#QAQo6n$!;{{;^QJ5ZI|}7SaW++pbu3=5+Ff;9;+jtc zaNwJbQt#6WEfD$U({rWCW0Rs%DY0zj%s5;L8^<=tJ*1>)jtNo`Y4pkID)@|SFlo&L zQB&x{_2mDE4znL>BEGL<6~hm=mAU|(3Oj~XrIi4bpLa5!vp zDsxzox^!YE5V)kK^jtL(xZHfJ)$ABViBCl)#BH4NzKg(FFtp5I=LB6pB!WSSCWLRh z`)x;#9kXx$h;)8($5Mk!9|)eidkBPWVr-`!{&@F1m!`nq-~~LLD6F1XucbDucKQ%X z_a*r5e1-0DNbqZA<_+!^>xh&Kqv>s|<0^gsM^S7K!)zl4S~I$?Wf{p{wF)YL$TT_p?~UnL-;}4y})Lnu>;_uVF9T84ZzC+2?GgoIXgncyTXK>-tyZx zkO0Y*N>hkeq6MR(>pCrV3kRx=x``Ua<@?P#mBT`eRBhp~#;%>#lDx$0ZgI)Q_rw#x z&lyHMYED3U_WfUO4x)zrdaE+my)hKsZUz<=l4_oyW=NXS0|SoTkru^gyL$e-G+4ZHCMfehNt90)PNg(Lo>_81j_z zPxj9w2)EL`PuA_WeSg&5K8__BYF~5ud?$p`li`#m^!10x{T`$s(`F?YJ8$9Px?T7n z%-9Z)dhgXgdWe98;f<-hVFV>?HxpC9R?BF<{_HSGyi-+4=zC5ooXPnMK)MnUAM_A( znr^1o$yj{n18yIN-{jqZ*VQ@)ebphDi~ex zL+|{ln#x9+V?Xz=jFj6H*Y#lLSzoa(ecjm(YU&%e?Z0nqnbLB$xcEGuhIf1F@3^L} z@yN%G3jgZ#2(#QN30*htao{Y^?9`$#W1eD=yc&z zdz78@Xf8vo>)LkuT+F{VjlJU#CkOCl#Z&Ra;dAS$KCT5b2f@SZs!8WdJVv*E_WJ)W z!W=Azyk_6kS6g-L+$ae*y|1)*X#8vABxatp!lry?rd6}&>~&GFXEjw6(<1Z}Xtpp8 zyWJFdfJoU3?YJfEtWjBUmKMiEkSY?y+UaQS63}5Zbai9ZSWmxMbZ1(Uy}D3UDw$B| zQoLGt!t<$`$~|4osQ(|^p+bgX(FMC=T4tH(J#bPFrw`TZ2k(p-Iq6^g{a-C;9i~ih zR@@6*dgNRFFzU*uuVX!sVd4S1h09_?Y(Jd4N@5`H2$lE0B!uQhc5<8Q5_tg!$;WTNm@Aw7oetxgg;jXJ~?d937}hM^XYRu zhs4CuD3t$45NI2sx52If9+5M=ep4HzIq|t7b?l0Ys(E`^&RO%86(~q}LO{&;4&;I? ztKe!v7=3Kd0Io9-azLPqs5`f7i~654gLBG@0iL@|N8cjvl}@~W*K?DH30Y=b!bGNI zhL`QH5BCnd$%h0lk|9=nh9YDmB}G(1=OYo8ll=O71%a<;UZjXC0qV#Rh39e}R*_!;hHs)zkxkekn?Vos+gXkQxweJ97tM&Rf-06km1C=Ii<()bVZ2WKbuY77eoXMD~!J6c6j;U`5lHoc*he$I^1 z;FnG2!>SO~HYo+g?PHbrOGZd0dycc6QQh1RfErDnljZ=`(do+o_%pba-j_y=m%l%B zBrRTZ0fohwUgx_b=?mdvDH=?gBp+>9(zCVED^D#bWhdk??dHd_r{N*k5b?SJi?}i6 z>Cip?8dP|LZGhpIN33xB22#iyz(q9^cvCkWi6xL(2VdtJpgbg;IQ&d932hh6P3!?a_6`JmvI=_Rq}s=TI=Wk!*>KYu_P>rkL@ za@#;S>&`IH2N|g*ZH0P;3m86ZWzIii37~WQxhOsB}1~U&WvR&V5^U8XLm8dm0nT zb9Xv6tYVApJeG)p%FwBbP5%shv#y&8d)s0|{BHOAYr-Z9Z@2_WEUO_9Pq$xBD9`!* zO!fi*+Aq5SnKn1TUvk;2*<5H+=mk8nMn%@~htOY>k%RWkUlP+aj9N!^qx2|hn(!6m z>}O8H!(Hdx4w@dx>i%)SSETlAQn$=uOv-xL@jyzD+y_3(g?9`dRiBt(j!x;8qjhJz zS`Pitd9{%e;aG=jx-O|(G}{WV-oM@7S}5o0kjJ06&!1L)b@WFHK zxu(c!?9&;rwARahqzf@j?1lgl2t8MS0O98mP7agTRZ@VfM=5cp7i=ykt|gu&*+M*a zSmot1R)SA>cOTc(+x2eWTO7mVz;plRYAFsjHxU(T0b^_RR`S#!igE9^c&3AzOfe(* z4Hj+^u_1i3zhX0d>?GL}bB9c{gnO3MVmUu<_v0F3o>=LS6lz%IT3VDMPF6iIA1L$x zf~#Zgp}d(!)A_J>D1{DuUN^~elQs*dX`6Yeyei4Hx{41$PL4ve2jSTDQ3BW9#!E^@ zS4l4L^nFKf#n`fefDqg^fQ5*NV<4Ju>%sS5T0N4adXZR>C|MJFI`??{aTawNPvQ#e=o?htKIENQgUNUvGRukSypk= zKH2Ra`8^3>G@*pwEovG~4GJ=>nE*?mS3$)_SWI9q7n>P%S9K5ePgACyVcPCPUJIF^ zH4k%}y%6Si&wykJ+A|r4Mc z%_zDS9`U=r^5CY)EmvcRet5%tq(t!v_uM)jQpUTFv>w+!Wz|F0C>Zx!MsJz5(Gz9% zL_?AiT+2=%5P$-?YADT8c3c(CQhy(|)#;_FOd|z-Yj4&pYIg)M*tr^65v2pcEfbq3 zE^~YtR@v{0taOQ%tK_^xAgE!u<&~*!veaVrB49r4+cRDUmN-7G2k;Ai(w4hDyAJkH zz|oDqk>W-PJgEKAy5_eYPz1iMoIoWIfb-{TwP*ofAmbV_0M~UWYU=yX|EsvfOkOLT zve$+uZ5LJyT5bwl%sHVdvBDw7cT?t4M)UB^n_sV+p2t=g%mN4V#v{`LcTM*kAO#1Y z;xPIvl8vTcr};j?#3lV|Rnqc4InBnNvI9L%7-cMd3_b%IqP_#P6E@tZlWuosQ<=UG z@V1@_tDs3SLRcU+@KQ8~kUOx;@I4>g`v(4JpMbAmg$Y_C`U%@ao5Mz6R6Lf7c0GDh zZ!bfH+sQe<>e(-Z+Akl`qX6z@8^HH}X)tkrf6*LKW1)Q%#y0ru`@!85dd!S2g8SCK){n7Cn+#-27Gu4O*_uI&dQf$>W zOUtlwuEwljf288f*>_Oc-??xv5pdsPPrZXr&0nNf{eE@eeZy}LK*`$ePOcI+wuey) za(1jDIp;XD(HMy~jH$NdsVq-GFp0t_Fl?lb^eN~BqW_-Y{X5UmlpyzbP zS$jTXB@UiB2V5*Hm)~b|%Ir}bJN+ebt&n@IC#xd*zq;c3Jt(tkm2FC#2_C_p z!4>ZE-EZ)e>5?6@1gMyqK|#=3M*gn*mYhLwEXl*y>S0p4+yLk4V2KXJnevx-DTd3D zxLe&@0!UmJiSnpi(rHc>m48t}AriszZVQyrg8#1j@N@EvcV4HCyh_}2#+da9Z*bjf z8w58T?Zy_79on^VH{XA#1>BdY6{-h}h09KEU}NsfE0k`g_PFypG8DeTE>_9$x~tko zjDNoa&al63%_k+I=lTbpR0h|`(DCUe(u2_xvBg#Exk|>y!(aJgdE-CIKaI)@4D}|W z!AN;NQv)e*YQ5v_(4!PPADo&wXQJlE|7vg}{|3@@A=eHPX~NsB^&q6=JWDuWl)WQC z2pOU1!m+j`Afe$e2|WX4=OD78MBUQML?nmsFD$v%eF5xO?sl@Sh~N&>PNNfEJ8epY zcnzqAr6oUg$;zlcMrW|pIyMGvpm3fpr7Pp)@^@BZwkP1@j%AVam0i<{Si{|!Z>SNs zDg4nGouT)hW(W%F7Z)uOEsrf1{mjnx5( z_`bv=@`TNW@U6Z9{UYwLhm;akgKVH~%-AP_Wp*GWBoCQsb-ef8LAOGf!AVq=aNI(Q_V+ zYK|W63MTE(WWHsEr!@3A_hyW!&T$|!yt{rvcHG63IG~fSd#I(Ln-27BVnc@pnF)vo z{Vo7FXDXj4pp0J3H&u@dGD#^@$!q^Wdl}=}vas850@U{KU#`*%e+Qz{d;iD(Ab@X* zU+%lL0NKfHO|sMbz_q@(_J9V%C%*f2Hvj6J%r1A8)l(98;_DUj?&Zi@z1@88pKYM> z3+{EOG->!$=>i2|(=xLA6q>K@c0o66%#JI=|HIEZ`;_ZQ6P>T^a%-#K~~c zaCs|P9*WyzPkD3;g85KmPd%%QOxY0WtX(S_Lp-NQT(3n{8YKeGFwvhMga{Yn+{{|ma8l|3H`AWTVVlySX|a~yyruF13{NiM4Wisy^qx^^(k z9{Qm~&v`@=#mzfpJMEv3DeLjJ@jqPfxa4bnz@=i7zTX;ym#FjH0ZnoY=wg-m7)!Gs z&I!Y3~iyK9>qI|c*s_X`XyFzoPj4}@%5SdWq(XsdtOc|uJ6RJs;a6`1qk`p zkHKm58K4%U?Cxr#OdM4_-_VXbcowtY2oO#@0O@eegZhIC?Yoie=``P|6_eaY0|koP zQktsi73@eW4_c<(8)&Gj*2GJNd!NjQrG zbVZkBs>Xp{P-l}17fZ=4eix%NytBsIr?ub`WtK356Dg}SPK@;vGN#uxEJZkIrqw9} zWens}nW-!orv8AGXXNP1$9`dw*-yy-T3FNE$gurQw{|lKB08<}Eq<8ytrI018GnG{ ztT{q0ffFxr0&Ug;G7FaWd7D`n1x!ZPPX1vWT{px3uR$DhOZ)FvQFOM?OJ9dAZvF2{{XuQcBjTlT!~p`8wP3gOae^&_tvnd`Q} zl3m^YiZ_ZJxsrKfOyUj+z<*i_-Vf7v4dv@qF?hi-_7`7q#}Rkdw99Ht{!dEH2_Be_ z!?{{X_)hJzQprnN(j%GZ(AuiCl}nIV7zYdN{Jfm`H4BzV4-DE*@;Pn51SG^A5**a6 z=rIP=D8FR}e$!agEexxIVExjj`Jr54q(V=nseHm>u|9OI#reLt7b!N>IugI!8p{bO z`58veO#;Z6odCasGoGNM)JVJo=R>hHff@_T8Y}uE<)icCqv0n%>+m{NQ`Jf`@wM zPvCRd!E+K;!DhLdYi~Sk%`S_OxM1nw7*lXcbQXM_zti6HGI7HR9|PR&8)}e~@F)ppaQkEd8uBN>` z854KVw8QL|=04Ws$!9nlX5@v78K{$*<}Ch{ilK_ffoqb#AYz5=Fv)Er)rD(NaAR(m z_i7*`f!!>aJM6LV3Uax}zzu8RvERY%b!HK5KZrY)E&um4PnAs_#Sx^a zl*sxYfX{57EShcCq)zoY*Zy164lZ3xo~!dG-1RbK3NFBXz^G=%HpuIomO;p27n3<|)e zYOm%+r9fjn6ww29m~L)lsW#UM3xLb$<7L9sMe~ha?Ov>|{mB6La)j@7K=Fyo<=sRJ z!Qz2epY8%->i4D_!2@6+d?*Ao98k5}`8vG<93D>q1Z>N2;l4hP`#udBM%S;R-&Ed$ zGWA*rHfJF6bu)uZaWOJr_r8ZD$WrS#Q+N{!;82zAiVRbCOqB_fy)QH zSb7i;(B%t`j@+f{*@M5_Z^G5*Jo9#6=3{Kk6iZ2&}^zY6DWi{=l12;ahq2O*sES*oOOFRcYZ# zp>`7)eTu!GSp_2d;0%s zxi~Ca!D3==^lmf$_)XdSqCKUJ7W=F++r=$`a{+2Z$wSY}!-*4Hb1U40kl7eoX$SAY zi6T(vH$a6vA(N8cMo9u*nYg*&%OS2yJeH7b(EBlJ#s(-Xfq(ev-OM!#u&FXMV%`A> zGLl#GZ0Hymd14A7Mu`~%iJUl)7^OAz()T+GFBx~UPF#-_D#5`(tAU9OX3C_Ir~eql zg-LQLip{p(q&t4-DDaOQ4alUMl&g<6!5JR{-0N+dWh<;E+s+gmX7ASrged@j5l6T% z>d&F1i<_P_xDE}A%8>!sz+?Lcl(igRHsTtRhp5mdjg$(;NJ8U>lf#cA6+4}*t9w8y zGe_%<5OsV7TfHd6aGU2V4p->5;uRQ)dj;kuYyW{5cUYYNkZ(?y?bpxV-c8Ram|&V@ zQuY1%jPM;G!C=bvu>IQx743wExzcK@CoS1zFGey4ZG2OTs-pF(wA4b(>O#Ef-4=R}ZYkw;}z|CUmuvEtxE zW{7HRKh)K(n?2p$WU&(=@1a(54Thiwph3y#+juXOGAX9&n=;oumY~c@WPG5L#C;P` z+@9u+P07i)bwDz{GH$e!X&t8o!X+3P{+$KuExw@j`_7-_0S7(@i${&AKB6!BLk4qH z_C7&7f?n%m4BZ0+bHI_)$K6i{WZK7~e$pYWS2>5MEi}*}>W!9CT=56DrU1=mOTx_@ z5xH^w#(2)7J^;qh!ar|;+)pB=y^Y(7|8AOsDZ8qT4XY%W=R%?+gTykltNV=DWw_|c zk05eV&0|7JIEcvgTBG`_@F;zcY;u@py-AW0cwmdz&EV~Ce(_&AjL|TjhhdEgQyi8! z-PZ|iA8=mRT13-dkUocIlGm5TEJ*G`g|oCdBHck{bVKO z6egP_(&iM-Wz}Rysv{w5e<>SCC(U#w)|YxPOE$ z)vM8X<;ibil**0RWmi42wf|@}9x2#$&fx7F78Jn2r|5y>ZG+f0Sd{M6;XKDOfB7!N zf+CTso3*^KsY;9Q8?~ZRx)5dW6_lUTuGCpXBBYEsQp!Ijv*Bk}faCoPHVPE{jOHF&h( zO@N+28uK5PkZY1<5|tT;v^a6vjs*$=jOiG_XW`-9(vw z;8bWAKm;{s34OdElffIvh`eM}>!9vy2b z`DCc0RW#u6?+0&e!2E$ptEnaLnPA3HQyEA#bDaPJ@ypMerO(Flh5UI78f?&JK2rJD zFXwQA3nUB8Tb(;FwommJ!w(2xn&5$Qn5Mz#Jag1CESh$j=R=`58_5of!E}>^b5G+D|?wA@Qu%K8_XFrhH46d(J5F zcx!uYKL*ZokPhqD#Gh6#UqunC8qM?!R`$K2wNiP1gZyOp&lvA?;#0)LsH|R5NEvp4 zM$wCh)&sy}5|H-fs;vMO^3Vz7HkDu4-K{ZL6$uSx5?v`y*s)y|y$xw*=NzzW&>ref z7-Mr<$L)`2BLYTH?1#m7F;@Uhd!>gy4R_G^Do+)dqZ&X_bc*956-2Q|ag%s}UiJk~ zDxB=Qa;9{U(h)9|5U%*yoaIuh=-~s-Y^f3YEsb`F;!RPWI6+EI$UifqzdvHMYHS5> zTRH&n>wmq~1|3xKf>*0isKH)N380EpmL9!(ur_7n5AjT$Y_JpCJnMkbQ_$6*F~rl! z+*2%|SdoCbF=3+=lnolFTz7X%9fOUV@je2R&|zkYyJ6fI+y5bdHbQpB2NjWF9MItR z4K(A#H2i>#ko({Kn@OX1d8z4WE*8JA#=GA=#ZcvH5q0(l;4e!rGEAE3Au0n4HPZze zfV#(@D5VN$+j!C4@(bMbR$7dS-5At4(#C!;3_O7(8Ae=2CKh6URiei_r602kW|B#D$cp%jC{cYFxE+dBZ)(c zjj}>i%@YDdKxG|sP0)8q0Z=N<&Udxr zIlW9fC~qnsa^hWd2JLzAjrA|UUIl*5PYP=i^Ty(ew8GcgRd{EhyvgDZD~;oy=go%k{e32@KtK=e~m*T!Wu<+3{A@9Q+;6i&}LbV|ALubw^9$w9?S( ztRTATI~X{Wqj=x7HlzHr2XOoEOl~aMRkG+*G6df5jxE!Ma@zkKMkB#01JHm$PkI#X z=*z{6;NF}XR`%ZB17y?jk9C^SHVucFRClbnt_DnVWyW!Q@oT8r2>9>&KT(R$1vC{d z1`)8$EZL8SB+J86QuV)XekUxxqKpjtH$qPdl$c-h?WK=8Oy|%Hi~l(upiYSpoRKGd zi250J)lEtVhL{)!T0p>oNnc-D@IlBG-b{DLZP}*o$^-fSKE5<@=qOl;16YK214Hch z0|8*2DQBKKx%sI;1DJL=CiKI*D0Ru2H#Vwk9M_mqh(=~+{4K_^^KFK3<2kM9fKI`{ zi2_a8`?B};A$v-3bxvt4!tu1VO#~D?FXiG`{vx|#m&#}dDrEV#^F>%TxlYOVX~KOoy;tzBEIXSyj$$|4w#E%+9dZha zuFzB-5!W8#NyeHvPVSaVFty^Pa9iP8tYH5j3yC)c8hV?s%Q_St8Pl-3K30j7$i1)F ze;#KAA_#6HDXO|49~Sn$7^>iGajCT!V{bED@@T(`j;KnC z+J9oeTy{oUKdfIYT8@(fG^}qnNB**~8u_K;?Wt%DSE zfK{{c0#2I;UY`qr!VW&tPomuD184Ad5q`u{jiLbCd%$S#V6tB}1) zg{(^U%of*nuYF0VWQ%N>WnJ?c*B)8f;@W#$u5r26b;s}Y$M1ia`#8?|ocH_ne!ZVB z(a!X9Zf@>&F|N8&yZ%Ne(eU(1N7}vvhG}4fD|6B3HK?w4At6o^X78ywx#<8vHR=A4 ziIHSy*55N1tp)_L@{KQY@=&UbIzVfPlsE6->|1P=Q5sndULJx~GcYwYk<%N+jcCxAnE zzVyS_rf2-@+ab1myDTQL4ae9kfCu3*E48uZDXY&IyB9ErEfHUISF_L_b`A5MQXL$I zJpO4U(2u7nj*A&O8qR-c)8uz_WbUkPH!D@75up&nSvZwnC+p24zCD;0*ttGwt2VYv z0II6E`PH|^O1d;H1M0W=2N_c0HydniQj;Iet9vAb>i!;S`j={EykDvm4 z2Dmxq2k86@^pLg^4@>C6*DhaQP*2H|{B#~U*m*O%@e*lKzZLMC`xt7ir5>V%{I#Jd zMC{#vVO&cG{7h;>Zghy7D^CDaWNvhG+#uiyxclVAefC3n-2^Yk?*K5D;_~I}ym6W| zsWF1O<3{|&Sf9FPqjmWZKl^!RQmeuX$hN!e-6y{rT@k}+nNnQ)bQ_PSUMJkiYw4;s zljt?FPuS;4V8~Aryqm@}kDecAeH>kr#r3#$Sz&4^_Z6E#z#XHj2h}{Ysdo4N6Jf45 zHz*13NZWWz9Z2=!&8`H!4>kDZ(~R4Ce@h3#K1V!Md0^daA99^~+jKef&#Ur6go8Ze z8}@tKGHZ2|e6r>!S8Nm8#oA4Mnn}sHR0sKIlmk;wjqm9X zubAW8J8uPQQVW-;p>M7>YRJOhRjGDj?Y}2m$pL;49nKBu$h(;g>P>I=1=8$gNGUn8 zx?=!pG7$%qg)cP~5`<>%VX}IhI-fFWNcG>g$@u!i4j}yh`-oJ;GolrHUKWEtpxyxK zyIAgoXCvzo1yVT+^-*8_B4)q)Afw~F4L<*V5|M96@gtdv**jU=^Kq^5=FyT-iCBXJ znfHW5HI$I2aN3hy6ksp)(uA`A9rT+QYyZ1%_Yzd3%x2Bh${B~Gq<+)5v{|J)x`aLY zZRPR-9u01DXY2>&qy^^dpA5!+r^?QgH%){5AqI|9E!o3Fva6NS znr6(%fk;URft{t-hR>h*1KJ7mApDif)O1b?WuyWoKbyw(LzeVvOB1#A-;~(zbh{!C z-{^A;&Pm<+wS6Y6@8rm^C#f(R|83uUqlYIzOQh>CFA4ZM&eH^UU~_N#8+^tLXt#1s z7GdNMR7^4|NV_K&d&s?k++FU*)stDD3+{t`5#(j#wRr%lO%H@LF--vLn1QDKZ8zZ1yQE007>ip zxS>m-Zs3ZIKOQaUvmbQ2H96}xDOxvQn(o%DExiayFP<}pVQhHEPi93$bS;Gt8Ld*# zLZQQnkco@kE}D#11@Y^4S3cJk=7QN|5k(yq+m)iT_im-v#fNHAfZCWbF%HQ5JLSB0 zKW%c=MeeTb%693heg4Dt&V5Cc7pbWxLlr%rnbNzQGXD+i-}r7~K(2S2vK=BsbyyV1 za{A_)?yd6qg4MY_?+Vei`?Rji+qt5;d=uJyWES4pcaKe)0i1Bdv5xjet}1dRd+BuE z&26`(r~GA#kg|l=W@cSc^r8X&5;$3#6|*f51Sh>j7VNGR4PJ-tl-1=E=Q$ec1m?M| z1u>ztdqt{DGnTZxfjLaFYgXLuOC%E{M0@5`J6AWvbbJvdGCEM$${l#nE{7XY)m+Sj z&t*Y^b_VOVCTn)nJ7Ig_o3+wnW=zc7{uN9ToQe(h3UPeddgC!6}riq<8Ww~SvrayprISVRp989FeJ;nEclv##>T=c~E$hly4j z)&J4I<@}uf`3v>-vanUX-esxGI`4o~(@rhyqg$v+uVKX^V3+WVc`!!C`gEL%St+N% z%RY+R0Pre50FlZNb0)D0hu;C@$P>jj*EU+7i7LB+E(7xw=!}zKyMyziXe4;HY90_% z_gD_mn1jv1^rCQjD3^6)y}aYaZe4U~Z_pBDd%*1~v~8?1={sT`!pR-*r_z7W*%H1V zc_QNvSO=RGh(;gK!%2zoZMcTVgs`boDN^qm-+ zn|xJ{2c`3h(_vBw=RS=RLi5kr8HcEOqgIIlTm;YP5TPS(x) zb4J6BOYE3IH_6tQm{T$XP2HM(mOJ*Jq*(|kgb?(F4c;Tok`S{Vkz-;3nP<-rMCx>KA$Q&4k6twgoSNHVf$pWX55TaPjfX451!n|!xNos-^`LB=`d>C! zp7$HR$F6kWV-!!lGcDEVw1N6bO;WB80ZWp}tNdjTxSMt=7$_QI9OKZ+G{mnzKJ&L| zN7kBYXazB(h1N%{4k5w$#TPRRct52D{<<mb;@B2?7A3F@qtu6Pi*cgAqQ+qQq_mA$#GWZ)8 z^=0~}7fI*G(V%4M@s~LhsMt^k&ePvqPW#?06rL^L7}jjLLVJ03o|;9uLh;^C0oPCf z&dkgTuGw?`dt_j1K4n!ZwW_MwV!~SqyYpN}zS6v(0%qclNw}&_u}r~UPsb6=RadQ6 z#k`oyl$5vGK}(m0e_K9|D9+K~xVLZO^Z2^AkLsdPVo^T!GuFN8%U=YVlly`3+B;K3 z_mlL!qqci)R>&G@p{AP5!kQnwsh)kU(M)A&o2Z6+wPu%f}bL=j2mnM#Xvn#Jv zB8uc_qvL)@2pc2x8xl(DLkq4?c9-OLGCSr#-rb0ahH#}pydxLiEnJBn(1Y6pdn=fsOg^n6EwnsCbtcAS+MHvBa70pH9p5)E2 zNXt5knOYH*!)?~zduVy~q>211cK(}<>KgiZa-h~yDSCc-W8F4>GWgtk{2U@krBs2G zL_`gOb&J@Pn}!~6y2gfo7pwO;tTgJW6(t?s>&_N?{^i9Bwf=DyworTD(AzUzg_P50 zp5g?_1|y2K*_iuLat2$3g)RjnT*-Y?1LL0a@bwEF8zJ6VxJqqn)8T~ zW9i{fuQ8O%Cf~-KpMP<)@flL*8OPYzugoa3%pzgAOyHN((k|5{CeL;}+vJzuL0%zs5@ZeQMJT08bEnH!CcUSCOiOc_kxiZOM4E2x|xo)g!BICH=Z2jj<0 zlF+v~X&!OY`pr+nNV67#RNU%L(07o{>ojqTp;1n8wdHGC6U;dW6?)b#1CYS(haQO! z>^_W#sc7C#VfYTliMSqOI`f{?IP)pDxKD<|_njl1 z{GmjndqFAiU7=Pf&)b{p2V-}`Sr})9=H&CBJ~nFh*G97haXw?HGC3Ti*6eJe3!}Q0K`Ywu=k0{G!H;6+X`Qzv0#BD}$HxS6 z12OKoYMgcVVmr8huEK>Axh*uF7@6AEEnk<+oQ?d?;#C6UmlU{woMb9E)WNjIZT2}& za1IyZh`XBMsA4Mf^!!d8}Oiav|_Uxg{E-Ae5RWSg*4V(xz z)xUFle!lR6M$H*F+%C9q;v1J_VPQ$TwO=8H{-kCB?*SP9-JEM|c3DAj?W?0|JY#2F zGrbn3ax#Hg^$UdLI>)+ssQy&~Se$%IMqR&6bnC>hzcK5nH)K%86F9rB;)>zpvZSj0K^j(=i z6>E+Ead9qNI+H=U+3U&h-z-BEDL;fgZy1fof{2aRW_LUaduBmh=y%Pn&^tI1x_p;! zN-Al^&1Mr}_i%_>Fieq`Z#PEuVy!79j9ido9upnC!Kdde4o;?@oT&ld{gW;)7G(Xj zMtSDWuCu|6v(sW?q6yO8r$Rt;QAzXvTEMPbv?F|t)@`q;M(-h1#|eHgRVZ4@1Y0jg z$?O<7uc&FycrBJ=!=$8HoX3ZkO8aN#`t^l1d3ptSmIS$pZh?Vic-~UXwyT}%m7N6X zj4Wm0px6_Hl+Vis!y<6G5jNL-M~)bLf=QrJx;6N{ojO>7=nKa4E10>cld8p)tP**? z{^w3{cz$ODi*q`YKvhuNgRD3a+Mi_!2c6xqYm@{vE{|u%j?HTcn%<;yw##hW9rU0v zYBnPFJYP|ZB{04Rv&08H&KBLc5wgB3qCaqDsT{FPwtaR`zeRkycT}P3#ZM7 zhUP&9S-vZk;%5vri485AZM5Irw+H@DH<~3SU(Bo+ zxbV3I)1F_1`x||NJ4v`~U=vjIJR`@syg`Spz&tE!^%9K7@DFwz})4q1mq} zu@)I8&;t-Ll2i7qD9iJ`6ZAk=X1VLoq&7;d(dA1(Uw6uj{Su#v*J>#w%`_gD-g-<` zOu%dWBflJ4Htm^52$|)NEH$=$38*cjO3lMLuVGPyN+dm~{x%U$FoJDVKcfF*)+S}2 z*%fV%x0Zw&<#{xOh#)*IE6ODe%HoOCS2Cb!TBV^*zY>$K#pFN z%pRBDOXF|yZ*5tAch~f6Z8?Ho>enaw<3=Nol4O$QSEo&?{mq=cXyp=`HixsbD~uc5 z=khm`#n_N!u4KH!AvFDVcYIjf~vS)f8qUClZ5u&$838=nMpykV2Qz>3qn8^(d8$Zz5 zB5@CTJkUxQ@SoqYgi8!7=5hIPlp}ru=qa{DRk~PA@Z(>WjPn)4BC3 zB3b-XLA)1JQYQqRA@x_kfM51pvR&mMAj|W1EK=d{GQtjduytdOnklVTPDwZ7U`%a* z!@@|T%#)T}3n!`;zA*S4N;9o3ClQbENPtN%B_{^9f39BGEO<9QjFnIyc_Q|QWkZb6 zA(m7$2Z#hL>x>HwPm?-zf&&kqp%}nV1@awUt$^`tX72F|M*;hTndkTHLiScYEU%6o zzk^)f%xCVThB%Zw`v#Q7GIxS^0XD@+U27)&6y17XoV)|B)*Lft>(2^mBMmEElnyCf zxOnuCk*yaFqXo9Z_kolfY=rOjkEH1YiICwTMpj)`7iJg$nhIwuZUli}$*RL^j)t^Vl!DAz zB1G1xY$di>SWUc33)fH}aGDGSFPjDP+NGgi{4$EY1CV$JsO#`OCgU)L>D2@t6!);j z=5>p+NA~HBJ#O+4^VZngoTd~6h+y6qO^y(eS()czzU#Id&S9)SrEW>EycV%y9=pX^ zTT>zl;*5RikQ+M9bGTxk<90YPR`|$JV}x@GvdogT)ayJRY04;09KWkQbT>h`-DALy zfUtwcc@@cy^?sSS()VlT$+)6W!Rmdr`0OUdk9^2C>G@&#@Bi8^t+-}Nqgv70ZZ~v2 zA0XLxUd`rC`A$9rHJ^zGt*~T|nM3CaKG!C`FYMEmDiHY?&%0^WnC*q!>G~)=`r}|! zT26s5qH5QsxcXHBhgWz^0CHq)8r(a&3%w5;dE&K=Z4w#ozBK+si_n+RFN=TwY*_iU zsRh^F`gc?LbjttmbC0I1>GqvrN)6E%CGOx5r4ViIBd&R8{PPeg0@_{OF0Fo@u1H2KI`@~_p z(bkvu{&S^Ew>UV*6X#ikJliebm2`qCsxQ?9*#7Mv(s50=F5nY5_8<~G9iz+FJh9Ql zxQM1dQ!J>9{kxIBzuZBvJ4WnhSRc@%-X9Gw_hT*Mzi8 za0785Qb)~?=xslujBr{R!VVQ$w59Jyf4Zdnwh!1glXZ+MsIGaF&eZ0Y9usET(TP^R zCo<0T?nQD}o5Q-8`0h|R)gq)%Fn5eyc$$?Kt0+UeMVs%PzZDt?gkfI3hq8Nr2=Jt{ zbQI9G+`es3>>gD0ejalFW)nyGrH+|!X1Z8xiT`Ff`Pb00Y(3TBV~XSQOtQ8T*aOT` z%d>RH8C>Ya10!Hd+067OBNt9vPCuii*G{0ngBB3T!$m!P^EWdQ%11%>y_gFr$;XzY=h=ic z!2!wjwY6t`J&=5@i~KUzJn3SUEar={LRI<^AuFy_KD6 z5R8K<*Fhn&IT{1XlDVhd{*XaYC3_O#5|ua1(rVs)XReByjOV?e?VNP@lku*dT^ML$ z{j5gLY}1Eiexda^O2e_NU(eJ3+yu!dyErUy4HHNlWoFF+dovku(ahwtj`YW-UJk>o z%FS)^<3?0Kt5;?aIh@472y<}}*>UiCEZijPwdr&+*N_^?D~xO$p)4H=8Qc>oQq9v8 zg9V?RrO%zf`@PwWD#aU1O%mld1Uz3H8)g&DCR-=B^s@0uh&j)wH&Pqhlso@9Pkwa> zhBYOfS_0Spctg6i!R6|CttIiXx%3YbliXQo@i!O-*Y!UUAL0z;2xcJ zAoJrzlR%{Qt=6O2{V~85%0ukVhMCmO1v-NwhKrg?Y{JSjP~qYgptjqwOsGp=9h&oo z#!-No(uC%BgAgy-j4_4M`uQZ$DD3iprLP6EBH=q=Ej>k-Sdxmf0!}XMC^9XY5d&85 z0v_D@r%msgeV6F9dpq%^lsgkfI`=1EELvJnehjV_f0gGJYmuV=OSM7{VpMGpc4^Wbb*W-&#!SY!5RUCy=b)ef$@I0CI_Y?f`P!YnrKpM??a30A+B0%-PS*_HeGV#mfNERKVT)vBst3J3~&Hnt=x# z#y?^BBG_16>k$}xIfT?77c_@eOR2pJv3nhn_hx7Z-rCZ%Is`G6wpJlTFA{1?<%3j# zLb&euFFeS&6<^X?`p=vT5Bw_}wE)!C8bbVyHe}$DL98A1zz98!+x@}=EG#~%K_{;J z`@ z97g|h0Jy)(aqu@St0_r`x#VrLkRk0>1@ecZqU|hF8XHOo1>UN@H+Z12{9gSl*a2-Typt)Q_C+EO_xH3*TQbtnv^lzj805w0K5W(K3ZBzdWHzSZ zb`Y>lKLI86K)pMorIWQUH=V|`Q>HWeiVv7vInQH({@VI$d-WUPMV|2boJ;j!jc?I& ze1T=KS|OSQa@Nis<@5@jdtXv^{4}d{#_V8Yc=1^zFXVeLaSCSMiWhF>lT(zt0~g~z zQL|6%00nHl3tEn{9NAPlHMF}8BYYN&Kw^I%Ny-`1Y>xCtdT(729kTyEHndEnKQ8jw z;9SiAw_;~qqJR)&_C?uwdmC&AB|~PxDGEM>T;DW1Fy=AbFM7dyGTrkIS(QjkX-$fn zXZ0Q+{lkU7B;YzPnJQlQvF-Yi|whyHIgxwN!eRXxk5@;1ySq1 zd?IwpiQD35j)GnqvoJGGbgEnZ1sf|JdLG%ByMK-OXMoBrJ3gL$+_3xg5z68dparCMs1UG%Z1;ijP`a3)cDBzJ8T!| zsw(BbD+b>D2Jy1;y31SIa+oW$sapy!n(r(0t$%48GTL)e+}ox6c1)Fj1%Tk~sZoSgF%AFa^;cWi*tH zlZZ!WL>*3?uD6n3`dz;m7!DSoS{I8-xiXwCZRlhEt>y>(V#I{PlS=K8Eu|W13-x`Q z;r89z46k&Cc9Vp73*Xh>dMA&Z%vX>bcdvQBdH-(_AbA|soN+7SQ8uYBGUIkF zyf<~zdrJ$M%pB5ll4Iyr%6$1yCB&0lIYgI zrPFzS4`fXC34@CxoQJqN;LzJBv{mEAZ>!>VT1h4N8RbCZ{j=`69eudJK8U95eUSyf zpy2bXVd${}&0`?psdWojpeKg{!SpQ#E`jagn>+NCvudQZSfAJSbiXAOCttu+*fCpr zvM1T_YR}OZOP0jHo8op2d=ds}jwb3!6hN@s&K=pa%xAUJo|mUs}$V zS?|Kebk=fFM_~FO70*w02~giIVOo#}f_@kw^YnFM@K`8%JYVzUt`HA8B!ado;mK7A zhEIAOD~B3yGG5K#dUbdx-Bl8mzG!|2PmiluxngEiGzO`Yfq@R{l9M%OOvYzphft|9 zZrmM26x9C~C4|it>3wPa`vRq>++Rnmu3A;E(}g$|#Jw1kUj8G2+A^7)q3rtN#)mXg zyiP-~!`G1*HeEP8^BE=i?0jgEAgbt24#U@4Uif$v4JWaWXPKE{4ibhC#UaSQX;G>K z?-w*IwlfBq^lHqr&tvzPysni=_zDE;WQjB^xzzqmo^c}w9q%m$IMB>kj{O(O3xWue z&SIPO-4u?r?H;y*#y{&S94A?rRX)&7Vqw2!h(;G>jZU?k=m(v}D&=n;*`BmB2deNA zx72C}rA(bg*hUs65jKSnZ%Pms(0UpmC!t$jlnsd> z&B6kZfO)taO4>jk=AW|JrB&<5u6>I78n~GlDy7R;as;GVDV}a8W)qTts)CfRbb^iD zp@$t&KU(iew0iJL|M45#9$0UxmQ@5LsT;T7o4AnGuobMUTM#^97xyAnx5N`=TRfqb zhd!wlMXEkGW#T;V-uo!{XK$t9-5Zb$m_rtO8+Vxca-2!xh7<%uC|mlE_ffcM0S~xm zkzuqS^5jxKZ7{ZJZKq)Q1dsM_YzAdWZc+T)&kEDzDhFqv44-&|X!bi^cKw+eFafIB zlPY^-<+zx~+`#ab`cKQdl@3mJcA+rYU={v?W!C&7Z5nMk4iAP)io8=04tJKCPaqIl zCKT?y^fD{KP5(WoFta23Et(JXn69;_dZBZ~lJbfC)$6pmPscR2fQd+~eH@XUxZ&2K z$E85$ekb5UK3EC52k#AkCrKs!y&&FSE00}a_gJ3It_JyVcJ!5FGHv+_t?Gy1+Vc&1 z?~POkdu;tUM`w z<_l(1GQ)(^KPz#*G5w3Y%%rvb9p{rN$^XPWr3R9DlFh}(EI-afGnhZ-_&7o8p*h=Z zrJm`-HUUa7&3#(GQx)D>I{oEDXe;Lp;_@9%o(k?DT5EizD&E7}!RGCM;zzYl00Yq1 z)X(=>t-zs-4D!1*dNlCNew8-2(|_}@mEHfCl?m>~@QNcD0SjByd7?>D|k>4{qTsjRu@PZPS z!Zhh&z$?N8;cYw`Ro@-O>g>@LrybIA4+2s=;Y&hi%z^C`25QIylY&pVETnpf6 zrMvPWYGAk7WU>Nb7j-aX4gcivnVNgnC+M6^Z>_N z%_C4-tXutStkn04kXi)R#M_UrXAa?+QoiX?d$;8 z?tz{bfG>i|E$Pg_$VBfp%8T$;-3mD1R+Gmn8)1GUNr2)9v^86Rx9&|kvP(6$6W|DC zNM7uO5Kn;K4Py*qor-|24oag7Omb)2DUoq(s za!YE0Sz0Gz{#&l&jC>XiGtci4cSviINSf_FK zB>i~06<-s4VcuHC4BN`XZySc_1RUad%Q)oC3ook72_I2QNcgi6=to zk4LJfI8O`B7_tNQ{B|pQEc|7{Fc-n(AZsv2s5R>A|Fr;s`_#WgdQR*$RxXy)1*!$V zI@d<*hV>Ef#5EE=>@5WBi*D1Ugno=dAE%aImhNg6I_|fRQ9PY92eQMzD4j*_|D7VA zJNu6tyZys*#A*(jS^3m5T48P%05+=m?q`cLhf{a@?^T(-mTM}f!z5uAXi^m72u z8p5P>)`rWZ^0As(q4h27MFXZCwo2@KUL;>~Cyk6*0PooCnFc$HM^OA;$!H<9ww%ghi(jo`h-{vme2ea zwb=upM9u!3jsS0#y5s3#QZ3KWxa!V}H5+JS4x6<6+Gj4a{y&l&JH~Flot#||FR6hH z=-zb0t>#KC7DEj;k)T_HV|dgBs@Z#0Jeg9I2g*$DHj@Gb~${11P+jSZ;c6>)uABQOP z<>0Z;*RD5FxL$RE1IxTtUYzfNXy|5{_x?GJ5E(J{QmvF&W?$p1b;4HQ(Gb^Rf;mP?khkoC7c1Y-Fg6<^$4VawTCA)Erv{DI% z{L8b+U=Nf|5!aw!rZ@NrTsK_{JF62&yZ%X+{lCJFjE73m56b%dS)3mzJkRnPYVd2s z`)1WE6~qRw>EQw1tb(o}?>HdIz7ASqRxZ`kRaS(a2=4g61ELoWlcjf{uzf}R0(AI4 zvW&d!f@7Q?vE4SYfkcOeQ)LFt_?*8G^A_oUHWm0*pI=CqyAC-r`im0ZP7RTC&3xR} zC$8No$?ir?o|$SX*lL-#0e~SiXxUAv=(J@M>b=2fnQ~lZxY_4V){5fEwIr=u z-Z0(u)1)CMc9H`teTX;HTVJwez*0#M*Dp$jN!o>1Q$EA4XJuq)1wH;*k+lcGsdLwU zt~B?C{JpAG$XI67@P^I8w=x)C6s%*3pM}3aDSgzux~p6Q6hOSxs-^KL8gD-eou zyzT_;OSqTnA6PV`w24uuC50~lNtqY>t%kh5WZL6-m@;zf&P;M+Ct}X;NISi8-4 z9xMi1{ObsP*1s8UIg=0UcB_u8u?g$3q&`9KMa5HxUAH$A{O5OVrZZVHbPwP>jF6{n zBZaAtJwcc|PsOARTfV?D zF^YxlQH~?u4;HQggbZc~oGUGrzBgmerLf{IpRd)cNn&8EScxX;U4L-ru9{mE;nV2E zJLJ!?fjqEo&kc{?M^&u15D~xX*@u~pa+0|vM#a7Q9LGHzOT-GMoj!H8K~Rp!@$&YW zofYJP&mx3v3YzTmXgqKkmAvZ|TCkfE^VEdTg^ejQ#A{@SDzZJ|;q107Hd&H`XXy4< zX&ZQk&T!^#SC=nMNiDUr@4&MPV3!ixsxhog{_wriA^PLvDqz@F5RGf=L_9)+6Eb&+QVtQ9_VIrO@9&(-a$oWSNf5817E?gY}q&U zBH)4R8~D%JXC6V@df8*jq*d6|VlX-i-)-q1iRkrT01}^afdpa} z7hzN66>-y1xv8|K)0;v_dW1s@;pcxVNj_-SuFYo2I)&RR$1Wr%RA&PeWNrNv(_dU{ zGVZ4c_(8_vU&t0SeDv9SLm3>mG=_CN$YF;h$g!noMQSS5A1vQVe8RE>kEj|A6{?O= zzV6R?9>%~6mW#Vu+*|%;h{s1?oAFw&0PpOI3aC5-32V5h)+1?Du6_+IDSz*C>%a3v zX|zj9{#m6eIbTX$jVyL!|J<0{tTs4-;%8fl7l->)Zhix>|I$T**Qa3GmiWWPowS|un{Ej` zu82ej!xMkow?5m2#l+Xlo|eIn^%0X_^PMFGcr@{scW2Qw8w-rwl) z^dS2*laArzv%z~{{63k;3-o=uYnSBi$etU7Hd~nU%_1sZCrb4*G7u@WHt3qb*Ei$G zc(;FuF8}_3wuz=eOK&lzZIyF%P3f1(Nk8&2ALx^}Y27jndm>C?d?${+FNj4^u;u8Q z>%R<7!mI3Aja&&%)G@z_tlyd~;%BUq+skps3e$?WdzY_$a{FuhngknN z3npNDx}Qp?E1v+i#!^3w@nNn+o2o$lPPu$HC$j~%-;h=DQGPI0ZkLRm_;i*3hl zJE+J)s&PN_SlIiW;7rizA{@EbqM84$;_hInNYZ{~0PET5g4#t$(1{STd4$uPa-Djs z3NUIq?>C=-P{Ml_#%~vG6VDro2zl#RWLHcRa=%5|Um4gw+C+y?F^vGdLxE!Ftc2aX z-)3fbOr0GO6CJp7Na$>mzUBG0@(mI5lL`TG3TsWsdyqww(NQk1a|kMo@Q?RU zzZqzm{7*i>=Sn~k$H>q zpp9yIp)B3C1z>L@yIH0IxNMFZZ-Cj+rdw`NR^Ur$kL&4tfaT115Oz^-Y_G<#C<*NL zqsJoPUTjhd_lG7?s^-dWAhnzIVot!~X6@-hO;K|K4Mx;L2;sSYbshpVX&c+l$AGpk z8ng#jg2x8pRvY4i^w=ytJ+`+=414@D_UYhm{B2JsUT9G%w4kh-{WCo0C|`D9)ge0fg^?YtFT_C@rKm^$|C~}m?zWtJ`|_pE~rZ7@EwD-CBv|4F1s1^zAyTOl(SW!d3BMW`{XmR6{~6nXDj`U5dHa zk2F&$6?ZBMxEK|*1zGqNxnF5Y6K@{H6XmsRHSp*}MGD`!nZXpZhs0EAVya3Yvq4kh z^g<2q6D7BmCq(D_=_Mp5}nB``#ms`t?r~D#G&jy-sT|Uie zGIePPPZkaMX~y*v3hDrm#?bBhn^GuQyZj8~b185*tP_Yj4;Uxy(KSNqU8cps*~iWE zQ9PNTwaRr?Q`Uy9KwVJd5^%1Jw#XC({9g;87b{iI+|Ql&@~U=lg`A+gprbs7qbrP@sJ@#I)5wWvE7PJrsW?!=Ibj@gBE;FGfis!pW`gQpxoQjQ+0s{05a2t!XkiNnGawqtN5Fs3`%dC8;?kc{gosE><3o78!qP3y&l`qht z+;utL{yTcQHxbms&wQAhnX?b-Z27!^i@F$V`K9dL)(sj~ZZ)H4+q++%PkAs^YRr#k zFbfftg{=!)-sukqxjU^+uTew;SZ?b#kYb?Oa=+zJMCw;U z-!CV+dW631??DAx>Vz2qg_~_o5>Pio@u;=3XGV$W^ge9wfOnMVHG9+ET&;de+E-aC z0x;jU7)YpikU?B6hi}*8O4IYm(GK3;c>U*O$J?`d>IZV>;zY?SMy7EcpXUI}CAVg` z(%NF)pkHj#3u5R(GwBSRa^E(W`99@&)hvqtmrW$vvn2nQx!{neFW6;r^RIn>X z;+LK-KePtFO?_I|sA9+Y6?1K=%?KQWo(J2?{dyrD-ovsE6tQbLUg?+*sD`z1$)8+> zFJ(F~Lkqo^!`f|eJdWaiSEngKZIeM9^0G`%8h^%BT`%E7z69y72pjTo7aM$wYSoYz zQb#(42}n7M6N`WaBGGBks~D*c)62eb)uHbVsefEarOUuurAQr5BEX}0+9rIvIu^r% zP0@b@&g+&bUQgDr(EX37w+w6g{onryVe&>c1qG>5lEOelVuJx9oq~W01Ed7q$k8n= z(xt%YkPhjRlmSX39fKhwrKCjszx*7>_y4=W9d7J!8=KGTdY+HRnQkF3_)wn}^}NWO zo8y`#$JjJjy+&k~)22>+sU-43(oTO-@{fbqz2Xm6t3dJ=D#s8-HCs$Q_zXmyEU8^5 z*upSZYw|G6S(GpyXrEz8i?PG=Tx-x&Y%w>eKJR!5AEokYPwNoaeE>3Mho&PhjoX=f@OzA>|!;KF#J9& zaH@s$6lQiWv|E`9(O#0UU}NVI9O%;Fc>nqxftL%Qnfjtr6lt&JBm1*>?W?BWVNNoR zbJtfoF)Ixs)X$4!T8)T(<5Iy-5`96;r-Wm@fIFDMP`=eywEV$N49r53PmAO?;vzN2 zHXMF>3=ENx21Yyekv-MzZ(#YxV8jjQ!J=;-%o8Sc_6@jqZc^ltB0KMElc>Bx$bE2Z za|K^}q!JlzgsKI@1!L{P6$e-y&srx^00t0Gwy)zSt;;AA+vQ+myl-41B*548hj^t&l9o1ETZQ_2!hkT(u%d_!d$8Jud{)KrB%5qlHo%Kzir2Vbh_->gh zM8(9Q39upjxOTGb`MQ~V;EL6P4vDo!q3xsN)t_9rl%$UIT$n}Y6bp;)b%qbNCII_P_QDM=gL@+p=-SnEcUNr0y3o$9buXfi3izT! z88WN}Yfkf4#{lPJV!)1@FtLsm`a>y|!%F*GG=N$h(-H zwiA3kTwVhAp6pL2FB`vs!_zXW>tm}?W0Ok1*PrYyXVW6Oukt|sfM912->nO$kDu#C zK`>4X%2?U9ms9GB>3~{m7^u0UIPnC_neIAgd6AZZ*6>o-mEO0q*9~k|9GV?V`O=*} zaynb#fM$|YQ$p4o)T;!WTBKbak`}VD=*6s-mb!T-hWWR&$HEMD#7?X|F2iB+_1`bW6WdPy2cO2xgz0r|lPRGz;}6n=^nP`KH%| zv5UKmvQF!?yj>J5-AQ1oA&{+guv@=P{Hyv2$M<6_B@VT2iA-<_E4)$?$?nBN=Y7p3 zF^5gkm$pfvJ5ODPprr-WEq~94%|<9>-FU&V$&lXN4U^*=n@XEtb|#T+SNIZXmpfFE z=a5es&XN{EuP6!kJC$fN+-L3K06Y-lGrLi=`EDu`=AMGWj`FUko{-5825EN7Z4epU z&YAONw2Q(61_X;Dlo$UcMgbMx(B#Z|X5JvIO-q%-Eq_RQ=O&JE2r!)rHEt_3pRQ;Q zLYTM{C78^8tJAQ{<9UPjge;c$$5kcglbbs?1bS4D( zarue5vXA-ux$j%=T8O7+z$ldyqBwaQn=*P zLzuMr`Xdh~U{k#TrNIIWtLTB6h&|xw@7CN!I-fuCXX?A7EWER$PQD8`qUnp2m4Uues7zISHVWPe!(ef5b4P zX6PLuMSdwgOJ(zDot+o+{h9G;a!{FLpfmSUkbt{sa;Q5Y2W#K61QOa*#aV}%f3iF- z&z_%;D6Mg{>mq(l=pb#Pb*?1<_l-FpS*=&r|Bl7^scc>z?dj6R`o_RF?NI(_$?)IX zuH%_+CRUs5O+4n^icUwB(f*r)0M3X1l5(-k=dNT<95)i!x@%q+s`F?a55vfwWw?w* zHm?ADrUSOXY$$5}a9B>)*xW7oBf~lQZhujJG;eJ6vrh)~hk1iD&i3o;j3(`ywYJVO{d_08AHp!EqchH2lx5bKZ?y^%rAF62Ywjzc)h%ywUCEM@^6=-eETV5Io2H}MyI*wg_4kjbL5gM%HQ=yU z^N-6-oAjN$_X0Srtm@(rj+bSPp9VA^HQiM*>oYGmEH$?K_T1lGJx$87{l`%HIG1-k z$OC=XsP(DYx)Mv3_peP7TowIdoqyWvQ&&b4fHq2VuPl>cJJ%c>-KlfD4%h83`3@fh z_#b>g7|$!ZI9u`G7Nw)kuiVl&T>p0WKxzToE;)xDCrKbY##iG%3q>rJ8qu63`F-EM zm+Uf>o{l{XMZMj2iVFu5gR)u-&`3xB#`Le_7lAGZ))WwSvY$t+MD>(L?GeO#seqUt z%0D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 diff --git a/app/src/main/res/mipmap-xxxhdpi/launcher_icon_foreground.png b/app/src/main/res/mipmap-xxxhdpi/launcher_icon_foreground.png deleted file mode 100644 index be958d5cd64c17aa6dfd8c204ffc093de2cb4131..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 117897 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
KkWG*gI4qR#64K|CT~E^Sm7wYpYcumfza zxF`-1x(e!o-M0pA(4~c{st~W$*C4rbw~Z~n8E@QB>Zo8}j^sH#%s)Z*iI)p`9ic=u zys;43sj0uw2GdqgYbsq^+i7~a6!N^)Rvl!m@m=k=c|0i{;mQ~@dwb-9gf2BGS-{i7E!u&VQNAJe25}t7e z>9ofLKFrC{o{$-gSmV1X>xvMwnwJXe^M;{VzMnC*z@EtW2^ESW+v&g0`I&H`?o`)7 zud0AjSqhINHc^^XZVKFhc=ap**hm3Kz2N?x(Yz7$vfQv{`na`Uap$`)o1dAG04EH zWQet>8r_?5a^LjX{t}sugI#cC_fPTaR!#yhW(Ju6vWl0~j5n==(jfeR3{88`#xbA; z9-1IM^s0qHn~B_rzh*zKN6CsjxVLW8Ds64pUE@`zYiyxu89|7Hl*Gtg8Z%P0Y5&W` z%Ri7GW~`AKaO18ZuuPs$G(LgSEd>nodu63uC1GzG_ccFLSf9*^y|?<6;f>jDq~dmI z4UfqLFbBK`yDmor7cJLGKfp~}T?;LgHWh~4oAa@LVx)6i4CzL?w!RPAFxz>FqHqd> zlnXU;>veL|ewAZyiyy=((_2mY=}!@CnF0YMpo4%ByqTHczDPDS(dH2mV!zQ zeE!cx!F-ei=sPY)}5B}u$Y^xiRdSSO{?sQKya zX=5w286A*br|a$93f@DqBo`~{M)G{~UqO>V74AAo4lU?pq;vwQgeus+BRgJ0TMA;4 zPU+fS^cwFb4<~7%vQ$c}ZdUv`Dy294PH&u0aI-Da129svp*eIbvczCqjekeqU&g=T z$bXKh^q7|*svDc1qj0!}W2;3?gvwDt2C8DMX6Cewreqbyej}gc{t)GSauPt4M|{XS zk(?kbYfgC|u$WBqR&w!X9WjV4Y{co|9PzFubg@{hMN@ajM!wEe5!kwWXIf_(pjWMa zcr5Tkfw#82uKdFP$JU145-XSluZfg2d?=e3wWOQ}!x=bwx`}U%Jt-$8`AMUz37Of+ zA^$k&P|@i+p4plGv+l*hpNFNy_=gQ)F=~SFa zV1bp|1h;C&N6)mHuqo+`AMK_E&2ibb!bSqii0E>Zi)#-S!(wy1c&! zl0sEq^=9pCHXRj4Q4Ik}0_4_q)}9$fgB9!eIH!FQx}1Btb~s;?hx3w7=WzJ^*q2IN zI08&)h=u92*@TBHc&7{crJ*;qLY4&bnO%48sn%zXBm;JlGZihJwZ{<$yHKf3^GV-V zJo-nXfwzkXIY{l+w7Zg*K^g@{*x8ULB!!$IG_{+zLw2E?S6*nEz5#}xJ}$uVDlb`;G_l}oXv#FE- z*#b)Yh#y89`L(cq{Nm*^z=ZXqtfpF~?zWdp81)wt&y*<2Hcos>Fc zL`MyY@fEcs;V&GtA!dPWBSX#-B#orMMqswy7|E$edeUN>GSN$ zt{Qb%SW(EwcBQ*yyOoMnrCsdz+;duF0%RPrPukLGs$Rg^LndnN%D*-5%X z$aG;a04O05@L|%v`sQB(v$``Vjla$*O-ivH0hIBJoXlsEb;j^Cx?l2od5F~&Bz#tk zX=<@7V^3B(d}9}QWaPahm~((OXQi%&)nLZVcF#l`axYu8Cta~4&q=Uo?#7wcB$Xqh zxmDQ#y{HpT1Sc<{*3jrE3~s-++5&VM%81u`Zw} zU-C~Z-oG%oD_zsCW)pSaI!#Ktl168G$K8;5O_8r09emgLb_SWM6l%{iE#a&{sc1Cj zG!n1^^Nd(>d?U@&QuZEWU_^GX6H)QGtm@ss4XpqyO{wQ5Zz(qnzMX6f{k!*+9hP~m z#9PVd@CnIVQ-s@`NO`paP%&~DT$l_w=nNk3&?mG~uaM4ARw+Tj-u!8Pt)?y>>6fw| zYU>i3q+=meKdbhceTDu?qP5tYgfwLT|6>7QPxtMIBke-mg4~7)-V`4aS!buy6?j|P zwdsMVLJ9+}ArjBE)@b~1QS~!lf)0-(DSS!F5A2kSh@orKK0I?gt=CyUlAuG`%H-tD z6ll{Dzo-${*+k8ID!&$q*IGXgqdJgAd}K21|AT2VPvg(NnzaM3T)`CmbK4(#*mXe5 z+Ml>KC>Ql}>gn6P81t_5MZ=yxw)ILyg!oR(r44%~l017J5~y^<`v~Gk97l&sHk)y$ zq7t0ArriGB1ww_c$7!wyC4?r=aZZQ<3KCr`8%fs3UTwHCb?}3T4kku6Q(Yb#M^=Ca z0iU=^TZmx`=mUNb+UEk7J)7gFw%q`N==19ropM&w!_$EuQ?QQ#gvActxMI&+kSRmV zL@Eb&jZ+Vqr(X;>M_(P+-3O*zkmRW(+NODZHRvz_q88H}G(7ejaT8$x6tOj`$+w2F zBUKz$$Y7*XqJvd;iceqn#yMQq%MDHcl6D9_Gd%jE#SiVnj%~(us?46htZ*4YemX?1u zbWqa$d)sfB-JX+~5pWJIx{_l>RQ2AQ0^9F|CH@6w#PK~ApK%q~aF|0eGNCnVo@^e! z-CUpTrlk|xV-~U@N1%6#i1q}|joFL%w<)e8ai*Wut#~|5*WNc>f$k7Y7;ky`Rrw4N zcGdL7xpm?s+SnD*rM@U&TZ5oemeEEVhG6Q_9DPC;gE?ohA#t(EB~>>HRi<9N zt(o>&0IpU&YGnCm1{Ka}Jv5cSKO4SS9XF9oa!5A@2BJYA#Cl!PfE?4e?K=~!>=fqF0oyT$3mTM#7YhfA;9bSnExx1f9F`ON z*NPckJHG*ajwzX59XMA0?>6|s7YohYXU-MWi1I+Jll8UXGaZJH-Xf@jCBJqkaxk-( z>m_Rd8|tGZ47g4ZKIehcYvW|6R^@sdn+--*HckdeGQ+CwU-7F};c^8cD6WeC%H5)xV$;Ar@xx75t zjXHH*j6zoM=x%vg=|y9mv1{<2X0*!5sCupnJM9nit!^qRSC_H2YrFMV?um8CSQ=TypCmpS4q3rtc0N)2!1qFNo=F`hp~N6Y zQLdGjp_=3}L{W=K@rVy`PfO#vl%gDPDCe1aW_wRnETxUX0PEh)&<7`jz6s1(+wXNB z77zn5%)CuG^JyZWi{r@WT>WDQVSML_8K@nL2RSm4VOpHzGVZ2%MM-BIR3>HYP`dF(drGMz}F9I|9ZzIaT zE?N2$O1|^f{v}y|?YU0YuG~jPskB9^lB4`L{-DJ6tgKd#sbdId`X0b}BzVr%L~5Z- znSXsj>{-Ef>% z%>XgFD^}Gc1`v~&!}U-6tuCP2o61T$lk;I9Iv|k{8sD0DKVbO8F;tF3;zU9|ZyW!~ zisXw8E9FXyH-dl_^pFO=ly2xXJ?Y~=8=SPFD%+$Sq!7L$phwqD1iCx=R&W_|NM;?c zt&oF-Cfr5c(fBqIS5OLR$SbRC^vv(WZ;}C-zBMJz$0Cm(0A-n;W5o8TdS$nnX zIF{$5*Pn>=jApb>vBY9F@-4cE*dd;>43`j%p_@c+)9>Cal%Q3bfDP69s^jKhR8Nm! z+~3y1LrDly#c%Z=HF{zyi|gpW{sh*wsdGwh`3_Fl+lHFe8GZYmlwW$vrU?O^g`9$~qymcAag}+pNU|NTOA7OjDx-46 zN1J@6{!zGf+sw+J*cD*QtVXU@Jp@l*$fFgdc_eOs&;AhTV2%x;|HwJ+{Qow*)AG+`9U4k-#fMQ7lz`72ry>~Pp_zz!-!Dz1ks!;M&Xq+JsKN|7+iGJt|kqtyk!9MQ9(Mp$ifwN0y+pszYDCcuNSb@F$NE})d5mtQ3`_u8#lkMyB&?}9TI zd8E6c8b@@>5k;8P{Pxkiquw#ghNs$)I+z<)F!qof=)}QlNp2~1$AVG@{aB`7{^B;1 zqESEqsTmE+3yaGJ%Bx}N2kSCnHJ=(322O@#$pJ#;7t^9`o@vEF?4vr z?UzYZ3;l{#abJ}W+V@ukle%RK)`(Kne3x>7di_5L;%kkIjeU!;9RyqDdkvLYJpW09 z$d4jns=~nI0AT<5zXCuiV>%rqu*Ku=L6o6Jr?{xx(~AtbY-B=^a^U?d@Xk8~7{VJ> zNzlk%KE|zUZ$xZp_?5l?oj8ajXBtycpg-J^Uk{3-~#ezkca?gGP3xkAodK{RWreBw|>o(2?I;5DbD#O3Gp_fmZv{Wl*aJw=260IR8%d68{2rk$OY2} zze(^di>-Hb{FgfUdd6|SBMBWre{k`Mo=tV)(E8@i~2TeJHDjSwe70B&g%>fqgD4A>!Yp)svyx(YugUITr(o~-|AX@DR z2bH6E^~dUUNo&;YZGx~h$x3|mo9^#+E$FjHiE_51w<#OBw&ovyiIi5Nx-x2Etncf@ z;+i=6@AdgPXqD;Dmhu<**9>ZraujKbBYpDo^Mh}DPCKchJK-GD9{Rm%0Xxv;?c!jEg9V(}swiNnQ zHRfJ)S<>N%9_7bQ^Oq5v^4!DEt2qbeo}3x9PYOYaQ^=gfz5K#8@Go<3ra6)P$=^=} zLTx8X#~sCWCQy2$H8dj^qb!mGf7&T9oG#*wDJpi`8nLKH8P)wu=b>Q<$D_#6b*J!g zdywh(*F2o2SI1U|)?OMhr#3BEG;|yjQ+0U!IP*5wjbSBfDMG0@vo(a@X{380$6*+D~VwMz9D)Hg-&z zOjAV1rKlNGh0)oR@7%8nB11BNuKfeY zgm2;qU58jH>bwcXKY?>dlC=4A^vEK;vC@>CQ5dGVUYN*BvZ}BQ_SkleX0qIjE3-JA zy*sDGsh%0ylK02J{dCib3TobxngGnPsc7r=SP@nV{FB zAG6B_0dG9`VJD+sk1O2Z^ABjvlMWgD+QUcaftl&oq;(t9^~rBz7C0c%X0fVL1GR~P zS|s_@&I#hROwz7fOsGj|wz>*KR1LO>W&FY<1qKXa6-eb14i(kiW`SiPZ2i6OW|yyD zLbDwM@aSE3TZ=+QJj=qpJnuKm@;72Wu${WQ3hdnPvfda!9Vb7lRTVflA;*12m#i~o zY%HA&_@2(=K($zldiT>)>~;H8A&=i;xG&|mT~5;X#$q_%$GH|uHFF!Q2eF0?dUP*L z^v_fjapw(*i6`urT)3?hIFF_z`=#0NJKu%a+O%~AZ-6to%}9@tL5_Q#;`og8MFjs7 z_jbAWG((>WOr=TS)Y*Aor25S%HP|^W*@o@ciuvG(Kxi~(fj6^*DWn$Sv>3g(DUemprINQi9#?ggCn&;8uc*1}SJgilE%uc}=2zJt zZ}#VBOB^vPP)~I^rHerB<=Wt4%(lr6AzYPqoA@c$CPg2^Hl+JuES!#B;iqqx&Xgsn zu`bQzoqQg?X(%O$r+m16)1af(D)X=u2DLdM0HO!8*-pv)GbT}UK1ZK*d$`f(>gDZJ zOa>#8r&}0`jC^AGvfnhCnruL|(s2nA77rc{^u1C}bpd$CBr3Dqt~hO<8+P&tw!JiC zIC(|Wt;bE=cPp5aUT=7ewR>v~`=SS;pZaT+)r)BJmyJ6-TMti-;q7E{Il44tkH;|B z772~=v8K&GJcbCp`Cz>$IC;ms=1~On-yI!kvfYq*?=$_V-g}0L0(cTax$!PfPe8s5 zAp{a08r8&FX|#XxEq*WBSu9Xavt?%OSuXPCvA46GK12g}&KR5bDq^Hd#MM zl)XAp*%!_oe|#IUx-?Xo*r^spa!M=m>BUjHimyX{oxvv>kus~Ph2cx}@n|Lv`n98U zAO0^LD-Zwiu2f?N?fKsXO!ee^Pw?M}8Wb=of)V*`nhydvZw+HS^GO>U%z-Lw&ZSCI zYvN!Ny<07CyDSAzHG#x%jXcc``osSI(0;O7iu>%Zxs zS}UsU2AMz>fMX}*+1RVuyS2X-k_Um4wtpV4Ep-G%$oA>$M z&?6j=Dat4_OCJYZ=Wyd_;r>=`y8H|1)72j__9#{FM*>iwe zCmCA?3zJ$RNyr--EL9L+Mi7O>v48`wAUpuSQRj~1n>Bi)@I%{UxHR>LT92_CQO|Th z#H?_8msKjf%P#EYJ#T+h&Ozsc#ar1{n)^W?MnqGWIA_17hQvtCj|OXo6ZOYGrd{Og z21IZ&nzA)eQaQLeGfeE9x|6L9x_*}7#6QP8kO~bhl#_ZY)s4cr4Js^Wmel7A+@Z4Q zbKfWczfaJJx6)RTRg%(1?`nT4>UQw)q$~NzP{<$R?w`)P_S2eD>b0p7LC)}ruH^6T ze!Ww@rSO52T{=zVyd-*FMlb~Ov*}Z>3ypDU?xU z4pseXN)tbFOh00H`S2l=)6o9C0n{D38_4kVm$*#g0G2F=8>582PUZ|s$YfJ=_B_b< zPrh5pXtK14-BWDz8VJ1@47Ev6fd&^!I&yZKaXwqtedH3HG>&7qd=w=v zm{%0P3MZ_3AKGM5$5M`*8f*c$7%k;Ws z(rcZ~puG4f;bs0C`^T%0%l4H-bjA;Zm4counj+zkhEpV~`eMI^nI%WW#7%$xrmdoH;G=&iYYRHS5;*3Qt2?^S8 zIX}lHw!J`{lky_NMp^&Bx%4i!9Aglv>5>;lLTRqB=X|$@h#>(o4+1?M2>!uLjyi|Diqc0Rh(Y1_XZt_{Je<@$WV+6H1`3MBVLmIIi@;#fwrjG@jYzB~4y zZ?lezR=Y5Uv=|?Sv1VaJd6=j)(cur6nUUf5=F6v`YkkjNZRWS3Q6Y>x4RVe^*nQ+h z8^ek#tVEZ_1|YTTM2U{^!z?`d{~?A3n#0Oo)$xmX6;{l#Gi7fljuSJcmkt!A_)P`XHYV0A)c-Jd>!w z*^>bFNC{p^^&4ptxXud}Ituk5>OwHYG!V zgT=U)s1bWWD^AM|;RAy@C#{*+c(Fe_WhI*z02LtZ_9VQp%L(YO_|}RC-Ldmi5}b8G zO2GMR(<2@rkTZ4>&)*g?Rusg=ifc)FZ6D13-kyaFDSD=~zUXM|ew`edy|f z_o;9kTz+QAE!b36-pYP?0T6TFOtr1kYu9LnuXRN06knCxO=7(tz6c2o2$sK7K%^hm zLJR;$7nA-HHfJ#rboz%E-zTwZUWk_n@Xd1OvqyERhzLfb<6 zPpl86V8$!9^ItRdEZs8^AR)_+i%`pVT->q#zIKy(llW4*H{RfKMZattu23^gVbXb& zw@*srv$jTLe?_FVNeMNkYObDq8DI_Rk<>QqydA*L7k$sT_H0=lG$!!L>YInUh*uY` zm(YM`>53~D4nqXJd<}lr&@1sCcCvEPqyStT0yH8~k@7m(8w4u9S^hJi%0eWOVMUsd zM4t+;PP2I0b5af+<%$kDj?tz68Ds1i$tPtgg?vLo(e$`G9`ur8PkZvkH%ZSNFW;XE zD(7an0iIoy!~|WA?izbB`%MM+3SYfvXh8*K- z0|)lFtH$kF>@rnON|$2*OJ>J4gWvcY6R=c3L@Ho&8&^q3zEi;aJkZ`iO)GHpMA2qC zCWSv2m|{v)*Z+`bfslog<^?MY^hB~1$`cN^)d`U}c4)n~Af&q~^w9gpYuRoi7^UkE zc4R7LT_gl9o1aRWyi504CU0!zdL_A{&~v>_SiT*}$-Y#(DY&0`{7nYdSQ#INgHam2 zJ=>+oZU%fEMw{8u^afL5uGObBzYW~F<#z=s5sgF6F4yO z6iD1If=M`n3UDCLa1?Bh(1R;+Lbns+F6{qd@apmEoW0$+!1Etg*Z5U9Ra8P$T(W$` zmbiDyOP-KjuIp1pXayl@rDuCCgO4j_;VU5byN%*dUQ5y{GxcngN;LiEZjQ`}J{BB> zM`cu0)E0L)GK2#C{=Mmg7+tbv3nE6^`|~UGe{(`5IaOl3xad17C#a*^2{+hRVeK!$ zDo=a*9{cwGfUQNSr{%_j+ivVc(oZ74EPPg|cC!Qr3rIBL<4!(O6R(Zh7R=&in@Q!f zR>w{OHu;x_TAX##v~#bMoVWkxb5M$#CS+-B(-sC1S2T?R7HQs7?fB=Yv=#YwzJ5-| zRUHLX=0@`fcic~m)JiYkIa+x2Hjr}Tir|O|7YDmJMSN{ZL=73Oz~ofyxF0m64SHj| z6qocBhgR`ox>`J)n2B|zY&R9T(ok>H=1bpJ8 zbUhyL+jUk$J?9>Ne!3O}cRjGRY?k<-k zALkbb<;+N=291&T3w^%*S9O3X?klkSU2DU7VMKo3A2HBai@L|~cuE_(!daLzdGD%P z)TZ;74C70U&l%cbk$0@ERATWsmuGZkQw=aiX-?tXwA#(NepdlAgQ(gW2KJFyfP#@? zfW6{lJZzk#Sw?-VzuDFDGjFSe7gr9 zD~DeU&1YtskTSrq#q!STw@JIH!jA}rRpT@fUbBgf4X5<@Vw8!g=v}#?scR0#LLb^y z0f9UD1uZrU(jOb|myqRKcI;OrU?h{{TIG)YWWBrIV?T-AQ_Fv=>8ccoRLDY!&bfL^ z%qOLn3Mu5iUrEof&eK_Wka#}RQ4%>vwDea6Fk7E$9u*rm0X)&(B%10+;KoKFZ%K|J zq>HO9J0{n%n_n)Or4kW5_J&s^D1Dyh+`xhc9(Pgv5sHBqj7Zhf2KBEOpEk0=n`q2K z{y!D~{bxHIb|TKDA^y5S&i2ePga$$!hLa3DI6o1q#Djs)mI#pLi@x8w@LT)Anpir6 z-9Y2}Pozd;^{dt4Pr|^6d*==x1F`_psKb1l%nYu#T(5V$lmT4B(@z@(f+{_9VlH?lma? zNT0SZ!DlhHF|dJ2(CIrYu>mv8@==CL2UFtthY_(aW zi>DLU$9BIzv@MjJ$GQoUc6=FhtNV^Cm*Kq9iCfxkX~O!O4SURq_i=7qDoR&7d7JWa z*xKqao)>Ht5VfZ+XsCB6%TsI$N}>A6u0b#riIHqslhE&9xwN23k@Z)ZFM8$@)@fIB zy^c5Hs7UlVlyT^Bx9j&f=l35c&(il4<7n7#u{4voG`>sj3RhFpF_NwW;i&u~KePHUUfimg#~}_44Ds&1^6n;=LFCohxQNZ-bG)gCHi>-l@k_7P7>D=`0YnEJ#c*~3N($XY zW0HtjEF|?mV|Rzax;2T6;PI@aVJMBv$O~sb6RgE!RGmpCqCxYnZy5F;^sSSM1cP4o z+{G+H&K5*)fMnj>%H(R0<68{1HR#NhZ1Ier8Pl`Mu{Deovrluum(?R2d4^CL1$$7TynKV_v7?Lq8GE!$ zj(NFXu2xuL8_fUGyQmxLp($nm=w_=p$w_NJt~t^_mAghXDg0hZ$^WDFE^;13BSBS; z{p6$23Y21=HKxH?ld@5ZrdHI6cRhY0E)~ilY7ddG8Ce7XsZ991F}+l#3gE(j!k0I7 z%@_2VmL@sW8`Mvgxh|R%mPKl1F=7ty-dG+K{<{Gj01ba*)PGobM+e zo&V16{KxSPoc^$_1BBOdiLk9qsxdp-B~9`d^Unt-JUumFPZs---%raZJP z%Cl^6s-l0}2!6cZ)1*K>#RDIOG}7U=A2HR710AIpT1Qr;}X z$+j7eqZ|8CLkeBZcRaFaUId$kyjau}6r>Ppx6bVrkxf5?qmTRRgq@p+RZ8YXwBNGT z^+}a>_#7@pOJ|iKu+P=}X1Ewx5lCYeH$m(44NfBq<;gRqIn3Nkk_&D>p@qPvpPR_F zN_7R-3^P_E@@;m+LGEB{0zI1=ttM|wRFq7^jT zD`t=c1>zVClQuWd%XTNT%!iv|TgDs3oE;o08vPZi(09F0oJnqSIdv#v8|q4rG&U-j zJ zOs^+S`JqKv!swmO#H`hK%Xe?AYM9N%`$C0nMX-6~R;R%)l+IfWW8ZfqPgG0g!1>N5 zG+U!Oo&x@ZEZqs!k^GyO(fQ7oK9>PMAp2p@Tvd1Xk}B2ap2nT#r`%F1`{p{jVOK@= zg{Di3`vY-U&N9Spc^YME#%tZ+AtSS-<~a9Wf$qHEP2ij`+vcOx3#; z>5s|908@xNZNu#mXsw6E4uy4EX4~4ymS6r~QtNK)GZzNcxJ(O6Q9vUm`QgIUa58Zf;9$KD+8iE^Vc3xZM{s*AeDAa{&}bFV;khM0SGhwCK04!wy0( zEs8l~0($$7iJ72gmJ0?V{}erV^V%bOcDr~=$9pwHpgTRk~(aLB%~)wvxU-b zF`{>rJ2q2?3g1+;BXaXW+9e_;0gGNGHLwYWg80bJ$}8xt1vD1>vqm!Zg6WwVbBRYJ~8swf+@RS#2YtiJbxC zKA&ZO)7_@&t2o#WrWv6_CWU@LlVCRk)v>8kMaUVMMn|z0g_o^IT%madttP{#{?6s` z=(Iv8um#`74nkLsR}m)la^(IPzRS?0!8NkZ17e`gL4Z(}j(2L+Toaq`FC9J*P7pPG()GB8up7#8}7l; z@p^J^U(2uJkH?=G+cE+}?o%8aD0*)AjfP6^j;1Rt&_eJ93pa$!Fx)h6+BoYAB9tLw0!_ok=Cq}gyhZ=00;@V|_O z%i;Hc%XH2a7Ag~-R-ZJ199I7N8rLx6`G?QmxnaH`hW^oLrenK=@mA6GxEcMx6Rm%` z!WASxxR~3yZuGQ@Nt|Pop+DiMu((p&x^{cWt@RBYqJB~pJ{b#Z_d)9^)kD3hbV8{( zp5ozh^vyc%a&1;|=KXQn`A0odXb6Ie6HgMUA_pqowTqZv$ikF5x~AI9o1cNrDpc-L z+EM<}H{eTC+1*pDf2N>eIt&Z{Nt9w$TyZF#!KjsGN z%9`Z(Jf!Nka27?W*%7F*zeiCpZH}m}5E2~A$6DSxg&f=&O=~1?XSMUgXX*|FH9jk4 z=S6S?4b+-{AqTvAku2k*Pg;mxk5epQ#VUD+Fiyg4wdW}UO&4dZ8pvC7#eyxB#MQF& zUan-q&oSS~GQNzt9HnLeG<0legvKhz8}MT0d1?ep7&f6a8e;hvx#wJlOggJS^@0Ny z0=>=*WE!CLedqeWE~hN$Grl)FW&G2|)Hp2Gs0TM;yf;TOmrMiU72`z5y0MK9uYT*I z1fBgIm?dDtK}`QE?h8tRlqCHoL7unfkV6^m3ud;hj)uOGe zih4m>DXOn-1^pl58cUn}XppY=-=W#}P-+%OVRnu(YwPf~eUr+=-Z!L~@hvm>W0O?N z-}*Z2YV=08ezcZc7nmso{Fq`2X##Dg)lTlA!C_lJO) zVLE9x>fF!5Te)y4ij>?>+4H!1QB9}2X+04C&2NM%&oNKzh(Xd>RXw8JM~ZswWv0>_ zm>CX;@nSl+%Hvo=RN2)yVb8Zuq2VKkE(5Isg)~p3ZRiNpeMdCq7WpffPslfa?;0K*Cncye>u^nX57bwp z{Q6}$B1O%ZG$!R!^K~{r@`k!7ScQiRs8FOb9U}_YygrwZ8cvRb4MId$TIuhma z;5D#K%Y-rFQCe5r<%n3rlnJKBHp^Lpb1h=cT$@c7$IWd`CH4eZXihcT6N)TNsMiih zY$a8StRyGiFEfvT)M=#0esM|2!&uKgCKFV7B>i{~y8;LwfbNK>hqKB|>(i9p{7T@? z2>f1-shKGZ$;V-PrK*66RAPYJvI}tLkqm4A8?iu&2H{HE$tk|dPmL|$&X^fR2hB;D z1tTLWH>(BMLyi*FmEvSprzpAM-o!wqFK?)1jeD$Rr-sp`anTng1=Py06(+pR zZ6O?bOpiN71%iQ1Y=>r)NU6g#UwV%w0q-GT$043)P(^h9y!q zoOY`vEuwUNI9mJhU`Zx!a*-XPHAqsa+HK)tPY=wE$(PGfsw9D%w{@1#$V?t|BbFad0%#AbpM- zE}Kn!f+J0w)$K~$1yfG*gDsO!aapve~%x68wu7583 zaMz+clNrmN*j~*5S^H!SXJYZgw2fdftAI zaN!Nt?cKh=`Jye*yHP+@6(b4EhN-o6#<0%8v$;D`uVYV-h4fTDMKS(r<&4L~1Xa_+ z?wr>4B%*hTi-W?RCT5j2{S+l6?VU_y(-#FkyNd!!Wc2iH{o{ zR6$F*o`js?$WCBX-{KpX#%Yt_SH`F3ys|dvFbUQPq_C~6B$#&=Tv)Yta@KKjZr+{j zWV*~$UvKvanwyK7n+vjoX)5kMIib7EhVZzwce*l*PV&~x%+B1sbB&G)ipGfpP5%jE zNaX>5PtEl@eIPZN^}9h%1EKjrdwWq{#z;o|-5hqqOLP%`5a%h>^`=wHd6xg#H~sb! zgBsJryVpnHub5Z)$E=-=6R%jUCE#)~UJ3j1+dJ={%ikIZG*1O+(UFOE&XtC-Qj{aM z)haLHHpxh;)*5u1!GjhO4cfOt7?qX<1i#{m6V@;4*tTZOpf0KlEL=DWzb4l%;|4Qc zL_Kfg%CtbIkqDMXBA7PYN>}D|2iK{>4Ob~yJh%gf1hQf|7rlOjW|kS*!Ep^ss`ZWy z890ay+{=&nF3TGjuTi;_1v+3xTw0k*b^6ZlOmUvAq}v!aY!b>7SWo<#*J^xRX60aM z+`$>Mi(-wE?}HXd+nB{LqI`o*#Kzur0}~loJe%c!y)3m3r#)^1?>*{Gz#F%HhYQZt z27k}R8cmCbL-ZWRb_3Mf=ZPmptvv>;c`#gVtTi1K^9rp%Vexi3hK!{mRv8HOV#FKv zsKp!h?!^=DB$mT0Rq6NUqZ)SSqdGWVtbPaVpGxX=I)Bq-hQwip7|KxFF5%Q}UY<{q z&9)mTvemgZm(==Tvf$mv%c?J5WXjN3Vu~EmQ^AayolrjVoN^e ztHn#22r)CSZ7&pd{dJx?AE7yPq+KIX)Q{|DO8D0n?*dIBk@#De6&%wJg$ZBQ8H71w z@#stlG&R*0Usui@*|oOYlsLr^Pc$bN z@v`2gPAden+s(e4hFi)zC1J??GhmEFF%y!uWWI+lzQ^@YV&2a3Xa+Ah*zeJ>bVcU8 z-syL|mal;)2%4{-bsw)cy|Fwle`aQC%vbVp$wpI$vs62YrhfaGq7%?$?&f-j!c2&x z*9D>12CvuZ98#VdcfI_52=H854mgb*1NWo$Uht`VUnx1Bydgj23eVe=kE>-8LDu%&w8Z;+hajAPCGo;z* z#}xP#j_$Ofg@tia(^8XlP1)p*y^wf44fDHJ=sqH;s4n-RI-+l?0^hG{Wv33NIYD3B>y^8iLR@c3M&m{({(+3M*JzpYQZ%$Nc zC|(I#4*XT(s~pGD!CU!=SUoYKG3HPbFJY{oareoyAb8Faf?RW*r5;@D%ADV+YSH~HiKT4l$>t4i=KN84-CdUuL({LhY;Vbym^_s|HySOFm!)UjlVvoNCiDv688e1`@%sYB9E9| z*H7V~k>a@P<36k*={4)LTKgD`*s9$I`hZyfaK#TnSvy}fqH4tqtkMRr>XqEV1V_7< zw##cz&0jSLR{k_T$GGx*&X2zy$Dd17-*le6g_lY7aPE<_H;J_d2D{2>a=sHiq!+Mq z4NhJ1`3VH+)#U~{I$XYf=bnkQs|#qvSp5AF)jRBF#=4n<CAr|qxDv0O7qoP3AnA4;>&@b#(q`hZ0!PD#iw zB%B3@kccFY@Mp3!qHS|`Q$u&1B$IBgZ4t(^sJDmHoB@{Ai@n<%3SmE<^qgU|%mC9< zW14Md}i{4r-)wR=(=2Rd$~(CbuntR=GjT+{ei-%PtU zM^}`WyGXH&2-P{HWrA8_6DrU3?E2keV*qJqAJiju?uwi;>mHGO|5L;}KF|s!I?ILU z?5oiBMbJgI{+m~8k#yS5q!rVs0X0JgijQ{p1-r{lo%HgWLny7L z>OX8;I`}b5Y}c_?DEU>qN}nqRYQj6O%Z?gdNBTrugB zsv}-d8h?%$YFu;AN=0()5Zqoe)MU4FF%;O6Zm+5*j8%LInyJa@!VC*wmy8)(?eCj; zp=u-t5CSN26^FJ}n*JVQOLsSIPj*HTTxq;s=WGp#_?&rwFHtuKru^Ip96Eh*JTB)? zAi@Uqat4GW>gHmqAl6iCDy0E?MB4%^9l?h057b@v!CQMAQ+flI!fxMkTK%wco`Sx2oOO+cy z5a#b;QAwv5RDE z@<@w5{an{p#p%p`fW_Yfr@GSa6fnA1vGU2Xd(2jm)GahS3#!{)2T_BrOi;&DF_*JPb0p63AE{wIDY3?^9h z4W*LuI)hq*a2m%TDyStxFp(%ZNA#E1a<^Fe8lry z8@_{@0XsPkyAzKANtK~9vjALksg-K~e#5g=Z~X4Q`}G9=mF-!l0h%0$uGi|SUH_NIoWUjFv#j9lJPe`XvPpd_Trz*wZ`&6$A71KH z!{0T%j!xpUT%sSOO)zaq(fUF44tPdP+~w$^OHO%L+>38>IqHXrD36TJ0pp6|aRG@h zFmpQ_(!iU?Iyml|36NJ+g*A{zBQvlvZI!9g`ch3Q!@C<%5>zVD87^F2A}AwAg7_PB zW)(r^fn^EcN3FQCw1ww?DJ9%gi&8AuOLQuqh**5}nM7;0K^S%(n&*CuyCFz!RID%2 zDe87T+r+L0whk!0Kl#4;Z}}2^?BzIY52SAP*i`52PDawU?3T=I1#KlIy0*Qoc}X{| z*gArCCG|Q0--d>US{!$vm<_vP%QopjjSgG6M`@(&>*%|$~>5Y2Taf`C)|KZ#5a@h_z%JR6=#-CpGM?#FlKXSJ+ z$X4`dTHak8`DWl}7rfQ^#O(KeDzca32O@s|9A+J?&+#UVH*AlP!%=h$iK?SZVy3?! zKOG0=1UA^uT0Z~1pg__y!MGbqYOr<3sO9(aHj!mb={_ewJvP^36)3$V)|0pla=kb8 zBJC~P=IRwM{=U$VBUHtEKFF^=_x*Wf$t9d+u?f$Pt8y?3($<>f*9G54p>Hi$%!5to z#F3aliEq=7^(9a<{M^WQLiNy9cH?)Q-ugzm1H2mEmdIMkA@*L^yAUZ^SPg_FZ4F)T ztlRnuzefy>xW*`3*9HCw?k3t6-{S3N2h5J^IbHB&{N`YD*9WZM>zoH@vAwv(W0g12 zD1G;01neEukYrR_D26Ov^XCi68qk%=(W2e zf0FpVg>udNtwOm}y@WMeZhW-=4&3|ka%Z#C8*tV6cs)qquss+{0Jvyey1p4>*;@j> za~XIZV0GLt>f($tx423%BXg62}~ zxBcHnIlxO(B7rPEhv?ZIO+BH}SkIaWdhF6+spCJSs0Vt;`Hd|J*m$Md)-NHA-Nu3- z<@}|PQXxRG-{_K%WB{HwEUA=@-~gN zwM>2NNU@Ob`;PY)r>6Ylq50#D2m+^5>?PYV+>h5(Y;%i{a8i|*g3ve%%an_T`R};2 z=HwK(IQJi+b>_uB!YC?}9ybCXnreV*?S?$Gmm1QKO5ReK>aCJboW9y60p7yCg9Lzm z(benyXP+^2!&@qwr&z$^d#j^QOn9}yz`bR5kEQS}p3fmiPS5?>5(vB(zxTOG0#g_i zskD8%P~HLn{e!Lh&l7q>k$8oL2WMu!ac9IbQ;ptJ>Mr=NU0~DD(6qQ5pRyJzTldsu66+JoKnebn#xcz z$AS)9t7`SmK;2;tjK!&0!vml2mT@eK z6C+Hu%0{d9;ws*nvZx=A8UMkNydA&W5Ujy-mvenu0x4uyVau6_QQjQH;;9@BojfVNw7e3V9v)W z_xmLQa8ShOh3FMrm;tz$5NL5xE$+jcOjCxickcmbOu%Y>-WiR^(`Qs3=K!xC35T=z zp2z_nRxF*~p4|kW_LEw??#p1y_x4PY6-BcvE#=BPMBH6nLy&Now?DlJe_r@yWy+*| zWB1`=t;OvO+kUena>>x2h{t}to1wZRNYl_43kV)yxvtN7`wDzLU;!OwIP6|-w9}ds zu$Cj@z|DC#BlsCqA5!l|()pXZfW`oTLpB#oRII zj7;?^#o?DG>ebcCd#UJOY4I|~lii$%VE^%TA(e7GN47!?@K7eWb_~=)v}<%#65RHh zR#^PBQ=dtzTdcq(fo}cLQj4awXJ$@Nb)apVl;xte8nudGgV~)Dq+sUmI-b}gH5Nhv z`CGg-+a+WUgBx(7#Z|Nmqpn2EIwkvizKf-B-_vT zXMp`gX}xX}{B`NJj-hAx`zM3f$$Bn`Pv0UZ_C9Bu*8!c^PwnpSf4KsF2ygnm*mb<# zi~)8+ajtixS$1ExK7DEkCvqiCY~ZaYps$>jtdpAh;`mw6}Rw+8CUD$?vHinASdx?^Oe*%5dVa zl)$o?Iil3Yo-&&wC=JQ0+L8E(uh;J(J$nx1%tV>9Z?#3vsWlq$X9P|B{Yg&pf;X{W zNs@prPs$an%q|?ot==m)JG0tRKegJ&yBFo3>V!TAG;rnQ67v8`r|)-tu6_4e_(bQ_ z4mEXeqpA@dz@H;tbI1MYatUj7 z6Tl66;KmmL+D}s2Z9U5FbD0wQpR0gBBT>ZJQuQ824mbpsX{C9W3Mi}pMAtvc zAA&m0_V>i*Tci60Hk!A?WwmzO^$X^3K-v*m<>+vGq#* znb=VMFQ#3rHCqxDWPVf>?iLX5RIYV5`@3Q|Y`nr4_+2o+Uub6c<_JH+SBV%n`pDMh z&OK!O-NE{H@jWs2SvM866g!Q+I*2lPez2vbyZUfY1WVeq@!MC=p9WUv@+>fGyp?x) ze_iXlSSR%oAQuiui#a(aBT{9TeLR!hmaF(c_6AcT#Ws`Df0^Trg}<6;m0h)B?5?;l z%hAk97cW2d>YRT-s>vC-aI%LzUcd$>2CERv2+Cd7sZNuOJfPFllD!3};l@3v&?jNsSGTsD>PW zFjQSk=;_654Zbo}D%N0X=a^M)%GY+XZK#~oXftHg_Ag|8QGF)Z(U)%DCjYd@zdiYP zhWx~c%2FhsY+NC*Nrm8Uu1%3#)Q2XVJN(zM^}YyfR||}OeXMxSlMo4<&m=jR%d_Bc zM9{dn#H6I`URL5MeQ|d<)1~I@MOWmq`i9C*yJ%7i{qSPGY25Z$Yeh}{%m({fSJ4%s zUyhXEOiH=&foGCtK))Z)X1^*UIB;U!bH;<%b(^mX7Wt^g0bP)EMSE;+ndrunq{bZ2 zJGA+q%u@Xa68`}PXvzO=34D_Zj8XD`o@?=YF?tYO z+`0PZ5eF**^nGcX9PWDAxY`XDc_s7v9Hrh_&@@~SrCwc;f#~~Y7OzrqAr490rgzu0Bob{S|d-EE_sBb;X2g{9@zA?ZX~^eVR+vEWR@(+3UB$9 zV!p-4l32cECWX-s$_1)!sMfB+K!q1__JZjpo!XOT=u$vUF_H@mz9KvoVEphmFB!Un zOH==MLup_r?wDS;wywW|Jg$kkTm)WED{>3K!9LywIlqrfiA&F2I9Oi1d>;K*O(8S{ zDkq0cK3Q;;m2U=SVp4X`Y)o8aFi=PNWJ{ow>AEowA1dTay3F#10wI9#TCL_^09l}& z#Ua^q34L)4wI8T$2ixd#PT{?2VPlS><9XHYwb|bX>Eq6t^ zEVuG2!1r!7A6zf;!r^maW7u~)B~smU_KCx7Tgel3stDK?iq0air0?f<1Xj`=$J1$_ z$Nb56|HJ6d3Q5l3=l}6JAFoH?Nsq4JE8i>c|6#%?L-ls&<7S_`z?)Y%5!R~FX^i#N zivi4L>rc>SwGwDh*I{Q+w;1p;sQ-FkC>X0G>xr%`ApySTzGX-41TB z1YbfeK|}tpL*OystDMi0|ZO@+?N{;@N|KYeO}hK29^A7Fgl)3%K;yU zO!8OppM!m>g<@)KM0x&476Ux~*WC7-Z+K0-1BPz{Zaz04isT78DhW#HDQz#mM~VjekS&|SEZ8SO3P2)d zzVx^nK>qSs>eNMBkt8kKK9MeB<}a+UB$5ufRu-%6p=Mf5jz1 zLZMD+no*CuXYZ_?$LH9ysSIVwq3>RVaB&0(L*ZsnY%ak>W99fe|+z-Gj z=(3x^pAT)>P+x5IBh@_4PIe#CA7q3QH^k|Zf>v@z`kR$~l8&{=nB$VGgcpqIIsZKS z?`6E8d68&Md<4U_$$)rwjH|sv)HQ^(@w?Vi417$YHU-B}F9f**kLKApnWRGcNILoV zvKo1RJ!dtUq2H)5ydS2&?*1- z+vP?ZoYVU@XnwMQWbW?H^YOQtg(BKCos~Oh2NK zbE3Hs*Ho)0%-7^ADZu#;@(H3*oiL-6GyCS35tmR3!BEe_#pzLPHv^`JE(XVw-(Tw4 zxoEG8t`QCZh|BxCNlZ(Yduoo2QvPh47tlb9TUoP!;RLc^Q5ae5omJT(@`~B_3>F!v?=lwQk$TVIk?Cs^z)WoFsin}$ zo4KVG1|Rqi99M8t(x#j|JmICKbmz;p&@3I-P@8}~wKZ5AbK>*VTm#WooSuUG#yyrJOUkQreB# z4k4WT(qyAYJJp?!E`;KfglYVQ6g**QombDa zU(x$~P)kh&<2y&4#yY`mXmC!@VK<@h;irWCgyxGXk*rJ_RSImHXeHuO33LUss5*TK zkPS81Us%N`7*P`>O{uY_9FE8I@_iYma>~1!euc_(Rlic=&Xbzk>)r0DCCEG_K{bTu z)bXqN)<5E~A1g_Wk^^I=;DjMS>adP)P=ceQFLz<#;ZCn$r}4>2lh6O# z-7k8_SUxMnnpHJ8c^vQ(qg*99-cj%j1l=rK%c9jD*clmc*V{sBf3sldor=K3^Z|Vk z(7fQImtV;YZT1Vk<${T-mT6NeW}{ZEqi`dxzK;0~@bf;B9HP++{|>%v)Knk;^_=ML z?INc53gJ8uKezYhoIH&7w|5h17ID293xR{1^41km@^|XUqu(WvoM%U2rfr6+=HKz} z3kgbCg8tL5Zs-9P!`q67F-PCoDRQ&$kmD8a^CDYRX@;HR47n`DS&N)U+9%jA$S!JH z?13W>#27Vga2m%eBi&=4&$NV#uI6ncy3;XnGfJ#IXOIt91lcT6`MqbHfip-Lw=Z0D zt?pg@3k_bw2^I}Y)oc7e`~<<6Q)#QL47MFgSEH zW#;UNo^f=qdhE$9ETC1R-1us<^M7gAe@5-@j{RRa|F62LepOi_Y+q`Kf;tORUv91s`t@~KepU0|*Abt)Dr=sIoC>a zq>kB}PfA0D&8+gVTy!fxgxbG=D+tRuD3R1WV=LI_0naaHX>9mGu}Y$_xCtriI{C~5 z;D?@qaV{-PN!;HrWH`GDGpBGyWD-neoFO%9P7Gma>tp3Vk#@Z1qx}p)*lQ!;12-N+f?2F32`T!_GM(b6~@pyG`m^H_98c;492_ zYKkKDG8Ln$uThBlqwTNipo$1}1_Gbn%{zSUF)Fhi#{j09)k{v`YvcbFbN)+AKh4&} z%PSo@6bajWdl$u67@e(QP`%-DKL@8W7z+{!u9qD@c>3W5i(Y__FVg#}6DKJt>2F$E z52`=-d&k@4Rc&i4LIGX??rA;~o)r%Yyiq;Pbvp->o?&~;{XM4P$1Eh_il!tXRjv>o z*~o^@ED8hsh7cUy)^Yoy5fp;m!)nO;(iiF;Da4GI*%#!QS&19OOr_{%1^#>ZY^AUp zxZjVuW)$-OtL%4vrFRuxp={uSxvrakVXmjgZIiZ98rypxdwIuTxrI?pCCjq zT}Yg;D5PgMVqro~Ly0i37GnOTa#W7=)$$6#sVL7eP)xfOV)m%)2aKQiOM2{4rnMXK zNai2aWWuH1CaWh!VR*%C!AKTAkhS1D7=zbom$#^>h_rD0LR#yz z*ZfElTM^!>DQR@{kG3O^8jI3f#Wdp>+7MeDkwDnViS_vwkmS=~^*ca^XW;!khGTbC z8N9&kYL(*x2_-3BV8X6|NK23+`i`z4UkHVFS&3$wJU_O3H$D$s{v@V#OL^<{BMX{s@UrcWkW~bMG_nOKEQ^=uQ{aO z=5&h6exjG1z){HC!Dbp6UhNmPj7tBhCHg}9FRmTCn~`raxfez%K!KAAhGAfV{)byA|I&O2tm?0FRJSJ=p)&DPAiOsA-m^}WVV5)3 z$3wg3^>cfM)g!rRNf!Ayh2!uiAtTm`?Kif<#kaO z+1Tyq2Ha^D3R384Tl1E-76dYk^9+(cu+^8mfiRW9b9IK})U54H)U2<=Z0S3?(ynKt zR+ngNcwMf83PBvKm2jm_K_|^n{mwc?3bq~5R{*?aPx3?!qSgL7Gw zB&#GLSWzkAaKmKvAnijL=cIgg27M3vL;4f;>5UiRKerpp;^M$5_16r_=5etyEJHQO z%gT+Vk)oqvBCec53@9Y?_yRWeczMR+p7ml5-x5YT|ks*40Fp%<&4hzXi z>7x!Apkl--1U~TLD)oG`6%Us0-`c8asei~7Ve7yEFt&jC2#e>`6kbOSIfHU(msDcRG+2fu|>h!%X~w~l#aZUC(# zA$_Wz6l|O1FJG6x8@VR0hZ**NCNhD+aHzQk)o1SJikk_Ng>63>Ut75}u%}hNIGaDd zH6;g)o6qzXzfNV zA;TUSokIzpQDQN@(u4V=xfpxMfBzQ2e`7bp?q6o+=~o)OsTr>TBx*CYvL!PQCAX4# zdiuY9R|-6g+d0!y*mUatcPTA5di`MEVHosS3sF9f3%ksGH=NaKTlVn05TC+NAB}!z z&IR=-UP>!^Rb+*168ML!u4KnN8X)NzwK!u-1BPbH{Crn-p*t{i9k4%Tk&>S5$8{Rv z?+_*AVu_9qF;i@-d(LY5BfR#j^Np>ApIV5zpUE<%tpT1@($u|cypjx@t7m&?p7C>q zhr#yS2)QU?ATHZ2-9;R+Ms6^{9#50az&Gg0I{ ziOIaEQ0(3B;)qOsVt%XLJ?_1f^H2ED&Xx`-oB4fzZ~>2i`$O-^cr9wzR>Z|L$;!s+)O-pEE93p(EGWU zhLF^)rYxSNxq`3enxfy5`0Zt3E%^A*rU`w0yH%nm3YA@nNR4)oZNqlE}wm$ZX z0Xv29wGAm`No?Y>@b@2svA&G1I7p=c^s7RgBd1L$hp+{p_-k`4c~^W3~77-m%K zi$2f3__Hu^oEasH^cQM)29a9G!y0*&$RH<0S0193YnN1@#vkq~^-^0K*gcrwD>I)c z8x(ByjY&A{w;|-SG{lYI^-W0JcXRQ8MkXDe8)7YZuBUr3{V2(qsJu4z0O}$lGims_ zdXDiDm_UB@kx|d0EG@ z`$1O2z>sQ=_m8%>vUxMA+W+k=Vh{H}-aDD|hSu3&Nl?~z7%5W4qxO3Kr+k@)nX+GbS|> zVLDOMMF zW}gyIbY63uqf$&RsA%6VBuNl z_@&`WM}53>odKP-3Y%`lt!UG!tqDI%dX-?7vls2bN}E57`3#4x70qZ&sqISjAB$;* zpK4`=q1P<@AS;@gFpLy7KfFC1DR|d2l99Vz6NN|(%X*HbRC?^yqiBJ zG;IG>h7=jsex_Z zGGc?$`9CcH3&kuf5GFtX8hu<5^B$AYF{nb!e#~ ze>5Hr0*%RVSoK>ztUDy3{(J8vf0ooRqYdp|b^s=$=jZ3QoK>|?pENj`8$*h`4CR>C zw<5gMwZae~1jZ^xY5D=fGz|=UH&^ukrY&~Z9YS0LT&gipR(jXhT1?GXivBCPAk(q;2LM}U_x3H=NB$7`TA%pw<&Uo@ zE6GuKe69;`93DH|x~&fFF8zOOon=g2UDT})?(XjH4#nkQ#jS8~cZw8>ySqEZ3$(bq z6)RF4TBKNUcZYBDCSP)I?oCdb{^8GFd#^R;n9mq%L=CwOp#^*>yV&bHR$**mrbj8? zV}mc9A!am8kqt){_!yLz<4lo>wFKIdZua;(*@n~Smm$O5Aitz}a^P%(l#otUky2%B z9*)3RqD>|8xx`OEDbKZn$)TZQ@Jsy;X@ieltl8=}+(_#3)&^v;w)Bk%4#Pq5mxFf; z{DDfKf~n6t)KOc6kGH3b>(_Fv0Ewekv*=Dj!++wSI}T%|N@?PU3&)ZQr2=Ry7k9gs z_FCVX22go32PO1j>qS0}Ku}86guaX##F?9$d){rxP3?b5`pV>g9%F1`ZXUwC;D?jw zZRp^|_9MaH9}WQ{cC)WTcDj7uMkWc0TRK#}DgjwS*4tnHFFqgdkh)H+c{5sf^8R{E zGh?S|*<*h_*5gd54!e^N4+OlyS2s3tIRlgdM0VXz&g1(uxEwR z^U}{lW0wk`AIqd|FYpQB z;ZPMbi`-Ngsna6{G!P{ckXcRYQf3v?O+Pk0$6eZ*?F>{FTrx<<{Mqu;8}3xn{sHoxpHv+|YISx*1-oR}J!IH%LNY{~2=QPTAC&g(jJp5V~f zh&r2MN$51r@@_Rg@guphUvm;>d|~|jlkj*(KzoC;LKwZ$cn+Qz!|a9-8xUl-N^#2o zt-I|#+b7L5&9vB~0nAZ%&x?NwBG+@8fLH)4D<}7e40$=+WpR5=3zAL(H2ie;mv#E#XePAFKW3lzuniA_Z-;MP(Qp z_MaF^XJ%y&pXgy%;z@wAraIP0sv?*A;MjWb_~AyeWQqN^F)5Xwr9K+(ENVwXzRg?Z zYkXFDP|Wa|%(@eT^gj=`bLo9rG-+IE{+1ITXqFX~{%hharDtJ_$;nbyW~A$bN6%F8 zQ2fVCog|dHkxgcpdTO^CMAYZ{7h*kjq{&6K${!jR6kY`~YAjS$t87Dj4lU(3rEZSO z)|@Gt?U01`V}_I-O*C|bi1Y^ipD^pI`ILVOL(2r8{P~=EqzKaA3JH}!!zL<`rz*i# z%&B5F3h+Ve@i&KKA+cK%3DRl->%T%gC&tIue+i%dC%?9}30(@MCR(be3jR*rMrpeR z5oUuImOY@Mqz>f^uj&4Nnd(wojybqx8=1<^G;VgN9JN8Bs`a^b61n+p?s>cVxvsW0 zFf9#FLMD+rWa=A`>+3}CvSEiHF8a*mBq|tR@kr09rA$@gYORiIM;j)9;+0dO%!yB| zO4UNM7lCB9HA8Zy?h4tcbA@S{!(xhq9Hnso9L)@X@vFPN2>iNGthX*}40+L07q0|= zwZUSvO0VfIX8*%Hxi~8hp%f^w7u3h0Jb7pQ}s6PGv+aZaaDD`#2MKs z5CoCt7Qv=ViCDquR9&>T7X~x8T!GDWt&lr9H}#ijW_xb`UkbeNESzugFK#La-Nc+0 zJ?NtR=kjFENT%?t~Et_U-thcad3#gi{C8U6iR z@C`))G_0-P9iKVA&D&Lf4AG^xtmY5My{ifEoAQ2`4`^6?+(v6tlny-Ykn=Kp#)US@ zFt)}83woYWb^|QeR`=rxkG_w~A?XN+YFd%@uV_zLMt~a{N(_<)7E_qq*Mf|q`H$tI zGsw15f&rt1%ZkQZv6Yhj2BQ-w*_ZyWee{iE0uUL_2PdD2-_uV5|0?$gG~oMUY-U#k zl;>quzoN^IRS7$%y_0!O=7h;Le$TSv^e=?XH>7lAYsgaQ`9?o_3BSre#@Q0~=?N^c z6QPB#XKlF%vbm#LObFCjy|8NbF=JqQ)j>C;VN-#in|2u3E6a2HMbLMZUEm?9)xdaM zVD+NX?neIPaZ~Y;L_W}07q0w<)WB*!^xp1lGx6isB0NzI$`mf0Z0*jgL%OF2AYf!U zeLwD)9)x(!lmO#{vH8ZDoOGOu#m2|KQ{MQwNQ$60Tj={D^mMy; zeCvj1fMPP=nUQL9-B1o4<$KILJYQeQC-C)H89>Ym%#>t$vedfKL@_PBSQK>vU8JH zMkn0ps*tTP?my0F%1ecY5G=QAX{VTt)Ndc>I{v;X6TP<1H6kRAq(jwjR0abYo6GD| zGNJV^et?D*AKGk(XGK4Xgi50N212+w`avOf4l8!sHfd^R7Ti{40t?4Si>syf4}BaZ zx0lgp`=N~-K>^$!et;1KGri5O)bp#z|B>?7sV4Gu&xjq%;fJI_0Y1Jk1PWhF>&Y*J zGc(xf>FK;!jA3#*psPestFt9eO;1a#j|v|rH#}uZVt2gGI=10~=wkJBF=S^z^( zBJ!`$e};V>9-`M_Q7h*W{JutP0ohG88dd#k==`Q421m~Y*WZpQDP|f8+9B8NVu5$u z(LN__2mx2)8C>E$%Z*GJW~T20RaYIbAwN0y2n_0p-v>Q`KxNY|k; zw|CQ3(kCK1*qah49qRTq49Cllb%=q&WBMJT_cD`C_}#JAzRd~xWSLI#T%1h8$4*HnZ{_D zArQ7a6((4*4@(})7L=M4iYwaDJVD#3{q=W)B|>-oHpOzVj_D?{MP&M=NV$WgzEnjm zTdd%`%BgAgJrtdQQas2RiGlP_S=Ew#zS~zH%1SsCVPoka1ErHxC`H>`Xco<#w96Wx zBR%d!;E&92sFVbwc!p$VeIwN~kR8JolJ(%jbvg;M6ey{Ab{Jtfp#eE+ z$0C$Z(CV@G;_kb(R&k+)hyA`&rACG=K&rMKp< z?hr)3-{E1jBNmtD2TkkYKPHivft1$gJFdAyzH$r=+4u!phHQH_XR7S4OuzDkBNmN( z&`?lN3`jc}Yk_gd`Hzxielf?UGDu(*)7g z*Z(mz1ph8C9%`Oe0Vs8+oLZ*sni6S|mX7(Go12xE{UiXvX5MZ-w(KJnG8HE`cd&O? zyxZ=t!VFqxB1I``E)4Oc-uw4Co|mi2N(tjs$8@^OHifG&l-@RT=CQo6#ArcDrY0rm zT0iT5QoH8BhBnOk5(VK(+SN4ulMdFkJA9uefYr0|z@e2}i6Ap=)mY+utA*P?g$(t+ zZTl3#=}*A^RGFoi|6$|Y!C|vLFBhG#4xN%b+L}4`ILsEr1ekUq5m8#gE9l)j<tU zs)sy)6L8zGp1mJR%}VfhD4vBJND#llvKOL(PE9pc6i(pe^j-KEOj)U_Co&5@-<4>6 z&rCOz8dDu&+q5;J=TFq*OvajMW1(er>xUa7Rd%GiU~aXPnJ9EIguFlR5cqJuv5lUr zq>4-g;}9ekZ@%JvSao;P(i6wwyTJrZbGg?sI=+-|$}^>tE|37-GGEC^5s!Xa0p230SeWZ+K!t8PL@n z934&V?NPdnCg)TsQ5kEi76D!8H%M%ou02i`1`vz^c$*m?A73%7P9{_pU-M~iaP00X zg+Dtd=gz_wr79klI;x_M*oq;7Q&{sy_p1AfM{7{XrG&IhWIbV|mYRII6`xArd0?P^ z&6EymgO!5hRv^o7)pa2^=SHE+#&yQwolX8e7L0Zsv)XzoIV6<794+PAe~*cVO^F2} zvS|q_O6eMzM#5QfYdGbZkNs92GYbB}S@)R-QIZ_Q++9@u&>V5kCRY(;_ zLh^9jvR8}3;IQq_bz|tPWqnRa19ivX28WXJe={D{hKrPrkewGH@Uy=u^S_7BVP)ICM8Di z3iZLY_nQ&t4H$W&up|jg81DlyU30ceoVEbu5PByj zc#zOB>S>%$ySvt3Jb%Pkn10XGn1ZVCb;ptqzx)I25DC`Japh*8c;+C*^M(`Ys&J@m z<=tOrXXo-NemV&eo2oCl)XX5cARb>b&l_i}1UD|Z?}2F1cRy}BGyTv#J5V0CtFkWJ z8(CyIGiV4bEkf@LZwi~U>bP4EQi%rE326hwKWw7SwkK7Uj7FkkYZG3?UEKDLN>0Uc zRKfI7N2zpwrDGk&jD@AB;(UcD$6wfP4g6c5gy=cIYv>jKq_6)`cHmba4GH6jN7EukWy?C;oDGlH_o|LEbWWr$Ny+n;4~H z`FL}s4ao00Cf*c$6QrDn$v$UJ4ks=r2S(}_G?EM%KhGNjaJy0O!GRrSs@Pcb<1?X% zWg_(NBj_AMG!JNR6`4JH?3`oN@5)iC)t0)g4_q>&rvKjixHwyb<=Da>OiMb>-x1a> z_KW`xI3~q9y4@@&EE*7nmi4;sWbK54)#*MBo#bLDh9w~&6xs^C zdPHuT?UfiP29Jw{%c!Yfn02CRtTo%99Z0P>F&`R;C$hMxLVCEYcO=;oIy0zGXIzOQ z;e2dRBKOWko)9Y8#DvgGl5L1$zFGteE>QA3qYBv?f`*t&0@FLM&55nq^#r1x8-Z!% zAONM{Jv~g&RXUV7#ICB_@rIx86(?*4A)E~F*+@5O&1&Tz{stZaF~Hr1fB#Tp=Hi0I z!ou<&iEG>wKR5_>aB?crs3=%IE&_f)OX=cr&I42P+LN4$Jz<6O<}ou0cy@mqoAU7R zsC+8okbjql{`Ok$<_D0Aznmx3wYNibZ^f%hKq!Ga_;i7|8q8cNl0_`$tgL08+Y^>6 ze#5*wWo4WO#l9k~quCKA^Y47>Gved$e@XX&!9{wzUY-Z7*<^K9GJYiF5$ zXlm*t@>~N`OIo9Qv9DoOY-5izIY*@CIwEyx7rwQDB$t?Bhyr&&m59NJ@a;ctO_y}( z3xfv_`+!Dv{ARy|)KuG9<`;XKWb$}|XY01HJX)xC{+s;7w$4^&sncfLV=E->G@u;L z=C1CW)P(d+C^jKX^OV>Qp_0bgqZE75r_D3~!Yo$)giTIpW;^T>S}gZ*kS0MSHc$Ao ziMu zWuY|9dcS#pQm*jBMrvoO^%d<~f&}v>Nldi7Gq7Y4`1sVe&SX1-v*LjkH^H-|Y`Vxs zuKN*{jRfG(2$stwlBesP#J-G;awgN9oe)&bdlP)}zo}`~O{=s}zW0!2I?`#l@k?sE0bW#FUoO<%+*jiQTQU;u8=kml%j2 zZivHqs+V_A%$a(Ee^X+vX$$c3S_C2lx1AN4vdZ>tK^Ht0XT(0t20z!eIror z*S5DuL#o0JJ3OF3Z{%98m>)5P|D7rOlFO9VS3xw5bQ^S?^gr0pfm+M*dS&1tAooto zynq~~oMR+w=5K4r>UkwOJgLa$l&*g22kwgAf8kYnZVe@j;+znC4?oDuQj;itxK59? zgxjw!Yc1F39$xRZS&kldTjh5+?mr&~@l5|hq}OKVDj1VH8L!=5@!F6+MlZxw2jPJ; z92ls%epBjLSEsP54C|sTXzy^xn29koBMjJuvOywMdMe+1MH+N-v2BKr$O6dTfi~w==G}r}!>7ZC-QYM6{TeiF&b!ShRsU0z)|z z4(l^zh9gQKOnFgJqQt#xY~QPC@YC_y3mNb-#wLgxNp!3RVIqev9iv04*czAf0)=bK z{Tv*`i+Oo@LxE>!YGDDJr!ovH3PO%$PD3V+gZJ(tf7?&0s@UW!q<)da!F!ynMAg-C zH4LR$61`O;_4UCM6BFIlzi1WCHXlv;F|qEPLWB z)cG;=6i~O))6)ZE1z09JVE1odt&SRpos%5{Hv2GWHAyN!?FLGuuL&~w(BS^(5}_Y( zUXsm-n}3n_@p-q~ifs4KSFk#$$5%A8 z5r(7`Q>)+w6%yycj+E`bRYtmTdG(4ktn0e*%Lf_V>?LgGL6Zn6+>0jaxTf+a5eAV0 z;O`WHVVF(jGnoBO!&QV*&I~p4sg6{a@$idNS3im)CN7;#3XKsQGVy51#^eMq(uu4b zGMqBd$kHvA)Y+#$4=4#`tUm3@lqt((Ob~BmxL_~#T;XCtQ^Np*I7;ac1Fhc5o6l~G zb$>kA*ab_2s;cmf{O<`crGPydzUjsc%78U<%z$pWNj?;lkc?~)@X2uj^dV4H{LL@A z(XhF{xTs(1)hPosTA=D*?f9I7C`C>uPpJlL(n--}gaNb^fWK9-(8Iss5aL2=?(0h$ zflk&xFaTT6%5ws#CuT`Q2Grcz?(X=oFgV^EWqBrb0K_vNMjsy^&wLos04^zdGsyA_ z2%vlkIU_IoKFu=EC`C6~8^At96Htp2af4QjUFH>7Scho1WrQrcNSCtF#$N| zLqPNjzmA|5N4^}`-q7k?+w}t!p4IaiLCl2U8K(ZI%B-5;aZAh`6L(18=2_ld%#O2ac$p+MCX)_mKD*|*@5JIbL^^TYaPTNoAlw$! z8uIfyx|7hQv?(zyp{j~d{0YdZFh5HpzfEQ>iq)Qxk4eCU+3KpOqa#QAvd^}tokcP^ zb*~$##Vl$wAAYN0XWRL5wJnIi09zd)fy6kJrbZ?p^PL-%?3LYOq@&Wx}M$r~?hFclj$-x@BqIL%QQJ|XvkXJ4- zv3OCRoAvd+5TMk%o3HT?!w|bOSw1wELZoTDcPZ82vNy8L&Ytq`t{(ic+`!7i@v6u) zfljy_m-@uY#xCyC3#YYayBJ5Spp>s)g%7ksK=Zn94E$XnDOla9EdJv5TtwUG(h(O* z?uP%YRPJ{D@1(NHWHn;L7TCaIv=Q_AOrXsJ!enJ%{fsWF#1Kb-p34Q`7i9>Ii7yS$V@W)rreGSggru`fB7%P* z?uv2M#)Nxd5yy69g{Q$pfjkxU1+HPV@}bl=?l<8W6GNHfEbtUKhQh-5jRd;_d3FWr zmK@A&n?k}=J8YV52FmeBWhZRB%@@T7U1EVAy|9o96%EbQ(~}Sf2ZxY^6TDaD%m`(prmbr6sB-{CZtjPs3%-H(L5Bf%G+f2^ODCy}JCm61v8t+Gkz884i*rB%emdZV>`pb0F{M+w(jD;IT)&&`tpzYka9f6gB-l%Eb0)bROKi?s|8}&Y4`o z>7e5yZ1^`(5Z0y=bqZ5GW0-_YJYOOlEvTt^&{MGIQ*WvW{z~DULH+$PI~ity+PxIS zKqv$SM5{}ij|?iY=pD3i2}@UfFW|dYHuykV0LLJZU&d)Nq9!7j@UVaN{?HLI1gmF} zqq}g#QWw@hK*k;uCALg$`*{=}%5dZZBzz|c)|^|;(F8+w=Od22@KRK2HS^G+snp+A z`mhw`pfudG-;z9`awzG8!BjOv$;oZ{)kC&yDh#Qa@wUy*i)9V`JKg^fiA>FT2JL%{ z2i!Oe1_lRlS7oS`VUu~yewb6#9VBdcuQu0G7F$a#`2sEb(Glz02?*@H00&N%nVUPX zx5xOktc>g3yJ+B8R8m$pb#TBfE~Wt%L@vEl7t#*T#AEU2rZ0F;(?<|fUHJZQpn>3} zAB-0-104Sq%&h;qM+5r+=I;eNzOt$(f70P!DBGRSq`jU*OPa|rx?VX|l<{z!e8lEo zsW^*nF2U5a+-$m4@2uf!)&E(@oBj)4f`CgrXGjZ$>;TVw&lf&en_iUbkkt1ZvlkX& z-5HlFwL;@~2c&c{QA@&R;k|A7B=DXEKk$dl(0S5WA_1YmAi zQ$j*?O)TSB?L7Zb8>xROa_2?xlJ?yR`Jm1WgQy?G$u2M~nguf?5gD4rs1su`l=~yr z7kj&r%^8YHiRhIaBWeQ1T#`kPM#Dna@!I)i2A|zPVM^)KUsN??|IzEjIPsQ|az#^r z;4GqNV5qZSWFMcLG5I>$=)G8JahoET=!z#Jz6`f!M@6t6JWf6L# zkUNuPa*$!FA5(6dAXUUBMFWz#Jt~;Pb@B9$AB$@sy)g3FQ4>4(5PicETQp3f8O3mU z$1&ovm7BNw97Gh=n+Z_RI0Sd zks{Q_u(SzcwZ@V#M0-3TPFQOi&;n`Z?O;*vhXFXcteUmLLAfcrdL8V2w_>;Uh4$|z z`Vc2JMS52|Nl;1Mq`oN_D^LWZQ>1W9Eeq4cF=ipI69HdJ+22ns!^|^0?9lZfHSre% zs^>^6#kz!u!ua+@eTOUvv&LuK64?@Qk2{?`iQPmn6T90a`Zw%P6gDDPm_3Iq){h;_ zR+>~JqS%sBk+2$jzEblQ@jO*Omx`pN`A3STZA`4J;C*h6`T)BQ7cjs8WZdTP(uF2O zSR1lY$7r;UU92Fzue~f|fwVuT_OD#olO;6(n*lMgRPi)tda7!EC|`miEUsWeY%HM! zWuHnut8L5jGJGwN$@8?I|HAZUKD<syBa%Y2 z(6EtcxCmT{NJ$xPx_7m5{+laPj{C9-KM|BDK&P&PIG=JG&5{;vvN*l*fgnUW- zOZe-g@OZbMon9YVF}E~F#_SMQ=<2b^fKRG!im&rsJ6F&J z8qoMC-js9^k=Q?f^p5^CAiOQg$VlWps$7?mKsEDUcBc(oWf{4KP}ePG6%~Ac&F`%0 zghG1i27+#Vcg36uorQ zw?iW*2axYOs6fTd@NgL_Pc(U-x&T=QQnfP_U&NzdwZP9R)xZHy8K~G4t=I%l)t;CI z>zA%at$nsR&Zeetj7gbc`oVY%lS(R8n^H}ZSZ*ZLo5;8TI!T*S1~~{<0{Qw6g+2pT z$`TxP0UJNGM2Q{SpHJXPxZ&u!%VpJS1Jhzje3kWX_Pucd>(3akWCfG4>15UkPDxK> zbB8(}j#KXtinQTP3f-&Jile6%#L@K(Ep2j(@tRexV8dAECb*27lCKuJ^GArGe6ssr z#zOc?O2M}!F9~vz*^WhxW4{tj-HF6S9Egm>7b9W6|2Va-78tLh^i-vNOjAr$iq&!6 zY}O+cZ4Lg+(LANt*g>D%#vlx|Im6^WsB3pa0>CEZ*bAJZ<1P*Ak5YiIt)3Dd(ox7k z_VG541+-IY_`+7Fw#@h~QEq$w(0#Z{_84l8Uu`)~BDQEm_bcu%6(?m^)0volFnh1R z-?nk!jt-$A4a8SDW+mcfvDmhfamn?}qKircx=JNjN1u9(8FMdq!He5bK^+Nsz}bCT z{_>lZEK{J8gbWeoyK;-VnQu*DxP>T5Nb)lBU}QKAr;blsAeqE0SMhIw3Ah?1iIIs^ zI_qBxe>W=p{>(>pF-qT(t@Olw9tn>oK##rCoyH}iBz|gGzx|vS4qr+~nnhXe^p&&$ z7c#R?fT3;?b${WXxLvIAe=}-h${Gpnr~N!F3Z)JBgj{5ztgn5@+#UNJM(sM6$7D_& z3Nz8aMK@}rs#982jd6mTqH1dJrl1qyy7~AcStgWd69TGIB+PsfTVJd74D=7p4m)X)vPh(h*<&%cvq^KhF#oc0lfxj5CJMviz9X-b;w*&l9X&DxJ2@Uo}pEml#kcm7yiGl+!5lcrGl;; zi2HSOiIPRCrI+@K+_~JhGD2+nrH7EKlot4*1iymwlpdY!42;r5A7}kWr%!0(pXu
H^|+$#}B|r}(5#GVgXMbeDBqzL=m^X8xM}^fd61^Ol{y?aa2SO8d)Jg)FRsxKTL*Yw4qu1idZLKYt25mg`vEa*TB+xwU3=` zIB&E+FROzL!a-Hvc`Q3j6<<8SKHIbewC=a9hKI*otc}}-`fvh^-3SDuXQHpKFRP|0 z0ox{7Ap+Ee-d&C;?n`v$pFZ*K?G!r}05(@;txXT?s(|y1=I32$dq`&uFtcmbduCK} z%0mA_8ySL))cHF7?(e+`p4^U{+FBuh82!sAuRJ0&-@L940rBA?+HJl!3ele^R;6^O#`6LvNmH_iG$$u5b0> zO7tVtQM}&^R<);FukAtwu_df}Htni7G!mP-{~?ev_%S!Hq67?7_v6}Bb-T6nD=!Tjz!sBfcM3 z85a;M_(TNsnSNLh7EFEc&b!+71u%y)6jhSTZH&s+))rtQWNJj00^vapFBX|%u(xBj zes`{m08e^*d%K_8-)FC@J`qlS(KmzGWHIILf#9=%lRz(Y?Scs-aWd-?P=g-*?IL;W z2)4&E5a7`RsuC8*f-0Af&HVgUb?X`z;Af{o2GvfS75xWQ6bDT~ZC(a>T9;@`pou@JtH@peq9 zC1u{h=JmH<~(Kv0^tbVpwLXC^KNgQjfDk;0(**#P(D9tlbh?P)jApR&@L84F1 zk$<6F9N8LY6*Ylb(x5iH1$f8ER1N-u?5KFgo1K@)_9GQevj!J^6<^161%XM@{O zi`cPzr;Q(D`g^pd5>y-S`1sOLz9NEEFAn`Tbs*|OUjTX6%G$c_ z{Wl0EJA;Zu)IHTcpIzfWZxQbdY@pz)`>RA1I`Gc|u7#AaKZ8Ojuttn4L6%RFUQ??i zG%>0ACxjiO39-~gavvJx;uETMHjn9eq0yYu_MhjYqNYzE^gM44vq=*9GSRWm9peLKNYYGCDXjGV3Sd?()=2uUD?SwVK?d@CqRZgl$ z`y$8jSSlFL1+>Y4jm+%rgb1el{P*an^4@o>z}SL*EIu&eV9R{%@cIoExW0C`7Vt$s z6S34wZ%{%|t*-rR$DnKESlq>jF2tM&mS8P)`61*2pNlaE=T2*u+x2_k^sl}&0ayHA zZ`jv~fNSHe!b$P)a{6gQ`>k=G)AgFy2jNyV?l8b%~)X&RC_qTtUL-feulpNQcm+;AZ<)VQBc1Rq1~ZU zE*(*3q?n@*YLNNc!D3TU7bNzn*xrk1d&a}24^FYcLSy`wSZio(JSKbS!ps93*fB<@ z2i(dH?f*he8IveCUEdzvrwJ+G#80QWlF1j}e>#t*`#u{Y=sw7ze}xcQt^R1>IQ!ak zuLjA#L?A1LD-2Yic(1TKQ>qLJ{9>#Do%dy+>^;fv-~T!$JBXjo&T8+=X=)}DO16jt zvPkOImIzdV!X1#=9&e6+JUxj3s>NeE)P+;i)ZMf<{;Lv78@U%PC7Al}-oqlGf!>^~ z#sH&~LZcdjo1E_PPQd04>}5U$AescsO06 zCCALs59L?~nrWV$Xy7JnlqfYV95qpXdW_oF*&l0BM;|k(_s#Ow`;1X+L?O#pZEEI# zoFH;VXctGt`jPhTIZKGbvX(erv7zCDstOf(*_ z59vKw2fXYG`VS)wsH1(r7rqmJInL3Az?i8+S-@3{NF2K64o}Q+kM!;oHM>fU*3zP- zuu?(H-4 zwPzDU98Fh^_()e_WLE0f9(Xmq}T4x_$b{wBho|S2*F;9HEAJ_0bPz;85pOZT450YH~F%_LzME+yf)rO`}h%!?0g&!)?%l zLpv`dYcwzX@R`$C89ow0twB+}PMRZnLpLIf9xRn}DxL{9SA>|ZE(Ln@5* z%f>jh%1o53_*AQ*g2);&68IX_pM&)vx#=IbT~OkEH^EB=^l;gZQQJ+htEqc!fV~jB z1yowViXiN@CHZxCRF4?$=-WKc+}#O!oc@jb5rJ{r)bB|s0-{N6bCYRLjlvXTmDgoc*V z#K3V%>ZqunT!4a3l?Dxb8#Yclv5%&^)y1*O)QC^ zP|_MMU}PQkh#edaq87OoGM5U6=Q6YpzFn(iHF2&T1D#k)EY+w%bYZ6eFscW!*n>(F z>F^=zhqq&gZingY4QFyTL`H;|wWRR7F2oX?)(3q^&mb=q`)bZ~X9?tinC$eblz89p zt?3WHWVVTfW|Iep9?bM8=mn+8I?jsev0zZdte{6|YyT?M`gRpB^gxeI0^b4v5eho5 z2i|A9Frp#LKlks%tkeL~9pJVZ{vzrFRKWO+D~!`)ZLlWY5`}pjh`p_FJNk52eecQV zI2re5PDmJ3zYO$+AUw)CTj_->mYR8-%e|uE-Om!XYi-vgL5xSr-sJc}$AKn_n7eVc+PnW4FzePH2Z}YS9WMQ8b@s z!+;f-ZFYqU6v$~RcmcP?Zn~XcOf5>{Yy9t-L|k9}BEfh>ursXSQtV=litOuM6$b63 zHmPGHY6}NbGC;bgoG0GbTdk3j>R$C^XcSA zo%#_qV^d}C%2mWIasXrmUhlHV*WVwzvhl+@K%DI_Xf*avz6RHS3@Wv?177LlqDV1_ z<|YTnEWT36R{(ne3W3d=<&VQa5pbF8l2l3z#_~8`3Zs#We@j&f(;-~1Ha&lL?;imx zQnwV36i=PzORuY_KsdSViq(Wl04P* z`(MyfL(H7C)n?`If)ORCgFI>?laOaEx>B>PuGnQob|p8-F#CfD%*^11^LZ)*81Zq*D92Z^wN(#M5(9w`(;8Nl8ZIQicL0SeHpBC zyeYbCdnOHZdO53FHH%z;-D!V+f5ksSs1$m{kR@6Q_DBZ#no8?*U?3DJoUs9ZUz8mb z54T+tbgzR{#c+P+1G38RkBf_Q44X=bkKY_gq7n4HtA&wSLEen2PKb-!NY{7jJKq`x zCUNmnC^<#a&lpaw>qT3MaI%(&orohN+U={0aM8)B5;Yk`tB3n&#d#ekm+^3 ziIHHdfoAuK!9+FFf9hJ&Rot=iHRA5GGK)Bph*70!K!!rf`@1{u=#3#xa=#-KL6-}1 zc`ZsXpzOG?I-eKE2>P6`*25CUQy*pJOVM*%cz4TQ@) zQtrbR1sS3Μ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¬MbW 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:MPU=rg(id`@23{ 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 diff --git a/app/src/main/res/mipmap-xxxhdpi/launcher_icon_round.png b/app/src/main/res/mipmap-xxxhdpi/launcher_icon_round.png deleted file mode 100644 index 4a065977fa64ee5aa68c838092bd9b09af625240..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 34381 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

- #edc23e - \ No newline at end of file + #825000 + diff --git a/app/src/main/res/values/launcher_icon_background.xml b/app/src/main/res/values/launcher_icon_background.xml new file mode 100644 index 00000000..1c62c2e7 --- /dev/null +++ b/app/src/main/res/values/launcher_icon_background.xml @@ -0,0 +1,4 @@ + + + #825000 + diff --git a/build-wsl.sh b/build-wsl.sh new file mode 100644 index 00000000..fc05d675 --- /dev/null +++ b/build-wsl.sh @@ -0,0 +1,89 @@ +#!/bin/bash +set -euo pipefail + +ABI="${1:-armv8}" +BUILD_TYPE="${2:-debug}" + +if [ ! -f "gradlew" ]; then + echo "Error: gradlew not found. Are you in the project root?" >&2 + exit 1 +fi + +chmod +x gradlew +chmod +x native/build-native.sh + +if ! command -v node >/dev/null 2>&1; then + echo "Error: Node.js is not installed in WSL." >&2 + echo "Please install Node.js in WSL using one of the following methods:" >&2 + echo "" >&2 + echo "Option 1: Install via nvm (recommended):" >&2 + echo " curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.0/install.sh | bash" >&2 + echo " source ~/.bashrc" >&2 + echo " nvm install --lts" >&2 + echo "" >&2 + echo "Option 2: Install via apt:" >&2 + echo " curl -fsSL https://deb.nodesource.com/setup_lts.x | sudo -E bash -" >&2 + echo " sudo apt-get install -y nodejs" >&2 + echo "" >&2 + exit 1 +fi + +if ! command -v npm >/dev/null 2>&1; then + echo "Error: npm is not installed in WSL." >&2 + echo "Please install npm (it should come with Node.js)." >&2 + exit 1 +fi + +if ! command -v gcc >/dev/null 2>&1 && ! command -v clang >/dev/null 2>&1; then + echo "Error: No C compiler found in WSL. Required for Rust build scripts." >&2 + echo "Please install build-essential:" >&2 + echo " sudo apt-get update" >&2 + echo " sudo apt-get install -y build-essential" >&2 + exit 1 +fi + +case "$ABI" in + armv8|arm64) + FLAVOR="armv8" + ;; + armv7|arm32) + FLAVOR="armv7" + ;; + all) + FLAVOR="all" + ;; + core) + FLAVOR="core" + ;; + *) + echo "Error: Unknown ABI '$ABI'. Valid options: armv8, armv7, all, core" >&2 + exit 1 + ;; +esac + +case "$BUILD_TYPE" in + debug|Debug|DEBUG) + BUILD_TYPE="Debug" + ;; + release|Release|RELEASE) + BUILD_TYPE="Release" + ;; + *) + echo "Error: Unknown build type '$BUILD_TYPE'. Valid options: debug, release" >&2 + exit 1 + ;; +esac + +TASK="assemble${FLAVOR^}${BUILD_TYPE^}" + +echo "Building $FLAVOR $BUILD_TYPE..." +echo "Clearing configuration cache..." +./gradlew --stop 2>/dev/null || true +rm -rf .gradle/configuration-cache 2>/dev/null || true +echo "Running: ./gradlew --configuration-cache $TASK" + +./gradlew --configuration-cache "$TASK" + +echo "Build completed successfully!" +echo "APK location: app/build/outputs/apk/$FLAVOR/$BUILD_TYPE/" + diff --git a/build.gradle.kts b/build.gradle.kts index 090b6ac9..6af24f72 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -7,7 +7,7 @@ plugins { } // Remove these lines: -// var versionName = "2.1.0" +// var versionName = "1.0.0" // var versionCode = 210 import org.gradle.api.provider.Property @@ -28,14 +28,14 @@ abstract class GetVersionTask : DefaultTask() { } tasks.register("getVersion") { - // Value comes from gradle.properties; falls back to 2.1.0 if not set. - versionName.set(providers.gradleProperty("APP_VERSION_NAME").orElse("2.1.0")) + // Value comes from gradle.properties; falls back to 1.0.0 if not set. + versionName.set(providers.gradleProperty("APP_VERSION_NAME").orElse("1.0.0")) } // You can still set these for legacy use by submodules or scripts: -rootProject.ext.set("appVersionName", providers.gradleProperty("APP_VERSION_NAME").orElse("2.1.0").get()) +rootProject.ext.set("appVersionName", providers.gradleProperty("APP_VERSION_NAME").orElse("1.0.0").get()) rootProject.ext.set("appVersionCode", 210) -rootProject.ext.set("applicationId", "me.rhunk.snapenhance") +rootProject.ext.set("applicationId", "me.eternal.purrfectsnap") rootProject.ext.set( "buildHash", properties["debug_build_hash"] diff --git a/common/build.gradle.kts b/common/build.gradle.kts index e251df48..84543430 100644 --- a/common/build.gradle.kts +++ b/common/build.gradle.kts @@ -8,7 +8,7 @@ plugins { android { namespace = rootProject.ext["applicationId"].toString() + ".common" - compileSdk = 35 + compileSdk = 36 buildFeatures { aidl = true @@ -60,4 +60,3 @@ dependencies { implementation(project(":mapper")) } - diff --git a/common/src/main/aidl/me/rhunk/snapenhance/bridge/AccountStorage.aidl b/common/src/main/aidl/me/eternal/purrfectsnap/bridge/AccountStorage.aidl similarity index 88% rename from common/src/main/aidl/me/rhunk/snapenhance/bridge/AccountStorage.aidl rename to common/src/main/aidl/me/eternal/purrfectsnap/bridge/AccountStorage.aidl index 521ec344..552581e6 100644 --- a/common/src/main/aidl/me/rhunk/snapenhance/bridge/AccountStorage.aidl +++ b/common/src/main/aidl/me/eternal/purrfectsnap/bridge/AccountStorage.aidl @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.bridge; +package me.eternal.purrfectsnap.bridge; interface AccountStorage { diff --git a/common/src/main/aidl/me/rhunk/snapenhance/bridge/BridgeInterface.aidl b/common/src/main/aidl/me/eternal/purrfectsnap/bridge/BridgeInterface.aidl similarity index 72% rename from common/src/main/aidl/me/rhunk/snapenhance/bridge/BridgeInterface.aidl rename to common/src/main/aidl/me/eternal/purrfectsnap/bridge/BridgeInterface.aidl index 8ed330f8..fbc1e377 100644 --- a/common/src/main/aidl/me/rhunk/snapenhance/bridge/BridgeInterface.aidl +++ b/common/src/main/aidl/me/eternal/purrfectsnap/bridge/BridgeInterface.aidl @@ -1,21 +1,22 @@ -package me.rhunk.snapenhance.bridge; +package me.eternal.purrfectsnap.bridge; import java.util.List; -import me.rhunk.snapenhance.bridge.DownloadCallback; -import me.rhunk.snapenhance.bridge.SyncCallback; -import me.rhunk.snapenhance.bridge.scripting.IScripting; -import me.rhunk.snapenhance.bridge.e2ee.E2eeInterface; -import me.rhunk.snapenhance.bridge.logger.LoggerInterface; -import me.rhunk.snapenhance.bridge.logger.TrackerInterface; -import me.rhunk.snapenhance.bridge.ConfigStateListener; -import me.rhunk.snapenhance.bridge.snapclient.MessagingBridge; -import me.rhunk.snapenhance.bridge.AccountStorage; -import me.rhunk.snapenhance.bridge.storage.FileHandleManager; -import me.rhunk.snapenhance.bridge.location.LocationManager; +import me.eternal.purrfectsnap.bridge.DownloadCallback; +import me.eternal.purrfectsnap.bridge.SyncCallback; +import me.eternal.purrfectsnap.bridge.scripting.IScripting; +import me.eternal.purrfectsnap.bridge.e2ee.E2eeInterface; +import me.eternal.purrfectsnap.bridge.logger.LoggerInterface; +import me.eternal.purrfectsnap.bridge.logger.TrackerInterface; +import me.eternal.purrfectsnap.bridge.ConfigStateListener; +import me.eternal.purrfectsnap.bridge.snapclient.MessagingBridge; +import me.eternal.purrfectsnap.bridge.AccountStorage; +import me.eternal.purrfectsnap.bridge.storage.FileHandleManager; +import me.eternal.purrfectsnap.bridge.location.LocationManager; +import me.eternal.purrfectsnap.bridge.task.TaskInterface; interface BridgeInterface { /** - * Get the SnapEnhance APK path (used in LSPatch updater and for auto bridge restart) + * Get the PurrfectSnap APK path (used in LSPatch updater and for auto bridge restart) */ String getApplicationApkPath(); @@ -93,6 +94,8 @@ interface BridgeInterface { LocationManager getLocationManager(); + TaskInterface getTaskInterface(); + oneway void registerMessagingBridge(MessagingBridge bridge); oneway void openOverlay(String type); @@ -102,4 +105,4 @@ interface BridgeInterface { oneway void registerConfigStateListener(in ConfigStateListener listener); @nullable String getDebugProp(String key, @nullable String defaultValue); -} \ No newline at end of file +} diff --git a/common/src/main/aidl/me/rhunk/snapenhance/bridge/ConfigStateListener.aidl b/common/src/main/aidl/me/eternal/purrfectsnap/bridge/ConfigStateListener.aidl similarity index 76% rename from common/src/main/aidl/me/rhunk/snapenhance/bridge/ConfigStateListener.aidl rename to common/src/main/aidl/me/eternal/purrfectsnap/bridge/ConfigStateListener.aidl index 85edf8c9..7465f774 100644 --- a/common/src/main/aidl/me/rhunk/snapenhance/bridge/ConfigStateListener.aidl +++ b/common/src/main/aidl/me/eternal/purrfectsnap/bridge/ConfigStateListener.aidl @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.bridge; +package me.eternal.purrfectsnap.bridge; oneway interface ConfigStateListener { void onConfigChanged(); diff --git a/common/src/main/aidl/me/rhunk/snapenhance/bridge/DownloadCallback.aidl b/common/src/main/aidl/me/eternal/purrfectsnap/bridge/DownloadCallback.aidl similarity index 81% rename from common/src/main/aidl/me/rhunk/snapenhance/bridge/DownloadCallback.aidl rename to common/src/main/aidl/me/eternal/purrfectsnap/bridge/DownloadCallback.aidl index 473a31a4..b3e24899 100644 --- a/common/src/main/aidl/me/rhunk/snapenhance/bridge/DownloadCallback.aidl +++ b/common/src/main/aidl/me/eternal/purrfectsnap/bridge/DownloadCallback.aidl @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.bridge; +package me.eternal.purrfectsnap.bridge; oneway interface DownloadCallback { void onSuccess(String outputPath); diff --git a/common/src/main/aidl/me/rhunk/snapenhance/bridge/SyncCallback.aidl b/common/src/main/aidl/me/eternal/purrfectsnap/bridge/SyncCallback.aidl similarity index 91% rename from common/src/main/aidl/me/rhunk/snapenhance/bridge/SyncCallback.aidl rename to common/src/main/aidl/me/eternal/purrfectsnap/bridge/SyncCallback.aidl index 6326a162..a901ad61 100644 --- a/common/src/main/aidl/me/rhunk/snapenhance/bridge/SyncCallback.aidl +++ b/common/src/main/aidl/me/eternal/purrfectsnap/bridge/SyncCallback.aidl @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.bridge; +package me.eternal.purrfectsnap.bridge; interface SyncCallback { /** diff --git a/common/src/main/aidl/me/rhunk/snapenhance/bridge/e2ee/E2eeInterface.aidl b/common/src/main/aidl/me/eternal/purrfectsnap/bridge/e2ee/E2eeInterface.aidl similarity index 92% rename from common/src/main/aidl/me/rhunk/snapenhance/bridge/e2ee/E2eeInterface.aidl rename to common/src/main/aidl/me/eternal/purrfectsnap/bridge/e2ee/E2eeInterface.aidl index 18fc171a..7fd58ab9 100644 --- a/common/src/main/aidl/me/rhunk/snapenhance/bridge/e2ee/E2eeInterface.aidl +++ b/common/src/main/aidl/me/eternal/purrfectsnap/bridge/e2ee/E2eeInterface.aidl @@ -1,6 +1,6 @@ -package me.rhunk.snapenhance.bridge.e2ee; +package me.eternal.purrfectsnap.bridge.e2ee; -import me.rhunk.snapenhance.bridge.e2ee.EncryptionResult; +import me.eternal.purrfectsnap.bridge.e2ee.EncryptionResult; interface E2eeInterface { /** diff --git a/common/src/main/aidl/me/rhunk/snapenhance/bridge/e2ee/EncryptionResult.aidl b/common/src/main/aidl/me/eternal/purrfectsnap/bridge/e2ee/EncryptionResult.aidl similarity index 60% rename from common/src/main/aidl/me/rhunk/snapenhance/bridge/e2ee/EncryptionResult.aidl rename to common/src/main/aidl/me/eternal/purrfectsnap/bridge/e2ee/EncryptionResult.aidl index 3e9e24b9..62c6e9fa 100644 --- a/common/src/main/aidl/me/rhunk/snapenhance/bridge/e2ee/EncryptionResult.aidl +++ b/common/src/main/aidl/me/eternal/purrfectsnap/bridge/e2ee/EncryptionResult.aidl @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.bridge.e2ee; +package me.eternal.purrfectsnap.bridge.e2ee; parcelable EncryptionResult { byte[] ciphertext; diff --git a/common/src/main/aidl/me/rhunk/snapenhance/bridge/location/FriendLocation.aidl b/common/src/main/aidl/me/eternal/purrfectsnap/bridge/location/FriendLocation.aidl similarity index 84% rename from common/src/main/aidl/me/rhunk/snapenhance/bridge/location/FriendLocation.aidl rename to common/src/main/aidl/me/eternal/purrfectsnap/bridge/location/FriendLocation.aidl index 40076e72..72fd8c7c 100644 --- a/common/src/main/aidl/me/rhunk/snapenhance/bridge/location/FriendLocation.aidl +++ b/common/src/main/aidl/me/eternal/purrfectsnap/bridge/location/FriendLocation.aidl @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.bridge.location; +package me.eternal.purrfectsnap.bridge.location; parcelable FriendLocation { String username; diff --git a/common/src/main/aidl/me/rhunk/snapenhance/bridge/location/LocationCoordinates.aidl b/common/src/main/aidl/me/eternal/purrfectsnap/bridge/location/LocationCoordinates.aidl similarity index 72% rename from common/src/main/aidl/me/rhunk/snapenhance/bridge/location/LocationCoordinates.aidl rename to common/src/main/aidl/me/eternal/purrfectsnap/bridge/location/LocationCoordinates.aidl index aab90195..19fdab9f 100644 --- a/common/src/main/aidl/me/rhunk/snapenhance/bridge/location/LocationCoordinates.aidl +++ b/common/src/main/aidl/me/eternal/purrfectsnap/bridge/location/LocationCoordinates.aidl @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.bridge.location; +package me.eternal.purrfectsnap.bridge.location; parcelable LocationCoordinates { diff --git a/common/src/main/aidl/me/eternal/purrfectsnap/bridge/location/LocationManager.aidl b/common/src/main/aidl/me/eternal/purrfectsnap/bridge/location/LocationManager.aidl new file mode 100644 index 00000000..20966d47 --- /dev/null +++ b/common/src/main/aidl/me/eternal/purrfectsnap/bridge/location/LocationManager.aidl @@ -0,0 +1,7 @@ +package me.eternal.purrfectsnap.bridge.location; + +import me.eternal.purrfectsnap.bridge.location.FriendLocation; + +interface LocationManager { + void provideFriendsLocation(in List friendsLocation); +} \ No newline at end of file diff --git a/common/src/main/aidl/me/rhunk/snapenhance/bridge/logger/BridgeLoggedMessage.aidl b/common/src/main/aidl/me/eternal/purrfectsnap/bridge/logger/BridgeLoggedMessage.aidl similarity index 81% rename from common/src/main/aidl/me/rhunk/snapenhance/bridge/logger/BridgeLoggedMessage.aidl rename to common/src/main/aidl/me/eternal/purrfectsnap/bridge/logger/BridgeLoggedMessage.aidl index 91d1c064..c807c8bb 100644 --- a/common/src/main/aidl/me/rhunk/snapenhance/bridge/logger/BridgeLoggedMessage.aidl +++ b/common/src/main/aidl/me/eternal/purrfectsnap/bridge/logger/BridgeLoggedMessage.aidl @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.bridge.logger; +package me.eternal.purrfectsnap.bridge.logger; parcelable BridgeLoggedMessage { long messageId; diff --git a/common/src/main/aidl/me/rhunk/snapenhance/bridge/logger/LoggedChatEdit.aidl b/common/src/main/aidl/me/eternal/purrfectsnap/bridge/logger/LoggedChatEdit.aidl similarity index 59% rename from common/src/main/aidl/me/rhunk/snapenhance/bridge/logger/LoggedChatEdit.aidl rename to common/src/main/aidl/me/eternal/purrfectsnap/bridge/logger/LoggedChatEdit.aidl index 9abb5d50..6ffff9b2 100644 --- a/common/src/main/aidl/me/rhunk/snapenhance/bridge/logger/LoggedChatEdit.aidl +++ b/common/src/main/aidl/me/eternal/purrfectsnap/bridge/logger/LoggedChatEdit.aidl @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.bridge.logger; +package me.eternal.purrfectsnap.bridge.logger; parcelable LoggedChatEdit { long timestamp; diff --git a/common/src/main/aidl/me/rhunk/snapenhance/bridge/logger/LoggerInterface.aidl b/common/src/main/aidl/me/eternal/purrfectsnap/bridge/logger/LoggerInterface.aidl similarity index 86% rename from common/src/main/aidl/me/rhunk/snapenhance/bridge/logger/LoggerInterface.aidl rename to common/src/main/aidl/me/eternal/purrfectsnap/bridge/logger/LoggerInterface.aidl index f80570c1..f40706d6 100644 --- a/common/src/main/aidl/me/rhunk/snapenhance/bridge/logger/LoggerInterface.aidl +++ b/common/src/main/aidl/me/eternal/purrfectsnap/bridge/logger/LoggerInterface.aidl @@ -1,7 +1,7 @@ -package me.rhunk.snapenhance.bridge.logger; +package me.eternal.purrfectsnap.bridge.logger; -import me.rhunk.snapenhance.bridge.logger.BridgeLoggedMessage; -import me.rhunk.snapenhance.bridge.logger.LoggedChatEdit; +import me.eternal.purrfectsnap.bridge.logger.BridgeLoggedMessage; +import me.eternal.purrfectsnap.bridge.logger.LoggedChatEdit; interface LoggerInterface { /** diff --git a/common/src/main/aidl/me/rhunk/snapenhance/bridge/logger/TrackerInterface.aidl b/common/src/main/aidl/me/eternal/purrfectsnap/bridge/logger/TrackerInterface.aidl similarity index 82% rename from common/src/main/aidl/me/rhunk/snapenhance/bridge/logger/TrackerInterface.aidl rename to common/src/main/aidl/me/eternal/purrfectsnap/bridge/logger/TrackerInterface.aidl index a83af4a9..b66450d0 100644 --- a/common/src/main/aidl/me/rhunk/snapenhance/bridge/logger/TrackerInterface.aidl +++ b/common/src/main/aidl/me/eternal/purrfectsnap/bridge/logger/TrackerInterface.aidl @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.bridge.logger; +package me.eternal.purrfectsnap.bridge.logger; interface TrackerInterface { String getTrackedEvents(String eventType); // returns serialized TrackerEventsResult diff --git a/common/src/main/aidl/me/rhunk/snapenhance/bridge/scripting/AutoReloadListener.aidl b/common/src/main/aidl/me/eternal/purrfectsnap/bridge/scripting/AutoReloadListener.aidl similarity index 55% rename from common/src/main/aidl/me/rhunk/snapenhance/bridge/scripting/AutoReloadListener.aidl rename to common/src/main/aidl/me/eternal/purrfectsnap/bridge/scripting/AutoReloadListener.aidl index 09cdb092..92838e61 100644 --- a/common/src/main/aidl/me/rhunk/snapenhance/bridge/scripting/AutoReloadListener.aidl +++ b/common/src/main/aidl/me/eternal/purrfectsnap/bridge/scripting/AutoReloadListener.aidl @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.bridge.scripting; +package me.eternal.purrfectsnap.bridge.scripting; interface AutoReloadListener { oneway void restartApp(); diff --git a/common/src/main/aidl/me/rhunk/snapenhance/bridge/scripting/IPCListener.aidl b/common/src/main/aidl/me/eternal/purrfectsnap/bridge/scripting/IPCListener.aidl similarity index 56% rename from common/src/main/aidl/me/rhunk/snapenhance/bridge/scripting/IPCListener.aidl rename to common/src/main/aidl/me/eternal/purrfectsnap/bridge/scripting/IPCListener.aidl index b817ff1f..95f363ae 100644 --- a/common/src/main/aidl/me/rhunk/snapenhance/bridge/scripting/IPCListener.aidl +++ b/common/src/main/aidl/me/eternal/purrfectsnap/bridge/scripting/IPCListener.aidl @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.bridge.scripting; +package me.eternal.purrfectsnap.bridge.scripting; interface IPCListener { diff --git a/common/src/main/aidl/me/rhunk/snapenhance/bridge/scripting/IScripting.aidl b/common/src/main/aidl/me/eternal/purrfectsnap/bridge/scripting/IScripting.aidl similarity index 74% rename from common/src/main/aidl/me/rhunk/snapenhance/bridge/scripting/IScripting.aidl rename to common/src/main/aidl/me/eternal/purrfectsnap/bridge/scripting/IScripting.aidl index e2b5c180..3d226170 100644 --- a/common/src/main/aidl/me/rhunk/snapenhance/bridge/scripting/IScripting.aidl +++ b/common/src/main/aidl/me/eternal/purrfectsnap/bridge/scripting/IScripting.aidl @@ -1,7 +1,7 @@ -package me.rhunk.snapenhance.bridge.scripting; +package me.eternal.purrfectsnap.bridge.scripting; -import me.rhunk.snapenhance.bridge.scripting.IPCListener; -import me.rhunk.snapenhance.bridge.scripting.AutoReloadListener; +import me.eternal.purrfectsnap.bridge.scripting.IPCListener; +import me.eternal.purrfectsnap.bridge.scripting.AutoReloadListener; interface IScripting { List getEnabledScripts(); diff --git a/common/src/main/aidl/me/rhunk/snapenhance/bridge/snapclient/MessagingBridge.aidl b/common/src/main/aidl/me/eternal/purrfectsnap/bridge/snapclient/MessagingBridge.aidl similarity index 77% rename from common/src/main/aidl/me/rhunk/snapenhance/bridge/snapclient/MessagingBridge.aidl rename to common/src/main/aidl/me/eternal/purrfectsnap/bridge/snapclient/MessagingBridge.aidl index 32c1573c..6b7a4a58 100644 --- a/common/src/main/aidl/me/rhunk/snapenhance/bridge/snapclient/MessagingBridge.aidl +++ b/common/src/main/aidl/me/eternal/purrfectsnap/bridge/snapclient/MessagingBridge.aidl @@ -1,8 +1,8 @@ -package me.rhunk.snapenhance.bridge.snapclient; +package me.eternal.purrfectsnap.bridge.snapclient; import java.util.List; -import me.rhunk.snapenhance.bridge.snapclient.types.Message; -import me.rhunk.snapenhance.bridge.snapclient.SessionStartListener; +import me.eternal.purrfectsnap.bridge.snapclient.types.Message; +import me.eternal.purrfectsnap.bridge.snapclient.SessionStartListener; interface MessagingBridge { boolean isSessionStarted(); diff --git a/common/src/main/aidl/me/rhunk/snapenhance/bridge/snapclient/SessionStartListener.aidl b/common/src/main/aidl/me/eternal/purrfectsnap/bridge/snapclient/SessionStartListener.aidl similarity index 56% rename from common/src/main/aidl/me/rhunk/snapenhance/bridge/snapclient/SessionStartListener.aidl rename to common/src/main/aidl/me/eternal/purrfectsnap/bridge/snapclient/SessionStartListener.aidl index d0f78e04..02c06239 100644 --- a/common/src/main/aidl/me/rhunk/snapenhance/bridge/snapclient/SessionStartListener.aidl +++ b/common/src/main/aidl/me/eternal/purrfectsnap/bridge/snapclient/SessionStartListener.aidl @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.bridge.snapclient; +package me.eternal.purrfectsnap.bridge.snapclient; oneway interface SessionStartListener { void onConnected(); diff --git a/common/src/main/aidl/me/rhunk/snapenhance/bridge/snapclient/types/Message.aidl b/common/src/main/aidl/me/eternal/purrfectsnap/bridge/snapclient/types/Message.aidl similarity index 77% rename from common/src/main/aidl/me/rhunk/snapenhance/bridge/snapclient/types/Message.aidl rename to common/src/main/aidl/me/eternal/purrfectsnap/bridge/snapclient/types/Message.aidl index b15e6fda..029a3501 100644 --- a/common/src/main/aidl/me/rhunk/snapenhance/bridge/snapclient/types/Message.aidl +++ b/common/src/main/aidl/me/eternal/purrfectsnap/bridge/snapclient/types/Message.aidl @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.bridge.snapclient.types; +package me.eternal.purrfectsnap.bridge.snapclient.types; parcelable Message { String conversationId; diff --git a/common/src/main/aidl/me/rhunk/snapenhance/bridge/storage/FileHandle.aidl b/common/src/main/aidl/me/eternal/purrfectsnap/bridge/storage/FileHandle.aidl similarity index 74% rename from common/src/main/aidl/me/rhunk/snapenhance/bridge/storage/FileHandle.aidl rename to common/src/main/aidl/me/eternal/purrfectsnap/bridge/storage/FileHandle.aidl index 2158b983..2135fec5 100644 --- a/common/src/main/aidl/me/rhunk/snapenhance/bridge/storage/FileHandle.aidl +++ b/common/src/main/aidl/me/eternal/purrfectsnap/bridge/storage/FileHandle.aidl @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.bridge.storage; +package me.eternal.purrfectsnap.bridge.storage; interface FileHandle { boolean exists(); diff --git a/common/src/main/aidl/me/eternal/purrfectsnap/bridge/storage/FileHandleManager.aidl b/common/src/main/aidl/me/eternal/purrfectsnap/bridge/storage/FileHandleManager.aidl new file mode 100644 index 00000000..f504d3d5 --- /dev/null +++ b/common/src/main/aidl/me/eternal/purrfectsnap/bridge/storage/FileHandleManager.aidl @@ -0,0 +1,7 @@ +package me.eternal.purrfectsnap.bridge.storage; + +import me.eternal.purrfectsnap.bridge.storage.FileHandle; + +interface FileHandleManager { + @nullable FileHandle getFileHandle(String scope, String name); +} \ No newline at end of file diff --git a/common/src/main/aidl/me/eternal/purrfectsnap/bridge/task/TaskInterface.aidl b/common/src/main/aidl/me/eternal/purrfectsnap/bridge/task/TaskInterface.aidl new file mode 100644 index 00000000..d3642c76 --- /dev/null +++ b/common/src/main/aidl/me/eternal/purrfectsnap/bridge/task/TaskInterface.aidl @@ -0,0 +1,14 @@ +package me.eternal.purrfectsnap.bridge.task; + +import me.eternal.purrfectsnap.bridge.task.TaskListener; + +interface TaskInterface { + String createTask(String type, String title, String author, String hash); + void updateTaskProgress(String hash, String label, int progress); + void cancelTask(String hash); + void failTask(String hash, String reason); + void successTask(String hash); + void registerTaskListener(String hash, TaskListener listener); + void unregisterTaskListener(String hash, TaskListener listener); +} + diff --git a/common/src/main/aidl/me/eternal/purrfectsnap/bridge/task/TaskListener.aidl b/common/src/main/aidl/me/eternal/purrfectsnap/bridge/task/TaskListener.aidl new file mode 100644 index 00000000..25ed0dd8 --- /dev/null +++ b/common/src/main/aidl/me/eternal/purrfectsnap/bridge/task/TaskListener.aidl @@ -0,0 +1,9 @@ +package me.eternal.purrfectsnap.bridge.task; + +interface TaskListener { + oneway void onProgress(String label, int progress); + oneway void onStateChange(String status); + oneway void onSuccess(); + oneway void onCancel(); +} + diff --git a/common/src/main/aidl/me/rhunk/snapenhance/bridge/location/LocationManager.aidl b/common/src/main/aidl/me/rhunk/snapenhance/bridge/location/LocationManager.aidl deleted file mode 100644 index 715e7265..00000000 --- a/common/src/main/aidl/me/rhunk/snapenhance/bridge/location/LocationManager.aidl +++ /dev/null @@ -1,7 +0,0 @@ -package me.rhunk.snapenhance.bridge.location; - -import me.rhunk.snapenhance.bridge.location.FriendLocation; - -interface LocationManager { - void provideFriendsLocation(in List friendsLocation); -} \ No newline at end of file diff --git a/common/src/main/aidl/me/rhunk/snapenhance/bridge/storage/FileHandleManager.aidl b/common/src/main/aidl/me/rhunk/snapenhance/bridge/storage/FileHandleManager.aidl deleted file mode 100644 index b9a3aa7d..00000000 --- a/common/src/main/aidl/me/rhunk/snapenhance/bridge/storage/FileHandleManager.aidl +++ /dev/null @@ -1,7 +0,0 @@ -package me.rhunk.snapenhance.bridge.storage; - -import me.rhunk.snapenhance.bridge.storage.FileHandle; - -interface FileHandleManager { - @nullable FileHandle getFileHandle(String scope, String name); -} \ No newline at end of file diff --git a/common/src/main/assets/lang/ar.json b/common/src/main/assets/lang/ar.json deleted file mode 100644 index 80b19e6f..00000000 --- a/common/src/main/assets/lang/ar.json +++ /dev/null @@ -1,2022 +0,0 @@ -{ - "setup": { - "dialogs": { - "select_language": "اختار اللغة", - "save_folder": "يتطلب PurrfectSnap أذونات التخزين لتنزيل وحفظ الوسائط من سناب شات.\nالرجاء اختيار الموقع الذي سيتم تنزيل الوسائط إليه.", - "select_save_folder_button": "اختار مجلد" - }, - "mappings": { - "dialog": "جاري إنشاء التعيينات، قد يستغرق هذا بعض الوقت...", - "generate_failure_no_snapchat": "لم يتمكن PurrfectSnap من اكتشاف سناب شات، يرجى محاولة إعادة تثبيت سناب شات.", - "generate_failure": "حدث خطأ أثناء محاولة إنشاء التعيينات، يرجى المحاولة مرة أخرى." - }, - "permissions": { - "dialog": "للمتابعة، يجب عليك تلبية المتطلبات التالية:", - "notification_access": "الوصول إلى الإشعارات", - "battery_optimization": "تحسين البطارية", - "display_over_other_apps": "العرض فوق التطبيقات الأخرى", - "request_button": "طلب" - } - }, - "scopes": { - "friend": "صديق", - "group": "مجموعة" - }, - "manager": { - "routes": { - "tasks": "المهام", - "features": "الميزات", - "manage_rule_feature": "إدارة ميزة القاعدة", - "home": "الرئيسية", - "home_settings": "الإعدادات", - "home_logs": "السجلات", - "logger_history": "سجل المسجل", - "logged_stories": "القصص المسجلة", - "friend_tracker": "متتبع الأصدقاء", - "edit_rule": "تعديل القاعدة", - "file_imports": "استيراد الملفات", - "manage_repos": "إدارة المستودعات", - "social": "اجتماعي", - "manage_scope": "إدارة النطاق", - "messaging_preview": "معاينة", - "scripts": "النصوص البرمجية", - "better_location": "موقع أفضل" - }, - "sections": { - "home": { - "version_title": "v{versionName} · متشعب بواسطة Eternal", - "update_title": "تحديث PurrfectSnap", - "update_content": "الإصدار {version} متوفر!", - "update_button": "تنزيل", - "debug_build_summary_title": "أنت تقوم بتشغيل إصدار تصحيح الأخطاء من PurrfectSnap", - "debug_build_summary_content": "الإصدار {versionName} ({versionCode})", - "debug_build_summary_date": "تاريخ الإنشاء: {date} (قبل {days} أيام)", - "quick_actions_title": "إجراءات سريعة", - "download_icon_description": "تنزيل", - "completed_icon_description": "مكتمل", - "failed_icon_description": "فشل", - "manage_quick_actions_description": "إدارة الإجراءات السريعة", - "quick_actions_icon_description": "إجراءات سريعة", - "add_quick_action_description": "إضافة إجراء سريع" - }, - "home_logs": { - "no_logs_hint": "لا توجد سجلات متاحة", - "clear_logs_button": "مسح السجلات", - "export_logs_button": "تصدير السجلات", - "saving_logs_toast": "جاري حفظ السجلات، قد يستغرق هذا بعض الوقت...", - "saved_logs_success_toast": "تم حفظ السجلات بنجاح", - "saved_logs_failure_toast": "فشل في حفظ السجلات" - }, - "home_settings": { - "actions_title": "الإجراءات", - "message_logger_title": "مسجل الرسائل", - "debug_title": "تصحيح الأخطاء", - "success_toast": "تم!", - "message_logger_summary": "{messageCount} رسالة\n{storyCount} قصة", - "export_button": "تصدير", - "clear_button": "مسح", - "view_logger_history_button": "عرض سجل المسجل", - "updates_title": "التحديثات", - "auto_update_check": "التحقق التلقائي من وجود تحديثات", - "update_check_frequency": "تردد التحقق من التحديثات", - "update_check_frequency_daily": "يوميًا", - "update_check_frequency_weekly": "أسبوعيًا", - "update_check_frequency_monthly": "شهريًا", - "theme_icon_description": "المظهر", - "app_theme_title": "مظهر التطبيق", - "theme_mode_system": "النظام", - "theme_mode_light": "فاتح", - "theme_mode_dark": "داكن", - "ui_settings_title": "إعدادات واجهة المستخدم", - "haptic_feedback_label": "ردود فعل لمسية", - "test_mode_label": "وضع الاختبار (للتصحيح فقط)", - "disable_feature_loading_label": "تعطيل تحميل الميزات", - "disable_auto_mapper_label": "تعطيل الخرائط التلقائي", - "disable_bypass_indicator_label": "تعطيل مؤشر تجاوز الحالة", - "update_notification_channel_name": "تحديثات PurrfectSnap", - "update_notification_channel_description": "إشعارات بتحديثات PurrfectSnap", - "update_notification_title": "تحديث PurrfectSnap متاح", - "update_notification_text": "الإصدار %s متاح الآن.", - "export_database_failed_toast": "فشل تصدير قاعدة البيانات! {message}", - "clear_messages_failed_toast": "فشل مسح الرسائل! {message}", - "clear_file_failed_toast": "فشل مسح الملف! {message}", - "debug_file_config": "التكوين", - "debug_file_mappings": "التعيينات", - "debug_file_message_logger": "مسجل الرسائل", - "debug_file_pinned_best_friend": "أفضل صديق مثبت", - "debug_file_native_sig_cache": "ذاكرة التخزين المؤقت للتوقيع الأصلي" - }, - "tasks": { - "no_tasks": "لا توجد مهام", - "merge_button": "دمج", - "failed_to_open_file": "فشل في فتح الملف", - "merge_files_toast": "دمج {count} ملفات", - "remove_selected_tasks_title": "هل أنت متأكد من أنك تريد إزالة المهام المحددة؟", - "remove_all_tasks_title": "هل أنت متأكد من أنك تريد إزالة جميع المهام؟", - "delete_files_option": "احذف الملفات أيضًا", - "remove_selected_tasks_confirm": "إزالة {count} مهام؟", - "remove_all_tasks_confirm": "إزالة جميع المهام؟", - "clear_tasks_description": "مسح المهام", - "file_not_found_icon_description": "الملف غير موجود", - "image_icon_description": "صورة", - "video_icon_description": "فيديو", - "audio_icon_description": "صوتي", - "file_icon_description": "ملف", - "download_icon_description": "تنزيل", - "chat_action_icon_description": "إجراء المحادثة", - "cancel_icon_description": "إلغاء", - "success_icon_description": "نجاح", - "failure_icon_description": "فشل", - "cancelled_icon_description": "تم الإلغاء", - "task_status_failure": "فشل", - "task_status_cancelled": "تم الإلغاء" - }, - "features": { - "disabled": "معطل", - "export_option": "تصدير", - "import_option": "استيراد", - "reset_option": "إعادة تعيين", - "config_export_success_toast": "تم تصدير التكوين بنجاح", - "config_import_success_toast": "تم استيراد التكوين بنجاح", - "config_import_failure_toast": "فشل استيراد التكوين {error}", - "config_export_failure_toast": "فشل تصدير التكوين {error}", - "saved_config_snackbar": "تم حفظ التكوين", - "older_required": "تتطلب هذه الميزة سناب شات الإصدار {version} أو أقدم للعمل بشكل صحيح", - "newer_required": "تتطلب هذه الميزة سناب شات الإصدار {version} أو أحدث للعمل بشكل صحيح", - "search_button": "بحث" - }, - "manage_rule_feature": { - "disable_state_option": "معطل", - "disable_state_subtext": "لن يتأثر أي أصدقاء/مجموعات", - "whitelist_state_option": "لا أحد باستثناء...", - "whitelist_state_subtext": "سيتأثر فقط {count} من الأصدقاء/المجموعات بهذه القاعدة", - "whitelist_state_button": "تحديد الأصدقاء/المجموعات المسموح بهم", - "blacklist_state_option": "الجميع باستثناء...", - "blacklist_state_subtext": "سيتأثر الجميع باستثناء {count} من الأصدقاء/المجموعات بهذه القاعدة", - "blacklist_state_button": "تحديد الأصدقاء/المجموعات المستبعدين", - "clear_list_button": "مسح قائمة الأصدقاء/المجموعات", - "dialog_clear_confirmation_text": "هل أنت متأكد من أنك تريد مسح القائمة؟" - }, - "social": { - "friends_tab": "الأصدقاء", - "groups_tab": "المجموعات", - "empty_hint": "(فارغ)", - "streaks_expiration_short": "{hours}س" - }, - "manage_scope": { - "logged_stories_button": "إظهار القصص المسجلة", - "e2ee_title": "تشفير من طرف إلى طرف", - "rules_title": "القواعد", - "participants_text": "{count} مشارك", - "not_found": "غير موجود", - "streaks_title": "سلسلة", - "streaks_length_text": "الطول: {length}", - "streaks_expiration_text": "تنتهي في {eta}", - "streaks_expiration_text_expired": "انتهت", - "reminder_button": "ضبط تذكير", - "delete_scope_confirm_dialog_title": "هل أنت متأكد من أنك تريد حذف {scope}؟", - "notes_placeholder": "انقر لإضافة ملاحظة", - "invalid_key_size_32_bytes": "حجم المفتاح غير صالح (يجب أن يكون 32 بايت)", - "successfully_imported_key": "تم استيراد المفتاح بنجاح", - "failed_to_import_key": "فشل استيراد المفتاح: {message}", - "export_base64_button": "تصدير Base64", - "import_base64_button": "استيراد Base64" - }, - "logged_stories": { - "story_failed_to_load": "فشل في تحميل القصة", - "no_stories": "لم يتم العثور على قصص", - "save_from_cache_button": "حفظ من ذاكرة التخزين المؤقت", - "downloaded_to_path": "تم التنزيل إلى {path}", - "download_failed": "فشل التنزيل: {message}", - "posted_at": "نشر في {date}", - "created_at": "تم الإنشاء في {date}", - "failed_to_open_file": "فشل في فتح الملف. تحقق من السجلات لمزيد من المعلومات", - "failed_to_get_file": "فشل في الحصول على الملف" - }, - "messaging_preview": { - "processed_messages_toast": "تمت معالجة {count} رسالة", - "processed_messages_text": "تمت معالجة {count} رسالة", - "close_button_description": "إغلاق", - "bridge_connection_failed": "فشل الاتصال بالجسر. تأكد من أن سناب شات يعمل في الخلفية", - "bridge_init_failed": "فشل تهيئة جسر المراسلة. تأكد من أن سناب شات يعمل في الخلفية", - "message_fetch_failed": "فشل في جلب الرسائل", - "no_message_hint": "لا توجد رسالة", - "save_selection_option": "حفظ التحديد", - "save_all_option": "حفظ الكل", - "unsave_selection_option": "إلغاء حفظ التحديد", - "unsave_all_option": "إلغاء حفظ الكل", - "mark_selection_as_seen_option": "تمييز المحدد كمقروء", - "mark_all_as_seen_option": "تمييز الكل كمقروء", - "delete_selection_option": "حذف التحديد", - "delete_all_option": "حذف الكل" - }, - "logger_history": { - "download_started_toast": "بدأ التنزيل!", - "download_success_toast": "تم التنزيل إلى {path}", - "download_failed_toast": "فشل تنزيل {message}", - "edited_at_text": "{message} (تم التعديل في {date})", - "download_button": "تنزيل", - "select_conversation_placeholder": "تحديد محادثة", - "close_button_description": "إغلاق", - "search_button_description": "بحث", - "list_friend_format": "صديق {name}", - "list_group_format": "مجموعة {name}", - "no_more_messages": "لا مزيد من الرسائل", - "reverse_order_checkbox": "ترتيب عكسي", - "chat_attachment": "مرفق {index}", - "empty_message": "رسالة محادثة فارغة", - "message_parse_failed": "فشل في تحليل الرسالة", - "unknown_sender": "مرسل غير معروف", - "download_attachment_failed_toast": "فشل تنزيل المرفق", - "log_header_format": "{date} - ({type}) {username}" - }, - "file_imports": { - "import_file_button": "استيراد ملف", - "file_not_found": "الملف غير موجود", - "file_import_failed": "فشل استيراد الملف: {error}", - "file_imported": "تم استيراد الملف بنجاح", - "file_delete_failed": "فشل حذف الملف", - "no_files_hint": "هنا يمكنك استيراد الملفات للاستخدام في سناب شات. اضغط على الزر أدناه لاستيراد ملف." - }, - "better_location": { - "spoofed_coordinates_title": "خط العرض {latitude}، خط الطول {longitude}", - "save_coordinates_dialog_title": "حفظ الإحداثيات", - "saved_name_dialog_hint": "الاسم المحفوظ", - "latitude_dialog_hint": "خط العرض", - "longitude_dialog_hint": "خط الطول", - "save_dialog_button": "حفظ", - "choose_location_button": "اختيار الموقع", - "teleport_to_friend_button": "الانتقال الفوري إلى صديق", - "spoof_location_toggle": "تزييف الموقع", - "suspend_location_updates": "تعليق تحديثات الموقع", - "saved_coordinates_title": "الإحداثيات المحفوظة", - "no_saved_coordinates_hint": "لا توجد إحداثيات محفوظة", - "delete_dialog_title": "حذف الإحداثيات المحفوظة", - "delete_dialog_message": "هل أنت متأكد من أنك تريد حذف هذه الإحداثيات المحفوظة؟", - "teleport_to_friend_title": "الانتقال الفوري إلى صديق", - "search_bar": "بحث", - "no_friends_map": "لا يوجد أصدقاء على الخريطة", - "no_friends_found": "لم يتم العثور على أصدقاء", - "edit_location_button_description": "تعديل الموقع", - "add_icon_description": "إضافة", - "edit_icon_description": "تعديل", - "delete_icon_description": "حذف" - } - }, - "dialogs": { - "add_friend": { - "title": "إضافة صديق أو مجموعة", - "search_hint": "بحث", - "fetch_error": "فشل في جلب البيانات", - "category_groups": "المجموعات", - "category_friends": "الأصدقاء", - "participants_text": "{count} مشارك", - "search_icon_description": "بحث" - }, - "scripting_warning": { - "title": "تحذير", - "content": "يتضمن PurrfectSnap أداة برمجة نصية، مما يسمح بتنفيذ التعليمات البرمجية المعرفة من قبل المستخدم على جهازك. توخ الحذر الشديد وقم بتثبيت الوحدات النمطية من مصادر معروفة وموثوقة فقط. قد تشكل الوحدات النمطية غير المصرح بها أو التي لم يتم التحقق منها مخاطر أمنية على نظامك." - }, - "reset_config": { - "title": "إعادة تعيين التكوين", - "content": "هل أنت متأكد من أنك تريد إعادة تعيين التكوين؟", - "success_toast": "تمت إعادة تعيين التكوين بنجاح" - }, - "export_config": { - "title": "تصدير البيانات الحساسة؟", - "content": "هل تريد تصدير التكوين مع البيانات الحساسة؟ (مثل إحداثيات الموقع، وما إلى ذلك)" - }, - "messaging_action": { - "title": "اختر أنواع المحتوى المراد معالجتها", - "select_all_button": "تحديد الكل" - }, - "file_imports": { - "no_files_settings_hint": "لم يتم العثور على ملفات. تأكد من أنك قمت باستيراد الملفات المطلوبة في قسم استيراد الملفات", - "settings_select_file_hint": "تحديد ملف مستورد" - }, - "quick_actions_dialog": { - "title": "تعديل الإجراءات السريعة", - "subtitle": "حدد وحجم إجراءاتك السريعة." - } - }, - "friend_tracker": { - "rules_tab": "القواعد", - "logs_tab": "السجلات", - "export_dialog_title": "تصدير", - "bulk_export_button": "تصدير مجمع", - "individual_export_button": "تصدير فردي", - "invalid_import_type_dialog_title": "نوع استيراد غير صالح", - "invalid_import_type_dialog_text": "الملف المحدد غير متوافق مع نوع الاستيراد هذا. يرجى تحديد نوع الاستيراد الصحيح.", - "import_dialog_title": "استيراد", - "bulk_import_button": "استيراد مجمع", - "individual_import_button": "استيراد فردي", - "import_button_description": "استيراد", - "export_button_description": "تصدير", - "export_button": "تصدير", - "delete_button_description": "حذف", - "delete_button": "حذف", - "catalog_button_description": "كتالوج", - "catalog_button": "كتالوج", - "add_rule_button_description": "إضافة قاعدة", - "add_rule_button": "إضافة قاعدة", - "no_rules_found": "لم يتم العثور على قواعد", - "empty_rule_name": "(فارغ)", - "events_suffix": "أحداث", - "scopes_suffix": "نطاقات", - "select_rule_to_export_title": "تحديد قاعدة للتصدير", - "deleted_logs_toast": "تم حذف {count} سجلات", - "delete_logs_dialog_title": "حذف السجلات؟", - "deleting_logs_dialog_text": "جاري حذف {count} سجلات...", - "delete_logs_dialog_confirm_text": "سيؤدي هذا إلى حذف السجلات بناءً على الفلتر الحالي واستعلام البحث. لا يمكن التراجع عن هذا الإجراء.", - "exported_logs_toast": "تم تصدير السجلات!", - "export_logs_failed_toast": "فشل تصدير السجلات. تحقق من logcat لمزيد من التفاصيل.", - "export_logs_dialog_title": "تصدير السجلات؟", - "exporting_logs_dialog_text": "جاري تصدير السجلات...", - "export_logs_dialog_confirm_text": "سيؤدي هذا إلى تصدير السجلات بناءً على الفلتر الحالي واستعلام البحث.", - "export_as_button": "تصدير كـ {type}", - "filters_title": "الفلاتر", - "search_by_label": "بحث حسب", - "newest_first_label": "الأحدث أولاً", - "since_label": "منذ", - "until_label": "حتى", - "pick_a_date_button": "اختيار تاريخ", - "search_placeholder": "بحث", - "filter_button_description": "فلتر", - "clear_button_description": "مسح", - "no_logs_found": "لم يتم العثور على سجلات", - "log_event_format": "{event} في {conversation}", - "condition_only_inside_conversation": "فقط عندما أكون داخل المحادثة", - "condition_only_outside_conversation": "فقط عندما أكون خارج المحادثة", - "condition_only_when_app_active": "فقط عندما يكون سناب شات نشطًا", - "condition_only_when_app_inactive": "فقط عندما يكون سناب شات غير نشط", - "condition_no_push_notification_when_app_active": "لا يوجد إشعار دفع عندما يكون سناب شات نشطًا", - "add_event_dialog_title": "إضافة حدث", - "event_type_label": "نوع الحدث", - "triggers_title": "المشغلات", - "conditions_title": "الشروط", - "add_button": "إضافة", - "default_rule_name": "قاعدة مخصصة", - "discard_changes_dialog_title": "تجاهل التغييرات؟", - "discard_changes_dialog_text": "لديك تغييرات غير محفوظة. هل أنت متأكد من أنك تريد تجاهلها؟", - "discard_button": "تجاهل", - "cannot_save_rule_dialog_title": "لا يمكن حفظ القاعدة", - "cannot_save_rule_dialog_text": "يجب أن تحتوي القاعدة على حدث واحد على الأقل للحفظ.", - "duplicate_rule_name_dialog_title": "اسم قاعدة مكرر", - "duplicate_rule_name_dialog_text": "توجد قاعدة بهذا الاسم بالفعل. يرجى اختيار اسم مختلف.", - "delete_rule_dialog_title": "حذف القاعدة", - "delete_rule_dialog_text": "هل أنت متأكد من أنك تريد حذف هذه القاعدة؟", - "new_rule_title": "قاعدة جديدة", - "edit_rule_title": "تعديل القاعدة", - "back_button_description": "عودة", - "save_button_description": "حفظ", - "general_section_title": "عام", - "rule_name_label": "اسم القاعدة", - "author_name_label": "اسم المؤلف", - "scope_section_title": "النطاق", - "scope_all": "الكل", - "scope_whitelist": "القائمة البيضاء", - "scope_blacklist": "القائمة السوداء", - "select_friends_groups_button": "تحديد الأصدقاء/المجموعات ({count})", - "events_section_title": "الأحداث", - "add_event_button": "إضافة حدث", - "no_events_text": "لا توجد أحداث" - }, - "friend_tracker_catalog": { - "download_failed": "فشل التنزيل: {code}", - "error": "خطأ: {message}", - "no_repos_added": "لم تتم إضافة أي مستودعات.", - "no_rules_available": "لا توجد قواعد متاحة من أي مستودع.", - "by_author": "بواسطة {author}", - "imported_button": "تم الاستيراد", - "import_button": "استيراد", - "title": "كتالوج متتبع الأصدقاء", - "manage_repos_description": "إدارة المستودعات" - }, - "friend_tracker_export": { - "title": "تصدير القواعد", - "back_button_description": "عودة", - "exported_toast": "تم تصدير قواعد متتبع الأصدقاء!", - "export_failed_toast": "فشل تصدير القواعد: {message}", - "save_button": "حفظ", - "expand_button_description": "توسيع" - }, - "friend_tracker_import": { - "title": "استيراد القواعد", - "back_button_description": "عودة", - "imported_toast": "تم استيراد قواعد متتبع الأصدقاء!", - "import_failed_toast": "فشل استيراد القواعد: {message}", - "confirm_button": "تأكيد", - "expand_button_description": "توسيع" - }, - "friend_tracker_repos": { - "invalid_repo_title": "مستودع غير صالح", - "add_repo_button": "إضافة مستودع", - "add_repo_dialog_title": "إضافة عنوان URL للمستودع", - "repo_url_label": "عنوان URL للمستودع", - "repo_added_toast": "تمت إضافة المستودع بنجاح!", - "invalid_repo_error": "لا يبدو أن هذا مستودع متتبع أصدقاء صالح.", - "add_repo_failed_toast": "فشل إضافة المستودع: {message}", - "add_button": "إضافة", - "no_repos_added": "لم تتم إضافة أي مستودعات", - "remove_button": "إزالة", - "remove_repo_dialog_title": "إزالة المستودع", - "remove_repo_dialog_text": "هل أنت متأكد من أنك تريد إزالة هذا المستودع؟" - }, - "navigation": { - "tracker_tab_label": "المتتبع", - "customize_bottom_bar_title": "تخصيص الشريط السفلي", - "customize_bottom_bar_subtitle": "إعادة ترتيب علامات التبويب أو إضافتها أو إزالتها. بحد أقصى خمس علامات تبويب.", - "shown_tabs_title": "علامات التبويب المعروضة", - "no_tabs_selected_text": "لم يتم تحديد أي علامات تبويب", - "available_tabs_title": "علامات التبويب المتاحة", - "reset_button": "إعادة تعيين", - "done_button": "تم" - }, - "scripting": { - "script_already_installed": "النص البرمجي مثبت بالفعل!", - "downloading_script": "جاري تنزيل النص البرمجي...", - "script_downloaded": "تم تنزيل النص البرمجي {name}!", - "download_script_failed": "فشل تنزيل النص البرمجي. تحقق من السجلات لمزيد من التفاصيل", - "import_script_from_url_title": "استيراد نص برمجي من عنوان URL", - "import_script_warning": "تحذير: يمكن أن تكون النصوص البرمجية المستوردة ضارة بجهازك. استورد فقط النصوص البرمجية من مصادر موثوقة.", - "enter_url_label": "أدخل عنوان URL هنا:", - "script_imported": "تم استيراد النص البرمجي {name}!", - "import_failed": "فشل استيراد النص البرمجي. {message}. تحقق من السجلات لمزيد من التفاصيل", - "import_button": "استيراد", - "update_module_button": "تحديث الوحدة النمطية", - "updating_script": "جاري تحديث النص البرمجي {name}...", - "module_not_found": "الوحدة النمطية غير موجودة", - "updated_script": "تم تحديث {name} إلى الإصدار {version}", - "update_module_failed": "فشل تحديث الوحدة النمطية. تحقق من السجلات لمزيد من التفاصيل", - "edit_module_button": "تعديل الوحدة النمطية", - "open_module_failed": "فشل فتح ملف الوحدة النمطية. تحقق من السجلات لمزيد من التفاصيل", - "clear_module_data_button": "مسح بيانات الوحدة النمطية", - "module_data_cleared": "تم مسح بيانات الوحدة النمطية!", - "clear_module_data_failed": "فشل مسح بيانات الوحدة النمطية. تحقق من السجلات لمزيد من التفاصيل", - "delete_module_button": "حذف الوحدة النمطية", - "deleted_script": "تم حذف النص البرمجي {name}!", - "delete_module_failed": "فشل حذف الوحدة النمطية. تحقق من السجلات لمزيد من التفاصيل", - "actions_title": "الإجراءات", - "no_description": "لا يوجد وصف", - "update_available": "التحديث متاح: {version}", - "actions_button": "الإجراءات", - "loaded_script": "تم تحميل النص البرمجي {name}", - "unloaded_script": "تم إلغاء تحميل النص البرمجي {name}", - "enable_script_failed": "فشل تمكين النص البرمجي. تحقق من السجلات لمزيد من التفاصيل", - "disable_script_failed": "فشل تعطيل النص البرمجي. تحقق من السجلات لمزيد من التفاصيل", - "select_scripts_folder_toast": "الرجاء تحديد مجلد النصوص البرمجية الخاص بك!", - "manage_repos_button": "إدارة المستودعات", - "import_from_url_button": "استيراد من عنوان URL", - "open_scripts_folder_button": "فتح مجلد النصوص البرمجية", - "no_settings_for_module": "لا تحتوي هذه الوحدة النمطية على أي إعدادات", - "installed_scripts_tab": "النصوص البرمجية المثبتة", - "catalog_tab": "الكتالوج", - "no_scripts_folder_selected_title": "لم يتم تحديد مجلد نصوص برمجية", - "select_folder_button": "تحديد مجلد", - "no_scripts_found_title": "لم يتم العثور على نصوص برمجية.", - "use_catalog_to_add_scripts": "استخدم علامة تبويب الكتالوج لإضافة نصوص برمجية!", - "ok_button_timeout": "موافق ({timeout})", - "documentation_button": "التوثيق", - "catalog": { - "script_already_installed": "النص البرمجي مثبت بالفعل!", - "download_failed": "فشل التنزيل: {code}", - "script_downloaded": "تم تنزيل النص البرمجي!", - "could_not_create_file": "لا يمكن إنشاء الملف.", - "no_scripts_folder_selected": "لم يتم تحديد مجلد نصوص برمجية.", - "error": "خطأ: {message}", - "no_repos_added": "لم تتم إضافة أي مستودعات.", - "repo_list_info": "هنا يمكنك العثور على قائمة بالمستودعات: ", - "link_text": "رابط", - "no_scripts_available": "لا توجد نصوص برمجية متاحة من أي مستودع.", - "by_author": "بواسطة {author}", - "version": "الإصدار: {version}", - "installed_button": "مثبت", - "download_button": "تنزيل" - }, - "repos": { - "invalid_repo_title": "مستودع غير صالح", - "add_repo_button": "إضافة مستودع", - "add_repo_dialog_title": "إضافة عنوان URL للمستودع", - "repo_url_label": "عنوان URL للمستودع", - "repo_added_toast": "تمت إضافة المستودع بنجاح!", - "invalid_repo_error": "لا يبدو أن هذا مستودع نصوص برمجية صالح.", - "add_repo_failed_toast": "فشل إضافة المستودع: {message}", - "add_button": "إضافة", - "no_repos_added": "لم تتم إضافة أي مستودعات", - "remove_button": "إزالة", - "remove_repo_dialog_title": "إزالة المستودع", - "remove_repo_dialog_text": "هل أنت متأكد من أنك تريد إزالة هذا المستودع؟" - } - }, - "features": { - "config_import": { - "title": "تأكيد الاستيراد", - "back_button_description": "عودة", - "config_imported_toast": "تم استيراد التكوين!", - "confirm_button": "تأكيد", - "expand_button_description": "توسيع", - "enable_feature": "تمكين الميزة", - "enabled": "ممكّن", - "disabled": "معطل" - }, - "config_export": { - "title": "ملخص التصدير", - "back_button_description": "عودة", - "save_button": "حفظ", - "expand_button_description": "توسيع", - "enable_feature": "تمكين الميزة", - "enabled": "ممكّن", - "disabled": "معطل" - } - }, - "manage_repos": { - "title": "إدارة مستودعات {type}", - "add_repo_button": "إضافة مستودع", - "add_repo_dialog_title": "إضافة عنوان URL للمستودع", - "repo_url_label": "عنوان URL للمستودع", - "repo_added_successfully": "تمت إضافة المستودع بنجاح!", - "add_repo_failed": "فشل إضافة المستودع: {message}", - "add_button": "إضافة", - "no_repos_added": "لم تتم إضافة أي مستودعات", - "remove_button": "إزالة" - } - }, - "rules": { - "toasts": { - "enabled": "{ruleName} ممكّن", - "disabled": "{ruleName} معطل" - }, - "modes": { - "blacklist": "وضع القائمة السوداء", - "whitelist": "وضع القائمة البيضاء" - }, - "properties": { - "auto_download": { - "name": "تنزيل تلقائي", - "description": "تنزيل Snaps تلقائيًا عند عرضها", - "options": { - "blacklist": "استبعاد من التنزيل التلقائي", - "whitelist": "تنزيل تلقائي" - } - }, - "stealth": { - "name": "وضع التخفي", - "description": "يمنع أي شخص من معرفة أنك فتحت Snaps/Chats والمحادثات الخاصة به", - "options": { - "blacklist": "استبعاد من وضع التخفي", - "whitelist": "وضع التخفي" - } - }, - "auto_save": { - "name": "حفظ تلقائي", - "description": "يحفظ رسائل المحادثة عند عرضها", - "options": { - "blacklist": "استبعاد من الحفظ التلقائي", - "whitelist": "حفظ تلقائي" - } - }, - "unsaveable_messages": { - "name": "رسائل غير قابلة للحفظ", - "description": "يمنع حفظ الرسائل في المحادثة من قبل أشخاص آخرين", - "options": { - "blacklist": "استبعاد من الرسائل غير القابلة للحفظ", - "whitelist": "رسائل غير قابلة للحفظ" - } - }, - "auto_open_snaps": { - "name": "فتح Snaps تلقائيًا", - "description": "يفتح Snaps تلقائيًا عند استلامها", - "options": { - "blacklist": "استبعاد من فتح Snaps تلقائيًا", - "whitelist": "فتح Snaps تلقائيًا" - } - }, - "hide_friend_feed": { - "name": "إخفاء من موجز الأصدقاء" - }, - "e2e_encryption": { - "name": "استخدام تشفير E2E" - }, - "pin_conversation": { - "name": "تثبيت المحادثة" - }, - "exclude_message_logger": { - "name": "استبعاد من مسجل الرسائل" - } - } - }, - "actions": { - "clean_snapchat_cache": { - "name": "تنظيف ذاكرة التخزين المؤقت لـ Snapchat", - "description": "ينظف ذاكرة التخزين المؤقت لـ Snapchat" - }, - "manage_friend_list": { - "name": "إدارة قائمة الأصدقاء", - "description": "استيراد/تصدير قائمة أصدقائك عند النسخ الاحتياطي" - }, - "export_chat_messages": { - "name": "تصدير رسائل المحادثة", - "description": "يصدر رسائل المحادثة إلى ملف JSON/HTML/TXT" - }, - "export_memories": { - "name": "تصدير الذكريات", - "description": "يصدر الذكريات إلى ملف ZIP" - }, - "bulk_messaging_action": { - "name": "إجراء المراسلة الجماعية", - "description": "يقوم بعمليات مثل حذف الأصدقاء أو الحذف الجماعي للمحادثات" - }, - "regen_mappings": { - "name": "إعادة إنشاء التعيينات", - "description": "إعادة إنشاء التعيينات يدويًا" - }, - "change_language": { - "name": "تغيير اللغة", - "description": "تغيير لغة PurrfectSnap" - }, - "file_imports": { - "name": "استيراد الملفات", - "description": "استيراد الملفات للاستخدام في Snapchat" - }, - "friend_tracker": { - "name": "متتبع الأصدقاء", - "description": "تتبع أصدقائك على Snapchat" - }, - "logger_history": { - "name": "سجل المسجل", - "description": "عرض محفوظات الرسائل المسجلة" - } - }, - "features": { - "notices": { - "unstable": "⚠️ غير مستقر", - "ban_risk": "⚠️ قد تتسبب هذه الميزة في فرض حظر", - "internal_behavior": "⚠️ قد يؤدي هذا إلى كسر السلوك الداخلي لـ Snapchat" - }, - "properties": { - "downloader": { - "name": "تنزيل", - "description": "تنزيل وسائط Snapchat", - "properties": { - "save_folder": { - "name": "مجلد الحفظ", - "description": "حدد الدليل الذي يجب تنزيل جميع الوسائط إليه" - }, - "auto_download_sources": { - "name": "مصادر التنزيل التلقائي", - "description": "حدد المصادر التي سيتم التنزيل منها تلقائيًا" - }, - "prevent_self_auto_download": { - "name": "منع التنزيل التلقائي الذاتي", - "description": "يمنع تنزيل Snaps الخاصة بك تلقائيًا" - }, - "path_format": { - "name": "تنسيق المسار", - "description": "حدد تنسيق مسار الملف" - }, - "allow_duplicate": { - "name": "السماح بالتكرار", - "description": "يسمح بتنزيل نفس الوسائط عدة مرات" - }, - "merge_overlays": { - "name": "دمج التراكبات", - "description": "يدمج النص والوسائط في Snap في ملف واحد" - }, - "force_image_format": { - "name": "فرض تنسيق الصورة", - "description": "يفرض حفظ الصور بتنسيق محدد" - }, - "force_voice_note_format": { - "name": "فرض تنسيق الملاحظات الصوتية", - "description": "يفرض حفظ الملاحظات الصوتية بتنسيق محدد" - }, - "auto_download_voice_notes": { - "name": "تنزيل الملاحظات الصوتية تلقائيًا", - "description": "يقوم بتنزيل الملاحظات الصوتية تلقائيًا عند تشغيلها" - }, - "download_profile_pictures": { - "name": "تنزيل صور الملف الشخصي", - "description": "يسمح لك بتنزيل صور الملف الشخصي من صفحة الملف الشخصي" - }, - "opera_download_button": { - "name": "زر تنزيل Opera", - "description": "يضيف زر تنزيل في الزاوية العلوية اليمنى عند عرض Snap.\nالضغط لفترة طويلة على الأزرار سيفرض التنزيل" - }, - "download_context_menu": { - "name": "قائمة سياق التنزيل", - "description": "يسمح لك بتنزيل/معاينة الرسائل من محادثة أو قصة باستخدام قائمة السياق.\nالضغط لفترة طويلة على الأزرار سيفرض التنزيل" - }, - "ffmpeg_options": { - "name": "خيارات FFmpeg", - "description": "حدد خيارات FFmpeg إضافية", - "properties": { - "threads": { - "name": "الخيوط", - "description": "عدد الخيوط المراد استخدامها" - }, - "preset": { - "name": "إعداد مسبق", - "description": "اضبط سرعة التحويل" - }, - "constant_rate_factor": { - "name": "عامل المعدل الثابت", - "description": "اضبط عامل المعدل الثابت لمشفر الفيديو\nمن 0 إلى 51 لـ libx264" - }, - "video_bitrate": { - "name": "معدل بت الفيديو", - "description": "اضبط معدل بت الفيديو (كيلوبت في الثانية)" - }, - "audio_bitrate": { - "name": "معدل بت الصوت", - "description": "اضبط معدل بت الصوت (كيلوبت في الثانية)" - }, - "custom_video_codec": { - "name": "برنامج ترميز فيديو مخصص", - "description": "اضبط برنامج ترميز فيديو مخصص (مثل libx264)" - }, - "custom_audio_codec": { - "name": "برنامج ترميز صوتي مخصص", - "description": "اضبط برنامج ترميز صوتي مخصص (مثل AAC)" - } - } - }, - "logging": { - "name": "تسجيل", - "description": "يعرض إشعارات عند تنزيل الوسائط" - }, - "custom_path_format": { - "name": "تنسيق مسار مخصص", - "description": "حدد تنسيق مسار مخصص للوسائط التي تم تنزيلها\n\nالمتغيرات المتاحة:\n - %username%\n - %source%\n - %hash%\n - %date_time%" - } - } - }, - "user_interface": { - "name": "واجهة المستخدم", - "description": "تغيير شكل ومظهر Snapchat", - "properties": { - "enable_app_appearance": { - "name": "تمكين إعدادات مظهر التطبيق", - "description": "يمكّن إعداد مظهر التطبيق المخفي\nقد لا يكون مطلوبًا في إصدارات Snapchat الأحدث" - }, - "friend_feed_message_preview": { - "name": "معاينة رسالة موجز الأصدقاء", - "description": "يعرض معاينة لآخر الرسائل في موجز الأصدقاء", - "properties": { - "amount": { - "name": "الكمية", - "description": "كمية الرسائل المراد معاينتها" - } - } - }, - "snap_preview": { - "name": "معاينة Snap", - "description": "يعرض معاينة صغيرة بجوار Snaps غير المرئية في المحادثة" - }, - "bootstrap_override": { - "name": "تجاوز Bootstrap", - "description": "يتجاوز إعدادات Bootstrap لواجهة المستخدم", - "properties": { - "app_appearance": { - "name": "مظهر التطبيق", - "description": "يضبط مظهر تطبيق ثابتًا" - }, - "home_tab": { - "name": "علامة تبويب الصفحة الرئيسية", - "description": "يتجاوز علامة تبويب بدء التشغيل عند فتح Snapchat" - } - } - }, - "force_amoled_theme": { - "name": "وضع Amoled الداكن", - "description": "يستخدم خلفية سوداء حقيقية للمظهر الداكن" - }, - "map_friend_nametags": { - "name": "علامات أسماء أصدقاء الخريطة المحسنة", - "description": "يحسن علامات أسماء الأصدقاء على Snapmap" - }, - "prevent_message_list_auto_scroll": { - "name": "منع التمرير التلقائي لقائمة الرسائل", - "description": "يمنع قائمة الرسائل من التمرير إلى الأسفل عند إرسال/استلام رسالة" - }, - "streak_expiration_info": { - "name": "إظهار معلومات انتهاء صلاحية السلسلة", - "description": "يعرض مؤقت انتهاء صلاحية السلسلة بجوار عداد السلاسل" - }, - "hide_friend_feed_entry": { - "name": "إخفاء إدخال موجز الأصدقاء", - "description": "يخفي صديقًا معينًا من موجز الأصدقاء\nاستخدم علامة التبويب الاجتماعية لإدارة هذه الميزة" - }, - "hide_streak_restore": { - "name": "إخفاء استعادة السلسلة", - "description": "يخفي زر الاستعادة في موجز الأصدقاء" - }, - "hide_quick_add_suggestions": { - "name": "إخفاء اقتراحات الإضافة السريعة", - "description": "يزيل اقتراحات الأصدقاء للإضافة السريعة" - }, - "hide_story_suggestions": { - "name": "إخفاء اقتراحات القصة", - "description": "يزيل الاقتراحات من صفحة القصص" - }, - "hide_ui_components": { - "name": "إخفاء مكونات واجهة المستخدم", - "description": "حدد مكونات واجهة المستخدم التي سيتم إخفاؤها" - }, - "opera_media_quick_info": { - "name": "معلومات سريعة عن وسائط Opera", - "description": "يعرض معلومات مفيدة عن الوسائط مثل تاريخ الإنشاء في قائمة سياق عارض opera" - }, - "old_bitmoji_selfie": { - "name": "صورة شخصية Bitmoji قديمة", - "description": "يعيد صور Bitmoji الشخصية من إصدارات Snapchat الأقدم" - }, - "disable_spotlight": { - "name": "تعطيل Spotlight", - "description": "يعطل صفحة Spotlight" - }, - "friend_feed_menu_buttons": { - "name": "أزرار قائمة موجز الأصدقاء", - "description": "حدد الأزرار التي سيتم عرضها في قائمة موجز الأصدقاء" - }, - "auto_close_friend_feed_menu": { - "name": "إغلاق قائمة موجز الأصدقاء تلقائيًا", - "description": "يغلق قائمة موجز الأصدقاء تلقائيًا بعد الضغط على زر إعداد" - }, - "vertical_story_viewer": { - "name": "عارض القصص العمودي", - "description": "يمكّن عارض القصص العمودي لجميع القصص" - }, - "enable_friend_feed_menu_bar": { - "name": "شريط قائمة موجز الأصدقاء", - "description": "يمكّن شريط قائمة موجز الأصدقاء الجديد" - }, - "message_indicators": { - "name": "مؤشرات الرسائل", - "description": "يضيف أيقونات مؤشرات محددة إلى الرسائل\nملاحظة: قد لا تكون المؤشرات دقيقة بنسبة 100٪" - }, - "stealth_mode_indicator": { - "name": "مؤشر وضع التخفي", - "description": "يضيف رمزًا تعبيريًا 👻 بجوار المحادثات في وضع التخفي" - }, - "edit_text_override": { - "name": "تجاوز تحرير النص", - "description": "يتجاوز سلوك حقل النص" - }, - "prevent_forced_keyboard": { - "name": "منع لوحة المفاتيح القسرية", - "description": "يمنع Snapchat من إظهار لوحة المفاتيح تلقائيًا عند فتح محادثة" - }, - "settings_menu": { - "name": "قائمة الإعدادات", - "description": "يغير طريقة فتح قائمة PurrfectSnap", - "options": { - "default": "افتراضي", - "legacy": "قديم" - } - } - } - }, - "messaging": { - "name": "المراسلة", - "description": "تغيير طريقة تفاعلك مع الأصدقاء", - "properties": { - "bypass_screenshot_detection": { - "name": "تجاوز اكتشاف لقطة الشاشة", - "description": "يمنع Snapchat من اكتشاف وقت التقاط لقطة شاشة" - }, - "anonymous_story_viewing": { - "name": "مشاهدة القصة المجهولة", - "description": "يمنع أي شخص من معرفة أنك شاهدت قصته" - }, - "prevent_story_rewatch_indicator": { - "name": "منع مؤشر إعادة مشاهدة القصة", - "description": "يمنع أي شخص من معرفة أنك أعدت مشاهدة قصته" - }, - "hide_peek_a_peek": { - "name": "إخفاء نظرة خاطفة", - "description": "يمنع إرسال الإشعارات عند التمرير نصف مرة في المحادثة" - }, - "hide_bitmoji_presence": { - "name": "إخفاء وجود Bitmoji", - "description": "يمنع ظهور Bitmoji الخاص بك أثناء وجودك في المحادثة" - }, - "hide_typing_notifications": { - "name": "إخفاء إشعارات الكتابة", - "description": "يمنع أي شخص من معرفة أنك تكتب رسالة" - }, - "unlimited_snap_view_time": { - "name": "وقت عرض Snap غير محدود", - "description": "يزيل الحد الزمني لعرض Snaps" - }, - "auto_mark_as_read": { - "name": "تمييز تلقائي كمقروء", - "description": "يقوم بتمييز الرسائل/اللقطات تلقائيًا كمقروءة حتى عند تمكين وضع التخفي" - }, - "mark_snap_as_seen_button": { - "name": "زر تمييز Snap كمقروء", - "description": "يضيف زرًا لتمييز Snap كمقروء عند عرضه.\nسيعمل هذا حتى عند تمكين وضع التخفي" - }, - "skip_when_marking_as_seen": { - "name": "تخطي عند التمييز كمقروء", - "description": "يتخطى تلقائيًا إلى Snap التالي عند تمييز Snap كمقروء.\nاستخدمه بالاقتران مع زر تمييز Snap كمقروء" - }, - "loop_media_playback": { - "name": "تشغيل الوسائط المتكرر", - "description": "يكرر تشغيل الوسائط عند عرض Snaps / القصص" - }, - "disable_replay_in_ff": { - "name": "تعطيل إعادة التشغيل في FF", - "description": "يعطل القدرة على إعادة التشغيل بضغطة طويلة من موجز الأصدقاء" - }, - "half_swipe_notifier": { - "name": "منبه التمرير النصفي", - "description": "يخطرك عندما يقوم شخص ما بالتمرير نصف مرة في محادثة", - "properties": { - "min_duration": { - "name": "الحد الأدنى للمدة", - "description": "الحد الأدنى لمدة التمرير النصفي (بالثواني)" - }, - "max_duration": { - "name": "الحد الأقصى للمدة", - "description": "الحد الأقصى لمدة التمرير النصفي (بالثواني)" - } - } - }, - "call_start_confirmation": { - "name": "تأكيد بدء المكالمة", - "description": "يعرض مربع حوار تأكيد عند بدء مكالمة" - }, - "unlimited_conversation_pinning": { - "name": "تثبيت محادثة غير محدود", - "description": "يسمح لك بتثبيت عدد غير محدود من المحادثات محليًا" - }, - "disable_snap_mode_restrictions": { - "name": "تعطيل قيود وضع Snap", - "description": "يسمح لك بمشاهدة Snaps ذاتية التدمير دون قيود" - }, - "prevent_message_sending": { - "name": "منع إرسال الرسائل", - "description": "يمنع إرسال أنواع معينة من الرسائل" - }, - "friend_mutation_notifier": { - "name": "منبه طفرة الصديق", - "description": "يخطرك عند تغيير شيء ما في ملف تعريف الصديق" - }, - "better_notifications": { - "name": "إشعارات أفضل", - "description": "يضيف المزيد من المعلومات في الإشعارات المستلمة", - "properties": { - "group_notifications": { - "name": "إشعارات المجموعة", - "description": "تجميع الإشعارات في إشعار واحد" - }, - "chat_preview": { - "name": "معاينة المحادثة", - "description": "يعرض معاينة للرسائل المستلمة في الإشعار" - }, - "media_preview": { - "name": "معاينة الوسائط", - "description": "يعرض معاينة لأنواع الوسائط المحددة في الإشعار" - }, - "media_caption": { - "name": "تسمية توضيحية للوسائط", - "description": "يعرض التسمية التوضيحية المرفقة للوسائط في الإشعار" - }, - "stacked_media_messages": { - "name": "رسائل الوسائط المكدسة", - "description": "يدمج رسائل وسائط متعددة في إشعار نصي واحد عندما لا يمكن معاينتها. استخدمه بالاقتران مع معاينة المحادثة" - }, - "friend_add_source": { - "name": "مصدر إضافة صديق", - "description": "يعرض مصدر طلب الصداقة في الإشعار" - }, - "reply_button": { - "name": "زر الرد", - "description": "يضيف زر رد إلى الإشعار" - }, - "smart_replies": { - "name": "الردود الذكية", - "description": "يضيف ردودًا مقترحة على الإشعارات (Android 10+). استخدمه بالاقتران مع زر الرد" - }, - "download_button": { - "name": "زر التنزيل", - "description": "يسمح لك بتنزيل الوسائط من الإشعار" - }, - "mark_as_read_button": { - "name": "زر التمييز كمقروء", - "description": "يسمح لك بتمييز رسالة كمقروءة من الإشعار" - }, - "mark_as_read_and_save_in_chat": { - "name": "تمييز كمقروء وحفظ في المحادثة", - "description": "يضيف زر تمييز كمقروء وحفظ في المحادثة إلى الإشعار" - } - } - }, - "notification_blacklist": { - "name": "القائمة السوداء للإشعارات", - "description": "حدد الإشعارات التي يجب حظرها" - }, - "message_logger": { - "name": "مسجل الرسائل", - "description": "يمنع حذف الرسائل", - "properties": { - "keep_my_own_messages": { - "name": "الاحتفاظ برسائلي الخاصة", - "description": "يمنع حذف رسائلك الخاصة" - }, - "auto_purge": { - "name": "تطهير تلقائي", - "description": "يحذف تلقائيًا الرسائل المخزنة مؤقتًا التي يزيد عمرها عن مقدار الوقت المحدد" - }, - "message_filter": { - "name": "مرشح الرسائل", - "description": "حدد الرسائل التي يجب تسجيلها (فارغة لجميع الرسائل)" - }, - "deleted_message_color": { - "name": "لون الرسالة المحذوفة", - "description": "يضبط لون الرسائل المحذوفة" - } - } - }, - "auto_save_messages_in_conversations": { - "name": "حفظ الرسائل تلقائيًا", - "description": "يحفظ تلقائيًا كل رسالة في المحادثات" - }, - "gallery_media_send_override": { - "name": "تجاوز إرسال وسائط المعرض", - "description": "يزيف مصدر الوسائط عند الإرسال من المعرض" - }, - "strip_media_metadata": { - "name": "إزالة بيانات تعريف الوسائط", - "description": "يزيل بيانات تعريف الوسائط قبل إرسالها كرسالة" - }, - "bypass_message_retention_policy": { - "name": "تجاوز سياسة الاحتفاظ بالرسائل", - "description": "يمنع حذف الرسائل بعد عرضها" - }, - "bypass_message_action_restrictions": { - "name": "تجاوز قيود إجراءات الرسائل", - "description": "يسمح لك بالرد على لقطة دون فتحها أو حفظ رسالة غير قابلة للحفظ" - }, - "remove_groups_locked_status": { - "name": "إزالة حالة قفل المجموعات", - "description": "يسمح لك بعرض معلومات المجموعة بعد طردك" - }, - "double_tap_chat_action": { - "name": "إجراء النقر المزدوج على المحادثة", - "description": "يقوم بإجراء مخصص عند النقر المزدوج على رسالة في المحادثة" - }, - "double_tap_chat_action_custom_emoji": { - "name": "رد فعل تعبيري مخصص لإجراء النقر المزدوج على المحادثة", - "description": "يضبط رد فعل تعبيري مخصصًا لإجراء النقر المزدوج على المحادثة" - } - } - }, - "global": { - "name": "عالمي", - "description": "تعديل إعدادات Snapchat العالمية", - "properties": { - "better_location": { - "name": "موقع أفضل", - "description": "يعزز موقع Snapchat", - "properties": { - "spoof_location": { - "name": "تزييف الموقع", - "description": "يزيف موقعك إلى موقع محدد" - }, - "coordinates": { - "name": "الإحداثيات", - "description": "اضبط إحداثيات الموقع المزيف" - }, - "walk_radius": { - "name": "نصف قطر المشي", - "description": "المشي عشوائيًا داخل هذا النصف قطر (قدم)" - }, - "always_update_location": { - "name": "تحديث الموقع دائمًا", - "description": "فرض Snapchat على تحديث الموقع حتى في حالة عدم تلقي بيانات GPS" - }, - "suspend_location_updates": { - "name": "تعليق تحديثات الموقع", - "description": "يمنع تحديث موقعك" - }, - "spoof_battery_level": { - "name": "تزييف مستوى البطارية", - "description": "يزيف مستوى بطارية جهازك على الخريطة\nيجب أن تكون القيمة بين 0 و 100" - }, - "spoof_headphones": { - "name": "تزييف سماعات الرأس", - "description": "يزيف حالة الاستماع إلى الموسيقى على الخريطة" - }, - "show_battery_level": { - "name": "إظهار مستوى البطارية", - "description": "يعرض مستوى بطارية أصدقائك على الخريطة" - } - } - }, - "snapchat_plus": { - "name": "سناب شات بلس", - "description": "يمكّن ميزات Snapchat Plus\nقد لا تعمل بعض الميزات من جانب الخادم" - }, - "media_upload_quality": { - "name": "جودة تحميل الوسائط", - "description": "يتجاوز جودة تحميل الوسائط", - "properties": { - "force_video_upload_source_quality": { - "name": "فرض جودة مصدر تحميل الفيديو", - "description": "يفرض على Snapchat استخدام جودة المصدر عند تحميل مقاطع الفيديو\nيرجى ملاحظة أن هذا قد لا يزيل بيانات التعريف من الوسائط" - }, - "disable_image_compression": { - "name": "تعطيل ضغط الصور", - "description": "يعطل ضغط الصور عند تحميل الوسائط" - }, - "custom_image_upload_format": { - "name": "تنسيق تحميل صورة مخصص", - "description": "يضبط تنسيق تحميل صورة مخصصًا\nحدد تنسيقًا بدون فقدان (مثل PNG) للحصول على أفضل جودة" - } - } - }, - "disable_confirmation_dialogs": { - "name": "تعطيل مربعات حوار التأكيد", - "description": "يؤكد تلقائيًا الإجراءات المحددة" - }, - "auto_updater": { - "name": "محدث تلقائي", - "description": "يتحقق تلقائيًا من وجود تحديثات جديدة" - }, - "disable_metrics": { - "name": "تعطيل المقاييس", - "description": "يحظر إرسال بيانات تحليلية محددة إلى Snapchat" - }, - "disable_story_sections": { - "name": "تعطيل أقسام القصة", - "description": "يزيل الأقسام من صفحة القصص\nقد يتطلب تحديثًا للعمل بشكل صحيح" - }, - "block_ads": { - "name": "حظر الإعلانات", - "description": "يمنع عرض الإعلانات" - }, - "disable_custom_tabs": { - "name": "تعطيل علامات التبويب المخصصة", - "description": "يفتح الروابط في التطبيقات المدعومة بدلاً من متصفح الويب" - }, - "disable_permission_requests": { - "name": "تعطيل طلبات الأذونات", - "description": "يمنع Snapchat من طلب أذونات محددة" - }, - "disable_memories_snap_feed": { - "name": "تعطيل موجز Snap للذكريات", - "description": "يمنع Snapchat من عرض الذكريات الحديثة عند التمرير لأعلى في الكاميرا" - }, - "spotlight_comments_username": { - "name": "اسم مستخدم تعليقات Spotlight", - "description": "يعرض اسم مستخدم المؤلف في تعليقات Spotlight" - }, - "bypass_video_length_restriction": { - "name": "تجاوز قيود طول الفيديو", - "description": "فردي: يرسل مقطع فيديو واحدًا\nتقسيم: تقسيم مقاطع الفيديو بعد التحرير" - }, - "default_video_playback_rate": { - "name": "معدل تشغيل الفيديو الافتراضي", - "description": "يضبط السرعة الافتراضية لتشغيل مقاطع الفيديو\nيجب أن تكون القيمة بين 0.1 و 4.0" - }, - "video_playback_rate_slider": { - "name": "شريط تمرير معدل تشغيل الفيديو", - "description": "يضيف شريط تمرير في قائمة سياق opera لتغيير معدل تشغيل الفيديو\nملاحظة: تنطبق التغييرات فقط على مقاطع الفيديو اللاحقة" - }, - "disable_google_play_dialogs": { - "name": "تعطيل مربعات حوار خدمات Google Play", - "description": "منع عرض مربعات حوار توفر خدمات Google Play" - }, - "default_volume_controls": { - "name": "عناصر التحكم في مستوى الصوت الافتراضية", - "description": "يفرض على Snapchat استخدام عناصر التحكم في مستوى صوت النظام" - }, - "disable_telecom_framework": { - "name": "تعطيل إطار عمل الاتصالات", - "description": "يمنع Snapchat من استخدام إطار عمل Android Telecom\nيتيح لك هذا الاستماع إلى الموسيقى أثناء إجراء مكالمة" - }, - "hide_active_music": { - "name": "إخفاء الموسيقى النشطة", - "description": "يمنع Snapchat من معرفة أنك تستمع إلى الموسيقى\nسيسمح لك هذا بالتقاط لقطات باستخدام أزرار التحكم في مستوى الصوت أثناء الاستماع إلى الموسيقى" - }, - "disable_snap_splitting": { - "name": "تعطيل تقسيم Snap", - "description": "يمنع تقسيم Snaps إلى أجزاء متعددة\nستتحول الصور التي ترسلها إلى مقاطع فيديو" - } - } - }, - "rules": { - "name": "القواعد", - "description": "إدارة الميزات التلقائية للأشخاص الفرديين" - }, - "camera": { - "name": "الكاميرا", - "description": "اضبط الإعدادات الصحيحة للحصول على لقطة مثالية", - "properties": { - "disable_cameras": { - "name": "تعطيل الكاميرات", - "description": "يمنع Snapchat من استخدام الكاميرات المحددة" - }, - "black_photos": { - "name": "صور سوداء", - "description": "يستبدل الصور الملتقطة بخلفية سوداء\nلا تتأثر مقاطع الفيديو" - }, - "immersive_camera_preview": { - "name": "معاينة غامرة", - "description": "يمنع Snapchat من اقتصاص معاينة الكاميرا\nقد يتسبب هذا في وميض الكاميرا على بعض الأجهزة" - }, - "override_front_resolution": { - "name": "تجاوز الدقة الأمامية", - "description": "يتجاوز دقة الكاميرا للكاميرا الأمامية" - }, - "override_back_resolution": { - "name": "تجاوز الدقة الخلفية", - "description": "يتجاوز دقة الكاميرا للكاميرا الخلفية" - }, - "custom_resolution": { - "name": "دقة مخصصة", - "description": "يضبط دقة كاميرا مخصصة، العرض × الارتفاع (على سبيل المثال 1920 × 1080).\nيجب أن تكون الدقة المخصصة مدعومة من جهازك" - }, - "front_custom_frame_rate": { - "name": "معدل إطارات مخصص أمامي", - "description": "يتجاوز معدل إطارات الكاميرا الأمامية" - }, - "back_custom_frame_rate": { - "name": "معدل إطارات مخصص خلفي", - "description": "يتجاوز معدل إطارات الكاميرا الخلفية" - }, - "force_camera_source_encoding": { - "name": "فرض ترميز مصدر الكاميرا", - "description": "يفرض ترميز مصدر الكاميرا" - }, - "startup_default_camera": { - "name": "كاميرا بدء التشغيل الافتراضية", - "description": "يضبط الكاميرا الافتراضية عند فتح Snapchat" - }, - "hevc_recording": { - "name": "تسجيل HEVC", - "description": "يستخدم برنامج ترميز HEVC (H.265) لتسجيل الفيديو" - } - } - }, - "streaks_reminder": { - "name": "تذكير بالسلاسل", - "description": "يخطرك بشكل دوري بسلاسلكم", - "properties": { - "interval": { - "name": "الفاصل الزمني", - "description": "الفاصل الزمني بين كل تذكير (ساعات)" - }, - "remaining_hours": { - "name": "الوقت المتبقي", - "description": "مقدار الوقت المتبقي قبل عرض الإشعار (ساعات)" - }, - "group_notifications": { - "name": "إشعارات المجموعة", - "description": "تجميع الإشعارات في إشعار واحد" - } - } - }, - "experimental": { - "name": "تجريبي", - "description": "ميزات تجريبية", - "properties": { - "native_hooks": { - "name": "خطافات أصلية", - "description": "ميزات غير آمنة تتصل بالرمز الأصلي لـ Snapchat", - "properties": { - "composer_hooks": { - "name": "خطافات Composer", - "description": "يحقن التعليمات البرمجية في إطار عمل واجهة المستخدم عبر الأنظمة الأساسية Composer", - "properties": { - "show_first_created_username": { - "name": "إظهار أول اسم مستخدم تم إنشاؤه", - "description": "يعرض أول اسم مستخدم تم إنشاؤه بجوار اسم المستخدم الحالي في صفحة الملف الشخصي" - }, - "bypass_camera_roll_limit": { - "name": "تجاوز حد لفة الكاميرا", - "description": "يزيد الحد الأقصى لمقدار الوسائط التي يمكنك إرسالها من لفة الكاميرا" - }, - "custom_self_destruct_snap_delay": { - "name": "تأخير Snap ذاتي التدمير مخصص", - "description": "يعطي المزيد من الخيارات لمؤقت التدمير الذاتي عند إرسال Snap" - }, - "composer_console": { - "name": "وحدة تحكم Composer", - "description": "يسمح لك بتنفيذ رمز JavaScript في Composer (arm64 فقط)" - }, - "composer_logs": { - "name": "سجلات Composer", - "description": "يعيد توجيه سجلات وحدة التحكم الخاصة بـ Composer إلى PurrfectSnap" - } - } - }, - "disable_bitmoji": { - "name": "تعطيل Bitmoji", - "description": "يعطل Bitmoji لملف تعريف الأصدقاء" - }, - "custom_emoji_font": { - "name": "خط رموز تعبيرية مخصص", - "description": "يسمح لك باستخدام خط رموز تعبيرية مخصص. يعمل فقط مع خطوط .ttf" - }, - "custom_shared_library": { - "name": "مكتبة مشتركة مخصصة", - "description": "يقوم بتحميل مكتبة مشتركة مخصصة في Snapchat. هذه الميزة مخصصة للاختبار فقط" - } - } - }, - "spoof": { - "name": "تزييف", - "description": "تزييف معلومات مختلفة عنك", - "properties": { - "play_store_installer_package_name": { - "name": "اسم حزمة مثبت متجر Play", - "description": "يتجاوز اسم حزمة المثبت إلى com.android.vending" - }, - "remove_vpn_transport_flag": { - "name": "إزالة علامة نقل VPN", - "description": "يمنع Snapchat من اكتشاف شبكات VPN" - }, - "remove_mock_location_flag": { - "name": "إزالة علامة الموقع الوهمي", - "description": "يمنع Snapchat من اكتشاف الموقع الوهمي" - } - } - }, - "convert_message_locally": { - "name": "تحويل الرسالة محليًا", - "description": "يحول اللقطات إلى وسائط خارجية للمحادثة محليًا. يظهر هذا في قائمة سياق تنزيل المحادثة" - }, - "media_file_picker": { - "name": "منتقي ملفات الوسائط", - "description": "يسمح لك باختيار أي ملف فيديو/صوت من المعرض" - }, - "story_logger": { - "name": "مسجل القصة", - "description": "يوفر تاريخًا لقصص الأصدقاء" - }, - "call_recorder": { - "name": "مسجل المكالمات", - "description": "يسجل المكالمات الصوتية تلقائيًا" - }, - "account_switcher": { - "name": "مبدل الحسابات", - "description": "يسمح لك بالتبديل بين الحسابات دون تسجيل الخروج\nاضغط لفترة طويلة على أيقونة البحث بجوار ملف تعريف Bitmoji لفتح القائمة\nملاحظة: هذه الميزة تجريبية ومن المحتمل أن تتغير في المستقبل", - "properties": { - "auto_backup_current_account": { - "name": "النسخ الاحتياطي التلقائي للحساب الحالي", - "description": "يقوم تلقائيًا بنسخ احتياطي للحساب الحالي عند تسجيل الخروج أو تبديل الحسابات" - } - } - }, - "better_transcript": { - "name": "نسخة أفضل", - "description": "يحسن نسخة الملاحظات الصوتية", - "properties": { - "force_transcription": { - "name": "فرض نسخ الملاحظات الصوتية", - "description": "يسمح بنسخ جميع الملاحظات الصوتية" - }, - "preferred_transcription_lang": { - "name": "لغة النسخ المفضلة", - "description": "اللغة المفضلة لنسخة الملاحظات الصوتية (على سبيل المثال EN ، ES ، FR)" - }, - "notification_transcript": { - "name": "نسخة الإشعار", - "description": "ينسخ الملاحظات الصوتية في الإشعارات\nتتطلب هذه الميزة تمكين ميزة معاينة المحادثة في إشعارات أفضل" - } - } - }, - "voice_note_auto_play": { - "name": "تشغيل الملاحظات الصوتية تلقائيًا", - "description": "يقوم بتشغيل الملاحظة الصوتية التالية تلقائيًا بعد انتهاء الملاحظة الحالية" - }, - "friend_notes": { - "name": "ملاحظات الأصدقاء", - "description": "يسمح لك بإضافة ملاحظات إلى ملفات تعريف الأصدقاء" - }, - "cof_experiments": { - "name": "تجارب COF", - "description": "يمكّن ميزات Snapchat غير الصادرة/التجريبية" - }, - "context_menu_fix": { - "name": "إصلاح قائمة السياق", - "description": "محاولة إصلاح قائمة موجز الأصدقاء حيث لا يمكن عرضها بشكل صحيح عندما يكون الجهاز غير متصل بالإنترنت" - }, - "app_lock": { - "name": "قفل التطبيق", - "description": "يمنع الوصول إلى Snapchat بدون رمز مرور", - "properties": { - "lock_on_resume": { - "name": "قفل عند الاستئناف", - "description": "يقفل التطبيق عند إعادة فتحه" - } - } - }, - "infinite_story_boost": { - "name": "تعزيز القصة اللانهائي", - "description": "تجاوز تأخير حد تعزيز القصة" - }, - "meo_passcode_bypass": { - "name": "تجاوز رمز مرور My Eyes Only", - "description": "تجاوز رمز مرور My Eyes Only\nسيعمل هذا فقط إذا تم إدخال رمز المرور بشكل صحيح من قبل" - }, - "no_friend_score_delay": { - "name": "لا يوجد تأخير في نقاط الصداقة", - "description": "يزيل التأخير عند عرض نقاط الصداقة" - }, - "best_friend_pinning": { - "name": "تثبيت أفضل صديق", - "description": "يسمح لك بتثبيت صديق كأفضل صديق لك رقم واحد. ملاحظة: يمكنك فقط رؤية أفضل صديق مثبت لديك" - }, - "e2ee": { - "name": "تشفير من طرف إلى طرف", - "description": "يشفر رسائلك باستخدام AES باستخدام مفتاح سري مشترك\nتأكد من حفظ مفتاحك في مكان آمن!", - "properties": { - "encrypted_message_indicator": { - "name": "مؤشر الرسائل المشفرة", - "description": "يضيف رمزًا تعبيريًا 🔒 بجوار الرسائل المشفرة" - }, - "force_message_encryption": { - "name": "فرض تشفير الرسائل", - "description": "يمنع إرسال رسائل مشفرة إلى الأشخاص الذين ليس لديهم تشفير من طرف إلى طرف ممكّن فقط عند تحديد محادثات متعددة" - } - } - }, - "add_friend_source_spoof": { - "name": "تزييف مصدر إضافة صديق", - "description": "يزيف مصدر طلب صداقة" - }, - "hidden_snapchat_plus_features": { - "name": "ميزات Snapchat Plus المخفية", - "description": "يمكّن ميزات Snapchat Plus غير الصادرة/التجريبية\nقد لا يعمل على إصدارات Snapchat الأقدم" - }, - "custom_streaks_expiration_format": { - "name": "تنسيق انتهاء صلاحية السلاسل المخصص", - "description": "يخصص تنسيق انتهاء صلاحية السلاسل\n\nالمتغيرات المتاحة:\n - %c: عدد السلاسل\n - %e: رمز الساعة الرملية\n - %d: أيام\n - %h: ساعات\n - %m: دقائق\n - %s: ثوانٍ\n - %w: الوقت المتبقي" - }, - "prevent_forced_logout": { - "name": "منع تسجيل الخروج القسري", - "description": "يمنع Snapchat من تسجيل خروجك عند تسجيل الدخول على جهاز آخر" - }, - "snapscore_changes": { - "name": "تغييرات Snapscore", - "description": "يتتبع التغييرات في Snapscore للأصدقاء\nاستخدم هذه الميزة في الإصدارات الأحدث من Snapchat فقط" - } - } - }, - "scripting": { - "name": "البرمجة النصية", - "description": "قم بتشغيل نصوص برمجية مخصصة لتوسيع PurrfectSnap", - "properties": { - "developer_mode": { - "name": "وضع المطور", - "description": "يعرض معلومات التصحيح على واجهة مستخدم Snapchat" - }, - "module_folder": { - "name": "مجلد الوحدة النمطية", - "description": "المجلد الذي توجد به النصوص البرمجية" - }, - "auto_reload": { - "name": "إعادة تحميل تلقائي", - "description": "يعيد تحميل النصوص البرمجية تلقائيًا عند تغييرها" - }, - "integrated_ui": { - "name": "واجهة مستخدم متكاملة", - "description": "يسمح للنصوص البرمجية بإضافة مكونات واجهة مستخدم مخصصة إلى Snapchat" - }, - "disable_log_anonymization": { - "name": "تعطيل إخفاء هوية السجل", - "description": "يعطل إخفاء هوية السجلات" - }, - "disable_optimization": { - "name": "تعطيل التحسين", - "description": "يعطل تحسين النصوص البرمجية. قد يتسبب هذا في حدوث مشكلات في الأداء." - } - } - }, - "friend_tracker": { - "name": "متتبع الأصدقاء", - "description": "يسجل نشاط الأصدقاء على Snapchat", - "properties": { - "record_messaging_events": { - "name": "تسجيل أحداث المراسلة", - "description": "يسجل أحداث المراسلة مثل فتح لقطة وقراءة رسالة وما إلى ذلك." - }, - "allow_running_in_background": { - "name": "السماح بالتشغيل في الخلفية", - "description": "يسمح للمتتبع بالعمل في الخلفية. ملاحظة: سيؤدي هذا إلى استنزاف البطارية بشكل كبير" - }, - "auto_purge": { - "name": "تطهير تلقائي", - "description": "يحذف تلقائيًا الأحداث المخزنة مؤقتًا التي يزيد عمرها عن مقدار الوقت المحدد" - } - } - } - }, - "options": { - "app_appearance": { - "always_light": "فاتح دائمًا", - "always_dark": "داكن دائمًا" - }, - "friend_feed_menu_buttons": { - "auto_download": "⬇️ تنزيل تلقائي", - "auto_save": "💬 حفظ الرسائل تلقائيًا", - "unsaveable_messages": "⬇️ رسائل غير قابلة للحفظ", - "auto_open_snaps": "📸 فتح Snaps تلقائيًا", - "stealth": "👻 وضع التخفي", - "mark_snaps_as_seen": "👀 تمييز Snaps كمقروءة", - "mark_stories_as_seen_locally": "👀 تمييز القصص كمقروءة محليًا", - "conversation_info": "🧑‍🤝‍🧑 معلومات المحادثة", - "e2e_encryption": "🔒 استخدام تشفير E2E" - }, - "path_format": { - "create_author_folder": "إنشاء مجلد لكل مؤلف", - "create_source_folder": "إنشاء مجلد لكل نوع مصدر وسائط", - "append_hash": "إضافة تجزئة فريدة إلى اسم الملف", - "append_source": "إضافة مصدر الوسائط إلى اسم الملف", - "append_username": "إضافة اسم المستخدم إلى اسم الملف", - "append_date_time": "إضافة التاريخ والوقت إلى اسم الملف" - }, - "auto_download_sources": { - "friend_snaps": "لقطات الأصدقاء", - "friend_stories": "قصص الأصدقاء", - "public_stories": "القصص العامة", - "spotlight": "الأضواء" - }, - "logging": { - "started": "بدأ", - "success": "نجاح", - "progress": "تقدم", - "failure": "فشل" - }, - "notifications": { - "chat_screenshot": "لقطة شاشة", - "chat_screen_record": "تسجيل الشاشة", - "snap_replay": "إعادة تشغيل Snap", - "camera_roll_save": "حفظ لفة الكاميرا", - "chat": "محادثة", - "chat_reply": "رد المحادثة", - "snap": "لقطة", - "typing": "يكتب", - "stories": "قصص", - "speaking": "يتحدث", - "chat_reaction": "رد فعل DM", - "group_chat_reaction": "رد فعل المجموعة", - "initiate_audio": "مكالمة صوتية واردة", - "abandon_audio": "مكالمة صوتية فائتة", - "initiate_video": "مكالمة فيديو واردة", - "abandon_video": "مكالمة فيديو فائتة", - "map_live_location": "موقع مباشر على الخريطة" - }, - "gallery_media_send_override": { - "always_ask": "اسأل دائمًا", - "ORIGINAL": "وسائط أصلية", - "NOTE": "ملاحظة صوتية", - "SNAP": "لقطة", - "SAVEABLE_SNAP": "Snap قابل للحفظ" - }, - "strip_media_metadata": { - "hide_caption_text": "إخفاء نص التسمية التوضيحية", - "hide_snap_filters": "إخفاء مرشحات Snap", - "hide_extras": "إخفاء الإضافات (على سبيل المثال الإشارات)", - "remove_audio_note_duration": "إزالة مدة الملاحظة الصوتية", - "remove_audio_note_transcript_capability": "إزالة إمكانية نسخ الملاحظات الصوتية" - }, - "hide_ui_components": { - "hide_profile_call_buttons": "إزالة أزرار الاتصال بالملف الشخصي", - "hide_chat_call_buttons": "إزالة أزرار الاتصال بالمحادثة", - "hide_live_location_share_button": "إزالة زر مشاركة الموقع المباشر", - "hide_stickers_button": "إزالة زر الملصقات", - "hide_voice_record_button": "إزالة زر تسجيل الصوت", - "hide_unread_chat_hint": "إزالة تلميح المحادثة غير المقروءة", - "hide_post_to_story_buttons": "إزالة أزرار النشر في القصة قبل إرسال Snap", - "hide_billboard_prompt": "إزالة موجه لوحة الإعلانات في موجز الأصدقاء", - "hide_snapchat_plus_gift_reminders": "إزالة تذكيرات هدايا Snapchat Plus في المحادثات", - "hide_map_reactions": "إزالة تفاعلات الخريطة" - }, - "hide_story_suggestions": { - "hide_suggested_friend_stories": "إخفاء قصص الأصدقاء المقترحة", - "hide_my_stories": "إخفاء قصصي" - }, - "home_tab": { - "map": "خريطة", - "chat": "محادثة", - "camera": "كاميرا", - "discover": "اكتشف", - "spotlight": "الأضواء" - }, - "add_friend_source_spoof": { - "added_by_username": "حسب اسم المستخدم", - "added_by_mention": "حسب الإشارة", - "added_by_group_chat": "حسب محادثة المجموعة", - "added_by_qr_code": "حسب رمز الاستجابة السريعة", - "added_by_community": "حسب المجتمع", - "added_by_quick_add": "حسب الإضافة السريعة (خطر كبير للحظر)" - }, - "bypass_video_length_restriction": { - "single": "وسائط فردية", - "split": "وسائط مقسمة" - }, - "old_bitmoji_selfie": { - "2d": "Bitmoji ثنائي الأبعاد", - "3d": "Bitmoji ثلاثي الأبعاد" - }, - "disable_confirmation_dialogs": { - "erase_message": "محو الرسالة", - "remove_friend": "إزالة صديق", - "block_friend": "حظر صديق", - "ignore_friend": "تجاهل صديق", - "hide_friend": "إخفاء صديق", - "hide_conversation": "إخفاء المحادثة", - "clear_conversation": "مسح المحادثة من موجز الأصدقاء" - }, - "auto_reload": { - "snapchat_only": "Snapchat فقط", - "all": "الكل (Snapchat + PurrfectSnap)" - }, - "edit_text_override": { - "multi_line_chat_input": "إدخال محادثة متعدد الأسطر", - "bypass_text_input_limit": "تجاوز حد إدخال النص" - }, - "auto_purge": { - "never": "أبدًا", - "1_hour": "ساعة واحدة", - "3_hours": "3 ساعات", - "6_hours": "6 ساعات", - "12_hours": "12 ساعة", - "1_day": "يوم واحد", - "3_days": "3 أيام", - "1_week": "أسبوع واحد", - "2_weeks": "أسبوعان", - "1_month": "شهر واحد", - "3_months": "3 أشهر", - "6_months": "6 أشهر" - }, - "disable_story_sections": { - "friends": "الأصدقاء", - "suggested_stories": "القصص المقترحة", - "following": "متابعة", - "discover": "اكتشف" - }, - "disable_cameras": { - "front": "الكاميرا الأمامية", - "back": "الكاميرا الخلفية" - }, - "disable_permission_requests": { - "notifications": "الإشعارات", - "read_media_images": "قراءة صور الوسائط", - "read_media_video": "قراءة فيديو الوسائط", - "camera": "الكاميرا", - "microphone": "الميكروفون", - "location": "الموقع", - "read_contacts": "قراءة جهات الاتصال", - "nearby_devices": "الأجهزة القريبة", - "phone_calls": "المكالمات الهاتفية" - }, - "message_indicators": { - "encryption_indicator": "يضيف أيقونة 🔒 بجوار الرسائل التي تم إرسالها إليك فقط", - "platform_indicator": "يضيف أيقونة النظام الأساسي الذي تم إرسال الوسائط منه (على سبيل المثال Android و iOS و Web)", - "location_indicator": "يضيف أيقونة 📍 إلى اللقطات عند إرسالها مع تمكين الموقع", - "ovf_editor_indicator": "يشير إلى ما إذا تم إرسال لقطة باستخدام محرر OVF", - "director_mode_indicator": "يضيف أيقونة 🎬 إلى اللقطات عند إرسالها باستخدام وضع المخرج ، والذي يمكن استخدامه لإرسال صور المعرض كلقطات" - }, - "auto_mark_as_read": { - "conversation_read": "تمييز المحادثة كمقروءة عند إرسال رسالة", - "snap_reply": "تمييز اللقطات كمقروءة عند الرد عليها", - "save_snap_in_chat": "تمييز اللقطات كمقروءة عند حفظها في المحادثة أثناء وجودك في وضع التخفي" - }, - "friend_mutation_notifier": { - "remove_friend": "إعلام عندما يزيلك شخص ما كصديق", - "birthday_changes": "إعلام عندما يغير شخص ما عيد ميلاده", - "bitmoji_selfie_changes": "إعلام عندما يغير شخص ما صورة Bitmoji الشخصية الخاصة به", - "bitmoji_avatar_changes": "إعلام عندما يغير شخص ما صورة Bitmoji الرمزية الخاصة به", - "bitmoji_background_changes": "إعلام عندما يغير شخص ما خلفية Bitmoji الخاصة به", - "bitmoji_scene_changes": "إعلام عندما يغير شخص ما مشهد Bitmoji الخاص به" - }, - "snapchat_plus": { - "not_subscribed": "غير مشترك", - "basic": "أساسي", - "ad_free": "بدون إعلانات" - }, - "double_tap_chat_action": { - "like_message": "إعجاب بالرسالة", - "copy_text": "نسخ النص إلى الحافظة", - "delete_message": "حذف الرسالة", - "mark_as_read": "تمييز كمقروء", - "custom_emoji_reaction": "رد فعل تعبيري مخصص" - }, - "startup_default_camera": { - "front": "الكاميرا الأمامية", - "back": "الكاميرا الخلفية" - } - } - }, - "friend_menu_option": { - "mark_snaps_as_seen": "تمييز اللقطات كمقروءة", - "mark_stories_as_seen_locally": "تمييز القصص كمقروءة محليًا", - "preview": "معاينة", - "stealth_mode": "وضع التخفي", - "auto_download_blacklist": "القائمة السوداء للتنزيل التلقائي", - "anti_auto_save": "مكافحة الحفظ التلقائي" - }, - "content_type": { - "CHAT": "محادثة", - "SNAP": "لقطة", - "EXTERNAL_MEDIA": "وسائط خارجية", - "NOTE": "ملاحظة صوتية", - "STICKER": "ملصق", - "SHARE": "مشاركة", - "STATUS": "الحالة", - "LOCATION": "الموقع", - "STATUS_SAVE_TO_CAMERA_ROLL": "تم الحفظ في لفة الكاميرا", - "STATUS_CONVERSATION_CAPTURE_SCREENSHOT": "لقطة شاشة", - "STATUS_CONVERSATION_CAPTURE_RECORD": "تسجيل الشاشة", - "STATUS_CALL_MISSED_VIDEO": "مكالمة فيديو فائتة", - "STATUS_CALL_MISSED_AUDIO": "مكالمة صوتية فائتة", - "LIVE_LOCATION_SHARE": "مشاركة الموقع المباشر", - "CREATIVE_TOOL_ITEM": "عنصر أداة إبداعية", - "FAMILY_CENTER_INVITE": "دعوة مركز العائلة", - "FAMILY_CENTER_ACCEPT": "قبول مركز العائلة", - "FAMILY_CENTER_LEAVE": "مغادرة مركز العائلة", - "STATUS_PLUS_GIFT": "هدية الحالة بلس", - "TINY_SNAP": "لقطة صغيرة", - "STATUS_COUNTDOWN": "عد تنازلي", - "MAP_REACTION": "تفاعل الخريطة" - }, - "media_download_source": { - "none": "لا شيء", - "pending": "قيد الانتظار", - "chat_media": "وسائط المحادثة", - "story": "قصة", - "public_story": "قصة عامة", - "spotlight": "الأضواء", - "profile_picture": "صورة الملف الشخصي", - "story_logger": "مسجل القصة", - "message_logger": "مسجل الرسائل", - "merged": "مدمج", - "voice_call": "مكالمة صوتية" - }, - "chat_action_menu": { - "preview_button": "معاينة", - "download_button": "تنزيل", - "delete_logged_message_button": "حذف الرسالة المسجلة", - "show_chat_edit_history": "إظهار محفوظات تعديل المحادثة", - "convert_message": "تحويل الرسالة" - }, - "opera_context_menu": { - "download": "تنزيل الوسائط", - "sent_at": "أرسلت في {date}", - "created_at": "أنشئت في {date}", - "expires_at": "تنتهي في {date}", - "media_size": "حجم الوسائط: {size}", - "media_duration": "مدة الوسائط: {duration} مللي ثانية", - "show_debug_info": "إظهار معلومات التصحيح" - }, - "modal_option": { - "profile_info": "معلومات الملف الشخصي", - "close": "إغلاق" - }, - "gallery_media_send_override": { - "multiple_media_toast": "يمكنك إرسال وسائط واحدة فقط في كل مرة" - }, - "mark_as_seen": { - "no_unseen_snaps_toast": "لم يتم العثور على لقطات غير مرئية!", - "seen_toast": "تم التمييز كمقروء!", - "unseen_toast": "تم التمييز كغير مقروء!", - "already_seen_toast": "تم التمييز بالفعل كمقروء!", - "already_unseen_toast": "تم التمييز بالفعل كغير مقروء!" - }, - "conversation_preview": { - "streak_expiration": "تنتهي في {day} أيام {hour} ساعات {minute} دقائق", - "total_messages": "إجمالي الرسائل المرسلة/المستلمة: {count}", - "title": "معاينة", - "unknown_user": "مستخدم غير معروف", - "no_messages": "لم يتم العثور على رسائل!" - }, - "profile_info": { - "title": "معلومات الملف الشخصي", - "first_created_username": "أول اسم مستخدم تم إنشاؤه", - "mutable_username": "اسم مستخدم قابل للتغيير", - "display_name": "اسم العرض", - "added_date": "تاريخ الإضافة", - "birthday": "عيد الميلاد: {day} {month}", - "hidden_birthday": "عيد الميلاد: مخفي", - "friendship": "صداقة", - "add_source": "إضافة مصدر", - "snapchat_plus": "سناب شات بلس", - "snapchat_plus_state": { - "subscribed": "مشترك", - "not_subscribed": "غير مشترك" - } - }, - "friendship_link_type": { - "mutual": "متبادل", - "outgoing": "صادر", - "blocked": "محظور", - "deleted": "محذوف", - "following": "متابعة", - "suggested": "مقترح", - "incoming": "وارد", - "incoming_follower": "متابع وارد" - }, - "bulk_messaging_action": { - "choose_action_title": "اختر إجراءً", - "progress_status": "معالجة {index} من {total}", - "selection_dialog_continue_button": "متابعة", - "confirmation_dialog": { - "title": "هل أنت متأكد؟", - "message": "سيؤثر هذا على جميع الأصدقاء المحددين. لا يمكن التراجع عن هذا الإجراء." - }, - "actions": { - "remove_friends": "إزالة الأصدقاء", - "clear_conversations": "مسح المحادثات" - } - }, - "chat_export": { - "exporter_dialog": { - "select_conversations_title": "تحديد المحادثات", - "text_field_selection": "{amount} محدد", - "text_field_selection_all": "الكل", - "export_file_format_title": "تنسيق ملف التصدير", - "message_type_filter_title": "تصفية الرسائل حسب النوع", - "amount_of_messages_title": "عدد الرسائل (اتركه فارغًا للكل)", - "download_medias_title": "تنزيل الوسائط" - }, - "dialog_negative_button": "إلغاء", - "dialog_positive_button": "تصدير", - "exported_to": "تم التصدير إلى {path}", - "exporting_chats": "جاري تصدير الدردشات...", - "processing_chats": "معالجة {amount} محادثة...", - "export_fail": "فشل تصدير المحادثة {conversation}", - "writing_output": "كتابة الإخراج...", - "finished": "تم! يمكنك الآن إغلاق مربع الحوار هذا.", - "no_messages_found": "لم يتم العثور على رسائل!", - "exporting_message": "تصدير {conversation}..." - }, - "button": { - "ok": "موافق", - "positive": "نعم", - "negative": "لا", - "cancel": "إلغاء", - "open": "فتح", - "download": "تنزيل", - "send": "إرسال", - "restore_original": "استعادة الأصل", - "convert_external_media": "تحويل الوسائط الخارجية", - "save": "حفظ" - }, - "tracker_events": { - "conversation_enter": "دخول المحادثة", - "conversation_exit": "خروج المحادثة", - "started_typing": "بدأ الكتابة", - "stopped_typing": "توقف عن الكتابة", - "started_speaking": "بدأ التحدث", - "stopped_speaking": "توقف عن التحدث", - "started_peeking": "بدأ النظرة الخاطفة", - "stopped_peeking": "توقف عن النظرة الخاطفة", - "message_read": "تمت قراءة الرسالة", - "message_deleted": "تم حذف الرسالة", - "message_saved": "تم حفظ الرسالة", - "message_unsaved": "تم إلغاء حفظ الرسالة", - "message_edited": "تم تعديل الرسالة", - "message_reaction_add": "إضافة تفاعل الرسالة", - "message_reaction_remove": "إزالة تفاعل الرسالة", - "snap_opened": "تم فتح Snap", - "snap_replayed": "تم إعادة تشغيل Snap", - "snap_replayed_twice": "تم إعادة تشغيل Snap مرتين", - "snap_screenshot": "لقطة شاشة Snap", - "snap_screen_record": "تسجيل شاشة Snap" - }, - "tracker_actions": { - "log": "سجل", - "in_app_notification": "إشعار داخل التطبيق", - "push_notification": "إشعار دفع", - "custom": "مخصص" - }, - "better_notifications": { - "button": { - "reply": "رد", - "download": "تنزيل", - "mark_as_read": "تمييز كمقروء" - } - }, - "profile_picture_downloader": { - "button": "تنزيل صورة الملف الشخصي", - "title": "تنزيل صورة الملف الشخصي", - "avatar_option": "الصورة الرمزية", - "background_option": "الخلفية" - }, - "call_start_confirmation": { - "dialog_title": "بدء المكالمة", - "dialog_message": "هل أنت متأكد من أنك تريد بدء مكالمة؟" - }, - "half_swipe_notifier": { - "notification_channel_name": "نظرة خاطفة", - "notification_content_dm": "{friend} نظر خلسة في محادثتك لمدة {duration} ثانية", - "notification_content_group": "{friend} نظر خلسة في {group} لمدة {duration} ثانية" - }, - "download_processor": { - "attachment_type": { - "snap": "لقطة", - "sticker": "ملصق", - "gif": "GIF", - "external_media": "وسائط خارجية", - "note": "ملاحظة", - "original_story": "القصة الأصلية" - }, - "select_attachments_title": "تحديد المرفقات", - "download_started_toast": "بدأ التنزيل", - "unsupported_content_type_toast": "نوع محتوى غير مدعوم!", - "failed_no_longer_available_toast": "الوسائط لم تعد متاحة", - "no_attachments_toast": "لم يتم العثور على مرفقات!", - "already_queued_toast": "الوسائط موجودة بالفعل في قائمة الانتظار!", - "already_downloaded_toast": "تم تنزيل الوسائط بالفعل!", - "content_saved_toast": "تم الحفظ!", - "download_toast": "جاري تنزيل {path}...", - "processing_toast": "جاري معالجة {path}...", - "failed_generic_toast": "فشل التنزيل", - "failed_to_create_preview_toast": "فشل إنشاء المعاينة", - "failed_processing_toast": "فشل المعالجة {error}", - "failed_gallery_toast": "فشل الحفظ في المعرض {error}", - "dash_no_chapter": "لم يتم العثور على فصل", - "dash_dialog": { - "title": "تنزيل وسائط dash", - "download_all": "تنزيل الكل", - "segment_text": "الجزء {from} - {to}" - } - }, - "streaks_reminder": { - "notification_title": "سلسلة", - "notification_text": "ستفقد سلسلتك مع {friend} في غضون {hoursLeft} ساعة" - }, - "biometric_auth": { - "unlock_button": "فتح", - "title": "فتح Snapchat", - "subtitle": "الرجاء المصادقة لفتح Snapchat" - }, - "end_to_end_encryption": { - "toolbox": { - "no_shared_key": "ليس لديك مفتاح سري مشترك مع هذا الصديق بعد. انقر أدناه لبدء واحد جديد.", - "shared_key_fingerprint": "بصمة إصبعك هي:\n\n{fingerprint}\n\nتأكد من التحقق مما إذا كانت تتطابق مع بصمة إصبع صديقك!", - "initiate_exchange_button": "بدء تبادل المفاتيح" - }, - "confirmation_dialogs": { - "title": "تشفير من طرف إلى طرف", - "confirmation_1": "تحذير: سيؤدي هذا إلى الكتابة فوق مفتاحك الحالي. ستفقد الوصول إلى جميع الرسائل المشفرة من هذا الصديق. هل أنت متأكد من أنك تريد المتابعة؟", - "confirmation_2": "هل أنت متأكد حقًا من أنك تريد المتابعة؟ هذه هي فرصتك الأخيرة للتراجع." - }, - "unencrypted_conversation_send_failure_toast": "لا يمكنك إرسال محتوى مشفر إلى كل من المحادثات المشفرة وغير المشفرة!", - "native_hooks_send_failure_toast": "فشل الإرسال! يرجى تمكين الخطافات الأصلية في الإعدادات.", - "no_participants_to_encrypt_toast": "ليس لديك أي أصدقاء في هذه المحادثة لتشفير الرسائل معهم!", - "encryption_failed_toast": "فشل تشفير الرسالة! تحقق من logcat لمزيد من التفاصيل.", - "accept_public_key_success_toast": "تم قبول المفتاح العام بنجاح!", - "accept_secret_key_success_toast": "تم! يمكنك الآن إرسال واستقبال رسائل مشفرة مع هذا الصديق.", - "accept_public_key_failure_toast": "فشل قبول المفتاح العام", - "accept_secret_key_failure_toast": "فشل قبول المفتاح السري", - "accept_secret_button": "قبول السر", - "accept_public_key_button": "قبول المفتاح العام", - "outgoing_pk_message": "طلب تبادل المفاتيح", - "outgoing_secret_message": "استجابة تبادل المفاتيح", - "incoming_pk_message": "لقد تلقيت للتو طلب مفتاح عام. انقر أدناه لقبوله.", - "incoming_secret_message": "لقد قبل صديقك للتو مفتاحك العام. انقر أدناه لقبول السر." - }, - "auto_open_snaps": { - "title": "فتح Snaps تلقائيًا", - "notification_content": "تم فتح {count} لقطة" - }, - "friend_mutation_observer": { - "notification_channel_name": "مراقب طفرة الصديق", - "friend_removed": "لقد أزالك {username} كصديق", - "birthday_removed": "لقد أزال {username} عيد ميلاده ({birthday})", - "birthday_added": "لقد أضاف {username} عيد ميلاده ({birthday})", - "birthday_changed": "{username} غير عيد ميلاده من {oldBirthday} إلى {newBirthday}", - "bitmoji_selfie_changed": "لقد غير {username} صورة Bitmoji الشخصية الخاصة به", - "bitmoji_avatar_changed": "لقد غير {username} صورة Bitmoji الرمزية الخاصة به", - "bitmoji_background_changed": "لقد غير {username} خلفية Bitmoji الخاصة به", - "bitmoji_scene_changed": "لقد غير {username} مشهد Bitmoji الخاص به" - }, - "material3_strings": { - "date_range_picker_start_headline": "من", - "date_range_picker_end_headline": "إلى", - "date_range_picker_title": "تحديد نطاق التاريخ", - "date_picker_switch_to_calendar_mode": "تقويم", - "date_picker_switch_to_input_mode": "إدخال", - "date_range_picker_scroll_to_previous_month": "الشهر السابق", - "date_range_picker_scroll_to_next_month": "الشهر التالي", - "date_picker_today_description": "اليوم", - "date_range_picker_day_in_range": "محدد", - "date_input_invalid_for_pattern": "تاريخ غير صالح", - "date_input_invalid_year_range": "سنة غير صالحة", - "date_input_invalid_not_allowed": "تاريخ غير صالح", - "date_range_input_invalid_range_input": "نطاق تاريخ غير صالح" - }, - "send_override_dialog": { - "title": "إرسال الوسائط كـ {type}", - "duration": "المدة: {duration}", - "saveable_snap_hint": "جعل Snap قابلاً للحفظ في المحادثة", - "unlimited_duration": "غير محدود" - }, - "invalid_input_toast": "إدخال غير صالح! تأكد من أنك أدخلت قيمة صالحة." -} \ No newline at end of file diff --git a/common/src/main/assets/lang/ar_AE.json b/common/src/main/assets/lang/ar_AE.json new file mode 100644 index 00000000..251bf5f6 --- /dev/null +++ b/common/src/main/assets/lang/ar_AE.json @@ -0,0 +1,2487 @@ +{ + "setup": { + "dialogs": { + "select_language": "اختر اللغة", + "save_folder": "يتطلب سناب إنهانس إذن التخزين لتنزيل وحفظ الوسائط من سناب شات.\nالرجاء اختيار الموقع الذي يجب تنزيل الوسائط إليه.", + "select_save_folder_button": "اختر مجلد" + }, + "mappings": { + "dialog": "جارٍ إنشاء التعيينات، قد يستغرق هذا بعض الوقت ...", + "generate_failure_no_snapchat": "تعذر على سناب إنهانس اكتشاف سناب شات، يرجى إعادة تثبيت سناب شات.", + "generate_failure": "حدث خطأ أثناء محاولة إنشاء التعيينات، يرجى المحاولة مرة أخرى." + }, + "permissions": { + "dialog": "للمتابعة، تحتاج إلى تلبية المتطلبات التالية:", + "notification_access": "الوصول إلى الإشعارات", + "battery_optimization": "تحسين البطارية", + "display_over_other_apps": "عرض فوق التطبيقات الأخرى", + "request_button": "طلب" + } + }, + + "scopes": { + "friend": "صديق", + "group": "مجموعة" + }, + + "manager": { + "routes": { + "tasks": "المهام", + "features": "الميزات", + "manage_rule_feature": "إدارة ميزة القاعدة", + "home": "الصفحة الرئيسية", + "home_settings": "الإعدادات", + "home_logs": "السجلات", + "logger_history": "سجل المسجل", + "logged_stories": "القصص المسجلة", + "friend_tracker": "تتبع الأصدقاء", + "edit_rule": "تحرير القاعدة", + "file_imports": "استيراد الملفات", + "manage_repos": "إدارة المستودعات", + "social": "اجتماعي", + "manage_scope": "إدارة النطاق", + "messaging_preview": "معاينة", + "scripts": "النصوص البرمجية", + "better_location": "موقع أفضل" + }, + "sections": { + "home": { + "version_title": "الإصدار {versionName} · بواسطة eternal", + "update_title": "تحديث سناب إنهانس", + "update_content": "الإصدار {version} متاح الآن!", + "update_button": "تنزيل", + "debug_build_summary_title": "أنت تستخدم إصدار تجريبي من سناب إنهانس", + "debug_build_summary_content": "الإصدار {versionName} ({versionCode})", + "debug_build_summary_date": "تاريخ البناء: {date} (منذ {days} أيام)", + "quick_actions_title": "إجراءات سريعة" + }, + "home_logs": { + "no_logs_hint": "لا توجد سجلات متاحة", + "clear_logs_button": "مسح السجلات", + "export_logs_button": "تصدير السجلات", + "saving_logs_toast": "جارٍ حفظ السجلات، قد يستغرق هذا بعض الوقت ...", + "saved_logs_success_toast": "تم حفظ السجلات بنجاح", + "saved_logs_failure_toast": "فشل في حفظ السجلات" + }, + "home_settings": { + "actions_title": "الإجراءات", + "message_logger_title": "مسجل الرسائل", + "debug_title": "التصحيح", + "success_toast": "تم!", + "message_logger_summary": "{messageCount} رسائل\n{storyCount} قصص", + "export_button": "تصدير", + "clear_button": "مسح", + "view_logger_history_button": "عرض سجل المسجل" + }, + "tasks": { + "no_tasks": "لا توجد مهام", + "merge_button": "دمج", + "failed_to_open_file": "فشل في فتح الملف", + "merge_files_toast": "جارٍ دمج {count} ملفات", + "remove_selected_tasks_title": "هل أنت متأكد أنك تريد إزالة المهام المحددة؟", + "remove_all_tasks_title": "هل أنت متأكد أنك تريد إزالة جميع المهام؟", + "delete_files_option": "حذف الملفات أيضًا", + "remove_selected_tasks_confirm": "إزالة {count} مهمة؟", + "remove_all_tasks_confirm": "إزالة جميع المهام؟" + }, + "features": { + "disabled": "معطل", + "export_option": "تصدير", + "import_option": "استيراد", + "reset_option": "إعادة تعيين", + "config_export_success_toast": "تم تصدير التكوين بنجاح", + "config_import_success_toast": "تم استيراد التكوين بنجاح", + "config_import_failure_toast": "فشل في استيراد التكوين {error}", + "config_export_failure_toast": "فشل في تصدير التكوين {error}", + "saved_config_snackbar": "تم حفظ التكوين", + "older_required": "تتطلب هذه الميزة سناب شات الإصدار {version} أو أقدم لتعمل بشكل صحيح", + "newer_required": "تتطلب هذه الميزة سناب شات الإصدار {version} أو أحدث لتعمل بشكل صحيح", + "search_button": "بحث" + }, + "manage_rule_feature": { + "disable_state_option": "معطل", + "disable_state_subtext": "لن يتأثر أي أصدقاء/مجموعات", + "whitelist_state_option": "لا أحد باستثناء ...", + "whitelist_state_subtext": "فقط {count} أصدقاء/مجموعات ستتأثر بهذه القاعدة", + "whitelist_state_button": "اختر الأصدقاء/المجموعات المسموح بها", + "blacklist_state_option": "الجميع باستثناء ...", + "blacklist_state_subtext": "الجميع باستثناء {count} أصدقاء/مجموعات ستتأثر بهذه القاعدة", + "blacklist_state_button": "اختر الأصدقاء/المجموعات المستثناة", + "clear_list_button": "مسح قائمة الأصدقاء/المجموعات", + "dialog_clear_confirmation_text": "هل أنت متأكد أنك تريد مسح القائمة؟" + }, + "social": { + "friends_tab": "الأصدقاء", + "groups_tab": "المجموعات", + "empty_hint": "(فارغ)", + "streaks_expiration_short": "{hours}س" + }, + "manage_scope": { + "logged_stories_button": "عرض القصص المسجلة", + "e2ee_title": "التشفير من طرف إلى طرف", + "rules_title": "القواعد", + "participants_text": "{count} مشاركين", + "not_found": "غير موجود", + "streaks_title": "الستريك", + "streaks_length_text": "المدة: {length}", + "streaks_expiration_text": "ينتهي في {eta}", + "streaks_expiration_text_expired": "منتهي", + "reminder_button": "تعيين تذكير", + "delete_scope_confirm_dialog_title": "هل أنت متأكد أنك تريد حذف {scope}؟", + "notes_placeholder": "انقر لإضافة ملاحظة" + }, + "logged_stories": { + "story_failed_to_load": "فشل في التحميل", + "no_stories": "لم يتم العثور على قصص", + "save_from_cache_button": "حفظ من الذاكرة المؤقتة" + }, + "messaging_preview": { + "bridge_connection_failed": "فشل في الاتصال بالجسر. تأكد من أن سناب شات يعمل في الخلفية", + "bridge_init_failed": "فشل في تهيئة جسر المراسلة. تأكد من أن سناب شات يعمل في الخلفية", + "message_fetch_failed": "فشل في جلب الرسائل", + "no_message_hint": "لا توجد رسالة", + "save_selection_option": "حفظ التحديد", + "save_all_option": "حفظ الكل", + "unsave_selection_option": "إلغاء حفظ التحديد", + "unsave_all_option": "إلغاء حفظ الكل", + "mark_selection_as_seen_option": "وضع علامة على السناب المحدد كمقروء", + "mark_all_as_seen_option": "وضع علامة على جميع السنابات كمقروءة", + "delete_selection_option": "حذف التحديد", + "delete_all_option": "حذف الكل" + }, + "logger_history": { + "list_friend_format": "الصديق {name}", + "list_group_format": "المجموعة {name}", + "no_more_messages": "لا توجد المزيد من الرسائل", + "reverse_order_checkbox": "ترتيب عكسي", + "chat_attachment": "مرفق {index}", + "empty_message": "رسالة محادثة فارغة", + "message_parse_failed": "فشل في تحليل الرسالة", + "unknown_sender": "مرسل غير معروف", + "download_attachment_failed_toast": "فشل في تنزيل المرفق" + }, + "file_imports": { + "import_file_button": "استيراد ملف", + "file_not_found": "الملف غير موجود", + "file_import_failed": "فشل في استيراد الملف: {error}", + "file_imported": "تم استيراد الملف بنجاح", + "file_delete_failed": "فشل في حذف الملف", + "no_files_hint": "هنا يمكنك استيراد الملفات لاستخدامها في سناب شات. اضغط على الزر أدناه لاستيراد ملف." + }, + "better_location": { + "spoofed_coordinates_title": "خط العرض {latitude}, خط الطول {longitude}", + "save_coordinates_dialog_title": "حفظ الإحداثيات", + "saved_name_dialog_hint": "الاسم المحفوظ", + "latitude_dialog_hint": "خط العرض", + "longitude_dialog_hint": "خط الطول", + "save_dialog_button": "حفظ", + "choose_location_button": "اختر موقعًا", + "teleport_to_friend_button": "الانتقال إلى صديق", + "spoof_location_toggle": "تزييف الموقع", + "suspend_location_updates": "تعطيل تحديثات الموقع", + "saved_coordinates_title": "الإحداثيات المحفوظة", + "no_saved_coordinates_hint": "لا توجد إحداثيات محفوظة", + "delete_dialog_title": "حذف الإحداثيات المحفوظة", + "delete_dialog_message": "هل أنت متأكد أنك تريد حذف هذه الإحداثيات المحفوظة؟", + "teleport_to_friend_title": "الانتقال إلى صديق", + "search_bar": "بحث", + "no_friends_map": "لا توجد أصدقاء على الخريطة", + "no_friends_found": "لم يتم العثور على أصدقاء" + } + }, + "dialogs": { + "add_friend": { + "title": "إضافة صديق أو مجموعة", + "search_hint": "بحث", + "fetch_error": "فشل في جلب البيانات", + "category_groups": "المجموعات", + "category_friends": "الأصدقاء", + "participants_text": "{count} مشاركين" + }, + "scripting_warning": { + "title": "تحذير", + "content": "يتضمن سناب إنهانس أداة برمجة تسمح بتنفيذ كود محدد من قبل المستخدم على جهازك. استخدم بحذر شديد وقم بتثبيت الوحدات فقط من مصادر معروفة وموثوقة. قد تشكل الوحدات غير المصرح بها أو غير المختبرة مخاطر أمنية على نظامك." + }, + "reset_config": { + "title": "إعادة تعيين التكوين", + "content": "هل أنت متأكد أنك تريد إعادة تعيين التكوين؟", + "success_toast": "تم إعادة تعيين التكوين بنجاح" + }, + "export_config": { + "title": "تصدير بيانات حساسة؟", + "content": "هل تريد تصدير التكوين مع البيانات الحساسة؟ (مثل إحداثيات الموقع، إلخ.)" + }, + "messaging_action": { + "title": "اختر أنواع المحتوى المراد معالجتها", + "select_all_button": "اختر الكل" + }, + "file_imports": { + "no_files_settings_hint": "لم يتم العثور على ملفات. تأكد من أنك قمت باستيراد الملفات المطلوبة في قسم استيراد الملفات", + "settings_select_file_hint": "اختر ملفًا مستوردًا" + } + } + }, + + "rules": { + "toasts": { + "enabled": "تم تمكين {ruleName}", + "disabled": "تم تعطيل {ruleName}" + }, + "modes": { + "blacklist": "وضع القائمة السوداء", + "whitelist": "وضع القائمة البيضاء" + }, + "properties": { + "auto_download": { + "name": "التنزيل التلقائي", + "description": "تنزيل السنابات تلقائيًا عند مشاهدتها", + "options": { + "blacklist": "استثناء من التنزيل التلقائي", + "whitelist": "التنزيل التلقائي" + } + }, + "stealth": { + "name": "وضع التخفي", + "description": "يمنع أي شخص من معرفة أنك قد فتحت سناباته/محادثاته", + "options": { + "blacklist": "استثناء من وضع التخفي", + "whitelist": "وضع التخفي" + } + }, + "auto_save": { + "name": "الحفظ التلقائي", + "description": "يحفظ رسائل المحادثة عند مشاهدتها", + "options": { + "blacklist": "استثناء من الحفظ التلقائي", + "whitelist": "الحفظ التلقائي" + } + }, + "unsaveable_messages": { + "name": "رسائل غير قابلة للحفظ", + "description": "يمنع الآخرين من حفظ الرسائل في المحادثة", + "options": { + "blacklist": "استثناء من الرسائل غير القابلة للحفظ", + "whitelist": "رسائل غير قابلة للحفظ" + } + }, + "auto_open_snaps": { + "name": "فتح السنابات تلقائيًا", + "description": "يفتح السنابات تلقائيًا عند استلامها", + "options": { + "blacklist": "استثناء من فتح السنابات تلقائيًا", + "whitelist": "فتح السنابات تلقائيًا" + } + }, + "hide_friend_feed": { + "name": "إخفاء من خلاصة الأصدقاء" + }, + "e2e_encryption": { + "name": "استخدام التشفير من طرف إلى طرف" + }, + "pin_conversation": { + "name": "تثبيت المحادثة" + }, + "exclude_message_logger": { + "name": "استثناء من مسجل الرسائل" + }, + "auto_reply": { + "name": "الرد التلقائي", + "description": "يرد تلقائيًا على الرسائل الواردة عندما تكون بعيدًا", + "options": { + "blacklist": "استثناء من الرد التلقائي", + "whitelist": "الرد التلقائي" + } + }, + "auto_delete_sent_messages": { + "name": "حذف الرسائل المرسلة تلقائيًا", + "description": "يحذف الرسائل المرسلة تلقائيًا بعد فترة زمنية محددة", + "options": { + "blacklist": "استثناء من الحذف التلقائي", + "whitelist": "الحذف التلقائي" + } + } + } + }, + + "actions": { + "clean_snapchat_cache": { + "name": "تنظيف ذاكرة سناب شات المؤقتة", + "description": "ينظف ذاكرة سناب شات المؤقتة" + }, + "manage_friend_list": { + "name": "إدارة قائمة الأصدقاء", + "description": "استيراد/تصدير قائمة أصدقائك عند النسخ الاحتياطي" + }, + "export_chat_messages": { + "name": "تصدير رسائل المحادثة", + "description": "يصدر رسائل المحادثة إلى ملف JSON/HTML/TXT" + }, + "export_memories": { + "name": "تصدير الذكريات", + "description": "يصدر الذكريات إلى ملف ZIP" + }, + "bulk_messaging_action": { + "name": "إجراء مراسلة جماعية", + "description": "ينفذ عمليات مثل حذف الأصدقاء أو الحذف الجماعي للمحادثات" + }, + "regen_mappings": { + "name": "إعادة إنشاء التعيينات", + "description": "إعادة إنشاء التعيينات يدويًا" + }, + "change_language": { + "name": "تغيير اللغة", + "description": "تغيير لغة سناب إنهانس" + }, + "file_imports": { + "name": "استيراد الملفات", + "description": "استيراد الملفات لاستخدامها في سناب شات" + }, + "friend_tracker": { + "name": "تتبع الأصدقاء", + "description": "تتبع نشاط أصدقائك على سناب شات" + }, + "logger_history": { + "name": "سجل المسجل", + "description": "عرض سجل الرسائل المسجلة" + } + }, + + "features": { + "notices": { + "unstable": "\u26A0 غير مستقر", + "ban_risk": "\u26A0 قد تتسبب هذه الميزة في حظر حسابك", + "internal_behavior": "\u26A0 قد يؤدي هذا إلى تعطيل السلوك الداخلي لـ سناب شات" + }, + "properties": { + "downloader": { + "name": "أداة التنزيل", + "description": "تنزيل وسائط سناب شات", + "properties": { + "save_folder": { + "name": "مجلد الحفظ", + "description": "اختر الدليل الذي يجب تنزيل جميع الوسائط إليه" + }, + "auto_download_sources": { + "name": "مصادر التنزيل التلقائي", + "description": "اختر المصادر التي يجب التنزيل منها تلقائيًا" + }, + "prevent_self_auto_download": { + "name": "منع التنزيل التلقائي للسنابات الخاصة", + "description": "يمنع تنزيل سناباتك تلقائيًا" + }, + "path_format": { + "name": "تنسيق المسار", + "description": "حدد تنسيق مسار الملف" + }, + "allow_duplicate": { + "name": "السماح بالتكرار", + "description": "يسمح بتنزيل نفس الوسائط عدة مرات" + }, + "merge_overlays": { + "name": "دمج الطبقات", + "description": "يجمع النص والوسائط في السناب في ملف واحد" + }, + "force_image_format": { + "name": "فرض تنسيق الصورة", + "description": "يجبر الصور على الحفظ بتنسيق محدد" + }, + "force_voice_note_format": { + "name": "فرض تنسيق الملاحظات الصوتية", + "description": "يجبر الملاحظات الصوتية على الحفظ بتنسيق محدد" + }, + "auto_download_voice_notes": { + "name": "تنزيل الملاحظات الصوتية تلقائيًا", + "description": "تنزيل الملاحظات الصوتية تلقائيًا عند تشغيلها" + }, + "download_profile_pictures": { + "name": "تنزيل صور الملف الشخصي", + "description": "يسمح لك بتنزيل صور الملف الشخصي من صفحة الملف الشخصي" + }, + "opera_download_button": { + "name": "زر التنزيل في Opera", + "description": "يضيف زر تنزيل في الزاوية العلوية اليمنى عند مشاهدة سناب.\nالضغط المطول على الأزرار يجبر التنزيل" + }, + "download_context_menu": { + "name": "قائمة السياق للتنزيل", + "description": "يسمح لك بتنزيل/معاينة الرسائل من محادثة أو قصة باستخدام قائمة السياق.\nالضغط المطول على الأزرار يجبر التنزيل" + }, + "ffmpeg_options": { + "name": "خيارات FFmpeg", + "description": "حدد خيارات FFmpeg إضافية", + "properties": { + "threads": { + "name": "الخيوط", + "description": "عدد الخيوط المستخدمة" + }, + "preset": { + "name": "الإعداد المسبق", + "description": "تعيين سرعة التحويل" + }, + "constant_rate_factor": { + "name": "عامل المعدل الثابت", + "description": "تعيين عامل المعدل الثابت لبرنامج ترميز الفيديو\nمن 0 إلى 51 لـ libx264" + }, + "video_bitrate": { + "name": "معدل بت الفيديو", + "description": "تعيين معدل بت الفيديو (كيلوبت في الثانية)" + }, + "audio_bitrate": { + "name": "معدل بت الصوت", + "description": "تعيين معدل بت الصوت (كيلوبت في الثانية)" + }, + "custom_video_codec": { + "name": "برنامج ترميز فيديو مخصص", + "description": "تعيين برنامج ترميز فيديو مخصص (مثل libx264)" + }, + "custom_audio_codec": { + "name": "برنامج ترميز صوت مخصص", + "description": "تعيين برنامج ترميز صوت مخصص (مثل AAC)" + } + } + }, + "logging": { + "name": "التسجيل", + "description": "يعرض إشعارات عند تنزيل الوسائط" + }, + "custom_path_format": { + "name": "تنسيق مسار مخصص", + "description": "حدد تنسيق مسار مخصص للوسائط التي تم تنزيلها\n\nالمتغيرات المتاحة:\n - %username%\n - %source%\n - %hash%\n - %date_time%" + } + } + }, + "user_interface": { + "name": "واجهة المستخدم", + "description": "تغيير مظهر ومظهر سناب شات", + "properties": { + "enable_app_appearance": { + "name": "تمكين إعدادات مظهر التطبيق", + "description": "يسمح بإعدادات مظهر التطبيق المخفية\nقد لا يكون مطلوبًا في إصدارات سناب شات الأحدث" + }, + "friend_feed_message_preview": { + "name": "معاينة رسائل خلاصة الأصدقاء", + "description": "يعرض معاينة للرسائل الأخيرة في خلاصة الأصدقاء", + "properties": { + "amount": { + "name": "الكمية", + "description": "عدد الرسائل المراد معاينتها" + } + } + }, + "snap_preview": { + "name": "معاينة السناب", + "description": "يعرض معاينة صغيرة بجانب السنابات غير المقروءة في المحادثة" + }, + "bootstrap_override": { + "name": "تجاوز بوتستراب", + "description": "يتجاوز إعدادات واجهة المستخدم لـ بوتستراب", + "properties": { + "app_appearance": { + "name": "مظهر التطبيق", + "description": "تعيين مظهر تطبيق ثابت" + }, + "home_tab": { + "name": "علامة الصفحة الرئيسية", + "description": "يتجاوز علامة البداية عند فتح سناب شات" + }, + "simple_snapchat":{ + "name": "سناب شات مبسط", + "description": "يسمح بإصدار مبسط من سناب شات" + } + } + }, + "map_friend_nametags": { + "name": "علامات أسماء الأصدقاء المحسنة على الخريطة", + "description": "يحسن علامات أسماء الأصدقاء على خرائط سناب" + }, + "prevent_message_list_auto_scroll": { + "name": "منع التمرير التلقائي لقائمة الرسائل", + "description": "يمنع قائمة الرسائل من التمرير إلى الأسفل عند إرسال/استقبال رسالة" + }, + "streak_expiration_info": { + "name": "عرض معلومات انتهاء الستريك", + "description": "يعرض مؤقت انتهاء الستريك بجانب عداد الستريك" + }, + "hide_friend_feed_entry": { + "name": "إخفاء إدخال خلاصة الأصدقاء", + "description": "يخفي صديقًا معينًا من خلاصة الأصدقاء\nاستخدم علامة الاجتماعية لإدارة هذه الميزة" + }, + "hide_streak_restore": { + "name": "إخفاء زر استعادة الستريك", + "description": "يخفي زر الاستعادة في خلاصة الأصدقاء" + }, + "hide_quick_add_suggestions": { + "name": "إخفاء اقتراحات الإضافة السريعة", + "description": "يزيل اقتراحات الإضافة السريعة للأصدقاء" + }, + "hide_story_suggestions": { + "name": "إخفاء اقتراحات القصص", + "description": "يزيل الاقتراحات من صفحة القصص" + }, + "hide_ui_components": { + "name": "إخفاء مكونات واجهة المستخدم", + "description": "اختر مكونات واجهة المستخدم التي تريد إخفاءها" + }, + "opera_media_quick_info": { + "name": "معلومات سريعة عن الوسائط في Opera", + "description": "يعرض معلومات مفيدة عن الوسائط مثل تاريخ الإنشاء في قائمة سياق المشاهدة" + }, + "old_bitmoji_selfie": { + "name": "صورة بيتموجي القديمة", + "description": "يعيد صور بيتموجي الذاتية من إصدارات سناب شات الأقدم" + }, + "disable_spotlight": { + "name": "تعطيل منصة الأضواء", + "description": "يعطل صفحة منصة الأضواء" + }, + "friend_feed_menu_buttons": { + "name": "أزرار قائمة خلاصة الأصدقاء", + "description": "اختر الأزرار التي تريد عرضها في قائمة خلاصة الأصدقاء" + }, + "auto_close_friend_feed_menu": { + "name": "إغلاق قائمة خلاصة الأصدقاء تلقائيًا", + "description": "يغلق قائمة خلاصة الأصدقاء تلقائيًا بعد الضغط على زر إعداد" + }, + "vertical_story_viewer": { + "name": "عارض القصص العمودي", + "description": "يسمح بعارض القصص العمودي لجميع القصص" + }, + "enable_friend_feed_menu_bar": { + "name": "شريط قائمة خلاصة الأصدقاء", + "description": "يسمح بشريط قائمة خلاصة الأصدقاء الجديد" + }, + "message_indicators": { + "name": "مؤشرات الرسائل", + "description": "يضيف أيقونات مؤشرات محددة إلى الرسائل\nملاحظة: قد لا تكون المؤشرات دقيقة بنسبة 100%" + }, + "stealth_mode_indicator": { + "name": "مؤشر وضع التخفي", + "description": "يضيف رمز \uD83D\uDC7B بجانب المحادثات في وضع التخفي" + }, + "edit_text_override": { + "name": "تجاوز نص التحرير", + "description": "يتجاوز سلوك حقل النص" + } + } + }, + "messaging": { + "name": "المراسلة", + "description": "تغيير طريقة تفاعلك مع الأصدقاء", + "properties": { + "bypass_screenshot_detection": { + "name": "تجاوز اكتشاف لقطة الشاشة", + "description": "يمنع سناب شات من اكتشاف عندما تأخذ لقطة شاشة" + }, + "anonymous_story_viewing": { + "name": "مشاهدة القصص بشكل مجهول", + "description": "يمنع أي شخص من معرفة أنك قد شاهدت قصته" + }, + "prevent_story_rewatch_indicator": { + "name": "منع مؤشر إعادة مشاهدة القصة", + "description": "يمنع أي شخص من معرفة أنك قد أعدت مشاهدة قصته" + }, + "hide_peek_a_peek": { + "name": "إخفاء Peek-a-Peek", + "description": "يمنع إرسال إشعار عندما تنزلق إلى محادثة" + }, + "hide_bitmoji_presence": { + "name": "إخفاء وجود بيتموجي", + "description": "يمنع ظهور بيتموجي الخاص بك أثناء الدردشة" + }, + "hide_typing_notifications": { + "name": "إخفاء إشعارات الكتابة", + "description": "يمنع أي شخص من معرفة أنك تكتب رسالة" + }, + "unlimited_snap_view_time": { + "name": "وقت مشاهدة السناب غير محدود", + "description": "يزيل الحد الزمني لمشاهدة السنابات" + }, + "auto_mark_as_read": { + "name": "وضع علامة مقروء تلقائيًا", + "description": "يضع علامة مقروء على الرسائل/السنابات تلقائيًا حتى عند تمكين وضع التخفي" + }, + "mark_snap_as_seen_button": { + "name": "زر وضع علامة على السناب كمقروء", + "description": "يضيف زرًا لوضع علامة على السناب كمقروء عند مشاهدته.\nسيعمل هذا حتى عند تمكين وضع التخفي" + }, + "skip_when_marking_as_seen": { + "name": "تخطي عند وضع علامة مقروء", + "description": "يتخطى تلقائيًا إلى السناب التالي عند وضع علامة مقروء على السناب.\nاستخدم مع زر وضع علامة على السناب كمقروء" + }, + "loop_media_playback": { + "name": "تكرار تشغيل الوسائط", + "description": "يكرر تشغيل الوسائط عند مشاهدة السنابات/القصص" + }, + "disable_replay_in_ff": { + "name": "تعطيل إعادة التشغيل في خلاصة الأصدقاء", + "description": "يعطل القدرة على إعادة التشغيل بالضغط المطول من خلاصة الأصدقاء" + }, + "half_swipe_notifier": { + "name": "إشعار سحب الشاشة النصفي", + "description": "يخطرك عندما يسحب شخص نصف الشاشة", + "properties": { + "min_duration": { + "name": "المدة الأدنى", + "description": "المدة الأدنى لسحب الشاشة النصفي (بالثواني)" + }, + "max_duration": { + "name": "المدة الأقصى", + "description": "المدة الأقصى لسحب الشاشة النصفي (بالثواني)" + } + } + }, + "call_start_confirmation": { + "name": "تأكيد بدء المكالمة", + "description": "يعرض مربع حوار تأكيد عند بدء مكالمة" + }, + "unlimited_conversation_pinning": { + "name": "تثبيت المحادثات غير المحدود", + "description": "يسمح لك بتثبيت عدد غير محدود من المحادثات محليًا" + }, + "disable_snap_mode_restrictions": { + "name": "تعطيل قيود وضع السناب", + "description": "يسمح لك بمشاهدة السنابات ذاتية التدمير دون قيود" + }, + "prevent_message_sending": { + "name": "منع إرسال الرسائل", + "description": "يمنع إرسال أنواع معينة من الرسائل" + }, + "friend_mutation_notifier": { + "name": "إشعار تغيير الصديق", + "description": "يخطرك عندما يتغير شيء ما في ملف تعريف الصديق" + }, + "better_notifications": { + "name": "إشعارات أفضل", + "description": "يضيف المزيد من المعلومات في الإشعارات المستلمة", + "properties": { + "group_notifications": { + "name": "تجميع الإشعارات", + "description": "يجمع الإشعارات في إشعار واحد" + }, + "chat_preview": { + "name": "معاينة المحادثة", + "description": "يعرض معاينة للرسائل المستلمة في الإشعار" + }, + "media_preview": { + "name": "معاينة الوسائط", + "description": "يعرض معاينة لأنواع الوسائط المحددة في الإشعار" + }, + "media_caption": { + "name": "تسمية الوسائط", + "description": "يعرض التسمية المرفقة بالوسائط في الإشعار" + }, + "stacked_media_messages": { + "name": "رسائل الوسائط المكدسة", + "description": "يجمع عدة رسائل وسائط في إشعار نصي واحد عندما لا يمكن معاينتها. استخدم مع معاينة المحادثة" + }, + "friend_add_source": { + "name": "مصدر إضافة الصديق", + "description": "يعرض مصدر طلب الصداقة في الإشعار" + }, + "reply_button": { + "name": "زر الرد", + "description": "يضيف زر رد إلى الإشعار" + }, + "smart_replies": { + "name": "ردود ذكية", + "description": "يضيف ردودًا مقترحة إلى الإشعارات (آندرويد 10+). استخدم مع زر الرد" + }, + "download_button": { + "name": "زر التنزيل", + "description": "يسمح لك بتنزيل الوسائط من الإشعار" + }, + "mark_as_read_button": { + "name": "زر وضع علامة مقروء", + "description": "يسمح لك بوضع علامة مقروء على الرسالة من الإشعار" + }, + "mark_as_read_and_save_in_chat": { + "name": "وضع علامة مقروء وحفظ في المحادثة", + "description": "يضيف زرًا لوضع علامة مقروء وحفظ في المحادثة إلى الإشعار" + } + } + }, + "notification_blacklist": { + "name": "القائمة السوداء للإشعارات", + "description": "اختر الإشعارات التي يجب حظرها" + }, + "message_logger": { + "name": "مسجل الرسائل", + "description": "يمنع حذف الرسائل", + "properties": { + "keep_my_own_messages": { + "name": "حفظ رسائلي الخاصة", + "description": "يمنع حذف رسائلك الخاصة" + }, + "auto_purge": { + "name": "التنظيف التلقائي", + "description": "يحذف الرسائل المخزنة مؤقتًا التي تكون أقدم من الوقت المحدد تلقائيًا" + }, + "message_filter": { + "name": "تصفية الرسائل", + "description": "اختر الرسائل التي يجب تسجيلها (اتركها فارغة لجميع الرسائل)" + }, + "deleted_message_color": { + "name": "لون الرسالة المحذوفة", + "description": "تعيين لون الرسائل المحذوفة" + } + } + }, + "auto_save_messages_in_conversations": { + "name": "حفظ الرسائل تلقائيًا", + "description": "يحفظ كل الرسائل في المحادثات تلقائيًا" + }, + "gallery_media_send_override": { + "name": "تجاوز إرسال الوسائط من المعرض", + "description": "يخدع مصدر الوسائط عند الإرسال من المعرض" + }, + "strip_media_metadata": { + "name": "إزالة بيانات الوسائط الوصفية", + "description": "يزيل البيانات الوصفية للوسائط قبل إرسالها كرسالة" + }, + "bypass_message_retention_policy": { + "name": "تجاوز سياسة الاحتفاظ بالرسائل", + "description": "يمنع حذف الرسائل بعد مشاهدتها" + }, + "bypass_message_action_restrictions": { + "name": "تجاوز قيود إجراءات الرسائل", + "description": "يسمح لك بالرد على سناب دون فتحه أو حفظ رسالة غير قابلة للحفظ" + }, + "remove_groups_locked_status": { + "name": "إزالة حالة المجموعات المقفلة", + "description": "يسمح لك بمشاهدة معلومات المجموعة بعد طردك" + }, + "double_tap_chat_action": { + "name": "إجراء النقر المزدوج في المحادثة", + "description": "ينفذ إجراءً مخصصًا عند النقر المزدوج على رسالة في المحادثة" + }, + "double_tap_chat_action_custom_emoji": { + "name": "إيموجي رد فعل مخصص للنقر المزدوج", + "description": "تعيين إيموجي رد فعل مخصص لإجراء النقر المزدوج في المحادثة" + }, + "auto_reply": { + "name": "الرد التلقائي", + "description": "يرد تلقائيًا على الرسائل الواردة عندما تكون بعيدًا", + "properties": { + "allow_running_in_background": { + "name": "السماح بالتشغيل في الخلفية", + "description": "يسمح للرد التلقائي بالعمل في الخلفية. ملاحظة: سيؤدي هذا إلى استنزاف بطاريتك بشكل كبير" + }, + "cooldown_seconds": { + "name": "ثواني التبريد", + "description": "الحد الأدنى للوقت بين الردود التلقائية على نفس المحادثة (بالثواني)" + }, + "message_age_threshold": { + "name": "عمر الرسالة الحد الأدنى", + "description": "الرد فقط على الرسائل المستلمة خلال هذه الفترة الزمنية (بالثواني)" + }, + "ai_config": { + "name": "إعدادات الذكاء الاصطناعي", + "description": "إعدادات الردود التلقائية المدعومة بالذكاء الاصطناعي", + "properties": { + "enable_ai_replies": { + "name": "تمكين الردود الذكية", + "description": "استخدام الذكاء الاصطناعي لإنشاء ردود تلقائية ذكية بدلاً من الرسائل النموذجية" + }, + "ai_endpoint_url": { + "name": "رابط خدمة الذكاء الاصطناعي", + "description": "رابط API لخدمة الذكاء الاصطناعي (مثل OpenAI أو خادم ذكي محلي)" + }, + "ai_model": { + "name": "نموذج الذكاء الاصطناعي", + "description": "نموذج الذكاء الاصطناعي المستخدم لإنشاء الردود (مثل gpt-3.5-turbo، gpt-4)" + }, + "ai_api_key": { + "name": "مفتاح API للذكاء الاصطناعي", + "description": "مفتاح API للمصادقة مع خدمة الذكاء الاصطناعي" + }, + "ai_system_prompt": { + "name": "موجه النظام للذكاء الاصطناعي", + "description": "موجه النظام الذي يحدد شخصية وسلوك الذكاء الاصطناعي" + }, + "ai_max_tokens": { + "name": "الحد الأقصى للرموز", + "description": "الحد الأقصى لعدد الرموز (الكلمات) التي يمكن للذكاء الاصطناعي استخدامها في الردود" + }, + "ai_temperature": { + "name": "درجة حرارة الذكاء الاصطناعي", + "description": "يتحكم في العشوائية في ردود الذكاء الاصطناعي (0.0 = حتمي، 2.0 = عشوائي جداً)" + }, + "ai_context_length": { + "name": "طول السياق", + "description": "عدد الرسائل السابقة المراد تضمينها كسياق لردود الذكاء الاصطناعي" + }, + "ai_personality_traits": { + "name": "سمات الشخصية", + "description": "سمات الشخصية مفصولة بفواصل للذكاء الاصطناعي (مثل ودود، غير رسمي، مفيد)" + }, + "ai_response_style": { + "name": "أسلوب الرد", + "description": "الأسلوب العام لردود الذكاء الاصطناعي" + }, + "ai_use_conversation_history": { + "name": "استخدام تاريخ المحادثة", + "description": "تضمين الرسائل السابقة كسياق لردود ذكية أكثر صلة" + }, + "ai_include_friend_info": { + "name": "تضمين معلومات الصديق", + "description": "تضمين اسم الصديق والمعلومات المتاحة الأخرى في سياق الذكاء الاصطناعي" + }, + "ai_fallback_to_template": { + "name": "العودة للنموذج", + "description": "استخدام الرسائل النموذجية إذا فشل الذكاء الاصطناعي في إنشاء رد" + }, + "ai_request_timeout": { + "name": "مهلة طلب الذكاء الاصطناعي", + "description": "الحد الأقصى للوقت لانتظار رد الذكاء الاصطناعي (بالثواني)" + }, + "ai_retry_attempts": { + "name": "محاولات إعادة المحاولة", + "description": "عدد مرات إعادة محاولة طلبات الذكاء الاصطناعي في حالة الفشل" + }, + "ai_response_language": { + "name": "لغة رد الذكاء الاصطناعي", + "description": "لغة ردود الذكاء الاصطناعي (تلقائي = نفس لغة الرسالة المستلمة)" + } + } + }, + "auto_trigger_config": { + "name": "إعدادات المشغلات التلقائية", + "description": "إعدادات مشغلات الرد التلقائي وقوالب الرسائل", + "properties": { + "friendSpecificGreeting": { + "name": "تحية خاصة بالصديق", + "description": "إضافة اسم الصديق إلى الردود التلقائية للتخصيص" + }, + "friendGreeting": { + "name": "تحية الصديق", + "description": "نص التحية لاستخدامه عند تمكين التحية الخاصة بالصديق" + }, + "auto_reply_content_types": { + "name": "مشغلات الرد التلقائي", + "description": "اختر أنواع الرسائل التي يجب أن تشغل الرد التلقائي" + }, + "chat_messages": { + "name": "ردود رسائل المحادثة", + "description": "ردود على رسائل المحادثة النصية" + }, + "snap_messages": { + "name": "ردود رسائل السناب", + "description": "ردود على رسائل السناب" + }, + "story_share_messages": { + "name": "ردود مشاركات القصص", + "description": "رسائل الرد التلقائي لمشاركات القصص" + }, + "story_reply_messages": { + "name": "ردود تعليقات القصص", + "description": "رسائل الرد التلقائي لتعليقات القصص" + }, + "external_media_messages": { + "name": "ردود رسائل الوسائط الخارجية", + "description": "ردود على رسائل الوسائط الخارجية" + }, + "voice_note_messages": { + "name": "ردود الملاحظات الصوتية", + "description": "ردود على الملاحظات الصوتية" + }, + "sticker_messages": { + "name": "ردود الملصقات", + "description": "ردود على الملصقات" + }, + "tiny_snap_messages": { + "name": "ردود السنابات الصغيرة", + "description": "ردود على السنابات الصغيرة" + }, + "map_reaction_messages": { + "name": "ردود تفاعلات الخريطة", + "description": "ردود على تفاعلات الخريطة" + }, + "half_swipe_messages": { + "name": "رسائل السحب النصفي", + "description": "رسائل الرد التلقائي للسحبات النصفية" + } + } + } + } + }, + "auto_open_snaps": { + "name": "إعدادات فتح السنابات تلقائيًا", + "description": "تكوين إعدادات التأخير والطابور لفتح السنابات تلقائيًا", + "properties": { + "allow_running_in_background": { + "name": "السماح بالتشغيل في الخلفية", + "description": "يسمح لفتح السنابات تلقائيًا بالعمل في الخلفية. ملاحظة: سيؤدي هذا إلى استنزاف بطاريتك بشكل كبير" + }, + "min_delay": { + "name": "الحد الأدنى للتأخير (مللي ثانية)", + "description": "الحد الأدنى للتأخير بالمللي ثانية قبل فتح السناب" + }, + "max_delay_ms": { + "name": "الحد الأقصى للتأخير (مللي ثانية)", + "description": "الحد الأقصى للتأخير بالمللي ثانية قبل فتح السناب" + }, + "queue_size": { + "name": "حجم الطابور", + "description": "الحد الأقصى لعدد السنابات في الطابور" + }, + "retry_attempts": { + "name": "محاولات إعادة المحاولة", + "description": "عدد مرات إعادة محاولة فتح السناب إذا فشل" + }, + "retry_delay": { + "name": "تأخير إعادة المحاولة (مللي ثانية)", + "description": "التأخير بالمللي ثانية بين محاولات إعادة المحاولة" + } + } + }, + "auto_delete_sent_messages": { + "name": "حذف الرسائل المرسلة تلقائيًا", + "description": "يحذف الرسائل المرسلة تلقائيًا بعد فترة زمنية محددة", + "properties": { + "delete_after_value": { + "name": "الحذف بعد (القيمة)", + "description": "القيمة الزمنية قبل حذف الرسالة المرسلة" + }, + "delete_after_unit": { + "name": "وحدة الوقت", + "description": "اختر وحدة الوقت لتأخير الحذف" + }, + "message_types": { + "name": "أنواع الرسائل", + "description": "اختر أنواع الرسائل التي يجب حذفها تلقائيًا" + }, + "show_countdown": { + "name": "إظهار العد التنازلي", + "description": "إظهار عد تنازلي قبل حذف الرسالة" + }, + "show_notification": { + "name": "إظهار الإشعار", + "description": "إظهار إشعار أثناء العد التنازلي" + }, + "allow_running_in_background": { + "name": "السماح بالعمل في الخلفية", + "description": "السماح للميزة بالعمل في الخلفية" + } + } + }, + "instant_translation": { + "name": "مترجم الرسائل", + "description": "ترجمة الرسائل الواردة تلقائياً إلى لغتك المفضلة", + "properties": { + "enabled": { + "name": "تفعيل مترجم الرسائل", + "description": "تفعيل الترجمة التلقائية للرسائل" + }, + "source_language": { + "name": "لغة المصدر", + "description": "اللغة المطلوب الترجمة منها (استخدم 'auto' للكشف التلقائي)" + }, + "target_language": { + "name": "لغة الهدف", + "description": "اللغة المطلوب الترجمة إليها" + }, + "show_original": { + "name": "إظهار النص الأصلي", + "description": "إظهار النص الأصلي للرسالة مع الترجمة" + }, + "show_translation": { + "name": "إظهار الترجمة", + "description": "إظهار النص المترجم" + }, + "translation_position": { + "name": "موضع الترجمة", + "description": "أين تعرض الترجمة بالنسبة للنص الأصلي" + }, + "auto_translate": { + "name": "ترجمة تلقائية", + "description": "ترجمة الرسائل تلقائياً دون تدخل المستخدم" + }, + "translate_on_tap": { + "name": "ترجمة عند النقر", + "description": "ترجمة الرسالة عند النقر عليها" + }, + "supported_languages": { + "name": "اللغات المدعومة", + "description": "اللغات المتاحة للترجمة" + }, + "pause_on_error": { + "name": "إيقاف عند الخطأ", + "description": "إيقاف الترجمة عند حظر الخدمة" + }, + "max_retries": { + "name": "أقصى محاولات", + "description": "الحد الأقصى لعدد محاولات إعادة المحاولة" + }, + "retry_delay": { + "name": "تأخير إعادة المحاولة", + "description": "التأخير بين محاولات إعادة المحاولة (بالميلي ثانية)" + } + } + } + } + }, + "global": { + "name": "عام", + "description": "تعديل إعدادات سناب شات العامة", + "properties": { + "better_location": { + "name": "موقع أفضل", + "description": "يحسن موقع سناب شات", + "properties": { + "spoof_location": { + "name": "تزييف الموقع", + "description": "يخدع موقعك إلى موقع محدد" + }, + "coordinates": { + "name": "الإحداثيات", + "description": "تعيين إحداثيات الموقع المزيف" + }, + "walk_radius": { + "name": "نصف قطر المشي", + "description": "المشي عشوائيًا ضمن هذا النصف قطر (قدم)" + }, + "always_update_location": { + "name": "تحديث الموقع دائمًا", + "description": "يجبر سناب شات على تحديث الموقع حتى إذا لم يتم استقبال بيانات الموقع" + }, + "suspend_location_updates": { + "name": "تعطيل تحديثات الموقع", + "description": "يمنع تحديث موقعك" + }, + "spoof_battery_level": { + "name": "تزييف مستوى البطارية", + "description": "يخدع مستوى بطارية جهازك على الخريطة\nيجب أن تكون القيمة بين 0 و 100" + }, + "spoof_headphones": { + "name": "تزييف سماعات الرأس", + "description": "يخدع حالة الاستماع إلى الموسيقى على الخريطة" + }, + "show_battery_level": { + "name": "عرض مستوى البطارية", + "description": "يعرض مستوى بطارية أصدقائك على الخريطة" + } + } + }, + "snapchat_plus": { + "name": "سناب شات بلس", + "description": "يسمح بميزات سناب شات بلس\nقد لا تعمل بعض الميزات المعتمدة على الخادم" + }, + "media_upload_quality": { + "name": "جودة تحميل الوسائط", + "description": "يتجاوز جودة تحميل الوسائط", + "properties": { + "force_video_upload_source_quality": { + "name": "فرض جودة مصدر تحميل الفيديو", + "description": "يجبر سناب شات على استخدام جودة المصدر عند تحميل الفيديوهات\nيرجى ملاحظة أن هذا قد لا يزيل البيانات الوصفية من الوسائط" + }, + "disable_image_compression": { + "name": "تعطيل ضغط الصور", + "description": "يعطل ضغط الصور عند تحميل الوسائط" + }, + "custom_image_upload_format": { + "name": "تنسيق تحميل الصور المخصص", + "description": "تعيين تنسيق تحميل صور مخصص\nاختر تنسيقًا غير مضغوط (مثل PNG) للحصول على أفضل جودة" + } + } + }, + "disable_confirmation_dialogs": { + "name": "تعطيل مربعات حوار التأكيد", + "description": "يؤكد تلقائيًا الإجراءات المحددة" + }, + "auto_updater": { + "name": "التحديث التلقائي", + "description": "يتحقق تلقائيًا من وجود تحديثات جديدة" + }, + "disable_metrics": { + "name": "تعطيل المقاييس", + "description": "يمنع إرسال بيانات تحليلية محددة إلى سناب شات" + }, + "disable_story_sections": { + "name": "تعطيل أقسام القصص", + "description": "يزيل الأقسام من صفحة القصص\nقد يتطلب تحديثًا ليعمل بشكل صحيح" + }, + "block_ads": { + "name": "حظر الإعلانات", + "description": "يمنع عرض الإعلانات" + }, + "disable_custom_tabs": { + "name": "تعطيل علامات التبويب المخصصة", + "description": "يفتح الروابط في التطبيقات المدعومة بدلاً من متصفح الويب" + }, + "disable_permission_requests": { + "name": "تعطيل طلبات الأذونات", + "description": "يمنع سناب شات من طلب أذونات محددة" + }, + "disable_memories_snap_feed": { + "name": "تعطيل خلاصة الذكريات", + "description": "يمنع سناب شات من عرض الذكريات الأخيرة عند التمرير لأعلى في الكاميرا" + }, + "spotlight_comments_username": { + "name": "اسم المستخدم في تعليقات منصة الأضواء", + "description": "يعرض اسم المستخدم للمؤلف في تعليقات منصة الأضواء" + }, + "spotlight_comments_username_icon": { + "name": "أيقونة اسم المستخدم في منصة الأضواء", + "description": "كتابه أو رمز تعبيري مخصص لعرضه بجانب معلومات المستخدم" + }, + "bypass_video_length_restriction": { + "name": "تجاوز قيود طول الفيديو", + "description": "واحد: إرسال فيديو واحد\nتقسيم: تقسيم الفيديوهات بعد التحرير" + }, + "default_video_playback_rate": { + "name": "معدل تشغيل الفيديو الافتراضي", + "description": "تعيين السرعة الافتراضية لتشغيل الفيديوهات\nيجب أن تكون القيمة بين 0.1 و 4.0" + }, + "video_playback_rate_slider": { + "name": "شريط تمرير معدل تشغيل الفيديو", + "description": "يضيف شريط تمرير في قائمة سياق Opera لتغيير معدل تشغيل الفيديو\nملاحظة: التغييرات تنطبق فقط على الفيديوهات اللاحقة" + }, + "disable_google_play_dialogs": { + "name": "تعطيل مربعات حوار خدمات جوجل", + "description": "يمنع عرض مربعات حوار توفر خدمات جوجل" + }, + "default_volume_controls": { + "name": "ضوابط الصوت الافتراضية", + "description": "يجبر سناب شات على استخدام ضوابط الصوت النظامية" + }, + "disable_telecom_framework": { + "name": "تعطيل إطار تيلكوم", + "description": "يمنع سناب شات من استخدام إطار آندرويد تيلكوم\nهذا يسمح لك بالاستماع إلى الموسيقى أثناء المكالمة" + }, + "hide_active_music": { + "name": "إخفاء الموسيقى النشطة", + "description": "يمنع سناب شات من معرفة أنك تستمع إلى الموسيقى\nهذا سيسمح لك بأخذ سنابات باستخدام أزرار التحكم في الصوت أثناء الاستماع إلى الموسيقى" + }, + "disable_snap_splitting": { + "name": "تعطيل تقسيم السنابات", + "description": "يمنع تقسيم السنابات إلى أجزاء متعددة\nالصور التي ترسلها ستتحول إلى فيديوهات" + } + } + }, + "rules": { + "name": "القواعد", + "description": "إدارة الميزات التلقائية للأفراد" + }, + "camera": { + "name": "الكاميرا", + "description": "اضبط الإعدادات المناسبة لالتقاط السناب المثالي", + "properties": { + "disable_cameras": { + "name": "تعطيل الكاميرات", + "description": "يمنع سناب شات من استخدام الكاميرات المحددة" + }, + "black_photos": { + "name": "صور سوداء", + "description": "يستبدل الصور الملتقطة بخلفية سوداء\nلا تتأثر الفيديوهات" + }, + "immersive_camera_preview": { + "name": "معاينة كاميرا غامرة", + "description": "يمنع سناب شات من اقتصاص معاينة الكاميرا\nقد يتسبب هذا في وميض الكاميرا على بعض الأجهزة" + }, + "override_front_resolution": { + "name": "تجاوز دقة الكاميرا الأمامية", + "description": "يتجاوز دقة الكاميرا للكاميرا الأمامية" + }, + "override_back_resolution": { + "name": "تجاوز دقة الكاميرا الخلفية", + "description": "يتجاوز دقة الكاميرا للكاميرا الخلفية" + }, + "custom_resolution": { + "name": "دقة مخصصة", + "description": "تعيين دقة كاميرا مخصصة، العرض × الارتفاع (مثال: 1920x1080).\nيجب أن تدعم جهازك الدقة المخصصة" + }, + "front_custom_frame_rate": { + "name": "معدل إطارات مخصص للكاميرا الأمامية", + "description": "يتجاوز معدل إطارات الكاميرا الأمامية" + }, + "back_custom_frame_rate": { + "name": "معدل إطارات مخصص للكاميرا الخلفية", + "description": "يتجاوز معدل إطارات الكاميرا الخلفية" + }, + "force_camera_source_encoding": { + "name": "فرض ترميز مصدر الكاميرا", + "description": "يفرض ترميز مصدر الكاميرا" + }, + "startup_default_camera": { + "name": "الكاميرا الافتراضية عند البدء", + "description": "تعيين الكاميرا الافتراضية عند فتح سناب شات" + }, + "hevc_recording": { + "name": "تسجيل HEVC", + "description": "يستخدم برنامج ترميز HEVC (H.265) لتسجيل الفيديو" + } + } + }, + "streaks_reminder": { + "name": "تذكير الستريك", + "description": "يخطرك دوريًا عن الستريك الخاص بك", + "properties": { + "interval": { + "name": "الفاصل الزمني", + "description": "الفاصل الزمني بين كل تذكير (ساعات)" + }, + "remaining_hours": { + "name": "الوقت المتبقي", + "description": "الوقت المتبقي قبل عرض الإشعار (ساعات)" + }, + "group_notifications": { + "name": "تجميع الإشعارات", + "description": "يجمع الإشعارات في إشعار واحد" + } + } + }, + "experimental": { + "name": "تجريبي", + "description": "ميزات تجريبية", + "properties": { + "native_hooks": { + "name": "خطافات أصلية", + "description": "ميزات غير آمنة تتصل بالكود الأصلي لـ سناب شات", + "properties": { + "composer_hooks": { + "name": "خطافات Composer", + "description": "يحقن الكود في إطار واجهة المستخدم Cross-platform لـ Composer", + "properties": { + "show_first_created_username": { + "name": "عرض أول اسم مستخدم تم إنشاؤه", + "description": "يعرض أول اسم مستخدم تم إنشاؤه بجانب اسم المستخدم الحالي في صفحة الملف الشخصي" + }, + "bypass_camera_roll_limit": { + "name": "تجاوز حد معرض الكاميرا", + "description": "يزيد الحد الأقصى لعدد الوسائط التي يمكنك إرسالها من معرض الكاميرا" + }, + "custom_self_destruct_snap_delay": { + "name": "تأخير ذاتي التدمير مخصص للسناب", + "description": "يعطي المزيد من الخيارات للمؤقت الذاتي التدمير عند إرسال سناب" + }, + "composer_console": { + "name": "وحدة تحكم Composer", + "description": "يسمح لك بتنفيذ كود JavaScript في Composer (arm64 فقط)" + }, + "composer_logs": { + "name": "سجلات Composer", + "description": "إعادة توجيه سجلات وحدة تحكم Composer إلى سناب إنهانس" + } + } + }, + "disable_bitmoji": { + "name": "تعطيل بيتموجي", + "description": "يعطل بيتموجي لملفات تعريف الأصدقاء" + }, + "custom_emoji_font": { + "name": "خط إيموجي مخصص", + "description": "يسمح لك باستخدام خط إيموجي مخصص. يعمل فقط مع خطوط .ttf" + }, + "custom_shared_library": { + "name": "مكتبة مشتركة مخصصة", + "description": "تحميل مكتبة مشتركة مخصصة في سناب شات. هذه الميزة مخصصة لأغراض الاختبار فقط" + } + } + }, + "spoof": { + "name": "تزييف", + "description": "تزييف معلومات مختلفة عنك", + "properties": { + "play_store_installer_package_name": { + "name": "اسم حزمة مثبت Play Store", + "description": "يتجاوز اسم حزمة المثبت إلى com.android.vending" + }, + "remove_vpn_transport_flag": { + "name": "إزالة علامة نقل VPN", + "description": "يمنع سناب شات من اكتشاف VPNs" + }, + "remove_mock_location_flag": { + "name": "إزالة علامة الموقع المزيف", + "description": "يمنع سناب شات من اكتشاف الموقع المزيف" + } + } + }, + "convert_message_locally": { + "name": "تحويل الرسائل محليًا", + "description": "يحول السنابات إلى وسائط خارجية للمحادثة محليًا. يظهر هذا في قائمة سياق تنزيل المحادثة" + }, + "media_file_picker": { + "name": "منتقي ملفات الوسائط", + "description": "يسمح لك باختيار أي ملف فيديو/صوت من المعرض" + }, + "story_logger": { + "name": "مسجل القصص", + "description": "يوفر سجلًا لقصص الأصدقاء" + }, + "call_recorder": { + "name": "مسجل المكالمات", + "description": "يسجل المكالمات الصوتية تلقائيًا" + }, + "account_switcher": { + "name": "مبدل الحسابات", + "description": "يسمح لك بالتبديل بين الحسابات دون تسجيل الخروج\nاضغط مطولًا على أيقونة البحث بجانب صورة بيتموجي لفتح القائمة\nملاحظة: هذه الميزة تجريبية ومن المحتمل أن تتغير في المستقبل", + "properties": { + "auto_backup_current_account": { + "name": "نسخ احتياطي تلقائي للحساب الحالي", + "description": "يقوم بنسخ احتياطي تلقائي للحساب الحالي عند تسجيل الخروج أو تبديل الحسابات" + } + } + }, + "better_transcript": { + "name": "نسخة أفضل", + "description": "يحسن نسخة الملاحظة الصوتية", + "properties": { + "force_transcription": { + "name": "فرض نسخ الملاحظة الصوتية", + "description": "يسمح بنسخ جميع الملاحظات الصوتية" + }, + "preferred_transcription_lang": { + "name": "لغة النسخ المفضلة", + "description": "اللغة المفضلة لنسخ الملاحظة الصوتية (مثال: EN, ES, FR)" + }, + "notification_transcript": { + "name": "نسخة الإشعار", + "description": "ينسخ الملاحظات الصوتية في الإشعارات\nتتطلب هذه الميزة تمكين ميزة معاينة المحادثة في الإشعارات الأفضل" + } + } + }, + "voice_note_auto_play": { + "name": "تشغيل الملاحظات الصوتية تلقائيًا", + "description": "يشغل الملاحظة الصوتية التالية تلقائيًا بعد انتهاء الحالية" + }, + "friend_notes": { + "name": "ملاحظات الأصدقاء", + "description": "يسمح لك بإضافة ملاحظات إلى ملفات تعريف الأصدقاء" + }, + "cof_experiments": { + "name": "تجارب COF", + "description": "يسمح بميزات سناب شات غير المعلنة/بيتا" + }, + "edit_message": { + "name": "تحرير الرسائل", + "description": "يسمح لك بتحرير الرسائل في المحادثات" + }, + "context_menu_fix": { + "name": "إصلاح قائمة السياق", + "description": "محاولة إصلاح قائمة خلاصة الأصدقاء عندما يكون الجهاز غير متصل بالإنترنت ولا يمكن عرضها بشكل صحيح" + }, + "app_lock": { + "name": "قفل التطبيق", + "description": "يمنع الوصول إلى سناب شات بدون كلمة مرور", + "properties": { + "lock_on_resume": { + "name": "القفل عند الاستئناف", + "description": "يقفل التطبيق عند إعادة فتحه" + } + } + }, + "infinite_story_boost": { + "name": "تعزيز القصة اللانهائي", + "description": "يتجاوز حد تأخير تعزيز القصة" + }, + "meo_passcode_bypass": { + "name": "تجاوز كلمة مرور My Eyes Only", + "description": "يتجاوز كلمة مرور My Eyes Only\nسيعمل هذا فقط إذا تم إدخال كلمة المرور بشكل صحيح من قبل" + }, + "no_friend_score_delay": { + "name": "لا يوجد تأخير في نقاط الصديق", + "description": "يزيل التأخير عند عرض نقاط الصديق" + }, + "best_friend_pinning": { + "name": "تثبيت أفضل صديق", + "description": "يسمح لك بتثبيت صديق كأفضل صديق لك. ملاحظة: يمكنك فقط رؤية أفضل صديق لك" + }, + "e2ee": { + "name": "التشفير من طرف إلى طرف", + "description": "يشفر رسائلك باستخدام AES باستخدام مفتاح سري مشترك\nتأكد من حفظ مفتاحك في مكان آمن!", + "properties": { + "encrypted_message_indicator": { + "name": "مؤشر الرسالة المشفرة", + "description": "يضيف رمز \uD83D\uDD12 بجانب الرسائل المشفرة" + }, + "force_message_encryption": { + "name": "فرض تشفير الرسائل", + "description": "يمنع إرسال رسائل مشفرة إلى أشخاص لا يملكون تشفير E2E ممكّن فقط عند تحديد محادثات متعددة" + } + } + }, + "add_friend_source_spoof": { + "name": "تزييف مصدر إضافة الصديق", + "description": "يخدع مصدر طلب الصداقة" + }, + "hidden_snapchat_plus_features": { + "name": "ميزات سناب شات بلس المخفية", + "description": "يسمح بميزات سناب شات بلس غير المعلنة/بيتا\nقد لا يعمل على إصدارات سناب شات الأقدم" + }, + "custom_streaks_expiration_format": { + "name": "تنسيق انتهاء الستريك المخصص", + "description": "يخصص تنسيق انتهاء الستريك\n\nالمتغيرات المتاحة:\n - %c: عدد الستريك\n - %e: رمز الساعة الرملية\n - %d: الأيام\n - %h: الساعات\n - %m: الدقائق\n - %s: الثواني\n - %w: الوقت المتبقي" + }, + "prevent_forced_logout": { + "name": "منع تسجيل الخروج القسري", + "description": "يمنع سناب شات من تسجيل خروجك عند تسجيل الدخول على جهاز آخر" + }, + "snapscore_changes": { + "name": "تغييرات نقاط سناب", + "description": "يتتبع التغييرات في نقاط سناب الأصدقاء\nاستخدم هذه الميزة في إصدارات سناب شات الأحدث فقط" + } + } + }, + "scripting": { + "name": "البرمجة", + "description": "تشغيل نصوص برمجية مخصصة لتوسيع سناب إنهانس", + "properties": { + "developer_mode": { + "name": "وضع المطور", + "description": "يعرض معلومات التصحيح على واجهة مستخدم سناب شات" + }, + "module_folder": { + "name": "مجلد الوحدة", + "description": "المجلد الذي توجد فيه النصوص البرمجية" + }, + "auto_reload": { + "name": "إعادة التحميل التلقائي", + "description": "يعيد تحميل النصوص البرمجية تلقائيًا عند تغييرها" + }, + "integrated_ui": { + "name": "واجهة مستخدم متكاملة", + "description": "يسمح للنصوص البرمجية بإضافة مكونات واجهة مستخدم مخصصة إلى سناب شات" + }, + "disable_log_anonymization": { + "name": "تعطيل إخفاء الهوية للسجلات", + "description": "يعطل إخفاء الهوية للسجلات" + }, + "disable_optimization": { + "name": "تعطيل التحسين", + "description": "يعطل تحسين النصوص البرمجية. قد يؤدي هذا إلى مشاكل في الأداء." + } + } + }, + "friend_tracker": { + "name": "تتبع الأصدقاء", + "description": "يسجل نشاط الأصدقاء على سناب شات", + "properties": { + "record_messaging_events": { + "name": "تسجيل أحداث المراسلة", + "description": "يسجل أحداث المراسلة مثل فتح سناب، قراءة رسالة، إلخ." + }, + "allow_running_in_background": { + "name": "السماح بالتشغيل في الخلفية", + "description": "يسمح للمتتبع بالعمل في الخلفية. ملاحظة: سيؤدي هذا إلى استنزاف بطاريتك بشكل كبير" + }, + "auto_purge": { + "name": "التنظيف التلقائي", + "description": "يحذف الأحداث المخزنة مؤقتًا التي تكون أقدم من الوقت المحدد تلقائيًا" + } + } + } + }, + "options": { + "app_appearance": { + "always_light": "فاتح دائمًا", + "always_dark": "داكن دائمًا" + }, + "friend_feed_menu_buttons": { + "auto_download": "\u2B07\uFE0F تنزيل تلقائي", + "auto_save": "\uD83D\uDCAC حفظ الرسائل تلقائيًا", + "unsaveable_messages": "\u2B07\uFE0F رسائل غير قابلة للحفظ", + "auto_open_snaps": "\uD83D\uDCF7 فتح السنابات تلقائيًا", + "stealth": "\uD83D\uDC7B وضع التخفي", + "auto_reply": "\uD83D\uDCE8 رد تلقائي", + "auto_delete_sent_messages": "\uD83D\uDDD1\uFE0F حذف الرسائل المرسلة تلقائيًا", + "mark_snaps_as_seen": "\uD83D\uDC40 وضع علامة على السنابات كمقروءة", + "mark_stories_as_seen_locally": "\uD83D\uDC40 وضع علامة على القصص كمقروءة محليًا", + "conversation_info": "\uD83D\uDC64 معلومات المحادثة", + "e2e_encryption": "\uD83D\uDD12 استخدام تشفير من طرف إلى طرف" + }, + "path_format": { + "create_author_folder": "إنشاء مجلد لكل مؤلف", + "create_source_folder": "إنشاء مجلد لكل نوع مصدر وسائط", + "append_hash": "إضافة رمز فريد إلى اسم الملف", + "append_source": "إضافة مصدر الوسائط إلى اسم الملف", + "append_username": "إضافة اسم المستخدم إلى اسم الملف", + "append_date_time": "إضافة التاريخ والوقت إلى اسم الملف" + }, + "auto_download_sources": { + "friend_snaps": "سنابات الأصدقاء", + "friend_stories": "قصص الأصدقاء", + "public_stories": "قصص عامة", + "spotlight": "منصة الأضواء" + }, + "logging": { + "started": "بدأ", + "success": "نجاح", + "progress": "تقدم", + "failure": "فشل" + }, + "notifications": { + "chat_screenshot": "لقطة شاشة", + "chat_screen_record": "تسجيل شاشة", + "snap_replay": "إعادة تشغيل السناب", + "camera_roll_save": "حفظ في معرض الكاميرا", + "chat": "محادثة", + "chat_reply": "رد المحادثة", + "snap": "سناب", + "typing": "كتابة", + "stories": "قصص", + "speaking": "تحدث", + "chat_reaction": "رد فعل DM", + "group_chat_reaction": "رد فعل المجموعة", + "initiate_audio": "مكالمة صوتية واردة", + "abandon_audio": "مكالمة صوتية فائتة", + "initiate_video": "مكالمة فيديو واردة", + "abandon_video": "مكالمة فيديو فائتة", + "map_live_location": "الموقع المباشر على الخريطة" + }, + "gallery_media_send_override": { + "always_ask": "السؤال دائمًا", + "ORIGINAL": "وسائط أصلية", + "NOTE": "ملاحظة صوتية", + "SNAP": "سناب", + "SAVEABLE_SNAP": "سناب قابل للحفظ" + }, + "strip_media_metadata": { + "hide_caption_text": "إخفاء نص التسمية", + "hide_snap_filters": "إخفاء فلاتر السناب", + "hide_extras": "إخفاء الإضافات (مثل الإشارات)", + "remove_audio_note_duration": "إزالة مدة الملاحظة الصوتية", + "remove_audio_note_transcript_capability": "إزالة قدرة نسخ الملاحظة الصوتية" + }, + "hide_ui_components": { + "hide_profile_call_buttons": "إزالة أزرار المكالمة في الملف الشخصي", + "hide_chat_call_buttons": "إزالة أزرار المكالمة في المحادثة", + "hide_live_location_share_button": "إزالة زر مشاركة الموقع المباشر", + "hide_stickers_button": "إزالة زر الملصقات", + "hide_voice_record_button": "إزالة زر تسجيل الصوت", + "hide_unread_chat_hint": "إزالة تلميح المحادثة غير المقروءة", + "hide_post_to_story_buttons": "إزالة أزرار النشر في القصة قبل إرسال سناب", + "hide_billboard_prompt": "إزالة موجه لوحة الإعلانات في خلاصة الأصدقاء", + "hide_snapchat_plus_gift_reminders": "إزالة تذكيرات هدايا سناب شات بلس في المحادثات", + "hide_map_reactions": "إزالة تفاعلات الخريطة" + }, + "hide_story_suggestions": { + "hide_suggested_friend_stories": "إخفاء قصص الأصدقاء المقترحة", + "hide_my_stories": "إخفاء قصصي" + }, + "home_tab": { + "map": "الخريطة", + "chat": "المحادثة", + "camera": "الكاميرا", + "discover": "اكتشف", + "spotlight": "منصة الأضواء" + }, + "simple_snapchat": { + "always_enabled": "ممكّن دائمًا", + "always_disabled": "معطل دائمًا" + }, + "add_friend_source_spoof": { + "added_by_username": "باسم المستخدم", + "added_by_mention": "بالإشارة", + "added_by_group_chat": "بالمحادثة الجماعية", + "added_by_qr_code": "برمز QR", + "added_by_community": "بالمجتمع", + "added_by_quick_add": "بالإضافة السريعة (خطر كبير بالحظر)" + }, + "bypass_video_length_restriction": { + "single": "وسائط واحدة", + "split": "تقسيم الوسائط" + }, + "old_bitmoji_selfie": { + "2d": "بيتموجي ثنائي الأبعاد", + "3d": "بيتموجي ثلاثي الأبعاد" + }, + "disable_confirmation_dialogs": { + "erase_message": "مسح الرسالة", + "remove_friend": "إزالة الصديق", + "block_friend": "حظر الصديق", + "ignore_friend": "تجاهل الصديق", + "hide_friend": "إخفاء الصديق", + "hide_conversation": "إخفاء المحادثة", + "clear_conversation": "مسح المحادثة من خلاصة الأصدقاء" + }, + "auto_reload": { + "snapchat_only": "سناب شات فقط", + "all": "الكل (سناب شات + سناب إنهانس)" + }, + "edit_text_override": { + "multi_line_chat_input": "إدخال محادثة متعدد الأسطر", + "bypass_text_input_limit": "تجاوز حد إدخال النص" + }, + "auto_purge": { + "never": "أبدًا", + "1_hour": "1 ساعة", + "3_hours": "3 ساعات", + "6_hours": "6 ساعات", + "12_hours": "12 ساعة", + "1_day": "1 يوم", + "3_days": "3 أيام", + "1_week": "1 أسبوع", + "2_weeks": "أسبوعين", + "1_month": "1 شهر", + "3_months": "3 أشهر", + "6_months": "6 أشهر" + }, + "delete_after_unit": { + "seconds": "ثواني", + "minutes": "دقائق", + "hours": "ساعات" + }, + "disable_story_sections": { + "friends": "الأصدقاء", + "suggested_stories": "قصص مقترحة", + "following": "متابَعون", + "discover": "اكتشف" + }, + "disable_cameras":{ + "front": "الكاميرا الأمامية", + "back": "الكاميرا الخلفية" + }, + "disable_permission_requests": { + "notifications": "الإشعارات", + "read_media_images": "قراءة صور الوسائط", + "read_media_video": "قراءة فيديو الوسائط", + "camera": "الكاميرا", + "microphone": "الميكروفون", + "location": "الموقع", + "read_contacts": "قراءة جهات الاتصال", + "nearby_devices": "الأجهزة القريبة", + "phone_calls": "المكالمات الهاتفية" + }, + "message_indicators": { + "encryption_indicator": "إضافة رمز \uD83D\uDD12 بجانب الرسائل التي تم إرسالها إليك فقط", + "platform_indicator": "إضافة أيقونة النظام الذي تم إرسال الوسائط منه (مثل Android, iOS, Web)", + "location_indicator": "إضافة رمز \uD83D\uDCCD إلى السنابات عندما يتم إرسالها مع تمكين الموقع", + "ovf_editor_indicator": "يشير إلى ما إذا كان السناب قد تم إرساله باستخدام محرر OVF", + "director_mode_indicator": "إضافة رمز \u270F\uFE0F إلى السنابات عندما يتم إرسالها باستخدام وضع المخرج، والذي يمكن استخدامه لإرسال صور المعرض كسنابات" + }, + "auto_mark_as_read": { + "conversation_read": "وضع علامة مقروء على المحادثة عند إرسال رسالة", + "snap_reply": "وضع علامة مقروء على السنابات عند الرد عليها" + }, + "friend_mutation_notifier": { + "remove_friend": "إشعار عند إزالة شخص لك كصديق", + "birthday_changes": "إشعار عند تغيير شخص لعيد ميلاده", + "bitmoji_selfie_changes": "إشعار عند تغيير شخص لصورة بيتموجي الذاتية", + "bitmoji_avatar_changes": "إشعار عند تغيير شخص لصورة بيتموجي الخاصة به", + "bitmoji_background_changes": "إشعار عند تغيير شخص لخلفية بيتموجي", + "bitmoji_scene_changes": "إشعار عند تغيير شخص لمشهد بيتموجي" + }, + "snapchat_plus":{ + "not_subscribed": "غير مشترك", + "basic": "أساسي", + "ad_free": "خالي من الإعلانات" + }, + + "double_tap_chat_action": { + "like_message": "إعجاب بالرسالة", + "copy_text": "نسخ النص إلى الحافظة", + "delete_message": "حذف الرسالة", + "mark_as_read": "وضع علامة مقروء", + "custom_emoji_reaction": "رد فعل إيموجي مخصص" + }, + "startup_default_camera": { + "front": "الكاميرا الأمامية", + "back": "الكاميرا الخلفية" + } + } + }, + + "friend_menu_option": { + "mark_snaps_as_seen": "وضع علامة على السنابات كمقروءة", + "mark_stories_as_seen_locally": "وضع علامة على القصص كمقروءة محليًا", + "preview": "معاينة", + "stealth_mode": "وضع التخفي", + "auto_download_blacklist": "قائمة سوداء للتنزيل التلقائي", + "anti_auto_save": "مضاد الحفظ التلقائي" + }, + + "content_type": { + "CHAT": "محادثة", + "SNAP": "سناب", + "EXTERNAL_MEDIA": "وسائط خارجية", + "NOTE": "ملاحظة صوتية", + "STICKER": "ملصق", + "SHARE": "مشاركة", + "STATUS": "حالة", + "LOCATION": "موقع", + "STATUS_SAVE_TO_CAMERA_ROLL": "حفظ في معرض الكاميرا", + "STATUS_CONVERSATION_CAPTURE_SCREENSHOT": "لقطة شاشة", + "STATUS_CONVERSATION_CAPTURE_RECORD": "تسجيل شاشة", + "STATUS_CALL_MISSED_VIDEO": "مكالمة فيديو فائتة", + "STATUS_CALL_MISSED_AUDIO": "مكالمة صوتية فائتة", + "LIVE_LOCATION_SHARE": "مشاركة الموقع المباشر", + "CREATIVE_TOOL_ITEM": "عنصر أداة إبداعية", + "FAMILY_CENTER_INVITE": "دعوة مركز العائلة", + "FAMILY_CENTER_ACCEPT": "قبول مركز العائلة", + "FAMILY_CENTER_LEAVE": "مغادرة مركز العائلة", + "STATUS_PLUS_GIFT": "حالة هدية بلس", + "TINY_SNAP": "سناب صغير", + "STATUS_COUNTDOWN": "عد تنازلي", + "MAP_REACTION": "تفاعل الخريطة", + "chat_messages": "رسائل المحادثة", + "snap_messages": "سنابات", + "story_share_messages": "مشاركات القصص", + "story_reply_messages": "ردود القصص", + "story_messages": "قصة", + "external_media_messages": "وسائط خارجية", + "voice_note_messages": "ملاحظة صوتية", + "sticker_messages": "ملصق", + "tiny_snap_messages": "سناب صغير", + "map_reaction_messages": "تفاعل الخريطة", + "half_swipes": "سحب الشاشة النصفي" + }, + + "media_download_source": { + "none": "لا شيء", + "pending": "قيد الانتظار", + "chat_media": "وسائط المحادثة", + "story": "قصة", + "public_story": "قصة عامة", + "spotlight": "منصة الأضواء", + "profile_picture": "صورة الملف الشخصي", + "story_logger": "مسجل القصص", + "message_logger": "مسجل الرسائل", + "merged": "مدمج", + "voice_call": "مكالمة صوتية" + }, + + "chat_action_menu": { + "preview_button": "معاينة", + "download_button": "تنزيل", + "delete_logged_message_button": "حذف الرسالة المسجلة", + "show_chat_edit_history": "عرض سجل تحرير المحادثة", + "convert_message": "تحويل الرسالة", + "edit_message": "تحرير الرسالة" + }, + + "opera_context_menu": { + "download": "تنزيل الوسائط", + "sent_at": "تم الإرسال في {date}", + "created_at": "تم الإنشاء في {date}", + "expires_at": "ينتهي في {date}", + "media_size": "حجم الوسائط: {size}", + "media_duration": "مدة الوسائط: {duration} مللي ثانية", + "show_debug_info": "عرض معلومات التصحيح" + }, + + "modal_option": { + "profile_info": "معلومات الملف الشخصي", + "close": "إغلاق" + }, + + "gallery_media_send_override": { + "multiple_media_toast": "يمكنك إرسال وسائط واحدة فقط في كل مرة" + }, + + "mark_as_seen": { + "no_unseen_snaps_toast": "لم يتم العثور على سنابات غير مقروءة!", + "seen_toast": "تم وضع علامة مقروء!", + "unseen_toast": "تم وضع علامة غير مقروء!", + "already_seen_toast": "تم وضع علامة مقروء بالفعل!", + "already_unseen_toast": "تم وضع علامة غير مقروء بالفعل!" + }, + + "conversation_preview": { + "streak_expiration": "ينتهي في {day} أيام {hour} ساعات {minute} دقائق", + "total_messages": "إجمالي الرسائل المرسلة/المستلمة: {count}", + "title": "معاينة", + "unknown_user": "مستخدم غير معروف", + "no_messages": "لم يتم العثور على رسائل!" + }, + + "profile_info": { + "title": "معلومات الملف الشخصي", + "first_created_username": "أول اسم مستخدم تم إنشاؤه", + "mutable_username": "اسم مستخدم قابل للتغيير", + "display_name": "اسم العرض", + "added_date": "تاريخ الإضافة", + "birthday": "عيد الميلاد : {month} {day}", + "hidden_birthday": "عيد الميلاد : مخفي", + "friendship": "الصداقة", + "add_source": "مصدر الإضافة", + "snapchat_plus": "سناب شات بلس", + "snapchat_plus_state": { + "subscribed": "مشترك", + "not_subscribed": "غير مشترك" + } + }, + + "friendship_link_type": { + "mutual": "متبادل", + "outgoing": "صادر", + "blocked": "محظور", + "deleted": "محذوف", + "following": "متابَع", + "suggested": "مقترح", + "incoming": "وارد", + "incoming_follower": "متابِع وارد" + }, + + "bulk_messaging_action": { + "choose_action_title": "اختر إجراءً", + "progress_status": "جارٍ معالجة {index} من {total}", + "selection_dialog_continue_button": "متابعة", + "confirmation_dialog": { + "title": "هل أنت متأكد؟", + "message": "سيؤثر هذا على جميع المحددين. لا يمكن التراجع عن هذا الإجراء." + }, + "actions": { + "remove_friends": "إزالة الأصدقاء", + "clear_conversations": "مسح المحادثات" + }, + "leave_groups": "مغادرة {count} مجموعات", + "left_group_success": "تم مغادرة المجموعة بنجاح", + "failed_to_leave_group": "فشل في مغادرة المجموعة: {error}", + "conversation_types": { + "friends_only": "الأصدقاء فقط", + "groups_only": "المجموعات فقط", + "both": "الأصدقاء والمجموعات" + }, + "sort_by": "ترتيب حسب", + "reverse_order": "ترتيب عكسي", + "search_by_name": "البحث بالاسم", + "no_friends_found": "لم يتم العثور على أصدقاء", + "no_groups_found": "لم يتم العثور على مجموعات", + "no_friends_or_groups_found": "لم يتم العثور على أصدقاء أو مجموعات", + "relationship": "العلاقة: ", + "unknown_group": "مجموعة غير معروفة", + "type_group_chat": "النوع: محادثة جماعية", + "clean_conversations": "مسح {count} محادثات", + "remove_friends": "إزالة {count} أصدقاء", + "clean_conversations_and_remove_friends": "مسح {count} محادثات وإزالة {count} أصدقاء", + "clean_group_conversations": "مسح {count} محادثات جماعية", + "clean_all_conversations": "مسح {count} محادثات", + "failed_to_fetch_conversations": "فشل في جلب المحادثات: {error}", + "failed_to_fetch_friend_conversations": "فشل في جلب محادثات الأصدقاء: {error}", + "failed_to_process": "فشل في معالجة {id}", + "deleted_messages": "{count} رسائل محذوفة", + "filters": { + "all": "الكل", + "my_friends": "أصدقائي", + "blocked": "محظور", + "removed_me": "أزالني", + "suggested": "مقترح", + "deleted": "محذوف", + "business_accounts": "الحسابات التجارية", + "streaks": "الستريك", + "non_streaks": "غير الستريك", + "followed": "متابَع", + "location_on_map": "الموقع على الخريطة" + }, + "sort_options": { + "none": "لا شيء", + "username": "اسم المستخدم", + "added_timestamp": "وقت الإضافة", + "snap_score": "نقاط السناب", + "streak_length": "طول الستريك", + "most_messages_sent": "أكثر الرسائل إرسالاً", + "most_recent_message": "أحدث رسالة", + "nearest_location": "أقرب موقع" + } + }, + + "chat_export": { + "exporter_dialog": { + "select_conversations_title": "اختر المحادثات", + "text_field_selection": "{amount} محددة", + "text_field_selection_all": "الكل", + "export_file_format_title": "تنسيق ملف التصدير", + "message_type_filter_title": "تصفية الرسائل حسب النوع", + "amount_of_messages_title": "عدد الرسائل (اتركه فارغًا للكل)", + "download_medias_title": "تنزيل الوسائط" + }, + "dialog_negative_button": "إلغاء", + "dialog_positive_button": "تصدير", + "exported_to": "تم التصدير إلى {path}", + "exporting_chats": "جارٍ تصدير المحادثات...", + "processing_chats": "جارٍ معالجة {amount} محادثات...", + "export_fail": "فشل في تصدير المحادثة {conversation}", + "writing_output": "جارٍ كتابة المخرجات...", + "finished": "تم! يمكنك الآن إغلاق مربع الحوار هذا.", + "no_messages_found": "لم يتم العثور على رسائل!", + "exporting_message": "جارٍ تصدير {conversation}..." + }, + + "button": { + "ok": "موافق", + "positive": "نعم", + "negative": "لا", + "cancel": "إلغاء", + "save": "حفظ", + "open": "فتح", + "download": "تنزيل", + "send": "إرسال", + "restore_original": "استعادة الأصل", + "convert_external_media": "تحويل وسائط خارجية" + }, + + "tracker_events": { + "conversation_enter": "دخول المحادثة", + "conversation_exit": "خروج المحادثة", + "started_typing": "بدأ الكتابة", + "stopped_typing": "توقف عن الكتابة", + "started_speaking": "بدأ التحدث", + "stopped_speaking": "توقف عن التحدث", + "started_peeking": "بدأ في سحب الشاشة النصفي", + "stopped_peeking": "توقف عن سحب الشاشة النصفي", + "message_read": "قراءة الرسالة", + "message_deleted": "حذف الرسالة", + "message_saved": "حفظ الرسالة", + "message_unsaved": "إلغاء حفظ الرسالة", + "message_edited": "تحرير الرسالة", + "message_reaction_add": "إضافة رد فعل للرسالة", + "message_reaction_remove": "إزالة رد فعل للرسالة", + "snap_opened": "فتح السناب", + "snap_replayed": "إعادة تشغيل السناب", + "snap_replayed_twice": "إعادة تشغيل السناب مرتين", + "snap_screenshot": "لقطة شاشة للسناب", + "snap_screen_record": "تسجيل شاشة للسناب" + }, + + "tracker_actions": { + "log": "سجل", + "in_app_notification": "إشعار داخل التطبيق", + "push_notification": "إشعار دفع", + "custom": "مخصص" + }, + + "better_notifications": { + "button": { + "reply": "رد", + "download": "تنزيل", + "mark_as_read": "وضع علامة مقروء" + } + }, + + "profile_picture_downloader": { + "button": "تنزيل صورة الملف الشخصي", + "title": "أداة تنزيل صورة الملف الشخصي", + "avatar_option": "صورة رمزية", + "background_option": "خلفية" + }, + + "call_start_confirmation": { + "dialog_title": "بدء مكالمة", + "dialog_message": "هل أنت متأكد أنك تريد بدء مكالمة؟" + }, + + "half_swipe_notifier": { + "notification_channel_name": "سحب الشاشة النصفي", + "notification_content_dm": "{friend} انزلق نصفيًا إلى محادثتك لمدة {duration} ثوانٍ", + "notification_content_group": "{friend} انزلق نصفيًا إلى {group} لمدة {duration} ثوانٍ" + }, + + "download_processor": { + "attachment_type": { + "snap": "سناب", + "sticker": "ملصق", + "gif": "GIF", + "external_media": "وسائط خارجية", + "note": "ملاحظة", + "original_story": "قصة أصلية" + }, + "select_attachments_title": "اختر المرفقات", + "download_started_toast": "بدأ التنزيل", + "unsupported_content_type_toast": "نوع المحتوى غير مدعوم!", + "failed_no_longer_available_toast": "الوسائط لم تعد متاحة", + "no_attachments_toast": "لم يتم العثور على مرفقات!", + "already_queued_toast": "الوسائط موجودة بالفعل في الطابور!", + "already_downloaded_toast": "تم تنزيل الوسائط بالفعل!", + "content_saved_toast": "تم الحفظ!", + "download_toast": "جارٍ تنزيل {path}...", + "processing_toast": "جارٍ معالجة {path}...", + "failed_generic_toast": "فشل في التنزيل", + "failed_to_create_preview_toast": "فشل في إنشاء معاينة", + "failed_processing_toast": "فشل في المعالجة {error}", + "failed_gallery_toast": "فشل في الحفظ في المعرض {error}", + "dash_no_chapter": "لم يتم العثور على فصل", + "dash_dialog": { + "title": "تنزيل وسائط Dash", + "download_all": "تنزيل الكل", + "segment_text": "الجزء {from} - {to}" + } + }, + + "streaks_reminder": { + "notification_title": "الستريك", + "notification_text": "ستفقد ستريكك مع {friend} في {hoursLeft} ساعات" + }, + + "biometric_auth": { + "unlock_button": "فتح", + "title": "فتح سناب شات", + "subtitle": "يرجى المصادقة لفتح سناب شات" + }, + + "end_to_end_encryption": { + "toolbox": { + "no_shared_key": "ليس لديك مفتاح سري مشترك مع هذا الصديق بعد. انقر أدناه لبدء مفتاح جديد.", + "shared_key_fingerprint": "بصمة إصبعك هي:\n\n{fingerprint}\n\nتأكد من مطابقتها مع بصمة إصبع صديقك!", + "initiate_exchange_button": "بدء تبادل المفتاح" + }, + "confirmation_dialogs": { + "title": "التشفير من طرف إلى طرف", + "confirmation_1": "تحذير: هذا سيتجاوز مفتاحك الحالي. ستفقد الوصول إلى جميع الرسائل المشفرة من هذا الصديق. هل أنت متأكد أنك تريد المتابعة؟", + "confirmation_2": "هل أنت متأكد حقًا أنك تريد المتابعة؟ هذه هي فرصتك الأخيرة للتراجع." + }, + "unencrypted_conversation_send_failure_toast": "لا يمكنك إرسال محتوى مشفر إلى محادثات مشفرة وغير مشفرة!", + "native_hooks_send_failure_toast": "فشل في الإرسال! يرجى تمكين الخطافات الأصلية في الإعدادات.", + "no_participants_to_encrypt_toast": "ليس لديك أصدقاء في هذه المحادثة لتشفير الرسائل معهم!", + "encryption_failed_toast": "فشل في تشفير الرسالة! تحقق من logcat لمزيد من التفاصيل.", + "accept_public_key_success_toast": "تم قبول المفتاح العام بنجاح!", + "accept_secret_key_success_toast": "تم! يمكنك الآن إرسال واستقبال رسائل مشفرة مع هذا الصديق.", + "accept_public_key_failure_toast": "فشل في قبول المفتاح العام", + "accept_secret_key_failure_toast": "فشل في قبول المفتاح السري", + "accept_secret_button": "قبول المفتاح السري", + "accept_public_key_button": "قبول المفتاح العام", + "outgoing_pk_message": "طلب تبادل مفتاح", + "outgoing_secret_message": "استجابة تبادل مفتاح", + "incoming_pk_message": "لقد تلقيت طلب مفتاح عام. انقر أدناه لقبوله.", + "incoming_secret_message": "قبل صديقك مفتاحك العام. انقر أدناه لقبول المفتاح السري." + }, + + "auto_open_snaps": { + "title": "فتح السنابات تلقائيًا", + "priority_title": "فتح السنابات تلقائيًا (أولوية)", + "error_title": "فتح السنابات تلقائيًا (أخطاء)", + "channel_description": "إشعارات لحالة طابور فتح السنابات تلقائيًا", + "priority_channel_description": "إشعارات عالية الأولوية لفتح السنابات تلقائيًا", + "error_channel_description": "إشعارات الأخطاء عند فشل فتح السنابات تلقائيًا", + "paused_status": "فتح السنابات تلقائيًا متوقف", + "processing_status": "جارٍ معالجة السنابات: {queued} في الطابور، {processed} معالجة", + "monitor_status": "جارٍ المراقبة...", + "recent_snaps": "السنابات الأخيرة", + "action_pause": "إيقاف", + "action_resume": "استئناف", + "action_clear": "مسح الطابور", + "action_reset": "إعادة تعيين العدد", + "error_content": "فشل في فتح سناب من {sender}: {error}", + "resumed_feedback": "فتح السنابات تلقائيًا مستأنف", + "paused_feedback": "فتح السنابات تلقائيًا متوقف", + "resumed_message": "ستستمر المعالجة تلقائيًا للسنابات في الطابور", + "paused_message": "المعالجة متوقفة. الطابور محفوظ ({count} سناب)", + "status_paused": "متوقف", + "status_monitoring": "مراقبة", + "status_active": "نشط", + "queue_cleared": "تم مسح الطابور وإعادة تعيين الإحصائيات", + "queue_cleared_title": "تم مسح الطابور", + "queue_cleared_reset": "تم مسح الطابور وإعادة التعيين", + "queue_cleared_feedback": "تم مسح {count} سناب في الطابور • إعادة تعيين {processed} سناب معالج", + "queue_cleared_feedback_simple": "إعادة تعيين {processed} سناب معالج", + "unknown_sender": "غير معروف", + "unknown_user": "مستخدم غير معروف", + "content_type_external_media": "وسائط خارجية", + "content_type_snap": "سناب", + "conversation_type_friend_dm": "رسالة صديق", + "conversation_type_dm": "رسالة", + "conversation_type_group_chat": "محادثة جماعية", + "conversation_type_chat": "محادثة", + "notification_status": "الحالة", + "notification_statistics": "الإحصائيات", + "notification_queue_size": "حجم الطابور", + "notification_total_opened": "إجمالي السنابات المفتوحة", + "notification_queue_preview": "معاينة الطابور", + "notification_processing_continue": "ستستمر المعالجة تلقائيًا...", + "notification_no_snaps_queue": "لا توجد سنابات في الطابور.", + "notification_queue_cleared_opened": "تم مسح الطابور ({opened} مفتوح)", + "content_type_photo_video_snap": "سناب صورة/فيديو", + "conversation_type_group_with_name": "مجموعة: {name}", + "delete_logs_title": "حذف السجلات؟", + "delete_logs_progress": "جارٍ حذف {count} سجل...", + "delete_logs_description": "سيتم حذف السجلات بناءً على الفلتر الحالي واستعلام البحث. لا يمكن التراجع عن هذا الإجراء.", + "export_logs_title": "تصدير السجلات؟", + "export_logs_progress": "جارٍ تصدير السجلات...", + "export_logs_description": "سيتم تصدير السجلات بناءً على الفلتر الحالي واستعلام البحث.", + "export_logs_as": "تصدير كـ {type}", + "export_logs_success": "تم تصدير السجلات بنجاح!", + "export_logs_failure": "فشل في تصدير السجلات. تحقق من logcat لمزيد من التفاصيل.", + "deleted_logs_count": "تم حذف {count} سجل" + }, + "script_imported": "تم استيراد السكريبت {name}!", + "script_import_failed": "فشل في استيراد السكريبت. {error}. تحقق من السجلات لمزيد من التفاصيل", + "script_updating": "جارٍ تحديث السكريبت {name}...", + "script_updated": "تم تحديث {name} إلى الإصدار {version}", + "script_update_failed": "فشل في تحديث الوحدة. تحقق من السجلات لمزيد من التفاصيل", + "script_edit_failed": "فشل في فتح ملف الوحدة. تحقق من السجلات لمزيد من التفاصيل", + "script_data_cleared": "تم مسح بيانات الوحدة!", + "script_data_clear_failed": "فشل في مسح بيانات الوحدة. تحقق من السجلات لمزيد من التفاصيل", + "script_deleted": "تم حذف السكريبت {name}!", + "script_delete_failed": "فشل في حذف الوحدة. تحقق من السجلات لمزيد من التفاصيل", + "script_actions": "الإجراءات", + "script_no_description": "لا يوجد وصف", + "script_update_available": "التحديث متاح: {version}", + "script_loaded": "تم تحميل السكريبت {name}", + "script_unloaded": "تم إلغاء تحميل السكريبت {name}", + "script_enable_disable_failed": "فشل في {action} السكريبت. تحقق من السجلات لمزيد من التفاصيل", + "script_no_settings": "هذه الوحدة لا تحتوي على أي إعدادات", + "script_no_scripts_found": "لم يتم العثور على سكريبتات", + "script_ok_timeout": "موافق {timeout}", + "delete_rule_title": "حذف القاعدة", + "delete_rule_description": "هل أنت متأكد من أنك تريد حذف هذه القاعدة؟", + "rule_name": "اسم القاعدة", + + "friend_tracker_notifications": { + "notification_channel_name": "تتبع الأصدقاء", + "notification_title": "نشاط الأصدقاء", + "conversation_enter": "{friend} دخل إلى {conversation}", + "conversation_exit": "{friend} غادر {conversation}", + "started_typing": "{friend} بدأ الكتابة في {conversation}", + "stopped_typing": "{friend} توقف عن الكتابة في {conversation}", + "started_speaking": "{friend} بدأ في تسجيل ملاحظة صوتية {conversation}", + "stopped_speaking": "{friend} توقف عن تسجيل الملاحظة الصوتية {conversation}", + "started_peeking": "{friend} بدأ سحب نصف الشاشة في {conversation}", + "stopped_peeking": "{friend} توقف عن سحب نصف الشاشة في {conversation}", + "message_read": "{friend} قرأ رسالة في {conversation}", + "message_deleted": "{friend} حذف رسالة في {conversation}", + "message_saved": "{friend} حفظ رسالة في {conversation}", + "message_unsaved": "{friend} ألغى حفظ رسالة في {conversation}", + "message_edited": "{friend} عدّل رسالة في {conversation}", + "message_reaction_add": "{friend} أضاف تفاعلاً في {conversation}", + "message_reaction_remove": "{friend} أزال تفاعلاً في {conversation}", + "snap_opened": "{friend} فتح سناب في {conversation}", + "snap_replayed": "{friend} أعاد تشغيل السنابه في {conversation}", + "snap_replayed_twice": "{friend} أعاد تشغيل السنابه مرتين في {conversation}", + "snap_screenshot": "{friend} أخذ لقطة شاشة في {conversation}", + "snap_screen_record": "{friend} سجل الشاشة في {conversation}" + }, + + "friend_mutation_observer": { + "notification_channel_name": "مراقب تغيير الصديق", + "friend_removed": "{username} أزالك كصديق", + "birthday_removed": "{username} أزال عيد ميلاده ({birthday})", + "birthday_added": "{username} أضاف عيد ميلاده ({birthday})", + "birthday_changed": "{username} غير عيد ميلاده من {oldBirthday} إلى {newBirthday}", + "bitmoji_selfie_changed": "{username} غير صورة بيتموجي الذاتية", + "bitmoji_avatar_changed": "{username} غير صورة بيتموجي الخاصة به", + "bitmoji_background_changed": "{username} غير خلفية بيتموجي", + "bitmoji_scene_changed": "{username} غير مشهد بيتموجي" + }, + + "material3_strings": { + "date_range_picker_start_headline": "من", + "date_range_picker_end_headline": "إلى", + "date_range_picker_title": "اختر نطاق التاريخ", + "date_picker_switch_to_calendar_mode": "التقويم", + "date_picker_switch_to_input_mode": "إدخال", + "date_range_picker_scroll_to_previous_month": "الشهر السابق", + "date_range_picker_scroll_to_next_month": "الشهر التالي", + "date_picker_today_description": "اليوم", + "date_range_picker_day_in_range": "محدد", + "date_input_invalid_for_pattern": "تاريخ غير صالح", + "date_input_invalid_year_range": "سنة غير صالحة", + "date_input_invalid_not_allowed": "تاريخ غير صالح", + "date_range_input_invalid_range_input": "نطاق تاريخ غير صالح" + }, + + "send_override_dialog": { + "title": "إرسال الوسائط كـ {type}", + "duration": "المدة: {duration}", + "saveable_snap_hint": "اجعل السناب قابلًا للحفظ في المحادثة", + "unlimited_duration": "غير محدود" + }, + + "auto_reply_messages": { + "dialog": { + "add_message": "إضافة رسالة", + "edit_message": "تحرير الرسالة", + "message_label": "الرسالة", + "no_messages": "لا توجد رسائل بعد. أضف رسالتك الأولى!", + "message_placeholder": "أدخل رسالة الرد التلقائي..." + } + }, + + "auto_delete_sent_messages": { + "countdown_toast": "سيتم حذف الرسالة خلال {time}", + "delete_success_toast": "تم حذف الرسالة بنجاح", + "delete_failed_toast": "فشل في حذف الرسالة" + }, + + + + "translation_position": { + "above": "أعلى", + "below": "أسفل", + "inline": "ضمن السطر" + }, + + "language_codes": { + "en": "الإنجليزية", + "es": "الإسبانية", + "fr": "الفرنسية", + "de": "الألمانية", + "it": "الإيطالية", + "pt": "البرتغالية", + "ru": "الروسية", + "ja": "اليابانية", + "ko": "الكورية", + "zh": "الصينية", + "ar": "العربية", + "hi": "الهندية", + "tr": "التركية", + "nl": "الهولندية", + "pl": "البولندية", + "sv": "السويدية", + "da": "الدنماركية", + "no": "النرويجية", + "fi": "الفنلندية", + "cs": "التشيكية", + "hu": "المجرية", + "ro": "الرومانية", + "bg": "البلغارية", + "hr": "الكرواتية", + "sk": "السلوفاكية", + "sl": "السلوفينية", + "et": "الإستونية", + "lv": "اللاتفية", + "lt": "الليتوانية", + "mt": "المالطية", + "ga": "الأيرلندية", + "cy": "الويلزية" + }, + + "tracker": { + "tabs": { + "logs": "السجلات", + "rules": "القواعد" + }, + "actions": { + "export": "تصدير", + "delete": "حذف", + "add_rule": "إضافة قاعدة", + "save_rule": "حفظ القاعدة" + }, + "messages": { + "no_logs_found": "لم يتم العثور على سجلات", + "no_rules_found": "لم يتم العثور على قواعد", + "no_events": "لا توجد أحداث" + }, + "search": { + "placeholder": "بحث" + }, + "filters": { + "newest_first": "الأحدث أولاً", + "pick_a_date": "اختر تاريخًا", + "title": "المرشحات", + "search_by": "البحث بواسطة", + "since": "منذ", + "until": "حتى", + "types": { + "username": "اسم المستخدم", + "conversation": "المحادثة", + "event": "الحدث" + }, + "event_types": { + "conversation_enter": "دخل المحادثة", + "conversation_exit": "غادر المحادثة", + "started_typing": "بدأ الكتابة", + "stopped_typing": "توقف عن الكتابة", + "started_speaking": "بدأ التحدث", + "stopped_speaking": "توقف عن التحدث", + "started_peeking": "بدأ في سحب الشاشة النصفي", + "stopped_peeking": "توقف عن سحب الشاشة النصفي", + "message_read": "قرأ رسالة", + "message_deleted": "حذف رسالة", + "message_saved": "حفظ رسالة", + "message_unsaved": "ألغى حفظ رسالة", + "message_edited": "حرر رسالة", + "message_reaction_add": "أضاف رد فعل", + "message_reaction_remove": "أزال رد فعل", + "snap_opened": "فتح السنابه", + "snap_replayed": "أعاد تشغيل السنابه", + "snap_replayed_twice": "أعاد تشغيل السنابه مرتين", + "snap_screenshot": "أخذ لقطة شاشة", + "snap_screen_record": "سجل الشاشة" + } + }, + "logs": { + "export_dialog": { + "title": "تصدير السجلات", + "description": "تصدير سجلات متتبع الأصدقاء إلى ملف", + "progress": "جارٍ تصدير السجلات...", + "export_as": "تصدير كـ {type}", + "format_json": "JSON", + "format_csv": "CSV" + }, + "delete_dialog": { + "title": "حذف السجلات", + "message": "هل أنت متأكد أنك تريد حذف جميع السجلات؟ لا يمكن التراجع عن هذا الإجراء.", + "confirm": "حذف الكل", + "cancel": "إلغاء", + "progress": "جارٍ حذف {count} سجل..." + }, + "log_entry": { + "in_conversation": "في {conversation}", + "unknown_user": "غير معروف", + "unknown_conversation": "الرسائل الخاصة", + "event_text": "{friend} {event} في {conversation}", + "events": { + "conversation_enter": "دخل", + "conversation_exit": "غادر", + "started_typing": "بدأ الكتابة", + "stopped_typing": "توقف عن الكتابة", + "started_speaking": "بدأ التحدث", + "stopped_speaking": "توقف عن التحدث", + "started_peeking": "بدأ في سحب الشاشة النصفي", + "stopped_peeking": "توقف عن سحب الشاشة النصفي", + "message_read": "قرأ رسالة", + "message_deleted": "حذف رسالة", + "message_saved": "حفظ رسالة", + "message_unsaved": "ألغى حفظ رسالة", + "message_edited": "حرر رسالة", + "message_reaction_add": "أضاف رد فعل", + "message_reaction_remove": "أزال رد فعل", + "snap_opened": "فتح سنابه", + "snap_replayed": "أعاد تشغيل سنابه", + "snap_replayed_twice": "أعاد تشغيل سنابه مرتين", + "snap_screenshot": "أخذ لقطة شاشة", + "snap_screen_record": "سجل الشاشة" + } + } + }, + "edit_rule": { + "custom_rule": "قاعدة مخصصة", + "scope": "النطاق", + "events": "الأحداث", + "add_event": "إضافة حدث", + "type": "النوع", + "triggers": "المحفزات", + "conditions": "الشروط", + "only_inside_conversation": "فقط عندما أكون داخل المحادثة", + "only_outside_conversation": "فقط عندما أكون خارج المحادثة", + "only_when_app_active": "فقط عندما يكون سناب شات نشط", + "only_when_app_inactive": "فقط عندما يكون سناب شات غير نشط", + "no_notification_when_app_active": "لا إشعار عندما يكون سناب شات نشط", + "scope_options": { + "all_friends_groups": "جميع الأصدقاء/المجموعات", + "no_one_except": "لا أحد باستثناء ...", + "everyone_except": "الجميع باستثناء ..." + } + } + }, + + "debug": { + "title": "التصحيح", + "clear": "مسح", + "files": { + "config_json": "ملف التكوين", + "mappings_json": "ملف التعيينات", + "message_logger_db": "قاعدة بيانات مسجل الرسائل", + "pinned_best_friend_txt": "ملف أفضل صديق مثبت", + "native_sig_cache_txt": "ملف ذاكرة التوقيع الأصلي" + }, + "settings": { + "test_mode": "وضع الاختبار (للتصحيح فقط)", + "disable_feature_loading": "تعطيل تحميل الميزات", + "disable_auto_mapper": "تعطيل المخطط التلقائي", + "disable_bypass_status_indicator": "تعطيل مؤشر حالة الالتفاف" + } + }, + + "friend_list": { + "manage_title": "إدارة قائمة الأصدقاء", + "export_description": "تصدير الأصدقاء يسمح لك بحفظ قائمة معرفات أصدقائك في ملف نصي. استيراد من ملف سيعرض الأصدقاء في قائمة حيث يمكنك إضافتهم.", + "export_friends": "تصدير الأصدقاء", + "import_from_file": "استيراد من ملف", + "add": "إضافة" + }, + + "memories": { + "export_title": "تصدير الذكريات", + "total_memories": "إجمالي الذكريات: {count}", + "date_range": "نطاق التاريخ", + "select": "اختر", + "sort_by_folder": "ترتيب حسب المجلد", + "include_my_eyes_only": "تضمين عيني فقط", + "cancel": "إلغاء", + "export": "تصدير", + "quit": "خروج", + "done": "تم", + "ok": "موافق", + "exporting_memories": "تصدير الذكريات... ({failed} فشل)" + }, + + "scripting_ui": { + "no_scripts_folder_selected": "لم يتم تحديد مجلد النصوص البرمجية", + "select_folder": "اختر مجلد", + "import_from_url": "استيراد من رابط", + "open_scripts_folder": "فتح مجلد النصوص البرمجية", + "import_script_from_url": "استيراد نص برمجي من رابط", + "warning_imported_scripts": "تحذير: النصوص البرمجية المستوردة قد تكون ضارة بجهازك. استورد النصوص البرمجية من مصادر موثوقة فقط.", + "enter_url_here": "أدخل الرابط هنا:", + "import": "استيراد", + "cancel": "إلغاء", + "documentation": "الوثائق" + }, + + "common": { + "cancel": "إلغاء", + "add": "إضافة", + "ok": "موافق", + "quit": "خروج", + "done": "تم", + "back": "رجوع", + "unknown": "غير معروف", + "added": "تمت الإضافة", + "no_friends_found": "لم يتم العثور على أصدقاء", + "exporting_memories": "تصدير الذكريات... ({failed} فشل)" + }, + + "logger_history": { + "download_started": "تم بدء التحميل!", + "downloaded_to": "تم التحميل إلى {path}", + "failed_to_download": "فشل في تحميل {message}", + "select_conversation": "اختر محادثة", + "edited_at": "تم التعديل في {date}", + "download_attachment_failed_toast": "فشل في تحميل المرفق", + "message_parse_failed": "فشل في تحليل الرسالة", + "empty_message": "رسالة فارغة", + "no_more_messages": "لا توجد رسائل أخرى", + "reverse_order_checkbox": "ترتيب عكسي", + "view_logger_history_button": "عرض سجل المحادثات", + "posted_at": "تم النشر في {date}", + "created_at": "تم الإنشاء في {date}", + "failed_to_open_file": "فشل في فتح الملف. تحقق من السجلات لمزيد من المعلومات", + "failed_to_get_file": "فشل في الحصول على الملف" + }, + + "debug_dialogs": { + "info": "معلومات", + "refs": "المراجع", + "arroyo": "أرويو", + "message": "الرسالة", + "media_references": "مراجع الوسائط", + "arroyo_proto": "أرويو بروتو", + "message_proto": "رسالة بروتو" + }, + + "error_messages": { + "failed_to_fetch_message": "فشل في جلب الرسالة: {error}", + "failed_to_edit_message": "فشل في تعديل الرسالة: {error}" + }, + + "ai_response_style": { + "casual": "غير رسمي", + "formal": "رسمي", + "friendly": "ودود", + "humorous": "فكاهي", + "empathetic": "متعاطف", + "toxic": "سام" + }, + + "ai_response_language": { + "auto": "تلقائي (نفس اللغة المستلمة)", + "en": "الإنجليزية", + "es": "الإسبانية", + "fr": "الفرنسية", + "de": "الألمانية", + "it": "الإيطالية", + "pt": "البرتغالية", + "ru": "الروسية", + "ja": "اليابانية", + "ko": "الكورية", + "zh": "الصينية", + "ar": "العربية", + "hi": "الهندية", + "tr": "التركية", + "pl": "البولندية", + "nl": "الهولندية", + "sv": "السويدية", + "da": "الدنماركية", + "no": "النرويجية", + "fi": "الفنلندية" + } +} diff --git a/common/src/main/assets/lang/bn.json b/common/src/main/assets/lang/bn.json index 0c72b102..4e77d6d0 100644 --- a/common/src/main/assets/lang/bn.json +++ b/common/src/main/assets/lang/bn.json @@ -1,1859 +1,46 @@ { - "setup": { - "dialogs": { - "select_language": "ভাষা নির্বাচন করুন", - "save_folder": "PurrfectSnap-এর Snapchat থেকে মিডিয়া ডাউনলোড এবং সেভ করার জন্য স্টোরেজ অনুমতির প্রয়োজন।\nঅনুগ্রহ করে সেই স্থানটি নির্বাচন করুন যেখানে মিডিয়া ডাউনলোড করা হবে।", - "select_save_folder_button": "ফোল্ডার নির্বাচন করুন" - }, - "mappings": { - "dialog": "ম্যাপিং তৈরি করা হচ্ছে, এতে কিছু সময় লাগতে পারে...", - "generate_failure_no_snapchat": "PurrfectSnap Snapchat সনাক্ত করতে পারেনি, অনুগ্রহ করে Snapchat পুনরায় ইনস্টল করার চেষ্টা করুন।", - "generate_failure": "ম্যাপিং তৈরি করার সময় একটি ত্রুটি ঘটেছে, অনুগ্রহ করে আবার চেষ্টা করুন।" - }, - "permissions": { - "dialog": "চালিয়ে যেতে আপনাকে নিম্নলিখিত প্রয়োজনীয়তাগুলি পূরণ করতে হবে:", - "notification_access": "বিজ্ঞপ্তি অ্যাক্সেস", - "battery_optimization": "ব্যাটারি অপ্টিমাইজেশান", - "display_over_other_apps": "অন্যান্য অ্যাপের উপরে প্রদর্শন করুন", - "request_button": "অনুরোধ" - } - }, - "scopes": { - "friend": "বন্ধু", - "group": "গ্রুপ" - }, - "manager": { - "routes": { - "tasks": "কাজ", - "features": "বৈশিষ্ট্য", - "manage_rule_feature": "নিয়ম বৈশিষ্ট্য পরিচালনা করুন", - "home": "হোম", - "home_settings": "সেটিংস", - "home_logs": "লগ", - "logger_history": "লগার ইতিহাস", - "logged_stories": "লগ করা গল্প", - "friend_tracker": "বন্ধু ট্র্যাকার", - "edit_rule": "নিয়ম সম্পাদনা করুন", - "file_imports": "ফাইল আমদানি", - "manage_repos": "সংগ্রহস্থল পরিচালনা করুন", - "social": "সামাজিক", - "manage_scope": "স্কোপ পরিচালনা করুন", - "messaging_preview": "প্রিভিউ", - "scripts": "স্ক্রিপ্ট", - "better_location": "আরও ভাল অবস্থান" - }, - "sections": { - "home": { - "version_title": "v{versionName} · Eternal দ্বারা ফর্ক করা হয়েছে", - "update_title": "PurrfectSnap আপডেট", - "update_content": "সংস্করণ {version} উপলব্ধ!", - "update_button": "ডাউনলোড করুন", - "debug_build_summary_title": "আপনি PurrfectSnap-এর একটি ডিবাগ বিল্ড চালাচ্ছেন", - "debug_build_summary_content": "সংস্করণ {versionName} ({versionCode})", - "debug_build_summary_date": "বিল্ড তারিখ: {date} ({days} দিন আগে)", - "quick_actions_title": "দ্রুত ক্রিয়া", - "download_icon_description": "ডাউনলোড করুন", - "completed_icon_description": "সম্পন্ন", - "failed_icon_description": "ব্যর্থ", - "manage_quick_actions_description": "দ্রুত ক্রিয়া পরিচালনা করুন", - "quick_actions_icon_description": "দ্রুত ক্রিয়া", - "add_quick_action_description": "দ্রুত ক্রিয়া যোগ করুন" - }, - "home_logs": { - "no_logs_hint": "কোনো লগ উপলব্ধ নেই", - "clear_logs_button": "লগ সাফ করুন", - "export_logs_button": "লগ রপ্তানি করুন", - "saving_logs_toast": "লগ সংরক্ষণ করা হচ্ছে, এতে কিছু সময় লাগতে পারে...", - "saved_logs_success_toast": "লগ সফলভাবে সংরক্ষিত হয়েছে", - "saved_logs_failure_toast": "লগ সংরক্ষণ করতে ব্যর্থ হয়েছে" - }, - "home_settings": { - "actions_title": "ক্রিয়া", - "message_logger_title": "বার্তা লগার", - "debug_title": "ডিবাগ", - "success_toast": "সম্পন্ন!", - "message_logger_summary": "{messageCount} টি বার্তা\n{storyCount} টি গল্প", - "export_button": "রপ্তানি করুন", - "clear_button": "সাফ করুন", - "view_logger_history_button": "লগার ইতিহাস দেখুন", - "updates_title": "আপডেট", - "auto_update_check": "আপডেটের জন্য স্বয়ংক্রিয়ভাবে পরীক্ষা করুন", - "update_check_frequency": "আপডেট পরীক্ষার ফ্রিকোয়েন্সি", - "update_check_frequency_daily": "দৈনিক", - "update_check_frequency_weekly": "সাপ্তাহিক", - "update_check_frequency_monthly": "মাসিক", - "theme_icon_description": "থিম", - "app_theme_title": "অ্যাপ থিম", - "theme_mode_system": "সিস্টেম", - "theme_mode_light": "হালকা", - "theme_mode_dark": "অন্ধকার", - "ui_settings_title": "UI সেটিংস", - "haptic_feedback_label": "হ্যাপটিক ফিডব্যাক", - "test_mode_label": "পরীক্ষা মোড (শুধুমাত্র ডিবাগিংয়ের জন্য)", - "disable_feature_loading_label": "বৈশিষ্ট্য লোডিং অক্ষম করুন", - "disable_auto_mapper_label": "স্বয়ংক্রিয় ম্যাপার অক্ষম করুন", - "disable_bypass_indicator_label": "বাইপাস স্থিতি সূচক অক্ষম করুন", - "update_notification_channel_name": "PurrfectSnap আপডেট", - "update_notification_channel_description": "PurrfectSnap আপডেটের জন্য বিজ্ঞপ্তি", - "update_notification_title": "PurrfectSnap আপডেট উপলব্ধ", - "update_notification_text": "সংস্করণ %s এখন উপলব্ধ।", - "export_database_failed_toast": "ডাটাবেস রপ্তানি করতে ব্যর্থ! {message}", - "clear_messages_failed_toast": "বার্তা সাফ করতে ব্যর্থ! {message}", - "clear_file_failed_toast": "ফাইল সাফ করতে ব্যর্থ! {message}", - "debug_file_config": "কনফিগারেশন", - "debug_file_mappings": "ম্যাপিং", - "debug_file_message_logger": "বার্তা লগার", - "debug_file_pinned_best_friend": "পিন করা সেরা বন্ধু", - "debug_file_native_sig_cache": "নেটিভ স্বাক্ষর ক্যাশে" - }, - "tasks": { - "no_tasks": "কোনো কাজ নেই", - "merge_button": "একত্রীকরণ করুন", - "failed_to_open_file": "ফাইল খুলতে ব্যর্থ হয়েছে", - "merge_files_toast": "{count} টি ফাইল একীভূত করা হচ্ছে", - "remove_selected_tasks_title": "আপনি কি নির্বাচিত কাজগুলি সরাতে নিশ্চিত?", - "remove_all_tasks_title": "আপনি কি সমস্ত কাজ সরাতে নিশ্চিত?", - "delete_files_option": "ফাইলগুলিও মুছুন", - "remove_selected_tasks_confirm": "{count} টি কাজ সরান?", - "remove_all_tasks_confirm": "সমস্ত কাজ সরান?", - "clear_tasks_description": "কাজ সাফ করুন", - "file_not_found_icon_description": "ফাইল পাওয়া যায়নি", - "image_icon_description": "ছবি", - "video_icon_description": "ভিডিও", - "audio_icon_description": "অডিও", - "file_icon_description": "ফাইল", - "download_icon_description": "ডাউনলোড করুন", - "chat_action_icon_description": "চ্যাট ক্রিয়া", - "cancel_icon_description": "বাতিল করুন", - "success_icon_description": "সাফল্য", - "failure_icon_description": "ব্যর্থতা", - "cancelled_icon_description": "বাতিল করা হয়েছে", - "task_status_failure": "ব্যর্থতা", - "task_status_cancelled": "বাতিল করা হয়েছে" - }, - "features": { - "disabled": "অক্ষম", - "export_option": "রপ্তানি করুন", - "import_option": "আমদানি করুন", - "reset_option": "রিসেট করুন", - "config_export_success_toast": "কনফিগ সফলভাবে রপ্তানি করা হয়েছে", - "config_import_success_toast": "কনফিগ সফলভাবে আমদানি করা হয়েছে", - "config_import_failure_toast": "কনফিগ আমদানি করতে ব্যর্থ হয়েছে {error}", - "config_export_failure_toast": "কনফিগ রপ্তানি করতে ব্যর্থ হয়েছে {error}", - "saved_config_snackbar": "কনফিগ সংরক্ষিত হয়েছে", - "older_required": "এই বৈশিষ্ট্যটির সঠিকভাবে কাজ করার জন্য Snapchat v{version} বা তার চেয়ে পুরানো সংস্করণ প্রয়োজন", - "newer_required": "এই বৈশিষ্ট্যটির সঠিকভাবে কাজ করার জন্য Snapchat v{version} বা তার চেয়ে নতুন সংস্করণ প্রয়োজন", - "search_button": "অনুসন্ধান করুন" - }, - "manage_rule_feature": { - "disable_state_option": "অক্ষম", - "disable_state_subtext": "কোনো বন্ধু/গ্রুপ প্রভাবিত হবে না", - "whitelist_state_option": "কেউ ছাড়া ...", - "whitelist_state_subtext": "শুধুমাত্র {count} জন বন্ধু/গ্রুপ এই নিয়ম দ্বারা প্রভাবিত হবে", - "whitelist_state_button": "অনুমোদিত বন্ধু/গ্রুপ নির্বাচন করুন", - "blacklist_state_option": "সবাই ছাড়া ...", - "blacklist_state_subtext": "সবাই ছাড়া {count} জন বন্ধু/গ্রুপ এই নিয়ম দ্বারা প্রভাবিত হবে", - "blacklist_state_button": "বাদ দেওয়া বন্ধু/গ্রুপ নির্বাচন করুন", - "clear_list_button": "বন্ধু/গ্রুপ তালিকা সাফ করুন", - "dialog_clear_confirmation_text": "আপনি কি তালিকাটি সাফ করতে নিশ্চিত?" - }, - "social": { - "friends_tab": "বন্ধু", - "groups_tab": "গ্রুপ", - "empty_hint": "(খালি)", - "streaks_expiration_short": "{hours}ঘন্টা" - }, - "manage_scope": { - "logged_stories_button": "লগ করা গল্প দেখান", - "e2ee_title": "এন্ড-টু-এন্ড এনক্রিপশন", - "rules_title": "নিয়ম", - "participants_text": "{count} জন অংশগ্রহণকারী", - "not_found": "পাওয়া যায়নি", - "streaks_title": "ধারাবাহিকতা", - "streaks_length_text": "দৈর্ঘ্য: {length}", - "streaks_expiration_text": "{eta} এর মধ্যে মেয়াদ শেষ হবে", - "streaks_expiration_text_expired": "মেয়াদোত্তীর্ণ", - "reminder_button": "অনুस्मारक সেট করুন", - "delete_scope_confirm_dialog_title": "আপনি কি একটি {scope} মুছতে নিশ্চিত?", - "notes_placeholder": "একটি নোট যোগ করতে ক্লিক করুন", - "invalid_key_size_32_bytes": "অবৈধ কী আকার (32 বাইট হতে হবে)", - "successfully_imported_key": "কী সফলভাবে আমদানি করা হয়েছে", - "failed_to_import_key": "কী আমদানি করতে ব্যর্থ হয়েছে: {message}", - "export_base64_button": "Base64 রপ্তানি করুন", - "import_base64_button": "Base64 আমদানি করুন" - }, - "logged_stories": { - "story_failed_to_load": "গল্প লোড করতে ব্যর্থ হয়েছে", - "no_stories": "কোনো গল্প পাওয়া যায়নি", - "save_from_cache_button": "ক্যাশে থেকে সংরক্ষণ করুন", - "downloaded_to_path": "{path} এ ডাউনলোড করা হয়েছে", - "download_failed": "ডাউনলোড ব্যর্থ হয়েছে: {message}", - "posted_at": "{date} এ পোস্ট করা হয়েছে", - "created_at": "{date} এ তৈরি করা হয়েছে", - "failed_to_open_file": "ফাইল খুলতে ব্যর্থ হয়েছে। আরও তথ্যের জন্য লগ দেখুন", - "failed_to_get_file": "ফাইল পেতে ব্যর্থ হয়েছে" - }, - "messaging_preview": { - "processed_messages_toast": "{count} টি বার্তা প্রক্রিয়াজাত করা হয়েছে", - "processed_messages_text": "{count} টি বার্তা প্রক্রিয়াজাত করা হয়েছে", - "close_button_description": "বন্ধ করুন", - "bridge_connection_failed": "ব্রিজের সাথে সংযোগ করতে ব্যর্থ হয়েছে। নিশ্চিত করুন যে Snapchat পটভূমিতে চলছে", - "bridge_init_failed": "মেসেজিং ব্রিজ শুরু করতে ব্যর্থ হয়েছে। নিশ্চিত করুন যে Snapchat পটভূমিতে চলছে", - "message_fetch_failed": "বার্তা আনতে ব্যর্থ হয়েছে", - "no_message_hint": "কোনো বার্তা নেই", - "save_selection_option": "নির্বাচন সংরক্ষণ করুন", - "save_all_option": "সব সংরক্ষণ করুন", - "unsave_selection_option": "নির্বাচন সংরক্ষণ रद्द করুন", - "unsave_all_option": "সব সংরক্ষণ रद्द করুন", - "mark_selection_as_seen_option": "নির্বাচিত স্ন্যাপকে দেখা হিসাবে চিহ্নিত করুন", - "mark_all_as_seen_option": "সব স্ন্যাপকে দেখা হিসাবে চিহ্নিত করুন", - "delete_selection_option": "নির্বাচন মুছুন", - "delete_all_option": "সব মুছুন" - }, - "logger_history": { - "download_started_toast": "ডাউনলোড শুরু হয়েছে!", - "download_success_toast": "{path} এ ডাউনলোড করা হয়েছে", - "download_failed_toast": "{message} ডাউনলোড করতে ব্যর্থ হয়েছে", - "edited_at_text": "{message} ({date} এ সম্পাদিত)", - "download_button": "ডাউনলোড করুন", - "select_conversation_placeholder": "একটি কথোপকথন নির্বাচন করুন", - "close_button_description": "বন্ধ করুন", - "search_button_description": "অনুসন্ধান করুন", - "list_friend_format": "বন্ধু {name}", - "list_group_format": "গ্রুপ {name}", - "no_more_messages": "আর কোনো বার্তা নেই", - "reverse_order_checkbox": "বিপরীত ক্রম", - "chat_attachment": "সংযুক্তি {index}", - "empty_message": "খালি চ্যাট বার্তা", - "message_parse_failed": "বার্তা পার্স করতে ব্যর্থ হয়েছে", - "unknown_sender": "অজানা প্রেরক", - "download_attachment_failed_toast": "সংযুক্তি ডাউনলোড করতে ব্যর্থ হয়েছে", - "log_header_format": "{username} ({type}) - {date}" - }, - "file_imports": { - "import_file_button": "ফাইল আমদানি করুন", - "file_not_found": "ফাইল পাওয়া যায়নি", - "file_import_failed": "ফাইল আমদানি করতে ব্যর্থ হয়েছে: {error}", - "file_imported": "ফাইল সফলভাবে আমদানি করা হয়েছে", - "file_delete_failed": "ফাইল মুছতে ব্যর্থ হয়েছে", - "no_files_hint": "এখানে আপনি Snapchat-এ ব্যবহারের জন্য ফাইল আমদানি করতে পারেন। একটি ফাইল আমদানি করতে নীচের বোতামটি টিপুন।" - }, - "better_location": { - "spoofed_coordinates_title": "ল্যাট {latitude}, লং {longitude}", - "save_coordinates_dialog_title": "স্থানাঙ্ক সংরক্ষণ করুন", - "saved_name_dialog_hint": "সংরক্ষিত নাম", - "latitude_dialog_hint": "অক্ষাংশ", - "longitude_dialog_hint": "দ্রাঘিমাংশ", - "save_dialog_button": "সংরক্ষণ করুন", - "choose_location_button": "অবস্থান নির্বাচন করুন", - "teleport_to_friend_button": "বন্ধুর কাছে টেলিপোর্ট করুন", - "spoof_location_toggle": "অবস্থান স্পুফ করুন", - "suspend_location_updates": "অবস্থান আপডেট স্থগিত করুন", - "saved_coordinates_title": "সংরক্ষিত স্থানাঙ্ক", - "no_saved_coordinates_hint": "কোনো সংরক্ষিত স্থানাঙ্ক নেই", - "delete_dialog_title": "সংরক্ষিত স্থানাঙ্ক মুছুন", - "delete_dialog_message": "আপনি কি এই সংরক্ষিত স্থানাঙ্কটি মুছতে নিশ্চিত?", - "teleport_to_friend_title": "বন্ধুর কাছে টেলিপোর্ট করুন", - "search_bar": "অনুসন্ধান করুন", - "no_friends_map": "মানচিত্রে কোনো বন্ধু নেই", - "no_friends_found": "কোনো বন্ধু পাওয়া যায়নি", - "edit_location_button_description": "অবস্থান সম্পাদনা করুন", - "add_icon_description": "যোগ করুন", - "edit_icon_description": "সম্পাদনা করুন", - "delete_icon_description": "মুছুন" - } - }, - "dialogs": { - "add_friend": { - "title": "বন্ধু বা গ্রুপ যোগ করুন", - "search_hint": "অনুসন্ধান করুন", - "fetch_error": "ডেটা আনতে ব্যর্থ হয়েছে", - "category_groups": "গ্রুপ", - "category_friends": "বন্ধু", - "participants_text": "{count} জন অংশগ্রহণকারী", - "search_icon_description": "অনুসন্ধান করুন" - }, - "scripting_warning": { - "title": "সতর্কতা", - "content": "PurrfectSnap-এ একটি স্ক্রিপ্টিং টুল রয়েছে, যা আপনার ডিভাইসে ব্যবহারকারী-সংজ্ঞায়িত কোড কার্যকর করার অনুমতি দেয়। চরম সতর্কতা অবলম্বন করুন এবং শুধুমাত্র পরিচিত, নির্ভরযোগ্য উৎস থেকে মডিউল ইনস্টল করুন। অননুমোদিত বা যাচাই না করা মডিউল আপনার সিস্টেমের জন্য নিরাপত্তা ঝুঁকি তৈরি করতে পারে।" - }, - "reset_config": { - "title": "কনফিগ রিসেট করুন", - "content": "আপনি কি কনফিগ রিসেট করতে নিশ্চিত?", - "success_toast": "কনফিগ সফলভাবে রিসেট করা হয়েছে" - }, - "export_config": { - "title": "সংবেদনশীল ডেটা রপ্তানি করবেন?", - "content": "আপনি কি সংবেদনশীল ডেটা সহ কনফিগ রপ্তানি করতে চান? (যেমন অবস্থানের স্থানাঙ্ক, ইত্যাদি)" - }, - "messaging_action": { - "title": "প্রক্রিয়াজাত করার জন্য বিষয়বস্তুর প্রকারগুলি চয়ন করুন", - "select_all_button": "সব নির্বাচন করুন" - }, - "file_imports": { - "no_files_settings_hint": "কোনো ফাইল পাওয়া যায়নি। নিশ্চিত করুন যে আপনি ফাইল আমদানি বিভাগে প্রয়োজনীয় ফাইলগুলি আমদানি করেছেন", - "settings_select_file_hint": "একটি আমদানি করা ফাইল নির্বাচন করুন" - }, - "quick_actions_dialog": { - "title": "দ্রুত ক্রিয়া সম্পাদনা করুন", - "subtitle": "আপনার দ্রুত ক্রিয়াগুলি নির্বাচন করুন এবং আকার দিন।" - } - }, - "friend_tracker": { - "rules_tab": "নিয়ম", - "logs_tab": "লগ", - "export_dialog_title": "রপ্তানি করুন", - "bulk_export_button": "বাল্ক রপ্তানি", - "individual_export_button": "স্বতন্ত্র রপ্তানি", - "invalid_import_type_dialog_title": "অবৈধ আমদানি প্রকার", - "invalid_import_type_dialog_text": "নির্বাচিত ফাইলটি এই আমদানি প্রকারের সাথে সামঞ্জস্যপূর্ণ নয়। অনুগ্রহ করে সঠিক আমদানি প্রকার নির্বাচন করুন।", - "import_dialog_title": "আমদানি করুন", - "bulk_import_button": "বাল্ক আমদানি", - "individual_import_button": "স্বতন্ত্র আমদানি", - "import_button_description": "আমদানি করুন", - "export_button_description": "রপ্তানি করুন", - "export_button": "রপ্তানি করুন", - "delete_button_description": "মুছুন", - "delete_button": "মুছুন", - "catalog_button_description": "ক্যাটালগ", - "catalog_button": "ক্যাটালগ", - "add_rule_button_description": "নিয়ম যোগ করুন", - "add_rule_button": "নিয়ম যোগ করুন", - "no_rules_found": "কোনো নিয়ম পাওয়া যায়নি", - "empty_rule_name": "(খালি)", - "events_suffix": "ইভেন্ট", - "scopes_suffix": "স্কোপ", - "select_rule_to_export_title": "রপ্তানি করার জন্য নিয়ম নির্বাচন করুন", - "deleted_logs_toast": "{count} টি লগ মুছে ফেলা হয়েছে", - "delete_logs_dialog_title": "লগ মুছবেন?", - "deleting_logs_dialog_text": "{count} টি লগ মোছা হচ্ছে...", - "delete_logs_dialog_confirm_text": "এটি বর্তমান ফিল্টার এবং অনুসন্ধান প্রশ্নের উপর ভিত্তি করে লগগুলি মুছে ফেলবে। এই ক্রিয়াটি পূর্বাবস্থায় ফেরানো যাবে না।", - "exported_logs_toast": "লগ রপ্তানি করা হয়েছে!", - "export_logs_failed_toast": "লগ রপ্তানি করতে ব্যর্থ হয়েছে। আরও বিস্তারিত জানার জন্য logcat দেখুন।", - "export_logs_dialog_title": "লগ রপ্তানি করবেন?", - "exporting_logs_dialog_text": "লগ রপ্তানি করা হচ্ছে...", - "export_logs_dialog_confirm_text": "এটি বর্তমান ফিল্টার এবং অনুসন্ধান প্রশ্নের উপর ভিত্তি করে লগগুলি রপ্তানি করবে।", - "export_as_button": "{type} হিসাবে রপ্তানি করুন", - "filters_title": "ফিল্টার", - "search_by_label": "অনুসন্ধান করুন", - "newest_first_label": "নতুনতম প্রথমে", - "since_label": "থেকে", - "until_label": "পর্যন্ত", - "pick_a_date_button": "একটি তারিখ বাছুন", - "search_placeholder": "অনুসন্ধান করুন", - "filter_button_description": "ফিল্টার", - "clear_button_description": "সাফ করুন", - "no_logs_found": "কোনো লগ পাওয়া যায়নি", - "log_event_format": "{conversation}-এ {event}", - "condition_only_inside_conversation": "শুধুমাত্র যখন আমি কথোপকথনের ভিতরে থাকি", - "condition_only_outside_conversation": "শুধুমাত্র যখন আমি কথোপকথনের বাইরে থাকি", - "condition_only_when_app_active": "শুধুমাত্র যখন Snapchat সক্রিয় থাকে", - "condition_only_when_app_inactive": "শুধুমাত্র যখন Snapchat নিষ্ক্রিয় থাকে", - "condition_no_push_notification_when_app_active": "Snapchat সক্রিয় থাকাকালীন কোনো পুশ বিজ্ঞপ্তি নেই", - "add_event_dialog_title": "ইভেন্ট যোগ করুন", - "event_type_label": "ইভেন্টের প্রকার", - "triggers_title": "ট্রিগার", - "conditions_title": "শর্ত", - "add_button": "যোগ করুন", - "default_rule_name": "কাস্টম নিয়ম", - "discard_changes_dialog_title": "পরিবর্তনগুলি বাতিল করবেন?", - "discard_changes_dialog_text": "আপনার অসংরক্ষিত পরিবর্তন আছে। আপনি কি সেগুলি বাতিল করতে নিশ্চিত?", - "discard_button": "বাতিল করুন", - "cannot_save_rule_dialog_title": "নিয়ম সংরক্ষণ করা যাবে না", - "cannot_save_rule_dialog_text": "সংরক্ষণ করার জন্য একটি নিয়মে কমপক্ষে একটি ইভেন্ট থাকতে হবে।", - "duplicate_rule_name_dialog_title": "নকল নিয়ম নাম", - "duplicate_rule_name_dialog_text": "এই নামের একটি নিয়ম ইতিমধ্যে বিদ্যমান। অনুগ্রহ করে একটি ভিন্ন নাম চয়ন করুন।", - "delete_rule_dialog_title": "নিয়ম মুছুন", - "delete_rule_dialog_text": "আপনি কি এই নিয়মটি মুছতে নিশ্চিত?", - "new_rule_title": "নতুন নিয়ম", - "edit_rule_title": "নিয়ম সম্পাদনা করুন", - "back_button_description": "ফিরে যান", - "save_button_description": "সংরক্ষণ করুন", - "general_section_title": "সাধারণ", - "rule_name_label": "নিয়মের নাম", - "author_name_label": "লেখকের নাম", - "scope_section_title": "স্কোপ", - "scope_all": "সব", - "scope_whitelist": "হোয়াইটলিস্ট", - "scope_blacklist": "ব্ল্যাকলিস্ট", - "select_friends_groups_button": "বন্ধু/গ্রুপ নির্বাচন করুন ({count})", - "events_section_title": "ইভেন্ট", - "add_event_button": "ইভেন্ট যোগ করুন", - "no_events_text": "কোনো ইভেন্ট নেই" - }, - "friend_tracker_catalog": { - "download_failed": "ডাউনলোড ব্যর্থ হয়েছে: {code}", - "error": "ত্রুটি: {message}", - "no_repos_added": "কোনো সংগ্রহস্থল যোগ করা হয়নি।", - "no_rules_available": "কোনো সংগ্রহস্থল থেকে কোনো নিয়ম উপলব্ধ নেই।", - "by_author": "{author} দ্বারা", - "imported_button": "আমদানি করা হয়েছে", - "import_button": "আমদানি করুন", - "title": "বন্ধু ট্র্যাকার ক্যাটালগ", - "manage_repos_description": "সংগ্রহস্থল পরিচালনা করুন" - }, - "friend_tracker_export": { - "title": "নিয়ম রপ্তানি করুন", - "back_button_description": "ফিরে যান", - "exported_toast": "বন্ধু ট্র্যাকার নিয়ম রপ্তানি করা হয়েছে!", - "export_failed_toast": "নিয়ম রপ্তানি করতে ব্যর্থ হয়েছে: {message}", - "save_button": "সংরক্ষণ করুন", - "expand_button_description": "প্রসারিত করুন" - }, - "friend_tracker_import": { - "title": "নিয়ম আমদানি করুন", - "back_button_description": "ফিরে যান", - "imported_toast": "বন্ধু ট্র্যাকার নিয়ম আমদানি করা হয়েছে!", - "import_failed_toast": "নিয়ম আমদানি করতে ব্যর্থ হয়েছে: {message}", - "confirm_button": "নিশ্চিত করুন", - "expand_button_description": "প্রসারিত করুন" - }, - "friend_tracker_repos": { - "invalid_repo_title": "অবৈধ সংগ্রহস্থল", - "add_repo_button": "সংগ্রহস্থল যোগ করুন", - "add_repo_dialog_title": "সংগ্রহস্থল URL যোগ করুন", - "repo_url_label": "সংগ্রহস্থল URL", - "repo_added_toast": "সংগ্রহস্থল সফলভাবে যোগ করা হয়েছে!", - "invalid_repo_error": "এটি একটি বৈধ বন্ধু ট্র্যাকার সংগ্রহস্থল বলে মনে হচ্ছে না।", - "add_repo_failed_toast": "সংগ্রহস্থল যোগ করতে ব্যর্থ হয়েছে: {message}", - "add_button": "যোগ করুন", - "no_repos_added": "কোনো সংগ্রহস্থল যোগ করা হয়নি", - "remove_button": "সরান", - "remove_repo_dialog_title": "সংগ্রহস্থল সরান", - "remove_repo_dialog_text": "আপনি কি এই সংগ্রহস্থলটি সরাতে নিশ্চিত?" - }, - "navigation": { - "tracker_tab_label": "ট্র্যাকার", - "customize_bottom_bar_title": "নীচের বার কাস্টমাইজ করুন", - "customize_bottom_bar_subtitle": "ট্যাবগুলি পুনরায় সাজান, যোগ করুন বা সরান। সর্বাধিক পাঁচটি।", - "shown_tabs_title": "দেখানো ট্যাব", - "no_tabs_selected_text": "কোনো ট্যাব নির্বাচন করা হয়নি", - "available_tabs_title": "উপলব্ধ ট্যাব", - "reset_button": "রিসেট করুন", - "done_button": "সম্পন্ন" - }, - "scripting": { - "script_already_installed": "স্ক্রিপ্ট ইতিমধ্যে ইনস্টল করা আছে!", - "downloading_script": "স্ক্রিপ্ট ডাউনলোড করা হচ্ছে...", - "script_downloaded": "{name} স্ক্রিপ্ট ডাউনলোড করা হয়েছে!", - "download_script_failed": "স্ক্রিপ্ট ডাউনলোড করতে ব্যর্থ হয়েছে। আরও বিস্তারিত জানার জন্য লগ দেখুন", - "import_script_from_url_title": "URL থেকে স্ক্রিপ্ট আমদানি করুন", - "import_script_warning": "সতর্কতা: আমদানি করা স্ক্রিপ্টগুলি আপনার ডিভাইসের জন্য ক্ষতিকারক হতে পারে। শুধুমাত্র বিশ্বস্ত উৎস থেকে স্ক্রিপ্ট আমদানি করুন।", - "enter_url_label": "এখানে URL লিখুন:", - "script_imported": "{name} স্ক্রিপ্ট আমদানি করা হয়েছে!", - "import_failed": "স্ক্রিপ্ট আমদানি করতে ব্যর্থ হয়েছে। {message}। আরও বিস্তারিত জানার জন্য লগ দেখুন", - "import_button": "আমদানি করুন", - "update_module_button": "মডিউল আপডেট করুন", - "updating_script": "{name} স্ক্রিপ্ট আপডেট করা হচ্ছে...", - "module_not_found": "মডিউল পাওয়া যায়নি", - "updated_script": "{name} সংস্করণ {version}-এ আপডেট করা হয়েছে", - "update_module_failed": "মডিউল আপডেট করতে ব্যর্থ হয়েছে। আরও বিস্তারিত জানার জন্য লগ দেখুন", - "edit_module_button": "মডিউল সম্পাদনা করুন", - "open_module_failed": "মডিউল ফাইল খুলতে ব্যর্থ হয়েছে। আরও বিস্তারিত জানার জন্য লগ দেখুন", - "clear_module_data_button": "মডিউল ডেটা সাফ করুন", - "module_data_cleared": "মডিউল ডেটা সাফ করা হয়েছে!", - "clear_module_data_failed": "মডিউল ডেটা সাফ করতে ব্যর্থ হয়েছে। আরও বিস্তারিত জানার জন্য লগ দেখুন", - "delete_module_button": "মডিউল মুছুন", - "deleted_script": "{name} স্ক্রিপ্ট মুছে ফেলা হয়েছে!", - "delete_module_failed": "মডিউল মুছতে ব্যর্থ হয়েছে। আরও বিস্তারিত জানার জন্য লগ দেখুন", - "actions_title": "ক্রিয়া", - "no_description": "কোনো বর্ণনা নেই", - "update_available": "আপডেট উপলব্ধ: {version}", - "actions_button": "ক্রিয়া", - "loaded_script": "{name} স্ক্রিপ্ট লোড করা হয়েছে", - "unloaded_script": "{name} স্ক্রিপ্ট আনলোড করা হয়েছে", - "enable_script_failed": "স্ক্রিপ্ট সক্ষম করতে ব্যর্থ হয়েছে। আরও বিস্তারিত জানার জন্য লগ দেখুন", - "disable_script_failed": "স্ক্রিপ্ট অক্ষম করতে ব্যর্থ হয়েছে। আরও বিস্তারিত জানার জন্য লগ দেখুন", - "select_scripts_folder_toast": "অনুগ্রহ করে আপনার স্ক্রিপ্ট ফোল্ডার নির্বাচন করুন!", - "manage_repos_button": "সংগ্রহস্থল পরিচালনা করুন", - "import_from_url_button": "URL থেকে আমদানি করুন", - "open_scripts_folder_button": "স্ক্রিপ্ট ফোল্ডার খুলুন", - "no_settings_for_module": "এই মডিউলের কোনো সেটিংস নেই", - "installed_scripts_tab": "ইনস্টল করা স্ক্রিপ্ট", - "catalog_tab": "ক্যাটালগ", - "no_scripts_folder_selected_title": "কোনো স্ক্রিপ্ট ফোল্ডার নির্বাচন করা হয়নি", - "select_folder_button": "ফোল্ডার নির্বাচন করুন", - "no_scripts_found_title": "কোনো স্ক্রিপ্ট পাওয়া যায়নি।", - "use_catalog_to_add_scripts": "স্ক্রিপ্ট যোগ করতে ক্যাটালগ ট্যাব ব্যবহার করুন!", - "ok_button_timeout": "ঠিক আছে ({timeout})", - "documentation_button": "ডকুমেন্টেশন", - "catalog": { - "script_already_installed": "স্ক্রিপ্ট ইতিমধ্যে ইনস্টল করা আছে!", - "download_failed": "ডাউনলোড ব্যর্থ হয়েছে: {code}", - "script_downloaded": "স্ক্রিপ্ট ডাউনলোড করা হয়েছে!", - "could_not_create_file": "ফাইল তৈরি করা যায়নি।", - "no_scripts_folder_selected": "কোনো স্ক্রিপ্ট ফোল্ডার নির্বাচন করা হয়নি।", - "error": "ত্রুটি: {message}", - "no_repos_added": "কোনো সংগ্রহস্থল যোগ করা হয়নি।", - "repo_list_info": "এখানে আপনি সংগ্রহস্থলের একটি তালিকা খুঁজে পেতে পারেন: ", - "link_text": "লিঙ্ক", - "no_scripts_available": "কোনো সংগ্রহস্থল থেকে কোনো স্ক্রিপ্ট উপলব্ধ নেই।", - "by_author": "{author} দ্বারা", - "version": "সংস্করণ: {version}", - "installed_button": "ইনস্টল করা হয়েছে", - "download_button": "ডাউনলোড করুন" - }, - "repos": { - "invalid_repo_title": "অবৈধ সংগ্রহস্থল", - "add_repo_button": "সংগ্রহস্থল যোগ করুন", - "add_repo_dialog_title": "সংগ্রহস্থল URL যোগ করুন", - "repo_url_label": "সংগ্রহস্থল URL", - "repo_added_toast": "সংগ্রহস্থল সফলভাবে যোগ করা হয়েছে!", - "invalid_repo_error": "এটি একটি বৈধ স্ক্রিপ্ট সংগ্রহস্থল বলে মনে হচ্ছে না।", - "add_repo_failed_toast": "সংগ্রহস্থল যোগ করতে ব্যর্থ হয়েছে: {message}", - "add_button": "যোগ করুন", - "no_repos_added": "কোনো সংগ্রহস্থল যোগ করা হয়নি", - "remove_button": "সরান", - "remove_repo_dialog_title": "সংগ্রহস্থল সরান", - "remove_repo_dialog_text": "আপনি কি এই সংগ্রহস্থলটি সরাতে নিশ্চিত?" - } - }, - "features": { - "config_import": { - "title": "আমদানি নিশ্চিত করুন", - "back_button_description": "ফিরে যান", - "config_imported_toast": "কনফিগ আমদানি করা হয়েছে!", - "confirm_button": "নিশ্চিত করুন", - "expand_button_description": "প্রসারিত করুন", - "enable_feature": "বৈশিষ্ট্য সক্ষম করুন", - "enabled": "সক্ষম", - "disabled": "অক্ষম" - }, - "config_export": { - "title": "রপ্তানি সারাংশ", - "back_button_description": "ফিরে যান", - "save_button": "সংরক্ষণ করুন", - "expand_button_description": "প্রসারিত করুন", - "enable_feature": "বৈশিষ্ট্য সক্ষম করুন", - "enabled": "সক্ষম", - "disabled": "অক্ষম" - } - }, - "manage_repos": { - "title": "সংগ্রহস্থল {type} পরিচালনা করুন", - "add_repo_button": "সংগ্রহস্থল যোগ করুন", - "add_repo_dialog_title": "সংগ্রহস্থল URL যোগ করুন", - "repo_url_label": "সংগ্রহস্থল URL", - "repo_added_successfully": "সংগ্রহস্থল সফলভাবে যোগ করা হয়েছে!", - "add_repo_failed": "সংগ্রহস্থল যোগ করতে ব্যর্থ হয়েছে: {message}", - "add_button": "যোগ করুন", - "no_repos_added": "কোনো সংগ্রহস্থল যোগ করা হয়নি", - "remove_button": "সরান" - } - }, - "rules": { - "toasts": { - "enabled": "{ruleName} সক্ষম", - "disabled": "{ruleName} অক্ষম" - }, - "modes": { - "blacklist": "ব্ল্যাকলিস্ট মোড", - "whitelist": "হোয়াইটলিস্ট মোড" - }, - "properties": { - "auto_download": { - "name": "স্বয়ংক্রিয় ডাউনলোড", - "description": "স্ন্যাপ দেখার সময় স্বয়ংক্রিয়ভাবে ডাউনলোড করুন", - "options": { - "blacklist": "স্বয়ংক্রিয় ডাউনলোড থেকে বাদ দিন", - "whitelist": "স্বয়ংক্রিয় ডাউনলোড" - } - }, - "stealth": { - "name": "স্টিলথ মোড", - "description": "আপনি তাদের স্ন্যাপ/চ্যাট এবং কথোপকথন খুলেছেন তা কাউকে জানতে বাধা দেয়", - "options": { - "blacklist": "স্টিলথ মোড থেকে বাদ দিন", - "whitelist": "স্টিলথ মোড" - } - }, - "auto_save": { - "name": "স্বয়ংক্রিয় সংরক্ষণ", - "description": "চ্যাট বার্তা দেখার সময় সংরক্ষণ করে", - "options": { - "blacklist": "স্বয়ংক্রিয় সংরক্ষণ থেকে বাদ দিন", - "whitelist": "স্বয়ংক্রিয় সংরক্ষণ" - } - }, - "unsaveable_messages": { - "name": "অসংরক্ষণযোগ্য বার্তা", - "description": "অন্যান্য ব্যক্তিদের দ্বারা চ্যাটে বার্তা সংরক্ষণ করা থেকে বাধা দেয়", - "options": { - "blacklist": "অসংরক্ষণযোগ্য বার্তা থেকে বাদ দিন", - "whitelist": "অসংরক্ষণযোগ্য বার্তা" - } - }, - "auto_open_snaps": { - "name": "স্বয়ংক্রিয়ভাবে স্ন্যাপ খুলুন", - "description": "স্ন্যাপ পাওয়ার সময় স্বয়ংক্রিয়ভাবে খোলে", - "options": { - "blacklist": "স্বয়ংক্রিয়ভাবে স্ন্যাপ খোলা থেকে বাদ দিন", - "whitelist": "স্বয়ংক্রিয়ভাবে স্ন্যাপ খুলুন" - } - }, - "hide_friend_feed": { - "name": "বন্ধু ফিড থেকে লুকান" - }, - "e2e_encryption": { - "name": "E2E এনক্রিপশন ব্যবহার করুন" - }, - "pin_conversation": { - "name": "কথোপকথন পিন করুন" - }, - "exclude_message_logger": { - "name": "বার্তা লগার থেকে বাদ দিন" - } - } - }, - "actions": { - "clean_snapchat_cache": { - "name": "Snapchat ক্যাশে পরিষ্কার করুন", - "description": "Snapchat ক্যাশে পরিষ্কার করে" - }, - "manage_friend_list": { - "name": "বন্ধু তালিকা পরিচালনা করুন", - "description": "ব্যাকআপ করার সময় আপনার বন্ধু তালিকা আমদানি/রপ্তানি করুন" - }, - "export_chat_messages": { - "name": "চ্যাট বার্তা রপ্তানি করুন", - "description": "কথোপকথন বার্তাগুলি একটি JSON/HTML/TXT ফাইলে রপ্তানি করে" - }, - "export_memories": { - "name": "স্মৃতি রপ্তানি করুন", - "description": "স্মৃতিগুলি একটি ZIP ফাইলে রপ্তানি করে" - }, - "bulk_messaging_action": { - "name": "বাল্ক মেসেজিং ক্রিয়া", - "description": "বন্ধু মুছে ফেলা বা কথোপকথনের ব্যাপক মুছে ফেলার মতো ক্রিয়াকলাপ সম্পাদন করে" - }, - "regen_mappings": { - "name": "ম্যাপিং পুনরায় তৈরি করুন", - "description": "ম্যানুয়ালি ম্যাপিং পুনরায় তৈরি করুন" - }, - "change_language": { - "name": "ভাষা পরিবর্তন করুন", - "description": "PurrfectSnap-এর ভাষা পরিবর্তন করুন" - }, - "file_imports": { - "name": "ফাইল আমদানি", - "description": "Snapchat-এ ব্যবহারের জন্য ফাইল আমদানি করুন" - }, - "friend_tracker": { - "name": "বন্ধু ট্র্যাকার", - "description": "Snapchat-এ আপনার বন্ধুদের ট্র্যাক করুন" - }, - "logger_history": { - "name": "লগার ইতিহাস", - "description": "লগ করা বার্তাগুলির ইতিহাস দেখুন" - } - }, - "features": { - "notices": { - "unstable": "⚠️ অস্থির", - "ban_risk": "⚠️ এই বৈশিষ্ট্যটি নিষেধাজ্ঞার কারণ হতে পারে", - "internal_behavior": "⚠️ এটি Snapchat-এর অভ্যন্তরীণ আচরণ ভঙ্গ করতে পারে" - }, - "properties": { - "downloader": { - "name": "ডাউনলোডার", - "description": "Snapchat মিডিয়া ডাউনলোড করুন", - "properties": { - "save_folder": { - "name": "ফোল্ডার সংরক্ষণ করুন", - "description": "যে ডিরেক্টরিতে সমস্ত মিডিয়া ডাউনলোড করা হবে তা নির্বাচন করুন" - }, - "auto_download_sources": { - "name": "স্বয়ংক্রিয় ডাউনলোড উৎস", - "description": "যে উৎসগুলি থেকে স্বয়ংক্রিয়ভাবে ডাউনলোড করা হবে তা নির্বাচন করুন" - }, - "prevent_self_auto_download": { - "name": "স্বয়ংক্রিয়ভাবে নিজের ডাউনলোড প্রতিরোধ করুন", - "description": "আপনার নিজের স্ন্যাপগুলি স্বয়ংক্রিয়ভাবে ডাউনলোড হওয়া থেকে বাধা দেয়" - }, - "path_format": { - "name": "পথ বিন্যাস", - "description": "ফাইলের পথ বিন্যাস নির্দিষ্ট করুন" - }, - "allow_duplicate": { - "name": "অনুলিপি অনুমতি দিন", - "description": "একই মিডিয়া একাধিকবার ডাউনলোড করার অনুমতি দেয়" - }, - "merge_overlays": { - "name": "ওভারলে একীভূত করুন", - "description": "একটি স্ন্যাপের পাঠ্য এবং মিডিয়া একটি একক ফাইলে একত্রিত করে" - }, - "force_image_format": { - "name": "চিত্র বিন্যাস জোর করুন", - "description": "একটি নির্দিষ্ট বিন্যাসে ছবি সংরক্ষণ করতে বাধ্য করে" - }, - "force_voice_note_format": { - "name": "ভয়েস নোট বিন্যাস জোর করুন", - "description": "একটি নির্দিষ্ট বিন্যাসে ভয়েস নোট সংরক্ষণ করতে বাধ্য করে" - }, - "auto_download_voice_notes": { - "name": "স্বয়ংক্রিয়ভাবে ভয়েস নোট ডাউনলোড করুন", - "description": "ভয়েস নোট চালানোর সময় স্বয়ংক্রিয়ভাবে ডাউনলোড করে" - }, - "download_profile_pictures": { - "name": "প্রোফাইল ছবি ডাউনলোড করুন", - "description": "প্রোফাইল পৃষ্ঠা থেকে প্রোফাইল ছবি ডাউনলোড করার অনুমতি দেয়" - }, - "opera_download_button": { - "name": "অপেরা ডাউনলোড বোতাম", - "description": "একটি স্ন্যাপ দেখার সময় উপরের ডান কোণে একটি ডাউনলোড বোতাম যোগ করে।\nবোতামগুলিতে দীর্ঘক্ষণ চাপ দিলে ডাউনলোড করতে বাধ্য করবে" - }, - "download_context_menu": { - "name": "ডাউনলোড প্রসঙ্গ মেনু", - "description": "প্রসঙ্গ মেনু ব্যবহার করে একটি কথোপকথন বা একটি গল্প থেকে বার্তা ডাউনলোড/প্রিভিউ করার অনুমতি দেয়।\nবোতামগুলিতে দীর্ঘক্ষণ চাপ দিলে ডাউনলোড করতে বাধ্য করবে" - }, - "ffmpeg_options": { - "name": "FFmpeg বিকল্প", - "description": "অতিরিক্ত FFmpeg বিকল্প নির্দিষ্ট করুন", - "properties": { - "threads": { - "name": "থ্রেড", - "description": "ব্যবহার করার জন্য থ্রেডের পরিমাণ" - }, - "preset": { - "name": "প্রিসেট", - "description": "রূপান্তরের গতি সেট করুন" - }, - "constant_rate_factor": { - "name": "ধ্রুবক হার ফ্যাক্টর", - "description": "ভিডিও এনকোডারের জন্য ধ্রুবক হার ফ্যাক্টর সেট করুন\nlibx264-এর জন্য 0 থেকে 51 পর্যন্ত" - }, - "video_bitrate": { - "name": "ভিডিও বিটরেট", - "description": "ভিডিও বিটরেট সেট করুন (kbps)" - }, - "audio_bitrate": { - "name": "অডিও বিটরেট", - "description": "অডিও বিটরেট সেট করুন (kbps)" - }, - "custom_video_codec": { - "name": "কাস্টম ভিডিও কোডেক", - "description": "একটি কাস্টম ভিডিও কোডেক সেট করুন (যেমন libx264)" - }, - "custom_audio_codec": { - "name": "কাস্টম অডিও কোডেক", - "description": "একটি কাস্টম অডিও কোডেক সেট করুন (যেমন AAC)" - } - } - }, - "logging": { - "name": "লগিং", - "description": "মিডিয়া ডাউনলোড করার সময় টোস্ট দেখায়" - }, - "custom_path_format": { - "name": "কাস্টম পথ বিন্যাস", - "description": "ডাউনলোড করা মিডিয়ার জন্য একটি কাস্টম পথ বিন্যাস নির্দিষ্ট করুন\n\nউপলব্ধ ভেরিয়েবল:\n - %username%\n - %source%\n - %hash%\n - %date_time%" - } - } - }, - "user_interface": { - "name": "ব্যবহারকারী ইন্টারফেস", - "description": "Snapchat-এর চেহারা এবং অনুভূতি পরিবর্তন করুন", - "properties": { - "enable_app_appearance": { - "name": "অ্যাপ চেহারা সেটিংস সক্ষম করুন", - "description": "লুকানো অ্যাপ চেহারা সেটিং সক্ষম করে\nনতুন Snapchat সংস্করণে প্রয়োজন নাও হতে পারে" - }, - "friend_feed_message_preview": { - "name": "বন্ধু ফিড বার্তা প্রিভিউ", - "description": "বন্ধু ফিডে শেষ বার্তাগুলির একটি প্রিভিউ দেখায়", - "properties": { - "amount": { - "name": "পরিমাণ", - "description": "প্রিভিউ করার জন্য বার্তার পরিমাণ" - } - } - }, - "snap_preview": { - "name": "স্ন্যাপ প্রিভিউ", - "description": "চ্যাটে অদেখা স্ন্যাপগুলির পাশে একটি ছোট প্রিভিউ প্রদর্শন করে" - }, - "bootstrap_override": { - "name": "বুটস্ট্র্যাপ ওভাররাইড", - "description": "ব্যবহারকারী ইন্টারফেস বুটস্ট্র্যাপ সেটিংস ওভাররাইড করে", - "properties": { - "app_appearance": { - "name": "অ্যাপ চেহারা", - "description": "একটি স্থায়ী অ্যাপ চেহারা সেট করে" - }, - "home_tab": { - "name": "হোম ট্যাব", - "description": "Snapchat খোলার সময় স্টার্টআপ ট্যাব ওভাররাইড করে" - } - } - }, - "force_amoled_theme": { - "name": "অ্যামোলেড ডার্ক মোড", - "description": "ডার্ক থিমের জন্য একটি সত্যিকারের কালো পটভূমি ব্যবহার করে" - }, - "map_friend_nametags": { - "name": "উন্নত বন্ধু মানচিত্র নামট্যাগ", - "description": "স্ন্যাপম্যাপে বন্ধুদের নামট্যাগ উন্নত করে" - }, - "prevent_message_list_auto_scroll": { - "name": "বার্তা তালিকা স্বয়ংক্রিয় স্ক্রোল প্রতিরোধ করুন", - "description": "একটি বার্তা পাঠানো/গ্রহণ করার সময় বার্তা তালিকা নীচে স্ক্রোল করা থেকে বাধা দেয়" - }, - "streak_expiration_info": { - "name": "ধারাবাহিকতার মেয়াদ শেষ হওয়ার তথ্য দেখান", - "description": "ধারাবাহিকতা কাউন্টারের পাশে একটি ধারাবাহিকতার মেয়াদ শেষ হওয়ার টাইমার দেখায়" - }, - "hide_friend_feed_entry": { - "name": "বন্ধু ফিড এন্ট্রি লুকান", - "description": "বন্ধু ফিড থেকে একটি নির্দিষ্ট বন্ধু লুকায়\nএই বৈশিষ্ট্যটি পরিচালনা করতে সামাজিক ট্যাব ব্যবহার করুন" - }, - "hide_streak_restore": { - "name": "ধারাবাহিকতা পুনরুদ্ধার লুকান", - "description": "বন্ধু ফিডে পুনরুদ্ধার বোতাম লুকায়" - }, - "hide_quick_add_suggestions": { - "name": "দ্রুত যোগ পরামর্শ লুকান", - "description": "দ্রুত যোগ বন্ধু পরামর্শগুলি সরিয়ে দেয়" - }, - "hide_story_suggestions": { - "name": "গল্প পরামর্শ লুকান", - "description": "গল্প পৃষ্ঠা থেকে পরামর্শগুলি সরিয়ে দেয়" - }, - "hide_ui_components": { - "name": "UI উপাদান লুকান", - "description": "কোন UI উপাদানগুলি লুকানো হবে তা নির্বাচন করুন" - }, - "opera_media_quick_info": { - "name": "অপেরা মিডিয়া দ্রুত তথ্য", - "description": "অপেরা ভিউয়ার প্রসঙ্গ মেনুতে মিডিয়ার দরকারী তথ্য যেমন তৈরির তারিখ দেখায়" - }, - "old_bitmoji_selfie": { - "name": "পুরানো বিটমোজি সেলফি", - "description": "পুরানো Snapchat সংস্করণ থেকে বিটমোজি সেলফি ফিরিয়ে আনে" - }, - "disable_spotlight": { - "name": "স্পটলাইট অক্ষম করুন", - "description": "স্পটলাইট পৃষ্ঠা অক্ষম করে" - }, - "friend_feed_menu_buttons": { - "name": "বন্ধু ফিড মেনু বোতাম", - "description": "বন্ধু ফিড মেনুতে কোন বোতামগুলি দেখানো হবে তা নির্বাচন করুন" - }, - "auto_close_friend_feed_menu": { - "name": "বন্ধু ফিড মেনু স্বয়ংক্রিয়ভাবে বন্ধ করুন", - "description": "একটি সেটিং বোতাম চাপার পরে বন্ধু ফিড মেনু স্বয়ংক্রিয়ভাবে বন্ধ করে" - }, - "vertical_story_viewer": { - "name": "উল্লম্ব গল্প ভিউয়ার", - "description": "সমস্ত গল্পের জন্য উল্লম্ব গল্প ভিউয়ার সক্ষম করে" - }, - "enable_friend_feed_menu_bar": { - "name": "বন্ধু ফিড মেনু বার", - "description": "নতুন বন্ধু ফিড মেনু বার সক্ষম করে" - }, - "message_indicators": { - "name": "বার্তা সূচক", - "description": "বার্তাগুলিতে নির্দিষ্ট সূচক আইকন যোগ করে\nদ্রষ্টব্য: সূচকগুলি 100% সঠিক নাও হতে পারে" - }, - "stealth_mode_indicator": { - "name": "স্টিলথ মোড সূচক", - "description": "স্টিলথ মোডে কথোপকথনের পাশে একটি 👻 ইমোজি যোগ করে" - }, - "edit_text_override": { - "name": "পাঠ্য সম্পাদনা ওভাররাইড", - "description": "পাঠ্য ক্ষেত্রের আচরণ ওভাররাইড করে" - }, - "prevent_forced_keyboard": { - "name": "বাধ্যতামূলক কীবোর্ড প্রতিরোধ করুন", - "description": "আপনি একটি কথোপকথন খোলার সময় Snapchat কে স্বয়ংক্রিয়ভাবে কীবোর্ড পপ আপ করা থেকে বাধা দেয়" - }, - "settings_menu": { - "name": "সেটিংস মেনু", - "description": "আপনি যেভাবে PurrfectSnap মেনু খুলবেন তা পরিবর্তন করে", - "options": { - "default": "ডিফল্ট", - "legacy": "উত্তরাধিকার" - } - } - } - }, - "messaging": { - "name": "মেসেজিং", - "description": "বন্ধুদের সাথে আপনার যোগাযোগের উপায় পরিবর্তন করুন", - "properties": { - "bypass_screenshot_detection": { - "name": "স্ক্রিনশট সনাক্তকরণ বাইপাস করুন", - "description": "আপনি যখন একটি স্ক্রিনশট নেন তখন Snapchat কে সনাক্ত করা থেকে বাধা দেয়" - }, - "anonymous_story_viewing": { - "name": "বেনামী গল্প দেখা", - "description": "আপনি তাদের গল্প দেখেছেন তা কাউকে জানতে বাধা দেয়" - }, - "prevent_story_rewatch_indicator": { - "name": "গল্প পুনরায় দেখার সূচক প্রতিরোধ করুন", - "description": "আপনি তাদের গল্প পুনরায় দেখেছেন তা কাউকে জানতে বাধা দেয়" - }, - "hide_peek_a_peek": { - "name": "পিক-এ-পিক লুকান", - "description": "আপনি যখন একটি চ্যাটে অর্ধেক সোয়াইপ করেন তখন বিজ্ঞপ্তি পাঠানো থেকে বাধা দেয়" - }, - "hide_bitmoji_presence": { - "name": "বিটমোজি উপস্থিতি লুকান", - "description": "চ্যাটে থাকাকালীন আপনার বিটমোজি পপ আপ হওয়া থেকে বাধা দেয়" - }, - "hide_typing_notifications": { - "name": "টাইপিং বিজ্ঞপ্তি লুকান", - "description": "আপনি একটি বার্তা টাইপ করছেন তা কাউকে জানতে বাধা দেয়" - }, - "unlimited_snap_view_time": { - "name": "সীমাহীন স্ন্যাপ দেখার সময়", - "description": "স্ন্যাপ দেখার জন্য সময়সীমা সরিয়ে দেয়" - }, - "auto_mark_as_read": { - "name": "স্বয়ংক্রিয়ভাবে পঠিত হিসাবে চিহ্নিত করুন", - "description": "স্টিলথ মোড সক্ষম থাকলেও বার্তা/স্ন্যাপগুলি স্বয়ংক্রিয়ভাবে পঠিত হিসাবে চিহ্নিত করে" - }, - "mark_snap_as_seen_button": { - "name": "স্ন্যাপকে দেখা হিসাবে চিহ্নিত করুন বোতাম", - "description": "একটি স্ন্যাপ দেখার সময় এটিকে দেখা হিসাবে চিহ্নিত করার জন্য একটি বোতাম যোগ করে।\nএটি স্টিলথ মোড সক্ষম থাকলেও কাজ করবে" - }, - "skip_when_marking_as_seen": { - "name": "দেখা হিসাবে চিহ্নিত করার সময় এড়িয়ে যান", - "description": "একটি স্ন্যাপকে দেখা হিসাবে চিহ্নিত করার সময় স্বয়ংক্রিয়ভাবে পরবর্তী স্ন্যাপে এড়িয়ে যায়।\nস্ন্যাপকে দেখা হিসাবে চিহ্নিত করুন বোতামের সাথে একত্রে ব্যবহার করুন" - }, - "loop_media_playback": { - "name": "লুপ মিডিয়া প্লেব্যাক", - "description": "স্ন্যাপ/গল্প দেখার সময় মিডিয়া প্লেব্যাক লুপ করে" - }, - "disable_replay_in_ff": { - "name": "FF-এ রিপ্লে অক্ষম করুন", - "description": "বন্ধু ফিড থেকে একটি দীর্ঘ চাপ দিয়ে রিপ্লে করার ক্ষমতা অক্ষম করে" - }, - "half_swipe_notifier": { - "name": "হাফ সোয়াইপ নোটিফায়ার", - "description": "কেউ একটি কথোপকথনে অর্ধেক সোয়াইপ করলে আপনাকে অবহিত করে", - "properties": { - "min_duration": { - "name": "ন্যূনতম সময়কাল", - "description": "হাফ সোয়াইপের ন্যূনতম সময়কাল (সেকেন্ডে)" - }, - "max_duration": { - "name": "সর্বাধিক সময়কাল", - "description": "হাফ সোয়াইপের সর্বাধিক সময়কাল (সেকেন্ডে)" - } - } - }, - "call_start_confirmation": { - "name": "কল শুরু নিশ্চিতকরণ", - "description": "একটি কল শুরু করার সময় একটি নিশ্চিতকরণ ডায়ালগ দেখায়" - }, - "unlimited_conversation_pinning": { - "name": "সীমাহীন কথোপকথন পিনিং", - "description": "আপনাকে স্থানীয়ভাবে সীমাহীন সংখ্যক কথোপকথন পিন করার অনুমতি দেয়" - }, - "disable_snap_mode_restrictions": { - "name": "স্ন্যাপ মোড বিধিনিষেধ অক্ষম করুন", - "description": "আপনাকে বিধিনিষেধ ছাড়াই স্ব-ধ্বংসকারী স্ন্যাপগুলি দেখার অনুমতি দেয়" - }, - "prevent_message_sending": { - "name": "বার্তা পাঠানো প্রতিরোধ করুন", - "description": "নির্দিষ্ট ধরণের বার্তা পাঠানো প্রতিরোধ করে" - }, - "friend_mutation_notifier": { - "name": "বন্ধু মিউটেশন নোটিফায়ার", - "description": "একটি বন্ধুর প্রোফাইলে কিছু পরিবর্তন হলে আপনাকে অবহিত করে" - }, - "better_notifications": { - "name": "আরও ভাল বিজ্ঞপ্তি", - "description": "প্রাপ্ত বিজ্ঞপ্তিগুলিতে আরও তথ্য যোগ করে", - "properties": { - "group_notifications": { - "name": "গ্রুপ বিজ্ঞপ্তি", - "description": "গ্রুপ বিজ্ঞপ্তিগুলিকে একটি একক বিজ্ঞপ্তিতে গ্রুপ করে" - }, - "chat_preview": { - "name": "চ্যাট প্রিভিউ", - "description": "বিজ্ঞপ্তিতে প্রাপ্ত বার্তাগুলির একটি প্রিভিউ দেখায়" - }, - "media_preview": { - "name": "মিডিয়া প্রিভিউ", - "description": "বিজ্ঞপ্তিতে নির্বাচিত মিডিয়া প্রকারগুলির একটি প্রিভিউ দেখায়" - }, - "media_caption": { - "name": "মিডিয়া ক্যাপশন", - "description": "বিজ্ঞপ্তিতে মিডিয়ার সংযুক্ত ক্যাপশন দেখায়" - }, - "stacked_media_messages": { - "name": "স্ট্যাক করা মিডিয়া বার্তা", - "description": "একাধিক মিডিয়া বার্তাগুলিকে একটি পাঠ্য বিজ্ঞপ্তিতে একত্রিত করে যখন সেগুলি প্রিভিউ করা যায় না। চ্যাট প্রিভিউয়ের সাথে একত্রে ব্যবহার করুন" - }, - "friend_add_source": { - "name": "বন্ধু যোগ করার উৎস", - "description": "বিজ্ঞপ্তিতে একটি বন্ধু অনুরোধের উৎস দেখায়" - }, - "reply_button": { - "name": "উত্তর বোতাম", - "description": "বিজ্ঞপ্তিতে একটি উত্তর বোতাম যোগ করে" - }, - "smart_replies": { - "name": "স্মার্ট উত্তর", - "description": "বিজ্ঞপ্তিগুলিতে প্রস্তাবিত উত্তর যোগ করে (Android 10+)। উত্তর বোতামের সাথে একত্রে ব্যবহার করুন" - }, - "download_button": { - "name": "ডাউনলোড বোতাম", - "description": "আপনাকে বিজ্ঞপ্তি থেকে মিডিয়া ডাউনলোড করার অনুমতি দেয়" - }, - "mark_as_read_button": { - "name": "পঠিত হিসাবে চিহ্নিত করুন বোতাম", - "description": "আপনাকে বিজ্ঞপ্তি থেকে একটি বার্তা পঠিত হিসাবে চিহ্নিত করার অনুমতি দেয়" - }, - "mark_as_read_and_save_in_chat": { - "name": "পঠিত হিসাবে চিহ্নিত করুন এবং চ্যাটে সংরক্ষণ করুন", - "description": "বিজ্ঞপ্তিতে একটি পঠিত হিসাবে চিহ্নিত করুন এবং চ্যাটে সংরক্ষণ করুন বোতাম যোগ করে" - } - } - }, - "notification_blacklist": { - "name": "বিজ্ঞপ্তি ব্ল্যাকলিস্ট", - "description": "যে বিজ্ঞপ্তিগুলি ব্লক করা উচিত তা নির্বাচন করুন" - }, - "message_logger": { - "name": "বার্তা লগার", - "description": "বার্তা মুছে ফেলা থেকে বাধা দেয়", - "properties": { - "keep_my_own_messages": { - "name": "আমার নিজের বার্তা রাখুন", - "description": "আপনার নিজের বার্তা মুছে ফেলা থেকে বাধা দেয়" - }, - "auto_purge": { - "name": "স্বয়ংক্রিয় পরিস্কার", - "description": "নির্দিষ্ট সময়ের চেয়ে পুরানো ক্যাশে করা বার্তাগুলি স্বয়ংক্রিয়ভাবে মুছে ফেলে" - }, - "message_filter": { - "name": "বার্তা ফিল্টার", - "description": "কোন বার্তাগুলি লগ করা উচিত তা নির্বাচন করুন (সমস্ত বার্তার জন্য খালি)" - }, - "deleted_message_color": { - "name": "মুছে ফেলা বার্তার রঙ", - "description": "মুছে ফেলা বার্তাগুলির রঙ সেট করে" - } - } - }, - "auto_save_messages_in_conversations": { - "name": "কথোপকথনে বার্তা স্বয়ংক্রিয়ভাবে সংরক্ষণ করুন", - "description": "কথোপকথনে প্রতিটি বার্তা স্বয়ংক্রিয়ভাবে সংরক্ষণ করে" - }, - "gallery_media_send_override": { - "name": "গ্যালারী মিডিয়া প্রেরণ ওভাররাইড", - "description": "গ্যালারী থেকে প্রেরণ করার সময় মিডিয়া উৎস স্পুফ করে" - }, - "strip_media_metadata": { - "name": "মিডিয়া মেটাডেটা স্ট্রিপ করুন", - "description": "একটি বার্তা হিসাবে পাঠানোর আগে মিডিয়ার মেটাডেটা সরিয়ে দেয়" - }, - "bypass_message_retention_policy": { - "name": "বার্তা ধারণ নীতি বাইপাস করুন", - "description": "বার্তা দেখার পরে মুছে ফেলা থেকে বাধা দেয়" - }, - "bypass_message_action_restrictions": { - "name": "বার্তা ক্রিয়া বিধিনিষেধ বাইপাস করুন", - "description": "আপনাকে একটি স্ন্যাপ না খুলেও প্রতিক্রিয়া জানাতে বা একটি অসংরক্ষণযোগ্য বার্তা সংরক্ষণ করতে দেয়" - }, - "remove_groups_locked_status": { - "name": "গ্রুপ লক করা স্থিতি সরান", - "description": "আপনাকে কিক করার পরে গ্রুপ তথ্য দেখার অনুমতি দেয়" - }, - "double_tap_chat_action": { - "name": "ডবল ট্যাপ চ্যাট ক্রিয়া", - "description": "চ্যাটে একটি বার্তায় ডবল ট্যাপ করার সময় একটি কাস্টম ক্রিয়া সম্পাদন করে" - }, - "double_tap_chat_action_custom_emoji": { - "name": "ডবল ট্যাপ চ্যাট ক্রিয়া কাস্টম ইমোজি প্রতিক্রিয়া", - "description": "ডবল ট্যাপ চ্যাট ক্রিয়ার জন্য একটি কাস্টম ইমোজি প্রতিক্রিয়া সেট করে" - } - } - }, - "global": { - "name": "বিশ্বব্যাপী", - "description": "বিশ্বব্যাপী Snapchat সেটিংস টুইক করুন", - "properties": { - "better_location": { - "name": "আরও ভাল অবস্থান", - "description": "Snapchat অবস্থান উন্নত করে", - "properties": { - "spoof_location": { - "name": "অবস্থান স্পুফ করুন", - "description": "আপনার অবস্থান একটি নির্দিষ্ট অবস্থানে স্পুফ করে" - }, - "coordinates": { - "name": "স্থানাঙ্ক", - "description": "স্পুফ করা অবস্থানের স্থানাঙ্ক সেট করুন" - }, - "walk_radius": { - "name": "হাঁটার ব্যাসার্ধ", - "description": "এই ব্যাসার্ধের মধ্যে এলোমেলোভাবে হাঁটুন (ফুট)" - }, - "always_update_location": { - "name": "সর্বদা অবস্থান আপডেট করুন", - "description": "কোনো GPS ডেটা না পেলেও অবস্থান আপডেট করতে Snapchat কে বাধ্য করুন" - }, - "suspend_location_updates": { - "name": "অবস্থান আপডেট স্থগিত করুন", - "description": "আপনার অবস্থান আপডেট হওয়া থেকে বাধা দেয়" - }, - "spoof_battery_level": { - "name": "ব্যাটারি স্তর স্পুফ করুন", - "description": "মানচিত্রে আপনার ডিভাইসের ব্যাটারি স্তর স্পুফ করে\nমান 0 থেকে 100 এর মধ্যে হতে হবে" - }, - "spoof_headphones": { - "name": "হেডফোন স্পুফ করুন", - "description": "মানচিত্রে গান শোনার স্থিতি স্পুফ করে" - }, - "show_battery_level": { - "name": "ব্যাটারি স্তর দেখান", - "description": "মানচিত্রে আপনার বন্ধুদের ব্যাটারি স্তর দেখায়" - } - } - }, - "snapchat_plus": { - "name": "স্ন্যাপচ্যাট প্লাস", - "description": "Snapchat Plus বৈশিষ্ট্য সক্ষম করে\nকিছু সার্ভার-সাইড বৈশিষ্ট্য কাজ নাও করতে পারে" - }, - "media_upload_quality": { - "name": "মিডিয়া আপলোড গুণমান", - "description": "মিডিয়া আপলোড গুণমান ওভাররাইড করে", - "properties": { - "force_video_upload_source_quality": { - "name": "ভিডিও আপলোড উৎস গুণমান জোর করুন", - "description": "ভিডিও আপলোড করার সময় উৎস গুণমান ব্যবহার করতে Snapchat কে বাধ্য করে\nঅনুগ্রহ করে মনে রাখবেন যে এটি মিডিয়া থেকে মেটাডেটা নাও সরাতে পারে" - }, - "disable_image_compression": { - "name": "চিত্র সংক্ষেপণ অক্ষম করুন", - "description": "মিডিয়া আপলোড করার সময় চিত্র সংক্ষেপণ অক্ষম করে" - }, - "custom_image_upload_format": { - "name": "কাস্টম চিত্র আপলোড বিন্যাস", - "description": "একটি কাস্টম চিত্র আপলোড বিন্যাস সেট করে\nসেরা গুণমানের জন্য একটি ক্ষতিহীন বিন্যাস (যেমন PNG) নির্বাচন করুন" - } - } - }, - "disable_confirmation_dialogs": { - "name": "নিশ্চিতকরণ ডায়ালগ অক্ষম করুন", - "description": "নির্বাচিত ক্রিয়াগুলি স্বয়ংক্রিয়ভাবে নিশ্চিত করে" - }, - "auto_updater": { - "name": "স্বয়ংক্রিয় আপডেটার", - "description": "নতুন আপডেটের জন্য স্বয়ংক্রিয়ভাবে পরীক্ষা করে" - }, - "disable_metrics": { - "name": "মেট্রিক্স অক্ষম করুন", - "description": "Snapchat-এ নির্দিষ্ট বিশ্লেষণাত্মক ডেটা পাঠানো ব্লক করে" - }, - "disable_story_sections": { - "name": "গল্প বিভাগ অক্ষম করুন", - "description": "গল্প পৃষ্ঠা থেকে বিভাগগুলি সরিয়ে দেয়\nসঠিকভাবে কাজ করার জন্য একটি রিফ্রেশ প্রয়োজন হতে পারে" - }, - "block_ads": { - "name": "বিজ্ঞাপন ব্লক করুন", - "description": "বিজ্ঞাপন প্রদর্শন করা থেকে বাধা দেয়" - }, - "disable_custom_tabs": { - "name": "কাস্টম ট্যাব অক্ষম করুন", - "description": "ওয়েব ব্রাউজারের পরিবর্তে সমর্থিত অ্যাপ্লিকেশনগুলিতে লিঙ্ক খোলে" - }, - "disable_permission_requests": { - "name": "অনুমতি অনুরোধ অক্ষম করুন", - "description": "Snapchat কে নির্দিষ্ট অনুমতি চাইতে বাধা দেয়" - }, - "disable_memories_snap_feed": { - "name": "স্মৃতি স্ন্যাপ ফিড অক্ষম করুন", - "description": "আপনি ক্যামেরায় সোয়াইপ করার সময় Snapchat কে সাম্প্রতিক স্মৃতি দেখানো থেকে বাধা দেয়" - }, - "spotlight_comments_username": { - "name": "স্পটলাইট মন্তব্য ব্যবহারকারীর নাম", - "description": "স্পটলাইট মন্তব্যগুলিতে লেখকের ব্যবহারকারীর নাম দেখায়" - }, - "bypass_video_length_restriction": { - "name": "ভিডিও দৈর্ঘ্য বিধিনিষেধ বাইপাস করুন", - "description": "একক: একটি একক ভিডিও পাঠায়\nবিভক্ত: সম্পাদনা করার পরে ভিডিও বিভক্ত করুন" - }, - "default_video_playback_rate": { - "name": "ডিফল্ট ভিডিও প্লেব্যাক হার", - "description": "ভিডিওগুলির প্লেব্যাকের জন্য ডিফল্ট গতি সেট করে\nমান 0.1 থেকে 4.0 এর মধ্যে হতে হবে" - }, - "video_playback_rate_slider": { - "name": "ভিডিও প্লেব্যাক হার স্লাইডার", - "description": "ভিডিও প্লেব্যাক হার পরিবর্তন করতে অপেরা প্রসঙ্গ মেনুতে একটি স্লাইডার যোগ করে\nদ্রষ্টব্য: পরিবর্তনগুলি শুধুমাত্র পরবর্তী ভিডিওগুলিতে প্রযোজ্য" - }, - "disable_google_play_dialogs": { - "name": "Google Play পরিষেবা ডায়ালগ অক্ষম করুন", - "description": "Google Play পরিষেবা উপলব্ধতা ডায়ালগ দেখানো থেকে প্রতিরোধ করুন" - }, - "default_volume_controls": { - "name": "ডিফল্ট ভলিউম নিয়ন্ত্রণ", - "description": "সিস্টেম ভলিউম নিয়ন্ত্রণ ব্যবহার করতে Snapchat কে বাধ্য করে" - }, - "disable_telecom_framework": { - "name": "টেলিকম ফ্রেমওয়ার্ক অক্ষম করুন", - "description": "Snapchat কে Android টেলিকম ফ্রেমওয়ার্ক ব্যবহার করা থেকে বাধা দেয়\nএটি আপনাকে একটি কলে থাকাকালীন গান শোনার অনুমতি দেয়" - }, - "hide_active_music": { - "name": "সক্রিয় সঙ্গীত লুকান", - "description": "আপনি গান শুনছেন তা Snapchat কে জানতে বাধা দেয়\nএটি আপনাকে গান শোনার সময় নিয়ন্ত্রণ ভলিউম বোতাম ব্যবহার করে স্ন্যাপ নিতে দেবে" - }, - "disable_snap_splitting": { - "name": "স্ন্যাপ বিভাজন অক্ষম করুন", - "description": "স্ন্যাপগুলিকে একাধিক অংশে বিভক্ত হওয়া থেকে বাধা দেয়\nআপনি যে ছবিগুলি পাঠান সেগুলি ভিডিওতে পরিণত হবে" - } - } - }, - "rules": { - "name": "নিয়ম", - "description": "স্বতন্ত্র ব্যক্তিদের জন্য স্বয়ংক্রিয় বৈশিষ্ট্য পরিচালনা করুন" - }, - "camera": { - "name": "ক্যামেরা", - "description": "নিখুঁত স্ন্যাপের জন্য সঠিক সেটিংস সামঞ্জস্য করুন", - "properties": { - "disable_cameras": { - "name": "ক্যামেরা অক্ষম করুন", - "description": "Snapchat কে নির্বাচিত ক্যামেরা ব্যবহার করা থেকে বাধা দেয়" - }, - "black_photos": { - "name": "কালো ছবি", - "description": "তোলা ছবিগুলিকে একটি কালো পটভূমি দিয়ে প্রতিস্থাপন করে\nভিডিওগুলি প্রভাবিত হয় না" - }, - "immersive_camera_preview": { - "name": "ইমারসিভ প্রিভিউ", - "description": "Snapchat কে ক্যামেরা প্রিভিউ ক্রপ করা থেকে বাধা দেয়\nএটি কিছু ডিভাইসে ক্যামেরা ফ্লিকার করতে পারে" - }, - "override_front_resolution": { - "name": "সামনের রেজোলিউশন ওভাররাইড করুন", - "description": "সামনের ক্যামেরার জন্য ক্যামেরা রেজোলিউশন ওভাররাইড করে" - }, - "override_back_resolution": { - "name": "পিছনের রেজোলিউশন ওভাররাইড করুন", - "description": "পিছনের ক্যামেরার জন্য ক্যামেরা রেজোলিউশন ওভাররাইড করে" - }, - "custom_resolution": { - "name": "কাস্টম রেজোলিউশন", - "description": "একটি কাস্টম ক্যামেরা রেজোলিউশন সেট করে, প্রস্থ x উচ্চতা (যেমন 1920x1080)।\nকাস্টম রেজোলিউশন আপনার ডিভাইস দ্বারা সমর্থিত হতে হবে" - }, - "front_custom_frame_rate": { - "name": "সামনের কাস্টম ফ্রেম রেট", - "description": "সামনের ক্যামেরা ফ্রেম রেট ওভাররাইড করে" - }, - "back_custom_frame_rate": { - "name": "পিছনের কাস্টম ফ্রেম রেট", - "description": "পিছনের ক্যামেরা ফ্রেম রেট ওভাররাইড করে" - }, - "force_camera_source_encoding": { - "name": "ক্যামেরা উৎস এনকোডিং জোর করুন", - "description": "ক্যামেরা উৎস এনকোডিং জোর করে" - }, - "startup_default_camera": { - "name": "স্টার্টআপ ডিফল্ট ক্যামেরা", - "description": "Snapchat খোলার সময় ডিফল্ট ক্যামেরা সেট করে" - }, - "hevc_recording": { - "name": "HEVC রেকর্ডিং", - "description": "ভিডিও রেকর্ডিংয়ের জন্য HEVC (H.265) কোডেক ব্যবহার করে" - } - } - }, - "streaks_reminder": { - "name": "ধারাবাহিকতা অনুস্মারক", - "description": "পর্যায়ক্রমে আপনাকে আপনার ধারাবাহিকতা সম্পর্কে অবহিত করে", - "properties": { - "interval": { - "name": "ব্যবধান", - "description": "প্রতিটি অনুস্মারকের মধ্যে ব্যবধান (ঘন্টা)" - }, - "remaining_hours": { - "name": "অবশিষ্ট সময়", - "description": "বিজ্ঞপ্তি দেখানোর আগে অবশিষ্ট সময়ের পরিমাণ (ঘন্টা)" - }, - "group_notifications": { - "name": "গ্রুপ বিজ্ঞপ্তি", - "description": "গ্রুপ বিজ্ঞপ্তিগুলিকে একটি একক বিজ্ঞপ্তিতে গ্রুপ করে" - } - } - }, - "experimental": { - "name": "পরীক্ষামূলক", - "description": "পরীক্ষামূলক বৈশিষ্ট্য", - "properties": { - "native_hooks": { - "name": "নেটিভ হুক", - "description": "অনিরাপদ বৈশিষ্ট্য যা Snapchat-এর নেটিভ কোডে হুক করে", - "properties": { - "composer_hooks": { - "name": "কম্পোজার হুক", - "description": "কম্পোজার ক্রস-প্ল্যাটফর্ম UI ফ্রেমওয়ার্কে কোড ইনজেক্ট করে", - "properties": { - "show_first_created_username": { - "name": "প্রথম তৈরি ব্যবহারকারীর নাম দেখান", - "description": "প্রোফাইল পৃষ্ঠায় বর্তমান ব্যবহারকারীর নামের পাশে প্রথম তৈরি ব্যবহারকারীর নাম দেখায়" - }, - "bypass_camera_roll_limit": { - "name": "ক্যামেরা রোল সীমা বাইপাস করুন", - "description": "আপনি ক্যামেরা রোল থেকে যে পরিমাণ মিডিয়া পাঠাতে পারেন তা বাড়ায়" - }, - "custom_self_destruct_snap_delay": { - "name": "কাস্টম স্ব-ধ্বংস স্ন্যাপ বিলম্ব", - "description": "একটি স্ন্যাপ পাঠানোর সময় স্ব-ধ্বংস টাইমারের জন্য আরও বিকল্প দেয়" - }, - "composer_console": { - "name": "কম্পোজার কনসোল", - "description": "আপনাকে কম্পোজারে JavaScript কোড চালানোর অনুমতি দেয় (শুধুমাত্র arm64)" - }, - "composer_logs": { - "name": "কম্পোজার লগ", - "description": "কম্পোজারের কনসোল লগগুলি PurrfectSnap-এ পুনঃনির্দেশিত করে" - } - } - }, - "disable_bitmoji": { - "name": "বিটমোজি অক্ষম করুন", - "description": "বন্ধুদের প্রোফাইল বিটমোজি অক্ষম করে" - }, - "custom_emoji_font": { - "name": "কাস্টম ইমোজি ফন্ট", - "description": "আপনাকে একটি কাস্টম ইমোজি ফন্ট ব্যবহার করার অনুমতি দেয়। শুধুমাত্র .ttf ফন্টের সাথে কাজ করে" - }, - "custom_shared_library": { - "name": "কাস্টম শেয়ার করা লাইব্রেরি", - "description": "Snapchat-এ একটি কাস্টম শেয়ার করা লাইব্রেরি লোড করে। এই বৈশিষ্ট্যটি শুধুমাত্র পরীক্ষার উদ্দেশ্যে" - } - } - }, - "spoof": { - "name": "স্পুফ", - "description": "আপনার সম্পর্কে বিভিন্ন তথ্য স্পুফ করুন", - "properties": { - "play_store_installer_package_name": { - "name": "প্লে স্টোর ইনস্টলার প্যাকেজের নাম", - "description": "ইনস্টলার প্যাকেজের নাম com.android.vending-এ ওভাররাইড করে" - }, - "remove_vpn_transport_flag": { - "name": "VPN পরিবহন পতাকা সরান", - "description": "Snapchat কে VPN সনাক্ত করা থেকে বাধা দেয়" - }, - "remove_mock_location_flag": { - "name": "মক অবস্থান পতাকা সরান", - "description": "Snapchat কে মক অবস্থান সনাক্ত করা থেকে বাধা দেয়" - } - } - }, - "convert_message_locally": { - "name": "স্থানীয়ভাবে বার্তা রূপান্তর করুন", - "description": "স্থানীয়ভাবে স্ন্যাপগুলিকে চ্যাট বাহ্যিক মিডিয়ায় রূপান্তর করে। এটি চ্যাট ডাউনলোড প্রসঙ্গ মেনুতে উপস্থিত হয়" - }, - "media_file_picker": { - "name": "মিডিয়া ফাইল পিকার", - "description": "আপনাকে গ্যালারী থেকে যেকোনো ভিডিও/অডিও ফাইল বাছাই করার অনুমতি দেয়" - }, - "story_logger": { - "name": "গল্প লগার", - "description": "বন্ধুদের গল্পের একটি ইতিহাস সরবরাহ করে" - }, - "call_recorder": { - "name": "কল রেকর্ডার", - "description": "স্বয়ংক্রিয়ভাবে অডিও কল রেকর্ড করে" - }, - "account_switcher": { - "name": "অ্যাকাউন্ট সুইচার", - "description": "আপনাকে লগ আউট না করে অ্যাকাউন্টগুলির মধ্যে স্যুইচ করার অনুমতি দেয়\nমেনু খুলতে আপনার বিটমোজি প্রোফাইলের পাশের অনুসন্ধান আইকনে দীর্ঘক্ষণ চাপ দিন\nদ্রষ্টব্য: এই বৈশিষ্ট্যটি পরীক্ষামূলক এবং ভবিষ্যতে পরিবর্তন হওয়ার সম্ভাবনা রয়েছে", - "properties": { - "auto_backup_current_account": { - "name": "বর্তমান অ্যাকাউন্টের স্বয়ংক্রিয় ব্যাকআপ", - "description": "লগ আউট বা অ্যাকাউন্ট স্যুইচ করার সময় বর্তমান অ্যাকাউন্টের স্বয়ংক্রিয়ভাবে ব্যাকআপ নেয়" - } - } - }, - "better_transcript": { - "name": "আরও ভাল প্রতিলিপি", - "description": "ভয়েস নোট প্রতিলিপি উন্নত করে", - "properties": { - "force_transcription": { - "name": "ভয়েস নোট প্রতিলিপি জোর করুন", - "description": "সমস্ত ভয়েস নোট প্রতিলিপি করার অনুমতি দেয়" - }, - "preferred_transcription_lang": { - "name": "পছন্দের প্রতিলিপি ভাষা", - "description": "ভয়েস নোট প্রতিলিপির জন্য পছন্দের ভাষা (যেমন EN, ES, FR)" - }, - "notification_transcript": { - "name": "বিজ্ঞপ্তি প্রতিলিপি", - "description": "বিজ্ঞপ্তিতে ভয়েস নোট প্রতিলিপি করে\nএই বৈশিষ্ট্যটির জন্য আরও ভাল বিজ্ঞপ্তিতে চ্যাট প্রিভিউ বৈশিষ্ট্যটি সক্ষম করা প্রয়োজন" - } - } - }, - "voice_note_auto_play": { - "name": "ভয়েস নোট স্বয়ংক্রিয় প্লে", - "description": "বর্তমানটি শেষ হওয়ার পরে পরবর্তী ভয়েস নোটটি স্বয়ংক্রিয়ভাবে প্লে করে" - }, - "friend_notes": { - "name": "বন্ধু নোট", - "description": "আপনাকে বন্ধুদের প্রোফাইলে নোট যোগ করার অনুমতি দেয়" - }, - "cof_experiments": { - "name": "COF পরীক্ষা", - "description": "অপ্রকাশিত/বিটা Snapchat বৈশিষ্ট্য সক্ষম করে" - }, - "context_menu_fix": { - "name": "প্রসঙ্গ মেনু ফিক্স", - "description": "বন্ধু ফিড মেনু মেরামত করার চেষ্টা করুন কারণ ডিভাইস অফলাইন থাকলে এটি সঠিকভাবে প্রদর্শিত হতে পারে না" - }, - "app_lock": { - "name": "অ্যাপ লক", - "description": "একটি পাসকোড ছাড়া Snapchat-এ অ্যাক্সেস প্রতিরোধ করে", - "properties": { - "lock_on_resume": { - "name": "পুনরায় শুরু করার সময় লক করুন", - "description": "অ্যাপটি পুনরায় খোলার সময় লক করে" - } - } - }, - "infinite_story_boost": { - "name": "অসীম গল্প বুস্ট", - "description": "গল্প বুস্ট সীমা বিলম্ব বাইপাস করুন" - }, - "meo_passcode_bypass": { - "name": "আমার চোখ শুধুমাত্র পাসকোড বাইপাস", - "description": "আমার চোখ শুধুমাত্র পাসকোড বাইপাস করুন\nএটি শুধুমাত্র তখনই কাজ করবে যদি পাসকোডটি আগে সঠিকভাবে প্রবেশ করা হয়ে থাকে" - }, - "no_friend_score_delay": { - "name": "কোনো বন্ধু স্কোর বিলম্ব নেই", - "description": "একটি বন্ধুর স্কোর দেখার সময় বিলম্ব সরিয়ে দেয়" - }, - "best_friend_pinning": { - "name": "সেরা বন্ধু পিনিং", - "description": "আপনাকে আপনার এক নম্বর সেরা বন্ধু হিসাবে একটি বন্ধু পিন করার অনুমতি দেয়। দ্রষ্টব্য: শুধুমাত্র আপনি আপনার পিন করা সেরা বন্ধু দেখতে পারেন" - }, - "e2ee": { - "name": "এন্ড-টু-এন্ড এনক্রিপশন", - "description": "একটি শেয়ার করা গোপন কী ব্যবহার করে আপনার বার্তাগুলি AES দিয়ে এনক্রিপ্ট করে\nআপনার কী কোথাও নিরাপদে সংরক্ষণ করতে ভুলবেন না!", - "properties": { - "encrypted_message_indicator": { - "name": "এনক্রিপ্ট করা বার্তা সূচক", - "description": "এনক্রিপ্ট করা বার্তাগুলির পাশে একটি 🔒 ইমোজি যোগ করে" - }, - "force_message_encryption": { - "name": "বার্তা এনক্রিপশন জোর করুন", - "description": "একাধিক কথোপকথন নির্বাচন করা হলেই শুধুমাত্র এন্ড-টু-এন্ড এনক্রিপশন সক্ষম না থাকা লোকেদের কাছে এনক্রিপ্ট করা বার্তা পাঠানো প্রতিরোধ করে" - } - } - }, - "add_friend_source_spoof": { - "name": "বন্ধু যোগ করার উৎস স্পুফ", - "description": "একটি বন্ধু অনুরোধের উৎস স্পুফ করে" - }, - "hidden_snapchat_plus_features": { - "name": "লুকানো Snapchat Plus বৈশিষ্ট্য", - "description": "অপ্রকাশিত/বিটা Snapchat Plus বৈশিষ্ট্য সক্ষম করে\nপুরানো Snapchat সংস্করণে কাজ নাও করতে পারে" - }, - "custom_streaks_expiration_format": { - "name": "কাস্টম ধারাবাহিকতার মেয়াদ শেষ হওয়ার বিন্যাস", - "description": "ধারাবাহিকতার মেয়াদ শেষ হওয়ার বিন্যাস কাস্টমাইজ করে\n\nউপলব্ধ ভেরিয়েবল:\n - %c: ধারাবাহিকতা গণনা\n - %e: বালিঘড়ি ইমোজি\n - %d: দিন\n - %h: ঘন্টা\n - %m: মিনিট\n - %s: সেকেন্ড\n - %w: অবশিষ্ট সময়" - }, - "prevent_forced_logout": { - "name": "বাধ্যতামূলক লগআউট প্রতিরোধ করুন", - "description": "আপনি অন্য ডিভাইসে লগইন করার সময় Snapchat কে আপনাকে লগ আউট করা থেকে বাধা দেয়" - }, - "snapscore_changes": { - "name": "স্ন্যাপস্কোর পরিবর্তন", - "description": "বন্ধুদের স্ন্যাপস্কোরে পরিবর্তন ট্র্যাক করে\nশুধুমাত্র Snapchat-এর নতুন সংস্করণগুলিতে এই বৈশিষ্ট্যটি ব্যবহার করুন" - } - } - }, - "scripting": { - "name": "স্ক্রিপ্টিং", - "description": "PurrfectSnap প্রসারিত করতে কাস্টম স্ক্রিপ্ট চালান", - "properties": { - "developer_mode": { - "name": "ডেভেলপার মোড", - "description": "Snapchat-এর UI-তে ডিবাগ তথ্য দেখায়" - }, - "module_folder": { - "name": "মডিউল ফোল্ডার", - "description": "যে ফোল্ডারে স্ক্রিপ্টগুলি অবস্থিত" - }, - "auto_reload": { - "name": "স্বয়ংক্রিয় পুনরায় লোড", - "description": "পরিবর্তন হলে স্ক্রিপ্টগুলি স্বয়ংক্রিয়ভাবে পুনরায় লোড করে" - }, - "integrated_ui": { - "name": "সমন্বিত UI", - "description": "স্ক্রিপ্টগুলিকে Snapchat-এ কাস্টম UI উপাদান যোগ করার অনুমতি দেয়" - }, - "disable_log_anonymization": { - "name": "লগ বেনামীকরণ অক্ষম করুন", - "description": "লগগুলির বেনামীকরণ অক্ষম করে" - }, - "disable_optimization": { - "name": "অপ্টিমাইজেশন অক্ষম করুন", - "description": "স্ক্রিপ্টগুলির অপ্টিমাইজেশন অক্ষম করে। এটি কর্মক্ষমতা সমস্যা সৃষ্টি করতে পারে।" - } - } - }, - "friend_tracker": { - "name": "বন্ধু ট্র্যাকার", - "description": "Snapchat-এ বন্ধুর কার্যকলাপ রেকর্ড করে", - "properties": { - "record_messaging_events": { - "name": "মেসেজিং ইভেন্ট রেকর্ড করুন", - "description": "মেসেজিং ইভেন্ট যেমন একটি স্ন্যাপ খোলা, একটি বার্তা পড়া ইত্যাদি রেকর্ড করে।" - }, - "allow_running_in_background": { - "name": "পটভূমিতে চলার অনুমতি দিন", - "description": "ট্র্যাকারকে পটভূমিতে চলার অনুমতি দেয়। দ্রষ্টব্য: এটি আপনার ব্যাটারি উল্লেখযোগ্যভাবে নিঃশেষ করবে" - }, - "auto_purge": { - "name": "স্বয়ংক্রিয় পরিস্কার", - "description": "নির্দিষ্ট সময়ের চেয়ে পুরানো ক্যাশে করা ইভেন্টগুলি স্বয়ংক্রিয়ভাবে মুছে ফেলে" - } - } - } - }, - "options": { - "app_appearance": { - "always_light": "সর্বদা হালকা", - "always_dark": "সর্বদা অন্ধকার" - }, - "friend_feed_menu_buttons": { - "auto_download": "⬇️ স্বয়ংক্রিয় ডাউনলোড", - "auto_save": "💬 স্বয়ংক্রিয়ভাবে বার্তা সংরক্ষণ করুন", - "unsaveable_messages": "⬇️ অসংরক্ষণযোগ্য বার্তা", - "auto_open_snaps": "📸 স্বয়ংক্রিয়ভাবে স্ন্যাপ খুলুন", - "stealth": "👻 স্টিলথ মোড", - "mark_snaps_as_seen": "👀 স্ন্যাপগুলিকে দেখা হিসাবে চিহ্নিত করুন", - "mark_stories_as_seen_locally": "👀 গল্পগুলিকে স্থানীয়ভাবে দেখা হিসাবে চিহ্নিত করুন", - "conversation_info": "🧑‍🤝‍🧑 কথোপকথনের তথ্য", - "e2e_encryption": "🔒 E2E এনক্রিপশন ব্যবহার করুন" - }, - "path_format": { - "create_author_folder": "প্রতিটি লেখকের জন্য ফোল্ডার তৈরি করুন", - "create_source_folder": "প্রতিটি মিডিয়া উৎস প্রকারের জন্য ফোল্ডার তৈরি করুন", - "append_hash": "ফাইলের নামে একটি অনন্য হ্যাশ যোগ করুন", - "append_source": "ফাইলের নামে মিডিয়া উৎস যোগ করুন", - "append_username": "ফাইলের নামে ব্যবহারকারীর নাম যোগ করুন", - "append_date_time": "ফাইলের নামে তারিখ এবং সময় যোগ করুন" - }, - "auto_download_sources": { - "friend_snaps": "বন্ধু স্ন্যাপ", - "friend_stories": "বন্ধু গল্প", - "public_stories": "সর্বজনীন গল্প", - "spotlight": "স্পটলাইট" - }, - "logging": { - "started": "শুরু হয়েছে", - "success": "সাফল্য", - "progress": "অগ্রগতি", - "failure": "ব্যর্থতা" - }, - "notifications": { - "chat_screenshot": "স্ক্রিনশট", - "chat_screen_record": "স্ক্রিন রেকর্ড", - "snap_replay": "স্ন্যাপ রিপ্লে", - "camera_roll_save": "ক্যামেরা রোল সংরক্ষণ করুন", - "chat": "চ্যাট", - "chat_reply": "চ্যাট উত্তর", - "snap": "স্ন্যাপ", - "typing": "টাইপ করছে", - "stories": "গল্প", - "speaking": "কথা বলছে", - "chat_reaction": "ডিএম প্রতিক্রিয়া", - "group_chat_reaction": "গ্রুপ প্রতিক্রিয়া", - "initiate_audio": "ইনকামিং অডিও কল", - "abandon_audio": "মিসড অডিও কল", - "initiate_video": "ইনকামিং ভিডিও কল", - "abandon_video": "মিসড ভিডিও কল", - "map_live_location": "মানচিত্র লাইভ অবস্থান" - }, - "gallery_media_send_override": { - "always_ask": "সর্বদা জিজ্ঞাসা করুন", - "ORIGINAL": "আসল মিডিয়া", - "NOTE": "অডিও নোট", - "SNAP": "স্ন্যাপ", - "SAVEABLE_SNAP": "সংরক্ষণযোগ্য স্ন্যাপ" - }, - "strip_media_metadata": { - "hide_caption_text": "ক্যাপশন পাঠ্য লুকান", - "hide_snap_filters": "স্ন্যাপ ফিল্টার লুকান", - "hide_extras": "অতিরিক্ত লুকান (যেমন উল্লেখ)", - "remove_audio_note_duration": "অডিও নোটের সময়কাল সরান", - "remove_audio_note_transcript_capability": "অডিও নোট প্রতিলিপি ক্ষমতা সরান" - }, - "hide_ui_components": { - "hide_profile_call_buttons": "প্রোফাইল কল বোতাম সরান", - "hide_chat_call_buttons": "চ্যাট কল বোতাম সরান", - "hide_live_location_share_button": "লাইভ অবস্থান শেয়ার বোতাম সরান", - "hide_stickers_button": "স্টিকার বোতাম সরান", - "hide_voice_record_button": "ভয়েস রেকর্ড বোতাম সরান", - "hide_unread_chat_hint": "অপঠিত চ্যাট ইঙ্গিত সরান", - "hide_post_to_story_buttons": "একটি স্ন্যাপ পাঠানোর আগে গল্পে পোস্ট বোতাম সরান", - "hide_billboard_prompt": "বন্ধুদের ফিডে বিলবোর্ড প্রম্পট সরান", - "hide_snapchat_plus_gift_reminders": "কথোপকথনে Snapchat Plus উপহার অনুস্মারক সরান", - "hide_map_reactions": "মানচিত্র প্রতিক্রিয়া সরান" - }, - "hide_story_suggestions": { - "hide_suggested_friend_stories": "প্রস্তাবিত বন্ধু গল্প লুকান", - "hide_my_stories": "আমার গল্প লুকান" - }, - "home_tab": { - "map": "মানচিত্র", - "chat": "চ্যাট", - "camera": "ক্যামেরা", - "discover": "আবিষ্কার করুন", - "spotlight": "স্পটলাইট" - }, - "add_friend_source_spoof": { - "added_by_username": "ব্যবহারকারীর নাম দ্বারা", - "added_by_mention": "উল্লেখ দ্বারা", - "added_by_group_chat": "গ্রুপ চ্যাট দ্বারা", - "added_by_qr_code": "QR কোড দ্বারা", - "added_by_community": "সম্প্রদায় দ্বারা", - "added_by_quick_add": "দ্রুত যোগ দ্বারা (নিষিদ্ধ হওয়ার উচ্চ ঝুঁকি)" - }, - "bypass_video_length_restriction": { - "single": "একক মিডিয়া", - "split": "বিভক্ত মিডিয়া" - }, - "old_bitmoji_selfie": { - "2d": "2D বিটমোজি", - "3d": "3D বিটমোজি" - }, - "disable_confirmation_dialogs": { - "erase_message": "বার্তা মুছুন", - "remove_friend": "বন্ধু সরান", - "block_friend": "বন্ধু ব্লক করুন", - "ignore_friend": "বন্ধু উপেক্ষা করুন", - "hide_friend": "বন্ধু লুকান", - "hide_conversation": "কথোপকথন লুকান", - "clear_conversation": "বন্ধু ফিড থেকে কথোপকথন সাফ করুন" - }, - "auto_reload": { - "snapchat_only": "শুধুমাত্র Snapchat", - "all": "সব (Snapchat + PurrfectSnap)" - }, - "edit_text_override": { - "multi_line_chat_input": "একাধিক লাইন চ্যাট ইনপুট", - "bypass_text_input_limit": "পাঠ্য ইনপুট সীমা বাইপাস করুন" - }, - "auto_purge": { - "never": "কখনো না", - "1_hour": "1 ঘন্টা", - "3_hours": "3 ঘন্টা", - "6_hours": "6 ঘন্টা", - "12_hours": "12 ঘন্টা", - "1_day": "1 দিন", - "3_days": "3 দিন", - "1_week": "1 সপ্তাহ", - "2_weeks": "2 সপ্তাহ", - "1_month": "1 মাস", - "3_months": "3 মাস", - "6_months": "6 মাস" - }, - "disable_story_sections": { - "friends": "বন্ধু", - "suggested_stories": "প্রস্তাবিত গল্প", - "following": "অনুসরণ করা হচ্ছে", - "discover": "আবিষ্কার করুন" - }, - "disable_cameras": { - "front": "সামনের ক্যামেরা", - "back": "পিছনের ক্যামেরা" - }, - "disable_permission_requests": { - "notifications": "বিজ্ঞপ্তি", - "read_media_images": "মিডিয়া ছবি পড়ুন", - "read_media_video": "মিডিয়া ভিডিও পড়ুন", - "camera": "ক্যামেরা", - "microphone": "মাইক্রোফোন", - "location": "অবস্থান", - "read_contacts": "পরিচিতি পড়ুন", - "nearby_devices": "কাছাকাছি ডিভাইস", - "phone_calls": "ফোন কল" - }, - "message_indicators": { - "encryption_indicator": "শুধুমাত্র আপনাকে পাঠানো বার্তাগুলির পাশে একটি 🔒 আইকন যোগ করে", - "platform_indicator": "যে প্ল্যাটফর্ম থেকে একটি মিডিয়া পাঠানো হয়েছিল তার প্ল্যাটফর্ম আইকন যোগ করে (যেমন অ্যান্ড্রয়েড, আইওএস, ওয়েব)", - "location_indicator": "অবস্থান সক্ষম করে পাঠানো হলে স্ন্যাপগুলিতে একটি 📍 আইকন যোগ করে", - "ovf_editor_indicator": "OVF সম্পাদক ব্যবহার করে একটি স্ন্যাপ পাঠানো হয়েছে কিনা তা নির্দেশ করে", - "director_mode_indicator": "পরিচালক মোড ব্যবহার করে পাঠানো হলে স্ন্যাপগুলিতে একটি 🎬 আইকন যোগ করে, যা গ্যালারী ছবিগুলিকে স্ন্যাপ হিসাবে পাঠাতে ব্যবহার করা যেতে পারে" - }, - "auto_mark_as_read": { - "conversation_read": "একটি বার্তা পাঠানোর সময় কথোপকথনকে পঠিত হিসাবে চিহ্নিত করুন", - "snap_reply": "স্ন্যাপগুলিতে উত্তর দেওয়ার সময় সেগুলিকে পঠিত হিসাবে চিহ্নিত করুন", - "save_snap_in_chat": "স্টিলথ মোডে থাকাকালীন চ্যাটে স্ন্যাপগুলি সংরক্ষণ করার সময় সেগুলিকে পঠিত হিসাবে চিহ্নিত করুন" - }, - "friend_mutation_notifier": { - "remove_friend": "কেউ আপনাকে বন্ধু হিসাবে সরিয়ে দিলে অবহিত করুন", - "birthday_changes": "কেউ তাদের জন্মদিন পরিবর্তন করলে অবহিত করুন", - "bitmoji_selfie_changes": "কেউ তাদের বিটমোজি সেলফি পরিবর্তন করলে অবহিত করুন", - "bitmoji_avatar_changes": "কেউ তাদের বিটমোজি অবতার পরিবর্তন করলে অবহিত করুন", - "bitmoji_background_changes": "কেউ তাদের বিটমোজি পটভূমি পরিবর্তন করলে অবহিত করুন", - "bitmoji_scene_changes": "কেউ তাদের বিটমোজি দৃশ্য পরিবর্তন করলে অবহিত করুন" - }, - "snapchat_plus": { - "not_subscribed": "সাবস্ক্রাইব করা হয়নি", - "basic": "বেসিক", - "ad_free": "বিজ্ঞাপন মুক্ত" - }, - "double_tap_chat_action": { - "like_message": "বার্তা পছন্দ করুন", - "copy_text": "ক্লিপবোর্ডে পাঠ্য অনুলিপি করুন", - "delete_message": "বার্তা মুছুন", - "mark_as_read": "পঠিত হিসাবে চিহ্নিত করুন", - "custom_emoji_reaction": "কাস্টম ইমোজি প্রতিক্রিয়া" - }, - "startup_default_camera": { - "front": "সামনের ক্যামেরা", - "back": "পিছনের ক্যামেরা" - } - } - }, - "friend_menu_option": { - "mark_snaps_as_seen": "স্ন্যাপগুলিকে দেখা হিসাবে চিহ্নিত করুন", - "mark_stories_as_seen_locally": "গল্পগুলিকে স্থানীয়ভাবে দেখা হিসাবে চিহ্নিত করুন", - "preview": "প্রিভিউ", - "stealth_mode": "স্টিলথ মোড", - "auto_download_blacklist": "স্বয়ংক্রিয় ডাউনলোড ব্ল্যাকলিস্ট", - "anti_auto_save": "অ্যান্টি অটো সেভ" - }, - "content_type": { - "CHAT": "চ্যাট", - "SNAP": "স্ন্যাপ", - "EXTERNAL_MEDIA": "বাহ্যিক মিডিয়া", - "NOTE": "অডিও নোট", - "STICKER": "স্টিকার", - "SHARE": "শেয়ার করুন", - "STATUS": "স্থিতি", - "LOCATION": "অবস্থান", - "STATUS_SAVE_TO_CAMERA_ROLL": "ক্যামেরা রোলে সংরক্ষিত", - "STATUS_CONVERSATION_CAPTURE_SCREENSHOT": "স্ক্রিনশট", - "STATUS_CONVERSATION_CAPTURE_RECORD": "স্ক্রিন রেকর্ড", - "STATUS_CALL_MISSED_VIDEO": "মিসড ভিডিও কল", - "STATUS_CALL_MISSED_AUDIO": "মিসড অডিও কল", - "LIVE_LOCATION_SHARE": "লাইভ অবস্থান শেয়ার করুন", - "CREATIVE_TOOL_ITEM": "সৃজনশীল সরঞ্জাম আইটেম", - "FAMILY_CENTER_INVITE": "পরিবার কেন্দ্র আমন্ত্রণ", - "FAMILY_CENTER_ACCEPT": "পরিবার কেন্দ্র গ্রহণ করুন", - "FAMILY_CENTER_LEAVE": "পরিবার কেন্দ্র ত্যাগ করুন", - "STATUS_PLUS_GIFT": "স্থিতি প্লাস উপহার", - "TINY_SNAP": "ছোট স্ন্যাপ", - "STATUS_COUNTDOWN": "গণনা", - "MAP_REACTION": "মানচিত্র প্রতিক্রিয়া" - }, - "media_download_source": { - "none": "কিছুই না", - "pending": "মুলতুবি", - "chat_media": "চ্যাট মিডিয়া", - "story": "গল্প", - "public_story": "সর্বজনীন গল্প", - "spotlight": "স্পটলাইট", - "profile_picture": "প্রোফাইল ছবি", - "story_logger": "গল্প লগার", - "message_logger": "বার্তা লগার", - "merged": "একত্রিত", - "voice_call": "ভয়েস কল" - }, - "chat_action_menu": { - "preview_button": "প্রিভিউ", - "download_button": "ডাউনলোড করুন", - "delete_logged_message_button": "লগ করা বার্তা মুছুন", - "show_chat_edit_history": "চ্যাট সম্পাদনা ইতিহাস দেখান", - "convert_message": "বার্তা রূপান্তর করুন" - }, - "opera_context_menu": { - "download": "মিডিয়া ডাউনলোড করুন", - "sent_at": "{date} এ পাঠানো হয়েছে", - "created_at": "{date} এ তৈরি করা হয়েছে", - "expires_at": "{date} এ মেয়াদ শেষ হবে", - "media_size": "মিডিয়া আকার: {size}", - "media_duration": "মিডিয়া সময়কাল: {duration} ms", - "show_debug_info": "ডিবাগ তথ্য দেখান" - }, - "modal_option": { - "profile_info": "প্রোফাইল তথ্য", - "close": "বন্ধ করুন" - }, - "gallery_media_send_override": { - "multiple_media_toast": "আপনি একবারে শুধুমাত্র একটি মিডিয়া পাঠাতে পারেন" - }, - "mark_as_seen": { - "no_unseen_snaps_toast": "কোনো অদেখা স্ন্যাপ পাওয়া যায়নি!", - "seen_toast": "দেখা হিসাবে চিহ্নিত!", - "unseen_toast": "অদেখা হিসাবে চিহ্নিত!", - "already_seen_toast": "ইতিমধ্যে দেখা হিসাবে চিহ্নিত!", - "already_unseen_toast": "ইতিমধ্যে অদেখা হিসাবে চিহ্নিত!" - }, "conversation_preview": { + "unknown_user": "অজানা ব্যবহাকারী", "streak_expiration": "{day} দিন {hour} ঘন্টা {minute} মিনিটে মেয়াদ শেষ হবে", - "total_messages": "মোট পাঠানো/প্রাপ্ত বার্তা: {count}", - "title": "প্রিভিউ", - "unknown_user": "অজানা ব্যবহারকারী", - "no_messages": "কোনো বার্তা পাওয়া যায়নি!" + "title": "পূর্বরূপ", + "total_messages": "মোট পাঠানো/প্রাপ্ত বার্তা: {count}" }, "profile_info": { "title": "প্রোফাইল তথ্য", - "first_created_username": "প্রথম তৈরি ব্যবহারকারীর নাম", - "mutable_username": "পরিবর্তনযোগ্য ব্যবহারকারীর নাম", "display_name": "প্রদর্শন নাম", - "added_date": "যোগ করার তারিখ", - "birthday": "জন্মদিন : {day} {month}", + "added_date": "যুক্ত হওয়ার তারিখ", + "birthday": "জন্মদিন : {month}{day}", "hidden_birthday": "জন্মদিন : লুকানো", - "friendship": "বন্ধুত্ব", "add_source": "উৎস যোগ করুন", "snapchat_plus": "স্ন্যাপচ্যাট প্লাস", "snapchat_plus_state": { - "subscribed": "সাবস্ক্রাইব করা হয়েছে", + "subscribed": "সদস্যতা", "not_subscribed": "সাবস্ক্রাইব করা হয়নি" - } - }, - "friendship_link_type": { - "mutual": "পারস্পরিক", - "outgoing": "বহির্গামী", - "blocked": "ব্লক করা হয়েছে", - "deleted": "মুছে ফেলা হয়েছে", - "following": "অনুসরণ করা হচ্ছে", - "suggested": "প্রস্তাবিত", - "incoming": "ইনকামিং", - "incoming_follower": "ইনকামিং অনুসারী" - }, - "bulk_messaging_action": { - "choose_action_title": "একটি ক্রিয়া চয়ন করুন", - "progress_status": "{total} এর মধ্যে {index} প্রক্রিয়াজাত করা হচ্ছে", - "selection_dialog_continue_button": "চালিয়ে যান", - "confirmation_dialog": { - "title": "আপনি কি নিশ্চিত?", - "message": "এটি সমস্ত নির্বাচিত বন্ধুদের প্রভাবিত করবে। এই ক্রিয়াটি পূর্বাবস্থায় ফেরানো যাবে না।" }, - "actions": { - "remove_friends": "বন্ধু সরান", - "clear_conversations": "কথোপকথন সাফ করুন" - } + "friendship": "বন্ধুত্ব", + "mutable_username": "পরিবর্তনযোগ্য ব্যবহারকারী নাম", + "first_created_username": "প্রথম তৈরি ইউজারনেম" }, "chat_export": { - "exporter_dialog": { - "select_conversations_title": "কথোপকথন নির্বাচন করুন", - "text_field_selection": "{amount} টি নির্বাচিত", - "text_field_selection_all": "সব", - "export_file_format_title": "ফাইল বিন্যাস রপ্তানি করুন", - "message_type_filter_title": "প্রকার অনুসারে বার্তা ফিল্টার করুন", - "amount_of_messages_title": "বার্তার পরিমাণ (সবার জন্য খালি রাখুন)", - "download_medias_title": "মিডিয়া ডাউনলোড করুন" - }, "dialog_negative_button": "বাতিল করুন", "dialog_positive_button": "রপ্তানি করুন", - "exported_to": "{path} এ রপ্তানি করা হয়েছে", + "exported_to": "রপ্তানি করা হয়েছে {path}", "exporting_chats": "চ্যাট রপ্তানি করা হচ্ছে...", - "processing_chats": "{amount} টি কথোপকথন প্রক্রিয়াজাত করা হচ্ছে...", - "export_fail": "কথোপকথন {conversation} রপ্তানি করতে ব্যর্থ হয়েছে", - "writing_output": "আউটপুট লেখা হচ্ছে...", - "finished": "সম্পন্ন! আপনি এখন এই ডায়ালগটি বন্ধ করতে পারেন।", - "no_messages_found": "কোনো বার্তা পাওয়া যায়নি!", - "exporting_message": "{conversation} রপ্তানি করা হচ্ছে..." + "processing_chats": "{amount} গুলো আলাপ প্রসেসিং করা হচ্ছে...", + "export_fail": "{conversation} আলাপ রপ্তানি করতে সক্ষম হয়নি", + "writing_output": "আউটপুট লিখা হচ্ছে...", + "finished": "সম্পন্ন! আপনি এখন ডায়ালগটি বন্ধ করে দিতে পারেন।.", + "no_messages_found": "কোন বার্তা পাওয়া যায়নি!", + "exporting_message": "{conversation} রপ্তানি করা হচ্ছে...", + "exporter_dialog": { + "select_conversations_title": "কথোপকথন নির্বাচন করুন", + "text_field_selection_all": "সকল", + "export_file_format_title": "ফাইল বিন্যাস রপ্তানি করুন", + "message_type_filter_title": "বার্তাগুলি ধরন অনুযায়ী ফিল্টার করুন", + "amount_of_messages_title": "বার্তার পরিমাণ (সবের জন্য খালি রাখুন)", + "download_medias_title": "মিডিয়াগুলি ডাউনলোড করুন", + "text_field_selection": "{amount} নির্বাচিত" + } }, "button": { "ok": "ঠিক আছে", @@ -1861,162 +48,1416 @@ "negative": "না", "cancel": "বাতিল করুন", "open": "খুলুন", - "download": "ডাউনলোড করুন", - "send": "পাঠান", - "restore_original": "আসল পুনরুদ্ধার করুন", - "convert_external_media": "বাহ্যিক মিডিয়া রূপান্তর করুন", - "save": "সংরক্ষণ করুন" + "download": "ডাউনলোড" }, - "tracker_events": { - "conversation_enter": "কথোপকথনে প্রবেশ করুন", - "conversation_exit": "কথোপকথন থেকে প্রস্থান করুন", - "started_typing": "টাইপ করা শুরু করেছে", - "stopped_typing": "টাইপ করা বন্ধ করেছে", - "started_speaking": "কথা বলা শুরু করেছে", - "stopped_speaking": "কথা বলা বন্ধ করেছে", - "started_peeking": "উঁকি দেওয়া শুরু করেছে", - "stopped_peeking": "উঁকি দেওয়া বন্ধ করেছে", - "message_read": "বার্তা পঠিত", - "message_deleted": "বার্তা মুছে ফেলা হয়েছে", - "message_saved": "বার্তা সংরক্ষিত", - "message_unsaved": "বার্তা অসংরক্ষিত", - "message_edited": "বার্তা সম্পাদিত", - "message_reaction_add": "বার্তা প্রতিক্রিয়া যোগ করুন", - "message_reaction_remove": "বার্তা প্রতিক্রিয়া সরান", - "snap_opened": "স্ন্যাপ খোলা হয়েছে", - "snap_replayed": "স্ন্যাপ পুনরায় প্লে করা হয়েছে", - "snap_replayed_twice": "স্ন্যাপ দুবার পুনরায় প্লে করা হয়েছে", - "snap_screenshot": "স্ন্যাপ স্ক্রিনশট", - "snap_screen_record": "স্ন্যাপ স্ক্রিন রেকর্ড" + "download_processor": { + "download_started_toast": "ডাউনলোড শুরু হয়েছে", + "unsupported_content_type_toast": "অসমর্থিত কনটেন্ট ধরণ!", + "failed_no_longer_available_toast": "মিডিয়া আর পাওয়া যাচ্ছে না", + "already_queued_toast": "মিডিয়া ইতিমধ্যে কিউতে আছে!", + "already_downloaded_toast": "মিডিয়া ইতোমধ্যে ডাউনলোড হয়েছে!", + "download_toast": "ডাউনলোড হচ্ছে {path}...", + "processing_toast": "প্রসেসিং হচ্ছে {path}...", + "failed_generic_toast": "ডাউনলোড করতে সক্ষম হয়নি", + "failed_to_create_preview_toast": "পুর্বরূপ তৈরি করতে সক্ষম হয়নি", + "select_attachments_title": "সংযুক্তি নির্বাচন করুন", + "attachment_type": { + "original_story": "মূল কাহিনী", + "snap": "স্ন্যাপ", + "sticker": "স্টিকার", + "external_media": "বহিঃপ্রচার মাধ্যম", + "note": "নোট", + "gif": "GIF" + }, + "dash_dialog": { + "segment_text": "সেগমেন্ট {from} - {to}", + "title": "ড্যাশ মিডিয়া ডাউনলোড করুন", + "download_all": "সব ডাউনলোড করুন5" + }, + "failed_processing_toast": "প্রক্রিয়াকরণ ব্যর্থ হয়েছে {error}", + "failed_gallery_toast": "গ্যালারিতে সংরক্ষণ ব্যর্থ হয়েছে {error}", + "no_attachments_toast": "কোনও সংযুক্তি খুঁজে পাওয়া যায়নি !", + "dash_no_chapter": "কোন অধ্যায় খুঁজে পাওয়া যায়নি" }, - "tracker_actions": { - "log": "লগ", - "in_app_notification": "ইন-অ্যাপ বিজ্ঞপ্তি", - "push_notification": "পুশ বিজ্ঞপ্তি", - "custom": "কাস্টম" + "setup": { + "mappings": { + "dialog": "ম্যাপিংগুলি তৈরি করতে এটি কিছুটা সময় নিতে পারে ..।", + "generate_failure": "ম্যাপিং তৈরি করার চেষ্টা করতে গিয়ে একটি ত্রুটি ঘটেছে, অনুগ্রহ করে আবার চেষ্টা করুন।", + "generate_failure_no_snapchat": "স্ন্যাপএনহান্স স্ন্যাপচ্যাট সনাক্ত করতে অক্ষম ছিল, অনুগ্রহ করে স্ন্যাপচ্যাট পুনরায় ইনস্টল করার চেষ্টা করুন।" + }, + "dialogs": { + "select_language": "নির্বাচন ভাষা", + "save_folder": "স্ন্যাপএনহান্স-এর স্ন্যাপচ্যাট থেকে মিডিয়া ডাউনলোড এবং সংরক্ষণ করার জন্য স্টোরেজ অনুমতি প্রয়োজন।\nঅনুগ্রহ করে নির্বাচন করুন যে মিডিয়া কোথায় ডাউনলোড করা উচিত।", + "select_save_folder_button": "ফোল্ডার নির্বাচন করুন" + }, + "permissions": { + "dialog": "চালিয়ে যেতে আপনাকে নিম্নলিখিত শর্তগুলি মেনে চলতে হবে:", + "notification_access": "বিজ্ঞপ্তি অ্যাক্সেস", + "battery_optimization": "ব্যাটারি অপটিমাইজেশন", + "display_over_other_apps": "অন্যান্য অ্যাপের উপরে প্রদর্শন করুন", + "request_button": "অনুরোধ" + } }, - "better_notifications": { - "button": { - "reply": "উত্তর দিন", - "download": "ডাউনলোড করুন", - "mark_as_read": "পঠিত হিসাবে চিহ্নিত করুন" + "manager": { + "routes": { + "tasks": "কার্যসমূহ", + "home": "হোম", + "home_settings": "সেটিংস", + "scripts": "স্ক্রিপ্টস্", + "features": "বৈশিষ্ট্য", + "home_logs": "লগ", + "social": "সামাজিক", + "logged_stories": "লগ করা গল্প", + "manage_scope": "সুযোগ পরিচালনা করুন", + "messaging_preview": "পূর্বরূপ", + "logger_history": "লগার ইতিহাস", + "friend_tracker": "বন্ধু ট্র্যাকার", + "edit_rule": "সম্পাদনার নিয়ম", + "file_imports": "ফাইল আমদানি" + }, + "sections": { + "features": { + "disabled": "অক্ষম", + "export_option": "রপ্তানি", + "import_option": "আমদানি", + "reset_option": "রিসেট", + "config_export_success_toast": "কনফিগার সফলভাবে রপ্তানি করা হয়েছে", + "config_import_success_toast": "কনফিগ সফলভাবে আমদানি করা হয়েছে", + "saved_config_snackbar": "কনফিগার সংরক্ষণ করা হয়েছে", + "config_import_failure_toast": "কনফিগ আমদানি করতে ব্যর্থ হয়েছে {error}", + "config_export_failure_toast": "কনফিগ রপ্তানি করতে ব্যর্থ {error}" + }, + "social": { + "streaks_expiration_short": "{hours}h", + "friends_tab": "বন্ধুরা", + "groups_tab": "গোষ্ঠীগুলি", + "empty_hint": "(খালি)" + }, + "tasks": { + "no_tasks": "কোন কাজ নেই", + "delete_files_option": "ফাইলগুলিও মুছে ফেলুন", + "remove_selected_tasks_confirm": "{count} কাজ সরান?", + "remove_selected_tasks_title": "নিশ্চিত আপনি নির্বাচিত কাজগুলি সরাতে চান?", + "remove_all_tasks_title": "নিশ্চিত আপনি সব কাজ অপসারণ করতে চান?", + "remove_all_tasks_confirm": "সমস্ত কাজ মুছে ফেলুন?", + "merge_files_toast": "{count} ফাইল মিশ্রণ" + }, + "home_settings": { + "export_button": "রপ্তানি", + "message_logger_summary": "{messageCount} বার্তা\n{storyCount} গল্পগুলি", + "actions_title": "অ্যাকশন", + "message_logger_title": "বার্তা লগার", + "debug_title": "ডিবাগ", + "success_toast": "হয়ে গেছে!", + "clear_button": "পরিষ্কার", + "view_logger_history_button": "লগার ইতিহাস দেখুন" + }, + "manage_scope": { + "e2ee_title": "এন্ড-টু-এন্ড এনক্রিপশন", + "logged_stories_button": "লগ করা গল্পগুলি দেখান", + "rules_title": "বিধিগুলি", + "not_found": "পাওয়া যায়নি", + "streaks_title": "রেখাগুলি", + "participants_text": "{count} অংশগ্রহণকারী", + "streaks_length_text": "দৈর্ঘ্য: {length}", + "streaks_expiration_text": "{eta}-এ মেয়াদ শেষ হবে", + "streaks_expiration_text_expired": "মেয়াদোত্তীর্ণ", + "reminder_button": "অনুস্মারক সেট করুন", + "delete_scope_confirm_dialog_title": "নিশ্চিত আপনি একটি {scope} মুছতে চান?" + }, + "home": { + "update_content": "সংস্করণ {version} উপলব্ধ!", + "update_title": "স্ন্যাপএনহ্যান্স আপডেট", + "update_button": "ডাউনলোড" + }, + "home_logs": { + "no_logs_hint": "কোনও লগ উপলব্ধ নেই", + "clear_logs_button": "লগ পরিষ্কার করুন", + "export_logs_button": "রপ্তানি লগ", + "saving_logs_toast": "লগগুলি সংরক্ষণ করা এটি কিছু সময় নিতে পারে ..।", + "saved_logs_success_toast": "লগগুলি সফলভাবে সংরক্ষণ করা হয়েছে", + "saved_logs_failure_toast": "লগ সংরক্ষণ করতে ব্যর্থ" + }, + "logged_stories": { + "story_failed_to_load": "লোড করতে ব্যর্থ হয়েছে", + "no_stories": "কোনো গল্প খুঁজে পাওয়া যায়নি", + "save_from_cache_button": "ক্যাশ থেকে সংরক্ষণ করুন" + }, + "messaging_preview": { + "bridge_init_failed": "মেসেজিং ব্রিজ চালু করা যাচ্ছে না। নিশ্চিত করুন যে স্ন্যাপচ্যাট পটভূমিতে চলছে", + "message_fetch_failed": "বার্তা আনতে ব্যর্থ হয়েছে", + "save_selection_option": "সেভ সিলেকশন", + "unsave_selection_option": "আনসেভ সিলেকশন", + "unsave_all_option": "সব আনসেভ করুন", + "mark_selection_as_seen_option": "নির্বাচিত স্ন্যাপটি দেখা হিসেবে চিহ্নিত করুন", + "delete_selection_option": "ডিলিট সিলেকশন", + "delete_all_option": "সব মুছে ফেলুন", + "bridge_connection_failed": "ব্রিজে সংযোগ করতে ব্যর্থ হয়েছে। নিশ্চিত করুন যে স্ন্যাপচ্যাট ব্যাকগ্রাউন্ডে চলছে", + "no_message_hint": "কোন বার্তা নেই", + "save_all_option": "সব সংরক্ষণ করুন", + "mark_all_as_seen_option": "সমস্ত স্ন্যাপস যেমন দেখা যায় চিহ্নিত করুন" + }, + "logger_history": { + "list_friend_format": "বন্ধু {name}", + "list_group_format": "গ্রুপ {name}", + "no_more_messages": "আর কোনো বার্তা নেই", + "reverse_order_checkbox": "বিপরীত ক্রম", + "chat_attachment": "সংযুক্তি {index}", + "empty_message": "খালি চ্যাট বার্তা", + "unknown_sender": "অজানা প্রেরক", + "download_attachment_failed_toast": "সংযুক্তি ডাউনলোড করতে ব্যর্থ", + "message_parse_failed": "বার্তা পার্স করতে ব্যর্থ" + }, + "file_imports": { + "file_imported": "ফাইল সফলভাবে আমদানি করা হয়েছে", + "no_files_hint": "এখানে আপনি স্ন্যাপচ্যাটে ব্যবহারের জন্য ফাইল আমদানি করতে পারেন। ফাইল আমদানি করতে নীচের বোতামটি চাপুন।", + "import_file_button": "ফাইল আমদানি করুন", + "file_not_found": "ফাইল পাওয়া যায়নি", + "file_import_failed": "ফাইল আমদানি ব্যর্থ হয়েছে: {error}", + "file_delete_failed": "ফাইল মুছে ফেলতে ব্যর্থ হয়েছে" + } + }, + "dialogs": { + "add_friend": { + "title": "বন্ধু বা গ্রুপ যোগ করুন", + "category_groups": "গোষ্ঠীগুলি", + "search_hint": "সন্ধান", + "fetch_error": "তথ্য আনতে ব্যর্থ হয়েছে", + "category_friends": "বন্ধুরা" + }, + "scripting_warning": { + "title": "সতর্কতা", + "content": "স্ন্যাপএনহান্স একটি স্ক্রিপ্টিং টুল অন্তর্ভুক্ত করে, যা আপনার ডিভাইসে ব্যবহারকারী-নির্ধারিত কোডের নির্বাহ সম্ভব করে। অত্যন্ত সাবধানতা অবলম্বন করুন এবং কেবল পরিচিত, নির্ভরযোগ্য উৎস থেকে মডিউল ইনস্টল করুন। অননুমোদিত বা যাচাই না করা মডিউলগুলি আপনার সিস্টেমের জন্য নিরাপত্তা ঝুঁকি তৈরি করতে পারে।" + }, + "reset_config": { + "content": "আপনি কি নিশ্চিত যে আপনি কনফিগ রিসেট করতে চান?", + "success_toast": "কনফিগ সফলভাবে রিসেট হয়েছে", + "title": "কনফিগ রিসেট করুন" + }, + "messaging_action": { + "title": "প্রক্রিয়া করতে সামগ্রীর ধরণগুলি চয়ন করুন", + "select_all_button": "সব নির্বাচন করুন" + }, + "file_imports": { + "no_files_settings_hint": "কোনো ফাইল পাওয়া যায়নি। নিশ্চিত করুন যে আপনি ফাইল আমদানি বিভাগে প্রয়োজনীয় ফাইলগুলি আমদানি করেছেন", + "settings_select_file_hint": "আমদানি করা একটি ফাইল নির্বাচন করুন" + }, + "export_config": { + "title": "সংবেদনশীল তথ্য রপ্তানি করুন?", + "content": "আপনি কি সংবেদনশীল ডেটা সহ কনফিগারেশন রপ্তানি করতে চান? (যেমন অবস্থানের স্থানাঙ্ক, ইত্যাদি)" + } + } + }, + "scopes": { + "friend": "বন্ধু", + "group": "গোষ্ঠী" + }, + "streaks_reminder": { + "notification_title": "রেখা", + "notification_text": "আপনি {friend} এর সাথে আপনার রেখা {hoursLeft} ঘন্টার মধ্যে হারাবেন" + }, + "rules": { + "properties": { + "stealth": { + "name": "স্টিলথ মোড", + "options": { + "whitelist": "স্টেলথ মোড", + "blacklist": "স্টিলথ মোড থেকে বাদ দিন" + }, + "description": "কারও জানার থেকে বিরত রাখে যে আপনি তাদের স্ন্যাপ/চ্যাট এবং কথোপকথন খুলেছেন" + }, + "auto_save": { + "options": { + "blacklist": "অটো সেভ থেকে বাদ দিন", + "whitelist": "স্বয়ংক্রিয় সংরক্ষণ" + }, + "name": "অটো সেভ", + "description": "চ্যাট মেসেজ দেখার সময় সেভ করে" + }, + "pin_conversation": { + "name": "কনভারসেশন পিন করুন" + }, + "auto_download": { + "options": { + "blacklist": "স্বতঃ ডাউনলোড থেকে বহির্ভূত করুন", + "whitelist": "স্বয়ংক্রিয় ডাউনলোড" + }, + "name": "স্বতঃ ডাউনলোড", + "description": "দেখার সময় স্ন্যাপগুলি স্বয়ংক্রিয়ভাবে ডাউনলোড করুন" + }, + "unsaveable_messages": { + "description": "অন্যান্য লোকের দ্বারা চ্যাটে মেসেজ সংরক্ষণ প্রতিরোধ করে", + "options": { + "blacklist": "অসংরক্ষণযোগ্য মেসেজ থেকে বাদ দিন", + "whitelist": "অসংরক্ষণযোগ্য মেসেজ" + }, + "name": "অসংরক্ষণযোগ্য মেসেজ" + }, + "hide_friend_feed": { + "name": "ফ্রেন্ড ফিড থেকে লুকান" + }, + "e2e_encryption": { + "name": "E2E এনক্রিপশন ব্যবহার করুন" + }, + "auto_open_snaps": { + "options": { + "blacklist": "অটো ওপেন স্ন্যাপস থেকে বাদ দিন", + "whitelist": "অটো ওপেন স্ন্যাপস" + }, + "name": "অটো ওপেন স্ন্যাপস", + "description": "স্ন্যাপস পাওয়ার সময় স্বয়ংক্রিয়ভাবে খোলে" + } + }, + "modes": { + "whitelist": "হোয়াইটলিস্ট মোড", + "blacklist": "ব্ল্যাকলিস্ট মোড" + }, + "toasts": { + "enabled": "{ruleName} সক্ষম", + "disabled": "{ruleName} অক্ষম" + } + }, + "actions": { + "clean_snapchat_cache": { + "description": "স্ন্যাপচ্যাট ক্যাশে পরিষ্কার করে", + "name": "স্ন্যাপচ্যাট ক্যাশে পরিষ্কার করুন" + }, + "manage_friend_list": { + "name": "বন্ধু তালিকা পরিচালনা করুন", + "description": "ব্যাক আপ করার সময় বন্ধু তালিকা আমদানি/রপ্তানি করুন" + }, + "regen_mappings": { + "name": "ম্যাপিং পুনরুত্পাদন করুন", + "description": "ম্যানুয়ালি ম্যাপিং পুনরুত্পাদন করুন" + }, + "bulk_messaging_action": { + "description": "বন্ধু মুছে ফেলা বা কথোপকথনের গণ মুছে ফেলার মতো অপারেশন সম্পাদন করে", + "name": "বাল্ক মেসেজিং অ্যাকশন" + }, + "export_chat_messages": { + "name": "চ্যাট মেসেজ রপ্তানি করুন", + "description": "কথোপকথনের মেসেজগুলি একটি JSON/HTML/TXT ফাইলে রপ্তানি করে" + }, + "export_memories": { + "name": "স্মৃতি রপ্তানি করুন", + "description": "স্মৃতিগুলি একটি ZIP ফাইলে রপ্তানি করে" + }, + "change_language": { + "name": "ভাষা পরিবর্তন করুন", + "description": "স্ন্যাপএনহ্যান্সের ভাষা পরিবর্তন করুন" + } + }, + "features": { + "properties": { + "downloader": { + "description": "স্ন্যাপচ্যাট মিডিয়া ডাউনলোড করুন", + "properties": { + "path_format": { + "name": "পাথ ফরম্যাট", + "description": "ফাইল পাথ ফরম্যাট নির্দিষ্ট করুন" + }, + "auto_download_sources": { + "description": "সেই সোর্সগুলি নির্বাচন করুন যেখান থেকে স্বয়ংক্রিয়ভাবে ডাউনলোড হবে", + "name": "অটো ডাউনলোড সোর্স" + }, + "prevent_self_auto_download": { + "name": "নিজের স্ন্যাপস স্বয়ংক্রিয়ভাবে ডাউনলোড হওয়া থেকে বিরত রাখুন", + "description": "নিজের স্ন্যাপসগুলি স্বয়ংক্রিয়ভাবে ডাউনলোড হওয়া থেকে বিরত রাখে" + }, + "force_image_format": { + "name": "ছবির ফরম্যাট জোর করে নির্ধারণ করুন", + "description": "ছবিগুলিকে নির্দিষ্ট ফরম্যাটে সংরক্ষণ করতে বাধ্য করে" + }, + "force_voice_note_format": { + "description": "ভয়েস নোটগুলিকে নির্দিষ্ট ফরম্যাটে সংরক্ষণ করতে বাধ্য করে", + "name": "ভয়েস নোটের ফরম্যাট জোর করে নির্ধারণ করুন" + }, + "opera_download_button": { + "description": "একটি স্ন্যাপ দেখার সময় উপরের ডান কোণে একটি ডাউনলোড বোতাম যোগ করে।\nবোতামে দীর্ঘ চাপ ডাউনলোড জোর করে করবে", + "name": "অপেরা ডাউনলোড বোতাম" + }, + "ffmpeg_options": { + "description": "অতিরিক্ত FFmpeg অপশনস নির্দিষ্ট করুন", + "properties": { + "custom_video_codec": { + "name": "কাস্টম ভিডিও কোডেক", + "description": "একটি কাস্টম ভিডিও কোডেক নির্ধারণ করুন (যেমন libx264)" + }, + "video_bitrate": { + "description": "ভিডিও বিটরেট নির্ধারণ করুন (kbps)", + "name": "ভিডিও বিটরেট" + }, + "audio_bitrate": { + "name": "অডিও বিটরেট", + "description": "অডিও বিটরেট নির্ধারণ করুন (kbps)" + }, + "threads": { + "description": "ব্যবহারের জন্য থ্রেডের পরিমাণ", + "name": "থ্রেডস" + }, + "custom_audio_codec": { + "description": "একটি কাস্টম অডিও কোডেক নির্ধারণ করুন (যেমন AAC)", + "name": "কাস্টম অডিও কোডেক" + }, + "preset": { + "name": "প্রিসেট", + "description": "রূপান্তরের গতি নির্ধারণ করুন" + }, + "constant_rate_factor": { + "name": "স্থির হার ফ্যাক্টর", + "description": "ভিডিও এনকোডারের জন্য স্থির হার ফ্যাক্টর নির্ধারণ করুন\nlibx264 এর জন্য 0 থেকে 51 পর্যন্ত" + } + }, + "name": "FFmpeg অপশনস" + }, + "logging": { + "name": "লগিং", + "description": "মিডিয়া ডাউনলোড হচ্ছে এমন সময় টোস্ট দেখায়" + }, + "custom_path_format": { + "description": "ডাউনলোডেড মিডিয়ার জন্য একটি কাস্টম পাথ ফরম্যাট নির্দিষ্ট করুন\n\nউপলব্ধ ভেরিয়েবল:\n - %username%\n - %source%\n - %hash%\n - %date_time%", + "name": "কাস্টম পাথ ফরম্যাট" + }, + "save_folder": { + "name": "সেভ ফোল্ডার", + "description": "সেই ডিরেক্টরি নির্বাচন করুন যেখানে সমস্ত মিডিয়া ডাউনলোড করা হবে" + }, + "allow_duplicate": { + "description": "একই মিডিয়া একাধিকবার ডাউনলোড করার অনুমতি দেয়", + "name": "একই মিডিয়া একাধিকবার ডাউনলোড করা অনুমোদন করুন" + }, + "merge_overlays": { + "name": "একটি স্ন্যাপের টেক্সট এবং মিডিয়াকে একটি একক ফাইলে মিশ্রিত করুন", + "description": "একটি স্ন্যাপের টেক্সট এবং মিডিয়াকে একটি একক ফাইলে মিশ্রিত করে" + }, + "download_profile_pictures": { + "name": "প্রোফাইল ছবি ডাউনলোড করুন", + "description": "প্রোফাইল পৃষ্ঠা থেকে প্রোফাইল ছবি ডাউনলোড করতে অনুমতি দেয়" + }, + "download_context_menu": { + "name": "ডাউনলোড কনটেক্সট মেনু", + "description": "কনটেক্সট মেনু ব্যবহার করে কথোপকথন বা গল্প থেকে মেসেজ ডাউনলোড/প্রিভিউ করতে অনুমতি দেয়।\nবোতামে দীর্ঘ চাপ ডাউনলোড জোর করে করবে" + } + }, + "name": "ডাউনলোডার" + }, + "user_interface": { + "description": "স্ন্যাপচ্যাটের চেহারা এবং অনুভূতি পরিবর্তন করুন", + "properties": { + "friend_feed_message_preview": { + "properties": { + "amount": { + "name": "পরিমাণ", + "description": "প্রিভিউ পাওয়ার জন্য বার্তাগুলির পরিমাণ" + } + }, + "name": "বন্ধু ফিড মেসেজ প্রিভিউ", + "description": "বন্ধু ফিডে শেষ বার্তাগুলির একটি প্রিভিউ দেখায়" + }, + "hide_ui_components": { + "name": "UI উপাদান লুকান", + "description": "কোন UI উপাদান লুকাতে চান তা নির্বাচন করুন" + }, + "enable_friend_feed_menu_bar": { + "description": "নতুন বন্ধু ফিড মেনু বার সক্রিয় করে", + "name": "বন্ধু ফিড মেনু বার" + }, + "old_bitmoji_selfie": { + "name": "পুরানো বিটমোজি সেলফি", + "description": "পুরানো স্ন্যাপচ্যাট সংস্করণ থেকে বিটমোজি সেলফিগুলি ফিরিয়ে আনে" + }, + "disable_spotlight": { + "name": "স্পটলাইট অক্ষম করুন", + "description": "স্পটলাইট পৃষ্ঠা অক্ষম করে" + }, + "enable_app_appearance": { + "description": "লুকানো অ্যাপ চেহারা সেটিং সক্রিয় করে\nনতুন স্ন্যাপচ্যাট সংস্করণে এটি প্রয়োজন নাও হতে পারে", + "name": "অ্যাপ চেহারা সেটিংস সক্রিয় করুন" + }, + "snap_preview": { + "name": "স্ন্যাপ প্রিভিউ", + "description": "চ্যাটে অদেখা স্ন্যাপের পাশে একটি ছোট প্রিভিউ দেখায়" + }, + "bootstrap_override": { + "description": "ব্যবহারকারীর ইন্টারফেস বুটস্ট্র্যাপ সেটিংস ওভাররাইড করে", + "name": "বুটস্ট্র্যাপ ওভাররাইড", + "properties": { + "app_appearance": { + "name": "অ্যাপের চেহারা", + "description": "একটি স্থায়ী অ্যাপের চেহারা সেট করে" + }, + "home_tab": { + "name": "হোম ট্যাব", + "description": "স্ন্যাপচ্যাট খুললে স্টার্টআপ ট্যাব ওভাররাইড করে" + } + } + }, + "hide_friend_feed_entry": { + "name": "বন্ধু ফিড এন্ট্রি লুকান", + "description": "বন্ধু ফিড থেকে নির্দিষ্ট একজন বন্ধুকে লুকায়\nএই বৈশিষ্ট্য পরিচালনা করতে সামাজিক ট্যাব ব্যবহার করুন" + }, + "prevent_message_list_auto_scroll": { + "name": "বার্তা তালিকা অটো স্ক্রোল প্রতিরোধ করে", + "description": "বার্তা পাঠানো/গ্রহণ করার সময় বার্তা তালিকাকে নীচে স্ক্রোল করা থেকে প্রতিরোধ করে" + }, + "streak_expiration_info": { + "name": "স্ট্রিক মেয়াদ শেষের তথ্য দেখায়", + "description": "স্ট্রিকস কাউন্টারের পাশে স্ট্রিক মেয়াদ শেষের টাইমার দেখায়" + }, + "hide_streak_restore": { + "name": "স্ট্রিক পুনরুদ্ধার লুকান", + "description": "বন্ধু ফিডে পুনরুদ্ধার বোতাম লুকায়" + }, + "friend_feed_menu_buttons": { + "name": "বন্ধু ফিড মেনু বোতাম", + "description": "বন্ধু ফিড মেনুতে কোন বোতামগুলি দেখানো হবে তা নির্বাচন করুন" + }, + "vertical_story_viewer": { + "name": "উল্লম্ব গল্প দর্শক", + "description": "সমস্ত গল্পের জন্য উল্লম্ব গল্প দর্শক সক্রিয় করে" + }, + "hide_story_suggestions": { + "description": "গল্পের পৃষ্ঠা থেকে পরামর্শ সরায়", + "name": "গল্পের পরামর্শ লুকান" + }, + "map_friend_nametags": { + "name": "উন্নত বন্ধু মানচিত্র নামফলক", + "description": "স্ন্যাপম্যাপে বন্ধুদের নামফলক উন্নত করে" + }, + "edit_text_override": { + "name": "টেক্সট সম্পাদনা ওভাররাইড", + "description": "টেক্সট ফিল্ডের আচরণ ওভাররাইড করে" + }, + "stealth_mode_indicator": { + "name": "স্টেলথ মোড সূচক", + "description": "স্টেলথ মোডে কথোপকথনের পাশে একটি 👻 ইমোজি যোগ করে" + }, + "opera_media_quick_info": { + "name": "অপেরা মিডিয়া দ্রুত তথ্য", + "description": "অপেরা দর্শক কনটেক্সট মেনুতে মিডিয়ার সৃষ্টির তারিখের মতো উপকারী তথ্য দেখায়" + }, + "message_indicators": { + "name": "বার্তা সূচক", + "description": "বার্তাগুলিতে নির্দিষ্ট সূচক আইকন যোগ করে\nনোট: সূচকগুলি ১০০% সঠিক নাও হতে পারে" + } + }, + "name": "ব্যবহারকারীর ইন্টারফেস" + }, + "messaging": { + "properties": { + "disable_replay_in_ff": { + "description": "বন্ধু ফিড থেকে দীর্ঘ চাপ দিয়ে পুনরায় চালানোর ক্ষমতা অক্ষম করে", + "name": "এফএফ-এ পুনরায় চালানো অক্ষম করুন" + }, + "half_swipe_notifier": { + "properties": { + "max_duration": { + "name": "সর্বাধিক সময়কাল", + "description": "অর্ধেক সোয়াইপের সর্বাধিক সময়কাল (সেকেন্ডে)" + }, + "min_duration": { + "description": "অর্ধেক সোয়াইপের সর্বনিম্ন সময়কাল (সেকেন্ডে)", + "name": "সর্বনিম্ন সময়কাল" + } + }, + "name": "অর্ধেক সোয়াইপ সূচক", + "description": "কেউ যখন কথোপকথনে অর্ধেক সোয়াইপ করে তখন আপনাকে জানায়" + }, + "remove_groups_locked_status": { + "description": "আপনাকে গ্রুপের তথ্য দেখতে দেয়, যদিও আপনাকে গ্রুপ থেকে বের করা হয়েছে", + "name": "গ্রুপের লক অবস্থা সরান" + }, + "loop_media_playback": { + "name": "মিডিয়া প্লেব্যাক পুনরাবৃত্তি", + "description": "স্ন্যাপ/গল্প দেখার সময় মিডিয়া প্লেব্যাক পুনরাবৃত্তি করে" + }, + "message_logger": { + "properties": { + "message_filter": { + "name": "বার্তা ফিল্টার", + "description": "নির্বাচন করুন কোন বার্তা লগ হবে (সব বার্তার জন্য খালি)" + }, + "keep_my_own_messages": { + "description": "আপনার নিজের বার্তা মুছে ফেলা থেকে প্রতিরোধ করে", + "name": "আমার নিজের বার্তা রাখুন" + }, + "auto_purge": { + "name": "অটো পার্জ", + "description": "নির্দিষ্ট সময়ের চেয়ে পুরানো ক্যাশে করা বার্তা স্বয়ংক্রিয়ভাবে মুছে ফেলে" + } + }, + "name": "বার্তা লগার", + "description": "বার্তাগুলি মুছে ফেলা থেকে প্রতিরোধ করে" + }, + "hide_peek_a_peek": { + "description": "চ্যাটে অর্ধেক সোয়াইপ করার সময় নোটিফিকেশন পাঠানো থেকে বিরত রাখে", + "name": "পিক-এ-পিক লুকান" + }, + "hide_typing_notifications": { + "name": "টাইপিং নোটিফিকেশন লুকান", + "description": "কেউ যেন জানতে না পারে আপনি একটি বার্তা টাইপ করছেন" + }, + "prevent_message_sending": { + "description": "নির্দিষ্ট ধরনের বার্তা পাঠানো প্রতিরোধ করে", + "name": "বার্তা পাঠানো প্রতিরোধ করুন" + }, + "better_notifications": { + "name": "উন্নত নোটিফিকেশন", + "description": "প্রাপ্ত নোটিফিকেশনে আরও তথ্য যোগ করে", + "properties": { + "media_caption": { + "name": "মিডিয়া ক্যাপশন", + "description": "নোটিফিকেশনে মিডিয়ার সংযুক্ত ক্যাপশন দেখায়" + }, + "friend_add_source": { + "name": "বন্ধু যোগ উৎস", + "description": "নোটিফিকেশনে বন্ধু অনুরোধের উৎস দেখায়" + }, + "reply_button": { + "description": "নোটিফিকেশনে একটি উত্তর বোতাম যোগ করে", + "name": "উত্তর বোতাম" + }, + "mark_as_read_button": { + "name": "পড়া হিসেবে চিহ্নিত বোতাম", + "description": "নোটিফিকেশন থেকে একটি বার্তা পড়া হিসেবে চিহ্নিত করতে দেয়" + }, + "group_notifications": { + "name": "গ্রুপ নোটিফিকেশন", + "description": "একক নোটিফিকেশনে গ্রুপ নোটিফিকেশন একত্রিত করে" + }, + "chat_preview": { + "name": "চ্যাট প্রিভিউ", + "description": "নোটিফিকেশনে প্রাপ্ত বার্তাগুলির প্রিভিউ দেখায়" + }, + "media_preview": { + "name": "মিডিয়া প্রিভিউ", + "description": "নোটিফিকেশনে নির্বাচিত মিডিয়া ধরনের প্রিভিউ দেখায়" + }, + "stacked_media_messages": { + "name": "স্তূপীকৃত মিডিয়া বার্তা", + "description": "প্রিভিউ করা না গেলে একাধিক মিডিয়া বার্তাকে একটি টেক্সট নোটিফিকেশনে একত্রিত করে। চ্যাট প্রিভিউ এর সাথে ব্যবহার করুন" + }, + "download_button": { + "name": "ডাউনলোড বোতাম", + "description": "নোটিফিকেশন থেকে মিডিয়া ডাউনলোড করতে দেয়" + }, + "mark_as_read_and_save_in_chat": { + "name": "পড়া হিসেবে চিহ্নিত এবং চ্যাটে সংরক্ষণ করুন", + "description": "নোটিফিকেশনে পড়া হিসেবে চিহ্নিত এবং চ্যাটে সংরক্ষণ করার বোতাম যোগ করে" + } + } + }, + "auto_save_messages_in_conversations": { + "description": "কথোপকথনে প্রতিটি বার্তা স্বয়ংক্রিয়ভাবে সংরক্ষণ করে", + "name": "অটো সেভ বার্তা" + }, + "auto_mark_as_read": { + "name": "অটো পড়া হিসেবে চিহ্নিত করুন", + "description": "স্টেলথ মোড সক্রিয় থাকলেও বার্তা/স্ন্যাপগুলি স্বয়ংক্রিয়ভাবে পড়া হিসাবে চিহ্নিত করে" + }, + "bypass_message_action_restrictions": { + "description": "একটি স্ন্যাপ খোলা ছাড়াই প্রতিক্রিয়া জানাতে দেয় বা একটি অসংরক্ষণযোগ্য বার্তা সংরক্ষণ করতে দেয়", + "name": "বার্তা ক্রিয়া সীমাবদ্ধতা এড়িয়ে চলুন" + }, + "anonymous_story_viewing": { + "description": "কেউ যেন জানতে না পারে আপনি তাদের গল্প দেখেছেন", + "name": "অজ্ঞাতসারে গল্প দেখা" + }, + "unlimited_snap_view_time": { + "description": "স্ন্যাপ দেখার সময়সীমা সরিয়ে দেয়", + "name": "স্ন্যাপ দেখার সময়সীমা অসীম" + }, + "call_start_confirmation": { + "name": "কল শুরু নিশ্চিতকরণ", + "description": "কল শুরু করার সময় একটি নিশ্চিতকরণ ডায়ালগ দেখায়" + }, + "unlimited_conversation_pinning": { + "name": "অসীম কথোপকথন পিনিং", + "description": "স্থানীয়ভাবে অসীম পরিমাণে কথোপকথন পিন করতে দেয়" + }, + "notification_blacklist": { + "name": "নোটিফিকেশন ব্ল্যাকলিস্ট", + "description": "সেই নোটিফিকেশনগুলি নির্বাচন করুন যা ব্লক করা উচিত" + }, + "strip_media_metadata": { + "description": "বার্তা হিসেবে পাঠানোর আগে মিডিয়ার মেটাডেটা সরায়", + "name": "মিডিয়া মেটাডেটা সরান" + }, + "prevent_story_rewatch_indicator": { + "name": "গল্প পুনরায় দেখার সূচক প্রতিরোধ করুন", + "description": "কেউ যেন জানতে না পারে আপনি তাদের গল্প পুনরায় দেখেছেন" + }, + "hide_bitmoji_presence": { + "name": "বিটমোজি উপস্থিতি লুকান", + "description": "চ্যাটে থাকাকালীন আপনার বিটমোজি পপ আপ হওয়া থেকে বিরত রাখে" + }, + "friend_mutation_notifier": { + "name": "বন্ধু পরিবর্তন সূচক", + "description": "বন্ধুর প্রোফাইলে কিছু পরিবর্তন হলে আপনাকে জানায়" + }, + "bypass_screenshot_detection": { + "name": "স্ক্রিনশট সনাক্তকরণ এড়িয়ে চলুন", + "description": "স্ন্যাপচ্যাট যখন আপনি স্ক্রিনশট নেন তা সনাক্ত করা থেকে বিরত রাখে" + }, + "gallery_media_send_override": { + "name": "গ্যালারি মিডিয়া পাঠানো ওভাররাইড", + "description": "গ্যালারি থেকে পাঠানোর সময় মিডিয়া উৎস নকল করে" + }, + "bypass_message_retention_policy": { + "name": "বার্তা ধরে রাখার নীতি এড়িয়ে চলুন", + "description": "বার্তা দেখার পর তা মুছে ফেলা থেকে প্রতিরোধ করে" + } + }, + "description": "বন্ধুদের সাথে মিথস্ক্রিয়া পরিবর্তন করুন", + "name": "মেসেজিং" + }, + "global": { + "properties": { + "disable_confirmation_dialogs": { + "name": "নিশ্চিতকরণ ডায়ালগ অক্ষম করুন", + "description": "নির্বাচিত ক্রিয়াকলাপগুলি স্বয়ংক্রিয়ভাবে নিশ্চিত করে" + }, + "snapchat_plus": { + "description": "স্ন্যাপচ্যাট প্লাস বৈশিষ্ট্যগুলি সক্রিয় করে\nকিছু সার্ভার-সাইডেড বৈশিষ্ট্য কাজ নাও করতে পারে", + "name": "স্ন্যাপচ্যাট প্লাস" + }, + "video_playback_rate_slider": { + "name": "ভিডিও প্লেব্যাক হার স্লাইডার", + "description": "অপেরা কনটেক্সট মেনুতে একটি স্লাইডার যোগ করে যা ভিডিও প্লেব্যাক হার পরিবর্তন করে\nনোট: পরিবর্তনগুলি কেবল পরবর্তী ভিডিওগুলিতে প্রযোজ্য" + }, + "disable_metrics": { + "name": "মেট্রিক্স অক্ষম করুন", + "description": "স্ন্যাপচ্যাটে নির্দিষ্ট বিশ্লেষণাত্মক ডেটা পাঠানো ব্লক করে" + }, + "default_video_playback_rate": { + "description": "ভিডিও প্লেব্যাকের জন্য ডিফল্ট গতি সেট করে\nমান 0.1 থেকে 4.0 এর মধ্যে হতে হবে", + "name": "ডিফল্ট ভিডিও প্লেব্যাক হার" + }, + "default_volume_controls": { + "name": "ডিফল্ট ভলিউম নিয়ন্ত্রণ", + "description": "স্ন্যাপচ্যাটকে সিস্টেম ভলিউম নিয়ন্ত্রণ ব্যবহার করতে বাধ্য করে" + }, + "better_location": { + "properties": { + "suspend_location_updates": { + "name": "অবস্থান আপডেট স্থগিত করুন", + "description": "মানচিত্র সেটিংসে একটি বোতাম যোগ করে যা অবস্থান আপডেট স্থগিত করে" + }, + "spoof_battery_level": { + "name": "ব্যাটারি লেভেল নকল করুন", + "description": "মানচিত্রে আপনার ডিভাইসের ব্যাটারি লেভেল নকল করে\nমান 0 থেকে 100 এর মধ্যে হতে হবে" + }, + "coordinates": { + "description": "নকল অবস্থানের স্থানাঙ্ক সেট করুন", + "name": "স্থানাঙ্ক" + }, + "walk_radius": { + "description": "এই ব্যাসার্ধের মধ্যে এলোমেলোভাবে হাঁটুন (ft)", + "name": "হাঁটার ব্যাসার্ধ" + }, + "spoof_location": { + "name": "অবস্থান নকল করুন", + "description": "আপনার অবস্থানকে নির্দিষ্ট একটিতে নকল করে" + }, + "always_update_location": { + "name": "সবসময় অবস্থান আপডেট করুন", + "description": "জিপিএস ডেটা না পেলেও স্ন্যাপচ্যাটকে অবস্থান আপডেট করতে বাধ্য করুন" + }, + "spoof_headphones": { + "name": "হেডফোন নকল করুন", + "description": "মানচিত্রে সঙ্গীত শোনার অবস্থা নকল করে" + } + }, + "description": "স্ন্যাপচ্যাটের অবস্থান উন্নত করে", + "name": "উন্নত অবস্থান" + }, + "block_ads": { + "name": "বিজ্ঞাপন ব্লক করুন", + "description": "বিজ্ঞাপন প্রদর্শন থেকে প্রতিরোধ করে" + }, + "disable_story_sections": { + "name": "গল্পের অংশগুলি অক্ষম করুন", + "description": "গল্পের পৃষ্ঠা থেকে অংশগুলি সরায়\nঠিকভাবে কাজ করতে রিফ্রেশ করা প্রয়োজন হতে পারে" + }, + "disable_google_play_dialogs": { + "description": "গুগল প্লে সার্ভিসেস উপলব্ধতা ডায়ালগ প্রদর্শন থেকে প্রতিরোধ করে", + "name": "গুগল প্লে সার্ভিসেস ডায়ালগ অক্ষম করুন" + }, + "disable_snap_splitting": { + "name": "স্ন্যাপ বিভক্তি অক্ষম করুন", + "description": "স্ন্যাপগুলিকে একাধিক অংশে বিভক্ত হওয়া থেকে প্রতিরোধ করে\nআপনি যে ছবিগুলি পাঠাবেন তা ভিডিওতে পরিণত হবে" + }, + "disable_permission_requests": { + "description": "স্ন্যাপচ্যাটকে নির্দিষ্ট অনুমতি চাওয়া থেকে প্রতিরোধ করে", + "name": "অনুমতি অনুরোধ অক্ষম করুন" + }, + "media_upload_quality": { + "properties": { + "disable_image_compression": { + "name": "ইমেজ কম্প্রেশন অক্ষম করুন", + "description": "মিডিয়া আপলোড করার সময় ইমেজ কম্প্রেশন অক্ষম করে" + }, + "custom_image_upload_format": { + "name": "কাস্টম ইমেজ আপলোড ফরম্যাট", + "description": "একটি কাস্টম ইমেজ আপলোড ফরম্যাট সেট করে\nসেরা গুণমানের জন্য একটি লসলেস ফরম্যাট (যেমন PNG) নির্বাচন করুন" + }, + "force_video_upload_source_quality": { + "name": "ভিডিও আপলোড সোর্স গুণমান জোর করে ব্যবহার করুন", + "description": "ভিডিও আপলোড করার সময় স্ন্যাপচ্যাটকে সোর্স গুণমান ব্যবহার করতে বাধ্য করে\nদয়া করে মনে রাখবেন এটি মিডিয়া থেকে মেটাডেটা সরাতে নাও পারে" + } + }, + "name": "মিডিয়া আপলোডের গুণমান", + "description": "মিডিয়া আপলোডের গুণমান ওভাররাইড করে" + }, + "disable_custom_tabs": { + "name": "কাস্টম ট্যাব অক্ষম করুন", + "description": "ওয়েব ব্রাউজারের পরিবর্তে সমর্থিত অ্যাপ্লিকেশনগুলিতে লিঙ্ক খোলে" + }, + "bypass_video_length_restriction": { + "name": "ভিডিও দৈর্ঘ্যের সীমাবদ্ধতা এড়িয়ে চলুন", + "description": "একক: একটি একক ভিডিও পাঠায়\nবিভক্ত: সম্পাদনার পর ভিডিওগুলি বিভক্ত করে" + }, + "spotlight_comments_username": { + "description": "স্পটলাইট মন্তব্যে লেখকের ব্যবহারকারীর নাম দেখায়", + "name": "স্পটলাইট মন্তব্যের ব্যবহারকারীর নাম" + }, + "hide_active_music": { + "name": "সক্রিয় সঙ্গীত লুকান", + "description": "স্ন্যাপচ্যাটকে আপনি সঙ্গীত শুনছেন তা জানা থেকে প্রতিরোধ করে\nএটি আপনাকে সঙ্গীত শোনার সময় বোতাম ব্যবহার করে স্ন্যাপ তুলতে দেবে" + }, + "auto_updater": { + "name": "অটো আপডেটার", + "description": "স্বয়ংক্রিয়ভাবে নতুন আপডেটগুলি পরীক্ষা করে" + }, + "disable_memories_snap_feed": { + "name": "মেমোরিজ স্ন্যাপ ফিড অক্ষম করুন", + "description": "ক্যামেরায় উপরে সোয়াইপ করলে স্ন্যাপচ্যাটকে সাম্প্রতিক মেমোরিজ দেখানো থেকে প্রতিরোধ করে" + } + }, + "description": "গ্লোবাল স্ন্যাপচ্যাট সেটিংস মোড়ান", + "name": "গ্লোবাল" + }, + "experimental": { + "properties": { + "spoof": { + "properties": { + "play_store_installer_package_name": { + "name": "প্লে স্টোর ইনস্টলার প্যাকেজের নাম", + "description": "ইনস্টলার প্যাকেজের নামকে com.android.vending এ ওভাররাইড করে" + }, + "remove_vpn_transport_flag": { + "name": "ভিপিএন ট্রান্সপোর্ট ফ্ল্যাগ সরান", + "description": "স্ন্যাপচ্যাটকে ভিপিএন সনাক্ত করা থেকে প্রতিরোধ করে" + }, + "remove_mock_location_flag": { + "name": "মক লোকেশন ফ্ল্যাগ সরান", + "description": "স্ন্যাপচ্যাটকে মক লোকেশন সনাক্ত করা থেকে প্রতিরোধ করে" + } + }, + "description": "আপনার সম্পর্কে বিভিন্ন তথ্য নকল করে", + "name": "নকল" + }, + "best_friend_pinning": { + "name": "সেরা বন্ধু পিনিং", + "description": "আপনাকে আপনার নম্বর ওয়ান সেরা বন্ধু হিসেবে একজন বন্ধুকে পিন করতে দেয়। নোট: কেবল আপনিই আপনার পিন করা সেরা বন্ধুটি দেখতে পাবেন" + }, + "hidden_snapchat_plus_features": { + "description": "অপ্রকাশিত/বেটা স্ন্যাপচ্যাট প্লাস বৈশিষ্ট্যগুলি সক্রিয় করে\nপুরানো স্ন্যাপচ্যাট সংস্করণে কাজ নাও করতে পারে", + "name": "লুকানো স্ন্যাপচ্যাট প্লাস বৈশিষ্ট্যগুলি" + }, + "native_hooks": { + "properties": { + "disable_bitmoji": { + "description": "বন্ধুর প্রোফাইল বিটমোজি অক্ষম করে", + "name": "বিটমোজি অক্ষম করুন" + }, + "composer_hooks": { + "properties": { + "composer_console": { + "description": "কম্পোজারে (শুধুমাত্র arm64) জাভাস্ক্রিপ্ট কোড চালানোর অনুমতি দেয়", + "name": "কম্পোজার কনসোল" + }, + "show_first_created_username": { + "name": "প্রথম তৈরি ব্যবহারকারীর নাম দেখান", + "description": "প্রোফাইল পৃষ্ঠায় বর্তমান ব্যবহারকারীর নামের পাশে প্রথম তৈরি ব্যবহারকারীর নাম দেখায়" + }, + "bypass_camera_roll_limit": { + "name": "ক্যামেরা রোল সীমা এড়িয়ে চলুন", + "description": "ক্যামেরা রোল থেকে পাঠানো যায় এমন মিডিয়ার সর্বাধিক পরিমাণ বাড়ায়" + }, + "composer_logs": { + "name": "কম্পোজার লগস", + "description": "কম্পোজারের কনসোল লগগুলি স্ন্যাপএনহ্যান্সে পুনঃনির্দেশ করে" + } + }, + "description": "কম্পোজার ক্রস-প্ল্যাটফর্ম UI ফ্রেমওয়ার্কে কোড ইনজেক্ট করে", + "name": "কম্পোজার হুকস" + }, + "custom_emoji_font": { + "description": "আপনাকে কাস্টম ইমোজি ফন্ট ব্যবহার করতে দেয়। শুধুমাত্র .ttf ফন্টগুলির সাথে কাজ করে", + "name": "কাস্টম ইমোজি ফন্ট" + } + }, + "name": "নেটিভ হুকস", + "description": "স্ন্যাপচ্যাটের নেটিভ কোডে যুক্ত অনিরাপদ বৈশিষ্ট্য" + }, + "e2ee": { + "properties": { + "encrypted_message_indicator": { + "name": "এনক্রিপ্টেড বার্তা সূচক", + "description": "এনক্রিপ্টেড বার্তার পাশে একটি 🔒 ইমোজি যোগ করে" + }, + "force_message_encryption": { + "name": "বার্তা এনক্রিপশন জোর করে", + "description": "E2E এনক্রিপশন সক্রিয় না থাকা ব্যক্তিদের কাছে এনক্রিপ্টেড বার্তা পাঠানো বন্ধ করে কেবল যখন একাধিক কথোপকথন নির্বাচিত হয়" + } + }, + "name": "End-To-End এনক্রিপশন", + "description": "একটি ভাগ করা গোপন কী ব্যবহার করে আপনার বার্তাগুলি AES দিয়ে এনক্রিপ্ট করে\nনিশ্চিত করুন যে আপনার কীটি কোথাও নিরাপদে সংরক্ষণ করেছেন!" + }, + "no_friend_score_delay": { + "name": "কোনও বন্ধু স্কোর বিলম্ব করেনি", + "description": "বন্ধুর স্কোর দেখার সময় বিলম্ব অপসারণ করে" + }, + "account_switcher": { + "name": "অ্যাকাউন্ট স্যুইচার", + "properties": { + "auto_backup_current_account": { + "description": "লগ আউট করা বা অ্যাকাউন্ট পরিবর্তন করার সময় বর্তমান অ্যাকাউন্ট স্বয়ংক্রিয়ভাবে ব্যাকআপ করে", + "name": "অটো ব্যাকআপ বর্তমান অ্যাকাউন্ট" + } + }, + "description": "লগ আউট না করে অ্যাকাউন্টের মধ্যে স্যুইচ করতে দেয়\nমেনু খুলতে আপনার বিটমোজি প্রোফাইলের পাশের সার্চ আইকনে দীর্ঘ চাপ দিন\nনোট: এই বৈশিষ্ট্যটি পরীক্ষামূলক এবং ভবিষ্যতে সম্ভবত পরিবর্তন হবে" + }, + "custom_streaks_expiration_format": { + "description": "স্ট্রিকস মেয়াদ শেষের ফরম্যাট কাস্টমাইজ করে\n\nউপলব্ধ ভেরিয়েবল:\n - %c: স্ট্রিকস গণনা\n - %e: আওয়ারগ্লাস ইমোজি\n - %d: দিন\n - %h: ঘন্টা\n - %m: মিনিট\n - %s: সেকেন্ড\n - %w: অবশিষ্ট সময়", + "name": "কাস্টম স্ট্রিকস মেয়াদ শেষের ফরম্যাট" + }, + "prevent_forced_logout": { + "name": "জোর করে লগআউট প্রতিরোধ করে", + "description": "অন্য ডিভাইসে লগইন করলে স্ন্যাপচ্যাট আপনাকে লগআউট করা থেকে বিরত রাখে" + }, + "story_logger": { + "description": "বন্ধুদের গল্পের ইতিহাস প্রদান করে", + "name": "গল্প লগার" + }, + "edit_message": { + "description": "কথোপকথনে বার্তা সম্পাদনা করতে দেয়", + "name": "বার্তাগুলি সম্পাদনা করুন" + }, + "convert_message_locally": { + "name": "স্থানীয়ভাবে বার্তা রূপান্তর করুন", + "description": "স্থানীয়ভাবে স্ন্যাপগুলিকে চ্যাট বাহ্যিক মিডিয়ায় রূপান্তর করে | এটি চ্যাট ডাউনলোড কনটেক্সট মেনুতে প্রদর্শিত হয়" + }, + "call_recorder": { + "description": "স্বয়ংক্রিয়ভাবে অডিও কল রেকর্ড করে", + "name": "কল রেকর্ডার" + }, + "infinite_story_boost": { + "name": "অনন্ত গল্প বৃদ্ধি", + "description": "স্টোরি বুস্ট লিমিট বিলম্ব বাইপাস করুন" + }, + "meo_passcode_bypass": { + "name": "আমার চোখ শুধু পাসকোড বাইপাস", + "description": "আমার চোখে কেবল পাসকোড বাইপাস করুন\nএটি কেবল তখনই কাজ করবে যদি পাসকোড আগে সঠিকভাবে প্রবেশ করানো হয়" + }, + "add_friend_source_spoof": { + "name": "বন্ধু উৎস স্পুফ যোগ করুন", + "description": "একটি বন্ধু অনুরোধের উৎস স্পুফ করে" + }, + "media_file_picker": { + "name": "মিডিয়া ফাইল পিকার", + "description": "গ্যালারি থেকে যেকোনো ভিডিও/অডিও ফাইল নির্বাচন করতে দেয়" + }, + "app_lock": { + "name": "অ্যাপ লক", + "description": "পাসকোড ছাড়া স্ন্যাপচ্যাটে প্রবেশ আটকায়", + "properties": { + "lock_on_resume": { + "name": "রিজুমে লক", + "description": "অ্যাপটি পুনরায় খোলার সময় লক করে" + } + } + }, + "cof_experiments": { + "name": "COF পরীক্ষা-নিরীক্ষা", + "description": "অপ্রকাশিত/বেটা স্ন্যাপচ্যাট বৈশিষ্ট্যগুলি সক্রিয় করে" + } + }, + "description": "পরীক্ষামূলক বৈশিষ্ট্য", + "name": "পরীক্ষামূলক" + }, + "scripting": { + "properties": { + "auto_reload": { + "name": "অটো রিলোড", + "description": "স্ক্রিপ্টগুলি পরিবর্তন হলে স্বয়ংক্রিয়ভাবে রিলোড করে" + }, + "module_folder": { + "name": "মডিউল ফোল্ডার", + "description": "স্ক্রিপ্টগুলি যে ফোল্ডারে অবস্থিত" + }, + "disable_log_anonymization": { + "name": "লগ অ্যানোনিমাইজেশন অক্ষম করুন", + "description": "লগগুলির বেনামী নিষ্ক্রিয় করে" + }, + "integrated_ui": { + "name": "ইন্টিগ্রেটেড UI", + "description": "স্ক্রিপ্টগুলিকে স্ন্যাপচ্যাটে কাস্টম UI উপাদান যোগ করতে দেয়" + }, + "developer_mode": { + "name": "ডেভেলপার মোড", + "description": "স্ন্যাপচ্যাটের UI-এ ডিবাগ তথ্য দেখায়" + } + }, + "description": "স্ন্যাপএনহ্যান্স প্রসারিত করতে কাস্টম স্ক্রিপ্ট চালান", + "name": "স্ক্রিপ্টিং" + }, + "camera": { + "properties": { + "black_photos": { + "description": "ধারণ করা ছবিগুলিকে কালো পটভূমির সাথে প্রতিস্থাপন করে\nভিডিওগুলি প্রভাবিত হয় না", + "name": "কালো ছবি" + }, + "front_custom_frame_rate": { + "name": "ফ্রন্ট কাস্টম ফ্রেম রেট", + "description": "ফ্রন্ট ক্যামেরার ফ্রেম রেট ওভাররাইড করে" + }, + "immersive_camera_preview": { + "description": "ক্যামেরা প্রিভিউ ক্রপ করা থেকে স্ন্যাপচ্যাটকে প্রতিরোধ করে\nএটি কিছু ডিভাইসে ক্যামেরা ঝলসানোর কারণ হতে পারে", + "name": "ইমারসিভ প্রিভিউ" + }, + "disable_cameras": { + "description": "নির্বাচিত ক্যামেরা ব্যবহার থেকে স্ন্যাপচ্যাটকে প্রতিরোধ করে", + "name": "ক্যামেরা অক্ষম করুন" + }, + "custom_resolution": { + "name": "কাস্টম রেজোলিউশন", + "description": "একটি কাস্টম ক্যামেরা রেজোলিউশন সেট করে, প্রস্থ x উচ্চতা (যেমন 1920x1080)\nকাস্টম রেজোলিউশনটি আপনার ডিভাইস দ্বারা সমর্থিত হতে হবে" + }, + "override_back_resolution": { + "name": "ব্যাক রেজোলিউশন ওভাররাইড করুন", + "description": "ব্যাক ক্যামেরার জন্য ক্যামেরা রেজোলিউশন ওভাররাইড করে" + }, + "back_custom_frame_rate": { + "name": "ব্যাক কাস্টম ফ্রেম রেট", + "description": "ব্যাক ক্যামেরার ফ্রেম রেট ওভাররাইড করে" + }, + "hevc_recording": { + "name": "HEVC রেকর্ডিং", + "description": "ভিডিও রেকর্ডিংয়ের জন্য HEVC (H.265) কোডেক ব্যবহার করে" + }, + "override_front_resolution": { + "name": "ফ্রন্ট রেজোলিউশন ওভাররাইড করুন", + "description": "ফ্রন্ট ক্যামেরার জন্য ক্যামেরা রেজোলিউশন ওভাররাইড করে" + }, + "force_camera_source_encoding": { + "name": "ক্যামেরা সোর্স এনকোডিং জোর করে ব্যবহার করুন", + "description": "ক্যামেরা সোর্স এনকোডিং জোর করে ব্যবহার করে" + } + }, + "name": "ক্যামেরা", + "description": "নিখুঁত স্ন্যাপের জন্য সঠিক সেটিংস সামঞ্জস্য করুন" + }, + "rules": { + "description": "প্রতিটি ব্যক্তির জন্য স্বয়ংক্রিয় বৈশিষ্ট্যগুলি পরিচালনা করুন", + "name": "নিয়মাবলী" + }, + "streaks_reminder": { + "properties": { + "group_notifications": { + "name": "গ্রুপ নোটিফিকেশন", + "description": "একক নোটিফিকেশনে গ্রুপ নোটিফিকেশন একত্রিত করে" + }, + "remaining_hours": { + "description": "নোটিফিকেশন দেখানোর আগে অবশিষ্ট সময়ের পরিমাণ (ঘন্টা)", + "name": "অবশিষ্ট সময়" + }, + "interval": { + "name": "বিরতি", + "description": "প্রতিটি অনুস্মারকের মধ্যে বিরতি (ঘন্টা)" + } + }, + "name": "স্ট্রিকস অনুস্মারক", + "description": "নিয়মিত আপনাকে আপনার স্ট্রিকস সম্পর্কে জানায়" + }, + "friend_tracker": { + "description": "স্ন্যাপচ্যাটে বন্ধুর ক্রিয়াকলাপ রেকর্ড করে", + "properties": { + "record_messaging_events": { + "name": "মেসেজিং ইভেন্টগুলি রেকর্ড করুন", + "description": "স্ন্যাপ খোলা, বার্তা পড়া ইত্যাদি মেসেজিং ইভেন্টগুলি রেকর্ড করে ।" + }, + "allow_running_in_background": { + "name": "ব্যাকগ্রাউন্ডে দৌড়ানোর অনুমতি দিন", + "description": "ট্র্যাকারকে ব্যাকগ্রাউন্ডে চালানোর অনুমতি দেয়। নোট: এটি আপনার ব্যাটারির চার্জ অনেক কমিয়ে দেবে" + }, + "auto_purge": { + "description": "নির্দিষ্ট সময়ের চেয়ে পুরানো ক্যাশে করা ইভেন্টগুলি স্বয়ংক্রিয়ভাবে মুছে ফেলে", + "name": "স্বয়ংক্রিয় শুদ্ধি" + } + }, + "name": "বন্ধু ট্র্যাকার" + } + }, + "options": { + "message_indicators": { + "location_indicator": "লোকেশন সক্রিয় করে পাঠানো স্ন্যাপগুলির পাশে একটি 📍 আইকন যোগ করে", + "director_mode_indicator": "ডিরেক্টর মোড ব্যবহার করে পাঠানো স্ন্যাপগুলির পাশে একটি ✏️ আইকন যোগ করে, যা গ্যালারির চিত্রগুলি স্ন্যাপ হিসেবে পাঠানোর জন্য ব্যবহৃত হতে পারে", + "encryption_indicator": "যে বার্তাগুলি শুধুমাত্র আপনাকে পাঠানো হয়েছে তার পাশে একটি 🔒 আইকন যোগ করে", + "platform_indicator": "যে প্ল্যাটফর্ম থেকে মিডিয়া পাঠানো হয়েছে তার আইকন যোগ করে (যেমন অ্যান্ড্রয়েড, আইওএস, ওয়েব)", + "ovf_editor_indicator": "যদি কোনো স্ন্যাপ OVF এডিটর ব্যবহার করে পাঠানো হয় তাহলে তা নির্দেশ করে" + }, + "friend_feed_menu_buttons": { + "conversation_info": "👤 কথোপকথনের তথ্য", + "mark_snaps_as_seen": "👀 দেখা হিসেবে স্ন্যাপস চিহ্নিত করুন", + "mark_stories_as_seen_locally": "👀 স্থানীয়ভাবে দেখা হিসেবে গল্পগুলি চিহ্নিত করুন", + "auto_save": "💬 বার্তাগুলি স্বতঃ সংরক্ষণ করুন", + "stealth": "👻 স্টিলথ মোড", + "auto_open_snaps": "📷 স্বতঃ খুলুন স্ন্যাপস", + "auto_download": "⬇️ স্বয়ংক্রিয় ডাউনলোড", + "unsaveable_messages": "⬇️ অসংরক্ষণযোগ্য বার্তা", + "e2e_encryption": "🔒 E2E এনক্রিপশন ব্যবহার করুন" + }, + "path_format": { + "create_source_folder": "প্রতিটি মিডিয়া উৎসের ধরন অনুযায়ী ফোল্ডার তৈরি করুন", + "append_hash": "ফাইলের নামে একটি অনন্য হ্যাশ যোগ করুন", + "create_author_folder": "প্রতিটি লেখকের জন্য ফোল্ডার তৈরি করুন", + "append_date_time": "ফাইলের নামে তারিখ ও সময় যোগ করুন", + "append_source": "ফাইলের নামে মিডিয়া উৎস যোগ করুন", + "append_username": "ফাইলের নামে ব্যবহারকারীর নাম যোগ করুন" + }, + "add_friend_source_spoof": { + "added_by_community": "সম্প্রদায় অনুসারে", + "added_by_username": "ব্যবহারকারীর নাম অনুসারে", + "added_by_qr_code": "QR কোড দ্বারা", + "added_by_mention": "উল্লেখ করে", + "added_by_group_chat": "গ্রুপ চ্যাট দ্বারা", + "added_by_quick_add": "কুইক অ্যাড দ্বারা (ব্যান হওয়ার উচ্চ ঝুঁকি)" + }, + "disable_story_sections": { + "discover": "আবিষ্কার", + "friends": "বন্ধুরা", + "following": "অনুসরণ" + }, + "old_bitmoji_selfie": { + "3d": "৩ডি বিটমোজি", + "2d": "২ডি বিটমোজি" + }, + "auto_mark_as_read": { + "conversation_read": "বার্তা পাঠানোর সময় কথোপকথনকে পড়া হিসেবে চিহ্নিত করুন", + "snap_reply": "তাদের উত্তর দেওয়ার সময় স্ন্যাপগুলিকে পড়া হিসেবে চিহ্নিত করুন" + }, + "notifications": { + "speaking": "স্পিকিং", + "abandon_video": "মিসড ভিডিও কল", + "stories": "গল্পগুলি", + "typing": "টাইপিং", + "snap_replay": "স্ন্যাপ রিপ্লে", + "chat_reaction": "DM প্রতিক্রিয়া", + "group_chat_reaction": "গ্রুপ প্রতিক্রিয়া", + "initiate_video": "আসন্ন ভিডিও কল", + "initiate_audio": "আসন্ন অডিও কল", + "snap": "স্ন্যাপ", + "chat_reply": "চ্যাটের উত্তর", + "chat_screenshot": "স্ক্রিনশট", + "chat_screen_record": "স্ক্রিন রেকর্ড", + "camera_roll_save": "ক্যামেরা রোল সংরক্ষণ করুন", + "chat": "চ্যাট", + "abandon_audio": "মিসড অডিও কল" + }, + "gallery_media_send_override": { + "always_ask": "সর্বদা জিজ্ঞাসা করুন", + "NOTE": "অডিও নোট", + "SNAP": "স্ন্যাপ", + "ORIGINAL": "মূল" + }, + "hide_ui_components": { + "hide_profile_call_buttons": "প্রোফাইল কল বোতামগুলি অপসারণ করুন", + "hide_chat_call_buttons": "চ্যাট কল বোতামগুলি অপসারণ করুন", + "hide_live_location_share_button": "লাইভ লোকেশন শেয়ার বোতাম অপসারণ করুন", + "hide_stickers_button": "স্টিকার বোতাম অপসারণ করুন", + "hide_voice_record_button": "ভয়েস রেকর্ড বোতাম অপসারণ করুন", + "hide_unread_chat_hint": "অপঠিত চ্যাটের সংকেত অপসারণ করুন" + }, + "strip_media_metadata": { + "remove_audio_note_transcript_capability": "অডিও নোট ট্রান্সক্রিপ্ট ক্ষমতা অপসারণ করুন", + "hide_extras": "অতিরিক্ত লুকান", + "remove_audio_note_duration": "অডিও নোটের সময়কাল অপসারণ করুন", + "hide_snap_filters": "স্ন্যাপ ফিল্টারগুলি লুকান", + "hide_caption_text": "ক্যাপশন পাঠ্য লুকান" + }, + "bypass_video_length_restriction": { + "single": "একক মিডিয়া", + "split": "বিভক্ত মিডিয়া" + }, + "disable_confirmation_dialogs": { + "ignore_friend": "বন্ধুকে উপেক্ষা করুন", + "hide_friend": "বন্ধুকে লুকান", + "erase_message": "বার্তা মুছে ফেলুন", + "hide_conversation": "কথোপকথন লুকান", + "remove_friend": "বন্ধুকে সরান", + "block_friend": "বন্ধুকে ব্লক করুন", + "clear_conversation": "বন্ধু ফিড থেকে কথোপকথন পরিষ্কার করুন" + }, + "auto_purge": { + "1_month": "১ মাস", + "6_months": "৬ মাস", + "6_hours": "৬ ঘন্টা", + "3_days": "৩ দিন", + "1_day": "১ দিন", + "2_weeks": "২ সপ্তাহ", + "never": "কখনও না", + "1_hour": "১ ঘন্টা", + "3_hours": "৩ ঘন্টা", + "12_hours": "১২ ঘন্টা", + "1_week": "১ সপ্তাহ", + "3_months": "৩ মাস" + }, + "auto_download_sources": { + "friend_snaps": "বন্ধু স্ন্যাপস", + "spotlight": "স্পটলাইট", + "friend_stories": "বন্ধুর গল্প", + "public_stories": "পাবলিক গল্প" + }, + "friend_mutation_notifier": { + "birthday_changes": "কেউ যখন তাদের জন্মদিন পরিবর্তন করে তখন বিজ্ঞপ্তি দিন", + "bitmoji_scene_changes": "কেউ যখন তাদের বিটমোজি দৃশ্য পরিবর্তন করে তখন বিজ্ঞপ্তি দিন", + "remove_friend": "কেউ যখন আপনাকে বন্ধু হিসেবে সরিয়ে দেয় তখন বিজ্ঞপ্তি দিন", + "bitmoji_avatar_changes": "কেউ যখন তাদের বিটমোজি অবতার পরিবর্তন করে তখন বিজ্ঞপ্তি দিন", + "bitmoji_background_changes": "কেউ যখন তাদের বিটমোজি পটভূমি পরিবর্তন করে তখন বিজ্ঞপ্তি দিন", + "bitmoji_selfie_changes": "কেউ যখন তাদের বিটমোজি সেলফি পরিবর্তন করে তখন বিজ্ঞপ্তি দিন" + }, + "app_appearance": { + "always_light": "সর্বদা লাইট", + "always_dark": "সর্বদা ডার্ক" + }, + "hide_story_suggestions": { + "hide_suggested_friend_stories": "প্রস্তাবিত বন্ধুর গল্পগুলি লুকান", + "hide_my_stories": "আমার গল্প লুকান" + }, + "home_tab": { + "chat": "চ্যাট", + "map": "মানচিত্র", + "camera": "ক্যামেরা", + "discover": "আবিষ্কার", + "spotlight": "স্পটলাইট" + }, + "edit_text_override": { + "bypass_text_input_limit": "টেক্সট ইনপুট সীমা বাইপাস করুন", + "multi_line_chat_input": "মাল্টি লাইন চ্যাট ইনপুট" + }, + "disable_permission_requests": { + "notifications": "বিজ্ঞপ্তিগুলি", + "microphone": "মাইক্রোফোন", + "read_media_images": "মিডিয়া চিত্র পড়ুন", + "read_media_video": "মিডিয়া ভিডিও পড়ুন", + "camera": "ক্যামেরা", + "location": "অবস্থান", + "read_contacts": "পরিচিতিগুলি পড়ুন", + "nearby_devices": "আশেপাশের ডিভাইসগুলি", + "phone_calls": "ফোন কল" + }, + "auto_reload": { + "all": "সব (স্ন্যাপচ্যাট + স্ন্যাপএনহ্যান্স)", + "snapchat_only": "শুধুমাত্র স্ন্যাপচ্যাট" + }, + "logging": { + "started": "শুরু হয়েছে", + "success": "সাফল্য", + "progress": "অগ্রগতি", + "failure": "ব্যর্থতা" + }, + "disable_cameras": { + "back": "পিছনের ক্যামেরা", + "front": "সামনের ক্যামেরা" + } + }, + "notices": { + "unstable": "⚠ অস্থির", + "internal_behavior": "⚠ এটি স্ন্যাপচ্যাটের অভ্যন্তরীণ আচরণ ভেঙে দিতে পারে", + "ban_risk": "⚠ এই বৈশিষ্ট্যটি নিষেধাজ্ঞা ঘটাতে পারে" + } + }, + "content_type": { + "FAMILY_CENTER_INVITE": "পরিবার কেন্দ্রের আমন্ত্রণ", + "LIVE_LOCATION_SHARE": "লাইভ লোকেশন শেয়ার করুন", + "CREATIVE_TOOL_ITEM": "ক্রিয়েটিভ টুল আইটেম", + "NOTE": "অডিও নোট", + "CHAT": "চ্যাট", + "STATUS_CONVERSATION_CAPTURE_SCREENSHOT": "স্ক্রীনশট", + "STATUS_CONVERSATION_CAPTURE_RECORD": "স্ক্রিন রেকর্ড", + "STATUS_CALL_MISSED_VIDEO": "মিসড ভিডিও কল", + "STATUS_CALL_MISSED_AUDIO": "মিসড অডিও কল", + "FAMILY_CENTER_ACCEPT": "ফ্যামিলি সেন্টার গ্রহণ", + "SNAP": "স্ন্যাপ", + "STICKER": "স্টিকার", + "STATUS": "স্থিতি", + "LOCATION": "অবস্থান", + "TINY_SNAP": "টিনি স্ন্যাপ", + "EXTERNAL_MEDIA": "বাহ্যিক মিডিয়া", + "STATUS_SAVE_TO_CAMERA_ROLL": "ক্যামেরা রোলে সংরক্ষণ করা হয়েছে", + "SHARE": "শেয়ার", + "STATUS_COUNTDOWN": "কাউন্টডাউন", + "MAP_REACTION": "ম্যাপ প্রতিক্রিয়া", + "FAMILY_CENTER_LEAVE": "ফ্যামিলি সেন্টার ছুটি", + "STATUS_PLUS_GIFT": "স্ট্যাটাস প্লাস উপহার" + }, + "media_download_source": { + "message_logger": "বার্তা লগার", + "pending": "মুলতুবি", + "story": "গল্প", + "profile_picture": "প্রোফাইল ছবি", + "story_logger": "গল্প লগার", + "public_story": "পাবলিক স্টোরি", + "spotlight": "স্পটলাইট", + "voice_call": "ভয়েস কল", + "none": "কিছু না", + "chat_media": "চ্যাট মিডিয়া", + "merged": "মার্জ করা হয়েছে" + }, + "end_to_end_encryption": { + "incoming_secret_message": "আপনার বন্ধু সবেমাত্র আপনার সর্বজনীন কী গ্রহণ করেছেন। গোপন কথা গ্রহণ করতে নীচে ক্লিক করুন।", + "unencrypted_conversation_send_failure_toast": "আপনি এনক্রিপ্টেড এবং অ-এনক্রিপ্টেড উভয় ধরনের কথোপকথনে এনক্রিপ্টেড সামগ্রী পাঠাতে পারবেন না!", + "native_hooks_send_failure_toast": "পাঠানো ব্যর্থ হয়েছে! অনুগ্রহ করে সেটিংসে নেটিভ হুকস সক্রিয় করুন।", + "no_participants_to_encrypt_toast": "এই কথোপকথনে আপনার কোনো বন্ধু নেই যাদের সাথে বার্তা এনক্রিপ্ট করা যায়!", + "encryption_failed_toast": "বার্তা এনক্রিপ্ট করা ব্যর্থ হয়েছে! আরও বিস্তারিত জানতে লগক্যাট চেক করুন।", + "accept_secret_key_success_toast": "সম্পন্ন! আপনি এখন এই বন্ধুর সাথে এনক্রিপ্টেড বার্তা পাঠাতে এবং গ্রহণ করতে পারবেন।", + "accept_public_key_success_toast": "সর্বজনীন কী সফলভাবে স্বীকৃত!", + "accept_public_key_failure_toast": "সর্বজনীন কী স্বীকার করতে ব্যর্থ হয়েছে", + "accept_public_key_button": "সর্বজনীন কী মেনে নিন", + "outgoing_pk_message": "কী বিনিময়ের অনুরোধ", + "confirmation_dialogs": { + "title": "End-to-end এনক্রিপশন", + "confirmation_2": "আপনি কি সত্যিই নিশ্চিত যে আপনি চালিয়ে যেতে চান? এটি পিছু হটার শেষ সুযোগ।", + "confirmation_1": "সতর্কীকরণ: এটি আপনার বিদ্যমান কী ওভাররাইট করবে। আপনি এই বন্ধুর সমস্ত এনক্রিপ্টেড বার্তার অ্যাক্সেস হারাবেন। আপনি কি নিশ্চিত যে আপনি চালিয়ে যেতে চান?" + }, + "outgoing_secret_message": "কী বিনিময়ের প্রতিক্রিয়া", + "toolbox": { + "shared_key_fingerprint": "আপনার ফিঙ্গারপ্রিন্ট হল:\n\n{fingerprint}\n\nনিশ্চিত করুন যে এটি আপনার বন্ধুর ফিঙ্গারপ্রিন্টের সাথে মিলে যায়!", + "no_shared_key": "আপনার এই বন্ধুর সাথে এখনও কোনো গোপন শেয়ার নেই। নতুন একটি শুরু করতে নীচে ক্লিক করুন।", + "initiate_exchange_button": "কী এক্সচেঞ্জ শুরু করুন" + }, + "accept_secret_key_failure_toast": "গোপন কী স্বীকার করতে ব্যর্থ হয়েছে", + "incoming_pk_message": "আপনি সবেমাত্র একটি সর্বজনীন কী অনুরোধ পেয়েছেন। এটি গ্রহণ করতে নীচে ক্লিক করুন।", + "accept_secret_button": "গোপন গ্রহণ" + }, + "friend_mutation_observer": { + "bitmoji_background_changed": "{username} তাদের বিটমোজি পটভূমি পরিবর্তন করেছেন", + "bitmoji_scene_changed": "{username} তাদের বিটমোজি দৃশ্য পরিবর্তন করেছেন", + "birthday_added": "{username} তাদের জন্মদিন ({birthday}) যোগ করেছেন", + "birthday_changed": "{username} তাদের জন্মদিন {oldBirthday} থেকে {newBirthday} পরিবর্তন করেছেন", + "bitmoji_selfie_changed": "{username} তাদের বিটমোজি সেলফি পরিবর্তন করেছেন", + "bitmoji_avatar_changed": "{username} তাদের বিটমোজি অবতার পরিবর্তন করেছেন", + "birthday_removed": "{username} তাদের জন্মদিন ({birthday}) সরিয়ে ফেলেছেন", + "notification_channel_name": "বন্ধু মিউটেশন পর্যবেক্ষক", + "friend_removed": "{username} আপনাকে বন্ধু হিসেবে সরিয়ে দিয়েছেন" + }, + "modal_option": { + "profile_info": "প্রোফাইলের তথ্য", + "close": "বন্ধ" + }, + "bulk_messaging_action": { + "actions": { + "remove_friends": "বন্ধুদের সরান", + "clear_conversations": "পরিষ্কার কথোপকথন" + }, + "progress_status": "প্রক্রিয়াকরণ {index} এর {total}", + "choose_action_title": "একটি ক্রিয়া নির্বাচন করুন", + "selection_dialog_continue_button": "অবিরত", + "confirmation_dialog": { + "title": "তুমি কি নিশ্চিত?", + "message": "এটি সমস্ত নির্বাচিত বন্ধুদের প্রভাবিত করবে। এই ক্রিয়াটি পূর্বাবস্থায় ফেরানো যাবে না।" } }, "profile_picture_downloader": { - "button": "প্রোফাইল ছবি ডাউনলোড করুন", - "title": "প্রোফাইল ছবি ডাউনলোডার", "avatar_option": "অবতার", - "background_option": "পটভূমি" + "title": "প্রোফাইল ছবি ডাউনলোডার", + "button": "ডাউনলোড প্রোফাইল পিকচার", + "background_option": "প্রেক্ষাপট" + }, + "material3_strings": { + "date_range_picker_scroll_to_next_month": "পরের মাসে", + "date_input_invalid_for_pattern": "অকার্যকর তারিখ", + "date_range_picker_day_in_range": "নির্বাচিত", + "date_picker_switch_to_calendar_mode": "ক্যালেন্ডার", + "date_input_invalid_not_allowed": "অকার্যকর তারিখ", + "date_range_picker_title": "তারিখের সীমা নির্বাচন করুন", + "date_range_picker_start_headline": "থেকে", + "date_range_picker_end_headline": "প্রতি", + "date_picker_today_description": "আজ", + "date_input_invalid_year_range": "অবৈধ বছর", + "date_picker_switch_to_input_mode": "ইনপুট", + "date_range_picker_scroll_to_previous_month": "পূর্ববর্তী মাসে", + "date_range_input_invalid_range_input": "তারিখের সীমা অবৈধ" + }, + "friendship_link_type": { + "following": "অনুসরণ", + "suggested": "প্রস্তাবিত", + "incoming_follower": "আসন্ন অনুসারী", + "mutual": "পারস্পরিক", + "outgoing": "বহির্গামী", + "blocked": "অবরুদ্ধ", + "deleted": "বিলোপ", + "incoming": "আসন্ন" }, "call_start_confirmation": { - "dialog_title": "কল শুরু করুন", - "dialog_message": "আপনি কি একটি কল শুরু করতে নিশ্চিত?" + "dialog_message": "আপনি কি নিশ্চিত যে আপনি কল শুরু করতে চান?", + "dialog_title": "কল শুরু করুন" }, - "half_swipe_notifier": { - "notification_channel_name": "হাফ সোয়াইপ", - "notification_content_dm": "{friend} আপনার চ্যাটে {duration} সেকেন্ডের জন্য অর্ধেক সোয়াইপ করেছে", - "notification_content_group": "{group}-এ {friend} {duration} সেকেন্ডের জন্য অর্ধেক সোয়াইপ করেছে" - }, - "download_processor": { - "attachment_type": { - "snap": "স্ন্যাপ", - "sticker": "স্টিকার", - "gif": "জিআইএফ", - "external_media": "বাহ্যিক মিডিয়া", - "note": "নোট", - "original_story": "আসল গল্প" - }, - "select_attachments_title": "সংযুক্তি নির্বাচন করুন", - "download_started_toast": "ডাউনলোড শুরু হয়েছে", - "unsupported_content_type_toast": "অসমর্থিত বিষয়বস্তুর প্রকার!", - "failed_no_longer_available_toast": "মিডিয়া আর উপলব্ধ নেই", - "no_attachments_toast": "কোনো সংযুক্তি পাওয়া যায়নি!", - "already_queued_toast": "মিডিয়া ইতিমধ্যে সারিতে আছে!", - "already_downloaded_toast": "মিডিয়া ইতিমধ্যে ডাউনলোড করা হয়েছে!", - "content_saved_toast": "সংরক্ষিত!", - "download_toast": "{path} ডাউনলোড করা হচ্ছে...", - "processing_toast": "{path} প্রক্রিয়াজাত করা হচ্ছে...", - "failed_generic_toast": "ডাউনলোড করতে ব্যর্থ হয়েছে", - "failed_to_create_preview_toast": "প্রিভিউ তৈরি করতে ব্যর্থ হয়েছে", - "failed_processing_toast": "প্রক্রিয়াকরণে ব্যর্থ হয়েছে {error}", - "failed_gallery_toast": "গ্যালারিতে সংরক্ষণ করতে ব্যর্থ হয়েছে {error}", - "dash_no_chapter": "কোনো অধ্যায় পাওয়া যায়নি", - "dash_dialog": { - "title": "ড্যাশ মিডিয়া ডাউনলোড করুন", - "download_all": "সব ডাউনলোড করুন", - "segment_text": "সেগমেন্ট {from} - {to}" + "better_notifications": { + "button": { + "reply": "উত্তর", + "mark_as_read": "পঠিত হিসাবে চিহ্নিত করুন", + "download": "ডাউনলোড" } }, - "streaks_reminder": { - "notification_title": "ধারাবাহিকতা", - "notification_text": "আপনি {hoursLeft} ঘন্টার মধ্যে {friend}-এর সাথে আপনার ধারাবাহিকতা হারাবেন" + "half_swipe_notifier": { + "notification_content_dm": "{friend} সবেমাত্র আপনার চ্যাটে {duration} সেকেন্ডের জন্য হাফ সোয়াইপ করেছেন", + "notification_content_group": "{friend} সবেমাত্র {group}-এ {duration} সেকেন্ডের জন্য হাফ সোয়াইপ করেছেন", + "notification_channel_name": "হাফ সোয়াইপ" + }, + "friend_menu_option": { + "preview": "পূর্বরূপ", + "mark_snaps_as_seen": "যেমন দেখা যায় তেমন স্ন্যাপগুলি চিহ্নিত করুন", + "anti_auto_save": "অ্যান্টি অটো সেভ", + "mark_stories_as_seen_locally": "স্থানীয়ভাবে দেখা হিসেবে গল্পগুলি চিহ্নিত করুন", + "auto_download_blacklist": "অটো ডাউনলোড ব্ল্যাকলিস্ট", + "stealth_mode": "স্টিলথ মোড" + }, + "chat_action_menu": { + "preview_button": "পূর্বরূপ", + "edit_message": "বার্তা সম্পাদনা করুন", + "convert_message": "বার্তা রূপান্তর করুন", + "download_button": "ডাউনলোড", + "delete_logged_message_button": "লগ করা বার্তা মুছে ফেলুন" + }, + "mark_as_seen": { + "seen_toast": "দেখা হিসেবে চিহ্নিত!", + "already_unseen_toast": "ইতিমধ্যে অদেখা হিসেবে চিহ্নিত!", + "unseen_toast": "অদেখা হিসেবে চিহ্নিত!", + "no_unseen_snaps_toast": "কোনো অদেখা স্ন্যাপ পাওয়া যায়নি!", + "already_seen_toast": "ইতিমধ্যে দেখা হিসেবে চিহ্নিত!" }, "biometric_auth": { - "unlock_button": "আনলক করুন", - "title": "Snapchat আনলক করুন", - "subtitle": "Snapchat আনলক করতে অনুগ্রহ করে প্রমাণীকরণ করুন" + "title": "স্ন্যাপচ্যাট আনলক করুন", + "subtitle": "স্ন্যাপচ্যাট আনলক করতে অনুগ্রহ করে প্রমাণীকরণ করুন", + "unlock_button": "আনলক করুন" }, - "end_to_end_encryption": { - "toolbox": { - "no_shared_key": "এই বন্ধুর সাথে আপনার এখনও কোনো শেয়ার করা গোপন কী নেই। একটি নতুন শুরু করতে নীচে ক্লিক করুন।", - "shared_key_fingerprint": "আপনার ফিঙ্গারপ্রিন্ট হল:\n\n{fingerprint}\n\nএটি আপনার বন্ধুর ফিঙ্গারপ্রিন্টের সাথে মেলে কিনা তা পরীক্ষা করতে ভুলবেন না!", - "initiate_exchange_button": "কী বিনিময় শুরু করুন" - }, - "confirmation_dialogs": { - "title": "এন্ড-টু-এন্ড এনক্রিপশন", - "confirmation_1": "সতর্কতা: এটি আপনার বিদ্যমান কী ওভাররাইট করবে। আপনি এই বন্ধুর কাছ থেকে সমস্ত এনক্রিপ্ট করা বার্তাগুলিতে অ্যাক্সেস হারাবেন। আপনি কি চালিয়ে যেতে নিশ্চিত?", - "confirmation_2": "আপনি কি সত্যিই চালিয়ে যেতে নিশ্চিত? এটি আপনার পিছিয়ে যাওয়ার শেষ সুযোগ।" - }, - "unencrypted_conversation_send_failure_toast": "আপনি এনক্রিপ্ট করা এবং অ-এনক্রিপ্ট করা উভয় কথোপকথনে এনক্রিপ্ট করা সামগ্রী পাঠাতে পারবেন না!", - "native_hooks_send_failure_toast": "পাঠাতে ব্যর্থ! অনুগ্রহ করে সেটিংসে নেটিভ হুক সক্ষম করুন।", - "no_participants_to_encrypt_toast": "এই কথোপকথনে আপনার কোনো বন্ধু নেই যার সাথে বার্তা এনক্রিপ্ট করা যাবে!", - "encryption_failed_toast": "বার্তা এনক্রিপ্ট করতে ব্যর্থ! আরও বিস্তারিত জানার জন্য logcat দেখুন।", - "accept_public_key_success_toast": "পাবলিক কী সফলভাবে গৃহীত হয়েছে!", - "accept_secret_key_success_toast": "সম্পন্ন! আপনি এখন এই বন্ধুর সাথে এনক্রিপ্ট করা বার্তা পাঠাতে এবং গ্রহণ করতে পারেন।", - "accept_public_key_failure_toast": "পাবলিক কী গ্রহণ করতে ব্যর্থ হয়েছে", - "accept_secret_key_failure_toast": "গোপন কী গ্রহণ করতে ব্যর্থ হয়েছে", - "accept_secret_button": "গোপন কী গ্রহণ করুন", - "accept_public_key_button": "পাবলিক কী গ্রহণ করুন", - "outgoing_pk_message": "কী বিনিময় অনুরোধ", - "outgoing_secret_message": "কী বিনিময় প্রতিক্রিয়া", - "incoming_pk_message": "আপনি এইমাত্র একটি পাবলিক কী অনুরোধ পেয়েছেন। এটি গ্রহণ করতে নীচে ক্লিক করুন।", - "incoming_secret_message": "আপনার বন্ধু এইমাত্র আপনার পাবলিক কী গ্রহণ করেছে। গোপন কী গ্রহণ করতে নীচে ক্লিক করুন।" + "gallery_media_send_override": { + "multiple_media_toast": "একসময়ে আপনি শুধু একটি মিডিয়া পাঠাতে পারেন" + }, + "opera_context_menu": { + "media_duration": "মিডিয়ার সময়কাল: {duration} ms", + "sent_at": "{date} এ পাঠানো হয়েছে", + "created_at": "{date} তারিখে তৈরি করা হয়েছে", + "expires_at": "{date} তারিখে মেয়াদ শেষ হয়", + "show_debug_info": "ডিবাগ তথ্য দেখান", + "download": "মিডিয়া ডাউনলোড করুন", + "media_size": "মিডিয়ার আকার: {size}" }, "auto_open_snaps": { "title": "স্বয়ংক্রিয়ভাবে স্ন্যাপ খুলুন", - "notification_content": "{count} টি স্ন্যাপ খোলা হয়েছে" - }, - "friend_mutation_observer": { - "notification_channel_name": "বন্ধু মিউটেশন পর্যবেক্ষক", - "friend_removed": "{username} আপনাকে বন্ধু হিসাবে সরিয়ে দিয়েছে", - "birthday_removed": "{username} তাদের জন্মদিন ({birthday}) সরিয়ে দিয়েছে", - "birthday_added": "{username} তাদের জন্মদিন ({birthday}) যোগ করেছে", - "birthday_changed": "{username} তাদের জন্মদিন {oldBirthday} থেকে {newBirthday}-এ পরিবর্তন করেছে", - "bitmoji_selfie_changed": "{username} তাদের বিটমোজি সেলফি পরিবর্তন করেছে", - "bitmoji_avatar_changed": "{username} তাদের বিটমোজি অবতার পরিবর্তন করেছে", - "bitmoji_background_changed": "{username} তাদের বিটমোজি পটভূমি পরিবর্তন করেছে", - "bitmoji_scene_changed": "{username} তাদের বিটমোজি দৃশ্য পরিবর্তন করেছে" - }, - "material3_strings": { - "date_range_picker_start_headline": "থেকে", - "date_range_picker_end_headline": "প্রতি", - "date_range_picker_title": "তারিখ পরিসীমা নির্বাচন করুন", - "date_picker_switch_to_calendar_mode": "ক্যালেন্ডার", - "date_picker_switch_to_input_mode": "ইনপুট", - "date_range_picker_scroll_to_previous_month": "পূর্ববর্তী মাস", - "date_range_picker_scroll_to_next_month": "পরবর্তী মাস", - "date_picker_today_description": "আজ", - "date_range_picker_day_in_range": "নির্বাচিত", - "date_input_invalid_for_pattern": "অবৈধ তারিখ", - "date_input_invalid_year_range": "অবৈধ বছর", - "date_input_invalid_not_allowed": "অবৈধ তারিখ", - "date_range_input_invalid_range_input": "অবৈধ তারিখ পরিসীমা" - }, - "send_override_dialog": { - "title": "{type} হিসাবে মিডিয়া পাঠান", - "duration": "সময়কাল: {duration}", - "saveable_snap_hint": "চ্যাটে স্ন্যাপ সংরক্ষণযোগ্য করুন", - "unlimited_duration": "সীমাহীন" - }, - "invalid_input_toast": "অবৈধ ইনপুট! নিশ্চিত করুন যে আপনি একটি বৈধ মান প্রবেশ করেছেন।" -} \ No newline at end of file + "notification_content": "{count} স্ন্যাপ খোলা হয়েছে" + } +} diff --git a/common/src/main/assets/lang/cs.json b/common/src/main/assets/lang/cs.json deleted file mode 100644 index 0b8be59d..00000000 --- a/common/src/main/assets/lang/cs.json +++ /dev/null @@ -1,2022 +0,0 @@ -{ - "setup": { - "dialogs": { - "select_language": "Vyberte jazyk", - "save_folder": "PurrfectSnap vyžaduje oprávnění k úložišti pro stahování a ukládání médií ze Snapchatu.\nVyberte prosím umístění, kam se mají média stahovat.", - "select_save_folder_button": "Vybrat složku" - }, - "mappings": { - "dialog": "Generování mapování, může to chvíli trvat...", - "generate_failure_no_snapchat": "PurrfectSnap nedokázal detekovat Snapchat, zkuste prosím přeinstalovat Snapchat.", - "generate_failure": "Při generování mapování došlo k chybě, zkuste to prosím znovu." - }, - "permissions": { - "dialog": "Pro pokračování musíte splnit následující požadavky:", - "notification_access": "Přístup k oznámením", - "battery_optimization": "Optimalizace baterie", - "display_over_other_apps": "Zobrazení přes ostatní aplikace", - "request_button": "Požádat" - } - }, - "scopes": { - "friend": "Přítel", - "group": "Skupina" - }, - "manager": { - "routes": { - "tasks": "Úlohy", - "features": "Funkce", - "manage_rule_feature": "Spravovat funkci pravidel", - "home": "Domů", - "home_settings": "Nastavení", - "home_logs": "Protokoly", - "logger_history": "Historie záznamů", - "logged_stories": "Zaznamenané příběhy", - "friend_tracker": "Sledování přátel", - "edit_rule": "Upravit pravidlo", - "file_imports": "Import souborů", - "manage_repos": "Spravovat repozitáře", - "social": "Sociální", - "manage_scope": "Spravovat rozsah", - "messaging_preview": "Náhled", - "scripts": "Skripty", - "better_location": "Lepší poloha" - }, - "sections": { - "home": { - "version_title": "v{versionName} · forkováno Eternalem", - "update_title": "Aktualizace PurrfectSnap", - "update_content": "Verze {version} je k dispozici!", - "update_button": "Stáhnout", - "debug_build_summary_title": "Spouštíte ladicí sestavení PurrfectSnap", - "debug_build_summary_content": "Verze {versionName} ({versionCode})", - "debug_build_summary_date": "Datum sestavení: {date} (před {days} dny)", - "quick_actions_title": "Rychlé akce", - "download_icon_description": "Stáhnout", - "completed_icon_description": "Dokončeno", - "failed_icon_description": "Selhalo", - "manage_quick_actions_description": "Spravovat rychlé akce", - "quick_actions_icon_description": "Rychlé akce", - "add_quick_action_description": "Přidat rychlou akci" - }, - "home_logs": { - "no_logs_hint": "Nejsou k dispozici žádné protokoly", - "clear_logs_button": "Vymazat protokoly", - "export_logs_button": "Exportovat protokoly", - "saving_logs_toast": "Ukládání protokolů, může to chvíli trvat...", - "saved_logs_success_toast": "Protokoly úspěšně uloženy", - "saved_logs_failure_toast": "Uložení protokolů se nezdařilo" - }, - "home_settings": { - "actions_title": "Akce", - "message_logger_title": "Záznamník zpráv", - "debug_title": "Ladění", - "success_toast": "Hotovo!", - "message_logger_summary": "{messageCount} zpráv\n{storyCount} příběhů", - "export_button": "Exportovat", - "clear_button": "Vymazat", - "view_logger_history_button": "Zobrazit historii záznamů", - "updates_title": "Aktualizace", - "auto_update_check": "Automaticky kontrolovat aktualizace", - "update_check_frequency": "Frekvence kontroly aktualizací", - "update_check_frequency_daily": "Denně", - "update_check_frequency_weekly": "Týdně", - "update_check_frequency_monthly": "Měsíčně", - "theme_icon_description": "Motiv", - "app_theme_title": "Motiv aplikace", - "theme_mode_system": "Systém", - "theme_mode_light": "Světlý", - "theme_mode_dark": "Tmavý", - "ui_settings_title": "Nastavení uživatelského rozhraní", - "haptic_feedback_label": "Haptická odezva", - "test_mode_label": "Testovací režim (POUZE PRO LADĚNÍ)", - "disable_feature_loading_label": "Zakázat načítání funkcí", - "disable_auto_mapper_label": "Zakázat automatické mapování", - "disable_bypass_indicator_label": "Zakázat indikátor obejití stavu", - "update_notification_channel_name": "Aktualizace PurrfectSnap", - "update_notification_channel_description": "Oznámení o aktualizacích PurrfectSnap", - "update_notification_title": "K dispozici je aktualizace PurrfectSnap", - "update_notification_text": "Verze %s je nyní k dispozici.", - "export_database_failed_toast": "Export databáze se nezdařil! {message}", - "clear_messages_failed_toast": "Vymazání zpráv se nezdařilo! {message}", - "clear_file_failed_toast": "Vymazání souboru se nezdařilo! {message}", - "debug_file_config": "Konfigurace", - "debug_file_mappings": "Mapování", - "debug_file_message_logger": "Záznamník zpráv", - "debug_file_pinned_best_friend": "Připnutý nejlepší přítel", - "debug_file_native_sig_cache": "Mezipaměť nativních podpisů" - }, - "tasks": { - "no_tasks": "Žádné úlohy", - "merge_button": "Sloučit", - "failed_to_open_file": "Otevření souboru se nezdařilo", - "merge_files_toast": "Slučování {count} souborů", - "remove_selected_tasks_title": "Opravdu chcete odstranit vybrané úkoly?", - "remove_all_tasks_title": "Opravdu chcete odstranit všechny úkoly?", - "delete_files_option": "Smazat také soubory", - "remove_selected_tasks_confirm": "Odstranit {count} úkolů?", - "remove_all_tasks_confirm": "Odstranit všechny úkoly?", - "clear_tasks_description": "Vymazat úkoly", - "file_not_found_icon_description": "Soubor nenalezen", - "image_icon_description": "Obrázek", - "video_icon_description": "Video", - "audio_icon_description": "Zvuk", - "file_icon_description": "Soubor", - "download_icon_description": "Stáhnout", - "chat_action_icon_description": "Akce chatu", - "cancel_icon_description": "Zrušit", - "success_icon_description": "Úspěch", - "failure_icon_description": "Selhání", - "cancelled_icon_description": "Zrušeno", - "task_status_failure": "Selhání", - "task_status_cancelled": "Zrušeno" - }, - "features": { - "disabled": "Zakázáno", - "export_option": "Exportovat", - "import_option": "Importovat", - "reset_option": "Resetovat", - "config_export_success_toast": "Konfigurace úspěšně exportována", - "config_import_success_toast": "Konfigurace úspěšně importována", - "config_import_failure_toast": "Import konfigurace se nezdařil {error}", - "config_export_failure_toast": "Export konfigurace se nezdařil {error}", - "saved_config_snackbar": "Konfigurace uložena", - "older_required": "Tato funkce vyžaduje pro správnou funkci Snapchat v{version} nebo starší", - "newer_required": "Tato funkce vyžaduje pro správnou funkci Snapchat v{version} nebo novější", - "search_button": "Hledat" - }, - "manage_rule_feature": { - "disable_state_option": "Zakázáno", - "disable_state_subtext": "Žádní přátelé/skupiny nebudou ovlivněni", - "whitelist_state_option": "Nikdo kromě...", - "whitelist_state_subtext": "Tímto pravidlem bude ovlivněno pouze {count} přátel/skupin", - "whitelist_state_button": "Vybrat povolené přátele/skupiny", - "blacklist_state_option": "Všichni kromě...", - "blacklist_state_subtext": "Tímto pravidlem budou ovlivněni všichni kromě {count} přátel/skupin", - "blacklist_state_button": "Vybrat vyloučené přátele/skupiny", - "clear_list_button": "Vymazat seznam přátel/skupin", - "dialog_clear_confirmation_text": "Opravdu chcete vymazat seznam?" - }, - "social": { - "friends_tab": "Přátelé", - "groups_tab": "Skupiny", - "empty_hint": "(prázdný)", - "streaks_expiration_short": "{hours}h" - }, - "manage_scope": { - "logged_stories_button": "Zobrazit zaznamenané příběhy", - "e2ee_title": "End-to-End šifrování", - "rules_title": "Pravidla", - "participants_text": "{count} účastníků", - "not_found": "Nenalezeno", - "streaks_title": "Série", - "streaks_length_text": "Délka: {length}", - "streaks_expiration_text": "Vyprší za {eta}", - "streaks_expiration_text_expired": "Vypršelo", - "reminder_button": "Nastavit připomenutí", - "delete_scope_confirm_dialog_title": "Opravdu chcete smazat {scope}?", - "notes_placeholder": "Kliknutím přidáte poznámku", - "invalid_key_size_32_bytes": "Neplatná velikost klíče (musí být 32 bajtů)", - "successfully_imported_key": "Klíč úspěšně importován", - "failed_to_import_key": "Import klíče se nezdařil: {message}", - "export_base64_button": "Exportovat Base64", - "import_base64_button": "Importovat Base64" - }, - "logged_stories": { - "story_failed_to_load": "Načtení příběhu se nezdařilo", - "no_stories": "Nebyly nalezeny žádné příběhy", - "save_from_cache_button": "Uložit z mezipaměti", - "downloaded_to_path": "Staženo do {path}", - "download_failed": "Stažení se nezdařilo: {message}", - "posted_at": "Zveřejněno {date}", - "created_at": "Vytvořeno {date}", - "failed_to_open_file": "Otevření souboru se nezdařilo. Zkontrolujte protokoly pro více informací", - "failed_to_get_file": "Načtení souboru se nezdařilo" - }, - "messaging_preview": { - "processed_messages_toast": "Zpracováno {count} zpráv", - "processed_messages_text": "Zpracováno {count} zpráv", - "close_button_description": "Zavřít", - "bridge_connection_failed": "Připojení k můstku se nezdařilo. Ujistěte se, že Snapchat běží na pozadí", - "bridge_init_failed": "Inicializace můstku pro zasílání zpráv se nezdařila. Ujistěte se, že Snapchat běží na pozadí", - "message_fetch_failed": "Načtení zpráv se nezdařilo", - "no_message_hint": "Žádná zpráva", - "save_selection_option": "Uložit výběr", - "save_all_option": "Uložit vše", - "unsave_selection_option": "Zrušit uložení výběru", - "unsave_all_option": "Zrušit uložení všeho", - "mark_selection_as_seen_option": "Označit vybrané jako přečtené", - "mark_all_as_seen_option": "Označit vše jako přečtené", - "delete_selection_option": "Smazat výběr", - "delete_all_option": "Smazat vše" - }, - "logger_history": { - "download_started_toast": "Stahování zahájeno!", - "download_success_toast": "Staženo do {path}", - "download_failed_toast": "Stažení {message} se nezdařilo", - "edited_at_text": "{message} (upraveno {date})", - "download_button": "Stáhnout", - "select_conversation_placeholder": "Vybrat konverzaci", - "close_button_description": "Zavřít", - "search_button_description": "Hledat", - "list_friend_format": "Přítel {name}", - "list_group_format": "Skupina {name}", - "no_more_messages": "Žádné další zprávy", - "reverse_order_checkbox": "Obrácené pořadí", - "chat_attachment": "Příloha {index}", - "empty_message": "Prázdná zpráva chatu", - "message_parse_failed": "Analýza zprávy se nezdařila", - "unknown_sender": "Neznámý odesílatel", - "download_attachment_failed_toast": "Stažení přílohy se nezdařilo", - "log_header_format": "{username} ({type}) - {date}" - }, - "file_imports": { - "import_file_button": "Importovat soubor", - "file_not_found": "Soubor nenalezen", - "file_import_failed": "Import souboru se nezdařil: {error}", - "file_imported": "Soubor úspěšně importován", - "file_delete_failed": "Smazání souboru se nezdařilo", - "no_files_hint": "Zde můžete importovat soubory pro použití ve Snapchatu. Stisknutím tlačítka níže importujete soubor." - }, - "better_location": { - "spoofed_coordinates_title": "Zem. šířka {latitude}, Zem. délka {longitude}", - "save_coordinates_dialog_title": "Uložit souřadnice", - "saved_name_dialog_hint": "Uložený název", - "latitude_dialog_hint": "Zeměpisná šířka", - "longitude_dialog_hint": "Zeměpisná délka", - "save_dialog_button": "Uložit", - "choose_location_button": "Vybrat polohu", - "teleport_to_friend_button": "Teleportovat se k příteli", - "spoof_location_toggle": "Falšovat polohu", - "suspend_location_updates": "Pozastavit aktualizace polohy", - "saved_coordinates_title": "Uložené souřadnice", - "no_saved_coordinates_hint": "Žádné uložené souřadnice", - "delete_dialog_title": "Smazat uložené souřadnice", - "delete_dialog_message": "Opravdu chcete smazat tyto uložené souřadnice?", - "teleport_to_friend_title": "Teleportovat se k příteli", - "search_bar": "Hledat", - "no_friends_map": "Na mapě nejsou žádní přátelé", - "no_friends_found": "Nebyly nalezeny žádné přátele", - "edit_location_button_description": "Upravit polohu", - "add_icon_description": "Přidat", - "edit_icon_description": "Upravit", - "delete_icon_description": "Smazat" - } - }, - "dialogs": { - "add_friend": { - "title": "Přidat přítele nebo skupinu", - "search_hint": "Hledat", - "fetch_error": "Načtení dat se nezdařilo", - "category_groups": "Skupiny", - "category_friends": "Přátelé", - "participants_text": "{count} účastníků", - "search_icon_description": "Hledat" - }, - "scripting_warning": { - "title": "Varování", - "content": "PurrfectSnap obsahuje skriptovací nástroj, který umožňuje spouštění uživatelsky definovaného kódu na vašem zařízení. Buďte extrémně opatrní a instalujte moduly pouze ze známých a spolehlivých zdrojů. Neoprávněné nebo neověřené moduly mohou představovat bezpečnostní rizika pro váš systém." - }, - "reset_config": { - "title": "Resetovat konfiguraci", - "content": "Opravdu chcete resetovat konfiguraci?", - "success_toast": "Konfigurace úspěšně resetována" - }, - "export_config": { - "title": "Exportovat citlivá data?", - "content": "Chcete exportovat konfiguraci s citlivými daty? (např. souřadnice polohy atd.)" - }, - "messaging_action": { - "title": "Vyberte typy obsahu ke zpracování", - "select_all_button": "Vybrat vše" - }, - "file_imports": { - "no_files_settings_hint": "Nebyly nalezeny žádné soubory. Ujistěte se, že jste importovali požadované soubory v sekci Import souborů", - "settings_select_file_hint": "Vybrat importovaný soubor" - }, - "quick_actions_dialog": { - "title": "Upravit rychlé akce", - "subtitle": "Vyberte a změňte velikost svých rychlých akcí." - } - }, - "friend_tracker": { - "rules_tab": "Pravidla", - "logs_tab": "Protokoly", - "export_dialog_title": "Exportovat", - "bulk_export_button": "Hromadný export", - "individual_export_button": "Individuální export", - "invalid_import_type_dialog_title": "Neplatný typ importu", - "invalid_import_type_dialog_text": "Vybraný soubor není kompatibilní s tímto typem importu. Vyberte prosím správný typ importu.", - "import_dialog_title": "Importovat", - "bulk_import_button": "Hromadný import", - "individual_import_button": "Individuální import", - "import_button_description": "Importovat", - "export_button_description": "Exportovat", - "export_button": "Exportovat", - "delete_button_description": "Smazat", - "delete_button": "Smazat", - "catalog_button_description": "Katalog", - "catalog_button": "Katalog", - "add_rule_button_description": "Přidat pravidlo", - "add_rule_button": "Přidat pravidlo", - "no_rules_found": "Nebyly nalezeny žádné pravidla", - "empty_rule_name": "(prázdný)", - "events_suffix": "události", - "scopes_suffix": "rozsahy", - "select_rule_to_export_title": "Vybrat pravidlo k exportu", - "deleted_logs_toast": "Smazáno {count} protokolů", - "delete_logs_dialog_title": "Smazat protokoly?", - "deleting_logs_dialog_text": "Mazání {count} protokolů...", - "delete_logs_dialog_confirm_text": "Tímto se smažou protokoly na základě aktuálního filtru a vyhledávacího dotazu. Tuto akci nelze vrátit zpět.", - "exported_logs_toast": "Protokoly exportovány!", - "export_logs_failed_toast": "Export protokolů se nezdařil. Zkontrolujte logcat pro více podrobností.", - "export_logs_dialog_title": "Exportovat protokoly?", - "exporting_logs_dialog_text": "Exportování protokolů...", - "export_logs_dialog_confirm_text": "Tímto se exportují protokoly na základě aktuálního filtru a vyhledávacího dotazu.", - "export_as_button": "Exportovat jako {type}", - "filters_title": "Filtry", - "search_by_label": "Hledat podle", - "newest_first_label": "Nejnovější první", - "since_label": "Od", - "until_label": "Do", - "pick_a_date_button": "Vybrat datum", - "search_placeholder": "Hledat", - "filter_button_description": "Filtr", - "clear_button_description": "Vymazat", - "no_logs_found": "Nebyly nalezeny žádné protokoly", - "log_event_format": "{event} v {conversation}", - "condition_only_inside_conversation": "Pouze když jsem v konverzaci", - "condition_only_outside_conversation": "Pouze když jsem mimo konverzaci", - "condition_only_when_app_active": "Pouze když je Snapchat aktivní", - "condition_only_when_app_inactive": "Pouze když je Snapchat neaktivní", - "condition_no_push_notification_when_app_active": "Žádné push oznámení, když je Snapchat aktivní", - "add_event_dialog_title": "Přidat událost", - "event_type_label": "Typ události", - "triggers_title": "Spouštěče", - "conditions_title": "Podmínky", - "add_button": "Přidat", - "default_rule_name": "Vlastní pravidlo", - "discard_changes_dialog_title": "Zahodit změny?", - "discard_changes_dialog_text": "Máte neuložené změny. Opravdu je chcete zahodit?", - "discard_button": "Zahodit", - "cannot_save_rule_dialog_title": "Nelze uložit pravidlo", - "cannot_save_rule_dialog_text": "Pravidlo musí mít alespoň jednu událost, aby se dalo uložit.", - "duplicate_rule_name_dialog_title": "Duplicitní název pravidla", - "duplicate_rule_name_dialog_text": "Pravidlo s tímto názvem již existuje. Vyberte prosím jiný název.", - "delete_rule_dialog_title": "Smazat pravidlo", - "delete_rule_dialog_text": "Opravdu chcete smazat toto pravidlo?", - "new_rule_title": "Nové pravidlo", - "edit_rule_title": "Upravit pravidlo", - "back_button_description": "Zpět", - "save_button_description": "Uložit", - "general_section_title": "Obecné", - "rule_name_label": "Název pravidla", - "author_name_label": "Jméno autora", - "scope_section_title": "Rozsah", - "scope_all": "Vše", - "scope_whitelist": "Whitelist", - "scope_blacklist": "Černá listina", - "select_friends_groups_button": "Vybrat přátele/skupiny ({count})", - "events_section_title": "Události", - "add_event_button": "Přidat událost", - "no_events_text": "Žádné události" - }, - "friend_tracker_catalog": { - "download_failed": "Stažení se nezdařilo: {code}", - "error": "Chyba: {message}", - "no_repos_added": "Nebyly přidány žádné repozitáře.", - "no_rules_available": "Z žádného repozitáře nejsou k dispozici žádná pravidla.", - "by_author": "od {author}", - "imported_button": "Importováno", - "import_button": "Importovat", - "title": "Katalog sledování přátel", - "manage_repos_description": "Spravovat repozitáře" - }, - "friend_tracker_export": { - "title": "Exportovat pravidla", - "back_button_description": "Zpět", - "exported_toast": "Pravidla sledování přátel exportována!", - "export_failed_toast": "Export pravidel se nezdařil: {message}", - "save_button": "Uložit", - "expand_button_description": "Rozbalit" - }, - "friend_tracker_import": { - "title": "Importovat pravidla", - "back_button_description": "Zpět", - "imported_toast": "Pravidla sledování přátel importována!", - "import_failed_toast": "Import pravidel se nezdařil: {message}", - "confirm_button": "Potvrdit", - "expand_button_description": "Rozbalit" - }, - "friend_tracker_repos": { - "invalid_repo_title": "Neplatný repozitář", - "add_repo_button": "Přidat repozitář", - "add_repo_dialog_title": "Přidat URL repozitáře", - "repo_url_label": "URL repozitáře", - "repo_added_toast": "Repozitář úspěšně přidán!", - "invalid_repo_error": "Toto se nezdá být platným repozitářem skriptů.", - "add_repo_failed_toast": "Přidání repozitáře se nezdařilo: {message}", - "add_button": "Přidat", - "no_repos_added": "Nebyly přidány žádné repozitáře", - "remove_button": "Odstranit", - "remove_repo_dialog_title": "Odstranit repozitář", - "remove_repo_dialog_text": "Opravdu chcete odstranit tento repozitář?" - }, - "navigation": { - "tracker_tab_label": "Sledovač", - "customize_bottom_bar_title": "Přizpůsobit spodní lištu", - "customize_bottom_bar_subtitle": "Změňte pořadí, přidejte nebo odeberte karty. Maximálně pět.", - "shown_tabs_title": "Zobrazené karty", - "no_tabs_selected_text": "Nebyly vybrány žádné karty", - "available_tabs_title": "Dostupné karty", - "reset_button": "Resetovat", - "done_button": "Hotovo" - }, - "scripting": { - "script_already_installed": "Skript je již nainstalován!", - "downloading_script": "Stahování skriptu...", - "script_downloaded": "Skript {name} stažen!", - "download_script_failed": "Stažení skriptu se nezdařilo. Zkontrolujte protokoly pro více podrobností", - "import_script_from_url_title": "Importovat skript z URL", - "import_script_warning": "Varování: Importované skripty mohou být škodlivé pro vaše zařízení. Importujte skripty pouze z důvěryhodných zdrojů.", - "enter_url_label": "Zadejte URL zde:", - "script_imported": "Skript {name} importován!", - "import_failed": "Import skriptu se nezdařil. {message}. Zkontrolujte protokoly pro více podrobností", - "import_button": "Importovat", - "update_module_button": "Aktualizovat modul", - "updating_script": "Aktualizace skriptu {name}...", - "module_not_found": "Modul nenalezen", - "updated_script": "{name} aktualizován na verzi {version}", - "update_module_failed": "Aktualizace modulu se nezdařila. Zkontrolujte protokoly pro více podrobností", - "edit_module_button": "Upravit modul", - "open_module_failed": "Otevření souboru modulu se nezdařilo. Zkontrolujte protokoly pro více podrobností", - "clear_module_data_button": "Vymazat data modulu", - "module_data_cleared": "Data modulu vymazána!", - "clear_module_data_failed": "Vymazání dat modulu se nezdařilo. Zkontrolujte protokoly pro více podrobností", - "delete_module_button": "Smazat modul", - "deleted_script": "Smazán skript {name}!", - "delete_module_failed": "Smazání modulu se nezdařilo. Zkontrolujte protokoly pro více podrobností", - "actions_title": "Akce", - "no_description": "Žádný popis", - "update_available": "K dispozici je aktualizace: {version}", - "actions_button": "Akce", - "loaded_script": "Načten skript {name}", - "unloaded_script": "Uvolněn skript {name}", - "enable_script_failed": "Povolení skriptu se nezdařilo. Zkontrolujte protokoly pro více podrobností", - "disable_script_failed": "Zakázání skriptu se nezdařilo. Zkontrolujte protokoly pro více podrobností", - "select_scripts_folder_toast": "Vyberte prosím složku se skripty!", - "manage_repos_button": "Spravovat repozitáře", - "import_from_url_button": "Importovat z URL", - "open_scripts_folder_button": "Otevřít složku se skripty", - "no_settings_for_module": "Tento modul nemá žádná nastavení", - "installed_scripts_tab": "Nainstalované skripty", - "catalog_tab": "Katalog", - "no_scripts_folder_selected_title": "Není vybrána žádná složka se skripty", - "select_folder_button": "Vybrat složku", - "no_scripts_found_title": "Nebyly nalezeny žádné skripty.", - "use_catalog_to_add_scripts": "Použijte kartu katalogu k přidání skriptů!", - "ok_button_timeout": "Dobře ({timeout})", - "documentation_button": "Dokumentace", - "catalog": { - "script_already_installed": "Skript je již nainstalován!", - "download_failed": "Stažení se nezdařilo: {code}", - "script_downloaded": "Skript stažen!", - "could_not_create_file": "Nelze vytvořit soubor.", - "no_scripts_folder_selected": "Není vybrána žádná složka se skripty.", - "error": "Chyba: {message}", - "no_repos_added": "Nebyly přidány žádné repozitáře.", - "repo_list_info": "Zde naleznete seznam repozitářů: ", - "link_text": "Odkaz", - "no_scripts_available": "Z žádného repozitáře nejsou k dispozici žádné skripty.", - "by_author": "od {author}", - "version": "Verze: {version}", - "installed_button": "Nainstalováno", - "download_button": "Stáhnout" - }, - "repos": { - "invalid_repo_title": "Neplatný repozitář", - "add_repo_button": "Přidat repozitář", - "add_repo_dialog_title": "Přidat URL repozitáře", - "repo_url_label": "URL repozitáře", - "repo_added_toast": "Repozitář úspěšně přidán!", - "invalid_repo_error": "Toto se nezdá být platným repozitářem skriptů.", - "add_repo_failed_toast": "Přidání repozitáře se nezdařilo: {message}", - "add_button": "Přidat", - "no_repos_added": "Nebyly přidány žádné repozitáře", - "remove_button": "Odstranit", - "remove_repo_dialog_title": "Odstranit repozitář", - "remove_repo_dialog_text": "Opravdu chcete odstranit tento repozitář?" - } - }, - "features": { - "config_import": { - "title": "Potvrdit import", - "back_button_description": "Zpět", - "config_imported_toast": "Konfigurace importována!", - "confirm_button": "Potvrdit", - "expand_button_description": "Rozbalit", - "enable_feature": "Povolit funkci", - "enabled": "Povoleno", - "disabled": "Zakázáno" - }, - "config_export": { - "title": "Souhrn exportu", - "back_button_description": "Zpět", - "save_button": "Uložit", - "expand_button_description": "Rozbalit", - "enable_feature": "Povolit funkci", - "enabled": "Povoleno", - "disabled": "Zakázáno" - } - }, - "manage_repos": { - "title": "Spravovat repozitáře {type}", - "add_repo_button": "Přidat repozitář", - "add_repo_dialog_title": "Přidat URL repozitáře", - "repo_url_label": "URL repozitáře", - "repo_added_successfully": "Repozitář úspěšně přidán!", - "add_repo_failed": "Přidání repozitáře se nezdařilo: {message}", - "add_button": "Přidat", - "no_repos_added": "Nebyly přidány žádné repozitáře", - "remove_button": "Odstranit" - } - }, - "rules": { - "toasts": { - "enabled": "{ruleName} povoleno", - "disabled": "{ruleName} zakázáno" - }, - "modes": { - "blacklist": "Režim blacklistu", - "whitelist": "Režim whitelistu" - }, - "properties": { - "auto_download": { - "name": "Automatické stahování", - "description": "Automaticky stahovat snapy při jejich prohlížení", - "options": { - "blacklist": "Vyloučit z automatického stahování", - "whitelist": "Automatické stahování" - } - }, - "stealth": { - "name": "Stealth režim", - "description": "Zabraňuje komukoli vědět, že jste otevřeli jejich snapy/chaty a konverzace", - "options": { - "blacklist": "Vyloučit ze Stealth režimu", - "whitelist": "Stealth režim" - } - }, - "auto_save": { - "name": "Automatické ukládání", - "description": "Ukládá zprávy chatu při jejich prohlížení", - "options": { - "blacklist": "Vyloučit z automatického ukládání", - "whitelist": "Automatické ukládání" - } - }, - "unsaveable_messages": { - "name": "Neuložitelné zprávy", - "description": "Zabraňuje ukládání zpráv v chatu jinými lidmi", - "options": { - "blacklist": "Vyloučit z neuložitelných zpráv", - "whitelist": "Neuložitelné zprávy" - } - }, - "auto_open_snaps": { - "name": "Automaticky otevírat snapy", - "description": "Automaticky otevírá snapy při jejich přijetí", - "options": { - "blacklist": "Vyloučit z automatického otevírání snapů", - "whitelist": "Automaticky otevírat snapy" - } - }, - "hide_friend_feed": { - "name": "Skrýt z kanálu přátel" - }, - "e2e_encryption": { - "name": "Použít E2E šifrování" - }, - "pin_conversation": { - "name": "Připnout konverzaci" - }, - "exclude_message_logger": { - "name": "Vyloučit ze záznamníku zpráv" - } - } - }, - "actions": { - "clean_snapchat_cache": { - "name": "Vyčistit mezipaměť Snapchatu", - "description": "Vyčistí mezipaměť Snapchatu" - }, - "manage_friend_list": { - "name": "Spravovat seznam přátel", - "description": "Import/export seznamu přátel při zálohování" - }, - "export_chat_messages": { - "name": "Exportovat zprávy chatu", - "description": "Exportuje zprávy konverzace do souboru JSON/HTML/TXT" - }, - "export_memories": { - "name": "Exportovat vzpomínky", - "description": "Exportuje vzpomínky do souboru ZIP" - }, - "bulk_messaging_action": { - "name": "Hromadná akce zasílání zpráv", - "description": "Provádí operace jako mazání přátel nebo hromadné mazání konverzací" - }, - "regen_mappings": { - "name": "Znovu vygenerovat mapování", - "description": "Ručně znovu vygenerovat mapování" - }, - "change_language": { - "name": "Změnit jazyk", - "description": "Změnit jazyk PurrfectSnap" - }, - "file_imports": { - "name": "Import souborů", - "description": "Importovat soubory pro použití ve Snapchatu" - }, - "friend_tracker": { - "name": "Sledování přátel", - "description": "Sledovat své přátele na Snapchatu" - }, - "logger_history": { - "name": "Historie záznamů", - "description": "Zobrazit historii zaznamenaných zpráv" - } - }, - "features": { - "notices": { - "unstable": "⚠️ Nestabilní", - "ban_risk": "⚠️ Tato funkce může způsobit zákazy", - "internal_behavior": "⚠️ Toto může narušit interní chování Snapchatu" - }, - "properties": { - "downloader": { - "name": "Stahovač", - "description": "Stahovat média Snapchatu", - "properties": { - "save_folder": { - "name": "Složka pro ukládání", - "description": "Vyberte adresář, do kterého se mají stahovat všechna média" - }, - "auto_download_sources": { - "name": "Zdroje automatického stahování", - "description": "Vyberte zdroje, ze kterých se má automaticky stahovat" - }, - "prevent_self_auto_download": { - "name": "Zabránit vlastnímu automatickému stahování", - "description": "Zabraňuje automatickému stahování vašich vlastních snapů" - }, - "path_format": { - "name": "Formát cesty", - "description": "Zadejte formát cesty k souboru" - }, - "allow_duplicate": { - "name": "Povolit duplikáty", - "description": "Umožňuje stahovat stejná média vícekrát" - }, - "merge_overlays": { - "name": "Sloučit překryvy", - "description": "Kombinuje text a média snapu do jednoho souboru" - }, - "force_image_format": { - "name": "Vynutit formát obrázku", - "description": "Vynutí ukládání obrázků v zadaném formátu" - }, - "force_voice_note_format": { - "name": "Vynutit formát hlasové poznámky", - "description": "Vynutí ukládání hlasových poznámek v zadaném formátu" - }, - "auto_download_voice_notes": { - "name": "Automaticky stahovat hlasové poznámky", - "description": "Automaticky stahuje hlasové poznámky při jejich přehrávání" - }, - "download_profile_pictures": { - "name": "Stahovat profilové obrázky", - "description": "Umožňuje stahovat profilové obrázky z profilové stránky" - }, - "opera_download_button": { - "name": "Tlačítko stahování Opera", - "description": "Přidá tlačítko stahování v pravém horním rohu při prohlížení snapu.\nDlouhým stisknutím tlačítek se vynutí stahování" - }, - "download_context_menu": { - "name": "Kontextové menu stahování", - "description": "Umožňuje stahovat/prohlížet zprávy z konverzace nebo příběhu pomocí kontextového menu.\nDlouhým stisknutím tlačítek se vynutí stahování" - }, - "ffmpeg_options": { - "name": "Možnosti FFmpeg", - "description": "Zadejte další možnosti FFmpeg", - "properties": { - "threads": { - "name": "Vlákna", - "description": "Počet vláken k použití" - }, - "preset": { - "name": "Přednastavení", - "description": "Nastavte rychlost převodu" - }, - "constant_rate_factor": { - "name": "Faktor konstantní rychlosti", - "description": "Nastavte faktor konstantní rychlosti pro video kodér\nOd 0 do 51 pro libx264" - }, - "video_bitrate": { - "name": "Video bitrate", - "description": "Nastavte video bitrate (kbps)" - }, - "audio_bitrate": { - "name": "Audio bitrate", - "description": "Nastavte audio bitrate (kbps)" - }, - "custom_video_codec": { - "name": "Vlastní video kodek", - "description": "Nastavte vlastní video kodek (např. libx264)" - }, - "custom_audio_codec": { - "name": "Vlastní audio kodek", - "description": "Nastavte vlastní audio kodek (např. AAC)" - } - } - }, - "logging": { - "name": "Protokolování", - "description": "Zobrazuje toasty při stahování médií" - }, - "custom_path_format": { - "name": "Vlastní formát cesty", - "description": "Zadejte vlastní formát cesty pro stažená média\n\nDostupné proměnné:\n - %username%\n - %source%\n - %hash%\n - %date_time%" - } - } - }, - "user_interface": { - "name": "Uživatelské rozhraní", - "description": "Změnit vzhled a dojem Snapchatu", - "properties": { - "enable_app_appearance": { - "name": "Povolit nastavení vzhledu aplikace", - "description": "Povolí skryté nastavení vzhledu aplikace\nNemusí být vyžadováno v novějších verzích Snapchatu" - }, - "friend_feed_message_preview": { - "name": "Náhled zprávy v kanálu přátel", - "description": "Zobrazí náhled posledních zpráv v kanálu přátel", - "properties": { - "amount": { - "name": "Množství", - "description": "Množství zpráv k náhledu" - } - } - }, - "snap_preview": { - "name": "Náhled snapu", - "description": "Zobrazí malý náhled vedle nepřečtených snapů v chatu" - }, - "bootstrap_override": { - "name": "Přepsání bootstrapu", - "description": "Přepíše nastavení bootstrapu uživatelského rozhraní", - "properties": { - "app_appearance": { - "name": "Vzhled aplikace", - "description": "Nastaví trvalý vzhled aplikace" - }, - "home_tab": { - "name": "Karta Domů", - "description": "Přepíše úvodní kartu při otevření Snapchatu" - } - } - }, - "force_amoled_theme": { - "name": "Tmavý režim Amoled", - "description": "Používá skutečně černé pozadí pro tmavý motiv" - }, - "map_friend_nametags": { - "name": "Vylepšené jmenovky přátel na mapě", - "description": "Vylepšuje jmenovky přátel na Snapmapě" - }, - "prevent_message_list_auto_scroll": { - "name": "Zabránit automatickému posouvání seznamu zpráv", - "description": "Zabraňuje posouvání seznamu zpráv dolů při odesílání/přijímání zprávy" - }, - "streak_expiration_info": { - "name": "Zobrazit informace o vypršení série", - "description": "Zobrazí časovač vypršení série vedle počítadla sérií" - }, - "hide_friend_feed_entry": { - "name": "Skrýt položku v kanálu přátel", - "description": "Skryje konkrétního přítele z kanálu přátel\nPro správu této funkce použijte sociální kartu" - }, - "hide_streak_restore": { - "name": "Skrýt obnovení série", - "description": "Skryje tlačítko Obnovit v kanálu přátel" - }, - "hide_quick_add_suggestions": { - "name": "Skrýt návrhy rychlého přidání", - "description": "Odstraní návrhy rychlého přidání přátel" - }, - "hide_story_suggestions": { - "name": "Skrýt návrhy příběhů", - "description": "Odstraní návrhy ze stránky Příběhy" - }, - "hide_ui_components": { - "name": "Skrýt komponenty uživatelského rozhraní", - "description": "Vyberte, které komponenty uživatelského rozhraní se mají skrýt" - }, - "opera_media_quick_info": { - "name": "Rychlé informace o médiích Opera", - "description": "Zobrazuje užitečné informace o médiích, jako je datum vytvoření, v kontextovém menu prohlížeče opera" - }, - "old_bitmoji_selfie": { - "name": "Staré selfie Bitmoji", - "description": "Vrací selfie Bitmoji ze starších verzí Snapchatu" - }, - "disable_spotlight": { - "name": "Zakázat Spotlight", - "description": "Zakáže stránku Spotlight" - }, - "friend_feed_menu_buttons": { - "name": "Tlačítka menu kanálu přátel", - "description": "Vyberte, která tlačítka se mají zobrazit v menu kanálu přátel" - }, - "auto_close_friend_feed_menu": { - "name": "Automaticky zavřít menu kanálu přátel", - "description": "Automaticky zavře menu kanálu přátel po stisknutí tlačítka nastavení" - }, - "vertical_story_viewer": { - "name": "Vertikální prohlížeč příběhů", - "description": "Povolí vertikální prohlížeč příběhů pro všechny příběhy" - }, - "enable_friend_feed_menu_bar": { - "name": "Lišta menu kanálu přátel", - "description": "Povolí novou lištu menu kanálu přátel" - }, - "message_indicators": { - "name": "Indikátory zpráv", - "description": "Přidá ke zprávám specifické ikony indikátorů\nPoznámka: Indikátory nemusí být 100% přesné" - }, - "stealth_mode_indicator": { - "name": "Indikátor stealth režimu", - "description": "Přidá emotikon 👻 vedle konverzací v stealth režimu" - }, - "edit_text_override": { - "name": "Přepsání úpravy textu", - "description": "Přepíše chování textového pole" - }, - "prevent_forced_keyboard": { - "name": "Zabránit vynucené klávesnici", - "description": "Zabraňuje Snapchatu automaticky zobrazovat klávesnici při otevření konverzace" - }, - "settings_menu": { - "name": "Menu nastavení", - "description": "Změní způsob, jakým otevíráte menu PurrfectSnap", - "options": { - "default": "Výchozí", - "legacy": "Starší" - } - } - } - }, - "messaging": { - "name": "Zasílání zpráv", - "description": "Změnit způsob interakce s přáteli", - "properties": { - "bypass_screenshot_detection": { - "name": "Obejít detekci snímků obrazovky", - "description": "Zabraňuje Snapchatu detekovat pořízení snímku obrazovky" - }, - "anonymous_story_viewing": { - "name": "Anonymní prohlížení příběhů", - "description": "Zabraňuje komukoli vědět, že jste viděli jejich příběh" - }, - "prevent_story_rewatch_indicator": { - "name": "Zabránit indikátoru opětovného zhlédnutí příběhu", - "description": "Zabraňuje komukoli vědět, že jste znovu zhlédli jejich příběh" - }, - "hide_peek_a_peek": { - "name": "Skrýt Peek-a-Peek", - "description": "Zabraňuje odesílání oznámení, když se napůl přejedete do chatu" - }, - "hide_bitmoji_presence": { - "name": "Skrýt přítomnost Bitmoji", - "description": "Zabraňuje zobrazování vašeho Bitmoji v chatu" - }, - "hide_typing_notifications": { - "name": "Skrýt oznámení o psaní", - "description": "Zabraňuje komukoli vědět, že píšete zprávu" - }, - "unlimited_snap_view_time": { - "name": "Neomezená doba prohlížení snapu", - "description": "Odstraňuje časový limit pro prohlížení snapů" - }, - "auto_mark_as_read": { - "name": "Automaticky označit jako přečtené", - "description": "Automaticky označí zprávy/snapy jako přečtené, i když je povolen Stealth režim" - }, - "mark_snap_as_seen_button": { - "name": "Tlačítko Označit snap jako přečtený", - "description": "Přidá tlačítko pro označení snapu jako přečteného při jeho prohlížení.\nTo bude fungovat i v Stealth režimu" - }, - "skip_when_marking_as_seen": { - "name": "Přeskočit při označování jako přečtené", - "description": "Automaticky přeskočí na další snap při označování snapu jako přečteného.\nPoužijte v kombinaci s tlačítkem Označit snap jako přečtený" - }, - "loop_media_playback": { - "name": "Smyčka přehrávání médií", - "description": "Smyčkuje přehrávání médií při prohlížení snapů/příběhů" - }, - "disable_replay_in_ff": { - "name": "Zakázat opakované přehrávání v FF", - "description": "Zakáže možnost opakovaného přehrávání dlouhým stisknutím z kanálu přátel" - }, - "half_swipe_notifier": { - "name": "Oznámení o polovičním přejetí", - "description": "Upozorní vás, když někdo napůl přejede do konverzace", - "properties": { - "min_duration": { - "name": "Minimální doba trvání", - "description": "Minimální doba trvání polovičního přejetí (v sekundách)" - }, - "max_duration": { - "name": "Maximální doba trvání", - "description": "Maximální doba trvání polovičního přejetí (v sekundách)" - } - } - }, - "call_start_confirmation": { - "name": "Potvrzení zahájení hovoru", - "description": "Zobrazí potvrzovací dialog při zahájení hovoru" - }, - "unlimited_conversation_pinning": { - "name": "Neomezené připínání konverzací", - "description": "Umožňuje připnout neomezené množství konverzací lokálně" - }, - "disable_snap_mode_restrictions": { - "name": "Zakázat omezení režimu Snap", - "description": "Umožňuje prohlížet samodestrukční snapy bez omezení" - }, - "prevent_message_sending": { - "name": "Zabránit odesílání zpráv", - "description": "Zabraňuje odesílání určitých typů zpráv" - }, - "friend_mutation_notifier": { - "name": "Oznámení o mutaci přítele", - "description": "Upozorní vás, když se něco změní v profilu přítele" - }, - "better_notifications": { - "name": "Lepší oznámení", - "description": "Přidá více informací do přijatých oznámení", - "properties": { - "group_notifications": { - "name": "Skupinová oznámení", - "description": "Seskupí oznámení do jednoho" - }, - "chat_preview": { - "name": "Náhled chatu", - "description": "Zobrazí náhled přijatých zpráv v oznámení" - }, - "media_preview": { - "name": "Náhled médií", - "description": "Zobrazí náhled vybraných typů médií v oznámení" - }, - "media_caption": { - "name": "Popisek médií", - "description": "Zobrazí připojený popisek médií v oznámení" - }, - "stacked_media_messages": { - "name": "Skládané mediální zprávy", - "description": "Kombinuje více mediálních zpráv do jednoho textového oznámení, když je nelze zobrazit v náhledu. Použijte v kombinaci s náhledem chatu" - }, - "friend_add_source": { - "name": "Zdroj přidání přítele", - "description": "Zobrazí zdroj žádosti o přátelství v oznámení" - }, - "reply_button": { - "name": "Tlačítko Odpovědět", - "description": "Přidá tlačítko odpovědi do oznámení" - }, - "smart_replies": { - "name": "Chytré odpovědi", - "description": "Přidá navrhované odpovědi do oznámení (Android 10+). Použijte v kombinaci s tlačítkem Odpovědět" - }, - "download_button": { - "name": "Tlačítko Stáhnout", - "description": "Umožňuje stahovat média z oznámení" - }, - "mark_as_read_button": { - "name": "Tlačítko Označit jako přečtené", - "description": "Umožňuje označit zprávu jako přečtenou z oznámení" - }, - "mark_as_read_and_save_in_chat": { - "name": "Označit jako přečtené a uložit v chatu", - "description": "Přidá tlačítko označit jako přečtené a uložit v chatu do oznámení" - } - } - }, - "notification_blacklist": { - "name": "Blacklist oznámení", - "description": "Vyberte oznámení, která se mají blokovat" - }, - "message_logger": { - "name": "Záznamník zpráv", - "description": "Zabraňuje mazání zpráv", - "properties": { - "keep_my_own_messages": { - "name": "Ponechat mé vlastní zprávy", - "description": "Zabraňuje mazání vašich vlastních zpráv" - }, - "auto_purge": { - "name": "Automatické čištění", - "description": "Automaticky maže zprávy v mezipaměti, které jsou starší než zadaná doba" - }, - "message_filter": { - "name": "Filtr zpráv", - "description": "Vyberte, které zprávy se mají zaznamenávat (prázdný pro všechny zprávy)" - }, - "deleted_message_color": { - "name": "Barva smazané zprávy", - "description": "Nastaví barvu smazaných zpráv" - } - } - }, - "auto_save_messages_in_conversations": { - "name": "Automaticky ukládat zprávy", - "description": "Automaticky ukládá každou zprávu v konverzacích" - }, - "gallery_media_send_override": { - "name": "Přepsání odeslání médií z galerie", - "description": "Falšuje zdroj médií při odesílání z galerie" - }, - "strip_media_metadata": { - "name": "Odstranit metadata médií", - "description": "Odstraní metadata médií před odesláním jako zprávy" - }, - "bypass_message_retention_policy": { - "name": "Obejít zásady uchovávání zpráv", - "description": "Zabraňuje mazání zpráv po jejich zhlédnutí" - }, - "bypass_message_action_restrictions": { - "name": "Obejít omezení akcí se zprávami", - "description": "Umožňuje reagovat na snap, aniž byste ho otevřeli, nebo uložit neuložitelnou zprávu" - }, - "remove_groups_locked_status": { - "name": "Odstranit stav uzamčení skupin", - "description": "Umožňuje zobrazit informace o skupině po vyhození" - }, - "double_tap_chat_action": { - "name": "Akce dvojitého klepnutí v chatu", - "description": "Provádí vlastní akci při dvojitém klepnutí na zprávu v chatu" - }, - "double_tap_chat_action_custom_emoji": { - "name": "Vlastní reakce emotikonem na akci dvojitého klepnutí v chatu", - "description": "Nastaví vlastní reakci emotikonem na akci dvojitého klepnutí v chatu" - } - } - }, - "global": { - "name": "Globální", - "description": "Upravit globální nastavení Snapchatu", - "properties": { - "better_location": { - "name": "Lepší poloha", - "description": "Vylepšuje polohu Snapchatu", - "properties": { - "spoof_location": { - "name": "Falšovat polohu", - "description": "Falšuje vaši polohu na zadanou" - }, - "coordinates": { - "name": "Souřadnice", - "description": "Nastavte souřadnice falšované polohy" - }, - "walk_radius": { - "name": "Poloměr chůze", - "description": "Náhodně se procházet v tomto poloměru (stopy)" - }, - "always_update_location": { - "name": "Vždy aktualizovat polohu", - "description": "Vynutí Snapchat aktualizovat polohu, i když nejsou přijata žádná data GPS" - }, - "suspend_location_updates": { - "name": "Pozastavit aktualizace polohy", - "description": "Zabraňuje aktualizaci vaší polohy" - }, - "spoof_battery_level": { - "name": "Falšovat úroveň baterie", - "description": "Falšuje úroveň baterie vašeho zařízení na mapě\nHodnota musí být mezi 0 a 100" - }, - "spoof_headphones": { - "name": "Falšovat sluchátka", - "description": "Falšuje stav poslechu hudby na mapě" - }, - "show_battery_level": { - "name": "Zobrazit úroveň baterie", - "description": "Zobrazuje úroveň baterie vašich přátel na mapě" - } - } - }, - "snapchat_plus": { - "name": "Snapchat Plus", - "description": "Povolí funkce Snapchat Plus\nNěkteré funkce na straně serveru nemusí fungovat" - }, - "media_upload_quality": { - "name": "Kvalita nahrávání médií", - "description": "Přepíše kvalitu nahrávání médií", - "properties": { - "force_video_upload_source_quality": { - "name": "Vynutit kvalitu zdroje nahrávání videa", - "description": "Vynutí Snapchat používat kvalitu zdroje při nahrávání videí\nVšimněte si, že to nemusí odstranit metadata z médií" - }, - "disable_image_compression": { - "name": "Zakázat kompresi obrázků", - "description": "Zakáže kompresi obrázků při nahrávání médií" - }, - "custom_image_upload_format": { - "name": "Vlastní formát nahrávání obrázků", - "description": "Nastaví vlastní formát nahrávání obrázků\nVyberte bezeztrátový formát (jako PNG) pro nejlepší kvalitu" - } - } - }, - "disable_confirmation_dialogs": { - "name": "Zakázat potvrzovací dialogy", - "description": "Automaticky potvrdí vybrané akce" - }, - "auto_updater": { - "name": "Automatický aktualizátor", - "description": "Automaticky kontroluje nové aktualizace" - }, - "disable_metrics": { - "name": "Zakázat metriky", - "description": "Blokuje odesílání specifických analytických dat do Snapchatu" - }, - "disable_story_sections": { - "name": "Zakázat sekce příběhů", - "description": "Odstraní sekce ze stránky Příběhy\nPro správnou funkci může vyžadovat obnovení" - }, - "block_ads": { - "name": "Blokovat reklamy", - "description": "Zabraňuje zobrazování reklam" - }, - "disable_custom_tabs": { - "name": "Zakázat vlastní karty", - "description": "Otevírá odkazy v podporovaných aplikacích místo ve webovém prohlížeči" - }, - "disable_permission_requests": { - "name": "Zakázat žádosti o oprávnění", - "description": "Zabraňuje Snapchatu žádat o specifická oprávnění" - }, - "disable_memories_snap_feed": { - "name": "Zakázat kanál snapů ze vzpomínek", - "description": "Zabraňuje Snapchatu zobrazovat nedávné vzpomínky, když přejedete prstem nahoru v kameře" - }, - "spotlight_comments_username": { - "name": "Uživatelské jméno v komentářích Spotlight", - "description": "Zobrazuje uživatelské jméno autora v komentářích Spotlight" - }, - "bypass_video_length_restriction": { - "name": "Obejít omezení délky videa", - "description": "Jedno: odešle jedno video\nRozdělit: rozdělí videa po úpravě" - }, - "default_video_playback_rate": { - "name": "Výchozí rychlost přehrávání videa", - "description": "Nastaví výchozí rychlost přehrávání videí\nHodnota musí být mezi 0,1 a 4,0" - }, - "video_playback_rate_slider": { - "name": "Posuvník rychlosti přehrávání videa", - "description": "Přidá posuvník do kontextového menu opera pro změnu rychlosti přehrávání videa\nPoznámka: Změny se projeví pouze u následujících videí" - }, - "disable_google_play_dialogs": { - "name": "Zakázat dialogy služeb Google Play", - "description": "Zabránit zobrazování dialogů o dostupnosti služeb Google Play" - }, - "default_volume_controls": { - "name": "Výchozí ovládání hlasitosti", - "description": "Vynutí Snapchat používat systémové ovládání hlasitosti" - }, - "disable_telecom_framework": { - "name": "Zakázat telekomunikační framework", - "description": "Zabraňuje Snapchatu používat telekomunikační framework Androidu\nTo vám umožní poslouchat hudbu během hovoru" - }, - "hide_active_music": { - "name": "Skrýt aktivní hudbu", - "description": "Zabraňuje Snapchatu vědět, že posloucháte hudbu\nTo vám umožní pořizovat snapy pomocí tlačítek ovládání hlasitosti při poslechu hudby" - }, - "disable_snap_splitting": { - "name": "Zakázat rozdělování snapů", - "description": "Zabraňuje rozdělování snapů na více částí\nObrázky, které odešlete, se změní na videa" - } - } - }, - "rules": { - "name": "Pravidla", - "description": "Spravovat automatické funkce pro jednotlivé osoby" - }, - "camera": { - "name": "Kamera", - "description": "Upravte správná nastavení pro dokonalý snap", - "properties": { - "disable_cameras": { - "name": "Zakázat kamery", - "description": "Zabraňuje Snapchatu používat vybrané kamery" - }, - "black_photos": { - "name": "Černé fotografie", - "description": "Nahradí pořízené fotografie černým pozadím\nVidea nejsou ovlivněna" - }, - "immersive_camera_preview": { - "name": "Pohlcující náhled", - "description": "Zabraňuje Snapchatu ořezávat náhled kamery\nTo může způsobit blikání kamery na některých zařízeních" - }, - "override_front_resolution": { - "name": "Přepsat přední rozlišení", - "description": "Přepíše rozlišení kamery pro přední kameru" - }, - "override_back_resolution": { - "name": "Přepsat zadní rozlišení", - "description": "Přepíše rozlišení kamery pro zadní kameru" - }, - "custom_resolution": { - "name": "Vlastní rozlišení", - "description": "Nastaví vlastní rozlišení kamery, šířka x výška (např. 1920x1080).\nVlastní rozlišení musí být podporováno vaším zařízením" - }, - "front_custom_frame_rate": { - "name": "Přední vlastní snímková frekvence", - "description": "Přepíše snímkovou frekvenci přední kamery" - }, - "back_custom_frame_rate": { - "name": "Zadní vlastní snímková frekvence", - "description": "Přepíše snímkovou frekvenci zadní kamery" - }, - "force_camera_source_encoding": { - "name": "Vynutit kódování zdroje kamery", - "description": "Vynutí kódování zdroje kamery" - }, - "startup_default_camera": { - "name": "Výchozí kamera při spuštění", - "description": "Nastaví výchozí kameru při otevření Snapchatu" - }, - "hevc_recording": { - "name": "Nahrávání HEVC", - "description": "Používá kodek HEVC (H.265) pro nahrávání videa" - } - } - }, - "streaks_reminder": { - "name": "Připomenutí sérií", - "description": "Pravidelně vás upozorňuje na vaše série", - "properties": { - "interval": { - "name": "Interval", - "description": "Interval mezi jednotlivými připomenutími (hodiny)" - }, - "remaining_hours": { - "name": "Zbývající čas", - "description": "Zbývající doba před zobrazením oznámení (hodiny)" - }, - "group_notifications": { - "name": "Skupinová oznámení", - "description": "Seskupí oznámení do jednoho" - } - } - }, - "experimental": { - "name": "Experimentální", - "description": "Experimentální funkce", - "properties": { - "native_hooks": { - "name": "Nativní hooky", - "description": "Nebezpečné funkce, které se napojují na nativní kód Snapchatu", - "properties": { - "composer_hooks": { - "name": "Hooky Composeru", - "description": "Vkládá kód do multiplatformního UI frameworku Composer", - "properties": { - "show_first_created_username": { - "name": "Zobrazit první vytvořené uživatelské jméno", - "description": "Zobrazí první vytvořené uživatelské jméno vedle aktuálního uživatelského jména na profilové stránce" - }, - "bypass_camera_roll_limit": { - "name": "Obejít limit galerie", - "description": "Zvýší maximální množství médií, které můžete odeslat z galerie" - }, - "custom_self_destruct_snap_delay": { - "name": "Vlastní zpoždění samodestrukčního snapu", - "description": "Poskytuje více možností pro časovač samodestrukce při odesílání snapu" - }, - "composer_console": { - "name": "Konzole Composeru", - "description": "Umožňuje spouštět JavaScriptový kód v Composeru (pouze arm64)" - }, - "composer_logs": { - "name": "Protokoly Composeru", - "description": "Přesměruje protokoly konzole Composeru do PurrfectSnap" - } - } - }, - "disable_bitmoji": { - "name": "Zakázat Bitmoji", - "description": "Zakáže Bitmoji profilu přátel" - }, - "custom_emoji_font": { - "name": "Vlastní písmo emotikonů", - "description": "Umožňuje používat vlastní písmo emotikonů. Funguje pouze s písmy .ttf" - }, - "custom_shared_library": { - "name": "Vlastní sdílená knihovna", - "description": "Načte vlastní sdílenou knihovnu do Snapchatu. Tato funkce je pouze pro testovací účely" - } - } - }, - "spoof": { - "name": "Falšovat", - "description": "Falšovat různé informace o vás", - "properties": { - "play_store_installer_package_name": { - "name": "Název balíčku instalačního programu Obchodu Play", - "description": "Přepíše název balíčku instalačního programu na com.android.vending" - }, - "remove_vpn_transport_flag": { - "name": "Odstranit příznak transportu VPN", - "description": "Zabraňuje Snapchatu detekovat VPN" - }, - "remove_mock_location_flag": { - "name": "Odstranit příznak falešné polohy", - "description": "Zabraňuje Snapchatu detekovat falešnou polohu" - } - } - }, - "convert_message_locally": { - "name": "Převést zprávu lokálně", - "description": "Převádí snapy na externí média chatu lokálně. Zobrazí se v kontextovém menu stahování chatu" - }, - "media_file_picker": { - "name": "Výběr mediálního souboru", - "description": "Umožňuje vybrat jakýkoli video/audio soubor z galerie" - }, - "story_logger": { - "name": "Záznamník příběhů", - "description": "Poskytuje historii příběhů přátel" - }, - "call_recorder": { - "name": "Záznamník hovorů", - "description": "Automaticky nahrává audio hovory" - }, - "account_switcher": { - "name": "Přepínač účtů", - "description": "Umožňuje přepínat mezi účty bez odhlášení\nDlouhým stisknutím ikony hledání vedle vašeho profilu Bitmoji otevřete menu\nPoznámka: Tato funkce je experimentální a v budoucnu se pravděpodobně změní", - "properties": { - "auto_backup_current_account": { - "name": "Automaticky zálohovat aktuální účet", - "description": "Automaticky zálohuje aktuální účet při odhlášení nebo přepnutí účtů" - } - } - }, - "better_transcript": { - "name": "Lepší přepis", - "description": "Vylepšuje přepis hlasových poznámek", - "properties": { - "force_transcription": { - "name": "Vynutit přepis hlasových poznámek", - "description": "Umožňuje přepis všech hlasových poznámek" - }, - "preferred_transcription_lang": { - "name": "Preferovaný jazyk přepisu", - "description": "Preferovaný jazyk pro přepis hlasových poznámek (např. EN, ES, FR)" - }, - "notification_transcript": { - "name": "Přepis oznámení", - "description": "Přepisuje hlasové poznámky v oznámeních\nTato funkce vyžaduje povolení funkce Náhled chatu v Lepších oznámeních" - } - } - }, - "voice_note_auto_play": { - "name": "Automatické přehrávání hlasových poznámek", - "description": "Automaticky přehraje další hlasovou poznámku po skončení aktuální" - }, - "friend_notes": { - "name": "Poznámky k přátelům", - "description": "Umožňuje přidávat poznámky k profilům přátel" - }, - "cof_experiments": { - "name": "Experimenty COF", - "description": "Povolí nevydané/beta funkce Snapchatu" - }, - "context_menu_fix": { - "name": "Oprava kontextového menu", - "description": "Pokusí se opravit menu kanálu přátel, protože když je zařízení offline, nelze ho správně zobrazit" - }, - "app_lock": { - "name": "Zámek aplikace", - "description": "Zabraňuje přístupu do Snapchatu bez hesla", - "properties": { - "lock_on_resume": { - "name": "Zamknout při obnovení", - "description": "Zamkne aplikaci při jejím opětovném otevření" - } - } - }, - "infinite_story_boost": { - "name": "Nekonečné posílení příběhu", - "description": "Obejít zpoždění limitu posílení příběhu" - }, - "meo_passcode_bypass": { - "name": "Obejít heslo My Eyes Only", - "description": "Obejít heslo My Eyes Only\nTo bude fungovat pouze v případě, že bylo heslo zadáno správně dříve" - }, - "no_friend_score_delay": { - "name": "Žádné zpoždění skóre přátel", - "description": "Odstraní zpoždění při prohlížení skóre přátel" - }, - "best_friend_pinning": { - "name": "Připnutí nejlepšího přítele", - "description": "Umožňuje připnout přítele jako svého nejlepšího přítele číslo jedna. Poznámka: Pouze vy můžete vidět svého připnutého nejlepšího přítele" - }, - "e2ee": { - "name": "End-To-End šifrování", - "description": "Šifruje vaše zprávy pomocí AES pomocí sdíleného tajného klíče\nUjistěte se, že si klíč uložíte na bezpečné místo!", - "properties": { - "encrypted_message_indicator": { - "name": "Indikátor šifrovaných zpráv", - "description": "Přidá emotikon 🔒 vedle šifrovaných zpráv" - }, - "force_message_encryption": { - "name": "Vynutit šifrování zpráv", - "description": "Zabraňuje odesílání šifrovaných zpráv lidem, kteří nemají povoleno E2E šifrování, pouze když je vybráno více konverzací" - } - } - }, - "add_friend_source_spoof": { - "name": "Falšovat zdroj přidání přítele", - "description": "Falšuje zdroj žádosti o přátelství" - }, - "hidden_snapchat_plus_features": { - "name": "Skryté funkce Snapchat Plus", - "description": "Povolí nevydané/beta funkce Snapchat Plus\nNemusí fungovat na starších verzích Snapchatu" - }, - "custom_streaks_expiration_format": { - "name": "Vlastní formát vypršení sérií", - "description": "Přizpůsobí formát vypršení sérií\n\nDostupné proměnné:\n - %c: Počet sérií\n - %e: Emotikon přesýpacích hodin\n - %d: Dny\n - %h: Hodiny\n - %m: Minuty\n - %s: Sekundy\n - %w: Zbývající čas" - }, - "prevent_forced_logout": { - "name": "Zabránit vynucenému odhlášení", - "description": "Zabraňuje Snapchatu vás odhlásit, když se přihlásíte na jiném zařízení" - }, - "snapscore_changes": { - "name": "Změny Snapscore", - "description": "Sleduje změny ve Snapscore přátel\nPoužijte tuto funkci pouze v novějších verzích Snapchatu" - } - } - }, - "scripting": { - "name": "Skriptování", - "description": "Spouštět vlastní skripty pro rozšíření PurrfectSnap", - "properties": { - "developer_mode": { - "name": "Vývojářský režim", - "description": "Zobrazuje ladicí informace v uživatelském rozhraní Snapchatu" - }, - "module_folder": { - "name": "Složka modulů", - "description": "Složka, kde se nacházejí skripty" - }, - "auto_reload": { - "name": "Automatické obnovení", - "description": "Automaticky obnovuje skripty při jejich změně" - }, - "integrated_ui": { - "name": "Integrované uživatelské rozhraní", - "description": "Umožňuje skriptům přidávat vlastní komponenty uživatelského rozhraní do Snapchatu" - }, - "disable_log_anonymization": { - "name": "Zakázat anonymizaci protokolů", - "description": "Zakáže anonymizaci protokolů" - }, - "disable_optimization": { - "name": "Zakázat optimalizaci", - "description": "Zakáže optimalizaci skriptů. To může způsobit problémy s výkonem." - } - } - }, - "friend_tracker": { - "name": "Sledování přátel", - "description": "Zaznamenává aktivitu přátel na Snapchatu", - "properties": { - "record_messaging_events": { - "name": "Zaznamenávat události zasílání zpráv", - "description": "Zaznamenává události zasílání zpráv, jako je otevření snapu, přečtení zprávy atd." - }, - "allow_running_in_background": { - "name": "Povolit běh na pozadí", - "description": "Umožňuje sledovači běžet na pozadí. Poznámka: To výrazně vybije vaši baterii" - }, - "auto_purge": { - "name": "Automatické čištění", - "description": "Automaticky maže události v mezipaměti, které jsou starší než zadaná doba" - } - } - } - }, - "options": { - "app_appearance": { - "always_light": "Vždy světlý", - "always_dark": "Vždy tmavý" - }, - "friend_feed_menu_buttons": { - "auto_download": "⬇️ Automatické stahování", - "auto_save": "💬 Automaticky ukládat zprávy", - "unsaveable_messages": "⬇️ Neuložitelné zprávy", - "auto_open_snaps": "📸 Automaticky otevírat snapy", - "stealth": "👻 Stealth režim", - "mark_snaps_as_seen": "👀 Označit snapy jako přečtené", - "mark_stories_as_seen_locally": "👀 Označit příběhy jako přečtené lokálně", - "conversation_info": "🧑‍🤝‍🧑 Informace o konverzaci", - "e2e_encryption": "🔒 Použít E2E šifrování" - }, - "path_format": { - "create_author_folder": "Vytvořit složku pro každého autora", - "create_source_folder": "Vytvořit složku pro každý typ zdroje médií", - "append_hash": "Přidat jedinečný hash do názvu souboru", - "append_source": "Přidat zdroj médií do názvu souboru", - "append_username": "Přidat uživatelské jméno do názvu souboru", - "append_date_time": "Přidat datum a čas do názvu souboru" - }, - "auto_download_sources": { - "friend_snaps": "Snapy přátel", - "friend_stories": "Příběhy přátel", - "public_stories": "Veřejné příběhy", - "spotlight": "Reflektor" - }, - "logging": { - "started": "Zahájeno", - "success": "Úspěch", - "progress": "Průběh", - "failure": "Selhání" - }, - "notifications": { - "chat_screenshot": "Snímek obrazovky", - "chat_screen_record": "Záznam obrazovky", - "snap_replay": "Opakované přehrání snapu", - "camera_roll_save": "Uložit do galerie", - "chat": "Povídání", - "chat_reply": "Odpověď v chatu", - "snap": "Snap", - "typing": "Píše", - "stories": "Příběhy", - "speaking": "Mluví", - "chat_reaction": "Reakce na DM", - "group_chat_reaction": "Reakce skupiny", - "initiate_audio": "Příchozí audio hovor", - "abandon_audio": "Zmeškaný audio hovor", - "initiate_video": "Příchozí video hovor", - "abandon_video": "Zmeškaný video hovor", - "map_live_location": "Živá poloha na mapě" - }, - "gallery_media_send_override": { - "always_ask": "Vždy se zeptat", - "ORIGINAL": "Původní média", - "NOTE": "Hlasová poznámka", - "SNAP": "Snap", - "SAVEABLE_SNAP": "Uložitelný snap" - }, - "strip_media_metadata": { - "hide_caption_text": "Skrýt text popisku", - "hide_snap_filters": "Skrýt filtry snapu", - "hide_extras": "Skrýt doplňky (např. zmínky)", - "remove_audio_note_duration": "Odstranit dobu trvání hlasové poznámky", - "remove_audio_note_transcript_capability": "Odstranit schopnost přepisu hlasové poznámky" - }, - "hide_ui_components": { - "hide_profile_call_buttons": "Odstranit tlačítka volání v profilu", - "hide_chat_call_buttons": "Odstranit tlačítka volání v chatu", - "hide_live_location_share_button": "Odstranit tlačítko sdílení živé polohy", - "hide_stickers_button": "Odstranit tlačítko nálepek", - "hide_voice_record_button": "Odstranit tlačítko nahrávání hlasu", - "hide_unread_chat_hint": "Odstranit nápovědu k nepřečtenému chatu", - "hide_post_to_story_buttons": "Odstranit tlačítka pro zveřejnění v příběhu před odesláním snapu", - "hide_billboard_prompt": "Odstranit výzvu na billboardu v kanálu přátel", - "hide_snapchat_plus_gift_reminders": "Odstranit připomenutí dárků Snapchat Plus v konverzacích", - "hide_map_reactions": "Odstranit reakce na mapě" - }, - "hide_story_suggestions": { - "hide_suggested_friend_stories": "Skrýt navrhované příběhy přátel", - "hide_my_stories": "Skrýt mé příběhy" - }, - "home_tab": { - "map": "Mapa", - "chat": "Povídání", - "camera": "Kamera", - "discover": "Objevit", - "spotlight": "Reflektor" - }, - "add_friend_source_spoof": { - "added_by_username": "Podle uživatelského jména", - "added_by_mention": "Podle zmínky", - "added_by_group_chat": "Podle skupinového chatu", - "added_by_qr_code": "Podle QR kódu", - "added_by_community": "Podle komunity", - "added_by_quick_add": "Podle rychlého přidání (vysoké riziko zákazu)" - }, - "bypass_video_length_restriction": { - "single": "Jedno médium", - "split": "Rozdělit médium" - }, - "old_bitmoji_selfie": { - "2d": "2d bitmoji", - "3d": "3d bitmoji" - }, - "disable_confirmation_dialogs": { - "erase_message": "Smazat zprávu", - "remove_friend": "Odstranit přítele", - "block_friend": "Blokovat přítele", - "ignore_friend": "Ignorovat přítele", - "hide_friend": "Skrýt přítele", - "hide_conversation": "Skrýt konverzaci", - "clear_conversation": "Vymazat konverzaci z kanálu přátel" - }, - "auto_reload": { - "snapchat_only": "Pouze Snapchat", - "all": "Vše (Snapchat + PurrfectSnap)" - }, - "edit_text_override": { - "multi_line_chat_input": "Víceřádkový vstup chatu", - "bypass_text_input_limit": "Obejít limit vstupu textu" - }, - "auto_purge": { - "never": "Nikdy", - "1_hour": "1 hodina", - "3_hours": "3 hodiny", - "6_hours": "6 hodin", - "12_hours": "12 hodin", - "1_day": "1 den", - "3_days": "3 dny", - "1_week": "1 týden", - "2_weeks": "2 týdny", - "1_month": "1 měsíc", - "3_months": "3 měsíce", - "6_months": "6 měsíců" - }, - "disable_story_sections": { - "friends": "Přátelé", - "suggested_stories": "Navrhované příběhy", - "following": "Sledování", - "discover": "Objevit" - }, - "disable_cameras": { - "front": "Přední kamera", - "back": "Zadní kamera" - }, - "disable_permission_requests": { - "notifications": "Oznámení", - "read_media_images": "Číst obrázky médií", - "read_media_video": "Číst video médií", - "camera": "Kamera", - "microphone": "Mikrofon", - "location": "Poloha", - "read_contacts": "Číst kontakty", - "nearby_devices": "Zařízení v okolí", - "phone_calls": "Telefonní hovory" - }, - "message_indicators": { - "encryption_indicator": "Přidá ikonu 🔒 vedle zpráv, které byly odeslány pouze vám", - "platform_indicator": "Přidá ikonu platformy, ze které bylo médium odesláno (např. Android, iOS, Web)", - "location_indicator": "Přidá ikonu 📍 ke snapům, když byly odeslány s povolenou polohou", - "ovf_editor_indicator": "Indikuje, zda byl snap odeslán pomocí editoru OVF", - "director_mode_indicator": "Přidá ikonu 🎬 ke snapům, když byly odeslány pomocí režimu režiséra, který lze použít k odeslání obrázků z galerie jako snapů" - }, - "auto_mark_as_read": { - "conversation_read": "Označit konverzaci jako přečtenou při odeslání zprávy", - "snap_reply": "Označit snapy jako přečtené při odpovědi na ně", - "save_snap_in_chat": "Označit snapy jako přečtené při jejich ukládání do chatu v režimu Stealth" - }, - "friend_mutation_notifier": { - "remove_friend": "Upozornit, když vás někdo odebere jako přítele", - "birthday_changes": "Upozornit, když někdo změní své narozeniny", - "bitmoji_selfie_changes": "Upozornit, když někdo změní své selfie Bitmoji", - "bitmoji_avatar_changes": "Upozornit, když někdo změní svůj avatar Bitmoji", - "bitmoji_background_changes": "Upozornit, když někdo změní své pozadí Bitmoji", - "bitmoji_scene_changes": "Upozornit, když někdo změní svou scénu Bitmoji" - }, - "snapchat_plus": { - "not_subscribed": "Nepředplaceno", - "basic": "Základní", - "ad_free": "Bez reklam" - }, - "double_tap_chat_action": { - "like_message": "Líbí se mi zpráva", - "copy_text": "Kopírovat text do schránky", - "delete_message": "Smazat zprávu", - "mark_as_read": "Označit jako přečtené", - "custom_emoji_reaction": "Vlastní reakce emotikonem" - }, - "startup_default_camera": { - "front": "Přední kamera", - "back": "Zadní kamera" - } - } - }, - "friend_menu_option": { - "mark_snaps_as_seen": "Označit snapy jako přečtené", - "mark_stories_as_seen_locally": "Označit příběhy jako přečtené lokálně", - "preview": "Náhled", - "stealth_mode": "Stealth režim", - "auto_download_blacklist": "Blacklist automatického stahování", - "anti_auto_save": "Anti automatické ukládání" - }, - "content_type": { - "CHAT": "Povídání", - "SNAP": "Snap", - "EXTERNAL_MEDIA": "Externí média", - "NOTE": "Hlasová poznámka", - "STICKER": "Nálepka", - "SHARE": "Sdílet", - "STATUS": "Stav", - "LOCATION": "Poloha", - "STATUS_SAVE_TO_CAMERA_ROLL": "Uloženo do galerie", - "STATUS_CONVERSATION_CAPTURE_SCREENSHOT": "Snímek obrazovky", - "STATUS_CONVERSATION_CAPTURE_RECORD": "Záznam obrazovky", - "STATUS_CALL_MISSED_VIDEO": "Zmeškaný video hovor", - "STATUS_CALL_MISSED_AUDIO": "Zmeškaný audio hovor", - "LIVE_LOCATION_SHARE": "Sdílení živé polohy", - "CREATIVE_TOOL_ITEM": "Položka kreativního nástroje", - "FAMILY_CENTER_INVITE": "Pozvánka do rodinného centra", - "FAMILY_CENTER_ACCEPT": "Přijmout rodinné centrum", - "FAMILY_CENTER_LEAVE": "Opustit rodinné centrum", - "STATUS_PLUS_GIFT": "Dárek Status Plus", - "TINY_SNAP": "Malý snap", - "STATUS_COUNTDOWN": "Odpočítávání", - "MAP_REACTION": "Reakce na mapě" - }, - "media_download_source": { - "none": "Žádný", - "pending": "Čeká na vyřízení", - "chat_media": "Média chatu", - "story": "Příběh", - "public_story": "Veřejný příběh", - "spotlight": "Reflektor", - "profile_picture": "Profilový obrázek", - "story_logger": "Záznamník příběhů", - "message_logger": "Záznamník zpráv", - "merged": "Sloučeno", - "voice_call": "Hlasový hovor" - }, - "chat_action_menu": { - "preview_button": "Náhled", - "download_button": "Stáhnout", - "delete_logged_message_button": "Smazat zaznamenanou zprávu", - "show_chat_edit_history": "Zobrazit historii úprav chatu", - "convert_message": "Převést zprávu" - }, - "opera_context_menu": { - "download": "Stáhnout média", - "sent_at": "Odesláno {date}", - "created_at": "Vytvořeno {date}", - "expires_at": "Vyprší {date}", - "media_size": "Velikost médií: {size}", - "media_duration": "Doba trvání médií: {duration} ms", - "show_debug_info": "Zobrazit ladicí informace" - }, - "modal_option": { - "profile_info": "Informace o profilu", - "close": "Zavřít" - }, - "gallery_media_send_override": { - "multiple_media_toast": "Můžete odeslat pouze jedno médium najednou" - }, - "mark_as_seen": { - "no_unseen_snaps_toast": "Nebyly nalezeny žádné nepřečtené snapy!", - "seen_toast": "Označeno jako přečtené!", - "unseen_toast": "Označeno jako nepřečtené!", - "already_seen_toast": "Již označeno jako přečtené!", - "already_unseen_toast": "Již označeno jako nepřečtené!" - }, - "conversation_preview": { - "streak_expiration": "vyprší za {day} dní {hour} hodin {minute} minut", - "total_messages": "Celkem odeslaných/přijatých zpráv: {count}", - "title": "Náhled", - "unknown_user": "Neznámý uživatel", - "no_messages": "Nebyly nalezeny žádné zprávy!" - }, - "profile_info": { - "title": "Informace o profilu", - "first_created_username": "První vytvořené uživatelské jméno", - "mutable_username": "Měnitelné uživatelské jméno", - "display_name": "Zobrazované jméno", - "added_date": "Datum přidání", - "birthday": "Narozeniny: {day} {month}", - "hidden_birthday": "Narozeniny: Skryto", - "friendship": "Přátelství", - "add_source": "Přidat zdroj", - "snapchat_plus": "Snapchat Plus", - "snapchat_plus_state": { - "subscribed": "Předplaceno", - "not_subscribed": "Nepředplaceno" - } - }, - "friendship_link_type": { - "mutual": "Vzájemné", - "outgoing": "Odchozí", - "blocked": "Blokováno", - "deleted": "Smazáno", - "following": "Sledování", - "suggested": "Navrženo", - "incoming": "Příchozí", - "incoming_follower": "Příchozí sledující" - }, - "bulk_messaging_action": { - "choose_action_title": "Vyberte akci", - "progress_status": "Zpracovávání {index} z {total}", - "selection_dialog_continue_button": "Pokračovat", - "confirmation_dialog": { - "title": "Jste si jisti?", - "message": "To ovlivní všechny vybrané přátele. Tuto akci nelze vrátit zpět." - }, - "actions": { - "remove_friends": "Odstranit přátele", - "clear_conversations": "Vymazat konverzace" - } - }, - "chat_export": { - "exporter_dialog": { - "select_conversations_title": "Vybrat konverzace", - "text_field_selection": "{amount} vybráno", - "text_field_selection_all": "Vše", - "export_file_format_title": "Exportovat formát souboru", - "message_type_filter_title": "Filtrovat zprávy podle typu", - "amount_of_messages_title": "Množství zpráv (ponechte prázdný pro všechny)", - "download_medias_title": "Stáhnout média" - }, - "dialog_negative_button": "Zrušit", - "dialog_positive_button": "Exportovat", - "exported_to": "Exportováno do {path}", - "exporting_chats": "Exportování chatů...", - "processing_chats": "Zpracovávání {amount} konverzací...", - "export_fail": "Export konverzace {conversation} se nezdařil", - "writing_output": "Zapisování výstupu...", - "finished": "Hotovo! Nyní můžete tento dialog zavřít.", - "no_messages_found": "Nebyly nalezeny žádné zprávy!", - "exporting_message": "Exportování {conversation}..." - }, - "button": { - "ok": "Dobře", - "positive": "Ano", - "negative": "Ne", - "cancel": "Zrušit", - "open": "Otevřít", - "download": "Stáhnout", - "send": "Odeslat", - "restore_original": "Obnovit původní", - "convert_external_media": "Převést externí média", - "save": "Uložit" - }, - "tracker_events": { - "conversation_enter": "Vstup do konverzace", - "conversation_exit": "Opuštění konverzace", - "started_typing": "Začal psát", - "stopped_typing": "Přestal psát", - "started_speaking": "Začal mluvit", - "stopped_speaking": "Přestal mluvit", - "started_peeking": "Začal nahlížet", - "stopped_peeking": "Přestal nahlížet", - "message_read": "Zpráva přečtena", - "message_deleted": "Zpráva smazána", - "message_saved": "Zpráva uložena", - "message_unsaved": "Zpráva neuložena", - "message_edited": "Zpráva upravena", - "message_reaction_add": "Přidána reakce na zprávu", - "message_reaction_remove": "Odebrána reakce na zprávu", - "snap_opened": "Snap otevřen", - "snap_replayed": "Snap znovu přehrán", - "snap_replayed_twice": "Snap znovu přehrán dvakrát", - "snap_screenshot": "Snímek obrazovky snapu", - "snap_screen_record": "Záznam obrazovky snapu" - }, - "tracker_actions": { - "log": "Protokol", - "in_app_notification": "Oznámení v aplikaci", - "push_notification": "Push oznámení", - "custom": "Vlastní" - }, - "better_notifications": { - "button": { - "reply": "Odpovědět", - "download": "Stáhnout", - "mark_as_read": "Označit jako přečtené" - } - }, - "profile_picture_downloader": { - "button": "Stáhnout profilový obrázek", - "title": "Stahovač profilových obrázků", - "avatar_option": "Avatar", - "background_option": "Pozadí" - }, - "call_start_confirmation": { - "dialog_title": "Zahájit hovor", - "dialog_message": "Opravdu chcete zahájit hovor?" - }, - "half_swipe_notifier": { - "notification_channel_name": "Poloviční přejetí", - "notification_content_dm": "{friend} právě napůl přejel do vašeho chatu na {duration} sekund", - "notification_content_group": "{friend} právě napůl přejel do {group} na {duration} sekund" - }, - "download_processor": { - "attachment_type": { - "snap": "Snap", - "sticker": "Nálepka", - "gif": "Gif", - "external_media": "Externí média", - "note": "Poznámka", - "original_story": "Původní příběh" - }, - "select_attachments_title": "Vybrat přílohy", - "download_started_toast": "Stahování zahájeno", - "unsupported_content_type_toast": "Nepodporovaný typ obsahu!", - "failed_no_longer_available_toast": "Média již nejsou k dispozici", - "no_attachments_toast": "Nebyly nalezeny žádné přílohy!", - "already_queued_toast": "Média jsou již ve frontě!", - "already_downloaded_toast": "Média jsou již stažena!", - "content_saved_toast": "Uloženo!", - "download_toast": "Stahování {path}...", - "processing_toast": "Zpracovávání {path}...", - "failed_generic_toast": "Stažení se nezdařilo", - "failed_to_create_preview_toast": "Vytvoření náhledu se nezdařilo", - "failed_processing_toast": "Zpracování se nezdařilo {error}", - "failed_gallery_toast": "Uložení do galerie se nezdařilo {error}", - "dash_no_chapter": "Nebyly nalezeny žádné kapitoly", - "dash_dialog": { - "title": "Stáhnout média dash", - "download_all": "Stáhnout vše", - "segment_text": "Segment {from} - {to}" - } - }, - "streaks_reminder": { - "notification_title": "Série", - "notification_text": "Ztratíte svou sérii s {friend} za {hoursLeft} hodin" - }, - "biometric_auth": { - "unlock_button": "Odemknout", - "title": "Odemknout Snapchat", - "subtitle": "Pro odemknutí Snapchatu se prosím ověřte" - }, - "end_to_end_encryption": { - "toolbox": { - "no_shared_key": "S tímto přítelem ještě nemáte sdílený tajný klíč. Kliknutím níže zahájíte nový.", - "shared_key_fingerprint": "Váš otisk prstu je:\n\n{fingerprint}\n\nUjistěte se, že se shoduje s otiskem prstu vašeho přítele!", - "initiate_exchange_button": "Zahájit výměnu klíčů" - }, - "confirmation_dialogs": { - "title": "End-to-end šifrování", - "confirmation_1": "VAROVÁNÍ: Tímto přepíšete svůj stávající klíč. Ztratíte přístup ke všem šifrovaným zprávám od tohoto přítele. Opravdu chcete pokračovat?", - "confirmation_2": "Opravdu si přejete pokračovat? Toto je vaše poslední šance se vrátit." - }, - "unencrypted_conversation_send_failure_toast": "Nemůžete odesílat šifrovaný obsah do šifrovaných i nešifrovaných konverzací!", - "native_hooks_send_failure_toast": "Odeslání se nezdařilo! Povolte prosím nativní hooky v nastavení.", - "no_participants_to_encrypt_toast": "V této konverzaci nemáte žádné přátele, se kterými byste mohli šifrovat zprávy!", - "encryption_failed_toast": "Šifrování zprávy se nezdařilo! Zkontrolujte logcat pro více podrobností.", - "accept_public_key_success_toast": "Veřejný klíč úspěšně přijat!", - "accept_secret_key_success_toast": "Hotovo! Nyní můžete s tímto přítelem odesílat a přijímat šifrované zprávy.", - "accept_public_key_failure_toast": "Přijetí veřejného klíče se nezdařilo", - "accept_secret_key_failure_toast": "Přijetí tajného klíče se nezdařilo", - "accept_secret_button": "Přijmout tajemství", - "accept_public_key_button": "Přijmout veřejný klíč", - "outgoing_pk_message": "Požadavek na výměnu klíčů", - "outgoing_secret_message": "Odpověď na výměnu klíčů", - "incoming_pk_message": "Právě jste obdrželi požadavek na veřejný klíč. Kliknutím níže ho přijmete.", - "incoming_secret_message": "Váš přítel právě přijal váš veřejný klíč. Kliknutím níže přijmete tajemství." - }, - "auto_open_snaps": { - "title": "Automaticky otevírat snapy", - "notification_content": "{count} snapů otevřeno" - }, - "friend_mutation_observer": { - "notification_channel_name": "Pozorovatel mutací přátel", - "friend_removed": "{username} vás odebral jako přítele", - "birthday_removed": "{username} odstranil své narozeniny ({birthday})", - "birthday_added": "{username} přidal své narozeniny ({birthday})", - "birthday_changed": "{username} změnil své narozeniny z {oldBirthday} na {newBirthday}", - "bitmoji_selfie_changed": "{username} změnil své selfie Bitmoji", - "bitmoji_avatar_changed": "{username} změnil svůj avatar Bitmoji", - "bitmoji_background_changed": "{username} změnil své pozadí Bitmoji", - "bitmoji_scene_changed": "{username} změnil svou scénu Bitmoji" - }, - "material3_strings": { - "date_range_picker_start_headline": "Od", - "date_range_picker_end_headline": "Do", - "date_range_picker_title": "Vybrat rozsah dat", - "date_picker_switch_to_calendar_mode": "Kalendář", - "date_picker_switch_to_input_mode": "Vstup", - "date_range_picker_scroll_to_previous_month": "Předchozí měsíc", - "date_range_picker_scroll_to_next_month": "Následující měsíc", - "date_picker_today_description": "Dnes", - "date_range_picker_day_in_range": "Vybráno", - "date_input_invalid_for_pattern": "Neplatné datum", - "date_input_invalid_year_range": "Neplatný rok", - "date_input_invalid_not_allowed": "Neplatné datum", - "date_range_input_invalid_range_input": "Neplatný rozsah dat" - }, - "send_override_dialog": { - "title": "Odeslat média jako {type}", - "duration": "Doba trvání: {duration}", - "saveable_snap_hint": "Učinit snap uložitelným v chatu", - "unlimited_duration": "Neomezeně" - }, - "invalid_input_toast": "Neplatný vstup! Ujistěte se, že jste zadali platnou hodnotu." -} \ No newline at end of file diff --git a/common/src/main/assets/lang/da.json b/common/src/main/assets/lang/da.json index 75700360..7871451a 100644 --- a/common/src/main/assets/lang/da.json +++ b/common/src/main/assets/lang/da.json @@ -2,751 +2,311 @@ "setup": { "dialogs": { "select_language": "Vælg sprog", - "save_folder": "PurrfectSnap kræver lageradgang for at downloade og gemme medier fra Snapchat.\nVælg venligst den placering, hvor medier skal downloades til.", - "select_save_folder_button": "Vælg mappe" + "save_folder": "SnapEnhance kræver Lagringstilladelser til at downloade og gemme medier fra Snapchat.\nVælg venligst det sted, hvor medierne skal downloades til.", + "select_save_folder_button": "Vælg Mappe" }, "mappings": { - "dialog": "Genererer kortlægninger, dette kan tage et stykke tid...", - "generate_failure_no_snapchat": "PurrfectSnap kunne ikke registrere Snapchat, prøv venligst at geninstallere Snapchat.", - "generate_failure": "Der opstod en fejl under generering af kortlægninger, prøv venligst igen." + "dialog": "Generering af maps, dette kan tage et stykke tid, overvej at bruge tiden fornuftigt, drik noget eller lav en toast...", + "generate_failure_no_snapchat": "SnapEnhance kunne ikke detektere Snapchat, prøv at geninstallere Snapchat.", + "generate_failure": "Der opstod en fejl under forsøget på at generere mappings, prøv venligst igen." }, "permissions": { - "dialog": "For at fortsætte skal du opfylde følgende krav:", + "dialog": "For at fortsætte skal du passe til følgende krav:", "notification_access": "Adgang til notifikationer", "battery_optimization": "Batterioptimering", - "display_over_other_apps": "Visning over andre apps", - "request_button": "Anmod" + "display_over_other_apps": "Vis over andre apps", + "request_button": "Forespørgsel" } }, - "scopes": { - "friend": "Ven", - "group": "Gruppe" - }, "manager": { "routes": { - "tasks": "Opgaver", "features": "Funktioner", - "manage_rule_feature": "Administrer regelfunktion", "home": "Hjem", "home_settings": "Indstillinger", "home_logs": "Logfiler", - "logger_history": "Loggerhistorik", - "logged_stories": "Loggede historier", - "friend_tracker": "Venne-tracker", - "edit_rule": "Rediger regel", - "file_imports": "Filimport", - "manage_repos": "Administrer depoter", "social": "Social", + "scripts": "Scripts", + "tasks": "Opgaver", + "logger_history": "Log historik", + "logged_stories": "Loggede historier", "manage_scope": "Administrer omfang", "messaging_preview": "Forhåndsvisning", - "scripts": "Scripts", - "better_location": "Bedre placering" + "friend_tracker": "Ven Tracker", + "edit_rule": "Rediger regel" }, "sections": { + "features": { + "disabled": "Slået fra", + "config_import_success_toast": "Konfigurationen blev importeret", + "export_option": "Eksport", + "import_option": "Importere", + "reset_option": "Nulstil", + "config_export_success_toast": "Konfigurationen blev eksporteret", + "config_import_failure_toast": "Kunne ikke importere konfiguration {error}", + "saved_config_snackbar": "Konfiguration gemt" + }, + "social": { + "streaks_expiration_short": "{hours} timer", + "friends_tab": "Venner", + "groups_tab": "Grupper", + "empty_hint": "(tom)" + }, + "tasks": { + "no_tasks": "Ingen opgaver", + "remove_all_tasks_confirm": "Vil du fjerne alle opgaver?", + "merge_files_toast": "Fletter {count} filer", + "remove_selected_tasks_title": "Er du sikker på, at du vil fjerne valgte opgaver?", + "remove_all_tasks_title": "Er du sikker på, at du vil fjerne alle opgaver?", + "delete_files_option": "Slet også filer", + "remove_selected_tasks_confirm": "Vil du fjerne {count} opgaver?" + }, + "logger_history": { + "chat_attachment": "Vedhæftet {index}", + "empty_message": "Tom chat besked", + "message_parse_failed": "Kunne ikke parse meddelelsen", + "unknown_sender": "Ukendt afsender", + "download_attachment_failed_toast": "Kunne ikke downloade den vedhæftede fil", + "list_friend_format": "Ven {name}", + "list_group_format": "Gruppe {name}", + "no_more_messages": "Ikke flere beskeder", + "reverse_order_checkbox": "Omvendt rækkefølge" + }, + "manage_scope": { + "streaks_title": "Streaks", + "reminder_button": "Indstil påmindelse", + "logged_stories_button": "Vis loggede historier", + "e2ee_title": "End-to-End Kryptering", + "rules_title": "Regler", + "participants_text": "{count} deltagere", + "not_found": "Ikke fundet", + "streaks_length_text": "Længde: {length}", + "streaks_expiration_text": "Udløber om {eta}", + "streaks_expiration_text_expired": "Udløbet", + "delete_scope_confirm_dialog_title": "Er du sikker på, at du vil slette et {scope}?" + }, + "logged_stories": { + "no_stories": "Ingen historier fundet", + "story_failed_to_load": "Kunne ikke indlæses", + "save_from_cache_button": "Gem fra cachen" + }, + "messaging_preview": { + "delete_selection_option": "Slet markering", + "bridge_connection_failed": "Kunne ikke oprette forbindelse til Snapchat via bridge-tjenesten", + "bridge_init_failed": "Kunne ikke initialisere meddelelses broen", + "message_fetch_failed": "Kunne ikke hente beskeder", + "no_message_hint": "Ingen besked", + "save_selection_option": "Gem valg", + "save_all_option": "Gem alle", + "unsave_selection_option": "Fjern markering", + "unsave_all_option": "Fjern gem alle", + "mark_selection_as_seen_option": "Markér valgt Snap som set", + "mark_all_as_seen_option": "Markér alle snaps som set", + "delete_all_option": "Slet alt" + }, "home": { - "version_title": "v{versionName} · forket af Eternal", - "update_title": "PurrfectSnap-opdatering", + "update_title": "SnapEnhance Opdatering", "update_content": "Version {version} er tilgængelig!", - "update_button": "Download", - "debug_build_summary_title": "Du kører en fejlfindingsversion af PurrfectSnap", - "debug_build_summary_content": "Version {versionName} ({versionCode})", - "debug_build_summary_date": "Byggedato: {date} (for {days} dage siden)", - "quick_actions_title": "Hurtige handlinger", - "download_icon_description": "Download", - "completed_icon_description": "Fuldført", - "failed_icon_description": "Mislykkedes", - "manage_quick_actions_description": "Administrer hurtige handlinger", - "quick_actions_icon_description": "Hurtige handlinger", - "add_quick_action_description": "Tilføj hurtig handling" + "update_button": "Hent" }, "home_logs": { "no_logs_hint": "Ingen logfiler tilgængelige", "clear_logs_button": "Ryd logfiler", - "export_logs_button": "Eksporter logfiler", - "saving_logs_toast": "Gemmer logfiler, dette kan tage et stykke tid...", - "saved_logs_success_toast": "Logfiler gemt", + "export_logs_button": "Eksporter logs", + "saving_logs_toast": "Gemmer logfiler, dette kan tage et stykke tid ...", + "saved_logs_success_toast": "Logfiler blev gemt", "saved_logs_failure_toast": "Kunne ikke gemme logfiler" }, "home_settings": { "actions_title": "Handlinger", - "message_logger_title": "Besked-logger", - "debug_title": "Fejlfinding", + "message_logger_title": "Meddelelses logger", + "debug_title": "Fejlfinde", "success_toast": "Færdig!", "message_logger_summary": "{messageCount} beskeder\n{storyCount} historier", - "export_button": "Eksporter", + "export_button": "Eksport", "clear_button": "Ryd", - "view_logger_history_button": "Se loggerhistorik", - "updates_title": "Opdateringer", - "auto_update_check": "Søg automatisk efter opdateringer", - "update_check_frequency": "Opdateringskontrolfrekvens", - "update_check_frequency_daily": "Dagligt", - "update_check_frequency_weekly": "Ugentligt", - "update_check_frequency_monthly": "Månedligt", - "theme_icon_description": "Tema", - "app_theme_title": "App-tema", - "theme_mode_system": "System", - "theme_mode_light": "Lys", - "theme_mode_dark": "Mørk", - "ui_settings_title": "Brugergrænsefladeindstillinger", - "haptic_feedback_label": "Haptisk feedback", - "test_mode_label": "Testtilstand (KUN TIL FEJLFINDING)", - "disable_feature_loading_label": "Deaktiver indlæsning af funktioner", - "disable_auto_mapper_label": "Deaktiver automatisk kortlægger", - "disable_bypass_indicator_label": "Deaktiver statusindikator for omgåelse", - "update_notification_channel_name": "PurrfectSnap-opdateringer", - "update_notification_channel_description": "Notifikationer om PurrfectSnap-opdateringer", - "update_notification_title": "PurrfectSnap-opdatering tilgængelig", - "update_notification_text": "Version %s er nu tilgængelig.", - "export_database_failed_toast": "Kunne ikke eksportere database! {message}", - "clear_messages_failed_toast": "Kunne ikke rydde beskeder! {message}", - "clear_file_failed_toast": "Kunne ikke rydde fil! {message}", - "debug_file_config": "Konfiguration", - "debug_file_mappings": "Kortlægninger", - "debug_file_message_logger": "Besked-logger", - "debug_file_pinned_best_friend": "Fastgjort bedste ven", - "debug_file_native_sig_cache": "Cache for native signaturer" - }, - "tasks": { - "no_tasks": "Ingen opgaver", - "merge_button": "Flet", - "failed_to_open_file": "Kunne ikke åbne fil", - "merge_files_toast": "Fletter {count} filer", - "remove_selected_tasks_title": "Er du sikker på, at du vil fjerne de valgte opgaver?", - "remove_all_tasks_title": "Er du sikker på, at du vil fjerne alle opgaver?", - "delete_files_option": "Slet også filer", - "remove_selected_tasks_confirm": "Fjern {count} opgaver?", - "remove_all_tasks_confirm": "Fjern alle opgaver?", - "clear_tasks_description": "Ryd opgaver", - "file_not_found_icon_description": "Fil ikke fundet", - "image_icon_description": "Billede", - "video_icon_description": "Video", - "audio_icon_description": "Lyd", - "file_icon_description": "Fil", - "download_icon_description": "Download", - "chat_action_icon_description": "Chathandling", - "cancel_icon_description": "Annuller", - "success_icon_description": "Succes", - "failure_icon_description": "Fejl", - "cancelled_icon_description": "Annulleret", - "task_status_failure": "Fejl", - "task_status_cancelled": "Annulleret" - }, - "features": { - "disabled": "Deaktiveret", - "export_option": "Eksporter", - "import_option": "Importer", - "reset_option": "Nulstil", - "config_export_success_toast": "Konfiguration eksporteret", - "config_import_success_toast": "Konfiguration importeret", - "config_import_failure_toast": "Kunne ikke importere konfiguration {error}", - "config_export_failure_toast": "Kunne ikke eksportere konfiguration {error}", - "saved_config_snackbar": "Konfiguration gemt", - "older_required": "Denne funktion kræver Snapchat v{version} eller ældre for at fungere korrekt", - "newer_required": "Denne funktion kræver Snapchat v{version} eller nyere for at fungere korrekt", - "search_button": "Søg" - }, - "manage_rule_feature": { - "disable_state_option": "Deaktiveret", - "disable_state_subtext": "Ingen venner/grupper vil blive påvirket", - "whitelist_state_option": "Ingen undtagen...", - "whitelist_state_subtext": "Kun {count} venner/grupper vil blive påvirket af denne regel", - "whitelist_state_button": "Vælg tilladte venner/grupper", - "blacklist_state_option": "Alle undtagen...", - "blacklist_state_subtext": "Alle undtagen {count} venner/grupper vil blive påvirket af denne regel", - "blacklist_state_button": "Vælg udelukkede venner/grupper", - "clear_list_button": "Ryd venne-/gruppeliste", - "dialog_clear_confirmation_text": "Er du sikker på, at du vil rydde listen?" - }, - "social": { - "friends_tab": "Venner", - "groups_tab": "Grupper", - "empty_hint": "(tom)", - "streaks_expiration_short": "{hours}t" - }, - "manage_scope": { - "logged_stories_button": "Vis loggede historier", - "e2ee_title": "End-to-End-kryptering", - "rules_title": "Regler", - "participants_text": "{count} deltagere", - "not_found": "Ikke fundet", - "streaks_title": "Striber", - "streaks_length_text": "Længde: {length}", - "streaks_expiration_text": "Udløber om {eta}", - "streaks_expiration_text_expired": "Udløbet", - "reminder_button": "Indstil påmindelse", - "delete_scope_confirm_dialog_title": "Er du sikker på, at du vil slette en {scope}?", - "notes_placeholder": "Klik for at tilføje en note", - "invalid_key_size_32_bytes": "Ugyldig nøglestørrelse (skal være 32 bytes)", - "successfully_imported_key": "Nøgle importeret", - "failed_to_import_key": "Kunne ikke importere nøgle: {message}", - "export_base64_button": "Eksporter Base64", - "import_base64_button": "Importer Base64" - }, - "logged_stories": { - "story_failed_to_load": "Kunne ikke indlæse historie", - "no_stories": "Ingen historier fundet", - "save_from_cache_button": "Gem fra cache", - "downloaded_to_path": "Downloadet til {path}", - "download_failed": "Download mislykkedes: {message}", - "posted_at": "Opslået den {date}", - "created_at": "Oprettet den {date}", - "failed_to_open_file": "Kunne ikke åbne fil. Tjek logs for mere info", - "failed_to_get_file": "Kunne ikke hente fil" - }, - "messaging_preview": { - "processed_messages_toast": "Behandlede {count} beskeder", - "processed_messages_text": "Behandlede {count} beskeder", - "close_button_description": "Luk", - "bridge_connection_failed": "Kunne ikke oprette forbindelse til bro. Sørg for, at Snapchat kører i baggrunden", - "bridge_init_failed": "Kunne ikke initialisere beskedbro. Sørg for, at Snapchat kører i baggrunden", - "message_fetch_failed": "Kunne ikke hente beskeder", - "no_message_hint": "Ingen besked", - "save_selection_option": "Gem valg", - "save_all_option": "Gem alt", - "unsave_selection_option": "Fjern valg", - "unsave_all_option": "Fjern alt", - "mark_selection_as_seen_option": "Marker valgt snap som set", - "mark_all_as_seen_option": "Marker alle snaps som set", - "delete_selection_option": "Slet valg", - "delete_all_option": "Slet alt" - }, - "logger_history": { - "download_started_toast": "Download startet!", - "download_success_toast": "Downloadet til {path}", - "download_failed_toast": "Kunne ikke downloade {message}", - "edited_at_text": "{message} (redigeret den {date})", - "download_button": "Download", - "select_conversation_placeholder": "Vælg en samtale", - "close_button_description": "Luk", - "search_button_description": "Søg", - "list_friend_format": "Ven {name}", - "list_group_format": "Gruppe {name}", - "no_more_messages": "Ikke flere beskeder", - "reverse_order_checkbox": "Omvendt rækkefølge", - "chat_attachment": "Vedhæftning {index}", - "empty_message": "Tom chatbesked", - "message_parse_failed": "Kunne ikke parse besked", - "unknown_sender": "Ukendt afsender", - "download_attachment_failed_toast": "Kunne ikke downloade vedhæftning", - "log_header_format": "{username} ({type}) - {date}" - }, - "file_imports": { - "import_file_button": "Importer fil", - "file_not_found": "Fil ikke fundet", - "file_import_failed": "Kunne ikke importere fil: {error}", - "file_imported": "Fil importeret", - "file_delete_failed": "Kunne ikke slette fil", - "no_files_hint": "Her kan du importere filer til brug i Snapchat. Tryk på knappen nedenfor for at importere en fil." - }, - "better_location": { - "spoofed_coordinates_title": "Lat {latitude}, LNG {longitude}", - "save_coordinates_dialog_title": "Gem koordinater", - "saved_name_dialog_hint": "Gemt navn", - "latitude_dialog_hint": "Breddegrad", - "longitude_dialog_hint": "Længdegrad", - "save_dialog_button": "Gem", - "choose_location_button": "Vælg placering", - "teleport_to_friend_button": "Teleporter til ven", - "spoof_location_toggle": "Spoof placering", - "suspend_location_updates": "Suspender placeringsopdateringer", - "saved_coordinates_title": "Gemte koordinater", - "no_saved_coordinates_hint": "Ingen gemte koordinater", - "delete_dialog_title": "Slet gemt koordinat", - "delete_dialog_message": "Er du sikker på, at du vil slette dette gemte koordinat?", - "teleport_to_friend_title": "Teleporter til ven", - "search_bar": "Søg", - "no_friends_map": "Ingen venner på kortet", - "no_friends_found": "Ingen venner fundet", - "edit_location_button_description": "Rediger placering", - "add_icon_description": "Tilføj", - "edit_icon_description": "Rediger", - "delete_icon_description": "Slet" + "view_logger_history_button": "Se logger historik" } }, "dialogs": { "add_friend": { "title": "Tilføj ven eller gruppe", "search_hint": "Søg", - "fetch_error": "Kunne ikke hente data", + "fetch_error": "Dataene blev ikke hentet", "category_groups": "Grupper", - "category_friends": "Venner", - "participants_text": "{count} deltagere", - "search_icon_description": "Søg" + "category_friends": "Venner" }, "scripting_warning": { "title": "Advarsel", - "content": "PurrfectSnap indeholder et scriptværktøj, der tillader udførelse af brugerdefineret kode på din enhed. Vær yderst forsigtig og installer kun moduler fra kendte, pålidelige kilder. Uautoriserede eller ubekræftede moduler kan udgøre sikkerhedsrisici for dit system." + "content": "SnapEnhance inkluderer et scriptværktøj, der tillader udførelse af brugerdefineret kode på din enhed. Vær ekstrem forsigtig og installer kun moduler fra kendte, pålidelige kilder. Uautoriserede eller uverificerede moduler kan udgøre sikkerhedsrisici for dit system." }, "reset_config": { "title": "Nulstil konfiguration", "content": "Er du sikker på, at du vil nulstille konfigurationen?", - "success_toast": "Konfiguration nulstillet" - }, - "export_config": { - "title": "Eksporter følsomme data?", - "content": "Vil du eksportere konfigurationen med følsomme data? (f.eks. placeringskoordinater osv.)" + "success_toast": "Konfigurations nulstilling lykkedes" }, "messaging_action": { "title": "Vælg indholdstyper, der skal behandles", "select_all_button": "Vælg alle" - }, - "file_imports": { - "no_files_settings_hint": "Ingen filer fundet. Sørg for, at du har importeret de nødvendige filer i sektionen Filimport", - "settings_select_file_hint": "Vælg en importeret fil" - }, - "quick_actions_dialog": { - "title": "Rediger hurtige handlinger", - "subtitle": "Vælg og tilpas størrelsen på dine hurtige handlinger." } - }, - "friend_tracker": { - "rules_tab": "Regler", - "logs_tab": "Logfiler", - "export_dialog_title": "Eksporter", - "bulk_export_button": "Masseeksport", - "individual_export_button": "Individuel eksport", - "invalid_import_type_dialog_title": "Ugyldig importtype", - "invalid_import_type_dialog_text": "Den valgte fil er ikke kompatibel med denne importtype. Vælg venligst den korrekte importtype.", - "import_dialog_title": "Importer", - "bulk_import_button": "Masseimport", - "individual_import_button": "Individuel import", - "import_button_description": "Importer", - "export_button_description": "Eksporter", - "export_button": "Eksporter", - "delete_button_description": "Slet", - "delete_button": "Slet", - "catalog_button_description": "Katalog", - "catalog_button": "Katalog", - "add_rule_button_description": "Tilføj regel", - "add_rule_button": "Tilføj regel", - "no_rules_found": "Ingen regler fundet", - "empty_rule_name": "(tom)", - "events_suffix": "begivenheder", - "scopes_suffix": "omfang", - "select_rule_to_export_title": "Vælg regel, der skal eksporteres", - "deleted_logs_toast": "Slettede {count} logfiler", - "delete_logs_dialog_title": "Slet logfiler?", - "deleting_logs_dialog_text": "Sletter {count} logfiler...", - "delete_logs_dialog_confirm_text": "Dette sletter logfiler baseret på det aktuelle filter og søgeforespørgslen. Denne handling kan ikke fortrydes.", - "exported_logs_toast": "Eksporterede logfiler!", - "export_logs_failed_toast": "Kunne ikke eksportere logfiler. Tjek logcat for flere detaljer.", - "export_logs_dialog_title": "Eksporter logfiler?", - "exporting_logs_dialog_text": "Eksporterer logfiler...", - "export_logs_dialog_confirm_text": "Dette eksporterer logfiler baseret på det aktuelle filter og søgeforespørgslen.", - "export_as_button": "Eksporter som {type}", - "filters_title": "Filtre", - "search_by_label": "Søg efter", - "newest_first_label": "Nyeste først", - "since_label": "Siden", - "until_label": "Indtil", - "pick_a_date_button": "Vælg en dato", - "search_placeholder": "Søg", - "filter_button_description": "Filter", - "clear_button_description": "Ryd", - "no_logs_found": "Ingen logfiler fundet", - "log_event_format": "{event} i {conversation}", - "condition_only_inside_conversation": "Kun når jeg er i samtalen", - "condition_only_outside_conversation": "Kun når jeg er uden for samtalen", - "condition_only_when_app_active": "Kun når Snapchat er aktiv", - "condition_only_when_app_inactive": "Kun når Snapchat er inaktiv", - "condition_no_push_notification_when_app_active": "Ingen push-besked, når Snapchat er aktiv", - "add_event_dialog_title": "Tilføj begivenhed", - "event_type_label": "Begivenhedstype", - "triggers_title": "Udløsere", - "conditions_title": "Betingelser", - "add_button": "Tilføj", - "default_rule_name": "Brugerdefineret regel", - "discard_changes_dialog_title": "Kassér ændringer?", - "discard_changes_dialog_text": "Du har ugemte ændringer. Er du sikker på, at du vil kassere dem?", - "discard_button": "Kassér", - "cannot_save_rule_dialog_title": "Kan ikke gemme regel", - "cannot_save_rule_dialog_text": "En regel skal have mindst én begivenhed for at kunne gemmes.", - "duplicate_rule_name_dialog_title": "Dubletregelnavn", - "duplicate_rule_name_dialog_text": "Der findes allerede en regel med dette navn. Vælg venligst et andet navn.", - "delete_rule_dialog_title": "Slet regel", - "delete_rule_dialog_text": "Er du sikker på, at du vil slette denne regel?", - "new_rule_title": "Ny regel", - "edit_rule_title": "Rediger regel", - "back_button_description": "Tilbage", - "save_button_description": "Gem", - "general_section_title": "Generelt", - "rule_name_label": "Regelnavn", - "author_name_label": "Forfatternavn", - "scope_section_title": "Omfang", - "scope_all": "Alle", - "scope_whitelist": "Hvidliste", - "scope_blacklist": "Sortliste", - "select_friends_groups_button": "Vælg venner/grupper ({count})", - "events_section_title": "Begivenheder", - "add_event_button": "Tilføj begivenhed", - "no_events_text": "Ingen begivenheder" - }, - "friend_tracker_catalog": { - "download_failed": "Download mislykkedes: {code}", - "error": "Fejl: {message}", - "no_repos_added": "Ingen depoter tilføjet.", - "no_rules_available": "Ingen regler tilgængelige fra noget depot.", - "by_author": "af {author}", - "imported_button": "Importeret", - "import_button": "Importer", - "title": "Venne-tracker-katalog", - "manage_repos_description": "Administrer depoter" - }, - "friend_tracker_export": { - "title": "Eksporter regler", - "back_button_description": "Tilbage", - "exported_toast": "Venne-tracker-regler eksporteret!", - "export_failed_toast": "Kunne ikke eksportere regler: {message}", - "save_button": "Gem", - "expand_button_description": "Udvid" - }, - "friend_tracker_import": { - "title": "Importer regler", - "back_button_description": "Tilbage", - "imported_toast": "Venne-tracker-regler importeret!", - "import_failed_toast": "Kunne ikke importere regler: {message}", - "confirm_button": "Bekræft", - "expand_button_description": "Udvid" - }, - "friend_tracker_repos": { - "invalid_repo_title": "Ugyldigt depot", - "add_repo_button": "Tilføj depot", - "add_repo_dialog_title": "Tilføj depot-URL", - "repo_url_label": "Depot-URL", - "repo_added_toast": "Depot tilføjet!", - "invalid_repo_error": "Dette ser ikke ud til at være et gyldigt venne-tracker-depot.", - "add_repo_failed_toast": "Kunne ikke tilføje depot: {message}", - "add_button": "Tilføj", - "no_repos_added": "Ingen depoter tilføjet", - "remove_button": "Fjern", - "remove_repo_dialog_title": "Fjern depot", - "remove_repo_dialog_text": "Er du sikker på, at du vil fjerne dette depot?" - }, - "navigation": { - "tracker_tab_label": "Tracker", - "customize_bottom_bar_title": "Tilpas nederste bjælke", - "customize_bottom_bar_subtitle": "Omarranger, tilføj eller fjern faner. Maksimalt fem.", - "shown_tabs_title": "Viste faner", - "no_tabs_selected_text": "Ingen faner valgt", - "available_tabs_title": "Tilgængelige faner", - "reset_button": "Nulstil", - "done_button": "Færdig" - }, - "scripting": { - "script_already_installed": "Script allerede installeret!", - "downloading_script": "Downloader script...", - "script_downloaded": "Script {name} downloadet!", - "download_script_failed": "Kunne ikke downloade script. Tjek logfiler for flere detaljer", - "import_script_from_url_title": "Importer script fra URL", - "import_script_warning": "Advarsel: Importerede scripts kan være skadelige for din enhed. Importer kun scripts fra pålidelige kilder.", - "enter_url_label": "Indtast URL her:", - "script_imported": "Script {name} importeret!", - "import_failed": "Kunne ikke importere script. {message}. Tjek logfiler for flere detaljer", - "import_button": "Importer", - "update_module_button": "Opdater modul", - "updating_script": "Opdaterer script {name}...", - "module_not_found": "Modul ikke fundet", - "updated_script": "Opdaterede {name} til version {version}", - "update_module_failed": "Kunne ikke opdatere modul. Tjek logfiler for flere detaljer", - "edit_module_button": "Rediger modul", - "open_module_failed": "Kunne ikke åbne modulfil. Tjek logfiler for flere detaljer", - "clear_module_data_button": "Ryd moduldata", - "module_data_cleared": "Moduldata ryddet!", - "clear_module_data_failed": "Kunne ikke rydde moduldata. Tjek logfiler for flere detaljer", - "delete_module_button": "Slet modul", - "deleted_script": "Slettede script {name}!", - "delete_module_failed": "Kunne ikke slette modul. Tjek logfiler for flere detaljer", - "actions_title": "Handlinger", - "no_description": "Ingen beskrivelse", - "update_available": "Opdatering tilgængelig: {version}", - "actions_button": "Handlinger", - "loaded_script": "Indlæste script {name}", - "unloaded_script": "Aflæste script {name}", - "enable_script_failed": "Kunne ikke aktivere script. Tjek logfiler for flere detaljer", - "disable_script_failed": "Kunne ikke deaktivere script. Tjek logfiler for flere detaljer", - "select_scripts_folder_toast": "Vælg venligst din scriptmappe!", - "manage_repos_button": "Administrer depoter", - "import_from_url_button": "Importer fra URL", - "open_scripts_folder_button": "Åbn scriptmappe", - "no_settings_for_module": "Dette modul har ingen indstillinger", - "installed_scripts_tab": "Installerede scripts", - "catalog_tab": "Katalog", - "no_scripts_folder_selected_title": "Ingen scriptmappe valgt", - "select_folder_button": "Vælg mappe", - "no_scripts_found_title": "Ingen scripts fundet.", - "use_catalog_to_add_scripts": "Brug katalogfanen til at tilføje scripts!", - "ok_button_timeout": "OK ({timeout})", - "documentation_button": "Dokumentation", - "catalog": { - "script_already_installed": "Script allerede installeret!", - "download_failed": "Download mislykkedes: {code}", - "script_downloaded": "Script downloadet!", - "could_not_create_file": "Kunne ikke oprette fil.", - "no_scripts_folder_selected": "Ingen scriptmappe valgt.", - "error": "Fejl: {message}", - "no_repos_added": "Ingen depoter tilføjet.", - "repo_list_info": "Her kan du finde en liste over depoter: ", - "link_text": "Forbindelse", - "no_scripts_available": "Ingen scripts tilgængelige fra noget depot.", - "by_author": "af {author}", - "version": "Version: {version}", - "installed_button": "Installeret", - "download_button": "Download" - }, - "repos": { - "invalid_repo_title": "Ugyldigt depot", - "add_repo_button": "Tilføj depot", - "add_repo_dialog_title": "Tilføj depot-URL", - "repo_url_label": "Depot-URL", - "repo_added_toast": "Depot tilføjet!", - "invalid_repo_error": "Dette ser ikke ud til at være et gyldigt scriptdepot.", - "add_repo_failed_toast": "Kunne ikke tilføje depot: {message}", - "add_button": "Tilføj", - "no_repos_added": "Ingen depoter tilføjet", - "remove_button": "Fjern", - "remove_repo_dialog_title": "Fjern depot", - "remove_repo_dialog_text": "Er du sikker på, at du vil fjerne dette depot?" - } - }, - "features": { - "config_import": { - "title": "Bekræft import", - "back_button_description": "Tilbage", - "config_imported_toast": "Konfiguration importeret!", - "confirm_button": "Bekræft", - "expand_button_description": "Udvid", - "enable_feature": "Aktiver funktion", - "enabled": "Aktiveret", - "disabled": "Deaktiveret" - }, - "config_export": { - "title": "Eksportoversigt", - "back_button_description": "Tilbage", - "save_button": "Gem", - "expand_button_description": "Udvid", - "enable_feature": "Aktiver funktion", - "enabled": "Aktiveret", - "disabled": "Deaktiveret" - } - }, - "manage_repos": { - "title": "Administrer {type} depoter", - "add_repo_button": "Tilføj depot", - "add_repo_dialog_title": "Tilføj depot-URL", - "repo_url_label": "Depot-URL", - "repo_added_successfully": "Depot tilføjet!", - "add_repo_failed": "Kunne ikke tilføje depot: {message}", - "add_button": "Tilføj", - "no_repos_added": "Ingen depoter tilføjet", - "remove_button": "Fjern" } }, "rules": { - "toasts": { - "enabled": "{ruleName} aktiveret", - "disabled": "{ruleName} deaktiveret" - }, "modes": { "blacklist": "Sortlistetilstand", - "whitelist": "Hvidlistetilstand" + "whitelist": "Whitelist tilstand" }, "properties": { "auto_download": { - "name": "Automatisk download", + "name": "Auto-download", "description": "Download automatisk snaps, når du ser dem", "options": { - "blacklist": "Ekskluder fra automatisk download", - "whitelist": "Automatisk download" + "blacklist": "Udeluk fra automatisk download", + "whitelist": "Auto-hentning" } }, "stealth": { - "name": "Stealth-tilstand", - "description": "Forhindrer nogen i at vide, at du har åbnet deres snaps/chats og samtaler", + "name": "Stealth Tilstand", + "description": "Forhindrer alle i at vide, at du har åbnet deres Snaps/Chats og samtaler", "options": { - "blacklist": "Ekskluder fra Stealth-tilstand", - "whitelist": "Stealth-tilstand" + "blacklist": "Udeluk fra Stealth Mode", + "whitelist": "Stealth Tilstand" } }, "auto_save": { - "name": "Automatisk gem", - "description": "Gemmer chatbeskeder, når du ser dem", + "name": "Gem Automatisk", + "description": "Gemmer chatbeskeder når de vises", "options": { - "blacklist": "Ekskluder fra automatisk gem", - "whitelist": "Automatisk gem" - } - }, - "unsaveable_messages": { - "name": "Ugemmelige beskeder", - "description": "Forhindrer, at beskeder gemmes i chat af andre personer", - "options": { - "blacklist": "Ekskluder fra ugemmelige beskeder", - "whitelist": "Ugemmelige beskeder" - } - }, - "auto_open_snaps": { - "name": "Åbn automatisk snaps", - "description": "Åbner automatisk snaps, når du modtager dem", - "options": { - "blacklist": "Ekskluder fra automatisk åbning af snaps", - "whitelist": "Åbn automatisk snaps" + "blacklist": "Udeluk fra automatisk lagring", + "whitelist": "Auto-gem" } }, "hide_friend_feed": { - "name": "Skjul fra vennefeed" + "name": "Skjul fra venskabsfeed" }, "e2e_encryption": { - "name": "Brug E2E-kryptering" + "name": "Brug E2E Kryptering" }, "pin_conversation": { "name": "Fastgør samtale" }, - "exclude_message_logger": { - "name": "Ekskluder fra besked-logger" + "unsaveable_messages": { + "name": "Meddelelser, der ikke kan gemmes", + "description": "Forhindrer beskeder i at blive gemt i chat af andre personer", + "options": { + "blacklist": "Udelad fra meddelelser, der ikke kan gemmes", + "whitelist": "Meddelelser, der ikke kan gemmes" + } + }, + "auto_open_snaps": { + "name": "Auto åbn snaps", + "description": "Åbner automatisk Snaps, når de modtages", + "options": { + "blacklist": "Udeluk fra automatisk åbning af Snaps", + "whitelist": "Auto-åbn Snaps" + } } - } - }, - "actions": { - "clean_snapchat_cache": { - "name": "Ryd Snapchat-cache", - "description": "Rydder Snapchat-cachen" }, - "manage_friend_list": { - "name": "Administrer venneliste", - "description": "Importer/eksporter din venneliste, når du sikkerhedskopierer" - }, - "export_chat_messages": { - "name": "Eksporter chatbeskeder", - "description": "Eksporterer samtalebeskeder til en JSON/HTML/TXT-fil" - }, - "export_memories": { - "name": "Eksporter minder", - "description": "Eksporterer minder til en ZIP-fil" - }, - "bulk_messaging_action": { - "name": "Massebeskedhandling", - "description": "Udfører handlinger som at slette venner eller massesletning af samtaler" - }, - "regen_mappings": { - "name": "Genopbyg kortlægninger", - "description": "Genopbyg kortlægninger manuelt" - }, - "change_language": { - "name": "Skift sprog", - "description": "Skift sprog i PurrfectSnap" - }, - "file_imports": { - "name": "Filimport", - "description": "Importer filer til brug i Snapchat" - }, - "friend_tracker": { - "name": "Venne-tracker", - "description": "Følg dine venner på Snapchat" - }, - "logger_history": { - "name": "Loggerhistorik", - "description": "Se historikken for loggede beskeder" + "toasts": { + "enabled": "{ruleName} aktiveret", + "disabled": "{ruleName} deaktiveret" } }, "features": { "notices": { "unstable": "⚠️ Ustabil", "ban_risk": "⚠️ Denne funktion kan medføre forbud", - "internal_behavior": "⚠️ Dette kan ødelægge Snapchats interne adfærd" + "internal_behavior": "⚠️ Dette kan ødelægge Snapchat intern opførsel" }, "properties": { "downloader": { - "name": "Downloader", - "description": "Download Snapchat-medier", + "name": "Henter", + "description": "Download Snapchat Medie", "properties": { "save_folder": { - "name": "Gem mappe", - "description": "Vælg den mappe, som alle medier skal downloades til" + "name": "Gem Mappe", + "description": "Vælg den mappe som alle medier skal downloades til" }, "auto_download_sources": { - "name": "Automatiske downloadkilder", - "description": "Vælg de kilder, der skal downloades fra automatisk" + "name": "Download Kilder Automatisk", + "description": "Vælg de kilder, der skal downloades automatisk fra" }, "prevent_self_auto_download": { - "name": "Forhindre selv-automatisk download", - "description": "Forhindrer, at dine egne snaps downloades automatisk" + "name": "Forhindr Automatisk Download", + "description": "Forhindrer dine egne Snaps i automatisk at blive hentet" }, "path_format": { - "name": "Sti-format", - "description": "Angiv filsti-formatet" + "name": "Sti Format", + "description": "Angiv filstiens format" }, "allow_duplicate": { - "name": "Tillad dubletter", + "name": "Tillad Dupliker", "description": "Tillader, at de samme medier downloades flere gange" }, "merge_overlays": { - "name": "Flet overlejringer", - "description": "Kombinerer teksten og mediet i en snap i en enkelt fil" + "name": "Flet Overlejringer", + "description": "Kombinerer teksten og medierne for en Snap i en enkelt fil" }, "force_image_format": { - "name": "Tving billedformat", - "description": "Tvinger billeder til at blive gemt i et bestemt format" + "name": "Gennemtving Billedformat", + "description": "Tving billeder til at blive gemt i et angivet format" }, "force_voice_note_format": { - "name": "Tving stemmebeskedformat", - "description": "Tvinger stemmebeskeder til at blive gemt i et bestemt format" - }, - "auto_download_voice_notes": { - "name": "Download automatisk stemmebeskeder", - "description": "Downloader automatisk stemmebeskeder, når de afspilles" + "name": "Gennemtving Stemme Note Format", + "description": "Tving billeder til at blive gemt i et angivet format" }, "download_profile_pictures": { - "name": "Download profilbilleder", - "description": "Giver dig mulighed for at downloade profilbilleder fra profilsiden" - }, - "opera_download_button": { - "name": "Opera-downloadknap", - "description": "Tilføjer en downloadknap i øverste højre hjørne, når du ser en snap.\nLangt tryk på knapper vil tvinge download" - }, - "download_context_menu": { - "name": "Download-kontekstmenu", - "description": "Giver dig mulighed for at downloade/forhåndsvise beskeder fra en samtale eller en historie ved hjælp af kontekstmenuen.\nLangt tryk på knapper vil tvinge download" + "name": "Download Profilbilleder", + "description": "Tillader dig at downloade profilbilleder fra profilsiden" }, "ffmpeg_options": { "name": "FFmpeg-indstillinger", - "description": "Angiv yderligere FFmpeg-indstillinger", + "description": "Angiv yderligere FFmpeg indstillinger", "properties": { "threads": { "name": "Tråde", - "description": "Antallet af tråde, der skal bruges" + "description": "Mængden af tråde der skal bruges" }, "preset": { - "name": "Forudindstilling", - "description": "Indstil konverteringshastigheden" + "name": "Forvalg", + "description": "Indstil hastigheden for konverteringen" }, "constant_rate_factor": { - "name": "Konstant hastighedsfaktor", - "description": "Indstil den konstante hastighedsfaktor for videokoderen\nFra 0 til 51 for libx264" + "name": "Konstant Rate Faktor", + "description": "Indstil den konstante hastighedsfaktor for video-encoder\nFra 0 til 51 for libx264" }, "video_bitrate": { - "name": "Video-bitrate", - "description": "Indstil video-bitraten (kbps)" + "name": "Videobit-hastighed", + "description": "Indstil videoens bitrate (kbps)" }, "audio_bitrate": { - "name": "Lyd-bitrate", - "description": "Indstil lyd-bitraten (kbps)" + "name": "Audiobit-hastighed", + "description": "Indstil videoens bitrate (kbps)" }, "custom_video_codec": { - "name": "Brugerdefineret videokodec", - "description": "Indstil en brugerdefineret videokodec (f.eks. libx264)" + "name": "Brugerdefineret Lydkode", + "description": "Angiv en brugerdefineret Video Codec (f.eks. libx264)" }, "custom_audio_codec": { - "name": "Brugerdefineret lydkodek", - "description": "Indstil en brugerdefineret lydkodek (f.eks. AAC)" + "name": "Brugerdefineret Lydkode", + "description": "Angiv en brugerdefineret Video Codec (f.eks. libx264)" } } }, "logging": { - "name": "Logning", - "description": "Viser toasts, når medier downloades" + "name": "Logging", + "description": "Viser toasts, når mediet downloades" + }, + "download_context_menu": { + "name": "Download kontekst menu", + "description": "Giver dig mulighed for at downloade/forhåndsvise beskeder fra en samtale eller en historie ved hjælp af kontekstmenuen.\nLangt tryk på knapperne vil tvinge download" + }, + "opera_download_button": { + "name": "Opera download knap", + "description": "Tilføjer en downloadknap i øverste højre hjørne, når du ser et Snap.\nLangt tryk på knapperne vil tvinge download" }, "custom_path_format": { - "name": "Brugerdefineret sti-format", - "description": "Angiv et brugerdefineret sti-format for downloadede medier\n\nTilgængelige variabler:\n - %username%\n - %source%\n - %hash%\n - %date_time%" + "name": "Brugerdefineret sti", + "description": "Angiv et brugerdefineret stiformat for downloadede medier\n\nTilgængelige variabler:\n- %brugernavn%\n- %kilde%\n- %hash%\n- %dato_tid%" } } }, @@ -755,182 +315,214 @@ "description": "Skift udseendet og fornemmelsen af Snapchat", "properties": { "enable_app_appearance": { - "name": "Aktiver indstillinger for app-udseende", - "description": "Aktiverer den skjulte indstilling for app-udseende\nKræves muligvis ikke på nyere Snapchat-versioner" + "name": "Aktiver App-udseende Indstillinger", + "description": "Aktiverer den skjulte App Udseende Indstilling\nKan ikke kræves i nyere Snapchat versioner" }, "friend_feed_message_preview": { - "name": "Forhåndsvisning af besked i vennefeed", - "description": "Viser en forhåndsvisning af de seneste beskeder i vennefeedet", + "name": "Forhåndsvisning Af Venne Feed Besked", + "description": "Viser en forhåndsvisning af de sidste beskeder i venskabsfeedet", "properties": { "amount": { "name": "Mængde", - "description": "Mængden af beskeder, der skal forhåndsvises" + "description": "Antallet af beskeder der skal forhåndsvises" } } }, - "snap_preview": { - "name": "Snap-forhåndsvisning", - "description": "Viser en lille forhåndsvisning ved siden af usete snaps i chat" - }, "bootstrap_override": { - "name": "Bootstrap-overskrivning", - "description": "Overskriver brugergrænsefladens bootstrap-indstillinger", + "name": "Bootstrap Overskriv", + "description": "Tilsidesætter indstillinger for brugergrænseflade bootstrap", "properties": { "app_appearance": { - "name": "App-udseende", - "description": "Indstiller et vedvarende app-udseende" + "name": "App Udseende", + "description": "Indstiller en vedvarende app-udseende" }, "home_tab": { - "name": "Hjem-fane", - "description": "Overskriver startfanen, når Snapchat åbnes" + "name": "Fanebladet Hjem", + "description": "Tilsidesætter fanen opstart, når du åbner Snapchat" } } }, - "force_amoled_theme": { - "name": "Amoled mørk tilstand", - "description": "Bruger en ægte sort baggrund til det mørke tema" - }, "map_friend_nametags": { - "name": "Forbedrede navneskilte til venner på kortet", - "description": "Forbedrer navneskiltene for venner på Snapkortet" - }, - "prevent_message_list_auto_scroll": { - "name": "Forhindre automatisk rulning af beskedliste", - "description": "Forhindrer, at beskedlisten ruller til bunden, når der sendes/modtages en besked" + "name": "Forbedrede Vennekortnavne", + "description": "Forbedrer Nametags af venner på Snapmap" }, "streak_expiration_info": { - "name": "Vis oplysninger om udløb af streak", - "description": "Viser en timer for udløb af streak ved siden af streak-tælleren" + "name": "Vis Streak Udløbsinfo", + "description": "Viser en Streak- udløbstimer ved siden af Streaks tælleren" }, "hide_friend_feed_entry": { - "name": "Skjul post i vennefeed", - "description": "Skjuler en bestemt ven fra vennefeedet\nBrug den sociale fane til at administrere denne funktion" + "name": "Skjul Venne Feed Post", + "description": "Skjuler en bestemt ven fra venskabsfeed\nBrug fanen social til at håndtere denne funktion" }, "hide_streak_restore": { - "name": "Skjul gendannelse af streak", - "description": "Skjuler knappen Gendan i vennefeedet" + "description": "Skjuler knappen Gendan i vennefeedet", + "name": "Skjul Streak Gendan" }, - "hide_quick_add_suggestions": { - "name": "Skjul forslag til hurtig tilføjelse", - "description": "Fjerner forslag til hurtig tilføjelse af venner" + "hide_ui_components": { + "name": "Skjul UI Komponenter", + "description": "Vælg hvilke brugergrænsefladekomponenter der skal skjules" + }, + "disable_spotlight": { + "name": "Deaktivér Spotlight", + "description": "Deaktiverer Spotlight siden" + }, + "friend_feed_menu_buttons": { + "name": "Ven Feed Menu-Knapper", + "description": "Vælg hvilke knapper der skal vises i menulinjen Venne Feed" + }, + "enable_friend_feed_menu_bar": { + "name": "Ven Feed Menu-Knapper", + "description": "Aktiverer den nye vennefeed menulinjen" + }, + "vertical_story_viewer": { + "description": "Aktiverer den lodrette historiefremviser for alle historier", + "name": "Lodret historiefremviser" + }, + "stealth_mode_indicator": { + "name": "Stealth Tilstand Indikator", + "description": "Tilføjer en 👻 emoji ved siden af samtaler i stealth tilstand" }, "hide_story_suggestions": { "name": "Skjul historieforslag", - "description": "Fjerner forslag fra historiesiden" - }, - "hide_ui_components": { - "name": "Skjul brugergrænsefladekomponenter", - "description": "Vælg, hvilke brugergrænsefladekomponenter der skal skjules" - }, - "opera_media_quick_info": { - "name": "Hurtige oplysninger om Opera-medier", - "description": "Viser nyttige oplysninger om medier, såsom oprettelsesdato, i Opera-fremviserens kontekstmenu" - }, - "old_bitmoji_selfie": { - "name": "Gammel Bitmoji-selfie", - "description": "Gendanner Bitmoji-selfies fra ældre Snapchat-versioner" - }, - "disable_spotlight": { - "name": "Deaktiver Spotlight", - "description": "Deaktiverer Spotlight-siden" - }, - "friend_feed_menu_buttons": { - "name": "Menuknapper i vennefeed", - "description": "Vælg, hvilke knapper der skal vises i vennefeed-menuen" - }, - "auto_close_friend_feed_menu": { - "name": "Luk automatisk vennefeed-menu", - "description": "Lukker automatisk vennefeed-menuen efter tryk på en indstillingsknap" - }, - "vertical_story_viewer": { - "name": "Lodret historiefremviser", - "description": "Aktiverer den lodrette historiefremviser for alle historier" - }, - "enable_friend_feed_menu_bar": { - "name": "Menulinje i vennefeed", - "description": "Aktiverer den nye menulinje i vennefeed" + "description": "Fjerner forslag fra siden Historier" }, "message_indicators": { - "name": "Beskedindikatorer", - "description": "Tilføjer specifikke indikatorikoner til beskeder\nBemærk: Indikatorer er muligvis ikke 100 % nøjagtige" - }, - "stealth_mode_indicator": { - "name": "Indikator for stealth-tilstand", - "description": "Tilføjer en 👻-emoji ved siden af samtaler i stealth-tilstand" + "name": "Meddelelsesindikatorer", + "description": "Tilføjer specifikke indikatorikoner til beskeder\nBemærk: indikatorer er muligvis ikke 110% nøjagtige" }, "edit_text_override": { - "name": "Overskriv redigering af tekst", - "description": "Overskriver tekstfeltets adfærd" + "name": "Rediger tekst tilsidesættelse", + "description": "Tilsidesætter tekstfelt adfærd" }, - "prevent_forced_keyboard": { - "name": "Forhindre tvunget tastatur", - "description": "Forhindrer Snapchat i automatisk at poppe tastaturet op, når du åbner en samtale" + "snap_preview": { + "name": "Snap-forhåndsvisning", + "description": "Viser en lille forhåndsvisning ud for usete snaps i chat" }, - "settings_menu": { - "name": "Indstillingsmenu", - "description": "Ændrer den måde, du åbner PurrfectSnap-menuen på", - "options": { - "default": "Standard", - "legacy": "Forældet" - } + "prevent_message_list_auto_scroll": { + "name": "Forhindre meddelelse chat i automatisk rulning", + "description": "Forhindrer beskedlisten i at rulle til bunden, når du sender/modtager en besked" + }, + "old_bitmoji_selfie": { + "name": "Gammel Bitmoji Selfie", + "description": "Giver Bitmoji-selfies fra ældre Snapchat-versioner tilbage" + }, + "opera_media_quick_info": { + "description": "Viser nyttig information om medier såsom oprettelsesdato i opera fremviser kontekstmenu", + "name": "Opera Media Hurtig info" } } }, "messaging": { - "name": "Beskeder", - "description": "Skift, hvordan du interagerer med venner", + "name": "Meddelelser", + "description": "Skift hvordan du interagerer med venner", "properties": { - "bypass_screenshot_detection": { - "name": "Omgå registrering af skærmbillede", - "description": "Forhindrer Snapchat i at registrere, når du tager et skærmbillede" - }, "anonymous_story_viewing": { - "name": "Anonym visning af historie", - "description": "Forhindrer nogen i at vide, at du har set deres historie" - }, - "prevent_story_rewatch_indicator": { - "name": "Forhindre indikator for genafspilning af historie", - "description": "Forhindrer nogen i at vide, at du har set deres historie igen" - }, - "hide_peek_a_peek": { - "name": "Skjul Peek-a-Peek", - "description": "Forhindrer, at der sendes en notifikation, når du halvt swiper ind i en chat" + "name": "Anonym Historievisning", + "description": "Forhindrer alle i at kende du har set deres historie" }, "hide_bitmoji_presence": { - "name": "Skjul Bitmoji-tilstedeværelse", - "description": "Forhindrer, at din Bitmoji popper op, mens du er i chat" + "name": "Skjul Bitmoji Tilstedeværelse", + "description": "Forhindrer din Bitmoji i at dukke op, mens du er i Chat" }, "hide_typing_notifications": { - "name": "Skjul notifikationer om skrivning", - "description": "Forhindrer nogen i at vide, at du skriver en besked" + "name": "Skjul Skrivenotifikationer", + "description": "Forhindrer alle i at vide, at du skriver en besked" }, "unlimited_snap_view_time": { - "name": "Ubegrænset visningstid for snap", - "description": "Fjerner tidsbegrænsningen for visning af snaps" - }, - "auto_mark_as_read": { - "name": "Marker automatisk som læst", - "description": "Markerer automatisk beskeder/snaps som læst, selv når Stealth-tilstand er aktiveret" - }, - "mark_snap_as_seen_button": { - "name": "Knap til at markere snap som set", - "description": "Tilføjer en knap til at markere en snap som set, når du ser den.\nDette fungerer, selv når Stealth-tilstand er aktiveret" - }, - "skip_when_marking_as_seen": { - "name": "Spring over, når der markeres som set", - "description": "Springer automatisk til den næste snap, når en snap markeres som set.\nBrug i kombination med knappen Marker snap som set" - }, - "loop_media_playback": { - "name": "Gentag medieafspilning", - "description": "Gentager medieafspilning, når du ser snaps/historier" + "name": "Ubegrænset Snap Visningstid", + "description": "Fjerner tidsgrænsen for visning af Snaps" }, "disable_replay_in_ff": { - "name": "Deaktiver genafspilning i FF", - "description": "Deaktiverer muligheden for at genafspille med et langt tryk fra vennefeedet" + "name": "Deaktivér genafspilning i FF", + "description": "Deaktiverer evnen til at genspille med et langt tryk fra Vennefeed" + }, + "prevent_message_sending": { + "name": "Forhindre Besked Afsendelse", + "description": "Forhindrer afsendelse af visse typer beskeder" + }, + "better_notifications": { + "name": "Bedre Notifikationer", + "description": "Tilføjer mere information i modtagne notifikationer", + "properties": { + "media_preview": { + "name": "Medie forhåndsvisning", + "description": "Viser en forhåndsvisning af de valgte medietyper i notifikationen" + }, + "friend_add_source": { + "name": "Ven tilføjnings kilde", + "description": "Viser kilden til en venneanmodning i notifikationer" + }, + "reply_button": { + "name": "Svar knap", + "description": "Tilføjer en svarknap til notifikationen" + }, + "download_button": { + "name": "Hent knap", + "description": "Giver dig mulighed for at hente medier fra notifikationer" + }, + "mark_as_read_button": { + "name": "Markér som læst knap", + "description": "Giver dig mulighed for at markere en besked som læst fra notifikationen" + }, + "mark_as_read_and_save_in_chat": { + "description": "Tilføjer et mærke som læst og gem i chat-knap til notifikationen", + "name": "Markér som læst og gem i chat" + }, + "group_notifications": { + "name": "Gruppe notifikationer", + "description": "Gruppér notifikationer i en enkelt" + }, + "chat_preview": { + "name": "Chat forhåndsvisning", + "description": "Viser en forhåndsvisning af modtagne beskeder i notifikationen" + }, + "media_caption": { + "name": "Medie tekst", + "description": "Viser den vedhæftede billedtekst af medier i notifikationen" + }, + "stacked_media_messages": { + "name": "Stablede medie beskeder", + "description": "Kombinerer flere mediebeskeder i én tekstmeddelelse, når de ikke kan forhåndsvises. Brug i kombination med Chat forhåndsvisning" + } + } + }, + "notification_blacklist": { + "name": "Notifikation Sortliste", + "description": "Vælg notifikationer som skal blive blokeret" + }, + "message_logger": { + "name": "Besked Logger", + "description": "Forhindrer beskeder i at blive slettet", + "properties": { + "message_filter": { + "name": "Meddelelses filter", + "description": "Vælg, hvilke meddelelser der skal logges (tom for alle meddelelser)" + }, + "keep_my_own_messages": { + "name": "Behold mine egne beskeder", + "description": "Forhindrer dine egne beskeder i at blive slettet" + }, + "auto_purge": { + "name": "Automatisk udrensning", + "description": "Sletter automatisk cachelagrede meddelelser, der er ældre end det angivne tidsrum" + } + } + }, + "auto_save_messages_in_conversations": { + "name": "Gem Automatisk Beskeder", + "description": "Gem automatisk alle beskeder i samtaler" + }, + "gallery_media_send_override": { + "name": "Galleri Medier Send Overskriv", + "description": "Spoofs mediekilden, når du sender fra Galleri" + }, + "prevent_story_rewatch_indicator": { + "name": "Indikator for at forhindre gense af historie", + "description": "Forhindrer nogen i at vide, at du har genset deres historie" }, "half_swipe_notifier": { - "name": "Notifikation om halvt swipe", - "description": "Giver dig besked, når nogen halvt swiper ind i en samtale", + "name": "Halv Swipe Meddeler", + "description": "Giver dig besked, når nogen stryger halvt ind i en samtale", "properties": { "min_duration": { "name": "Minimum varighed", @@ -938,167 +530,107 @@ }, "max_duration": { "name": "Maksimal varighed", - "description": "Maksimal varighed af det halve swipe (i sekunder)" + "description": "Den maksimale varighed af det halve swipe (i sekunder)" } } }, - "call_start_confirmation": { - "name": "Bekræftelse af opkaldsstart", - "description": "Viser en bekræftelsesdialog, når et opkald startes" - }, - "unlimited_conversation_pinning": { - "name": "Ubegrænset fastgørelse af samtale", - "description": "Giver dig mulighed for at fastgøre et ubegrænset antal samtaler lokalt" - }, - "disable_snap_mode_restrictions": { - "name": "Deaktiver begrænsninger for snap-tilstand", - "description": "Giver dig mulighed for at se selvdestruerende snaps uden begrænsninger" - }, - "prevent_message_sending": { - "name": "Forhindre afsendelse af besked", - "description": "Forhindrer afsendelse af visse typer beskeder" - }, - "friend_mutation_notifier": { - "name": "Notifikation om venne-mutation", - "description": "Giver dig besked, når noget ændres i en vens profil" - }, - "better_notifications": { - "name": "Bedre notifikationer", - "description": "Tilføjer flere oplysninger i modtagne notifikationer", - "properties": { - "group_notifications": { - "name": "Gruppenotifikationer", - "description": "Grupperer notifikationer i en enkelt" - }, - "chat_preview": { - "name": "Chat-forhåndsvisning", - "description": "Viser en forhåndsvisning af modtagne beskeder i notifikationen" - }, - "media_preview": { - "name": "Medie-forhåndsvisning", - "description": "Viser en forhåndsvisning af de valgte medietyper i notifikationen" - }, - "media_caption": { - "name": "Mediebilledtekst", - "description": "Viser den vedhæftede billedtekst til medier i notifikationen" - }, - "stacked_media_messages": { - "name": "Stablede mediebeskeder", - "description": "Kombinerer flere mediebeskeder i en enkelt tekstnotifikation, når de ikke kan forhåndsvises. Brug i kombination med Chat-forhåndsvisning" - }, - "friend_add_source": { - "name": "Kilde til venneanmodning", - "description": "Viser kilden til en venneanmodning i notifikationen" - }, - "reply_button": { - "name": "Svar-knap", - "description": "Tilføjer en svar-knap til notifikationen" - }, - "smart_replies": { - "name": "Smarte svar", - "description": "Tilføjer foreslåede svar til notifikationer (Android 10+). Brug i kombination med Svar-knap" - }, - "download_button": { - "name": "Download-knap", - "description": "Giver dig mulighed for at downloade medier fra notifikationen" - }, - "mark_as_read_button": { - "name": "Knap til at markere som læst", - "description": "Giver dig mulighed for at markere en besked som læst fra notifikationen" - }, - "mark_as_read_and_save_in_chat": { - "name": "Marker som læst og gem i chat", - "description": "Tilføjer en knap til at markere som læst og gemme i chat til notifikationen" - } - } - }, - "notification_blacklist": { - "name": "Sortliste for notifikationer", - "description": "Vælg, hvilke notifikationer der skal blokeres" - }, - "message_logger": { - "name": "Besked-logger", - "description": "Forhindrer, at beskeder slettes", - "properties": { - "keep_my_own_messages": { - "name": "Behold mine egne beskeder", - "description": "Forhindrer, at dine egne beskeder slettes" - }, - "auto_purge": { - "name": "Automatisk rydning", - "description": "Sletter automatisk cachelagrede beskeder, der er ældre end den angivne tid" - }, - "message_filter": { - "name": "Beskedfilter", - "description": "Vælg, hvilke beskeder der skal logges (tom for alle beskeder)" - }, - "deleted_message_color": { - "name": "Farve på slettet besked", - "description": "Indstiller farven på slettede beskeder" - } - } - }, - "auto_save_messages_in_conversations": { - "name": "Gem automatisk beskeder", - "description": "Gemmer automatisk alle beskeder i samtaler" - }, - "gallery_media_send_override": { - "name": "Overskriv afsendelse af gallerimedier", - "description": "Spoofer mediekilden, når der sendes fra galleriet" - }, - "strip_media_metadata": { - "name": "Fjern mediemetadata", - "description": "Fjerner metadata fra medier, før de sendes som en besked" + "loop_media_playback": { + "name": "Løkke medie afspilning", + "description": "Løkke medie afspilning, når du ser Snaps / Stories" }, "bypass_message_retention_policy": { - "name": "Omgå politik for opbevaring af beskeder", - "description": "Forhindrer, at beskeder slettes, efter de er blevet set" + "name": "Omgå meddelelses opbevarings politik", + "description": "Forhindrer beskeder i at blive slettet efter at have set dem" + }, + "bypass_screenshot_detection": { + "name": "Omgå skærmbillede detektion", + "description": "Forhindrer Snapchat i at registrere, når du tager et skærmbillede" + }, + "hide_peek_a_peek": { + "name": "Skjul Kig-et-Kig", + "description": "Forhindrer besked i at blive sendt, når du stryger halvt ind i en chat" + }, + "call_start_confirmation": { + "name": "Bekræftelse af opkalds start", + "description": "Viser en bekræftelsesdialog, når du starter et opkald" + }, + "strip_media_metadata": { + "name": "Fjern Media Metadata", + "description": "Fjerner metadata fra medier før afsendelse af besked" }, "bypass_message_action_restrictions": { - "name": "Omgå begrænsninger for beskedhandlinger", - "description": "Giver dig mulighed for at reagere på en snap uden at have åbnet den eller at gemme en ugemmelig besked" + "name": "Omgå Begrænsninger for Beskedhandling", + "description": "Giver dig mulighed for at reagere på et snap uden at have åbnet det eller at gemme en besked, der ikke kan gemmes" }, "remove_groups_locked_status": { - "name": "Fjern status for låste grupper", - "description": "Giver dig mulighed for at se gruppeoplysninger, efter du er blevet smidt ud" + "name": "Fjern gruppers låst status", + "description": "Giver dig mulighed for at se gruppeoplysninger efter at være blevet sparket ud" }, - "double_tap_chat_action": { - "name": "Dobbelttryk-chathandling", - "description": "Udfører en brugerdefineret handling, når du dobbelttrykker på en besked i chat" + "auto_mark_as_read": { + "name": "Automatisk markér som læst", + "description": "Automatisk markerer beskeder/snaps som læst, selv når Stealth-tilstand er aktiveret" }, - "double_tap_chat_action_custom_emoji": { - "name": "Brugerdefineret emoji-reaktion på dobbelttryk-chathandling", - "description": "Indstiller en brugerdefineret emoji-reaktion for dobbelttryk-chathandlingen" + "friend_mutation_notifier": { + "description": "Giver dig besked, når noget ændrer sig i en vens profil", + "name": "Ven Mutation Notifier" + }, + "unlimited_conversation_pinning": { + "description": "Giver dig mulighed for at fastgøre et ubegrænset antal samtaler lokalt", + "name": "Ubegrænset samtale fastgørelse" } } }, "global": { "name": "Global", - "description": "Juster globale Snapchat-indstillinger", + "description": "Tweak Globale Snapchat-Indstillinger", "properties": { + "snapchat_plus": { + "name": "Snapchat Plus", + "description": "Aktiverer Snapchat Plus-funktioner\nNogle server-sidede funktioner fungerer muligvis ikke" + }, + "auto_updater": { + "name": "Automatisk Opdatering", + "description": "Søg automatisk efter opdateringer" + }, + "disable_metrics": { + "name": "Deaktivér Metrics", + "description": "Blokerer afsendelse af specifikke analytiske data til Snapchat" + }, + "block_ads": { + "name": "Bloker reklamer", + "description": "Forhindrer reklamer i at blive vist" + }, + "bypass_video_length_restriction": { + "name": "Bypass Videolængde Begrænsninger", + "description": "Single: sender en enkelt video\nSplit: split videoer efter redigering" + }, + "disable_google_play_dialogs": { + "name": "Deaktiver Google Play-tjenester Dialoger", + "description": "Forhindre, at Google Play-tjenesternes tilgængelighedsdialoger vises" + }, + "disable_snap_splitting": { + "name": "Deaktivér Snap Opdeling", + "description": "Forhindrer snaps i at blive opdelt i flere dele\nBilleder, du sender, vil blive til videoer" + }, "better_location": { - "name": "Bedre placering", "description": "Forbedrer Snapchat-placeringen", + "name": "Bedre placeringen", "properties": { "spoof_location": { "name": "Spoof placering", - "description": "Spoofer din placering til en bestemt" + "description": "Spoof din placering til et bestemt sted" }, "coordinates": { "name": "Koordinater", - "description": "Indstil koordinaterne for den spoofede placering" - }, - "walk_radius": { - "name": "Gåradius", - "description": "Gå tilfældigt rundt inden for denne radius (fod)" + "description": "Indstil koordinaterne for den spoofed placering" }, "always_update_location": { "name": "Opdater altid placering", "description": "Tving Snapchat til at opdatere placering, selvom der ikke modtages GPS-data" }, "suspend_location_updates": { - "name": "Suspender placeringsopdateringer", - "description": "Forhindrer, at din placering opdateres" + "name": "Suspender placerings opdateringer", + "description": "Tilføjer en knap i kortindstillingerne for at suspendere placerings opdateringer" }, "spoof_battery_level": { "name": "Spoof batteriniveau", @@ -1106,103 +638,71 @@ }, "spoof_headphones": { "name": "Spoof hovedtelefoner", - "description": "Spoofer status for at lytte til musik på kortet" + "description": "Spoof status for at lytte til musik på kortet" }, - "show_battery_level": { - "name": "Vis batteriniveau", - "description": "Viser batteriniveauet for dine venner på kortet" + "walk_radius": { + "name": "Gå radius", + "description": "Gå tilfældigt rundt inden for denne radius (ft)" } } }, - "snapchat_plus": { - "name": "Snapchat Plus", - "description": "Aktiverer Snapchat Plus-funktioner\nNogle server-side-funktioner fungerer muligvis ikke" + "disable_story_sections": { + "name": "Deaktiver historie sektioner", + "description": "Fjerner sektioner fra siden Historier\nKan kræve en opdatering for at fungere korrekt" }, - "media_upload_quality": { - "name": "Kvalitet af medieupload", - "description": "Overskriver kvaliteten af medieupload", - "properties": { - "force_video_upload_source_quality": { - "name": "Tving kildekvalitet for videoupload", - "description": "Tvinger Snapchat til at bruge kildekvaliteten, når der uploades videoer\nBemærk, at dette muligvis ikke fjerner metadata fra medier" - }, - "disable_image_compression": { - "name": "Deaktiver billedkomprimering", - "description": "Deaktiverer billedkomprimering, når der uploades medier" - }, - "custom_image_upload_format": { - "name": "Brugerdefineret billed-uploadformat", - "description": "Indstiller et brugerdefineret billed-uploadformat\nVælg et tabsfri format (som PNG) for den bedste kvalitet" - } - } + "disable_permission_requests": { + "name": "Deaktiver tilladelsesanmodninger", + "description": "Forhindrer Snapchat i at bede om specifikke tilladelser" + }, + "spotlight_comments_username": { + "name": "Spotlight Kommentarer Brugernavn", + "description": "Viser forfatterens brugernavn i Spotlight-kommentarer" + }, + "default_volume_controls": { + "description": "Tvinger Snapchat til at bruge systemets lydstyrke kontroller", + "name": "Standard lydstyrke kontroller" + }, + "disable_memories_snap_feed": { + "name": "Deaktiver minder Snap Feed", + "description": "Forhindrer Snapchat i at vise seneste minder, når du stryger op i kameraet" + }, + "default_video_playback_rate": { + "name": "Standard videoafspilningshastighed", + "description": "Indstil standardhastigheden for afspilning af videoer\nVærdien skal være mellem 0,1 og 4,0" + }, + "video_playback_rate_slider": { + "name": "Skyder for videoafspilningshastighed", + "description": "Tilføjer en skyder i opera kontekstmenu for at ændre videoafspilningshastigheden\nBemærk: Ændringer gælder kun for efterfølgende videoer" }, "disable_confirmation_dialogs": { "name": "Deaktiver bekræftelsesdialoger", "description": "Bekræfter automatisk valgte handlinger" }, - "auto_updater": { - "name": "Automatisk opdatering", - "description": "Søger automatisk efter nye opdateringer" - }, - "disable_metrics": { - "name": "Deaktiver målinger", - "description": "Blokerer afsendelse af specifikke analysedata til Snapchat" - }, - "disable_story_sections": { - "name": "Deaktiver historiesektioner", - "description": "Fjerner sektioner fra historiesiden\nKræver muligvis en opdatering for at fungere korrekt" - }, - "block_ads": { - "name": "Bloker annoncer", - "description": "Forhindrer, at annoncer vises" - }, - "disable_custom_tabs": { - "name": "Deaktiver brugerdefinerede faner", - "description": "Åbner links i understøttede programmer i stedet for i webbrowseren" - }, - "disable_permission_requests": { - "name": "Deaktiver anmodninger om tilladelse", - "description": "Forhindrer Snapchat i at anmode om specifikke tilladelser" - }, - "disable_memories_snap_feed": { - "name": "Deaktiver snap-feed fra minder", - "description": "Forhindrer Snapchat i at vise nylige minder, når du swiper op i kameraet" - }, - "spotlight_comments_username": { - "name": "Brugernavn i Spotlight-kommentarer", - "description": "Viser forfatterens brugernavn i Spotlight-kommentarer" - }, - "bypass_video_length_restriction": { - "name": "Omgå begrænsning af videolængde", - "description": "Enkelt: sender en enkelt video\nOpdel: opdeler videoer efter redigering" - }, - "default_video_playback_rate": { - "name": "Standardafspilningshastighed for video", - "description": "Indstiller standardhastigheden for afspilning af videoer\nVærdien skal være mellem 0,1 og 4,0" - }, - "video_playback_rate_slider": { - "name": "Glidebryder til afspilningshastighed for video", - "description": "Tilføjer en glidebryder i Opera-kontekstmenuen for at ændre videoafspilningshastigheden\nBemærk: Ændringer gælder kun for efterfølgende videoer" - }, - "disable_google_play_dialogs": { - "name": "Deaktiver dialoger fra Google Play Services", - "description": "Forhindrer, at dialoger om tilgængelighed af Google Play Services vises" - }, - "default_volume_controls": { - "name": "Standardlydstyrkekontroller", - "description": "Tvinger Snapchat til at bruge systemets lydstyrkekontroller" - }, - "disable_telecom_framework": { - "name": "Deaktiver Telecom-framework", - "description": "Forhindrer Snapchat i at bruge Android Telecom-frameworket\nDette giver dig mulighed for at lytte til musik under et opkald" - }, "hide_active_music": { "name": "Skjul aktiv musik", - "description": "Forhindrer Snapchat i at vide, at du lytter til musik\nDette giver dig mulighed for at tage snaps ved hjælp af lydstyrkeknapper, mens du lytter til musik" + "description": "Forhindrer Snapchat i at vide, at du lytter til musik\nDette giver dig mulighed for at tage snaps ved hjælp af kontrollydstyrkeknapperne, mens du lytter til musik" }, - "disable_snap_splitting": { - "name": "Deaktiver opdeling af snap", - "description": "Forhindrer, at snaps opdeles i flere dele\nBilleder, du sender, bliver til videoer" + "disable_custom_tabs": { + "name": "Deaktiver bruger tilpassede faner", + "description": "Åbner links i understøttede programmer i stedet for i webbrowseren" + }, + "media_upload_quality": { + "properties": { + "force_video_upload_source_quality": { + "name": "Tving video upload kilde kvalitet", + "description": "Tvinger Snapchat til at bruge kilde kvaliteten, når du uploader videoer\nBemærk, at dette muligvis ikke fjerner metadata fra medier" + }, + "custom_image_upload_format": { + "description": "Indstiller et brugerdefineret billedoverførselsformat\nVælg et tabsfrit format (som PNG) for den bedste kvalitet", + "name": "Brugerdefineret billed overførsels format" + }, + "disable_image_compression": { + "name": "Deaktiver billed komprimering", + "description": "Deaktiverer billed komprimering ved upload af medier" + } + }, + "name": "Medie upload kvalitet", + "description": "Tilsidesætter medie overførsel kvaliteten" } } }, @@ -1214,115 +714,99 @@ "name": "Kamera", "description": "Juster de rigtige indstillinger for den perfekte snap", "properties": { - "disable_cameras": { - "name": "Deaktiver kameraer", - "description": "Forhindrer Snapchat i at bruge de valgte kameraer" - }, - "black_photos": { - "name": "Sorte billeder", - "description": "Erstatter optagne billeder med en sort baggrund\nVideoer påvirkes ikke" - }, "immersive_camera_preview": { - "name": "Immersiv forhåndsvisning", - "description": "Forhindrer Snapchat i at beskære kameraforhåndsvisningen\nDette kan få kameraet til at flimre på nogle enheder" - }, - "override_front_resolution": { - "name": "Overskriv opløsning for forsidekamera", - "description": "Overskriver kameraopløsningen for forsidekameraet" - }, - "override_back_resolution": { - "name": "Overskriv opløsning for bagsidekamera", - "description": "Overskriver kameraopløsningen for bagsidekameraet" - }, - "custom_resolution": { - "name": "Brugerdefineret opløsning", - "description": "Indstiller en brugerdefineret kameraopløsning, bredde x højde (f.eks. 1920x1080).\nDen brugerdefinerede opløsning skal understøttes af din enhed" - }, - "front_custom_frame_rate": { - "name": "Brugerdefineret billedhastighed for forsidekamera", - "description": "Overskriver billedhastigheden for forsidekameraet" - }, - "back_custom_frame_rate": { - "name": "Brugerdefineret billedhastighed for bagsidekamera", - "description": "Overskriver billedhastigheden for bagsidekameraet" + "name": "Omfattende Forhåndsvisning", + "description": "Forhindrer Snapchat i at beskære kamera forhåndsvisning\nDette kan få kameraet til at flimre på nogle enheder" }, "force_camera_source_encoding": { - "name": "Tving kodning af kamerakilde", - "description": "Tvinger kodningen af kamerakilden" + "name": "Tving Kameraets Kildekodning", + "description": "Tving Kameraets Kildekodning" }, - "startup_default_camera": { - "name": "Standardkamera ved opstart", - "description": "Indstiller standardkameraet, når Snapchat åbnes" + "disable_cameras": { + "description": "Forhindrer Snapchat i at bruge de valgte kameraer", + "name": "Deaktiver kameraer" + }, + "front_custom_frame_rate": { + "description": "Tilsidesætter frontkameraets billedhastighed", + "name": "Frontkamera brugerdefineret billedhastighed" + }, + "override_front_resolution": { + "description": "Tilsidesætter kameraopløsningen for frontkameraet", + "name": "Tilsidesæt frontkamera opløsning" + }, + "override_back_resolution": { + "name": "Tilsidesæt bagkamera opløsning", + "description": "Tilsidesætter kameraopløsningen for bagkameraet" + }, + "back_custom_frame_rate": { + "description": "Tilsidesætter bagkameraets billedhastighed", + "name": "Bagkamera brugerdefineret billedhastighed" + }, + "custom_resolution": { + "description": "Indstiller en brugerdefineret kameraopløsning, bredde x højde (f.eks. 1920x1080).\nDen brugerdefinerede opløsning skal understøttes af din enhed", + "name": "Brugerdefineret opløsning" + }, + "black_photos": { + "name": "Sorte fotos", + "description": "Erstatter optagne fotos med sort baggrund\nVideoer påvirkes ikke" }, "hevc_recording": { - "name": "HEVC-optagelse", - "description": "Bruger HEVC (H.265)-kodek til videooptagelse" + "description": "Bruger HEVC (H.265) codec til videooptagelse", + "name": "HEVC optagelse" } } }, "streaks_reminder": { - "name": "Påmindelse om streaks", - "description": "Giver dig jævnligt besked om dine streaks", + "name": "Streaks Påmindelse", + "description": "Periodisk giver dig besked om dine streaks", "properties": { "interval": { - "name": "Interval", - "description": "Intervallet mellem hver påmindelse (timer)" + "description": "Intervallet mellem hver påmindelse (timer)", + "name": "Tidsrum" }, "remaining_hours": { "name": "Resterende tid", - "description": "Den resterende tid, før notifikationen vises (timer)" + "description": "Det resterende tid før meddelelsen vises (timer)" }, "group_notifications": { - "name": "Gruppenotifikationer", - "description": "Grupperer notifikationer i en enkelt" + "name": "Gruppe Notifikationer", + "description": "Grupper notifikationer til en enkelt" } } }, "experimental": { - "name": "Eksperimentel", + "name": "Eksperimental", "description": "Eksperimentelle funktioner", "properties": { "native_hooks": { - "name": "Native hooks", - "description": "Usikre funktioner, der hooker ind i Snapchats native kode", + "name": "Native Kroge", + "description": "Usikre funktioner, der hookes ind i Snapchat's native kode", "properties": { + "disable_bitmoji": { + "name": "Deaktivér Bitmoji", + "description": "Deaktiverer Venner Profil Bitmoji" + }, "composer_hooks": { - "name": "Composer-hooks", - "description": "Injicerer kode i Composer cross-platform UI-frameworket", "properties": { - "show_first_created_username": { - "name": "Vis først oprettede brugernavn", - "description": "Viser det først oprettede brugernavn ved siden af det aktuelle brugernavn på profilsiden" - }, - "bypass_camera_roll_limit": { - "name": "Omgå begrænsning for kamerarulle", - "description": "Øger det maksimale antal medier, du kan sende fra kamerarullen" - }, - "custom_self_destruct_snap_delay": { - "name": "Brugerdefineret forsinkelse for selvdestruerende snap", - "description": "Giver flere muligheder for selvdestruktionstimeren, når du sender en snap" - }, "composer_console": { - "name": "Composer-konsol", - "description": "Giver dig mulighed for at udføre JavaScript-kode i Composer (kun arm64)" + "description": "Giver dig mulighed for at udføre JavaScript-kode i Composer (kun arm64)", + "name": "Komponistkonsol" }, "composer_logs": { - "name": "Composer-logfiler", - "description": "Omdirigerer konsollogfiler fra Composer til PurrfectSnap" + "name": "Komponistlogfiler", + "description": "Omdirigerer konsollogfiler fra Composer til SnapEnhance" + }, + "bypass_camera_roll_limit": { + "name": "Undgå grænsen for kamerarulle", + "description": "Øger det maksimale antal medier, du kan sende fra kamerarullen" + }, + "show_first_created_username": { + "name": "Vis første oprettede brugernavn", + "description": "Viser det første oprettede brugernavn ud for det aktuelle brugernavn på profilsiden" } - } - }, - "disable_bitmoji": { - "name": "Deaktiver Bitmoji", - "description": "Deaktiverer venners profil-Bitmoji" - }, - "custom_emoji_font": { - "name": "Brugerdefineret emoji-skrifttype", - "description": "Giver dig mulighed for at bruge en brugerdefineret emoji-skrifttype. Fungerer kun med .ttf-skrifttyper" - }, - "custom_shared_library": { - "name": "Brugerdefineret delt bibliotek", - "description": "Indlæser et brugerdefineret delt bibliotek i Snapchat. Denne funktion er kun til testformål" + }, + "name": "Komponistkroge", + "description": "Injicerer kode i Composer-grænsefladen på tværs af platforme" } } }, @@ -1330,82 +814,90 @@ "name": "Spoof", "description": "Spoof forskellige oplysninger om dig", "properties": { - "play_store_installer_package_name": { - "name": "Pakkenavn for Play Butik-installationsprogram", - "description": "Overskriver installationsprogrammets pakkenavn til com.android.vending" - }, "remove_vpn_transport_flag": { "name": "Fjern VPN-transportflag", - "description": "Forhindrer Snapchat i at registrere VPN'er" + "description": "Forhindrer Snapchat i at opdage VPN'er" }, "remove_mock_location_flag": { - "name": "Fjern flag for falsk placering", - "description": "Forhindrer Snapchat i at registrere falsk placering" + "description": "Forhindrer Snapchat i at registrere falsk placering", + "name": "Fjern Falsk Location Flag" + }, + "play_store_installer_package_name": { + "name": "Play Butik Installer Pakkenavn", + "description": "Tilsidesætter installations pakkenavnet til com.android.vending" } } }, - "convert_message_locally": { - "name": "Konverter besked lokalt", - "description": "Konverterer snaps til eksterne chatmedier lokalt. Dette vises i chat-download-kontekstmenuen" + "infinite_story_boost": { + "name": "Uendelig Historie Boost", + "description": "Bypass Story Boost Limit delay" }, - "media_file_picker": { - "name": "Mediefilvælger", - "description": "Giver dig mulighed for at vælge en hvilken som helst video/lydfil fra galleriet" + "meo_passcode_bypass": { + "name": "Mine Øjne Kun Kode Bypass", + "description": "Bypass My Eyes Only Passcode\nDette vil kun fungere, hvis adgangskoden er indtastet korrekt før" + }, + "no_friend_score_delay": { + "name": "Ingen Vennescore Forsinkelse", + "description": "Fjerner forsinkelsen, når du ser en Venners Score" + }, + "e2ee": { + "name": "Ende-til-Ende kryptering", + "description": "Krypterer dine beskeder med AES ved hjælp af en delt hemmelig nøgle\nSørg for at gemme din nøgle et sikkert sted!", + "properties": { + "encrypted_message_indicator": { + "name": "Krypteret Meddelelsesindikator", + "description": "Tilføjer en 🔒 emoji ved siden af krypterede beskeder" + }, + "force_message_encryption": { + "name": "Tving besked Kryptering", + "description": "Forhindrer afsendelse af krypterede beskeder til personer, der ikke har E2E Kryptering aktiveret kun, når flere samtaler er valgt" + } + } + }, + "add_friend_source_spoof": { + "name": "Tilføj Ven Kilde Spoof", + "description": "Spoofs kilden til en venneanmodning" + }, + "hidden_snapchat_plus_features": { + "name": "Skjult Snapchat Plus-funktioner", + "description": "Aktiverer ikke-frigivet/beta Snapchat Plus funktioner\nKan ikke virke på ældre snapchat versioner" }, "story_logger": { - "name": "Historie-logger", - "description": "Giver en historik over venners historier" + "name": "Historie logger", + "description": "Giver en historie med venners historier" + }, + "convert_message_locally": { + "name": "Konverter besked lokalt", + "description": "Konverterer snaps til at chatte eksterne medier lokalt. Dette vises i chat download kontekstmenu" }, "call_recorder": { "name": "Opkaldsoptager", "description": "Optager automatisk lydopkald" }, "account_switcher": { - "name": "Kontoskifter", - "description": "Giver dig mulighed for at skifte mellem konti uden at logge ud\nLangt tryk på søgeikonet ved siden af din Bitmoji-profil for at åbne menuen\nBemærk: Denne funktion er eksperimentel og vil sandsynligvis ændre sig i fremtiden", "properties": { "auto_backup_current_account": { - "name": "Sikkerhedskopier automatisk nuværende konto", - "description": "Sikkerhedskopierer automatisk den nuværende konto, når du logger ud eller skifter konto" + "description": "Sikkerhedskopierer automatisk den aktuelle konto, når du logger ud eller skifter konto", + "name": "Automatisk backup af nuværende konto" } - } + }, + "name": "Konto skifter", + "description": "Giver dig mulighed for at skifte mellem konti uden at logge ud\nTryk længe på søgeikonet ved siden af din Bitmoji-profil for at åbne menuen\nBemærk: Denne funktion er eksperimentel og vil sandsynligvis ændre sig i fremtiden" }, - "better_transcript": { - "name": "Bedre transskription", - "description": "Forbedrer transskriptionen af stemmebeskeder", - "properties": { - "force_transcription": { - "name": "Tving transskription af stemmebesked", - "description": "Giver mulighed for at transskribere alle stemmebeskeder" - }, - "preferred_transcription_lang": { - "name": "Foretrukket transskriptionssprog", - "description": "Det foretrukne sprog for transskriptionen af stemmebeskeder (f.eks. EN, ES, FR)" - }, - "notification_transcript": { - "name": "Notifikationstransskription", - "description": "Transskriberer stemmebeskeder i notifikationer\nDenne funktion kræver, at funktionen Chat-forhåndsvisning er aktiveret i Bedre notifikationer" - } - } + "media_file_picker": { + "name": "Mediefilvælger", + "description": "Giver dig mulighed for at vælge en hvilken som helst video-/lydfil fra galleriet" }, - "voice_note_auto_play": { - "name": "Automatisk afspilning af stemmebesked", - "description": "Afspiller automatisk den næste stemmebesked, efter den nuværende er afsluttet" + "prevent_forced_logout": { + "description": "Forhindrer Snapchat i at logge dig ud, når du logger på en anden enhed", + "name": "Undgå tvungen log ud" }, - "friend_notes": { - "name": "Vennenoter", - "description": "Giver dig mulighed for at tilføje noter til venners profiler" - }, - "cof_experiments": { - "name": "COF-eksperimenter", - "description": "Aktiverer uudgivne/beta Snapchat-funktioner" - }, - "context_menu_fix": { - "name": "Rettelse af kontekstmenu", - "description": "Forsøg at reparere vennefeed-menuen, da den ikke kan vises korrekt, når enheden er offline" + "edit_message": { + "name": "Rediger beskeder", + "description": "Giver dig mulighed for at redigere beskeder i samtaler" }, "app_lock": { - "name": "App-lås", + "name": "Applås", "description": "Forhindrer adgang til Snapchat uden en adgangskode", "properties": { "lock_on_resume": { @@ -1414,135 +906,89 @@ } } }, - "infinite_story_boost": { - "name": "Uendelig historie-boost", - "description": "Omgå forsinkelsen for historie-boost-grænsen" - }, - "meo_passcode_bypass": { - "name": "Omgå adgangskode til My Eyes Only", - "description": "Omgå adgangskoden til My Eyes Only\nDette fungerer kun, hvis adgangskoden er blevet indtastet korrekt før" - }, - "no_friend_score_delay": { - "name": "Ingen forsinkelse af vennescore", - "description": "Fjerner forsinkelsen, når du ser en vens score" + "custom_streaks_expiration_format": { + "name": "Tilpasset format til udløb af Streaks", + "description": "Tilpasser formatet for udløbet af Streaks\n\nTilgængelige variabler:\n- %c: Antal Streaks\n- %e: Timeglas Emoji\n- %d: Dage\n- %h: Timer\n- %m: Minutter\n- %s: Sekunder\n- %w: Resterende tid" }, "best_friend_pinning": { - "name": "Fastgørelse af bedste ven", - "description": "Giver dig mulighed for at fastgøre en ven som din nummer et bedste ven. Bemærk: Kun du kan se din fastgjorte bedste ven" - }, - "e2ee": { - "name": "End-to-End-kryptering", - "description": "Krypterer dine beskeder med AES ved hjælp af en delt hemmelig nøgle\nSørg for at gemme din nøgle et sikkert sted!", - "properties": { - "encrypted_message_indicator": { - "name": "Indikator for krypteret besked", - "description": "Tilføjer en 🔒-emoji ved siden af krypterede beskeder" - }, - "force_message_encryption": { - "name": "Tving beskedkryptering", - "description": "Forhindrer afsendelse af krypterede beskeder til personer, der ikke har E2E-kryptering aktiveret, kun når flere samtaler er valgt" - } - } - }, - "add_friend_source_spoof": { - "name": "Spoof kilde til venneanmodning", - "description": "Spoofer kilden til en venneanmodning" - }, - "hidden_snapchat_plus_features": { - "name": "Skjulte Snapchat Plus-funktioner", - "description": "Aktiverer uudgivne/beta Snapchat Plus-funktioner\nFungerer muligvis ikke på ældre Snapchat-versioner" - }, - "custom_streaks_expiration_format": { - "name": "Brugerdefineret format for udløb af streaks", - "description": "Tilpasser formatet for udløb af streaks\n\nTilgængelige variabler:\n - %c: Antal streaks\n - %e: Timeglas-emoji\n - %d: Dage\n - %h: Timer\n - %m: Minutter\n - %s: Sekunder\n - %w: Resterende tid" - }, - "prevent_forced_logout": { - "name": "Forhindre tvungen logud", - "description": "Forhindrer Snapchat i at logge dig ud, når du logger ind på en anden enhed" - }, - "snapscore_changes": { - "name": "Snapscore-ændringer", - "description": "Følger ændringer i venners Snapscore\nBrug kun denne funktion i nyere versioner af Snapchat" + "description": "Tillader dig at fastgøre en ven som din bedste ven nummer ét. Bemærk: Kun du kan se din fastgjorte bedste ven", + "name": "Pinning af bedste ven" } } }, "scripting": { "name": "Scripting", - "description": "Kør brugerdefinerede scripts for at udvide PurrfectSnap", + "description": "Kør brugerdefinerede scripts for at udvide SnapEnhance", "properties": { "developer_mode": { "name": "Udviklertilstand", - "description": "Viser fejlfindingsoplysninger i Snapchats brugergrænseflade" + "description": "Viser debug info på Snapchats brugerflade" }, "module_folder": { - "name": "Modulmappe", - "description": "Den mappe, hvor scriptsene er placeret" + "name": "Modul Mappe", + "description": "Mappen hvor scripterne er placeret" }, "auto_reload": { "name": "Automatisk genindlæsning", "description": "Genindlæser automatisk scripts, når de ændres" }, "integrated_ui": { - "name": "Integreret brugergrænseflade", - "description": "Giver scripts mulighed for at tilføje brugerdefinerede brugergrænsefladekomponenter til Snapchat" + "description": "Tillader scripts at tilføje brugerdefinerede UI komponenter til Snapchat", + "name": "Integreret UI" }, "disable_log_anonymization": { - "name": "Deaktiver anonymisering af logfiler", + "name": "Deaktiver log anonymisering", "description": "Deaktiverer anonymisering af logfiler" - }, - "disable_optimization": { - "name": "Deaktiver optimering", - "description": "Deaktiverer optimering af scripts. Dette kan medføre ydeevneproblemer." } } }, "friend_tracker": { - "name": "Venne-tracker", - "description": "Registrerer venners aktivitet på Snapchat", "properties": { - "record_messaging_events": { - "name": "Registrer beskedbegivenheder", - "description": "Registrerer beskedbegivenheder som f.eks. at åbne en snap, læse en besked osv." - }, "allow_running_in_background": { "name": "Tillad kørsel i baggrunden", - "description": "Tillader trackeren at køre i baggrunden. Bemærk: Dette vil dræne dit batteri betydeligt" + "description": "Tillader trackeren at køre i baggrunden. Bemærk: Dette vil dræne dit batteri betydeligt, det anbefales ikke at se porno i mens" + }, + "record_messaging_events": { + "description": "Registrerer besked begivenheder såsom åbning af et snap, læsning af en besked osv.", + "name": "Optag meddelelses begivenheder" }, "auto_purge": { - "name": "Automatisk rydning", - "description": "Sletter automatisk cachelagrede begivenheder, der er ældre end den angivne tid" + "name": "Automatisk udrensning", + "description": "Sletter automatisk cachelagrede hændelser, der er ældre end det angivne tidsrum" } - } + }, + "name": "Ven Tracker", + "description": "Registrerer venners aktivitet på Snapchat" } }, "options": { "app_appearance": { - "always_light": "Altid lys", - "always_dark": "Altid mørk" + "always_light": "Altid Lys", + "always_dark": "Altid Mørk" }, "friend_feed_menu_buttons": { - "auto_download": "⬇️ Automatisk download", - "auto_save": "💬 Gem automatisk beskeder", - "unsaveable_messages": "⬇️ Ugemmelige beskeder", - "auto_open_snaps": "📸 Åbn automatisk snaps", - "stealth": "👻 Stealth-tilstand", - "mark_snaps_as_seen": "👀 Marker snaps som set", - "mark_stories_as_seen_locally": "👀 Marker historier som set lokalt", - "conversation_info": "🧑‍🤝‍🧑 Samtaleoplysninger", - "e2e_encryption": "🔒 Brug E2E-kryptering" + "auto_download": "⬇️ Auto-download", + "auto_save": "💬 Gem Automatisk Beskeder", + "stealth": "👻 Stealth Tilstand", + "conversation_info": "👤 Samtaleinfo", + "e2e_encryption": "🔒 Brug E2E Kryptering", + "mark_stories_as_seen_locally": "👀 Markér historier som set lokalt", + "mark_snaps_as_seen": "👀 Markér Snaps som set", + "unsaveable_messages": "⬇️ Beskeder, der ikke kan gemmes", + "auto_open_snaps": "📷 Automatisk åbn Snaps" }, "path_format": { "create_author_folder": "Opret mappe for hver forfatter", "create_source_folder": "Opret mappe for hver mediekildetype", - "append_hash": "Tilføj en unik hash til filnavnet", + "append_hash": "Tilføj et unikt hash til filnavnet", "append_source": "Tilføj mediekilden til filnavnet", - "append_username": "Tilføj brugernavnet til filnavnet", - "append_date_time": "Tilføj dato og klokkeslæt til filnavnet" + "append_username": "Tilføj mediekilden til filnavnet", + "append_date_time": "Tilføj dato og tid til filnavnet" }, "auto_download_sources": { - "friend_snaps": "Vennesnaps", + "friend_snaps": "Ven Snaps", "friend_stories": "Vennehistorier", - "public_stories": "Offentlige historier", + "public_stories": "Offentlige Historier", "spotlight": "Spotlight" }, "logging": { @@ -1554,306 +1000,213 @@ "notifications": { "chat_screenshot": "Skærmbillede", "chat_screen_record": "Skærmoptagelse", - "snap_replay": "Genafspilning af snap", - "camera_roll_save": "Gem i kamerarulle", - "chat": "Snak", - "chat_reply": "Chatsvar", + "snap_replay": "Fastgør Genafspilning", + "camera_roll_save": "Gem Kamera Rulle", + "chat": "Chat", + "chat_reply": "Chat Svar", "snap": "Snap", - "typing": "Skriver", + "typing": "Indtastning", "stories": "Historier", - "speaking": "Taler", - "chat_reaction": "DM-reaktion", - "group_chat_reaction": "Gruppereaktion", - "initiate_audio": "Indgående lydopkald", - "abandon_audio": "Ubesvaret lydopkald", + "chat_reaction": "DM Reaktion", + "group_chat_reaction": "Gruppe Reaktion", + "initiate_audio": "Indgående Lydopkald", + "abandon_audio": "Ubesvaret Lydopkald", "initiate_video": "Indgående videoopkald", - "abandon_video": "Ubesvaret videoopkald", - "map_live_location": "Live placering på kortet" + "abandon_video": "Ubesvarede videoopkald", + "speaking": "Taler" }, "gallery_media_send_override": { - "always_ask": "Spørg altid", - "ORIGINAL": "Originalt medie", - "NOTE": "Lydnote", + "ORIGINAL": "Original", + "NOTE": "Lyd Note", "SNAP": "Snap", - "SAVEABLE_SNAP": "Gemmelig snap" - }, - "strip_media_metadata": { - "hide_caption_text": "Skjul billedtekst", - "hide_snap_filters": "Skjul snap-filtre", - "hide_extras": "Skjul ekstramateriale (f.eks. omtaler)", - "remove_audio_note_duration": "Fjern varighed af lydnote", - "remove_audio_note_transcript_capability": "Fjern mulighed for transskription af lydnote" + "always_ask": "Spørg altid for at være sikker" }, "hide_ui_components": { - "hide_profile_call_buttons": "Fjern profilopkaldsknapper", - "hide_chat_call_buttons": "Fjern chatopkaldsknapper", - "hide_live_location_share_button": "Fjern knap til deling af live placering", - "hide_stickers_button": "Fjern klistermærkeknap", - "hide_voice_record_button": "Fjern stemmeoptagelsesknap", - "hide_unread_chat_hint": "Fjern tip om ulæst chat", - "hide_post_to_story_buttons": "Fjern knapper til at poste i historie, før du sender en snap", - "hide_billboard_prompt": "Fjern billboard-prompt i vennefeed", - "hide_snapchat_plus_gift_reminders": "Fjern påmindelser om Snapchat Plus-gaver i samtaler", - "hide_map_reactions": "Fjern kortreaktioner" - }, - "hide_story_suggestions": { - "hide_suggested_friend_stories": "Skjul foreslåede venne-historier", - "hide_my_stories": "Skjul mine historier" + "hide_profile_call_buttons": "Fjern Profilopkaldsknapper", + "hide_chat_call_buttons": "Fjern Profilopkaldsknapper", + "hide_live_location_share_button": "Fjern Knappen Live Placeringsdeling", + "hide_stickers_button": "Fjern Klistermærker Knap", + "hide_voice_record_button": "Fjern Stemmeoptagelsesknap", + "hide_unread_chat_hint": "Fjern ulæst chat tip" }, "home_tab": { "map": "Kort", - "chat": "Snak", + "chat": "Chat", "camera": "Kamera", "discover": "Opdag", "spotlight": "Spotlight" }, "add_friend_source_spoof": { - "added_by_username": "Efter brugernavn", - "added_by_mention": "Efter omtale", - "added_by_group_chat": "Efter gruppechat", - "added_by_qr_code": "Efter QR-kode", - "added_by_community": "Efter fællesskab", - "added_by_quick_add": "Efter hurtig tilføjelse (høj risiko for at blive udelukket)" + "added_by_username": "Efter Brugernavn", + "added_by_mention": "Efter Omtale", + "added_by_group_chat": "Efter Gruppechat", + "added_by_qr_code": "Via QR-kode", + "added_by_community": "Af Fællesskabet" }, "bypass_video_length_restriction": { "single": "Enkelt medie", - "split": "Opdel medie" + "split": "Opdel medier" }, - "old_bitmoji_selfie": { - "2d": "2d Bitmoji", - "3d": "3d Bitmoji" + "strip_media_metadata": { + "remove_audio_note_duration": "Fjern lyd note varighed", + "hide_caption_text": "Skjul billedtekst", + "remove_audio_note_transcript_capability": "Fjern lydnote-transskriptions kapacitet", + "hide_snap_filters": "Skjul snap filtre", + "hide_extras": "Skjul ekstramateriale (f.eks. omtaler)" }, "disable_confirmation_dialogs": { - "erase_message": "Slet besked", - "remove_friend": "Fjern ven", - "block_friend": "Bloker ven", + "remove_friend": "Fjern ven 😢", + "clear_conversation": "Ryd samtale fra vennefeed", + "block_friend": "Bloker ven 🚫", "ignore_friend": "Ignorer ven", "hide_friend": "Skjul ven", "hide_conversation": "Skjul samtale", - "clear_conversation": "Ryd samtale fra vennefeed" + "erase_message": "Slet besked" + }, + "disable_permission_requests": { + "camera": "Kamera", + "read_contacts": "Læs kontakter", + "phone_calls": "Telefonopkald", + "nearby_devices": "Enheder i nærheden", + "notifications": "Meddelelser", + "read_media_images": "Læs medie billeder", + "read_media_video": "Læs medie video", + "microphone": "Mikrofon", + "location": "Placering" + }, + "old_bitmoji_selfie": { + "3d": "3D Bitmoji", + "2d": "To-dimensionelle Bitmoji" + }, + "auto_purge": { + "6_hours": "6 Timer", + "12_hours": "12 Timer", + "1_month": "1 Måned", + "3_days": "3 Dage", + "never": "ALDRIG", + "3_hours": "3 Timer", + "1_day": "1 Dag", + "1_week": "1 Uge", + "2_weeks": "2 Uger", + "3_months": "3 Måneder", + "1_hour": "1 Time", + "6_months": "6 Måneder" + }, + "disable_cameras": { + "front": "Front kamera", + "back": "Bag kamera" }, "auto_reload": { "snapchat_only": "Kun Snapchat", - "all": "Alle (Snapchat + PurrfectSnap)" + "all": "Alle (Snapchat + SnapEnhance)" }, "edit_text_override": { - "multi_line_chat_input": "Flerlinjet chatinput", - "bypass_text_input_limit": "Omgå tekstinputgrænse" - }, - "auto_purge": { - "never": "Aldrig", - "1_hour": "1 time", - "3_hours": "3 timer", - "6_hours": "6 timer", - "12_hours": "12 timer", - "1_day": "1 dag", - "3_days": "3 dage", - "1_week": "1 uge", - "2_weeks": "2 uger", - "1_month": "1 måned", - "3_months": "3 måneder", - "6_months": "6 måneder" + "multi_line_chat_input": "Extra mange linjer chat input", + "bypass_text_input_limit": "Omgå grænse for tekst input" }, "disable_story_sections": { + "discover": "Opdage", "friends": "Venner", - "suggested_stories": "Foreslåede historier", - "following": "Følger", - "discover": "Opdag" + "following": "Følge" }, - "disable_cameras": { - "front": "Forsidekamera", - "back": "Bagsidekamera" - }, - "disable_permission_requests": { - "notifications": "Notifikationer", - "read_media_images": "Læs mediebilleder", - "read_media_video": "Læs medievideo", - "camera": "Kamera", - "microphone": "Mikrofon", - "location": "Placering", - "read_contacts": "Læs kontakter", - "nearby_devices": "Enheder i nærheden", - "phone_calls": "Telefonopkald" + "hide_story_suggestions": { + "hide_my_stories": "Skjul mine historier", + "hide_suggested_friend_stories": "Skjul foreslåede vennehistorier" }, "message_indicators": { - "encryption_indicator": "Tilføjer et 🔒-ikon ved siden af beskeder, der kun er sendt til dig", - "platform_indicator": "Tilføjer platformikonet, hvorfra et medie blev sendt (f.eks. Android, iOS, Web)", - "location_indicator": "Tilføjer et 📍-ikon til snaps, når de er blevet sendt med placering aktiveret", "ovf_editor_indicator": "Angiver, om en snap er blevet sendt ved hjælp af OVF Editor", - "director_mode_indicator": "Tilføjer et 🎬-ikon til snaps, når de er blevet sendt ved hjælp af Director Mode, som kan bruges til at sende galleribilleder som snaps" + "location_indicator": "Tilføjer et 📍 ikon til snaps, når de er blevet sendt med placering aktiveret", + "encryption_indicator": "Tilføjer et 🔒 ikon ud for beskeder, der kun er blevet sendt til dig", + "platform_indicator": "Tilføjer platforms ikonet, hvorfra et medie blev sendt (f.eks. Android, iOS, Web)", + "director_mode_indicator": "Tilføjer et ✏️ ikon til snaps, når de er blevet sendt ved hjælp af Director Mode, som kan bruges til at sende galleribilleder som snaps" }, "auto_mark_as_read": { - "conversation_read": "Marker samtale som læst, når du sender en besked", - "snap_reply": "Marker snaps som læst, når du svarer på dem", - "save_snap_in_chat": "Marker snaps som læst, når du gemmer dem i chat i Stealth-tilstand" + "conversation_read": "Marker samtalen som læst, når du sender en besked", + "snap_reply": "Marker snaps som læst, når du svarer på dem" }, "friend_mutation_notifier": { "remove_friend": "Giv besked, når nogen fjerner dig som ven", "birthday_changes": "Giv besked, når nogen ændrer deres fødselsdag", - "bitmoji_selfie_changes": "Giv besked, når nogen ændrer deres Bitmoji-selfie", - "bitmoji_avatar_changes": "Giv besked, når nogen ændrer deres Bitmoji-avatar", - "bitmoji_background_changes": "Giv besked, når nogen ændrer deres Bitmoji-baggrund", - "bitmoji_scene_changes": "Giv besked, når nogen ændrer deres Bitmoji-scene" - }, - "snapchat_plus": { - "not_subscribed": "Ikke abonneret", - "basic": "Grundlæggende", - "ad_free": "Reklamefri" - }, - "double_tap_chat_action": { - "like_message": "Synes godt om besked", - "copy_text": "Kopier tekst til udklipsholder", - "delete_message": "Slet besked", - "mark_as_read": "Marker som læst", - "custom_emoji_reaction": "Brugerdefineret emoji-reaktion" - }, - "startup_default_camera": { - "front": "Forsidekamera", - "back": "Bagsidekamera" + "bitmoji_selfie_changes": "Giv besked, når nogen ændrer deres Bitmoji selfie", + "bitmoji_avatar_changes": "Giv besked, når nogen ændrer deres Bitmoji avatar", + "bitmoji_background_changes": "Giv besked, når nogen ændrer deres Bitmoji baggrund", + "bitmoji_scene_changes": "Giv besked, når nogen ændrer deres Bitmoji scene" } } }, "friend_menu_option": { - "mark_snaps_as_seen": "Marker snaps som set", - "mark_stories_as_seen_locally": "Marker historier som set lokalt", "preview": "Forhåndsvisning", - "stealth_mode": "Stealth-tilstand", - "auto_download_blacklist": "Sortliste for automatisk download", - "anti_auto_save": "Anti automatisk gem" - }, - "content_type": { - "CHAT": "Snak", - "SNAP": "Snap", - "EXTERNAL_MEDIA": "Eksternt medie", - "NOTE": "Lydnote", - "STICKER": "Klistermærke", - "SHARE": "Del", - "STATUS": "Status", - "LOCATION": "Placering", - "STATUS_SAVE_TO_CAMERA_ROLL": "Gemt i kamerarulle", - "STATUS_CONVERSATION_CAPTURE_SCREENSHOT": "Skærmbillede", - "STATUS_CONVERSATION_CAPTURE_RECORD": "Skærmoptagelse", - "STATUS_CALL_MISSED_VIDEO": "Ubesvaret videoopkald", - "STATUS_CALL_MISSED_AUDIO": "Ubesvaret lydopkald", - "LIVE_LOCATION_SHARE": "Del live placering", - "CREATIVE_TOOL_ITEM": "Kreativt værktøjselement", - "FAMILY_CENTER_INVITE": "Invitation til Familiecenter", - "FAMILY_CENTER_ACCEPT": "Accepter Familiecenter", - "FAMILY_CENTER_LEAVE": "Forlad Familiecenter", - "STATUS_PLUS_GIFT": "Status Plus-gave", - "TINY_SNAP": "Lille snap", - "STATUS_COUNTDOWN": "Nedtælling", - "MAP_REACTION": "Kortreaktion" - }, - "media_download_source": { - "none": "Ingen", - "pending": "Afventer", - "chat_media": "Chatmedie", - "story": "Historie", - "public_story": "Offentlig historie", - "spotlight": "Spotlight", - "profile_picture": "Profilbillede", - "story_logger": "Historie-logger", - "message_logger": "Besked-logger", - "merged": "Flettet", - "voice_call": "Stemmeopkald" + "stealth_mode": "Stealth Tilstand", + "anti_auto_save": "Anti Automatisk Gem", + "mark_snaps_as_seen": "Markér Snaps som set", + "mark_stories_as_seen_locally": "Markér historier som set lokalt", + "auto_download_blacklist": "Automatisk download af sortliste" }, "chat_action_menu": { "preview_button": "Forhåndsvisning", - "download_button": "Download", - "delete_logged_message_button": "Slet logget besked", - "show_chat_edit_history": "Vis chathistorik for redigering", - "convert_message": "Konverter besked" + "download_button": "Hent", + "delete_logged_message_button": "Slet Logget Besked", + "convert_message": "Konverter besked", + "edit_message": "Rediger besked" }, "opera_context_menu": { - "download": "Download medie", - "sent_at": "Sendt den {date}", - "created_at": "Oprettet den {date}", - "expires_at": "Udløber den {date}", - "media_size": "Mediestørrelse: {size}", + "download": "Hent medie", + "sent_at": "Sendt den {dato}", + "show_debug_info": "Vis fejlretnings oplysninger", "media_duration": "Medievarighed: {duration} ms", - "show_debug_info": "Vis fejlfindingsoplysninger" + "expires_at": "Udløber {date}", + "created_at": "Oprettet {date}", + "media_size": "Mediestørrelse: {size}" }, "modal_option": { "profile_info": "Profiloplysninger", "close": "Luk" }, "gallery_media_send_override": { - "multiple_media_toast": "Du kan kun sende ét medie ad gangen" - }, - "mark_as_seen": { - "no_unseen_snaps_toast": "Ingen usete snaps fundet!", - "seen_toast": "Markeret som set!", - "unseen_toast": "Markeret som uset!", - "already_seen_toast": "Allerede markeret som set!", - "already_unseen_toast": "Allerede markeret som uset!" + "multiple_media_toast": "Du kan kun sende et medie ad gangen" }, "conversation_preview": { - "streak_expiration": "udløber om {day} dage {hour} timer {minute} minutter", - "total_messages": "Samlet antal sendte/modtagne beskeder: {count}", + "streak_expiration": "udløber på {day} dage {hour} timer {minute} minutter", + "total_messages": "Total sendt/modtagne meddelelser: {count}", "title": "Forhåndsvisning", - "unknown_user": "Ukendt bruger", - "no_messages": "Ingen beskeder fundet!" + "unknown_user": "Ukendt bruger" }, "profile_info": { "title": "Profiloplysninger", - "first_created_username": "Først oprettede brugernavn", - "mutable_username": "Foranderligt brugernavn", + "first_created_username": "Første Oprettet Brugernavn", + "mutable_username": "Mutabelt Brugernavn", "display_name": "Visningsnavn", - "added_date": "Tilføjet dato", - "birthday": "Fødselsdag: {day} {month}", - "hidden_birthday": "Fødselsdag: Skjult", + "added_date": "Tilføjet Dato", + "birthday": "Fødselsdag : {month} {day}", "friendship": "Venskab", - "add_source": "Tilføj kilde", + "add_source": "Tilføj Kilde", "snapchat_plus": "Snapchat Plus", "snapchat_plus_state": { - "subscribed": "Abonneret", + "subscribed": "Abonnement bekræftet", "not_subscribed": "Ikke abonneret" - } - }, - "friendship_link_type": { - "mutual": "Gensidig", - "outgoing": "Udgående", - "blocked": "Blokeret", - "deleted": "Slettet", - "following": "Følger", - "suggested": "Foreslået", - "incoming": "Indgående", - "incoming_follower": "Indgående følger" - }, - "bulk_messaging_action": { - "choose_action_title": "Vælg en handling", - "progress_status": "Behandler {index} af {total}", - "selection_dialog_continue_button": "Fortsæt", - "confirmation_dialog": { - "title": "Er du sikker?", - "message": "Dette vil påvirke alle valgte venner. Denne handling kan ikke fortrydes." }, - "actions": { - "remove_friends": "Fjern venner", - "clear_conversations": "Ryd samtaler" - } + "hidden_birthday": "Fødselsdag: Skjult" }, "chat_export": { - "exporter_dialog": { - "select_conversations_title": "Vælg samtaler", - "text_field_selection": "{amount} valgt", - "text_field_selection_all": "Alle", - "export_file_format_title": "Eksporter filformat", - "message_type_filter_title": "Filtrer beskeder efter type", - "amount_of_messages_title": "Antal beskeder (lad stå tomt for alle)", - "download_medias_title": "Download medier" - }, "dialog_negative_button": "Annuller", - "dialog_positive_button": "Eksporter", + "dialog_positive_button": "Eksportér", "exported_to": "Eksporteret til {path}", - "exporting_chats": "Eksporterer chats...", + "exporting_chats": "Eksporterer Chats...", "processing_chats": "Behandler {amount} samtaler...", "export_fail": "Kunne ikke eksportere samtale {conversation}", "writing_output": "Skriver output...", "finished": "Færdig! Du kan nu lukke denne dialog.", "no_messages_found": "Ingen beskeder fundet!", - "exporting_message": "Eksporterer {conversation}..." + "exporting_message": "Eksporterer {conversation}...", + "exporter_dialog": { + "text_field_selection": "{amount} valgt", + "message_type_filter_title": "Filtrer meddelelser efter type", + "download_medias_title": "Hent medier", + "text_field_selection_all": "Alle", + "select_conversations_title": "Vælg Samtaler", + "export_file_format_title": "Eksporter fil format", + "amount_of_messages_title": "Antal meddelelser (lad det stå tomt for alle)" + } }, "button": { "ok": "OK", @@ -1861,162 +1214,223 @@ "negative": "Nej", "cancel": "Annuller", "open": "Åbn", - "download": "Download", - "send": "Sende", - "restore_original": "Gendan original", - "convert_external_media": "Konverter eksternt medie", - "save": "Gem" - }, - "tracker_events": { - "conversation_enter": "Gå ind i samtale", - "conversation_exit": "Forlad samtale", - "started_typing": "Begyndte at skrive", - "stopped_typing": "Stoppede med at skrive", - "started_speaking": "Begyndte at tale", - "stopped_speaking": "Stoppede med at tale", - "started_peeking": "Begyndte at kigge", - "stopped_peeking": "Stoppede med at kigge", - "message_read": "Besked læst", - "message_deleted": "Besked slettet", - "message_saved": "Besked gemt", - "message_unsaved": "Besked ikke gemt", - "message_edited": "Besked redigeret", - "message_reaction_add": "Tilføj reaktion på besked", - "message_reaction_remove": "Fjern reaktion på besked", - "snap_opened": "Snap åbnet", - "snap_replayed": "Snap genafspillet", - "snap_replayed_twice": "Snap genafspillet to gange", - "snap_screenshot": "Skærmbillede af snap", - "snap_screen_record": "Skærmoptagelse af snap" - }, - "tracker_actions": { - "log": "Log", - "in_app_notification": "In-app-notifikation", - "push_notification": "Push-notifikation", - "custom": "Brugerdefineret" - }, - "better_notifications": { - "button": { - "reply": "Svar", - "download": "Download", - "mark_as_read": "Marker som læst" - } + "download": "Hent" }, "profile_picture_downloader": { - "button": "Download profilbillede", - "title": "Profilbillede-downloader", + "button": "Download Profilbillede", + "title": "Profil Billede Downloader", "avatar_option": "Avatar", "background_option": "Baggrund" }, - "call_start_confirmation": { - "dialog_title": "Start opkald", - "dialog_message": "Er du sikker på, at du vil starte et opkald?" - }, - "half_swipe_notifier": { - "notification_channel_name": "Halvt swipe", - "notification_content_dm": "{friend} har lige halvt swipet ind i din chat i {duration} sekunder", - "notification_content_group": "{friend} har lige halvt swipet ind i {group} i {duration} sekunder" - }, "download_processor": { "attachment_type": { "snap": "Snap", "sticker": "Klistermærke", - "gif": "Gif", - "external_media": "Eksternt medie", + "external_media": "Eksterne medier", "note": "Note", - "original_story": "Original historie" + "original_story": "Oprindelig Historie", + "gif": "GIF" }, - "select_attachments_title": "Vælg vedhæftninger", + "select_attachments_title": "Vælg vedhæftede filer", "download_started_toast": "Download startet", "unsupported_content_type_toast": "Ikke-understøttet indholdstype!", - "failed_no_longer_available_toast": "Medie ikke længere tilgængeligt", - "no_attachments_toast": "Ingen vedhæftninger fundet!", + "failed_no_longer_available_toast": "Medier er ikke længere tilgængelige", + "no_attachments_toast": "Ingen vedhæftning fundet!", "already_queued_toast": "Medie allerede i kø!", - "already_downloaded_toast": "Medie allerede downloadet!", - "content_saved_toast": "Gemt!", + "already_downloaded_toast": "Medier er allerede downloadet!", "download_toast": "Downloader {path}...", "processing_toast": "Behandler {path}...", "failed_generic_toast": "Kunne ikke downloade", "failed_to_create_preview_toast": "Kunne ikke oprette forhåndsvisning", - "failed_processing_toast": "Behandling mislykkedes {error}", + "failed_processing_toast": "Mislykkedes at behandle {error}", "failed_gallery_toast": "Kunne ikke gemme i galleri {error}", - "dash_no_chapter": "Intet kapitel fundet", "dash_dialog": { - "title": "Download dash-medie", - "download_all": "Download alle", + "download_all": "Hent alle", + "title": "Download dash-medier", "segment_text": "Segment {from} - {to}" - } + }, + "dash_no_chapter": "Intet kapitel fundet" }, "streaks_reminder": { - "notification_title": "Striber", - "notification_text": "Du mister din streak med {friend} om {hoursLeft} timer" + "notification_title": "Streaks", + "notification_text": "Du vil miste din Streak med {friend} på {hoursLeft} timer" + }, + "actions": { + "clean_snapchat_cache": { + "name": "Rens Snapchat-cachen", + "description": "Renser Snapchat-cachen" + }, + "manage_friend_list": { + "name": "Administrer venneliste", + "description": "Importer/eksporter din venneliste, når du sikkerhedskopierer" + }, + "export_chat_messages": { + "name": "Eksporter chatbeskeder", + "description": "Eksporterer samtalebeskeder til en JSON/HTML/TXT fil" + }, + "export_memories": { + "name": "Eksporter hukommelser", + "description": "Eksporterer minder til en ZIP fil" + }, + "bulk_messaging_action": { + "name": "Massemeddelelseshandling", + "description": "Udfører handlinger såsom sletning af venner eller massesletning af samtaler" + }, + "regen_mappings": { + "name": "Gendan kortlægninger", + "description": "Regenerer kortlægninger manuelt" + }, + "change_language": { + "name": "Skift sprog", + "description": "Skift sproget for SnapEnhance" + } + }, + "material3_strings": { + "date_range_input_invalid_range_input": "Ugyldigt datointerval", + "date_input_invalid_for_pattern": "Ugyldig dato", + "date_input_invalid_year_range": "Ugyldigt år", + "date_range_picker_start_headline": "Fra", + "date_range_picker_end_headline": "Til", + "date_range_picker_title": "Vælg dato interval", + "date_picker_switch_to_calendar_mode": "Kalender", + "date_range_picker_day_in_range": "Valgte", + "date_input_invalid_not_allowed": "Ugyldigt dato", + "date_range_picker_scroll_to_previous_month": "Forrige måned", + "date_range_picker_scroll_to_next_month": "Næste måned", + "date_picker_today_description": "I dag", + "date_picker_switch_to_input_mode": "Input" + }, + "friendship_link_type": { + "mutual": "Gensidig", + "deleted": "Slettet", + "outgoing": "Udgående", + "blocked": "Blokeret", + "suggested": "Foreslået", + "incoming": "Indkommende", + "incoming_follower": "Indgående følger", + "following": "Følge" + }, + "content_type": { + "SNAP": "Snap", + "STATUS_CALL_MISSED_AUDIO": "Mistet lydopkald", + "CHAT": "Chat", + "TINY_SNAP": "Lille Snap", + "STATUS_PLUS_GIFT": "Status Plus gave", + "EXTERNAL_MEDIA": "Eksterne medier", + "NOTE": "Lyd note", + "STICKER": "Klistermærke", + "CREATIVE_TOOL_ITEM": "Kreativt værktøjselement", + "FAMILY_CENTER_INVITE": "Invitation til Familiecenter", + "FAMILY_CENTER_ACCEPT": "Familiecenter Accepter", + "FAMILY_CENTER_LEAVE": "Familiecenter forlad", + "STATUS_COUNTDOWN": "Nedtælling", + "MAP_REACTION": "Kort reaktion", + "LIVE_LOCATION_SHARE": "Live placeringsdeling", + "STATUS": "Status", + "STATUS_CONVERSATION_CAPTURE_RECORD": "Skærmoptagelse", + "STATUS_CALL_MISSED_VIDEO": "Ubesvaret videoopkald", + "LOCATION": "Placering", + "STATUS_SAVE_TO_CAMERA_ROLL": "Gemt i kamerarulle", + "STATUS_CONVERSATION_CAPTURE_SCREENSHOT": "Skærmbillede", + "SHARE": "Del" + }, + "media_download_source": { + "none": "Ingen", + "merged": "Fusioneret", + "public_story": "Offentlig historie", + "story": "Historie", + "story_logger": "Historielogger", + "pending": "Afventende", + "spotlight": "Spotlight", + "chat_media": "Chat medier", + "profile_picture": "Profilbillede", + "message_logger": "Meddelelseslogger", + "voice_call": "Taleopkald" + }, + "half_swipe_notifier": { + "notification_channel_name": "Halvt swipe", + "notification_content_dm": "{friend} har lige stryget halvt ind i din chat i {duration} sekunder", + "notification_content_group": "{friend} har lige stryget halvt ind i {group} i {duration} sekunder" + }, + "bulk_messaging_action": { + "actions": { + "remove_friends": "Fjern venner 😢", + "clear_conversations": "Ryd samtaler" + }, + "confirmation_dialog": { + "message": "Dette vil påvirke alle udvalgte venner. Denne handling kan ikke fortrydes.", + "title": "Forsatan! Er du nu helt sikker?" + }, + "choose_action_title": "Vælg en handling", + "progress_status": "Behandler {index} af {total}", + "selection_dialog_continue_button": "Forsæt" + }, + "better_notifications": { + "button": { + "reply": "Svar", + "mark_as_read": "Marker som læst", + "download": "Hent" + } + }, + "mark_as_seen": { + "already_unseen_toast": "Allerede markeret som uset!", + "no_unseen_snaps_toast": "Ingen usete snaps fundet!", + "seen_toast": "Mærket som set!", + "unseen_toast": "Markeret som uset!", + "already_seen_toast": "Allerede markeret som set!" + }, + "call_start_confirmation": { + "dialog_title": "Start opkald", + "dialog_message": "Er du sikker på, at du gider at snakke?" + }, + "end_to_end_encryption": { + "toolbox": { + "no_shared_key": "Du har ikke en delt hemmelighed med denne ven endnu. Klik nedenfor for at starte en ny.", + "shared_key_fingerprint": "Dit fingeraftryk er:\n\n{fingerprint}\n\nSørg for at tjekke, om det matcher din vens fingeraftryk!", + "initiate_exchange_button": "Start nøgleudveksling" + }, + "confirmation_dialogs": { + "confirmation_1": "ADVARSEL: Dette vil overskrive din eksisterende nøgle. Du mister adgangen til alle krypterede beskeder fra denne ven. Er du sikker på, at du vil fortsætte?", + "title": "End-to-end kryptering", + "confirmation_2": "Dit fjols er du VIRKELIG sikker på, at du vil fortsætte? Dette er din sidste chance for at fortryde." + }, + "accept_secret_key_success_toast": "Færdig! Du kan nu sende og modtage krypterede beskeder med denne ven.", + "accept_secret_key_failure_toast": "Kunne ikke acceptere hemmelig nøgle", + "accept_secret_button": "Accepter hemmelighed", + "accept_public_key_button": "Accepter offentlig nøgle", + "outgoing_pk_message": "Anmodning om nøgleudveksling", + "outgoing_secret_message": "Nøgle udvekslings svar", + "unencrypted_conversation_send_failure_toast": "Du kan ikke sende krypteret indhold til både krypterede og ukrypterede samtaler!", + "native_hooks_send_failure_toast": "Afsendelse mislykkedes! Aktiver venligst Native Hooks i indstillingerne.", + "no_participants_to_encrypt_toast": "Du har ikke nogen venner i denne samtale at kryptere beskeder med!", + "encryption_failed_toast": "Kunne ikke kryptere meddelelsen! Tjek logfil for flere detaljer.", + "accept_public_key_success_toast": "Offentlig nøgle blev accepteret!", + "accept_public_key_failure_toast": "Kunne ikke acceptere offentlig nøgle", + "incoming_pk_message": "Du har lige modtaget en offentlig nøgleanmodning. Klik nedenfor for at acceptere det.", + "incoming_secret_message": "Din ven har lige accepteret din offentlige nøgle. Klik nedenfor for at acceptere hemmeligheden." + }, + "scopes": { + "friend": "Ven", + "group": "Gruppe" }, "biometric_auth": { "unlock_button": "Lås op", "title": "Lås Snapchat op", "subtitle": "Godkend venligst for at låse Snapchat op" }, - "end_to_end_encryption": { - "toolbox": { - "no_shared_key": "Du har endnu ikke en delt hemmelig nøgle med denne ven. Klik nedenfor for at starte en ny.", - "shared_key_fingerprint": "Dit fingeraftryk er:\n\n{fingerprint}\n\nSørg for at tjekke, om det matcher din vens fingeraftryk!", - "initiate_exchange_button": "Start nøgleudveksling" - }, - "confirmation_dialogs": { - "title": "End-to-end-kryptering", - "confirmation_1": "ADVARSEL: Dette vil overskrive din eksisterende nøgle. Du mister adgangen til alle krypterede beskeder fra denne ven. Er du sikker på, at du vil fortsætte?", - "confirmation_2": "Er du HELT sikker på, at du vil fortsætte? Dette er din sidste chance for at fortryde." - }, - "unencrypted_conversation_send_failure_toast": "Du kan ikke sende krypteret indhold til både krypterede og ukrypterede samtaler!", - "native_hooks_send_failure_toast": "Kunne ikke sende! Aktiver venligst native hooks i indstillingerne.", - "no_participants_to_encrypt_toast": "Du har ingen venner i denne samtale at kryptere beskeder med!", - "encryption_failed_toast": "Kunne ikke kryptere besked! Tjek logcat for flere detaljer.", - "accept_public_key_success_toast": "Offentlig nøgle accepteret!", - "accept_secret_key_success_toast": "Færdig! Du kan nu sende og modtage krypterede beskeder med denne ven.", - "accept_public_key_failure_toast": "Kunne ikke acceptere offentlig nøgle", - "accept_secret_key_failure_toast": "Kunne ikke acceptere hemmelig nøgle", - "accept_secret_button": "Accepter hemmelighed", - "accept_public_key_button": "Accepter offentlig nøgle", - "outgoing_pk_message": "Anmodning om nøgleudveksling", - "outgoing_secret_message": "Svar på nøgleudveksling", - "incoming_pk_message": "Du har lige modtaget en anmodning om en offentlig nøgle. Klik nedenfor for at acceptere den.", - "incoming_secret_message": "Din ven har lige accepteret din offentlige nøgle. Klik nedenfor for at acceptere hemmeligheden." - }, "auto_open_snaps": { - "title": "Åbn automatisk snaps", - "notification_content": "{count} snaps åbnet" + "title": "Auto Åbn Snaps", + "notification_content": "{count} Snaps åbnet" }, "friend_mutation_observer": { - "notification_channel_name": "Observatør for venne-mutation", "friend_removed": "{username} har fjernet dig som ven", - "birthday_removed": "{username} har fjernet sin fødselsdag ({birthday})", - "birthday_added": "{username} har tilføjet sin fødselsdag ({birthday})", - "birthday_changed": "{username} har ændret sin fødselsdag fra {oldBirthday} til {newBirthday}", - "bitmoji_selfie_changed": "{username} har ændret sin Bitmoji-selfie", - "bitmoji_avatar_changed": "{username} har ændret sin Bitmoji-avatar", - "bitmoji_background_changed": "{username} har ændret sin Bitmoji-baggrund", - "bitmoji_scene_changed": "{username} har ændret sin Bitmoji-scene" - }, - "material3_strings": { - "date_range_picker_start_headline": "Fra", - "date_range_picker_end_headline": "Til", - "date_range_picker_title": "Vælg datoperiode", - "date_picker_switch_to_calendar_mode": "Kalender", - "date_picker_switch_to_input_mode": "Input", - "date_range_picker_scroll_to_previous_month": "Forrige måned", - "date_range_picker_scroll_to_next_month": "Næste måned", - "date_picker_today_description": "I dag", - "date_range_picker_day_in_range": "Valgt", - "date_input_invalid_for_pattern": "Ugyldig dato", - "date_input_invalid_year_range": "Ugyldigt år", - "date_input_invalid_not_allowed": "Ugyldig dato", - "date_range_input_invalid_range_input": "Ugyldig datoperiode" - }, - "send_override_dialog": { - "title": "Send medie som {type}", - "duration": "Varighed: {duration}", - "saveable_snap_hint": "Gør snap gemmelig i chatten", - "unlimited_duration": "Ubegrænset" - }, - "invalid_input_toast": "Ugyldigt input! Sørg for, at du har indtastet en gyldig værdi." -} \ No newline at end of file + "birthday_removed": "{username} har fjernet deres fødselsdag ({birthday})", + "birthday_added": "{username} har tilføjet deres fødselsdag ({birthday})", + "birthday_changed": "{username} har ændret deres fødselsdag fra {oldBirthday} til {newBirthday}", + "bitmoji_selfie_changed": "{username} har ændret deres Bitmoji selfie", + "bitmoji_avatar_changed": "{username} har ændret deres Bitmoji avatar", + "bitmoji_scene_changed": "{username} har ændret deres Bitmoji scene", + "bitmoji_background_changed": "{username} har ændret deres Bitmoji baggrund", + "notification_channel_name": "Venmutationobserver" + } +} diff --git a/common/src/main/assets/lang/de_DE.json b/common/src/main/assets/lang/de_DE.json index 4a4516bc..fa9a2d90 100644 --- a/common/src/main/assets/lang/de_DE.json +++ b/common/src/main/assets/lang/de_DE.json @@ -2,1073 +2,688 @@ "setup": { "dialogs": { "select_language": "Sprache auswählen", - "save_folder": "PurrfectSnap benötigt Speicherberechtigungen, um Medien von Snapchat herunterzuladen und zu speichern.\nBitte wählen Sie den Speicherort, an den die Medien heruntergeladen werden sollen.", + "save_folder": "SnapEnhance benötigt Zugriff auf den Gerätespeicher, um Medien von Snapchat herunterzuladen und zu sichern.\nBitte wähle einen Ziel-Ordner für die Downloads aus.", "select_save_folder_button": "Ordner auswählen" }, "mappings": { - "dialog": "Mappings werden generiert, dies kann eine Weile dauern...", - "generate_failure_no_snapchat": "PurrfectSnap konnte Snapchat nicht erkennen, bitte versuchen Sie, Snapchat neu zu installieren.", - "generate_failure": "Beim Generieren der Mappings ist ein Fehler aufgetreten, bitte versuchen Sie es erneut." + "dialog": "Mappings werden generiert, dies könnte eine Weile dauern ...", + "generate_failure_no_snapchat": "SnapEnhance konnte Snapchat nicht finden, bitte versuche Snapchat neu zu installieren.", + "generate_failure": "Beim Generieren der Zuordnungen ist ein Fehler aufgetreten. Bitte versuche es erneut." }, "permissions": { - "dialog": "Um fortzufahren, müssen Sie die folgenden Anforderungen erfüllen:", + "dialog": "Um fortfahren zu können, musst du diese Anforderungen erfüllen:", "notification_access": "Benachrichtigungszugriff", - "battery_optimization": "Akku-Optimierung", + "battery_optimization": "Batterieoptimierung", "display_over_other_apps": "Über anderen Apps anzeigen", "request_button": "Anfordern" } }, - "scopes": { - "friend": "Freund", - "group": "Gruppe" - }, "manager": { "routes": { - "tasks": "Aufgaben", "features": "Funktionen", - "manage_rule_feature": "Regelfunktion verwalten", "home": "Startseite", "home_settings": "Einstellungen", "home_logs": "Protokolle", - "logger_history": "Logger-Verlauf", - "logged_stories": "Protokollierte Storys", - "friend_tracker": "Freundes-Tracker", - "edit_rule": "Regel bearbeiten", - "file_imports": "Datei-Importe", - "manage_repos": "Repositorys verwalten", - "social": "Soziales", - "manage_scope": "Bereich verwalten", - "messaging_preview": "Vorschau", + "social": "Sozial", "scripts": "Skripte", - "better_location": "Besserer Standort" + "tasks": "Aufgaben", + "logger_history": "Logs Verlauf", + "logged_stories": "Geloggte Storys", + "messaging_preview": "Vorschau", + "manage_scope": "Verwalte Scope", + "friend_tracker": "Freund:in-tracker", + "edit_rule": "Regel bearbeiten", + "better_location": "Besserer Standort", + "file_imports": "Datei Importe", + "manage_rule_feature": "Regelfunktion verwalten", + "manage_repos": "Repositorien verwalten", + "theming": "Personalisierung", + "edit_theme": "Theme bearbeiten" }, "sections": { - "home": { - "version_title": "v{versionName} · geforkt von Eternal", - "update_title": "PurrfectSnap-Update", - "update_content": "Version {version} ist verfügbar!", - "update_button": "Herunterladen", - "debug_build_summary_title": "Sie führen einen Debug-Build von PurrfectSnap aus", - "debug_build_summary_content": "Version {versionName} ({versionCode})", - "debug_build_summary_date": "Build-Datum: {date} (vor {days} Tagen)", - "quick_actions_title": "Schnellaktionen", - "download_icon_description": "Herunterladen", - "completed_icon_description": "Abgeschlossen", - "failed_icon_description": "Fehlgeschlagen", - "manage_quick_actions_description": "Schnellaktionen verwalten", - "quick_actions_icon_description": "Schnellaktionen", - "add_quick_action_description": "Schnellaktion hinzufügen" - }, - "home_logs": { - "no_logs_hint": "Keine Protokolle verfügbar", - "clear_logs_button": "Protokolle löschen", - "export_logs_button": "Protokolle exportieren", - "saving_logs_toast": "Protokolle werden gespeichert, dies kann eine Weile dauern...", - "saved_logs_success_toast": "Protokolle erfolgreich gespeichert", - "saved_logs_failure_toast": "Protokolle konnten nicht gespeichert werden" - }, - "home_settings": { - "actions_title": "Aktionen", - "message_logger_title": "Nachrichten-Logger", - "debug_title": "Debuggen", - "success_toast": "Fertig!", - "message_logger_summary": "{messageCount} Nachrichten\n{storyCount} Storys", - "export_button": "Exportieren", - "clear_button": "Löschen", - "view_logger_history_button": "Logger-Verlauf anzeigen", - "updates_title": "Aktualisierungen", - "auto_update_check": "Automatisch nach Updates suchen", - "update_check_frequency": "Update-Prüffrequenz", - "update_check_frequency_daily": "Täglich", - "update_check_frequency_weekly": "Wöchentlich", - "update_check_frequency_monthly": "Monatlich", - "theme_icon_description": "Thema", - "app_theme_title": "App-Thema", - "theme_mode_system": "System", - "theme_mode_light": "Hell", - "theme_mode_dark": "Dunkel", - "ui_settings_title": "UI-Einstellungen", - "haptic_feedback_label": "Haptisches Feedback", - "test_mode_label": "Testmodus (NUR ZUM DEBUGGEN)", - "disable_feature_loading_label": "Funktionsladen deaktivieren", - "disable_auto_mapper_label": "Auto-Mapper deaktivieren", - "disable_bypass_indicator_label": "Bypass-Statusanzeige deaktivieren", - "update_notification_channel_name": "PurrfectSnap-Updates", - "update_notification_channel_description": "Benachrichtigungen für PurrfectSnap-Updates", - "update_notification_title": "PurrfectSnap-Update verfügbar", - "update_notification_text": "Version %s ist jetzt verfügbar.", - "export_database_failed_toast": "Export der Datenbank fehlgeschlagen! {message}", - "clear_messages_failed_toast": "Löschen der Nachrichten fehlgeschlagen! {message}", - "clear_file_failed_toast": "Löschen der Datei fehlgeschlagen! {message}", - "debug_file_config": "Konfiguration", - "debug_file_mappings": "Zuordnungen", - "debug_file_message_logger": "Nachrichten-Logger", - "debug_file_pinned_best_friend": "Gepinnter bester Freund", - "debug_file_native_sig_cache": "Nativer Signatur-Cache" - }, - "tasks": { - "no_tasks": "Keine Aufgaben", - "merge_button": "Zusammenführen", - "failed_to_open_file": "Datei konnte nicht geöffnet werden", - "merge_files_toast": "Zusammenführen von {count} Dateien", - "remove_selected_tasks_title": "Möchten Sie die ausgewählten Aufgaben wirklich entfernen?", - "remove_all_tasks_title": "Möchten Sie wirklich alle Aufgaben entfernen?", - "delete_files_option": "Dateien ebenfalls löschen", - "remove_selected_tasks_confirm": "{count} Aufgaben entfernen?", - "remove_all_tasks_confirm": "Alle Aufgaben entfernen?", - "clear_tasks_description": "Aufgaben löschen", - "file_not_found_icon_description": "Datei nicht gefunden", - "image_icon_description": "Bild", - "video_icon_description": "Video", - "audio_icon_description": "Audio", - "file_icon_description": "Datei", - "download_icon_description": "Herunterladen", - "chat_action_icon_description": "Chat-Aktion", - "cancel_icon_description": "Abbrechen", - "success_icon_description": "Erfolg", - "failure_icon_description": "Fehler", - "cancelled_icon_description": "Abgebrochen", - "task_status_failure": "Fehler", - "task_status_cancelled": "Abgebrochen" - }, "features": { "disabled": "Deaktiviert", "export_option": "Exportieren", "import_option": "Importieren", "reset_option": "Zurücksetzen", - "config_export_success_toast": "Konfiguration erfolgreich exportiert", - "config_import_success_toast": "Konfiguration erfolgreich importiert", - "config_import_failure_toast": "Konfiguration konnte nicht importiert werden {error}", - "config_export_failure_toast": "Konfiguration konnte nicht exportiert werden {error}", - "saved_config_snackbar": "Konfiguration gespeichert", - "older_required": "Diese Funktion erfordert Snapchat v{version} oder älter, um korrekt zu funktionieren", - "newer_required": "Diese Funktion erfordert Snapchat v{version} oder neuer, um korrekt zu funktionieren", - "search_button": "Suchen" - }, - "manage_rule_feature": { - "disable_state_option": "Deaktiviert", - "disable_state_subtext": "Keine Freunde/Gruppen werden betroffen sein", - "whitelist_state_option": "Niemand außer...", - "whitelist_state_subtext": "Nur {count} Freunde/Gruppen werden von dieser Regel betroffen sein", - "whitelist_state_button": "Erlaubte Freunde/Gruppen auswählen", - "blacklist_state_option": "Alle außer...", - "blacklist_state_subtext": "Alle außer {count} Freunde/Gruppen werden von dieser Regel betroffen sein", - "blacklist_state_button": "Ausgeschlossene Freunde/Gruppen auswählen", - "clear_list_button": "Freundes-/Gruppenliste löschen", - "dialog_clear_confirmation_text": "Möchten Sie die Liste wirklich löschen?" + "config_export_success_toast": "Einstellungen erfolgreich exportiert", + "config_import_success_toast": "Einstellungen erfolgreich importiert", + "config_import_failure_toast": "Einstellungen konnten nicht importiert werden {error}", + "saved_config_snackbar": "Einstellungen gespeichert", + "config_export_failure_toast": "Der Export der Konfiguration ist fehlgeschlagen {error}", + "older_required": "Diese Funktion erfordert Snapchat v{version} oder älter um korrekt zu funktionieren", + "search_button": "Suche", + "newer_required": "Diese Funktion erfordert Snapchat v{version} oder neuer um korrekt zu funktionieren" }, "social": { - "friends_tab": "Freunde", - "groups_tab": "Gruppen", + "streaks_expiration_short": "{hours}h", "empty_hint": "(leer)", - "streaks_expiration_short": "{hours}h" + "friends_tab": "Freunde", + "groups_tab": "Gruppen" }, - "manage_scope": { - "logged_stories_button": "Protokollierte Storys anzeigen", - "e2ee_title": "Ende-zu-Ende-Verschlüsselung", - "rules_title": "Regeln", - "participants_text": "{count} Teilnehmer", - "not_found": "Nicht gefunden", - "streaks_title": "Streifen", - "streaks_length_text": "Länge: {length}", - "streaks_expiration_text": "Läuft in {eta} ab", - "streaks_expiration_text_expired": "Abgelaufen", - "reminder_button": "Erinnerung einstellen", - "delete_scope_confirm_dialog_title": "Möchten Sie einen {scope} wirklich löschen?", - "notes_placeholder": "Klicken, um eine Notiz hinzuzufügen", - "invalid_key_size_32_bytes": "Ungültige Schlüsselgröße (muss 32 Bytes sein)", - "successfully_imported_key": "Schlüssel erfolgreich importiert", - "failed_to_import_key": "Schlüssel konnte nicht importiert werden: {message}", - "export_base64_button": "Base64 exportieren", - "import_base64_button": "Base64 importieren" + "tasks": { + "no_tasks": "Keine Aufgaben", + "merge_files_toast": "Zusammenführen von {count} Dateien", + "remove_selected_tasks_title": "Sind Sie sicher, dass Sie die ausgewählten Aufgaben entfernen möchten?", + "remove_all_tasks_title": "Sind Sie sicher, dass Sie alle Aufgaben entfernen möchten?", + "delete_files_option": "Auch Dateien löschen", + "remove_selected_tasks_confirm": "{count} Aufgaben entfernen?", + "remove_all_tasks_confirm": "Alle Aufgaben entfernen?", + "failed_to_open_file": "Datei konnte nicht geöffnet werden", + "merge_button": "Zusammenführen" + }, + "home": { + "update_title": "SnapEnhance Update", + "update_content": "Version {version} ist verfügbar!", + "update_button": "Herunterladen", + "version_title": "v{versionName} · von eternal", + "debug_build_summary_title": "Du führst einen Debug-Build von SnapEnhance aus", + "quick_actions_title": "Schnelle aktionen", + "debug_build_summary_date": "Erstellungsdatum: {date} ({days} Tage her)", + "debug_build_summary_content": "Version {versionName} ({versionCode})" + }, + "home_logs": { + "saving_logs_toast": "Speichern von Protokollen, das kann eine Weile dauern ...", + "saved_logs_failure_toast": "Speichern von Protokollen fehlgeschlagen", + "saved_logs_success_toast": "Protokolle erfolgreich gespeichert", + "no_logs_hint": "Keine Protokolle verfügbar", + "clear_logs_button": "Protokolle löschen", + "export_logs_button": "Protokolle exportieren" + }, + "home_settings": { + "actions_title": "Aktionen", + "message_logger_title": "Nachrichtenaufzeichner", + "debug_title": "Debuggen", + "message_logger_summary": "{messageCount} Nachrichten\n{storyCount} Stories", + "success_toast": "Erledigt!", + "export_button": "Exportieren", + "clear_button": "Löschen", + "view_logger_history_button": "Historie des Nachrichtenaufzeichners ansehen" }, "logged_stories": { - "story_failed_to_load": "Story konnte nicht geladen werden", - "no_stories": "Keine Storys gefunden", - "save_from_cache_button": "Aus dem Cache speichern", - "downloaded_to_path": "Heruntergeladen nach {path}", - "download_failed": "Download fehlgeschlagen: {message}", - "posted_at": "Gepostet am {date}", - "created_at": "Erstellt am {date}", - "failed_to_open_file": "Datei konnte nicht geöffnet werden. Überprüfen Sie die Protokolle für weitere Informationen", - "failed_to_get_file": "Datei konnte nicht abgerufen werden" + "story_failed_to_load": "Laden fehlgeschlagen", + "no_stories": "Keine Stories gefunden", + "save_from_cache_button": "Aus Zwischenspeicher speichern" }, "messaging_preview": { - "processed_messages_toast": "{count} Nachrichten verarbeitet", - "processed_messages_text": "{count} Nachrichten verarbeitet", - "close_button_description": "Schließen", - "bridge_connection_failed": "Verbindung zur Brücke fehlgeschlagen. Stellen Sie sicher, dass Snapchat im Hintergrund läuft", - "bridge_init_failed": "Initialisierung der Nachrichtenbrücke fehlgeschlagen. Stellen Sie sicher, dass Snapchat im Hintergrund läuft", - "message_fetch_failed": "Nachrichten konnten nicht abgerufen werden", + "bridge_connection_failed": "Verbindung zu Snapchat über den Brückendienst fehlgeschlagen. Stellen Sie sicher das Snapchat im Hintergrund läuft", + "bridge_init_failed": "Initialisierung der Nachrichtenbrücke fehlgeschlagen. Stelle sicher, dass Snapchat im Hintergrund läuft", + "message_fetch_failed": "Fehler beim Abrufen der Nachrichten", "no_message_hint": "Keine Nachricht", "save_selection_option": "Auswahl speichern", - "save_all_option": "Alle speichern", - "unsave_selection_option": "Auswahl aufheben", - "unsave_all_option": "Alle aufheben", + "save_all_option": "Alles speichern", + "unsave_selection_option": "Auswahl nicht mehr speichern", + "unsave_all_option": "Alles nicht mehr speichern", "mark_selection_as_seen_option": "Ausgewählten Snap als gesehen markieren", "mark_all_as_seen_option": "Alle Snaps als gesehen markieren", "delete_selection_option": "Auswahl löschen", - "delete_all_option": "Alle löschen" + "delete_all_option": "Alles löschen" }, "logger_history": { - "download_started_toast": "Download gestartet!", - "download_success_toast": "Heruntergeladen nach {path}", - "download_failed_toast": "Download von {message} fehlgeschlagen", - "edited_at_text": "{message} (bearbeitet am {date})", - "download_button": "Herunterladen", - "select_conversation_placeholder": "Eine Konversation auswählen", - "close_button_description": "Schließen", - "search_button_description": "Suchen", "list_friend_format": "Freund {name}", "list_group_format": "Gruppe {name}", "no_more_messages": "Keine weiteren Nachrichten", "reverse_order_checkbox": "Umgekehrte Reihenfolge", "chat_attachment": "Anhang {index}", - "empty_message": "Leere Chat-Nachricht", - "message_parse_failed": "Nachricht konnte nicht geparst werden", + "empty_message": "Leere Chatnachricht", + "message_parse_failed": "Nachricht konnte nicht verarbeitet werden", "unknown_sender": "Unbekannter Absender", - "download_attachment_failed_toast": "Anhang konnte nicht heruntergeladen werden", - "log_header_format": "{username} ({type}) - {date}" + "download_attachment_failed_toast": "Fehler beim Herunterladen des Anhangs" }, - "file_imports": { - "import_file_button": "Datei importieren", - "file_not_found": "Datei nicht gefunden", - "file_import_failed": "Datei konnte nicht importiert werden: {error}", - "file_imported": "Datei erfolgreich importiert", - "file_delete_failed": "Datei konnte nicht gelöscht werden", - "no_files_hint": "Hier können Sie Dateien zur Verwendung in Snapchat importieren. Drücken Sie die Schaltfläche unten, um eine Datei zu importieren." + "manage_scope": { + "delete_scope_confirm_dialog_title": "Sind Sie sicher, dass Sie ein {scope} löschen wollen?", + "logged_stories_button": "Aufgezeichnete Stories anschauen", + "e2ee_title": "Ende-zu-Ende Verschlüsselung", + "rules_title": "Regeln", + "participants_text": "{count} Teilnehmer", + "not_found": "Nicht gefunden", + "streaks_title": "Streaks", + "streaks_length_text": "Länge: {length}", + "streaks_expiration_text": "Läuft ab in {eta}", + "streaks_expiration_text_expired": "Abgelaufen", + "reminder_button": "Erinnerung erstellen", + "notes_placeholder": "Klicken um eine Notiz hinzuzufügen" + }, + "manage_rule_feature": { + "disable_state_option": "Deaktiviert", + "disable_state_subtext": "Keine Freunde/Gruppen werden betroffen sein", + "whitelist_state_option": "Keiner ausser ...", + "whitelist_state_button": "Erlaubte Freunde/Gruppen auswählen", + "blacklist_state_subtext": "Alle ausser {count} Freunde/Gruppen sind von dieser Regel betroffen", + "clear_list_button": "Liste der Freunde/Gruppen löschen", + "dialog_clear_confirmation_text": "Bist du sicher, dass du die Liste löschen willst?", + "whitelist_state_subtext": "Nur {count} Freunde/Gruppen sind von dieser Regel betroffen", + "blacklist_state_option": "Jeder ausser ...", + "blacklist_state_button": "Ausgeschlossene Freunde/Gruppen auswählen" }, "better_location": { - "spoofed_coordinates_title": "Lat {latitude}, Lng {longitude}", - "save_coordinates_dialog_title": "Koordinaten speichern", "saved_name_dialog_hint": "Gespeicherter Name", "latitude_dialog_hint": "Breitengrad", "longitude_dialog_hint": "Längengrad", "save_dialog_button": "Speichern", - "choose_location_button": "Standort auswählen", - "teleport_to_friend_button": "Zu Freund teleportieren", "spoof_location_toggle": "Standort fälschen", - "suspend_location_updates": "Standortaktualisierungen aussetzen", - "saved_coordinates_title": "Gespeicherte Koordinaten", "no_saved_coordinates_hint": "Keine gespeicherten Koordinaten", - "delete_dialog_title": "Gespeicherte Koordinate löschen", - "delete_dialog_message": "Möchten Sie diese gespeicherte Koordinate wirklich löschen?", + "delete_dialog_title": "Lösche gespeicherte Koordinaten", + "delete_dialog_message": "Bist du sicher, dass du diese gespeicherte Koordinate löschen willst?", "teleport_to_friend_title": "Zu Freund teleportieren", - "search_bar": "Suchen", "no_friends_map": "Keine Freunde auf der Karte", "no_friends_found": "Keine Freunde gefunden", - "edit_location_button_description": "Standort bearbeiten", - "add_icon_description": "Hinzufügen", - "edit_icon_description": "Bearbeiten", - "delete_icon_description": "Löschen" + "save_coordinates_dialog_title": "Koordinaten speichern", + "choose_location_button": "Standort auswählen", + "teleport_to_friend_button": "Zu Freund teleportieren", + "suspend_location_updates": "Standortaktualisierungen aussetzen", + "saved_coordinates_title": "Gespeicherte Koordinaten", + "search_bar": "Suchen", + "spoofed_coordinates_title": "Breitengrad {latitude}, Längengrad {longitude}" + }, + "file_imports": { + "file_imported": "Datei erfolgreich importiert", + "file_delete_failed": "Löschen der Datei fehlgeschlagen", + "no_files_hint": "Hier kannst du Dateien zur Verwendung in Snapchat importieren. Drücken Sie auf die Schaltfläche unten, um eine Datei zu importieren.", + "import_file_button": "Datei importieren", + "file_not_found": "Datei nicht gefunden", + "file_import_failed": "Importieren der Datei fehlgeschlagen: {error}" + }, + "theming": { + "no_themes_hint": "Keine Personalisierungen gefunden" } }, "dialogs": { "add_friend": { "title": "Freund oder Gruppe hinzufügen", "search_hint": "Suchen", - "fetch_error": "Daten konnten nicht abgerufen werden", + "fetch_error": "Fehler beim Abrufen der Daten", "category_groups": "Gruppen", "category_friends": "Freunde", - "participants_text": "{count} Teilnehmer", - "search_icon_description": "Suchen" + "participants_text": "{count} Teilnehmer" }, "scripting_warning": { - "title": "Warnung", - "content": "PurrfectSnap enthält ein Skript-Tool, das die Ausführung von benutzerdefiniertem Code auf Ihrem Gerät ermöglicht. Seien Sie äußerst vorsichtig und installieren Sie Module nur aus bekannten, zuverlässigen Quellen. Nicht autorisierte oder nicht verifizierte Module können Sicherheitsrisiken für Ihr System darstellen." + "content": "SnapEnhance enthält ein Skripting-Tool, das die Ausführung von benutzerdefinierten Code auf Ihrem Gerät ermöglicht. Seien Sie äußerst vorsichtig und installieren Sie nur Module aus bekannten, zuverlässigen Quellen. Unautorisierte oder ungeprüfte Module können Sicherheitsrisiken für Ihr System darstellen.", + "title": "Warnung" }, "reset_config": { - "title": "Konfiguration zurücksetzen", - "content": "Möchten Sie die Konfiguration wirklich zurücksetzen?", - "success_toast": "Konfiguration erfolgreich zurückgesetzt" - }, - "export_config": { - "title": "Sensible Daten exportieren?", - "content": "Möchten Sie die Konfiguration mit sensiblen Daten exportieren? (z. B. Standortkoordinaten usw.)" + "success_toast": "Einstellungen erfolgreich zurückgesetzt", + "title": "Einstellungen zurücksetzen", + "content": "Bist Du sicher, dass Du die Einstellungen zurücksetzen möchtest?" }, "messaging_action": { - "title": "Wählen Sie die zu verarbeitenden Inhaltstypen aus", + "title": "Wählen Sie die zu verarbeitenden Inhaltstypen um fortzufahren", "select_all_button": "Alle auswählen" }, "file_imports": { - "no_files_settings_hint": "Keine Dateien gefunden. Stellen Sie sicher, dass Sie die erforderlichen Dateien im Abschnitt Datei-Importe importiert haben", + "no_files_settings_hint": "Keine Dateien gefunden. Vergewissere dich, dass du die erforderlichen Dateien im Abschnitt „Datei-Import“ importiert hast", "settings_select_file_hint": "Eine importierte Datei auswählen" }, - "quick_actions_dialog": { - "title": "Schnellaktionen bearbeiten", - "subtitle": "Wählen Sie Ihre Schnellaktionen aus und passen Sie ihre Größe an." + "export_config": { + "title": "Sensitive Daten exportieren?", + "content": "Willst du die Konfiguration mit sensiblen Daten exportieren? (z. B. Standortkoordinaten usw.)" } - }, - "friend_tracker": { - "rules_tab": "Regeln", - "logs_tab": "Protokolle", - "export_dialog_title": "Exportieren", - "bulk_export_button": "Massenexport", - "individual_export_button": "Einzelner Export", - "invalid_import_type_dialog_title": "Ungültiger Importtyp", - "invalid_import_type_dialog_text": "Die ausgewählte Datei ist mit diesem Importtyp nicht kompatibel. Bitte wählen Sie den richtigen Importtyp aus.", - "import_dialog_title": "Importieren", - "bulk_import_button": "Massenimport", - "individual_import_button": "Einzelner Import", - "import_button_description": "Importieren", - "export_button_description": "Exportieren", - "export_button": "Exportieren", - "delete_button_description": "Löschen", - "delete_button": "Löschen", - "catalog_button_description": "Katalog", - "catalog_button": "Katalog", - "add_rule_button_description": "Regel hinzufügen", - "add_rule_button": "Regel hinzufügen", - "no_rules_found": "Keine Regeln gefunden", - "empty_rule_name": "(leer)", - "events_suffix": "Ereignisse", - "scopes_suffix": "Bereiche", - "select_rule_to_export_title": "Zu exportierende Regel auswählen", - "deleted_logs_toast": "{count} Protokolle gelöscht", - "delete_logs_dialog_title": "Protokolle löschen?", - "deleting_logs_dialog_text": "{count} Protokolle werden gelöscht...", - "delete_logs_dialog_confirm_text": "Dadurch werden Protokolle basierend auf dem aktuellen Filter und der Suchanfrage gelöscht. Diese Aktion kann nicht rückgängig gemacht werden.", - "exported_logs_toast": "Protokolle exportiert!", - "export_logs_failed_toast": "Protokolle konnten nicht exportiert werden. Überprüfen Sie logcat für weitere Details.", - "export_logs_dialog_title": "Protokolle exportieren?", - "exporting_logs_dialog_text": "Protokolle werden exportiert...", - "export_logs_dialog_confirm_text": "Dadurch werden Protokolle basierend auf dem aktuellen Filter und der Suchanfrage exportiert.", - "export_as_button": "Als {type} exportieren", - "filters_title": "Filter", - "search_by_label": "Suchen nach", - "newest_first_label": "Neueste zuerst", - "since_label": "Seit", - "until_label": "Bis", - "pick_a_date_button": "Ein Datum auswählen", - "search_placeholder": "Suchen", - "filter_button_description": "Filter", - "clear_button_description": "Löschen", - "no_logs_found": "Keine Protokolle gefunden", - "log_event_format": "{event} in {conversation}", - "condition_only_inside_conversation": "Nur wenn ich in der Konversation bin", - "condition_only_outside_conversation": "Nur wenn ich außerhalb der Konversation bin", - "condition_only_when_app_active": "Nur wenn Snapchat aktiv ist", - "condition_only_when_app_inactive": "Nur wenn Snapchat inaktiv ist", - "condition_no_push_notification_when_app_active": "Keine Push-Benachrichtigung, wenn Snapchat aktiv ist", - "add_event_dialog_title": "Ereignis hinzufügen", - "event_type_label": "Ereignistyp", - "triggers_title": "Auslöser", - "conditions_title": "Bedingungen", - "add_button": "Hinzufügen", - "default_rule_name": "Benutzerdefinierte Regel", - "discard_changes_dialog_title": "Änderungen verwerfen?", - "discard_changes_dialog_text": "Sie haben nicht gespeicherte Änderungen. Möchten Sie sie wirklich verwerfen?", - "discard_button": "Verwerfen", - "cannot_save_rule_dialog_title": "Regel kann nicht gespeichert werden", - "cannot_save_rule_dialog_text": "Eine Regel muss mindestens ein Ereignis haben, um gespeichert zu werden.", - "duplicate_rule_name_dialog_title": "Doppelter Regelname", - "duplicate_rule_name_dialog_text": "Eine Regel mit diesem Namen existiert bereits. Bitte wählen Sie einen anderen Namen.", - "delete_rule_dialog_title": "Regel löschen", - "delete_rule_dialog_text": "Möchten Sie diese Regel wirklich löschen?", - "new_rule_title": "Neue Regel", - "edit_rule_title": "Regel bearbeiten", - "back_button_description": "Zurück", - "save_button_description": "Speichern", - "general_section_title": "Allgemein", - "rule_name_label": "Regelname", - "author_name_label": "Autorenname", - "scope_section_title": "Bereich", - "scope_all": "Alle", - "scope_whitelist": "Whitelist", - "scope_blacklist": "Schwarze Liste", - "select_friends_groups_button": "Freunde/Gruppen auswählen ({count})", - "events_section_title": "Ereignisse", - "add_event_button": "Ereignis hinzufügen", - "no_events_text": "Keine Ereignisse" - }, - "friend_tracker_catalog": { - "download_failed": "Download fehlgeschlagen: {code}", - "error": "Fehler: {message}", - "no_repos_added": "Keine Repositorys hinzugefügt.", - "no_rules_available": "Keine Regeln aus einem Repository verfügbar.", - "by_author": "von {author}", - "imported_button": "Importiert", - "import_button": "Importieren", - "title": "Freundes-Tracker-Katalog", - "manage_repos_description": "Repositorys verwalten" - }, - "friend_tracker_export": { - "title": "Regeln exportieren", - "back_button_description": "Zurück", - "exported_toast": "Freundes-Tracker-Regeln exportiert!", - "export_failed_toast": "Regeln konnten nicht exportiert werden: {message}", - "save_button": "Speichern", - "expand_button_description": "Erweitern" - }, - "friend_tracker_import": { - "title": "Regeln importieren", - "back_button_description": "Zurück", - "imported_toast": "Freundes-Tracker-Regeln importiert!", - "import_failed_toast": "Regeln konnten nicht importiert werden: {message}", - "confirm_button": "Bestätigen", - "expand_button_description": "Erweitern" - }, - "friend_tracker_repos": { - "invalid_repo_title": "Ungültiges Repository", - "add_repo_button": "Repository hinzufügen", - "add_repo_dialog_title": "Repository-URL hinzufügen", - "repo_url_label": "Repository-URL", - "repo_added_toast": "Repository erfolgreich hinzugefügt!", - "invalid_repo_error": "Dies scheint kein gültiges Freundes-Tracker-Repository zu sein.", - "add_repo_failed_toast": "Repository konnte nicht hinzugefügt werden: {message}", - "add_button": "Hinzufügen", - "no_repos_added": "Keine Repositorys hinzugefügt", - "remove_button": "Entfernen", - "remove_repo_dialog_title": "Repository entfernen", - "remove_repo_dialog_text": "Möchten Sie dieses Repository wirklich entfernen?" - }, - "navigation": { - "tracker_tab_label": "Tracker", - "customize_bottom_bar_title": "Untere Leiste anpassen", - "customize_bottom_bar_subtitle": "Tabs neu anordnen, hinzufügen oder entfernen. Maximal fünf.", - "shown_tabs_title": "Angezeigte Tabs", - "no_tabs_selected_text": "Keine Tabs ausgewählt", - "available_tabs_title": "Verfügbare Tabs", - "reset_button": "Zurücksetzen", - "done_button": "Fertig" - }, - "scripting": { - "script_already_installed": "Skript bereits installiert!", - "downloading_script": "Skript wird heruntergeladen...", - "script_downloaded": "Skript {name} heruntergeladen!", - "download_script_failed": "Skript konnte nicht heruntergeladen werden. Überprüfen Sie die Protokolle für weitere Details", - "import_script_from_url_title": "Skript von URL importieren", - "import_script_warning": "Warnung: Importierte Skripte können für Ihr Gerät schädlich sein. Importieren Sie Skripte nur aus vertrauenswürdigen Quellen.", - "enter_url_label": "URL hier eingeben:", - "script_imported": "Skript {name} importiert!", - "import_failed": "Skript konnte nicht importiert werden. {message}. Überprüfen Sie die Protokolle für weitere Details", - "import_button": "Importieren", - "update_module_button": "Modul aktualisieren", - "updating_script": "Skript {name} wird aktualisiert...", - "module_not_found": "Modul nicht gefunden", - "updated_script": "{name} auf Version {version} aktualisiert", - "update_module_failed": "Modul konnte nicht aktualisiert werden. Überprüfen Sie die Protokolle für weitere Details", - "edit_module_button": "Modul bearbeiten", - "open_module_failed": "Moduldatei konnte nicht geöffnet werden. Überprüfen Sie die Protokolle für weitere Details", - "clear_module_data_button": "Moduldaten löschen", - "module_data_cleared": "Moduldaten gelöscht!", - "clear_module_data_failed": "Moduldaten konnten nicht gelöscht werden. Überprüfen Sie die Protokolle für weitere Details", - "delete_module_button": "Modul löschen", - "deleted_script": "Skript {name} gelöscht!", - "delete_module_failed": "Modul konnte nicht gelöscht werden. Überprüfen Sie die Protokolle für weitere Details", - "actions_title": "Aktionen", - "no_description": "Keine Beschreibung", - "update_available": "Update verfügbar: {version}", - "actions_button": "Aktionen", - "loaded_script": "Skript {name} geladen", - "unloaded_script": "Skript {name} entladen", - "enable_script_failed": "Skript konnte nicht aktiviert werden. Überprüfen Sie die Protokolle für weitere Details", - "disable_script_failed": "Skript konnte nicht deaktiviert werden. Überprüfen Sie die Protokolle für weitere Details", - "select_scripts_folder_toast": "Bitte wählen Sie Ihren Skriptordner aus!", - "manage_repos_button": "Repositorys verwalten", - "import_from_url_button": "Von URL importieren", - "open_scripts_folder_button": "Skriptordner öffnen", - "no_settings_for_module": "Dieses Modul hat keine Einstellungen", - "installed_scripts_tab": "Installierte Skripte", - "catalog_tab": "Katalog", - "no_scripts_folder_selected_title": "Kein Skriptordner ausgewählt", - "select_folder_button": "Ordner auswählen", - "no_scripts_found_title": "Keine Skripte gefunden.", - "use_catalog_to_add_scripts": "Verwenden Sie den Katalog-Tab, um Skripte hinzuzufügen!", - "ok_button_timeout": "OK ({timeout})", - "documentation_button": "Dokumentation", - "catalog": { - "script_already_installed": "Skript bereits installiert!", - "download_failed": "Download fehlgeschlagen: {code}", - "script_downloaded": "Skript heruntergeladen!", - "could_not_create_file": "Datei konnte nicht erstellt werden.", - "no_scripts_folder_selected": "Kein Skriptordner ausgewählt.", - "error": "Fehler: {message}", - "no_repos_added": "Keine Repositorys hinzugefügt.", - "repo_list_info": "Hier finden Sie eine Liste der Repositorys: ", - "link_text": "Link", - "no_scripts_available": "Keine Skripte aus einem Repository verfügbar.", - "by_author": "von {author}", - "version": "Version: {version}", - "installed_button": "Installiert", - "download_button": "Herunterladen" - }, - "repos": { - "invalid_repo_title": "Ungültiges Repository", - "add_repo_button": "Repository hinzufügen", - "add_repo_dialog_title": "Repository-URL hinzufügen", - "repo_url_label": "Repository-URL", - "repo_added_toast": "Repository erfolgreich hinzugefügt!", - "invalid_repo_error": "Dies scheint kein gültiges Skript-Repository zu sein.", - "add_repo_failed_toast": "Repository konnte nicht hinzugefügt werden: {message}", - "add_button": "Hinzufügen", - "no_repos_added": "Keine Repositorys hinzugefügt", - "remove_button": "Entfernen", - "remove_repo_dialog_title": "Repository entfernen", - "remove_repo_dialog_text": "Möchten Sie dieses Repository wirklich entfernen?" - } - }, - "features": { - "config_import": { - "title": "Import bestätigen", - "back_button_description": "Zurück", - "config_imported_toast": "Konfiguration importiert!", - "confirm_button": "Bestätigen", - "expand_button_description": "Erweitern", - "enable_feature": "Funktion aktivieren", - "enabled": "Aktiviert", - "disabled": "Deaktiviert" - }, - "config_export": { - "title": "Exportzusammenfassung", - "back_button_description": "Zurück", - "save_button": "Speichern", - "expand_button_description": "Erweitern", - "enable_feature": "Funktion aktivieren", - "enabled": "Aktiviert", - "disabled": "Deaktiviert" - } - }, - "manage_repos": { - "title": "Verwalte {type} Repositories", - "add_repo_button": "Repository hinzufügen", - "add_repo_dialog_title": "Repository-URL hinzufügen", - "repo_url_label": "Repository-URL", - "repo_added_successfully": "Repository erfolgreich hinzugefügt!", - "add_repo_failed": "Repository konnte nicht hinzugefügt werden: {message}", - "add_button": "Hinzufügen", - "no_repos_added": "Keine Repositorys hinzugefügt", - "remove_button": "Entfernen" } }, "rules": { - "toasts": { - "enabled": "{ruleName} aktiviert", - "disabled": "{ruleName} deaktiviert" - }, "modes": { - "blacklist": "Blacklist-Modus", - "whitelist": "Whitelist-Modus" + "blacklist": "Blacklist Modus", + "whitelist": "Whitlist Modus" }, "properties": { "auto_download": { - "name": "Automatischer Download", - "description": "Snaps beim Anzeigen automatisch herunterladen", + "name": "Auto-Download", + "description": "Snaps beim Ansehen automatisch herunterladen", "options": { - "blacklist": "Vom automatischen Download ausschließen", - "whitelist": "Automatischer Download" + "blacklist": "Vom Auto-Download ausschließen", + "whitelist": "Auto-Download" } }, "stealth": { - "name": "Stealth-Modus", - "description": "Verhindert, dass jemand weiß, dass Sie seine Snaps/Chats und Konversationen geöffnet haben", + "name": "Heimlicher Modus", + "description": "Verhindert, dass jemand weiß, dass du seine Snaps/Chats oder Konversationen geöffnet hast", "options": { - "blacklist": "Vom Stealth-Modus ausschließen", - "whitelist": "Stealth-Modus" + "blacklist": "Vom Heimlichen Modus ausschließen", + "whitelist": "Heimlicher Modus" } }, "auto_save": { - "name": "Automatisches Speichern", - "description": "Speichert Chat-Nachrichten beim Anzeigen", + "name": "Automatisches speichern", + "description": "Speichert Chat-Nachrichten beim Ansehen", "options": { "blacklist": "Vom automatischen Speichern ausschließen", - "whitelist": "Automatisches Speichern" - } - }, - "unsaveable_messages": { - "name": "Nicht speicherbare Nachrichten", - "description": "Verhindert, dass Nachrichten von anderen Personen im Chat gespeichert werden", - "options": { - "blacklist": "Von nicht speicherbaren Nachrichten ausschließen", - "whitelist": "Nicht speicherbare Nachrichten" - } - }, - "auto_open_snaps": { - "name": "Snaps automatisch öffnen", - "description": "Öffnet Snaps automatisch beim Empfang", - "options": { - "blacklist": "Vom automatischen Öffnen von Snaps ausschließen", - "whitelist": "Snaps automatisch öffnen" + "whitelist": "Automatisch speichern" } }, "hide_friend_feed": { - "name": "Aus dem Freundes-Feed ausblenden" + "name": "Vom Freundes-Feed ausblenden" }, "e2e_encryption": { "name": "E2E-Verschlüsselung verwenden" }, "pin_conversation": { - "name": "Konversation anpinnen" + "name": "Unterhaltung anheften" }, - "exclude_message_logger": { - "name": "Vom Nachrichten-Logger ausschließen" + "unsaveable_messages": { + "name": "Nicht speicherbare Nachrichten", + "options": { + "blacklist": "Von nicht speicherbaren Nachrichten ausschließen", + "whitelist": "Nicht speicherbare Nachrichten" + }, + "description": "Verhindert, dass Nachrichten im Chat von anderen Personen gespeichert werden können" + }, + "auto_open_snaps": { + "name": "Öffne Snaps automatisch", + "description": "Öffnet Snaps selbstständig beim Empfangen", + "options": { + "blacklist": "Von der automatischen Snap-Öffnung ausschließen", + "whitelist": "Automatisches Öffnen von Snaps" + } } - } - }, - "actions": { - "clean_snapchat_cache": { - "name": "Snapchat-Cache leeren", - "description": "Leert den Snapchat-Cache" }, - "manage_friend_list": { - "name": "Freundesliste verwalten", - "description": "Importieren/Exportieren Sie Ihre Freundesliste beim Sichern" - }, - "export_chat_messages": { - "name": "Chat-Nachrichten exportieren", - "description": "Exportiert Konversationsnachrichten in eine JSON/HTML/TXT-Datei" - }, - "export_memories": { - "name": "Erinnerungen exportieren", - "description": "Exportiert Erinnerungen in eine ZIP-Datei" - }, - "bulk_messaging_action": { - "name": "Massen-Nachrichtenaktion", - "description": "Führt Operationen wie das Löschen von Freunden oder das Massenlöschen von Konversationen durch" - }, - "regen_mappings": { - "name": "Mappings neu generieren", - "description": "Mappings manuell neu generieren" - }, - "change_language": { - "name": "Sprache ändern", - "description": "Ändern Sie die Sprache von PurrfectSnap" - }, - "file_imports": { - "name": "Datei-Importe", - "description": "Dateien zur Verwendung in Snapchat importieren" - }, - "friend_tracker": { - "name": "Freundes-Tracker", - "description": "Verfolgen Sie Ihre Freunde auf Snapchat" - }, - "logger_history": { - "name": "Logger-Verlauf", - "description": "Verlauf der protokollierten Nachrichten anzeigen" + "toasts": { + "enabled": "{ruleName} aktiviert", + "disabled": "{ruleName} deaktiviert" } }, "features": { "notices": { - "unstable": "⚠️ Instabil", - "ban_risk": "⚠️ Diese Funktion kann zu Sperren führen", - "internal_behavior": "⚠️ Dies kann das interne Verhalten von Snapchat beeinträchtigen" + "unstable": "⚠ Instabil", + "ban_risk": "⚠ Dieses Feature kann zu Bans führen", + "internal_behavior": "⚠ Dies kann das interne Verhalten von Snapchat stören" }, "properties": { "downloader": { "name": "Downloader", - "description": "Snapchat-Medien herunterladen", + "description": "Snapchat Medien herunterladen", "properties": { "save_folder": { - "name": "Speicherordner", - "description": "Wählen Sie das Verzeichnis aus, in das alle Medien heruntergeladen werden sollen" + "name": "Speicherverzeichnis", + "description": "Wähle das Verzeichnis, in das alle Medien heruntergeladen werden sollen" }, "auto_download_sources": { - "name": "Automatische Download-Quellen", - "description": "Wählen Sie die Quellen aus, von denen automatisch heruntergeladen werden soll" + "name": "Quellen automatisch herunterladen", + "description": "Wähle die Quellen, von denen automatisch herunterzuladen ist" }, "prevent_self_auto_download": { - "name": "Eigenen automatischen Download verhindern", - "description": "Verhindert, dass Ihre eigenen Snaps automatisch heruntergeladen werden" + "name": "Selbst-Auto-Download verhindern", + "description": "Verhindert, dass eigene Snaps automatisch heruntergeladen werden" }, "path_format": { "name": "Pfadformat", - "description": "Geben Sie das Dateipfadformat an" + "description": "Gib das Dateiformat an" }, "allow_duplicate": { - "name": "Duplikate zulassen", - "description": "Ermöglicht das mehrfache Herunterladen derselben Medien" + "name": "Duplikate erlauben", + "description": "Ermöglicht es, dass dieselben Medien mehrmals heruntergeladen werden" }, "merge_overlays": { "name": "Overlays zusammenführen", - "description": "Kombiniert den Text und die Medien eines Snaps in einer einzigen Datei" + "description": "Kombiniert den Text und die Medien eines Snaps in eine Datei" }, "force_image_format": { "name": "Bildformat erzwingen", "description": "Erzwingt das Speichern von Bildern in einem bestimmten Format" }, "force_voice_note_format": { - "name": "Sprachnotizformat erzwingen", + "name": "Sprachnotiz Format erzwingen", "description": "Erzwingt das Speichern von Sprachnotizen in einem bestimmten Format" }, - "auto_download_voice_notes": { - "name": "Sprachnotizen automatisch herunterladen", - "description": "Lädt Sprachnotizen beim Abspielen automatisch herunter" - }, "download_profile_pictures": { "name": "Profilbilder herunterladen", - "description": "Ermöglicht das Herunterladen von Profilbildern von der Profilseite" - }, - "opera_download_button": { - "name": "Opera-Download-Schaltfläche", - "description": "Fügt eine Download-Schaltfläche in der oberen rechten Ecke hinzu, wenn ein Snap angezeigt wird.\nLanges Drücken auf Schaltflächen erzwingt den Download" - }, - "download_context_menu": { - "name": "Download-Kontextmenü", - "description": "Ermöglicht das Herunterladen/Vorschau von Nachrichten aus einer Konversation oder einer Story über das Kontextmenü.\nLanges Drücken auf Schaltflächen erzwingt den Download" + "description": "Ermöglicht das Herunterladen von Profilbildern von einer Profilseite" }, "ffmpeg_options": { "name": "FFmpeg-Optionen", - "description": "Geben Sie zusätzliche FFmpeg-Optionen an", + "description": "Zusätzliche FFmpeg-Optionen angeben", "properties": { "threads": { - "name": "Themen", - "description": "Die Anzahl der zu verwendenden Threads" + "name": "Threads", + "description": "Die Anzahl Threads, welche zu gebrauchen ist" }, "preset": { - "name": "Voreinstellung", - "description": "Stellen Sie die Geschwindigkeit der Konvertierung ein" + "name": "Voreinstellungen", + "description": "Geschwindigkeit der Konvertierung festlegen" }, "constant_rate_factor": { - "name": "Konstanter Ratenfaktor", - "description": "Stellen Sie den konstanten Ratenfaktor für den Video-Encoder ein\nVon 0 bis 51 für libx264" + "description": "Setze den Constant Rate Factor für den Video-Encoder\nvon 0 bis 51 für libx264", + "name": "Konstanter Rate-Faktor" }, "video_bitrate": { - "name": "Video-Bitrate", - "description": "Stellen Sie die Video-Bitrate ein (kbps)" + "name": "Videobitrate", + "description": "Video-Bitrate (kbps) festlegen" }, "audio_bitrate": { - "name": "Audio-Bitrate", - "description": "Stellen Sie die Audio-Bitrate ein (kbps)" + "name": "Audiobitrate", + "description": "Audio-Bitrate (kbps) festlegen" }, "custom_video_codec": { "name": "Benutzerdefinierter Video-Codec", - "description": "Stellen Sie einen benutzerdefinierten Video-Codec ein (z. B. libx264)" + "description": "Wähle einen benutzerdefinierten Video-Codec (z.B. libx264)" }, "custom_audio_codec": { "name": "Benutzerdefinierter Audio-Codec", - "description": "Stellen Sie einen benutzerdefinierten Audio-Codec ein (z. B. AAC)" + "description": "Wähle einen benutzerdefinierten Audio-Codec (z.B. AAC)" } } }, "logging": { "name": "Protokollierung", - "description": "Zeigt Toasts an, wenn Medien heruntergeladen werden" + "description": "Zeigt Toasts, wenn Medien heruntergeladen werden" }, "custom_path_format": { - "name": "Benutzerdefiniertes Pfadformat", - "description": "Geben Sie ein benutzerdefiniertes Pfadformat für heruntergeladene Medien an\n\nVerfügbare Variablen:\n - %username%\n - %source%\n - %hash%\n - %date_time%" + "description": "Legen Sie ein benutzerdefiniertes Pfadformat für heruntergeladene Medien fest\n\nVerfügbare Variablen:\n - %username%\n - %source%\n - %hash%\n - %date_time%", + "name": "Benutzerdefiniertes Pfadformat" + }, + "opera_download_button": { + "description": "Fügt einen Download-Button in der oberen rechten Ecke hinzu, wenn ein Snap angezeigt wird.\nGedrückt halten um einen Download zu starten", + "name": "Schwebender Download Button" + }, + "download_context_menu": { + "name": "Download Kontext Menü", + "description": "Ermöglicht es, Nachrichten oder eine Story herunterzuladen/vorher anzuschauen mithilfe des Kontext Menüs.\nLanges Drücken des Knopfes erzwingt den Download" + }, + "auto_download_voice_notes": { + "name": "Sprachnotizen automatisch herunterladen", + "description": "Sprachnotizen automatisch herunterladen, wenn sie abgespielt werden" } } }, "user_interface": { "name": "Benutzeroberfläche", - "description": "Ändern Sie das Aussehen und Verhalten von Snapchat", + "description": "Ändere das Aussehen von Snapchat", "properties": { "enable_app_appearance": { - "name": "App-Erscheinungsbildeinstellungen aktivieren", - "description": "Aktiviert die versteckte App-Erscheinungsbildeinstellung\nAuf neueren Snapchat-Versionen möglicherweise nicht erforderlich" + "name": "Aktiviert die App Darstellungseinstellungen", + "description": "Aktiviert die versteckte App-Erscheinungsbild Einstellung,\nbei neueren Snapchat-Versionen möglicherweise nicht erforderlich" }, "friend_feed_message_preview": { - "name": "Nachrichtenvorschau im Freundes-Feed", - "description": "Zeigt eine Vorschau der letzten Nachrichten im Freundes-Feed an", + "name": "Freund Feed Nachrichten Vorschau", + "description": "Zeigt eine Vorschau der letzten Nachrichten im Freundes-Feed", "properties": { "amount": { - "name": "Menge", - "description": "Die Menge der anzuzeigenden Nachrichten" + "name": "Anzahl", + "description": "Die Anzahl der Nachrichten, die in der Vorschau angezeigt werden" } } }, - "snap_preview": { - "name": "Snap-Vorschau", - "description": "Zeigt eine kleine Vorschau neben ungelesenen Snaps im Chat an" - }, "bootstrap_override": { - "name": "Bootstrap-Überschreibung", - "description": "Überschreibt die Bootstrap-Einstellungen der Benutzeroberfläche", + "name": "Bootstrap Überschreibung", + "description": "Bootstrap-Einstellungen der Benutzeroberfläche überschreiben", "properties": { "app_appearance": { "name": "App-Erscheinungsbild", - "description": "Legt ein dauerhaftes App-Erscheinungsbild fest" + "description": "Legt eine dauerhafte App-Darstellung fest" }, "home_tab": { - "name": "Start-Tab", + "name": "Home Registerkarte", "description": "Überschreibt den Start-Tab beim Öffnen von Snapchat" + }, + "simple_snapchat": { + "description": "Aktiviert eine vereinfachte Version von Snapchat", + "name": "Einfaches Snapchat" } } }, - "force_amoled_theme": { - "name": "Amoled-Dunkelmodus", - "description": "Verwendet einen echten schwarzen Hintergrund für das dunkle Thema" - }, "map_friend_nametags": { - "name": "Verbesserte Freundes-Namensschilder auf der Karte", + "name": "Verbesserte Karten-Namensschilder von Freunden", "description": "Verbessert die Namensschilder von Freunden auf der Snapmap" }, + "streak_expiration_info": { + "name": "Informationen zum Flammen-Ablauf anzeigen", + "description": "Zeigt einen Flammen-Ablauf-Timer neben dem Flammen-Zähler" + }, + "hide_friend_feed_entry": { + "name": "Freund Feed Eintrag ausblenden", + "description": "Versteckt einen bestimmten Freund aus dem Freundes-Feed,\nBenutze den sozialen Tab um diese Funktion zu verwalten" + }, + "hide_streak_restore": { + "name": "Flammen-Wiederherstellung verstecken", + "description": "Versteckt den Wiederherstellen-Button im Freundesfeed" + }, + "hide_ui_components": { + "name": "UI-Komponenten ausblenden", + "description": "Wähle aus welche UI-Elemente ausgeblendet werden sollen" + }, + "disable_spotlight": { + "name": "Spotlight deaktivieren", + "description": "Deaktiviert die Spotlight Seite" + }, + "friend_feed_menu_buttons": { + "name": "Schaltflächen für das Freunde-Feed Menü", + "description": "Wähle aus welche Schaltflächen in der Freunde Feed Menüleiste angezeigt werden sollen" + }, + "enable_friend_feed_menu_bar": { + "name": "Freunde Feed Menüleiste", + "description": "Aktiviert die neue Freunde Feed Menüleiste" + }, + "opera_media_quick_info": { + "description": "Zeigt nützliche Informationen zu Medien wie das Erstellungsdatum im Kontextmenü der Snap-Ansicht an", + "name": "Medien Schnellinfo" + }, + "vertical_story_viewer": { + "name": "Vertikale Story Ansicht", + "description": "Aktiviert die vertikale Story Ansicht für alle Storys" + }, + "old_bitmoji_selfie": { + "name": "Altes Bitmoji-Selfie", + "description": "Bringt die Bitmoji-Selfies aus früheren Snapchat-Versionen zurück" + }, "prevent_message_list_auto_scroll": { "name": "Automatisches Scrollen der Nachrichtenliste verhindern", "description": "Verhindert, dass die Nachrichtenliste beim Senden/Empfangen einer Nachricht nach unten scrollt" }, - "streak_expiration_info": { - "name": "Streak-Ablaufinformationen anzeigen", - "description": "Zeigt einen Streak-Ablauf-Timer neben dem Streak-Zähler an" + "edit_text_override": { + "name": "Textfeld-Verhalten überschreiben", + "description": "Überschreibt das Verhalten von Textfeldern" }, - "hide_friend_feed_entry": { - "name": "Freundes-Feed-Eintrag ausblenden", - "description": "Blendet einen bestimmten Freund aus dem Freundes-Feed aus\nVerwenden Sie den sozialen Tab, um diese Funktion zu verwalten" - }, - "hide_streak_restore": { - "name": "Streak-Wiederherstellung ausblenden", - "description": "Blendet die Schaltfläche Wiederherstellen im Freundes-Feed aus" - }, - "hide_quick_add_suggestions": { - "name": "Schnellhinzufügen-Vorschläge ausblenden", - "description": "Entfernt Schnellhinzufügen-Freundesvorschläge" + "snap_preview": { + "name": "Snap-Vorschau", + "description": "Zeigt eine kleine Vorschau neben ungesehenen Snaps im Chat an" }, "hide_story_suggestions": { - "name": "Story-Vorschläge ausblenden", - "description": "Entfernt Vorschläge von der Storys-Seite" + "name": "Story Vorschläge ausblenden", + "description": "Entfernt Empfehlungen von der Story‐Seite" }, - "hide_ui_components": { - "name": "UI-Komponenten ausblenden", - "description": "Wählen Sie aus, welche UI-Komponenten ausgeblendet werden sollen" - }, - "opera_media_quick_info": { - "name": "Opera-Medien-Schnellinfo", - "description": "Zeigt nützliche Informationen zu Medien wie das Erstellungsdatum im Kontextmenü des Opera-Viewers an" - }, - "old_bitmoji_selfie": { - "name": "Altes Bitmoji-Selfie", - "description": "Bringt die Bitmoji-Selfies aus älteren Snapchat-Versionen zurück" - }, - "disable_spotlight": { - "name": "Spotlight deaktivieren", - "description": "Deaktiviert die Spotlight-Seite" - }, - "friend_feed_menu_buttons": { - "name": "Freundes-Feed-Menüschaltflächen", - "description": "Wählen Sie aus, welche Schaltflächen im Freundes-Feed-Menü angezeigt werden sollen" - }, - "auto_close_friend_feed_menu": { - "name": "Freundes-Feed-Menü automatisch schließen", - "description": "Schließt das Freundes-Feed-Menü automatisch nach dem Drücken einer Einstellungsschaltfläche" - }, - "vertical_story_viewer": { - "name": "Vertikaler Story-Viewer", - "description": "Aktiviert den vertikalen Story-Viewer für alle Storys" - }, - "enable_friend_feed_menu_bar": { - "name": "Freundes-Feed-Menüleiste", - "description": "Aktiviert die neue Freundes-Feed-Menüleiste" + "stealth_mode_indicator": { + "name": "Diebstahl Modus Indikator", + "description": "Fügt den Konversationen im Stealth-Modus ein 👻-Emoji hinzu" }, "message_indicators": { "name": "Nachrichtenindikatoren", - "description": "Fügt Nachrichten spezifische Indikatorsymbole hinzu\nHinweis: Indikatoren sind möglicherweise nicht 100 % genau" + "description": "Fügt Nachrichten spezifische Anzeigesymbole hinzu\nHinweis: Die Symbole sind möglicherweise nicht 100 % genau" }, - "stealth_mode_indicator": { - "name": "Stealth-Modus-Indikator", - "description": "Fügt ein 👻-Emoji neben Konversationen im Stealth-Modus hinzu" + "custom_theme": { + "description": "Individualisiere Snapchat's Farben\nHinweis: Wenn du einen dunkles Thema (wie Amoled) wählst, musst du möglicherweise den dunklen Modus in den Einstellungen von Snapchat aktivieren für ein besseres Ergebnis", + "name": "Benutzerdefiniertes Thema" }, - "edit_text_override": { - "name": "Textbearbeitung überschreiben", - "description": "Überschreibt das Verhalten des Textfelds" + "auto_close_friend_feed_menu": { + "description": "Schließt das Freunde Feed Menü automatisch nachdem du einen Knopf für die Einstellungen drückst" }, - "prevent_forced_keyboard": { - "name": "Erzwungene Tastatur verhindern", - "description": "Verhindert, dass Snapchat die Tastatur automatisch öffnet, wenn Sie eine Konversation öffnen" - }, - "settings_menu": { - "name": "Einstellungsmenü", - "description": "Ändert die Art und Weise, wie Sie das PurrfectSnap-Menü öffnen", - "options": { - "default": "Standard", - "legacy": "Veraltet" - } + "hide_quick_add_suggestions": { + "name": "Verstecke Vorschläge" } } }, "messaging": { - "name": "Nachrichten", - "description": "Ändern Sie die Art und Weise, wie Sie mit Freunden interagieren", + "name": "Mitteilungen", + "description": "Ändern wie mit Freunden interagiert wird", "properties": { - "bypass_screenshot_detection": { - "name": "Screenshot-Erkennung umgehen", - "description": "Verhindert, dass Snapchat erkennt, wenn Sie einen Screenshot machen" - }, "anonymous_story_viewing": { - "name": "Anonymes Ansehen von Storys", - "description": "Verhindert, dass jemand weiß, dass Sie seine Story gesehen haben" - }, - "prevent_story_rewatch_indicator": { - "name": "Story-Wiederholungsanzeige verhindern", - "description": "Verhindert, dass jemand weiß, dass Sie seine Story erneut angesehen haben" - }, - "hide_peek_a_peek": { - "name": "Peek-a-Peek ausblenden", - "description": "Verhindert, dass eine Benachrichtigung gesendet wird, wenn Sie halb in einen Chat wischen" + "name": "Anonyme Story Ansicht", + "description": "Verhindert, dass jemand erfährt, dass du seine Story gesehen hast" }, "hide_bitmoji_presence": { - "name": "Bitmoji-Anwesenheit ausblenden", - "description": "Verhindert, dass Ihr Bitmoji im Chat angezeigt wird" + "name": "Bitmoji Präsenz verstecken", + "description": "Verhindert, dass dein Bitmoji im Chat auftaucht" }, "hide_typing_notifications": { - "name": "Tipp-Benachrichtigungen ausblenden", - "description": "Verhindert, dass jemand weiß, dass Sie eine Nachricht tippen" + "name": "Tippen-Benachrichtigungen verbergen", + "description": "Verhindert, dass jemand erfährt, dass du eine Nachricht tippst" }, "unlimited_snap_view_time": { - "name": "Unbegrenzte Snap-Anzeigedauer", - "description": "Entfernt das Zeitlimit für das Anzeigen von Snaps" - }, - "auto_mark_as_read": { - "name": "Automatisch als gelesen markieren", - "description": "Markiert Nachrichten/Snaps automatisch als gelesen, auch wenn der Stealth-Modus aktiviert ist" - }, - "mark_snap_as_seen_button": { - "name": "Snap als gesehen markieren-Schaltfläche", - "description": "Fügt eine Schaltfläche hinzu, um einen Snap beim Anzeigen als gesehen zu markieren.\nDies funktioniert auch, wenn der Stealth-Modus aktiviert ist" - }, - "skip_when_marking_as_seen": { - "name": "Beim Markieren als gesehen überspringen", - "description": "Überspringt automatisch zum nächsten Snap, wenn ein Snap als gesehen markiert wird.\nIn Kombination mit der Schaltfläche „Snap als gesehen markieren“ verwenden" - }, - "loop_media_playback": { - "name": "Medienwiedergabe in Schleife", - "description": "Wiederholt die Medienwiedergabe beim Anzeigen von Snaps/Storys" + "name": "Unbegrenzte Zeit zum Ansehen von Snaps", + "description": "Entfernt das Zeitlimit für die Anzeige von Snaps" }, "disable_replay_in_ff": { - "name": "Wiederholung in FF deaktivieren", - "description": "Deaktiviert die Möglichkeit, mit einem langen Druck aus dem Freundes-Feed erneut abzuspielen" - }, - "half_swipe_notifier": { - "name": "Halb-Wisch-Benachrichtiger", - "description": "Benachrichtigt Sie, wenn jemand halb in eine Konversation wischt", - "properties": { - "min_duration": { - "name": "Mindestdauer", - "description": "Die Mindestdauer des halben Wischens (in Sekunden)" - }, - "max_duration": { - "name": "Maximale Dauer", - "description": "Die maximale Dauer des halben Wischens (in Sekunden)" - } - } - }, - "call_start_confirmation": { - "name": "Bestätigung des Anrufstarts", - "description": "Zeigt einen Bestätigungsdialog an, wenn ein Anruf gestartet wird" - }, - "unlimited_conversation_pinning": { - "name": "Unbegrenztes Anpinnen von Konversationen", - "description": "Ermöglicht das lokale Anpinnen einer unbegrenzten Anzahl von Konversationen" - }, - "disable_snap_mode_restrictions": { - "name": "Snap-Modus-Einschränkungen deaktivieren", - "description": "Ermöglicht das Anzeigen von selbstzerstörenden Snaps ohne Einschränkungen" + "name": "Replay in FF deaktivieren", + "description": "Deaktiviert die Möglichkeit, mit einem langen Drücken vom Freundes-Feed zu wiederholen" }, "prevent_message_sending": { "name": "Nachrichtenversand verhindern", - "description": "Verhindert das Senden bestimmter Nachrichtentypen" - }, - "friend_mutation_notifier": { - "name": "Freundes-Mutations-Benachrichtiger", - "description": "Benachrichtigt Sie, wenn sich etwas im Profil eines Freundes ändert" + "description": "Verhindert das Versenden bestimmter Nachrichten" }, "better_notifications": { "name": "Bessere Benachrichtigungen", - "description": "Fügt empfangenen Benachrichtigungen weitere Informationen hinzu", + "description": "Zeige weitere Informationen in Benachrichtigungen an", "properties": { - "group_notifications": { - "name": "Gruppenbenachrichtigungen", - "description": "Gruppiert Benachrichtigungen in einer einzigen" - }, "chat_preview": { "name": "Chat-Vorschau", "description": "Zeigt eine Vorschau der empfangenen Nachrichten in der Benachrichtigung an" }, + "reply_button": { + "name": "Antwortknopf", + "description": "Fügt der Benachrichtigung eine Antwortschaltfläche hinzu" + }, + "group_notifications": { + "name": "Gruppenbenachrichtigungen", + "description": "Gruppieren Sie Benachrichtigungen zu einer einzigen" + }, "media_preview": { "name": "Medienvorschau", "description": "Zeigt eine Vorschau der ausgewählten Medientypen in der Benachrichtigung an" }, "media_caption": { - "name": "Medienüberschrift", - "description": "Zeigt die angehängte Überschrift von Medien in der Benachrichtigung an" + "name": "Medienuntertitel", + "description": "Zeigt die angehängte Bildunterschrift der Medien in der Benachrichtigung an" }, "stacked_media_messages": { "name": "Gestapelte Mediennachrichten", - "description": "Kombiniert mehrere Mediennachrichten in einer einzigen Textbenachrichtigung, wenn sie nicht in der Vorschau angezeigt werden können. In Kombination mit Chat-Vorschau verwenden" + "description": "Kombiniert mehrere Mediennachrichten in einer Textbenachrichtigung, wenn sie nicht in der Vorschau angezeigt werden können. In Kombination mit der Chat-Vorschau verwenden" }, "friend_add_source": { - "name": "Freund hinzufügen-Quelle", + "name": "Quelle neuer Freunde", "description": "Zeigt die Quelle einer Freundschaftsanfrage in der Benachrichtigung an" }, - "reply_button": { - "name": "Antworten-Schaltfläche", - "description": "Fügt der Benachrichtigung eine Antworten-Schaltfläche hinzu" - }, - "smart_replies": { - "name": "Intelligente Antworten", - "description": "Fügt vorgeschlagene Antworten zu Benachrichtigungen hinzu (Android 10+). In Kombination mit der Antworten-Schaltfläche verwenden" - }, "download_button": { - "name": "Download-Schaltfläche", + "name": "Download-Button", "description": "Ermöglicht das Herunterladen von Medien aus der Benachrichtigung" }, "mark_as_read_button": { - "name": "Als gelesen markieren-Schaltfläche", - "description": "Ermöglicht das Markieren einer Nachricht als gelesen aus der Benachrichtigung" + "name": "Schaltfläche „Als gelesen markieren“", + "description": "Ermöglicht es dir, eine Nachricht aus der Benachrichtigung als gelesen zu markieren" }, "mark_as_read_and_save_in_chat": { "name": "Als gelesen markieren und im Chat speichern", "description": "Fügt der Benachrichtigung eine Schaltfläche „Als gelesen markieren und im Chat speichern“ hinzu" + }, + "smart_replies": { + "description": "Fügt empfohlene Antworten zu Benachrichtigungen hinzu (Android 10+). In Kombination mit Antworten Knopf zu verwenden", + "name": "Smarte Antworten" } } }, "notification_blacklist": { - "name": "Benachrichtigungs-Blacklist", - "description": "Wählen Sie aus, welche Benachrichtigungen blockiert werden sollen" + "name": "Benachrichtigungs Blacklist", + "description": "Wählen Sie Benachrichtigungen aus, die blockiert werden sollen" }, "message_logger": { - "name": "Nachrichten-Logger", - "description": "Verhindert das Löschen von Nachrichten", + "name": "Nachrichten Logger", + "description": "Verhindert, dass Nachrichten gelöscht werden", "properties": { - "keep_my_own_messages": { - "name": "Meine eigenen Nachrichten behalten", - "description": "Verhindert, dass Ihre eigenen Nachrichten gelöscht werden" - }, - "auto_purge": { - "name": "Automatisches Löschen", - "description": "Löscht zwischengespeicherte Nachrichten automatisch, die älter als die angegebene Zeit sind" - }, "message_filter": { "name": "Nachrichtenfilter", - "description": "Wählen Sie aus, welche Nachrichten protokolliert werden sollen (leer für alle Nachrichten)" + "description": "Wählen Sie aus, welche Nachrichten behalten werden sollen (leer für alle Nachrichten)" + }, + "auto_purge": { + "description": "Löscht automatisch zwischengespeicherte Nachrichten, die älter als die angegebene Zeit sind", + "name": "Automatische Bereinigung" + }, + "keep_my_own_messages": { + "name": "Eigene Nachrichten behalten", + "description": "Verhindert, dass Ihre eigenen Nachrichten gelöscht werden" }, "deleted_message_color": { - "name": "Farbe gelöschter Nachrichten", - "description": "Legt die Farbe gelöschter Nachrichten fest" + "name": "Gelöschte Nachrichten Farbe", + "description": "Setzt die Farbe von gelöschten Nachrichten" } } }, "auto_save_messages_in_conversations": { - "name": "Nachrichten automatisch speichern", - "description": "Speichert jede Nachricht in Konversationen automatisch" + "name": "Automatisches Speichern von Nachrichten", + "description": "Speichert automatisch jede Nachricht in Unterhaltungen" }, "gallery_media_send_override": { - "name": "Galerie-Medienversand überschreiben", - "description": "Fälscht die Medienquelle beim Senden aus der Galerie" + "name": "Galerie-Medien senden Überschreiben", + "description": "Fälscht die Medienquelle, wenn etwas von der Galerie gesendet wird" + }, + "bypass_screenshot_detection": { + "description": "Verhindert, dass Snapchat erkennt, wenn du einen Screenshot machst", + "name": "Umgehen der Screenshot-Erkennung" + }, + "half_swipe_notifier": { + "name": "Über Half-Swipes informieren", + "description": "Benachrichtigt Sie, wenn jemand halb in ihren Chat swiped", + "properties": { + "min_duration": { + "name": "Mindestdauer", + "description": "Die Mindestdauer der halben Swipes (in Sekunden)" + }, + "max_duration": { + "description": "Die maximale Dauer des halben Swipes (in Sekunden)", + "name": "Maximale Dauer" + } + } + }, + "prevent_story_rewatch_indicator": { + "name": "Wiederholungs-Indikator bei Stories verhindern", + "description": "Verhindert, dass andere wissen, dass Sie ihre Story noch einmal angeschaut haben" + }, + "hide_peek_a_peek": { + "description": "Verhindert, dass eine Benachrichtigung gesendet wird, wenn Sie halb in einen Chat swipen", + "name": "Vorschau Benachrichtigung verhindern" }, "strip_media_metadata": { - "name": "Medien-Metadaten entfernen", - "description": "Entfernt Metadaten von Medien vor dem Senden als Nachricht" + "description": "Entfernt Metadaten von Medien vor dem Versand als Nachricht", + "name": "Medien-Metadaten entfernen" }, "bypass_message_retention_policy": { - "name": "Nachrichtenaufbewahrungsrichtlinie umgehen", - "description": "Verhindert das Löschen von Nachrichten nach dem Anzeigen" + "name": "Umgehung der Richtlinie zur Aufbewahrung von Nachrichten", + "description": "Verhindert, dass Nachrichten nach dem Anzeigen gelöscht werden" + }, + "call_start_confirmation": { + "name": "Bestätigung des Starts eines Anrufs", + "description": "Zeigt einen Bestätigungsdialog beim Starten eines Anrufs an" + }, + "loop_media_playback": { + "name": "Medien Wiedergabe Wiederholen", + "description": "Wiederholt Snaps & Stories beim ansehen in einer Schleife" }, "bypass_message_action_restrictions": { - "name": "Nachrichtenaktionseinschränkungen umgehen", - "description": "Ermöglicht es Ihnen, auf einen Snap zu reagieren, ohne ihn geöffnet zu haben, oder eine nicht speicherbare Nachricht zu speichern" + "description": "Ermöglicht es Ihnen, auf einen Snap zu reagieren, ohne ihn geöffnet zu haben, oder eine nicht speicherbare Nachricht zu speichern", + "name": "Umgehung von Nachrichtenaktionsbeschränkungen" }, "remove_groups_locked_status": { - "name": "Status gesperrter Gruppen entfernen", - "description": "Ermöglicht das Anzeigen von Gruppeninformationen nach dem Rauswurf" + "name": "Entfernen des Gruppen-Sperrstatus", + "description": "Ermöglicht es Ihnen, nach dem Rauswurf Gruppeninformationen anzuzeigen" + }, + "auto_mark_as_read": { + "name": "Automatisch als gelesen markieren", + "description": "Markiert Nachrichten bzw. Snaps automatisch als gelesen wenn der Stealth Mode aktiviert ist" + }, + "friend_mutation_notifier": { + "name": "Freund:innen-Änderungsbenachrichigung", + "description": "Benachrichtigt Sie, wenn sich etwas im Profil eines Freundes ändert" + }, + "unlimited_conversation_pinning": { + "name": "Unlimitiertes Anpinnen von Konversationen", + "description": "Erlaubt dir eine unlimitierte Anzahl von Konversationen lokal anzupinnen" + }, + "skip_when_marking_as_seen": { + "name": "Überspringen wenn als gelesen markiert", + "description": "Springt automatisch zum nächsten Snap, wenn ein Snap als gelesen markiert wird\nIn Kombination mit Snap als gelesen markieren Knopf verwenden" + }, + "mark_snap_as_seen_button": { + "name": "Snap als gelesen markieren Knopf", + "description": "Fügt einen Knopf hinzu, um einen Snap als gelesen zu markieren, wenn er angeschaut wurde.\nDas funktioniert sogar wenn Stealth Modus aktiviert ist" }, "double_tap_chat_action": { - "name": "Doppeltipp-Chat-Aktion", - "description": "Führt eine benutzerdefinierte Aktion aus, wenn Sie im Chat auf eine Nachricht doppeltippen" - }, - "double_tap_chat_action_custom_emoji": { - "name": "Benutzerdefinierte Emoji-Reaktion auf Doppeltipp-Chat-Aktion", - "description": "Legt eine benutzerdefinierte Emoji-Reaktion für die Doppeltipp-Chat-Aktion fest" + "name": "Doppelt Tippen Chat Aktion" } } }, @@ -1076,133 +691,125 @@ "name": "Global", "description": "Globale Snapchat-Einstellungen anpassen", "properties": { - "better_location": { - "name": "Besserer Standort", - "description": "Verbessert den Snapchat-Standort", - "properties": { - "spoof_location": { - "name": "Standort fälschen", - "description": "Fälscht Ihren Standort auf einen bestimmten" - }, - "coordinates": { - "name": "Koordinaten", - "description": "Legen Sie die Koordinaten des gefälschten Standorts fest" - }, - "walk_radius": { - "name": "Gehradius", - "description": "Zufällig in diesem Radius herumlaufen (Fuß)" - }, - "always_update_location": { - "name": "Standort immer aktualisieren", - "description": "Zwingt Snapchat, den Standort zu aktualisieren, auch wenn keine GPS-Daten empfangen werden" - }, - "suspend_location_updates": { - "name": "Standortaktualisierungen aussetzen", - "description": "Verhindert, dass Ihr Standort aktualisiert wird" - }, - "spoof_battery_level": { - "name": "Akkustand fälschen", - "description": "Fälscht den Akkustand Ihres Geräts auf der Karte\nDer Wert muss zwischen 0 und 100 liegen" - }, - "spoof_headphones": { - "name": "Kopfhörer fälschen", - "description": "Fälscht den Status des Musikhörens auf der Karte" - }, - "show_battery_level": { - "name": "Akkustand anzeigen", - "description": "Zeigt den Akkustand Ihrer Freunde auf der Karte an" - } - } - }, "snapchat_plus": { "name": "Snapchat Plus", - "description": "Aktiviert Snapchat Plus-Funktionen\nEinige serverseitige Funktionen funktionieren möglicherweise nicht" - }, - "media_upload_quality": { - "name": "Medien-Upload-Qualität", - "description": "Überschreibt die Medien-Upload-Qualität", - "properties": { - "force_video_upload_source_quality": { - "name": "Video-Upload-Quellqualität erzwingen", - "description": "Zwingt Snapchat, die Quellqualität beim Hochladen von Videos zu verwenden\nBitte beachten Sie, dass dadurch möglicherweise keine Metadaten aus den Medien entfernt werden" - }, - "disable_image_compression": { - "name": "Bildkomprimierung deaktivieren", - "description": "Deaktiviert die Bildkomprimierung beim Hochladen von Medien" - }, - "custom_image_upload_format": { - "name": "Benutzerdefiniertes Bild-Upload-Format", - "description": "Legt ein benutzerdefiniertes Bild-Upload-Format fest\nWählen Sie für die beste Qualität ein verlustfreies Format (wie PNG)" - } - } - }, - "disable_confirmation_dialogs": { - "name": "Bestätigungsdialoge deaktivieren", - "description": "Bestätigt ausgewählte Aktionen automatisch" + "description": "Aktiviert Snapchat Plus Funktionen\nEinige serverseitige Funktionen funktionieren möglicherweise nicht" }, "auto_updater": { - "name": "Automatischer Updater", - "description": "Sucht automatisch nach neuen Updates" + "name": "Automatische Aktualisierung", + "description": "Automatisch auf Updates prüfen" }, "disable_metrics": { "name": "Metriken deaktivieren", - "description": "Blockiert das Senden spezifischer Analysedaten an Snapchat" - }, - "disable_story_sections": { - "name": "Story-Abschnitte deaktivieren", - "description": "Entfernt Abschnitte von der Storys-Seite\nErfordert möglicherweise eine Aktualisierung, um ordnungsgemäß zu funktionieren" + "description": "Verhindert das Senden von analytischen Daten an Snapchat" }, "block_ads": { - "name": "Anzeigen blockieren", + "name": "Werbung blockieren", "description": "Verhindert die Anzeige von Werbung" }, - "disable_custom_tabs": { - "name": "Benutzerdefinierte Tabs deaktivieren", - "description": "Öffnet Links in unterstützten Anwendungen anstatt im Webbrowser" + "bypass_video_length_restriction": { + "name": "Umgeht Videolängenbeschränkungen", + "description": "Einzel: sendet ein einzelnes Video\nSplitt: Videos nach Bearbeitung aufteilen" + }, + "disable_google_play_dialogs": { + "name": "Google Play-Service Dialog deaktivieren", + "description": "Verfügbarkeitsdialog für Google Play Services nicht anzeigen" + }, + "disable_snap_splitting": { + "name": "Snap-Aufteilung deaktivieren", + "description": "Verhindert, dass Snaps in mehrere Teile aufgeteilt werden\nBilder werden in Videos umgewandelt" + }, + "disable_confirmation_dialogs": { + "name": "Bestätigungsdialoge deaktivieren", + "description": "Bestätigt automatisch ausgewählte Aktionen" + }, + "spotlight_comments_username": { + "name": "Spotlight Kommentare Benutzername", + "description": "Zeigt den Benutzernamen des Autors in Spotlight-Kommentaren an" + }, + "disable_story_sections": { + "name": "Story Sektion deaktivieren", + "description": "Entfernt Sektionen von der Story-Seite\nErfordert möglicherweise eine Aktualisierung, um richtig zu funktionieren" + }, + "better_location": { + "name": "Snapmap Plus", + "description": "Verbessert die Snapmap", + "properties": { + "spoof_location": { + "name": "Standort simulieren", + "description": "Ändert deinen Standort auf einen bestimmten Ort" + }, + "coordinates": { + "name": "Koordinaten", + "description": "Setze Koordinaten, deren Ort simuliert werden soll" + }, + "always_update_location": { + "name": "Dauerhafte Standort-Updates", + "description": "Zwingt Snapchat dazu, die den falschen Standort beizubehalten, auch wenn es kein GPS Signal erhält" + }, + "spoof_battery_level": { + "name": "­Akkuladung simulieren", + "description": "Simuliert einen falschen Akkustand auf der Snapmap\nDer Wert sollte zwischen 0% und 100% liegen" + }, + "spoof_headphones": { + "name": "Kopfhörer", + "description": "Simuliert auf der Snapmap, dass du gerade Musik hörst" + }, + "suspend_location_updates": { + "name": "Button zum Deaktivieren", + "description": "Fügt in den Karteneinstellungen einen Knopf hinzu, um Standortaktualisierungen zu pausieren" + }, + "walk_radius": { + "name": "Radius", + "description": "Laufe zufälligerweise in diesem Radius (ft) herum" + } + } + }, + "default_volume_controls": { + "name": "Standard Lautstärkekontrolle", + "description": "Zwinge Snapchat die Systemlautstärke zu nutzen" + }, + "disable_memories_snap_feed": { + "name": "Memories Snap Feed deaktivieren", + "description": "Verhindert, dass Snapchat aktuelle Erinnerungen anzeigt, wenn Sie in der Kamera nach oben wischen" }, "disable_permission_requests": { "name": "Berechtigungsanfragen deaktivieren", "description": "Verhindert, dass Snapchat nach bestimmten Berechtigungen fragt" }, - "disable_memories_snap_feed": { - "name": "Erinnerungen-Snap-Feed deaktivieren", - "description": "Verhindert, dass Snapchat aktuelle Erinnerungen anzeigt, wenn Sie in der Kamera nach oben wischen" - }, - "spotlight_comments_username": { - "name": "Spotlight-Kommentare-Benutzername", - "description": "Zeigt den Benutzernamen des Autors in Spotlight-Kommentaren an" - }, - "bypass_video_length_restriction": { - "name": "Videolängenbeschränkung umgehen", - "description": "Einzeln: sendet ein einzelnes Video\nGeteilt: teilt Videos nach der Bearbeitung" - }, "default_video_playback_rate": { - "name": "Standard-Video-Wiedergabegeschwindigkeit", - "description": "Legt die Standardgeschwindigkeit für die Wiedergabe von Videos fest\nDer Wert muss zwischen 0,1 und 4,0 liegen" + "name": "Standardmäßige Videowiedergaberate", + "description": "Legt die Standardgeschwindigkeit für die Wiedergabe von Videos fest\n\tDer Wert muss zwischen 0,1 und 4,0 liegen" }, "video_playback_rate_slider": { - "name": "Video-Wiedergabegeschwindigkeit-Schieberegler", - "description": "Fügt einen Schieberegler im Opera-Kontextmenü hinzu, um die Video-Wiedergabegeschwindigkeit zu ändern\nHinweis: Änderungen gelten nur für nachfolgende Videos" - }, - "disable_google_play_dialogs": { - "name": "Google Play Services-Dialoge deaktivieren", - "description": "Verhindern, dass Dialoge zur Verfügbarkeit von Google Play Services angezeigt werden" - }, - "default_volume_controls": { - "name": "Standard-Lautstärkeregler", - "description": "Zwingt Snapchat, die System-Lautstärkeregler zu verwenden" - }, - "disable_telecom_framework": { - "name": "Telekom-Framework deaktivieren", - "description": "Verhindert, dass Snapchat das Android-Telekom-Framework verwendet\nDies ermöglicht es Ihnen, während eines Anrufs Musik zu hören" + "name": "Schieberegler für die Videowiedergaberate", + "description": "Fügt einen Schieberegler im Opera-Kontextmenü hinzu, um die Videowiedergabegeschwindigkeit zu ändern\nHinweis: Änderungen gelten nur für nachfolgende Videos" }, "hide_active_music": { "name": "Aktive Musik ausblenden", - "description": "Verhindert, dass Snapchat weiß, dass Sie Musik hören\nDies ermöglicht es Ihnen, Snaps mit den Lautstärkereglern aufzunehmen, während Sie Musik hören" + "description": "Verhindert, dass Snapchat erkennt, dass Sie Musik hören.\nSo können Sie mithilfe der Lautstärketasten Snaps aufnehmen, während Sie Musik hören" }, - "disable_snap_splitting": { - "name": "Snap-Teilung deaktivieren", - "description": "Verhindert, dass Snaps in mehrere Teile geteilt werden\nBilder, die Sie senden, werden zu Videos" + "media_upload_quality": { + "properties": { + "disable_image_compression": { + "name": "Deaktiviert Bildkompression", + "description": "Deaktiviert Bildkompression, wenn Medien hochgeladen werden" + }, + "custom_image_upload_format": { + "description": "Setzt ein benutzerdefiniertes Bildhochladformat\nWähle ein verlustfreies Format (wie PNG) für die beste Qualität", + "name": "Benutzerdefiniertes Bild-Upload-Format" + }, + "force_video_upload_source_quality": { + "name": "Erzwingen Sie die Qualität der Video-Upload-Quelle", + "description": "Erzwing Snapchat die Quellenqualität zu nutzen, wenn Videos hochgelden werden\nBitte merke, dass dies eventuell die Metadaten von Medien nicht entfernt" + } + }, + "name": "Qualität", + "description": "Überschreibt die Medienuploadqualität" + }, + "disable_custom_tabs": { + "name": "Deaktivieren Sie benutzerdefinierte Registerkarten", + "description": "Öffnet Links in unterstützen Applikationen, anstatt dem Webbrowser" } } }, @@ -1212,57 +819,53 @@ }, "camera": { "name": "Kamera", - "description": "Passen Sie die richtigen Einstellungen für den perfekten Snap an", + "description": "Pass die richtigen Einstellungen für den perfekten Snap an", "properties": { - "disable_cameras": { - "name": "Kameras deaktivieren", - "description": "Verhindert, dass Snapchat die ausgewählten Kameras verwendet" - }, - "black_photos": { - "name": "Schwarze Fotos", - "description": "Ersetzt aufgenommene Fotos durch einen schwarzen Hintergrund\nVideos sind nicht betroffen" - }, "immersive_camera_preview": { "name": "Immersive Vorschau", - "description": "Verhindert, dass Snapchat die Kameravorschau zuschneidet\nDies kann dazu führen, dass die Kamera auf einigen Geräten flackert" + "description": "Verhindert das Beschneiden der Kameravorschau\nDas kann dazu führen, dass die Kamera auf einigen Geräten flickert" + }, + "force_camera_source_encoding": { + "name": "Kodierung der Kameraquelle erzwingen", + "description": "Erzwingt die Kodierung der Kameraquelle" + }, + "hevc_recording": { + "name": "HEVC Aufnahme", + "description": "Verwendet HEVC (H.265) Codec für die Videoaufzeichnung" + }, + "black_photos": { + "description": "Ersetzt die aufgenommenen Fotos durch einen schwarzen Hintergrund\nVideos sind davon nicht betroffen", + "name": "Schwarze Fotos" }, "override_front_resolution": { - "name": "Vordere Auflösung überschreiben", - "description": "Überschreibt die Kameraauflösung für die vordere Kamera" + "name": "Überschreiben der Frontauflösung", + "description": "Überschreibt die Kameraauflösung für die Selfie-Kamera" }, "override_back_resolution": { - "name": "Hintere Auflösung überschreiben", - "description": "Überschreibt die Kameraauflösung für die hintere Kamera" + "name": "Hauptkamera Auflösung überschreiben", + "description": "Überschreibt die Kameraauflösung der Hauptkamera" }, "custom_resolution": { "name": "Benutzerdefinierte Auflösung", - "description": "Legt eine benutzerdefinierte Kameraauflösung fest, Breite x Höhe (z. B. 1920x1080).\nDie benutzerdefinierte Auflösung muss von Ihrem Gerät unterstützt werden" + "description": "Legt eine benutzerdefinierte Kameraauflösung (Breite x Höhe) fest (z. B. 1920x1080).\nDie benutzerdefinierte Auflösung muss von Ihrem Gerät unterstützt werden" + }, + "disable_cameras": { + "name": "Kameras deaktivieren", + "description": "Verhindert, dass Snapchat die gewählten Kameras nutzt" }, "front_custom_frame_rate": { - "name": "Vordere benutzerdefinierte Bildrate", - "description": "Überschreibt die Bildrate der vorderen Kamera" + "name": "Benutzerdefinierte Frame-Rate Selfie-Kamera", + "description": "Überschreibt die Frame-Rate der Selfie-Kamera" }, "back_custom_frame_rate": { - "name": "Hintere benutzerdefinierte Bildrate", - "description": "Überschreibt die Bildrate der hinteren Kamera" - }, - "force_camera_source_encoding": { - "name": "Kameraquellenkodierung erzwingen", - "description": "Erzwingt die Kameraquellenkodierung" - }, - "startup_default_camera": { - "name": "Standardkamera beim Start", - "description": "Legt die Standardkamera beim Öffnen von Snapchat fest" - }, - "hevc_recording": { - "name": "HEVC-Aufnahme", - "description": "Verwendet den HEVC (H.265)-Codec für die Videoaufnahme" + "description": "Überschreibt die Frame-Rate der Haupt-Kamera", + "name": "Benutzerdefinierte Frame-Rate Haupt-Kamera" } } }, "streaks_reminder": { - "name": "Streak-Erinnerung", - "description": "Benachrichtigt Sie regelmäßig über Ihre Streaks", + "name": "Flammen-Erinnerung", + "description": "Benachrichtigt dich regelmäßig über deine Flammen", "properties": { "interval": { "name": "Intervall", @@ -1270,11 +873,11 @@ }, "remaining_hours": { "name": "Verbleibende Zeit", - "description": "Die verbleibende Zeit, bevor die Benachrichtigung angezeigt wird (Stunden)" + "description": "Die verbleibende Zeit, bevor die Benachrichtigung angezeigt wird (in Stunden)" }, "group_notifications": { - "name": "Gruppenbenachrichtigungen", - "description": "Gruppiert Benachrichtigungen in einer einzigen" + "name": "Gruppierte Benachrichtigungen", + "description": "Benachrichtigungen in eine einzelne gruppieren" } } }, @@ -1284,235 +887,185 @@ "properties": { "native_hooks": { "name": "Native Hooks", - "description": "Unsichere Funktionen, die in den nativen Code von Snapchat eingreifen", + "description": "Unsichere Funktionen, welche sich in Snapchats nativen Code einhängen", "properties": { + "disable_bitmoji": { + "name": "Bitmojis deaktivieren", + "description": "Deaktiviert das Bitmoji des Freund:innenprofil" + }, "composer_hooks": { - "name": "Composer-Hooks", - "description": "Injiziert Code in das plattformübergreifende UI-Framework von Composer", "properties": { - "show_first_created_username": { - "name": "Ersten erstellten Benutzernamen anzeigen", - "description": "Zeigt den ersten erstellten Benutzernamen neben dem aktuellen Benutzernamen auf der Profilseite an" - }, "bypass_camera_roll_limit": { - "name": "Kamerarollenlimit umgehen", + "name": "Umgeht das Kamerarollenlimit", "description": "Erhöht die maximale Anzahl von Medien, die Sie aus der Kamerarolle senden können" }, - "custom_self_destruct_snap_delay": { - "name": "Benutzerdefinierte Selbstzerstörungs-Snap-Verzögerung", - "description": "Bietet mehr Optionen für den Selbstzerstörungs-Timer beim Senden eines Snaps" - }, "composer_console": { "name": "Composer-Konsole", - "description": "Ermöglicht die Ausführung von JavaScript-Code in Composer (nur arm64)" + "description": "Ermöglicht das Ausführen von JavaScript-Code in Composer (nur arm64)" }, "composer_logs": { "name": "Composer-Protokolle", - "description": "Leitet Konsolenprotokolle von Composer an PurrfectSnap um" + "description": "Leitet Konsolenprotokolle von Composer zu SnapEnhance um" + }, + "show_first_created_username": { + "name": "Zeige erstgewählten Benutzernamen", + "description": "Zeige den erstgewählten Benutzernamen neben dem jetzigen Benutzernamen in der Profileseite" } - } - }, - "disable_bitmoji": { - "name": "Bitmoji deaktivieren", - "description": "Deaktiviert das Bitmoji des Freundesprofils" - }, - "custom_emoji_font": { - "name": "Benutzerdefinierte Emoji-Schriftart", - "description": "Ermöglicht die Verwendung einer benutzerdefinierten Emoji-Schriftart. Funktioniert nur mit .ttf-Schriftarten" - }, - "custom_shared_library": { - "name": "Benutzerdefinierte freigegebene Bibliothek", - "description": "Lädt eine benutzerdefinierte freigegebene Bibliothek in Snapchat. Diese Funktion dient nur zu Testzwecken" + }, + "name": "Composer Haken", + "description": "Injiziert Code in das Composer UI-Framework (nur arm64)" } } }, "spoof": { - "name": "Fälschen", - "description": "Fälschen Sie verschiedene Informationen über sich", + "name": "Simulieren", + "description": "Verschiedene Informationen über dich vortäuschen", "properties": { - "play_store_installer_package_name": { - "name": "Paketname des Play Store-Installers", - "description": "Überschreibt den Paketnamen des Installers auf com.android.vending" + "remove_mock_location_flag": { + "name": "Kennzeichnung für den gefälschten Standort entfernen", + "description": "Verhindert, dass Snapchat gefälschte Standorte erkennt" }, "remove_vpn_transport_flag": { - "name": "VPN-Transport-Flag entfernen", - "description": "Verhindert, dass Snapchat VPNs erkennt" + "description": "Hindert Snapchat daran, VPNs zu erkennen", + "name": "VPN-Transport-Flagge entfernen" }, - "remove_mock_location_flag": { - "name": "Mock-Standort-Flag entfernen", - "description": "Verhindert, dass Snapchat den Mock-Standort erkennt" - } - } - }, - "convert_message_locally": { - "name": "Nachricht lokal konvertieren", - "description": "Konvertiert Snaps lokal in externe Chat-Medien. Dies wird im Chat-Download-Kontextmenü angezeigt" - }, - "media_file_picker": { - "name": "Medien-Dateiauswahl", - "description": "Ermöglicht die Auswahl einer beliebigen Video-/Audiodatei aus der Galerie" - }, - "story_logger": { - "name": "Story-Logger", - "description": "Bietet einen Verlauf der Storys von Freunden" - }, - "call_recorder": { - "name": "Anrufrekorder", - "description": "Nimmt Sprachanrufe automatisch auf" - }, - "account_switcher": { - "name": "Kontowechsler", - "description": "Ermöglicht den Wechsel zwischen Konten, ohne sich abzumelden\nDrücken Sie lange auf das Suchsymbol neben Ihrem Bitmoji-Profil, um das Menü zu öffnen\nHinweis: Diese Funktion ist experimentell und wird sich in Zukunft wahrscheinlich ändern", - "properties": { - "auto_backup_current_account": { - "name": "Aktuelles Konto automatisch sichern", - "description": "Sichert das aktuelle Konto automatisch beim Abmelden oder Wechseln des Kontos" - } - } - }, - "better_transcript": { - "name": "Besseres Transkript", - "description": "Verbessert das Transkript von Sprachnotizen", - "properties": { - "force_transcription": { - "name": "Transkription von Sprachnotizen erzwingen", - "description": "Ermöglicht die Transkription aller Sprachnotizen" - }, - "preferred_transcription_lang": { - "name": "Bevorzugte Transkriptionssprache", - "description": "Die bevorzugte Sprache für das Transkript von Sprachnotizen (z. B. EN, ES, FR)" - }, - "notification_transcript": { - "name": "Benachrichtigungstranskript", - "description": "Transkribiert Sprachnotizen in Benachrichtigungen\nDiese Funktion erfordert, dass die Chat-Vorschau-Funktion in „Bessere Benachrichtigungen“ aktiviert ist" - } - } - }, - "voice_note_auto_play": { - "name": "Automatische Wiedergabe von Sprachnotizen", - "description": "Spielt die nächste Sprachnotiz automatisch ab, nachdem die aktuelle beendet ist" - }, - "friend_notes": { - "name": "Freundesnotizen", - "description": "Ermöglicht das Hinzufügen von Notizen zu Freundesprofilen" - }, - "cof_experiments": { - "name": "COF-Experimente", - "description": "Aktiviert unveröffentlichte/Beta-Funktionen von Snapchat" - }, - "context_menu_fix": { - "name": "Kontextmenü-Fix", - "description": "Versuch, das Freundes-Feed-Menü zu reparieren, da es nicht korrekt angezeigt werden kann, wenn das Gerät offline ist" - }, - "app_lock": { - "name": "App-Sperre", - "description": "Verhindert den Zugriff auf Snapchat ohne Passcode", - "properties": { - "lock_on_resume": { - "name": "Bei Wiederaufnahme sperren", - "description": "Sperrt die App, wenn sie erneut geöffnet wird" + "play_store_installer_package_name": { + "description": "Überschreibt den Namen des Installationspakets auf com.android.vending_machine", + "name": "Goolge Play Installationsname des Paketes" } } }, "infinite_story_boost": { - "name": "Unendlicher Story-Boost", - "description": "Story-Boost-Limit-Verzögerung umgehen" + "name": "Unendlicher Story Boost", + "description": "Story Boost Limit Verzögerung umgehen" }, "meo_passcode_bypass": { - "name": "My Eyes Only-Passcode umgehen", - "description": "My Eyes Only-Passcode umgehen\nDies funktioniert nur, wenn der Passcode zuvor korrekt eingegeben wurde" + "name": "Passwortumgehung für privaten Bereich", + "description": "Umgeht das Passwort für den privaten Bereich\nFunktioniert nur, wenn das korrekte Passwort schon einmal eingegeben wurde" }, "no_friend_score_delay": { - "name": "Keine Freundes-Score-Verzögerung", - "description": "Entfernt die Verzögerung beim Anzeigen des Freundes-Scores" - }, - "best_friend_pinning": { - "name": "Bester Freund anpinnen", - "description": "Ermöglicht das Anpinnen eines Freundes als Ihren besten Freund Nummer eins. Hinweis: Nur Sie können Ihren angepinnten besten Freund sehen" + "name": "Keine Friend Score Verzögerung", + "description": "Entfernt die Verzögerung beim Betrachten einer Friends Score" }, "e2ee": { "name": "Ende-zu-Ende-Verschlüsselung", - "description": "Verschlüsselt Ihre Nachrichten mit AES unter Verwendung eines gemeinsamen geheimen Schlüssels\nStellen Sie sicher, dass Sie Ihren Schlüssel an einem sicheren Ort aufbewahren!", + "description": "Verschlüsselt deine Nachrichten mit AES unter Verwendung eines freigegebenen geheimen Schlüssels\nAchte darauf, dass du deinen Schlüssel an einem sicheren Ort aufbewahrst!", "properties": { "encrypted_message_indicator": { - "name": "Indikator für verschlüsselte Nachrichten", - "description": "Fügt ein 🔒-Emoji neben verschlüsselten Nachrichten hinzu" + "name": "Anzeige für verschlüsselte Nachrichten", + "description": "Fügt einen 🔒 Emoji neben verschlüsselten Nachrichten hinzu" }, "force_message_encryption": { "name": "Nachrichtenverschlüsselung erzwingen", - "description": "Verhindert das Senden verschlüsselter Nachrichten an Personen, die die E2E-Verschlüsselung nicht aktiviert haben, nur wenn mehrere Konversationen ausgewählt sind" + "description": "Verhindert das Senden von verschlüsselten Nachrichten an Personen, die keine E2E-Verschlüsselung aktiviert haben, wenn mehrere Unterhaltungen ausgewählt sind" } } }, "add_friend_source_spoof": { - "name": "Freund hinzufügen-Quelle fälschen", - "description": "Fälscht die Quelle einer Freundschaftsanfrage" + "name": "Freundesquellen-Änderung hinzufügen", + "description": "Verfälscht die Quelle einer Freundschaftsanfrage" }, "hidden_snapchat_plus_features": { - "name": "Versteckte Snapchat Plus-Funktionen", - "description": "Aktiviert unveröffentlichte/Beta-Funktionen von Snapchat Plus\nFunktioniert möglicherweise nicht auf älteren Snapchat-Versionen" - }, - "custom_streaks_expiration_format": { - "name": "Benutzerdefiniertes Streak-Ablaufformat", - "description": "Passt das Streak-Ablaufformat an\n\nVerfügbare Variablen:\n - %c: Streak-Anzahl\n - %e: Sanduhr-Emoji\n - %d: Tage\n - %h: Stunden\n - %m: Minuten\n - %s: Sekunden\n - %w: Verbleibende Zeit" + "name": "Verborgene Snapchat Plus-Funktionen", + "description": "Aktiviert unveröffentlichte/beta Snapchat Plus Funktionen\nKönnte auf älteren Snapchat-Versionen nicht funktionieren" }, "prevent_forced_logout": { - "name": "Erzwungenes Abmelden verhindern", - "description": "Verhindert, dass Snapchat Sie abmeldet, wenn Sie sich auf einem anderen Gerät anmelden" + "name": "Erzwungenen Logout verhindern", + "description": "Verhindert, dass Snapchat dich abmeldet, wenn du dich auf einem anderen Gerät anmeldest" }, - "snapscore_changes": { - "name": "Snapscore-Änderungen", - "description": "Verfolgt Änderungen im Snapscore von Freunden\nVerwenden Sie diese Funktion nur in neueren Versionen von Snapchat" + "convert_message_locally": { + "description": "Konvertiert Snaps lokal in externe Chat-Medien. Dies erscheint im Kontextmenü für den Chat-Download", + "name": "Nachricht lokal umwandeln" + }, + "story_logger": { + "description": "Liefert eine Historie der Stories von Freund:innen", + "name": "Geschichtenprotokollierer" + }, + "call_recorder": { + "name": "Anrufaufzeichner", + "description": "Zeichnet automatisch Audioanrufe auf" + }, + "media_file_picker": { + "name": "Mediendatei-Auswahl", + "description": "Ermöglicht es beliebige Video und Audio Dateien von der Gallerie auszuwählen" + }, + "account_switcher": { + "name": "­Accountwechsler", + "description": "Ermöglicht es Ihnen, zwischen Konten zu wechseln, ohne sich auszuloggen\nHalten Sie lange auf das Suchsymbol neben Ihrem Bitmoji-Profil, um das Menü zu öffnen\nHinweis: Diese Funktion ist experimentell und wird wahrscheinlich in Zukunft geändert", + "properties": { + "auto_backup_current_account": { + "name": "Automatisches Backup des aktuellen Accounts", + "description": "Automatisch wird das aktuelle Konto gesichert, wenn Sie sich ausloggen oder zwischen Konten wechseln" + } + } + }, + "edit_message": { + "description": "Ermöglicht es Nachrichten in Konversationen zu bearbeiten", + "name": "Nachrichten bearbeiten" + }, + "app_lock": { + "name": "App-Sperre", + "description": "Verhindert den Zugriff auf Snapchat ohne dein Passwort", + "properties": { + "lock_on_resume": { + "description": "Sperrt die App, sobald sie wieder geöffnet wird", + "name": "Sperren beim Fortsetzen" + } + } + }, + "custom_streaks_expiration_format": { + "name": "Eigenes Ablaufdatum für Flammen", + "description": "Passt das Ablaufdatumformat für Flammen an\n\nVerfügbare Variablen:\n- %c: Anzahl der Serien\n- %e: Sanduhr-Emoji\n- %d: Tage\n- %h: Stunden\n- %m: Minuten\n- %s: Sekunden\n- %w: Verbleibende Zeit" + }, + "best_friend_pinning": { + "name": "Bester Freund Pinning", + "description": "Erlaubt einen Freund als besten Freund Nummer 1 anzupinnen. Notiz: Nur du kannst deinen gepinnten besten Freund sehen" } } }, "scripting": { - "name": "Skripting", - "description": "Führen Sie benutzerdefinierte Skripte aus, um PurrfectSnap zu erweitern", + "name": "Scripting", + "description": "Benutzerdefinierte Skripte ausführen, um SnapEnhance zu erweitern", "properties": { "developer_mode": { - "name": "Entwicklermodus", - "description": "Zeigt Debug-Informationen in der Benutzeroberfläche von Snapchat an" + "name": "Entwickler:innenmodus", + "description": "Zeigt Debug-Informationen auf Snapchat's UI" }, "module_folder": { "name": "Modulordner", "description": "Der Ordner, in dem sich die Skripte befinden" }, - "auto_reload": { - "name": "Automatisches Neuladen", - "description": "Lädt Skripte bei Änderungen automatisch neu" - }, "integrated_ui": { "name": "Integrierte Benutzeroberfläche", - "description": "Ermöglicht Skripten, benutzerdefinierte UI-Komponenten zu Snapchat hinzuzufügen" + "description": "Erlaubt Skripten, benutzerdefinierte UI-Komponenten zu Snapchat hinzuzufügen" }, "disable_log_anonymization": { - "name": "Protokollanonymisierung deaktivieren", - "description": "Deaktiviert die Anonymisierung von Protokollen" + "description": "Deaktiviert die Anonymisierung von Logs", + "name": "Log-Anonymisierung deaktivieren" }, - "disable_optimization": { - "name": "Optimierung deaktivieren", - "description": "Deaktiviert die Optimierung von Skripten. Dies kann zu Leistungsproblemen führen." + "auto_reload": { + "description": "Automatisches Neuladen von Skripten, wenn diese sich ändern", + "name": "Automatisches Neuladen" } } }, "friend_tracker": { - "name": "Freundes-Tracker", - "description": "Zeichnet die Aktivität von Freunden auf Snapchat auf", "properties": { + "allow_running_in_background": { + "name": "Hintergrundnutzung erlauben", + "description": "Ermöglicht die Ausführung des Trackers im Hintergrund. Hinweis: Dadurch wird Ihr Akku erheblich entladen" + }, "record_messaging_events": { - "name": "Nachrichtenereignisse aufzeichnen", + "name": "Nachrichtenevents aufzeichnen", "description": "Zeichnet Nachrichtenereignisse wie das Öffnen eines Snaps, das Lesen einer Nachricht usw. auf." }, - "allow_running_in_background": { - "name": "Im Hintergrund ausführen zulassen", - "description": "Ermöglicht dem Tracker, im Hintergrund zu laufen. Hinweis: Dies wird Ihren Akku erheblich belasten" - }, "auto_purge": { - "name": "Automatisches Löschen", - "description": "Löscht zwischengespeicherte Ereignisse automatisch, die älter als die angegebene Zeit sind" + "description": "Löscht zwischengespeicherte Ereignisse automatisch, wenn sie älter als die spezifizierte Dauer sind", + "name": "Automatisch Löschen" } - } + }, + "name": "Freundestracker", + "description": "Die Aktivität der Freunde aufzeichnen" } }, "options": { @@ -1521,339 +1074,247 @@ "always_dark": "Immer dunkel" }, "friend_feed_menu_buttons": { - "auto_download": "⬇️ Automatischer Download", - "auto_save": "💬 Nachrichten automatisch speichern", - "unsaveable_messages": "⬇️ Nicht speicherbare Nachrichten", - "auto_open_snaps": "📸 Snaps automatisch öffnen", - "stealth": "👻 Stealth-Modus", + "auto_download": "⬇️ Auto-Download", + "auto_save": "💬 Auto-Nachricht-Speichern", + "stealth": "👻 Heimlicher Modus", + "conversation_info": "👤 Gesprächsinformationen", + "e2e_encryption": "🔒 E2E-Verschlüsselung verwenden", + "mark_stories_as_seen_locally": "👀 Stories als lokal gesehen markieren", "mark_snaps_as_seen": "👀 Snaps als gesehen markieren", - "mark_stories_as_seen_locally": "👀 Storys lokal als gesehen markieren", - "conversation_info": "🧑‍🤝‍🧑 Konversationsinformationen", - "e2e_encryption": "🔒 E2E-Verschlüsselung verwenden" + "unsaveable_messages": "⬇️ Nicht speicherbare Nachrichten", + "auto_open_snaps": "📷 Automatisches Öffnen von Snaps" }, "path_format": { - "create_author_folder": "Ordner für jeden Autor erstellen", - "create_source_folder": "Ordner für jeden Medientyp erstellen", - "append_hash": "Einen eindeutigen Hash zum Dateinamen hinzufügen", - "append_source": "Die Medienquelle zum Dateinamen hinzufügen", - "append_username": "Den Benutzernamen zum Dateinamen hinzufügen", - "append_date_time": "Datum und Uhrzeit zum Dateinamen hinzufügen" + "create_author_folder": "Erzeuge ein Verzeichnis für jeden Benutzer", + "create_source_folder": "Ordner für jeden Medienquellentyp erstellen", + "append_hash": "Fügt jedem Dateinamen einen einzigartigen Hash hinzu", + "append_source": "Füge die Medienquelle zum Dateinamen hinzu", + "append_username": "Füge den Benutzernamen zum Dateinamen hinzu", + "append_date_time": "Füge Datum und Uhrzeit zum Dateinamen hinzu" }, "auto_download_sources": { - "friend_snaps": "Freundes-Snaps", - "friend_stories": "Freundes-Storys", - "public_stories": "Öffentliche Storys", - "spotlight": "Scheinwerfer" + "friend_snaps": "Freund-Snaps", + "friend_stories": "Freund-Stories", + "public_stories": "Öffentliche Stories", + "spotlight": "Spotlight" }, "logging": { "started": "Gestartet", - "success": "Erfolg", + "success": "Erfolgreich", "progress": "Fortschritt", "failure": "Fehler" }, "notifications": { "chat_screenshot": "Screenshot", "chat_screen_record": "Bildschirmaufnahme", - "snap_replay": "Snap-Wiederholung", - "camera_roll_save": "In Kamerarolle speichern", - "chat": "Chatten", - "chat_reply": "Chat-Antwort", - "snap": "Schnapp", - "typing": "Tippt", - "stories": "Storys", - "speaking": "Spricht", + "snap_replay": "Snap Wiederholung", + "camera_roll_save": "In Aufnahmen gespeichert", + "chat": "Chat", + "chat_reply": "Chat Antwort", + "snap": "Snap", + "typing": "Schreiben", + "stories": "Stories", "chat_reaction": "DM-Reaktion", "group_chat_reaction": "Gruppenreaktion", - "initiate_audio": "Eingehender Sprachanruf", - "abandon_audio": "Verpasster Sprachanruf", + "initiate_audio": "Eingehender Audioanruf", + "abandon_audio": "Verpasster Audioanruf", "initiate_video": "Eingehender Videoanruf", "abandon_video": "Verpasster Videoanruf", - "map_live_location": "Live-Standort auf der Karte" + "speaking": "Sprache" }, "gallery_media_send_override": { - "always_ask": "Immer fragen", - "ORIGINAL": "Originalmedien", - "NOTE": "Sprachnotiz", - "SNAP": "Schnapp", - "SAVEABLE_SNAP": "Speicherbarer Snap" - }, - "strip_media_metadata": { - "hide_caption_text": "Bildunterschrift ausblenden", - "hide_snap_filters": "Snap-Filter ausblenden", - "hide_extras": "Extras ausblenden (z. B. Erwähnungen)", - "remove_audio_note_duration": "Dauer der Sprachnotiz entfernen", - "remove_audio_note_transcript_capability": "Fähigkeit zur Transkription von Sprachnotizen entfernen" + "ORIGINAL": "Originale Medien", + "NOTE": "Audio-Notiz", + "SNAP": "Snap", + "always_ask": "Immer Fragen" }, "hide_ui_components": { - "hide_profile_call_buttons": "Profil-Anrufschaltflächen entfernen", - "hide_chat_call_buttons": "Chat-Anrufschaltflächen entfernen", - "hide_live_location_share_button": "Schaltfläche zum Teilen des Live-Standorts entfernen", - "hide_stickers_button": "Sticker-Schaltfläche entfernen", - "hide_voice_record_button": "Sprachaufnahmeschaltfläche entfernen", - "hide_unread_chat_hint": "Hinweis auf ungelesenen Chat entfernen", - "hide_post_to_story_buttons": "Schaltflächen zum Posten in der Story vor dem Senden eines Snaps entfernen", - "hide_billboard_prompt": "Billboard-Aufforderung im Freundes-Feed entfernen", - "hide_snapchat_plus_gift_reminders": "Snapchat Plus-Geschenkerinnerungen in Konversationen entfernen", - "hide_map_reactions": "Kartenreaktionen entfernen" - }, - "hide_story_suggestions": { - "hide_suggested_friend_stories": "Vorgeschlagene Freundes-Storys ausblenden", - "hide_my_stories": "Meine Storys ausblenden" + "hide_profile_call_buttons": "Entferne Anruf Tasten", + "hide_chat_call_buttons": "Entferne Anruf Tasten im Chat", + "hide_live_location_share_button": "Schaltfläche Live-Standortfreigabe entfernen", + "hide_stickers_button": "Entferne Stickers Taste", + "hide_voice_record_button": "Knopf für Sprachaufzeichnung entfernen", + "hide_unread_chat_hint": "Hinweis auf ungelesene Chats entfernen" }, "home_tab": { "map": "Karte", - "chat": "Chatten", + "chat": "Chat", "camera": "Kamera", "discover": "Entdecken", - "spotlight": "Scheinwerfer" + "spotlight": "Spotlight" }, "add_friend_source_spoof": { "added_by_username": "Nach Benutzername", - "added_by_mention": "Nach Erwähnung", - "added_by_group_chat": "Nach Gruppenchat", - "added_by_qr_code": "Nach QR-Code", - "added_by_community": "Nach Community", - "added_by_quick_add": "Nach Schnellhinzufügen (hohes Sperrrisiko)" + "added_by_mention": "Durch Erwähnung", + "added_by_group_chat": "Per Gruppenchat", + "added_by_qr_code": "Per QR-Code", + "added_by_community": "Per Community", + "added_by_quick_add": "Von Schnell Hinzufügen ->!!HOHES RISIKO, GEBANNT ZU WERDEN!!<-" }, "bypass_video_length_restriction": { "single": "Einzelnes Medium", - "split": "Geteiltes Medium" - }, - "old_bitmoji_selfie": { - "2d": "2D-Bitmoji", - "3d": "3D-Bitmoji" - }, - "disable_confirmation_dialogs": { - "erase_message": "Nachricht löschen", - "remove_friend": "Freund entfernen", - "block_friend": "Freund blockieren", - "ignore_friend": "Freund ignorieren", - "hide_friend": "Freund ausblenden", - "hide_conversation": "Konversation ausblenden", - "clear_conversation": "Konversation aus dem Freundes-Feed löschen" + "split": "Medien aufteilen" }, "auto_reload": { "snapchat_only": "Nur Snapchat", - "all": "Alle (Snapchat + PurrfectSnap)" + "all": "Alles (Snapchat + SnapEnhance)" }, - "edit_text_override": { - "multi_line_chat_input": "Mehrzeilige Chat-Eingabe", - "bypass_text_input_limit": "Texteingabelimit umgehen" + "strip_media_metadata": { + "remove_audio_note_duration": "Dauer der Sprachnachricht entfernen", + "remove_audio_note_transcript_capability": "Sprachnachricht-Transkriptionsfunktion entfernen", + "hide_extras": "Extras ausblenden (z. B. Erwähnungen)", + "hide_caption_text": "Bildunterschriftstext ausblenden", + "hide_snap_filters": "Snap Filter ausblenden" }, "auto_purge": { - "never": "Niemals", + "1_day": "1 Tag", + "1_week": "1 Woche", + "1_month": "1 Monat", + "2_weeks": "2 Wochen", + "never": "Nie", "1_hour": "1 Stunde", "3_hours": "3 Stunden", - "6_hours": "6 Stunden", - "12_hours": "12 Stunden", - "1_day": "1 Tag", + "6_months": "6 Monate", "3_days": "3 Tage", - "1_week": "1 Woche", - "2_weeks": "2 Wochen", - "1_month": "1 Monat", + "6_hours": "6 Stunden", "3_months": "3 Monate", - "6_months": "6 Monate" + "12_hours": "12 Stunden" + }, + "disable_confirmation_dialogs": { + "hide_conversation": "Konversation ausblenden", + "clear_conversation": "Konversation aus dem Freundes-Feed löschen", + "remove_friend": "Freund entfernen", + "hide_friend": "Freund ausblenden", + "ignore_friend": "Freund ignorieren", + "block_friend": "Freund blockieren", + "erase_message": "Nachricht löschen" + }, + "edit_text_override": { + "bypass_text_input_limit": "Umgehen des Limits für die Texteingabe", + "multi_line_chat_input": "Mehrzeiliges Chat-Eingabefeld" + }, + "old_bitmoji_selfie": { + "2d": "2D Bitmoji", + "3d": "3D Bitmoji" + }, + "hide_story_suggestions": { + "hide_suggested_friend_stories": "Empfohlene Stories von Freunden ausblenden", + "hide_my_stories": "Meine Stories verbergen" }, "disable_story_sections": { "friends": "Freunde", - "suggested_stories": "Vorgeschlagene Storys", - "following": "Folge ich", + "following": "Folge Ich", "discover": "Entdecken" }, "disable_cameras": { - "front": "Vordere Kamera", - "back": "Hintere Kamera" + "front": "Selfie Kamera", + "back": "Hauptkamera" }, "disable_permission_requests": { "notifications": "Benachrichtigungen", "read_media_images": "Medienbilder lesen", - "read_media_video": "Medienvideo lesen", "camera": "Kamera", "microphone": "Mikrofon", - "location": "Standort", + "read_media_video": "Medienvideos lesen", "read_contacts": "Kontakte lesen", - "nearby_devices": "Geräte in der Nähe", + "location": "Standort", + "nearby_devices": "In der Nähe befindliche Geräte", "phone_calls": "Telefonanrufe" }, "message_indicators": { - "encryption_indicator": "Fügt ein 🔒-Symbol neben Nachrichten hinzu, die nur an Sie gesendet wurden", - "platform_indicator": "Fügt das Plattformsymbol hinzu, von dem ein Medium gesendet wurde (z. B. Android, iOS, Web)", - "location_indicator": "Fügt ein 📍-Symbol zu Snaps hinzu, wenn sie mit aktiviertem Standort gesendet wurden", - "ovf_editor_indicator": "Gibt an, ob ein Snap mit dem OVF-Editor gesendet wurde", - "director_mode_indicator": "Fügt ein 🎬-Symbol zu Snaps hinzu, wenn sie im Regisseurmodus gesendet wurden, mit dem Galeriebilder als Snaps gesendet werden können" + "encryption_indicator": "Fügt neben Nachrichten, die nur an Sie gesendet wurden, ein 🔒-Symbol hinzu", + "location_indicator": "Fügt Snaps ein 📍-Symbol hinzu, wenn sie mit aktivierter Standortfunktion gesendet wurden", + "platform_indicator": "Fügt das Plattformsymbol hinzu, von der aus ein Medium gesendet wurde (z. B. Android, iOS, Web)", + "director_mode_indicator": "Fügt Snaps ein ✏️-Symbol hinzu, wenn sie mit dem Director-Modus gesendet wurden, der verwendet werden kann, um Galeriebilder als Snaps zu senden", + "ovf_editor_indicator": "Kennzeichnet, ob ein Snap mit dem OVF-Editor gesendet wurde" }, "auto_mark_as_read": { - "conversation_read": "Konversation als gelesen markieren, wenn eine Nachricht gesendet wird", - "snap_reply": "Snaps als gelesen markieren, wenn darauf geantwortet wird", - "save_snap_in_chat": "Snaps als gelesen markieren, wenn sie im Stealth-Modus im Chat gespeichert werden" + "conversation_read": "Markiert eine Konversation als gelesen sobald eine Narchicht gesendet wird", + "snap_reply": "Markiert Snaps als gelesen, sobald auf sie geantwortet wird" }, "friend_mutation_notifier": { - "remove_friend": "Benachrichtigen, wenn Sie jemand als Freund entfernt", - "birthday_changes": "Benachrichtigen, wenn jemand seinen Geburtstag ändert", + "remove_friend": "Benachrichtige, wenn dich jemand als Freund entfernt", + "bitmoji_avatar_changes": "Benachrichtige, wenn jemand sein Bitmoji-Avatar ändert", + "bitmoji_background_changes": "Benachrichtige, wenn jemand den Hintergrund seines Bitmoji ändert", + "birthday_changes": "Benachrichtige, wenn jemand sein Geburtsdatum ändert", "bitmoji_selfie_changes": "Benachrichtigen, wenn jemand sein Bitmoji-Selfie ändert", - "bitmoji_avatar_changes": "Benachrichtigen, wenn jemand seinen Bitmoji-Avatar ändert", - "bitmoji_background_changes": "Benachrichtigen, wenn jemand seinen Bitmoji-Hintergrund ändert", - "bitmoji_scene_changes": "Benachrichtigen, wenn jemand seine Bitmoji-Szene ändert" - }, - "snapchat_plus": { - "not_subscribed": "Nicht abonniert", - "basic": "Basic", - "ad_free": "Werbefrei" - }, - "double_tap_chat_action": { - "like_message": "Nachricht liken", - "copy_text": "Text in die Zwischenablage kopieren", - "delete_message": "Nachricht löschen", - "mark_as_read": "Als gelesen markieren", - "custom_emoji_reaction": "Benutzerdefinierte Emoji-Reaktion" - }, - "startup_default_camera": { - "front": "Vordere Kamera", - "back": "Hintere Kamera" + "bitmoji_scene_changes": "Benachrichtige, wenn jemand seine Bitmoji-Szene ändert" } } }, "friend_menu_option": { - "mark_snaps_as_seen": "Snaps als gesehen markieren", - "mark_stories_as_seen_locally": "Storys lokal als gesehen markieren", "preview": "Vorschau", - "stealth_mode": "Stealth-Modus", - "auto_download_blacklist": "Automatischer Download-Blacklist", - "anti_auto_save": "Anti-automatisches Speichern" - }, - "content_type": { - "CHAT": "Chatten", - "SNAP": "Schnapp", - "EXTERNAL_MEDIA": "Externe Medien", - "NOTE": "Sprachnotiz", - "STICKER": "Aufkleber", - "SHARE": "Teilen", - "STATUS": "Status", - "LOCATION": "Standort", - "STATUS_SAVE_TO_CAMERA_ROLL": "In Kamerarolle gespeichert", - "STATUS_CONVERSATION_CAPTURE_SCREENSHOT": "Screenshot", - "STATUS_CONVERSATION_CAPTURE_RECORD": "Bildschirmaufnahme", - "STATUS_CALL_MISSED_VIDEO": "Verpasster Videoanruf", - "STATUS_CALL_MISSED_AUDIO": "Verpasster Sprachanruf", - "LIVE_LOCATION_SHARE": "Live-Standort teilen", - "CREATIVE_TOOL_ITEM": "Kreatives Werkzeugelement", - "FAMILY_CENTER_INVITE": "Einladung zum Familienzentrum", - "FAMILY_CENTER_ACCEPT": "Familienzentrum annehmen", - "FAMILY_CENTER_LEAVE": "Familienzentrum verlassen", - "STATUS_PLUS_GIFT": "Status Plus-Geschenk", - "TINY_SNAP": "Kleiner Snap", - "STATUS_COUNTDOWN": "Countdown", - "MAP_REACTION": "Kartenreaktion" - }, - "media_download_source": { - "none": "Keine", - "pending": "Ausstehend", - "chat_media": "Chat-Medien", - "story": "Geschichte", - "public_story": "Öffentliche Story", - "spotlight": "Scheinwerfer", - "profile_picture": "Profilbild", - "story_logger": "Story-Logger", - "message_logger": "Nachrichten-Logger", - "merged": "Zusammengeführt", - "voice_call": "Sprachanruf" + "stealth_mode": "Inkognitomodus", + "auto_download_blacklist": "Blacklist für automatische Downloads", + "anti_auto_save": "Anti-Auto-Speichern", + "mark_snaps_as_seen": "Snaps als gesehen markieren", + "mark_stories_as_seen_locally": "Stories als lokal gesehen markieren" }, "chat_action_menu": { "preview_button": "Vorschau", - "download_button": "Herunterladen", - "delete_logged_message_button": "Protokollierte Nachricht löschen", - "show_chat_edit_history": "Chat-Bearbeitungsverlauf anzeigen", - "convert_message": "Nachricht konvertieren" + "download_button": "Download", + "delete_logged_message_button": "Gespeicherte Nachrichten löschen", + "convert_message": "Nachricht konvertieren", + "edit_message": "Nachricht bearbeiten" }, "opera_context_menu": { "download": "Medien herunterladen", - "sent_at": "Gesendet am {date}", - "created_at": "Erstellt am {date}", - "expires_at": "Läuft am {date} ab", - "media_size": "Mediengröße: {size}", "media_duration": "Mediendauer: {duration} ms", - "show_debug_info": "Debug-Informationen anzeigen" + "show_debug_info": "Debug-Informationen anzeigen", + "expires_at": "Läuft am {date} ab", + "created_at": "Erstellt am {date}", + "sent_at": "Gesendet am {date}", + "media_size": "Mediengröße: {size}" }, "modal_option": { - "profile_info": "Profilinformationen", + "profile_info": "Profil Info", "close": "Schließen" }, "gallery_media_send_override": { - "multiple_media_toast": "Sie können nur ein Medium gleichzeitig senden" - }, - "mark_as_seen": { - "no_unseen_snaps_toast": "Keine ungelesenen Snaps gefunden!", - "seen_toast": "Als gesehen markiert!", - "unseen_toast": "Als ungelesen markiert!", - "already_seen_toast": "Bereits als gesehen markiert!", - "already_unseen_toast": "Bereits als ungelesen markiert!" + "multiple_media_toast": "Du kannst nur eine Datei auf einmal senden" }, "conversation_preview": { - "streak_expiration": "läuft in {day} Tagen {hour} Stunden {minute} Minuten ab", - "total_messages": "Gesamtzahl der gesendeten/empfangenen Nachrichten: {count}", + "streak_expiration": "läuft in {day} Tagen, {hour} Stunden, {minute} Minuten ab", + "total_messages": "Insgesamt gesendete/empfangene Nachrichten: {count}", "title": "Vorschau", - "unknown_user": "Unbekannter Benutzer", - "no_messages": "Keine Nachrichten gefunden!" + "unknown_user": "Unbekannter Benutzer" }, "profile_info": { - "title": "Profilinformationen", - "first_created_username": "Erster erstellter Benutzername", - "mutable_username": "Veränderbarer Benutzername", + "title": "Profil Info", + "first_created_username": "Erster Benutzername", + "mutable_username": "Änderbarer Benutzername", "display_name": "Anzeigename", - "added_date": "Hinzugefügt am", - "birthday": "Geburtstag: {day} {month}", - "hidden_birthday": "Geburtstag: Versteckt", + "added_date": "Datum hinzugefügt", + "birthday": "Geburtstag: {month} {day}", "friendship": "Freundschaft", "add_source": "Quelle hinzufügen", "snapchat_plus": "Snapchat Plus", "snapchat_plus_state": { "subscribed": "Abonniert", "not_subscribed": "Nicht abonniert" - } - }, - "friendship_link_type": { - "mutual": "Gegenseitig", - "outgoing": "Ausgehend", - "blocked": "Blockiert", - "deleted": "Gelöscht", - "following": "Folge ich", - "suggested": "Vorgeschlagen", - "incoming": "Eingehend", - "incoming_follower": "Eingehender Follower" - }, - "bulk_messaging_action": { - "choose_action_title": "Eine Aktion auswählen", - "progress_status": "Verarbeite {index} von {total}", - "selection_dialog_continue_button": "Weiter", - "confirmation_dialog": { - "title": "Sind Sie sicher?", - "message": "Dies betrifft alle ausgewählten Freunde. Diese Aktion kann nicht rückgängig gemacht werden." }, - "actions": { - "remove_friends": "Freunde entfernen", - "clear_conversations": "Konversationen löschen" - } + "hidden_birthday": "Geburtstag : Versteckt" }, "chat_export": { - "exporter_dialog": { - "select_conversations_title": "Konversationen auswählen", - "text_field_selection": "{amount} ausgewählt", - "text_field_selection_all": "Alle", - "export_file_format_title": "Dateiformat exportieren", - "message_type_filter_title": "Nachrichten nach Typ filtern", - "amount_of_messages_title": "Anzahl der Nachrichten (leer lassen für alle)", - "download_medias_title": "Medien herunterladen" - }, "dialog_negative_button": "Abbrechen", "dialog_positive_button": "Exportieren", - "exported_to": "Exportiert nach {path}", - "exporting_chats": "Chats werden exportiert...", + "exported_to": "Exportiert zu {path}", + "exporting_chats": "Chats exportieren...", "processing_chats": "{amount} Konversationen werden verarbeitet...", "export_fail": "Konversation {conversation} konnte nicht exportiert werden", - "writing_output": "Ausgabe wird geschrieben...", - "finished": "Fertig! Sie können diesen Dialog jetzt schließen.", + "writing_output": "Ausgabe schreiben...", + "finished": "Fertig! Du kannst diesen Dialog jetzt schließen.", "no_messages_found": "Keine Nachrichten gefunden!", - "exporting_message": "{conversation} wird exportiert..." + "exporting_message": "{conversation} wird exportiert...", + "exporter_dialog": { + "text_field_selection_all": "Alle", + "export_file_format_title": "Dateiformat für den Export", + "download_medias_title": "Medien herunterladen", + "amount_of_messages_title": "Anzahl der Nachrichten (für alle leer lassen)", + "message_type_filter_title": "Nachrichten nach Typ filtern", + "text_field_selection": "{amount} ausgewählt", + "select_conversations_title": "Konversationen auswählen" + } }, "button": { "ok": "OK", @@ -1861,162 +1322,243 @@ "negative": "Nein", "cancel": "Abbrechen", "open": "Öffnen", - "download": "Herunterladen", - "send": "Senden", - "restore_original": "Original wiederherstellen", - "convert_external_media": "Externe Medien konvertieren", - "save": "Speichern" - }, - "tracker_events": { - "conversation_enter": "Konversation betreten", - "conversation_exit": "Konversation verlassen", - "started_typing": "Hat angefangen zu tippen", - "stopped_typing": "Hat aufgehört zu tippen", - "started_speaking": "Hat angefangen zu sprechen", - "stopped_speaking": "Hat aufgehört zu sprechen", - "started_peeking": "Hat angefangen zu spähen", - "stopped_peeking": "Hat aufgehört zu spähen", - "message_read": "Nachricht gelesen", - "message_deleted": "Nachricht gelöscht", - "message_saved": "Nachricht gespeichert", - "message_unsaved": "Nachricht nicht gespeichert", - "message_edited": "Nachricht bearbeitet", - "message_reaction_add": "Nachrichtenreaktion hinzufügen", - "message_reaction_remove": "Nachrichtenreaktion entfernen", - "snap_opened": "Snap geöffnet", - "snap_replayed": "Snap erneut abgespielt", - "snap_replayed_twice": "Snap zweimal erneut abgespielt", - "snap_screenshot": "Snap-Screenshot", - "snap_screen_record": "Snap-Bildschirmaufnahme" - }, - "tracker_actions": { - "log": "Protokoll", - "in_app_notification": "In-App-Benachrichtigung", - "push_notification": "Push-Benachrichtigung", - "custom": "Benutzerdefiniert" - }, - "better_notifications": { - "button": { - "reply": "Antworten", - "download": "Herunterladen", - "mark_as_read": "Als gelesen markieren" - } + "download": "Download" }, "profile_picture_downloader": { - "button": "Profilbild herunterladen", + "button": "Profilbilder herunterladen", "title": "Profilbild-Downloader", "avatar_option": "Avatar", "background_option": "Hintergrund" }, - "call_start_confirmation": { - "dialog_title": "Anruf starten", - "dialog_message": "Möchten Sie wirklich einen Anruf starten?" - }, - "half_swipe_notifier": { - "notification_channel_name": "Halbes Wischen", - "notification_content_dm": "{friend} hat gerade für {duration} Sekunden halb in Ihren Chat gewischt", - "notification_content_group": "{friend} hat gerade für {duration} Sekunden halb in {group} gewischt" - }, "download_processor": { "attachment_type": { - "snap": "Schnapp", - "sticker": "Aufkleber", - "gif": "GIF", + "snap": "Snap", + "sticker": "Sticker", "external_media": "Externe Medien", "note": "Notiz", - "original_story": "Original-Story" + "original_story": "Originale Story", + "gif": "GIF" }, "select_attachments_title": "Anhänge auswählen", "download_started_toast": "Download gestartet", - "unsupported_content_type_toast": "Nicht unterstützter Inhaltstyp!", - "failed_no_longer_available_toast": "Medien nicht mehr verfügbar", + "unsupported_content_type_toast": "Nicht unterstützter Content-Typ!", + "failed_no_longer_available_toast": "Datei ist nicht mehr verfügbar", "no_attachments_toast": "Keine Anhänge gefunden!", - "already_queued_toast": "Medien bereits in der Warteschlange!", - "already_downloaded_toast": "Medien bereits heruntergeladen!", - "content_saved_toast": "Gespeichert!", + "already_queued_toast": "Datei wird bereits bearbeitet!", + "already_downloaded_toast": "Datei wurde bereits heruntergeladen!", "download_toast": "{path} wird heruntergeladen...", - "processing_toast": "{path} wird verarbeitet...", + "processing_toast": "Verarbeite {path}...", "failed_generic_toast": "Download fehlgeschlagen", - "failed_to_create_preview_toast": "Vorschau konnte nicht erstellt werden", - "failed_processing_toast": "Verarbeitung fehlgeschlagen {error}", + "failed_to_create_preview_toast": "Fehler beim Erstellen der Vorschau", + "failed_processing_toast": "Fehler beim Verarbeiten {error}", "failed_gallery_toast": "Speichern in der Galerie fehlgeschlagen {error}", - "dash_no_chapter": "Kein Kapitel gefunden", + "dash_no_chapter": "Kein Abschnitt gefunden", "dash_dialog": { - "title": "Dash-Medien herunterladen", + "title": "Dash-Medium herunterladen", "download_all": "Alle herunterladen", "segment_text": "Segment {from} - {to}" } }, "streaks_reminder": { - "notification_title": "Streifen", - "notification_text": "Sie verlieren Ihren Streak mit {friend} in {hoursLeft} Stunden" + "notification_title": "Flammen", + "notification_text": "Du wirst deine Flammen mit {friend} in {hoursLeft} Stunden verlieren" }, - "biometric_auth": { - "unlock_button": "Entsperren", - "title": "Snapchat entsperren", - "subtitle": "Bitte authentifizieren Sie sich, um Snapchat zu entsperren" + "content_type": { + "FAMILY_CENTER_INVITE": "Family Center einladen", + "STATUS_CONVERSATION_CAPTURE_RECORD": "Bildschirmaufnahme", + "STATUS_CALL_MISSED_VIDEO": "Verpasster Videoanruf", + "CREATIVE_TOOL_ITEM": "Kreativ-Werkzeug Element", + "STICKER": "Sticker", + "TINY_SNAP": "Winziger Snap", + "STATUS_SAVE_TO_CAMERA_ROLL": "In Camera Roll gespeichert", + "EXTERNAL_MEDIA": "Externe Medien", + "SNAP": "Snap", + "LOCATION": "Standort", + "CHAT": "Chat", + "STATUS_PLUS_GIFT": "Status Plus Geschenk", + "STATUS_COUNTDOWN": "Countdown", + "LIVE_LOCATION_SHARE": "Live-Standort teilen", + "STATUS": "Status", + "STATUS_CONVERSATION_CAPTURE_SCREENSHOT": "Screenshot", + "FAMILY_CENTER_ACCEPT": "Family Center akzeptieren", + "FAMILY_CENTER_LEAVE": "Family Center verlassen", + "STATUS_CALL_MISSED_AUDIO": "Verpasster Sprachanruf", + "NOTE": "Sprachnachricht", + "MAP_REACTION": "Kartenreaktion", + "SHARE": "Teilen" + }, + "better_notifications": { + "button": { + "download": "Herunterladen", + "reply": "Antwort", + "mark_as_read": "Als gelesen markieren" + } + }, + "half_swipe_notifier": { + "notification_content_group": "{friend} hat gerade halb in {group} für {duration} Sekunden geswiped", + "notification_channel_name": "Halb-Swipe", + "notification_content_dm": "{friend} hat gerade für {duration} Sekunden halb in deinen Chat geswiped" + }, + "friendship_link_type": { + "mutual": "Gegenseitig", + "deleted": "Gelöscht", + "following": "Folge Ich", + "incoming_follower": "Eingehender Follower", + "incoming": "Eingehend", + "blocked": "Blockiert", + "suggested": "Empfohlen", + "outgoing": "Ausgehend" + }, + "call_start_confirmation": { + "dialog_message": "Sind Sie sicher, dass Sie einen Anruf starten wollen?", + "dialog_title": "Anruf starten" + }, + "bulk_messaging_action": { + "choose_action_title": "Wähle eine Aktion", + "progress_status": "Verarbeite {index} von {total}", + "actions": { + "clear_conversations": "Lösche Konversationen", + "remove_friends": "Freunde entfernen" + }, + "selection_dialog_continue_button": "Weiter", + "confirmation_dialog": { + "message": "Das betrifft alle ausgewählten Freunde. Diese Aktion kann nicht rückgängig gemacht werden.", + "title": "Sind Sie sicher?" + } + }, + "media_download_source": { + "none": "Keine", + "profile_picture": "Profilbild", + "chat_media": "Chat-Medium", + "public_story": "Öffentliche Story", + "spotlight": "Spotlight", + "pending": "Ausstehend", + "story": "Story", + "story_logger": "Story Logger", + "merged": "Zusammengeführt", + "message_logger": "Nachrichtenprotokollierung", + "voice_call": "Sprachanruf" + }, + "material3_strings": { + "date_input_invalid_not_allowed": "Invalides Datum", + "date_range_picker_scroll_to_previous_month": "Vorheriger Monat", + "date_input_invalid_for_pattern": "Invalides Datum", + "date_picker_today_description": "Heute", + "date_picker_switch_to_calendar_mode": "Kalender", + "date_range_picker_start_headline": "Von", + "date_range_picker_end_headline": "Bis", + "date_range_picker_scroll_to_next_month": "Nächster Monat", + "date_input_invalid_year_range": "Invalides Jahr", + "date_range_input_invalid_range_input": "Ungültiger Zeitraum", + "date_picker_switch_to_input_mode": "Eingabe", + "date_range_picker_day_in_range": "Gewählt", + "date_range_picker_title": "Wähle einen Zeitraum" + }, + "actions": { + "clean_snapchat_cache": { + "name": "Leere den Snapchat Cache", + "description": "Leert den Snapchat Cache" + }, + "manage_friend_list": { + "name": "Freundesliste verwalten", + "description": "Im-/ex- portiere deine Freundesliste beim Backup" + }, + "export_chat_messages": { + "name": "Exportiere die Chatnachrichten", + "description": "Exportiert Chat-Nachrichten in eine JSON/HTML/TXT Datei" + }, + "export_memories": { + "name": "Exportiere die Memories", + "description": "Exportiere die Memories in eine ZIP-Datei" + }, + "bulk_messaging_action": { + "name": "Massen Nachrichten Aktion", + "description": "Führt Operationen wie das Löschen von Freunden oder amassenlöschung von Konversationen durch" + }, + "regen_mappings": { + "name": "Erneuere die Mappings", + "description": "Erneuere die Mappings manuell" + }, + "change_language": { + "name": "Sprache ändern", + "description": "Ändere die Sprache von SnapEnhance" + }, + "file_imports": { + "description": "Importieren von Dateien zur Verwendung in Snapchat", + "name": "Dateiimporte" + }, + "logger_history": { + "name": "Logger Verlauf", + "description": "Historie der protokollierten Nachrichten anzeigen" + }, + "friend_tracker": { + "name": "Freund Tracker", + "description": "Verfolge deine Freunde auf Snapchat" + }, + "security_features": { + "name": "Sicherheitsfunktionen", + "description": "Einstellungen für Sicherheitsfunktionen ändern" + }, + "theming": { + "name": "Personalisierung", + "description": "Passe das Erscheinungsbild von Snapchat an" + } + }, + "mark_as_seen": { + "already_unseen_toast": "Schon als ungelesen markiert!", + "no_unseen_snaps_toast": "Es wurden keine ungesehenen Snaps gefunden!", + "seen_toast": "Markiert als gesehen!", + "unseen_toast": "Markiert als ungesehen!", + "already_seen_toast": "Bereits markiert als gesehen!" + }, + "scopes": { + "friend": "Freund:in", + "group": "Gruppe" }, "end_to_end_encryption": { "toolbox": { - "no_shared_key": "Sie haben noch keinen gemeinsamen geheimen Schlüssel mit diesem Freund. Klicken Sie unten, um einen neuen zu initiieren.", - "shared_key_fingerprint": "Ihr Fingerabdruck ist:\n\n{fingerprint}\n\nStellen Sie sicher, dass er mit dem Fingerabdruck Ihres Freundes übereinstimmt!", - "initiate_exchange_button": "Schlüsselaustausch initiieren" + "no_shared_key": "Sie haben noch kein gemeinsames Geheimnis mit diesem Freund. Klicken Sie unten, um ein neues zu erstellen.", + "shared_key_fingerprint": "Dein Fingerabdruck ist:\n\n{fingerprint}\n\nSieh nach, ob er mit dem Fingerabdruck deines Freundes übereinstimmt!", + "initiate_exchange_button": "Schlüsselaustausch einleiten" }, "confirmation_dialogs": { - "title": "Ende-zu-Ende-Verschlüsselung", - "confirmation_1": "WARNUNG: Dies überschreibt Ihren vorhandenen Schlüssel. Sie verlieren den Zugriff auf alle verschlüsselten Nachrichten von diesem Freund. Möchten Sie wirklich fortfahren?", - "confirmation_2": "Sind Sie WIRKLICH sicher, dass Sie fortfahren möchten? Dies ist Ihre letzte Chance, einen Rückzieher zu machen." + "title": "Ende-zu-Ende Verschlüsselung", + "confirmation_1": "WARNUNG: Dadurch wird Ihr vorhandener Schlüssel überschrieben. Sie werden den Zugang zu allen verschlüsselten Nachrichten dieses Freundes verlieren. Sind Sie sicher, dass Sie fortfahren möchten?", + "confirmation_2": "Sind Sie WIRKLICH sicher, dass Sie weitermachen wollen? Dies ist Ihre letzte Chance, einen Rückzieher zu machen." }, - "unencrypted_conversation_send_failure_toast": "Sie können keinen verschlüsselten Inhalt an sowohl verschlüsselte als auch unverschlüsselte Konversationen senden!", - "native_hooks_send_failure_toast": "Senden fehlgeschlagen! Bitte aktivieren Sie Native Hooks in den Einstellungen.", - "no_participants_to_encrypt_toast": "Sie haben keine Freunde in dieser Konversation, mit denen Sie Nachrichten verschlüsseln können!", - "encryption_failed_toast": "Nachricht konnte nicht verschlüsselt werden! Überprüfen Sie logcat für weitere Details.", + "native_hooks_send_failure_toast": "Senden fehlgeschlagen! Bitte aktivieren Sie die nativen Hooks in den Einstellungen.", + "no_participants_to_encrypt_toast": "Sie haben in diesem Gespräch keine Freunde, mit denen Sie Nachrichten verschlüsseln können!", + "encryption_failed_toast": "Nachricht konnte nicht verschlüsselt werden! Prüfen Sie logcat für weitere Details.", "accept_public_key_success_toast": "Öffentlicher Schlüssel erfolgreich akzeptiert!", - "accept_secret_key_success_toast": "Fertig! Sie können jetzt verschlüsselte Nachrichten mit diesem Freund senden und empfangen.", - "accept_public_key_failure_toast": "Öffentlicher Schlüssel konnte nicht akzeptiert werden", - "accept_secret_key_failure_toast": "Geheimer Schlüssel konnte nicht akzeptiert werden", + "accept_secret_key_success_toast": "Geschafft! Sie können nun verschlüsselte Nachrichten an diesen Freund senden und empfangen.", + "accept_secret_key_failure_toast": "Akzeptieren des geheimen Schlüssels fehlgeschlagen", + "outgoing_secret_message": "Schlüsselaustausch-Antwort", "accept_secret_button": "Geheimnis akzeptieren", "accept_public_key_button": "Öffentlichen Schlüssel akzeptieren", - "outgoing_pk_message": "Anfrage zum Schlüsselaustausch", - "outgoing_secret_message": "Antwort auf den Schlüsselaustausch", - "incoming_pk_message": "Sie haben gerade eine Anfrage für einen öffentlichen Schlüssel erhalten. Klicken Sie unten, um sie zu akzeptieren.", - "incoming_secret_message": "Ihr Freund hat gerade Ihren öffentlichen Schlüssel akzeptiert. Klicken Sie unten, um das Geheimnis zu akzeptieren." + "incoming_pk_message": "Sie haben gerade eine Anfrage für einen öffentlichen Schlüssel erhalten. Klicken Sie unten, um sie anzunehmen.", + "outgoing_pk_message": "Schlüsselaustausch-Anfrage", + "accept_public_key_failure_toast": "Akzeptieren des öffentlichen Schlüssels fehlgeschlagen", + "unencrypted_conversation_send_failure_toast": "Sie können keine verschlüsselten Inhalte zu verschlüsselten und unverschlüsselten Gesprächen gleichzeitig senden!", + "incoming_secret_message": "Ihr Freund hat gerade Ihren öffentlichen Schlüssel akzeptiert. Klicken Sie unten, um das Passwort zu akzeptieren." + }, + "biometric_auth": { + "unlock_button": "Entsperren", + "title": "Entsperre Snapchat", + "subtitle": "Bestätigen, dass du es bist, um Snapchat zu öffnen" }, "auto_open_snaps": { - "title": "Snaps automatisch öffnen", + "title": "Auto-Öffnen von Snaps", "notification_content": "{count} Snaps geöffnet" }, "friend_mutation_observer": { - "notification_channel_name": "Freundes-Mutations-Beobachter", - "friend_removed": "{username} hat Sie als Freund entfernt", - "birthday_removed": "{username} hat seinen Geburtstag entfernt ({birthday})", - "birthday_added": "{username} hat seinen Geburtstag hinzugefügt ({birthday})", - "birthday_changed": "{username} hat seinen Geburtstag von {oldBirthday} auf {newBirthday} geändert", - "bitmoji_selfie_changed": "{username} hat sein Bitmoji-Selfie geändert", - "bitmoji_avatar_changed": "{username} hat seinen Bitmoji-Avatar geändert", - "bitmoji_background_changed": "{username} hat seinen Bitmoji-Hintergrund geändert", - "bitmoji_scene_changed": "{username} hat seine Bitmoji-Szene geändert" - }, - "material3_strings": { - "date_range_picker_start_headline": "Von", - "date_range_picker_end_headline": "Bis", - "date_range_picker_title": "Datumsbereich auswählen", - "date_picker_switch_to_calendar_mode": "Kalender", - "date_picker_switch_to_input_mode": "Eingabe", - "date_range_picker_scroll_to_previous_month": "Vorheriger Monat", - "date_range_picker_scroll_to_next_month": "Nächster Monat", - "date_picker_today_description": "Heute", - "date_range_picker_day_in_range": "Ausgewählt", - "date_input_invalid_for_pattern": "Ungültiges Datum", - "date_input_invalid_year_range": "Ungültiges Jahr", - "date_input_invalid_not_allowed": "Ungültiges Datum", - "date_range_input_invalid_range_input": "Ungültiger Datumsbereich" - }, - "send_override_dialog": { - "title": "Medien als {type} senden", - "duration": "Dauer: {duration}", - "saveable_snap_hint": "Snap im Chat speicherbar machen", - "unlimited_duration": "Unbegrenzt" - }, - "invalid_input_toast": "Ungültige Eingabe! Stellen Sie sicher, dass Sie einen gültigen Wert eingegeben haben." -} \ No newline at end of file + "birthday_removed": "{username} hat sein/ ihr Geburtsdatum ({birthday}) entfernt", + "birthday_changed": "{username} hat sein/ ihr Geburtsdatum von {oldBirthday} auf {newBirthday} geändert", + "bitmoji_background_changed": "{username} hat den Hintergrund seines/ ihres Bitmojis geändert", + "birthday_added": "{username} hat sein/ ihr Geburtsdatum ({birthday}) hinzugefügt", + "bitmoji_scene_changed": "{username} hat seine/ ihre Bitmoji-Szene geändert", + "bitmoji_selfie_changed": "{username} hat sein/ ihr Bitmoji-Selfie geändert", + "bitmoji_avatar_changed": "{username} hat sein/ ihr Bitmoji-Avatar geändert", + "notification_channel_name": "Freund:innen-Veränderungs-Stalker", + "friend_removed": "{username} hat dich als Freund:in entfernt" + } +} diff --git a/common/src/main/assets/lang/el.json b/common/src/main/assets/lang/el.json deleted file mode 100644 index e1615165..00000000 --- a/common/src/main/assets/lang/el.json +++ /dev/null @@ -1,2022 +0,0 @@ -{ - "setup": { - "dialogs": { - "select_language": "Επιλογή Γλώσσας", - "save_folder": "Το PurrfectSnap απαιτεί δικαιώματα αποθήκευσης για λήψη και αποθήκευση πολυμέσων από το Snapchat.\nΕπιλέξτε την τοποθεσία στην οποία θα γίνει λήψη των πολυμέσων.", - "select_save_folder_button": "Επιλογή φακέλου" - }, - "mappings": { - "dialog": "Δημιουργία αντιστοιχίσεων, αυτό μπορεί να διαρκέσει λίγο...", - "generate_failure_no_snapchat": "Το PurrfectSnap δεν μπόρεσε να εντοπίσει το Snapchat, δοκιμάστε να το εγκαταστήσετε ξανά.", - "generate_failure": "Παρουσιάστηκε σφάλμα κατά τη δημιουργία αντιστοιχίσεων, δοκιμάστε ξανά." - }, - "permissions": { - "dialog": "Για να συνεχίσετε, πρέπει να πληροίτε τις ακόλουθες απαιτήσεις:", - "notification_access": "Πρόσβαση σε ειδοποιήσεις", - "battery_optimization": "Βελτιστοποίηση μπαταρίας", - "display_over_other_apps": "Εμφάνιση πάνω από άλλες εφαρμογές", - "request_button": "Αίτημα" - } - }, - "scopes": { - "friend": "Φίλος", - "group": "Ομάδα" - }, - "manager": { - "routes": { - "tasks": "Εργασίες", - "features": "Δυνατότητες", - "manage_rule_feature": "Διαχείριση δυνατότητας κανόνα", - "home": "Αρχική", - "home_settings": "Ρυθμίσεις", - "home_logs": "Αρχεία καταγραφής", - "logger_history": "Ιστορικό καταγραφέα", - "logged_stories": "Καταγεγραμμένες ιστορίες", - "friend_tracker": "Παρακολούθηση φίλων", - "edit_rule": "Επεξεργασία κανόνα", - "file_imports": "Εισαγωγές αρχείων", - "manage_repos": "Διαχείριση αποθετηρίων", - "social": "Κοινωνικά", - "manage_scope": "Διαχείριση εύρους", - "messaging_preview": "Προεπισκόπηση", - "scripts": "Σενάρια", - "better_location": "Καλύτερη τοποθεσία" - }, - "sections": { - "home": { - "version_title": "v{versionName} · διακλαδώθηκε από τον Eternal", - "update_title": "Ενημέρωση PurrfectSnap", - "update_content": "Η έκδοση {version} είναι διαθέσιμη!", - "update_button": "Λήψη", - "debug_build_summary_title": "Εκτελείτε μια έκδοση εντοπισμού σφαλμάτων του PurrfectSnap", - "debug_build_summary_content": "Έκδοση {versionName} ({versionCode})", - "debug_build_summary_date": "Ημερομηνία έκδοσης: {date} (πριν από {days} ημέρες)", - "quick_actions_title": "Γρήγορες ενέργειες", - "download_icon_description": "Λήψη", - "completed_icon_description": "Ολοκληρώθηκε", - "failed_icon_description": "Απέτυχε", - "manage_quick_actions_description": "Διαχείριση γρήγορων ενεργειών", - "quick_actions_icon_description": "Γρήγορες ενέργειες", - "add_quick_action_description": "Προσθήκη γρήγορης ενέργειας" - }, - "home_logs": { - "no_logs_hint": "Δεν υπάρχουν διαθέσιμα αρχεία καταγραφής", - "clear_logs_button": "Εκκαθάριση αρχείων καταγραφής", - "export_logs_button": "Εξαγωγή αρχείων καταγραφής", - "saving_logs_toast": "Αποθήκευση αρχείων καταγραφής, αυτό μπορεί να διαρκέσει λίγο...", - "saved_logs_success_toast": "Τα αρχεία καταγραφής αποθηκεύτηκαν με επιτυχία", - "saved_logs_failure_toast": "Η αποθήκευση των αρχείων καταγραφής απέτυχε" - }, - "home_settings": { - "actions_title": "Ενέργειες", - "message_logger_title": "Καταγραφέας μηνυμάτων", - "debug_title": "Εντοπισμός σφαλμάτων", - "success_toast": "Έγινε!", - "message_logger_summary": "{messageCount} μηνύματα\n{storyCount} ιστορίες", - "export_button": "Εξαγωγή", - "clear_button": "Εκκαθάριση", - "view_logger_history_button": "Προβολή ιστορικού καταγραφέα", - "updates_title": "Ενημερώσεις", - "auto_update_check": "Αυτόματος έλεγχος για ενημερώσεις", - "update_check_frequency": "Συχνότητα ελέγχου ενημερώσεων", - "update_check_frequency_daily": "Καθημερινά", - "update_check_frequency_weekly": "Εβδομαδιαία", - "update_check_frequency_monthly": "Μηνιαία", - "theme_icon_description": "Θέμα", - "app_theme_title": "Θέμα εφαρμογής", - "theme_mode_system": "Σύστημα", - "theme_mode_light": "Φωτεινό", - "theme_mode_dark": "Σκοτεινό", - "ui_settings_title": "Ρυθμίσεις διεπαφής χρήστη", - "haptic_feedback_label": "Απτική ανάδραση", - "test_mode_label": "Δοκιμαστική λειτουργία (ΜΟΝΟ ΓΙΑ ΕΝΤΟΠΙΣΜΟ ΣΦΑΛΜΑΤΩΝ)", - "disable_feature_loading_label": "Απενεργοποίηση φόρτωσης δυνατοτήτων", - "disable_auto_mapper_label": "Απενεργοποίηση αυτόματου αντιστοιχιστή", - "disable_bypass_indicator_label": "Απενεργοποίηση ένδειξης κατάστασης παράκαμψης", - "update_notification_channel_name": "Ενημερώσεις PurrfectSnap", - "update_notification_channel_description": "Ειδοποιήσεις για ενημερώσεις του PurrfectSnap", - "update_notification_title": "Διαθέσιμη ενημέρωση PurrfectSnap", - "update_notification_text": "Η έκδοση %s είναι τώρα διαθέσιμη.", - "export_database_failed_toast": "Η εξαγωγή της βάσης δεδομένων απέτυχε! {message}", - "clear_messages_failed_toast": "Η εκκαθάριση των μηνυμάτων απέτυχε! {message}", - "clear_file_failed_toast": "Η εκκαθάριση του αρχείου απέτυχε! {message}", - "debug_file_config": "Διαμόρφωση", - "debug_file_mappings": "Αντιστοιχίσεις", - "debug_file_message_logger": "Καταγραφέας μηνυμάτων", - "debug_file_pinned_best_friend": "Καρφιτσωμένος καλύτερος φίλος", - "debug_file_native_sig_cache": "Προσωρινή μνήμη εγγενών υπογραφών" - }, - "tasks": { - "no_tasks": "Δεν υπάρχουν εργασίες", - "merge_button": "Συγχώνευση", - "failed_to_open_file": "Το άνοιγμα του αρχείου απέτυχε", - "merge_files_toast": "Συγχώνευση {count} αρχείων", - "remove_selected_tasks_title": "Είστε βέβαιοι ότι θέλετε να καταργήσετε τις επιλεγμένες εργασίες;", - "remove_all_tasks_title": "Είστε βέβαιοι ότι θέλετε να καταργήσετε όλες τις εργασίες;", - "delete_files_option": "Διαγραφή και των αρχείων", - "remove_selected_tasks_confirm": "Κατάργηση {count} εργασιών;", - "remove_all_tasks_confirm": "Κατάργηση όλων των εργασιών;", - "clear_tasks_description": "Εκκαθάριση εργασιών", - "file_not_found_icon_description": "Το αρχείο δεν βρέθηκε", - "image_icon_description": "Εικόνα", - "video_icon_description": "Βίντεο", - "audio_icon_description": "Ήχος", - "file_icon_description": "Αρχείο", - "download_icon_description": "Λήψη", - "chat_action_icon_description": "Ενέργεια συνομιλίας", - "cancel_icon_description": "Ακύρωση", - "success_icon_description": "Επιτυχία", - "failure_icon_description": "Αποτυχία", - "cancelled_icon_description": "Ακυρώθηκε", - "task_status_failure": "Αποτυχία", - "task_status_cancelled": "Ακυρώθηκε" - }, - "features": { - "disabled": "Απενεργοποιημένο", - "export_option": "Εξαγωγή", - "import_option": "Εισαγωγή", - "reset_option": "Επαναφορά", - "config_export_success_toast": "Η διαμόρφωση εξήχθη με επιτυχία", - "config_import_success_toast": "Η διαμόρφωση εισήχθη με επιτυχία", - "config_import_failure_toast": "Η εισαγωγή της διαμόρφωσης απέτυχε {error}", - "config_export_failure_toast": "Η εξαγωγή της διαμόρφωσης απέτυχε {error}", - "saved_config_snackbar": "Η διαμόρφωση αποθηκεύτηκε", - "older_required": "Αυτή η δυνατότητα απαιτεί το Snapchat v{version} ή παλαιότερη για να λειτουργήσει σωστά", - "newer_required": "Αυτή η δυνατότητα απαιτεί το Snapchat v{version} ή νεότερη για να λειτουργήσει σωστά", - "search_button": "Αναζήτηση" - }, - "manage_rule_feature": { - "disable_state_option": "Απενεργοποιημένο", - "disable_state_subtext": "Κανένας φίλος/ομάδα δεν θα επηρεαστεί", - "whitelist_state_option": "Κανείς εκτός από...", - "whitelist_state_subtext": "Μόνο {count} φίλοι/ομάδες θα επηρεαστούν από αυτόν τον κανόνα", - "whitelist_state_button": "Επιλογή επιτρεπόμενων φίλων/ομάδων", - "blacklist_state_option": "Όλοι εκτός από...", - "blacklist_state_subtext": "Όλοι εκτός από {count} φίλοι/ομάδες θα επηρεαστούν από αυτόν τον κανόνα", - "blacklist_state_button": "Επιλογή εξαιρούμενων φίλων/ομάδων", - "clear_list_button": "Εκκαθάριση λίστας φίλων/ομάδων", - "dialog_clear_confirmation_text": "Είστε βέβαιοι ότι θέλετε να εκκαθαρίσετε τη λίστα;" - }, - "social": { - "friends_tab": "Φίλοι", - "groups_tab": "Ομάδες", - "empty_hint": "(κενό)", - "streaks_expiration_short": "{hours}ώ" - }, - "manage_scope": { - "logged_stories_button": "Εμφάνιση καταγεγραμμένων ιστοριών", - "e2ee_title": "Κρυπτογράφηση από άκρο σε άκρο", - "rules_title": "Κανόνες", - "participants_text": "{count} συμμετέχοντες", - "not_found": "Δεν βρέθηκε", - "streaks_title": "Σερί", - "streaks_length_text": "Μήκος: {length}", - "streaks_expiration_text": "Λήγει σε {eta}", - "streaks_expiration_text_expired": "Έληξε", - "reminder_button": "Ορισμός υπενθύμισης", - "delete_scope_confirm_dialog_title": "Είστε βέβαιοι ότι θέλετε να διαγράψετε ένα {scope};", - "notes_placeholder": "Κάντε κλικ για να προσθέσετε μια σημείωση", - "invalid_key_size_32_bytes": "Μη έγκυρο μέγεθος κλειδιού (πρέπει να είναι 32 byte)", - "successfully_imported_key": "Το κλειδί εισήχθη με επιτυχία", - "failed_to_import_key": "Η εισαγωγή του κλειδιού απέτυχε: {message}", - "export_base64_button": "Εξαγωγή Base64", - "import_base64_button": "Εισαγωγή Base64" - }, - "logged_stories": { - "story_failed_to_load": "Η φόρτωση της ιστορίας απέτυχε", - "no_stories": "Δεν βρέθηκαν ιστορίες", - "save_from_cache_button": "Αποθήκευση από την προσωρινή μνήμη", - "downloaded_to_path": "Λήψη στο {path}", - "download_failed": "Η λήψη απέτυχε: {message}", - "posted_at": "Δημοσιεύτηκε στις {date}", - "created_at": "Δημιουργήθηκε στις {date}", - "failed_to_open_file": "Το άνοιγμα του αρχείου απέτυχε. Ελέγξτε τα αρχεία καταγραφής για περισσότερες πληροφορίες", - "failed_to_get_file": "Η λήψη του αρχείου απέτυχε" - }, - "messaging_preview": { - "processed_messages_toast": "Επεξεργάστηκαν {count} μηνύματα", - "processed_messages_text": "Επεξεργάστηκαν {count} μηνύματα", - "close_button_description": "Κλείσιμο", - "bridge_connection_failed": "Η σύνδεση με τη γέφυρα απέτυχε. Βεβαιωθείτε ότι το Snapchat εκτελείται στο παρασκήνιο", - "bridge_init_failed": "Η αρχικοποίηση της γέφυρας μηνυμάτων απέτυχε. Βεβαιωθείτε ότι το Snapchat εκτελείται στο παρασκήνιο", - "message_fetch_failed": "Η ανάκτηση των μηνυμάτων απέτυχε", - "no_message_hint": "Κανένα μήνυμα", - "save_selection_option": "Αποθήκευση επιλογής", - "save_all_option": "Αποθήκευση όλων", - "unsave_selection_option": "Κατάργηση αποθήκευσης επιλογής", - "unsave_all_option": "Κατάργηση αποθήκευσης όλων", - "mark_selection_as_seen_option": "Σήμανση επιλεγμένου Snap ως αναγνωσμένου", - "mark_all_as_seen_option": "Σήμανση όλων των Snaps ως αναγνωσμένων", - "delete_selection_option": "Διαγραφή επιλογής", - "delete_all_option": "Διαγραφή όλων" - }, - "logger_history": { - "download_started_toast": "Η λήψη ξεκίνησε!", - "download_success_toast": "Λήψη στο {path}", - "download_failed_toast": "Η λήψη του {message} απέτυχε", - "edited_at_text": "{message} (επεξεργάστηκε στις {date})", - "download_button": "Λήψη", - "select_conversation_placeholder": "Επιλογή συνομιλίας", - "close_button_description": "Κλείσιμο", - "search_button_description": "Αναζήτηση", - "list_friend_format": "Φίλος {name}", - "list_group_format": "Ομάδα {name}", - "no_more_messages": "Δεν υπάρχουν άλλα μηνύματα", - "reverse_order_checkbox": "Αντίστροφη σειρά", - "chat_attachment": "Συνημμένο {index}", - "empty_message": "Κενό μήνυμα συνομιλίας", - "message_parse_failed": "Η ανάλυση του μηνύματος απέτυχε", - "unknown_sender": "Άγνωστος αποστολέας", - "download_attachment_failed_toast": "Η λήψη του συνημμένου απέτυχε", - "log_header_format": "{username} ({type}) - {date}" - }, - "file_imports": { - "import_file_button": "Εισαγωγή αρχείου", - "file_not_found": "Το αρχείο δεν βρέθηκε", - "file_import_failed": "Η εισαγωγή του αρχείου απέτυχε: {error}", - "file_imported": "Το αρχείο εισήχθη με επιτυχία", - "file_delete_failed": "Η διαγραφή του αρχείου απέτυχε", - "no_files_hint": "Εδώ μπορείτε να εισαγάγετε αρχεία για χρήση στο Snapchat. Πατήστε το παρακάτω κουμπί για να εισαγάγετε ένα αρχείο." - }, - "better_location": { - "spoofed_coordinates_title": "Πλάτος {latitude}, Μήκος {longitude}", - "save_coordinates_dialog_title": "Αποθήκευση συντεταγμένων", - "saved_name_dialog_hint": "Αποθηκευμένο όνομα", - "latitude_dialog_hint": "Γεωγραφικό πλάτος", - "longitude_dialog_hint": "Γεωγραφικό μήκος", - "save_dialog_button": "Αποθήκευση", - "choose_location_button": "Επιλογή τοποθεσίας", - "teleport_to_friend_button": "Τηλεμεταφορά σε φίλο", - "spoof_location_toggle": "Παραποίηση τοποθεσίας", - "suspend_location_updates": "Αναστολή ενημερώσεων τοποθεσίας", - "saved_coordinates_title": "Αποθηκευμένες συντεταγμένες", - "no_saved_coordinates_hint": "Δεν υπάρχουν αποθηκευμένες συντεταγμένες", - "delete_dialog_title": "Διαγραφή αποθηκευμένης συντεταγμένης", - "delete_dialog_message": "Είστε βέβαιοι ότι θέλετε να διαγράψετε αυτήν την αποθηκευμένη συντεταγμένη;", - "teleport_to_friend_title": "Τηλεμεταφορά σε φίλο", - "search_bar": "Αναζήτηση", - "no_friends_map": "Δεν υπάρχουν φίλοι στον χάρτη", - "no_friends_found": "Δεν βρέθηκαν φίλοι", - "edit_location_button_description": "Επεξεργασία τοποθεσίας", - "add_icon_description": "Προσθήκη", - "edit_icon_description": "Επεξεργασία", - "delete_icon_description": "Διαγραφή" - } - }, - "dialogs": { - "add_friend": { - "title": "Προσθήκη φίλου ή ομάδας", - "search_hint": "Αναζήτηση", - "fetch_error": "Η ανάκτηση δεδομένων απέτυχε", - "category_groups": "Ομάδες", - "category_friends": "Φίλοι", - "participants_text": "{count} συμμετέχοντες", - "search_icon_description": "Αναζήτηση" - }, - "scripting_warning": { - "title": "Προειδοποίηση", - "content": "Το PurrfectSnap περιλαμβάνει ένα εργαλείο δέσμης ενεργειών, το οποίο επιτρέπει την εκτέλεση κώδικα που ορίζεται από τον χρήστη στη συσκευή σας. Να είστε εξαιρετικά προσεκτικοί και να εγκαθιστάτε λειτουργικές μονάδες μόνο από γνωστές, αξιόπιστες πηγές. Οι μη εξουσιοδοτημένες ή μη επαληθευμένες λειτουργικές μονάδες ενδέχεται να αποτελούν κίνδυνο για την ασφάλεια του συστήματός σας." - }, - "reset_config": { - "title": "Επαναφορά διαμόρφωσης", - "content": "Είστε βέβαιοι ότι θέλετε να επαναφέρετε τη διαμόρφωση;", - "success_toast": "Η διαμόρφωση επαναφέρθηκε με επιτυχία" - }, - "export_config": { - "title": "Εξαγωγή ευαίσθητων δεδομένων;", - "content": "Θέλετε να εξαγάγετε τη διαμόρφωση με ευαίσθητα δεδομένα; (π.χ. συντεταγμένες τοποθεσίας κ.λπ.)" - }, - "messaging_action": { - "title": "Επιλέξτε τύπους περιεχομένου για επεξεργασία", - "select_all_button": "Επιλογή όλων" - }, - "file_imports": { - "no_files_settings_hint": "Δεν βρέθηκαν αρχεία. Βεβαιωθείτε ότι έχετε εισαγάγει τα απαιτούμενα αρχεία στην ενότητα Εισαγωγές αρχείων", - "settings_select_file_hint": "Επιλογή εισαγόμενου αρχείου" - }, - "quick_actions_dialog": { - "title": "Επεξεργασία γρήγορων ενεργειών", - "subtitle": "Επιλέξτε και προσαρμόστε το μέγεθος των γρήγορων ενεργειών σας." - } - }, - "friend_tracker": { - "rules_tab": "Κανόνες", - "logs_tab": "Αρχεία καταγραφής", - "export_dialog_title": "Εξαγωγή", - "bulk_export_button": "Μαζική εξαγωγή", - "individual_export_button": "Ατομική εξαγωγή", - "invalid_import_type_dialog_title": "Μη έγκυρος τύπος εισαγωγής", - "invalid_import_type_dialog_text": "Το επιλεγμένο αρχείο δεν είναι συμβατό με αυτόν τον τύπο εισαγωγής. Επιλέξτε τον σωστό τύπο εισαγωγής.", - "import_dialog_title": "Εισαγωγή", - "bulk_import_button": "Μαζική εισαγωγή", - "individual_import_button": "Ατομική εισαγωγή", - "import_button_description": "Εισαγωγή", - "export_button_description": "Εξαγωγή", - "export_button": "Εξαγωγή", - "delete_button_description": "Διαγραφή", - "delete_button": "Διαγραφή", - "catalog_button_description": "Κατάλογος", - "catalog_button": "Κατάλογος", - "add_rule_button_description": "Προσθήκη κανόνα", - "add_rule_button": "Προσθήκη κανόνα", - "no_rules_found": "Δεν βρέθηκαν κανόνες", - "empty_rule_name": "(κενό)", - "events_suffix": "συμβάντα", - "scopes_suffix": "εύρη", - "select_rule_to_export_title": "Επιλογή κανόνα για εξαγωγή", - "deleted_logs_toast": "Διαγράφηκαν {count} αρχεία καταγραφής", - "delete_logs_dialog_title": "Διαγραφή αρχείων καταγραφής;", - "deleting_logs_dialog_text": "Διαγραφή {count} αρχείων καταγραφής...", - "delete_logs_dialog_confirm_text": "Αυτό θα διαγράψει τα αρχεία καταγραφής με βάση το τρέχον φίλτρο και το ερώτημα αναζήτησης. Αυτή η ενέργεια δεν μπορεί να αναιρεθεί.", - "exported_logs_toast": "Τα αρχεία καταγραφής εξήχθησαν!", - "export_logs_failed_toast": "Η εξαγωγή των αρχείων καταγραφής απέτυχε. Ελέγξτε το logcat για περισσότερες λεπτομέρειες.", - "export_logs_dialog_title": "Εξαγωγή αρχείων καταγραφής;", - "exporting_logs_dialog_text": "Εξαγωγή αρχείων καταγραφής...", - "export_logs_dialog_confirm_text": "Αυτό θα εξαγάγει τα αρχεία καταγραφής με βάση το τρέχον φίλτρο και το ερώτημα αναζήτησης.", - "export_as_button": "Εξαγωγή ως {type}", - "filters_title": "Φίλτρα", - "search_by_label": "Αναζήτηση κατά", - "newest_first_label": "Νεότερα πρώτα", - "since_label": "Από", - "until_label": "Έως", - "pick_a_date_button": "Επιλογή ημερομηνίας", - "search_placeholder": "Αναζήτηση", - "filter_button_description": "Φίλτρο", - "clear_button_description": "Εκκαθάριση", - "no_logs_found": "Δεν βρέθηκαν αρχεία καταγραφής", - "log_event_format": "{event} στο {conversation}", - "condition_only_inside_conversation": "Μόνο όταν είμαι μέσα στη συνομιλία", - "condition_only_outside_conversation": "Μόνο όταν είμαι έξω από τη συνομιλία", - "condition_only_when_app_active": "Μόνο όταν το Snapchat είναι ενεργό", - "condition_only_when_app_inactive": "Μόνο όταν το Snapchat είναι ανενεργό", - "condition_no_push_notification_when_app_active": "Καμία ειδοποίηση push όταν το Snapchat είναι ενεργό", - "add_event_dialog_title": "Προσθήκη συμβάντος", - "event_type_label": "Τύπος συμβάντος", - "triggers_title": "Εναύσματα", - "conditions_title": "Συνθήκες", - "add_button": "Προσθήκη", - "default_rule_name": "Προσαρμοσμένος κανόνας", - "discard_changes_dialog_title": "Απόρριψη αλλαγών;", - "discard_changes_dialog_text": "Έχετε μη αποθηκευμένες αλλαγές. Είστε βέβαιοι ότι θέλετε να τις απορρίψετε;", - "discard_button": "Απόρριψη", - "cannot_save_rule_dialog_title": "Δεν είναι δυνατή η αποθήκευση του κανόνα", - "cannot_save_rule_dialog_text": "Ένας κανόνας πρέπει να έχει τουλάχιστον ένα συμβάν για να αποθηκευτεί.", - "duplicate_rule_name_dialog_title": "Διπλότυπο όνομα κανόνα", - "duplicate_rule_name_dialog_text": "Υπάρχει ήδη ένας κανόνας με αυτό το όνομα. Επιλέξτε ένα διαφορετικό όνομα.", - "delete_rule_dialog_title": "Διαγραφή κανόνα", - "delete_rule_dialog_text": "Είστε βέβαιοι ότι θέλετε να διαγράψετε αυτόν τον κανόνα;", - "new_rule_title": "Νέος κανόνας", - "edit_rule_title": "Επεξεργασία κανόνα", - "back_button_description": "Πίσω", - "save_button_description": "Αποθήκευση", - "general_section_title": "Γενικά", - "rule_name_label": "Όνομα κανόνα", - "author_name_label": "Όνομα συγγραφέα", - "scope_section_title": "Εύρος", - "scope_all": "Όλα", - "scope_whitelist": "Λευκή λίστα", - "scope_blacklist": "Μαύρη λίστα", - "select_friends_groups_button": "Επιλογή φίλων/ομάδων ({count})", - "events_section_title": "Συμβάντα", - "add_event_button": "Προσθήκη συμβάντος", - "no_events_text": "Κανένα συμβάν" - }, - "friend_tracker_catalog": { - "download_failed": "Η λήψη απέτυχε: {code}", - "error": "Σφάλμα: {message}", - "no_repos_added": "Δεν προστέθηκαν αποθετήρια.", - "no_rules_available": "Δεν υπάρχουν διαθέσιμοι κανόνες από κανένα αποθετήριο.", - "by_author": "από {author}", - "imported_button": "Εισήχθη", - "import_button": "Εισαγωγή", - "title": "Κατάλογος παρακολούθησης φίλων", - "manage_repos_description": "Διαχείριση αποθετηρίων" - }, - "friend_tracker_export": { - "title": "Εξαγωγή κανόνων", - "back_button_description": "Πίσω", - "exported_toast": "Οι κανόνες παρακολούθησης φίλων εξήχθησαν!", - "export_failed_toast": "Η εξαγωγή των κανόνων απέτυχε: {message}", - "save_button": "Αποθήκευση", - "expand_button_description": "Επέκταση" - }, - "friend_tracker_import": { - "title": "Εισαγωγή κανόνων", - "back_button_description": "Πίσω", - "imported_toast": "Οι κανόνες παρακολούθησης φίλων εισήχθησαν!", - "import_failed_toast": "Η εισαγωγή των κανόνων απέτυχε: {message}", - "confirm_button": "Επιβεβαίωση", - "expand_button_description": "Επέκταση" - }, - "friend_tracker_repos": { - "invalid_repo_title": "Μη έγκυρο αποθετήριο", - "add_repo_button": "Προσθήκη αποθετηρίου", - "add_repo_dialog_title": "Προσθήκη URL αποθετηρίου", - "repo_url_label": "URL αποθετηρίου", - "repo_added_toast": "Το αποθετήριο προστέθηκε με επιτυχία!", - "invalid_repo_error": "Αυτό δεν φαίνεται να είναι ένα έγκυρο αποθετήριο παρακολούθησης φίλων.", - "add_repo_failed_toast": "Η προσθήκη του αποθετηρίου απέτυχε: {message}", - "add_button": "Προσθήκη", - "no_repos_added": "Δεν προστέθηκαν αποθετήρια", - "remove_button": "Κατάργηση", - "remove_repo_dialog_title": "Κατάργηση αποθετηρίου", - "remove_repo_dialog_text": "Είστε βέβαιοι ότι θέλετε να καταργήσετε αυτό το αποθετήριο;" - }, - "navigation": { - "tracker_tab_label": "Παρακολούθηση", - "customize_bottom_bar_title": "Προσαρμογή κάτω γραμμής", - "customize_bottom_bar_subtitle": "Αναδιάταξη, προσθήκη ή κατάργηση καρτελών. Το πολύ πέντε.", - "shown_tabs_title": "Εμφανιζόμενες καρτέλες", - "no_tabs_selected_text": "Δεν επιλέχθηκαν καρτέλες", - "available_tabs_title": "Διαθέσιμες καρτέλες", - "reset_button": "Επαναφορά", - "done_button": "Έγινε" - }, - "scripting": { - "script_already_installed": "Το σενάριο έχει ήδη εγκατασταθεί!", - "downloading_script": "Λήψη σεναρίου...", - "script_downloaded": "Το σενάριο {name} λήφθηκε!", - "download_script_failed": "Η λήψη του σεναρίου απέτυχε. Ελέγξτε τα αρχεία καταγραφής για περισσότερες λεπτομέρειες", - "import_script_from_url_title": "Εισαγωγή σεναρίου από URL", - "import_script_warning": "Προειδοποίηση: Τα εισαγόμενα σενάρια μπορεί να είναι επιβλαβή για τη συσκευή σας. Εισαγάγετε σενάρια μόνο από αξιόπιστες πηγές.", - "enter_url_label": "Εισαγάγετε το URL εδώ:", - "script_imported": "Το σενάριο {name} εισήχθη!", - "import_failed": "Η εισαγωγή του σεναρίου απέτυχε. {message}. Ελέγξτε τα αρχεία καταγραφής για περισσότερες λεπτομέρειες", - "import_button": "Εισαγωγή", - "update_module_button": "Ενημέρωση λειτουργικής μονάδας", - "updating_script": "Ενημέρωση σεναρίου {name}...", - "module_not_found": "Η λειτουργική μονάδα δεν βρέθηκε", - "updated_script": "Ενημερώθηκε το {name} στην έκδοση {version}", - "update_module_failed": "Η ενημέρωση της λειτουργικής μονάδας απέτυχε. Ελέγξτε τα αρχεία καταγραφής για περισσότερες λεπτομέρειες", - "edit_module_button": "Επεξεργασία λειτουργικής μονάδας", - "open_module_failed": "Το άνοιγμα του αρχείου της λειτουργικής μονάδας απέτυχε. Ελέγξτε τα αρχεία καταγραφής για περισσότερες λεπτομέρειες", - "clear_module_data_button": "Εκκαθάριση δεδομένων λειτουργικής μονάδας", - "module_data_cleared": "Τα δεδομένα της λειτουργικής μονάδας εκκαθαρίστηκαν!", - "clear_module_data_failed": "Η εκκαθάριση των δεδομένων της λειτουργικής μονάδας απέτυχε. Ελέγξτε τα αρχεία καταγραφής για περισσότερες λεπτομέρειες", - "delete_module_button": "Διαγραφή λειτουργικής μονάδας", - "deleted_script": "Διαγράφηκε το σενάριο {name}!", - "delete_module_failed": "Η διαγραφή της λειτουργικής μονάδας απέτυχε. Ελέγξτε τα αρχεία καταγραφής για περισσότερες λεπτομέρειες", - "actions_title": "Ενέργειες", - "no_description": "Καμία περιγραφή", - "update_available": "Διαθέσιμη ενημέρωση: {version}", - "actions_button": "Ενέργειες", - "loaded_script": "Φορτώθηκε το σενάριο {name}", - "unloaded_script": "Αποφορτώθηκε το σενάριο {name}", - "enable_script_failed": "Η ενεργοποίηση του σεναρίου απέτυχε. Ελέγξτε τα αρχεία καταγραφής για περισσότερες λεπτομέρειες", - "disable_script_failed": "Η απενεργοποίηση του σεναρίου απέτυχε. Ελέγξτε τα αρχεία καταγραφής για περισσότερες λεπτομέρειες", - "select_scripts_folder_toast": "Επιλέξτε τον φάκελο των σεναρίων σας!", - "manage_repos_button": "Διαχείριση αποθετηρίων", - "import_from_url_button": "Εισαγωγή από URL", - "open_scripts_folder_button": "Άνοιγμα φακέλου σεναρίων", - "no_settings_for_module": "Αυτή η λειτουργική μονάδα δεν έχει ρυθμίσεις", - "installed_scripts_tab": "Εγκατεστημένα σενάρια", - "catalog_tab": "Κατάλογος", - "no_scripts_folder_selected_title": "Δεν επιλέχθηκε φάκελος σεναρίων", - "select_folder_button": "Επιλογή φακέλου", - "no_scripts_found_title": "Δεν βρέθηκαν σενάρια.", - "use_catalog_to_add_scripts": "Χρησιμοποιήστε την καρτέλα του καταλόγου για να προσθέσετε σενάρια!", - "ok_button_timeout": "Εντάξει ({timeout})", - "documentation_button": "Τεκμηρίωση", - "catalog": { - "script_already_installed": "Το σενάριο έχει ήδη εγκατασταθεί!", - "download_failed": "Η λήψη απέτυχε: {code}", - "script_downloaded": "Το σενάριο λήφθηκε!", - "could_not_create_file": "Δεν ήταν δυνατή η δημιουργία του αρχείου.", - "no_scripts_folder_selected": "Δεν επιλέχθηκε φάκελος σεναρίων.", - "error": "Σφάλμα: {message}", - "no_repos_added": "Δεν προστέθηκαν αποθετήρια.", - "repo_list_info": "Εδώ μπορείτε να βρείτε μια λίστα με αποθετήρια: ", - "link_text": "Σύνδεσμος", - "no_scripts_available": "Δεν υπάρχουν διαθέσιμα σενάρια από κανένα αποθετήριο.", - "by_author": "από {author}", - "version": "Έκδοση: {version}", - "installed_button": "Εγκατεστημένο", - "download_button": "Λήψη" - }, - "repos": { - "invalid_repo_title": "Μη έγκυρο αποθετήριο", - "add_repo_button": "Προσθήκη αποθετηρίου", - "add_repo_dialog_title": "Προσθήκη URL αποθετηρίου", - "repo_url_label": "URL αποθετηρίου", - "repo_added_toast": "Το αποθετήριο προστέθηκε με επιτυχία!", - "invalid_repo_error": "Αυτό δεν φαίνεται να είναι ένα έγκυρο αποθετήριο σεναρίων.", - "add_repo_failed_toast": "Η προσθήκη του αποθετηρίου απέτυχε: {message}", - "add_button": "Προσθήκη", - "no_repos_added": "Δεν προστέθηκαν αποθετήρια", - "remove_button": "Κατάργηση", - "remove_repo_dialog_title": "Κατάργηση αποθετηρίου", - "remove_repo_dialog_text": "Είστε βέβαιοι ότι θέλετε να καταργήσετε αυτό το αποθετήριο;" - } - }, - "features": { - "config_import": { - "title": "Επιβεβαίωση εισαγωγής", - "back_button_description": "Πίσω", - "config_imported_toast": "Η διαμόρφωση εισήχθη!", - "confirm_button": "Επιβεβαίωση", - "expand_button_description": "Επέκταση", - "enable_feature": "Ενεργοποίηση δυνατότητας", - "enabled": "Ενεργοποιημένο", - "disabled": "Απενεργοποιημένο" - }, - "config_export": { - "title": "Σύνοψη εξαγωγής", - "back_button_description": "Πίσω", - "save_button": "Αποθήκευση", - "expand_button_description": "Επέκταση", - "enable_feature": "Ενεργοποίηση δυνατότητας", - "enabled": "Ενεργοποιημένο", - "disabled": "Απενεργοποιημένο" - } - }, - "manage_repos": { - "title": "Διαχείριση αποθετηρίων {type}", - "add_repo_button": "Προσθήκη αποθετηρίου", - "add_repo_dialog_title": "Προσθήκη URL αποθετηρίου", - "repo_url_label": "URL αποθετηρίου", - "repo_added_successfully": "Το αποθετήριο προστέθηκε με επιτυχία!", - "add_repo_failed": "Η προσθήκη του αποθετηρίου απέτυχε: {message}", - "add_button": "Προσθήκη", - "no_repos_added": "Δεν προστέθηκαν αποθετήρια", - "remove_button": "Κατάργηση" - } - }, - "rules": { - "toasts": { - "enabled": "{ruleName} ενεργοποιήθηκε", - "disabled": "{ruleName} απενεργοποιήθηκε" - }, - "modes": { - "blacklist": "Λειτουργία μαύρης λίστας", - "whitelist": "Λειτουργία λευκής λίστας" - }, - "properties": { - "auto_download": { - "name": "Αυτόματη λήψη", - "description": "Αυτόματη λήψη των Snaps κατά την προβολή τους", - "options": { - "blacklist": "Εξαίρεση από την αυτόματη λήψη", - "whitelist": "Αυτόματη λήψη" - } - }, - "stealth": { - "name": "Λειτουργία μυστικότητας", - "description": "Αποτρέπει οποιονδήποτε να γνωρίζει ότι έχετε ανοίξει τα Snaps/Chats και τις συνομιλίες του", - "options": { - "blacklist": "Εξαίρεση από τη λειτουργία μυστικότητας", - "whitelist": "Λειτουργία μυστικότητας" - } - }, - "auto_save": { - "name": "Αυτόματη αποθήκευση", - "description": "Αποθηκεύει τα μηνύματα συνομιλίας κατά την προβολή τους", - "options": { - "blacklist": "Εξαίρεση από την αυτόματη αποθήκευση", - "whitelist": "Αυτόματη αποθήκευση" - } - }, - "unsaveable_messages": { - "name": "Μη αποθηκεύσιμα μηνύματα", - "description": "Αποτρέπει την αποθήκευση μηνυμάτων στη συνομιλία από άλλα άτομα", - "options": { - "blacklist": "Εξαίρεση από τα μη αποθηκεύσιμα μηνύματα", - "whitelist": "Μη αποθηκεύσιμα μηνύματα" - } - }, - "auto_open_snaps": { - "name": "Αυτόματο άνοιγμα Snaps", - "description": "Ανοίγει αυτόματα τα Snaps κατά τη λήψη τους", - "options": { - "blacklist": "Εξαίρεση από το αυτόματο άνοιγμα Snaps", - "whitelist": "Αυτόματο άνοιγμα Snaps" - } - }, - "hide_friend_feed": { - "name": "Απόκρυψη από τη ροή φίλων" - }, - "e2e_encryption": { - "name": "Χρήση κρυπτογράφησης E2E" - }, - "pin_conversation": { - "name": "Καρφίτσωμα συνομιλίας" - }, - "exclude_message_logger": { - "name": "Εξαίρεση από τον καταγραφέα μηνυμάτων" - } - } - }, - "actions": { - "clean_snapchat_cache": { - "name": "Εκκαθάριση προσωρινής μνήμης του Snapchat", - "description": "Εκκαθαρίζει την προσωρινή μνήμη του Snapchat" - }, - "manage_friend_list": { - "name": "Διαχείριση λίστας φίλων", - "description": "Εισαγωγή/εξαγωγή της λίστας φίλων σας κατά τη δημιουργία αντιγράφων ασφαλείας" - }, - "export_chat_messages": { - "name": "Εξαγωγή μηνυμάτων συνομιλίας", - "description": "Εξάγει τα μηνύματα συνομιλίας σε αρχείο JSON/HTML/TXT" - }, - "export_memories": { - "name": "Εξαγωγή αναμνήσεων", - "description": "Εξάγει τις αναμνήσεις σε αρχείο ZIP" - }, - "bulk_messaging_action": { - "name": "Μαζική ενέργεια μηνυμάτων", - "description": "Εκτελεί λειτουργίες όπως διαγραφή φίλων ή μαζική διαγραφή συνομιλιών" - }, - "regen_mappings": { - "name": "Επαναδημιουργία αντιστοιχίσεων", - "description": "Επαναδημιουργία αντιστοιχίσεων με μη αυτόματο τρόπο" - }, - "change_language": { - "name": "Αλλαγή γλώσσας", - "description": "Αλλαγή της γλώσσας του PurrfectSnap" - }, - "file_imports": { - "name": "Εισαγωγές αρχείων", - "description": "Εισαγωγή αρχείων για χρήση στο Snapchat" - }, - "friend_tracker": { - "name": "Παρακολούθηση φίλων", - "description": "Παρακολούθηση των φίλων σας στο Snapchat" - }, - "logger_history": { - "name": "Ιστορικό καταγραφέα", - "description": "Προβολή του ιστορικού των καταγεγραμμένων μηνυμάτων" - } - }, - "features": { - "notices": { - "unstable": "⚠️ Ασταθές", - "ban_risk": "⚠️ Αυτή η δυνατότητα μπορεί να προκαλέσει αποκλεισμό", - "internal_behavior": "⚠️ Αυτό μπορεί να διαταράξει την εσωτερική συμπεριφορά του Snapchat" - }, - "properties": { - "downloader": { - "name": "Λήπτης", - "description": "Λήψη πολυμέσων του Snapchat", - "properties": { - "save_folder": { - "name": "Φάκελος αποθήκευσης", - "description": "Επιλέξτε τον κατάλογο στον οποίο θα γίνει λήψη όλων των πολυμέσων" - }, - "auto_download_sources": { - "name": "Πηγές αυτόματης λήψης", - "description": "Επιλέξτε τις πηγές από τις οποίες θα γίνει αυτόματη λήψη" - }, - "prevent_self_auto_download": { - "name": "Αποτροπή αυτόματης λήψης από τον εαυτό σας", - "description": "Αποτρέπει την αυτόματη λήψη των δικών σας Snaps" - }, - "path_format": { - "name": "Μορφή διαδρομής", - "description": "Καθορίστε τη μορφή διαδρομής αρχείου" - }, - "allow_duplicate": { - "name": "Να επιτρέπονται τα διπλότυπα", - "description": "Επιτρέπει τη λήψη των ίδιων πολυμέσων πολλές φορές" - }, - "merge_overlays": { - "name": "Συγχώνευση επικαλύψεων", - "description": "Συνδυάζει το κείμενο και τα πολυμέσα ενός Snap σε ένα μόνο αρχείο" - }, - "force_image_format": { - "name": "Εξαναγκασμός μορφής εικόνας", - "description": "Εξαναγκάζει την αποθήκευση των εικόνων σε μια καθορισμένη μορφή" - }, - "force_voice_note_format": { - "name": "Εξαναγκασμός μορφής φωνητικής σημείωσης", - "description": "Εξαναγκάζει την αποθήκευση των φωνητικών σημειώσεων σε μια καθορισμένη μορφή" - }, - "auto_download_voice_notes": { - "name": "Αυτόματη λήψη φωνητικών σημειώσεων", - "description": "Κάνει αυτόματη λήψη των φωνητικών σημειώσεων κατά την αναπαραγωγή τους" - }, - "download_profile_pictures": { - "name": "Λήψη εικόνων προφίλ", - "description": "Σας επιτρέπει να κάνετε λήψη εικόνων προφίλ από τη σελίδα του προφίλ" - }, - "opera_download_button": { - "name": "Κουμπί λήψης Opera", - "description": "Προσθέτει ένα κουμπί λήψης στην επάνω δεξιά γωνία κατά την προβολή ενός Snap.\nΤο παρατεταμένο πάτημα στα κουμπιά θα εξαναγκάσει τη λήψη" - }, - "download_context_menu": { - "name": "Μενού περιβάλλοντος λήψης", - "description": "Σας επιτρέπει να κάνετε λήψη/προεπισκόπηση μηνυμάτων από μια συνομιλία ή μια ιστορία χρησιμοποιώντας το μενού περιβάλλοντος.\nΤο παρατεταμένο πάτημα στα κουμπιά θα εξαναγκάσει τη λήψη" - }, - "ffmpeg_options": { - "name": "Επιλογές FFmpeg", - "description": "Καθορίστε πρόσθετες επιλογές FFmpeg", - "properties": { - "threads": { - "name": "Νήματα", - "description": "Ο αριθμός των νημάτων που θα χρησιμοποιηθούν" - }, - "preset": { - "name": "Προεπιλογή", - "description": "Ορίστε την ταχύτητα της μετατροπής" - }, - "constant_rate_factor": { - "name": "Συντελεστής σταθερού ρυθμού", - "description": "Ορίστε τον συντελεστή σταθερού ρυθμού για τον κωδικοποιητή βίντεο\nΑπό 0 έως 51 για το libx264" - }, - "video_bitrate": { - "name": "Ρυθμός bit βίντεο", - "description": "Ορίστε τον ρυθμό bit του βίντεο (kbps)" - }, - "audio_bitrate": { - "name": "Ρυθμός bit ήχου", - "description": "Ορίστε τον ρυθμό bit του ήχου (kbps)" - }, - "custom_video_codec": { - "name": "Προσαρμοσμένος κωδικοποιητής βίντεο", - "description": "Ορίστε έναν προσαρμοσμένο κωδικοποιητή βίντεο (π.χ. libx264)" - }, - "custom_audio_codec": { - "name": "Προσαρμοσμένος κωδικοποιητής ήχου", - "description": "Ορίστε έναν προσαρμοσμένο κωδικοποιητή ήχου (π.χ. AAC)" - } - } - }, - "logging": { - "name": "Καταγραφή", - "description": "Εμφανίζει αναδυόμενα μηνύματα κατά τη λήψη πολυμέσων" - }, - "custom_path_format": { - "name": "Προσαρμοσμένη μορφή διαδρομής", - "description": "Καθορίστε μια προσαρμοσμένη μορφή διαδρομής για τα ληφθέντα πολυμέσα\n\nΔιαθέσιμες μεταβλητές:\n - %username%\n - %source%\n - %hash%\n - %date_time%" - } - } - }, - "user_interface": { - "name": "Διεπαφή χρήστη", - "description": "Αλλάξτε την εμφάνιση και την αίσθηση του Snapchat", - "properties": { - "enable_app_appearance": { - "name": "Ενεργοποίηση ρυθμίσεων εμφάνισης εφαρμογής", - "description": "Ενεργοποιεί την κρυφή ρύθμιση εμφάνισης εφαρμογής\nΕνδέχεται να μην απαιτείται σε νεότερες εκδόσεις του Snapchat" - }, - "friend_feed_message_preview": { - "name": "Προεπισκόπηση μηνύματος ροής φίλων", - "description": "Εμφανίζει μια προεπισκόπηση των τελευταίων μηνυμάτων στη ροή φίλων", - "properties": { - "amount": { - "name": "Ποσότητα", - "description": "Η ποσότητα των μηνυμάτων που θα προβληθούν" - } - } - }, - "snap_preview": { - "name": "Προεπισκόπηση Snap", - "description": "Εμφανίζει μια μικρή προεπισκόπηση δίπλα σε μη αναγνωσμένα Snaps στη συνομιλία" - }, - "bootstrap_override": { - "name": "Παράκαμψη Bootstrap", - "description": "Παρακάμπτει τις ρυθμίσεις bootstrap της διεπαφής χρήστη", - "properties": { - "app_appearance": { - "name": "Εμφάνιση εφαρμογής", - "description": "Ορίζει μια μόνιμη εμφάνιση εφαρμογής" - }, - "home_tab": { - "name": "Καρτέλα Αρχική", - "description": "Παρακάμπτει την καρτέλα εκκίνησης κατά το άνοιγμα του Snapchat" - } - } - }, - "force_amoled_theme": { - "name": "Σκοτεινή λειτουργία Amoled", - "description": "Χρησιμοποιεί ένα πραγματικά μαύρο φόντο για το σκούρο θέμα" - }, - "map_friend_nametags": { - "name": "Βελτιωμένες ετικέτες ονομάτων φίλων στον χάρτη", - "description": "Βελτιώνει τις ετικέτες ονομάτων των φίλων στο Snapmap" - }, - "prevent_message_list_auto_scroll": { - "name": "Αποτροπή αυτόματης κύλισης της λίστας μηνυμάτων", - "description": "Αποτρέπει την κύλιση της λίστας μηνυμάτων προς τα κάτω κατά την αποστολή/λήψη ενός μηνύματος" - }, - "streak_expiration_info": { - "name": "Εμφάνιση πληροφοριών λήξης σερί", - "description": "Εμφανίζει έναν χρονοδιακόπτη λήξης σερί δίπλα στον μετρητή σερί" - }, - "hide_friend_feed_entry": { - "name": "Απόκρυψη καταχώρισης ροής φίλων", - "description": "Αποκρύπτει έναν συγκεκριμένο φίλο από τη ροή φίλων\nΧρησιμοποιήστε την καρτέλα κοινωνικών δικτύων για να διαχειριστείτε αυτήν τη δυνατότητα" - }, - "hide_streak_restore": { - "name": "Απόκρυψη επαναφοράς σερί", - "description": "Αποκρύπτει το κουμπί Επαναφορά στη ροή φίλων" - }, - "hide_quick_add_suggestions": { - "name": "Απόκρυψη προτάσεων γρήγορης προσθήκης", - "description": "Καταργεί τις προτάσεις γρήγορης προσθήκης φίλων" - }, - "hide_story_suggestions": { - "name": "Απόκρυψη προτάσεων ιστορίας", - "description": "Καταργεί τις προτάσεις από τη σελίδα Ιστορίες" - }, - "hide_ui_components": { - "name": "Απόκρυψη στοιχείων διεπαφής χρήστη", - "description": "Επιλέξτε ποια στοιχεία διεπαφής χρήστη θα αποκρύψετε" - }, - "opera_media_quick_info": { - "name": "Γρήγορες πληροφορίες πολυμέσων Opera", - "description": "Εμφανίζει χρήσιμες πληροφορίες πολυμέσων, όπως ημερομηνία δημιουργίας, στο μενού περιβάλλοντος του προγράμματος προβολής opera" - }, - "old_bitmoji_selfie": { - "name": "Παλιά selfie Bitmoji", - "description": "Επαναφέρει τα selfie Bitmoji από παλαιότερες εκδόσεις του Snapchat" - }, - "disable_spotlight": { - "name": "Απενεργοποίηση Spotlight", - "description": "Απενεργοποιεί τη σελίδα Spotlight" - }, - "friend_feed_menu_buttons": { - "name": "Κουμπιά μενού ροής φίλων", - "description": "Επιλέξτε ποια κουμπιά θα εμφανίζονται στο μενού ροής φίλων" - }, - "auto_close_friend_feed_menu": { - "name": "Αυτόματο κλείσιμο μενού ροής φίλων", - "description": "Κλείνει αυτόματα το μενού ροής φίλων μετά το πάτημα ενός κουμπιού ρύθμισης" - }, - "vertical_story_viewer": { - "name": "Κάθετος προβολέας ιστοριών", - "description": "Ενεργοποιεί τον κάθετο προβολέα ιστοριών για όλες τις ιστορίες" - }, - "enable_friend_feed_menu_bar": { - "name": "Γραμμή μενού ροής φίλων", - "description": "Ενεργοποιεί τη νέα γραμμή μενού ροής φίλων" - }, - "message_indicators": { - "name": "Ενδείξεις μηνυμάτων", - "description": "Προσθέτει συγκεκριμένα εικονίδια ενδείξεων στα μηνύματα\nΣημείωση: Οι ενδείξεις ενδέχεται να μην είναι 100% ακριβείς" - }, - "stealth_mode_indicator": { - "name": "Ένδειξη λειτουργίας μυστικότητας", - "description": "Προσθέτει ένα emoji 👻 δίπλα στις συνομιλίες σε λειτουργία μυστικότητας" - }, - "edit_text_override": { - "name": "Παράκαμψη επεξεργασίας κειμένου", - "description": "Παρακάμπτει τη συμπεριφορά του πεδίου κειμένου" - }, - "prevent_forced_keyboard": { - "name": "Αποτροπή εξαναγκασμένου πληκτρολογίου", - "description": "Αποτρέπει το Snapchat από το να εμφανίζει αυτόματα το πληκτρολόγιο όταν ανοίγετε μια συνομιλία" - }, - "settings_menu": { - "name": "Μενού ρυθμίσεων", - "description": "Αλλάζει τον τρόπο με τον οποίο ανοίγετε το μενού του PurrfectSnap", - "options": { - "default": "Προεπιλογή", - "legacy": "Παλαιού τύπου" - } - } - } - }, - "messaging": { - "name": "Μηνύματα", - "description": "Αλλάξτε τον τρόπο με τον οποίο αλληλεπιδράτε με τους φίλους σας", - "properties": { - "bypass_screenshot_detection": { - "name": "Παράκαμψη ανίχνευσης στιγμιότυπου οθόνης", - "description": "Αποτρέπει το Snapchat από το να ανιχνεύει πότε τραβάτε ένα στιγμιότυπο οθόνης" - }, - "anonymous_story_viewing": { - "name": "Ανώνυμη προβολή ιστορίας", - "description": "Αποτρέπει οποιονδήποτε να γνωρίζει ότι έχετε δει την ιστορία του" - }, - "prevent_story_rewatch_indicator": { - "name": "Αποτροπή ένδειξης επανάληψης προβολής ιστορίας", - "description": "Αποτρέπει οποιονδήποτε να γνωρίζει ότι έχετε ξαναδεί την ιστορία του" - }, - "hide_peek_a_peek": { - "name": "Απόκρυψη Peek-a-Peek", - "description": "Αποτρέπει την αποστολή ειδοποίησης όταν σύρετε το μισό σε μια συνομιλία" - }, - "hide_bitmoji_presence": { - "name": "Απόκρυψη παρουσίας Bitmoji", - "description": "Αποτρέπει την εμφάνιση του Bitmoji σας ενώ βρίσκεστε στη συνομιλία" - }, - "hide_typing_notifications": { - "name": "Απόκρυψη ειδοποιήσεων πληκτρολόγησης", - "description": "Αποτρέπει οποιονδήποτε να γνωρίζει ότι πληκτρολογείτε ένα μήνυμα" - }, - "unlimited_snap_view_time": { - "name": "Απεριόριστος χρόνος προβολής Snap", - "description": "Καταργεί το χρονικό όριο για την προβολή των Snaps" - }, - "auto_mark_as_read": { - "name": "Αυτόματη σήμανση ως αναγνωσμένο", - "description": "Σημειώνει αυτόματα τα μηνύματα/snaps ως αναγνωσμένα ακόμη και όταν είναι ενεργοποιημένη η λειτουργία μυστικότητας" - }, - "mark_snap_as_seen_button": { - "name": "Κουμπί σήμανσης Snap ως αναγνωσμένου", - "description": "Προσθέτει ένα κουμπί για να επισημάνετε ένα Snap ως αναγνωσμένο κατά την προβολή του.\nΑυτό θα λειτουργήσει ακόμη και όταν είναι ενεργοποιημένη η λειτουργία μυστικότητας" - }, - "skip_when_marking_as_seen": { - "name": "Παράλειψη κατά τη σήμανση ως αναγνωσμένο", - "description": "Παραλείπει αυτόματα στο επόμενο Snap κατά τη σήμανση ενός Snap ως αναγνωσμένου.\nΧρήση σε συνδυασμό με το κουμπί Σήμανση Snap ως αναγνωσμένου" - }, - "loop_media_playback": { - "name": "Επανάληψη αναπαραγωγής πολυμέσων", - "description": "Επαναλαμβάνει την αναπαραγωγή πολυμέσων κατά την προβολή Snaps/Ιστοριών" - }, - "disable_replay_in_ff": { - "name": "Απενεργοποίηση επανάληψης στο FF", - "description": "Απενεργοποιεί τη δυνατότητα επανάληψης με παρατεταμένο πάτημα από τη ροή φίλων" - }, - "half_swipe_notifier": { - "name": "Ειδοποιητής μισού σάρωσης", - "description": "Σας ειδοποιεί όταν κάποιος σύρει το μισό σε μια συνομιλία", - "properties": { - "min_duration": { - "name": "Ελάχιστη διάρκεια", - "description": "Η ελάχιστη διάρκεια της μισής σάρωσης (σε δευτερόλεπτα)" - }, - "max_duration": { - "name": "Μέγιστη διάρκεια", - "description": "Η μέγιστη διάρκεια της μισής σάρωσης (σε δευτερόλεπτα)" - } - } - }, - "call_start_confirmation": { - "name": "Επιβεβαίωση έναρξης κλήσης", - "description": "Εμφανίζει ένα παράθυρο διαλόγου επιβεβαίωσης κατά την έναρξη μιας κλήσης" - }, - "unlimited_conversation_pinning": { - "name": "Απεριόριστο καρφίτσωμα συνομιλιών", - "description": "Σας επιτρέπει να καρφιτσώνετε έναν απεριόριστο αριθμό συνομιλιών τοπικά" - }, - "disable_snap_mode_restrictions": { - "name": "Απενεργοποίηση περιορισμών λειτουργίας Snap", - "description": "Σας επιτρέπει να βλέπετε αυτοκαταστρεφόμενα Snaps χωρίς περιορισμούς" - }, - "prevent_message_sending": { - "name": "Αποτροπή αποστολής μηνυμάτων", - "description": "Αποτρέπει την αποστολή ορισμένων τύπων μηνυμάτων" - }, - "friend_mutation_notifier": { - "name": "Ειδοποιητής μετάλλαξης φίλου", - "description": "Σας ειδοποιεί όταν κάτι αλλάζει στο προφίλ ενός φίλου" - }, - "better_notifications": { - "name": "Καλύτερες ειδοποιήσεις", - "description": "Προσθέτει περισσότερες πληροφορίες στις ληφθείσες ειδοποιήσεις", - "properties": { - "group_notifications": { - "name": "Ειδοποιήσεις ομάδας", - "description": "Ομαδοποιεί τις ειδοποιήσεις σε μία" - }, - "chat_preview": { - "name": "Προεπισκόπηση συνομιλίας", - "description": "Εμφανίζει μια προεπισκόπηση των ληφθέντων μηνυμάτων στην ειδοποίηση" - }, - "media_preview": { - "name": "Προεπισκόπηση πολυμέσων", - "description": "Εμφανίζει μια προεπισκόπηση των επιλεγμένων τύπων πολυμέσων στην ειδοποίηση" - }, - "media_caption": { - "name": "Λεζάντα πολυμέσων", - "description": "Εμφανίζει τη συνημμένη λεζάντα των πολυμέσων στην ειδοποίηση" - }, - "stacked_media_messages": { - "name": "Στοιβαγμένα μηνύματα πολυμέσων", - "description": "Συνδυάζει πολλά μηνύματα πολυμέσων σε μία ειδοποίηση κειμένου όταν δεν μπορούν να προβληθούν. Χρήση σε συνδυασμό με την προεπισκόπηση συνομιλίας" - }, - "friend_add_source": { - "name": "Πηγή προσθήκης φίλου", - "description": "Εμφανίζει την πηγή μιας αίτησης φιλίας στην ειδοποίηση" - }, - "reply_button": { - "name": "Κουμπί απάντησης", - "description": "Προσθέτει ένα κουμπί απάντησης στην ειδοποίηση" - }, - "smart_replies": { - "name": "Έξυπνες απαντήσεις", - "description": "Προσθέτει προτεινόμενες απαντήσεις στις ειδοποιήσεις (Android 10+). Χρήση σε συνδυασμό με το κουμπί απάντησης" - }, - "download_button": { - "name": "Κουμπί λήψης", - "description": "Σας επιτρέπει να κάνετε λήψη πολυμέσων από την ειδοποίηση" - }, - "mark_as_read_button": { - "name": "Κουμπί σήμανσης ως αναγνωσμένο", - "description": "Σας επιτρέπει να επισημάνετε ένα μήνυμα ως αναγνωσμένο από την ειδοποίηση" - }, - "mark_as_read_and_save_in_chat": { - "name": "Σήμανση ως αναγνωσμένο και αποθήκευση στη συνομιλία", - "description": "Προσθέτει ένα κουμπί σήμανσης ως αναγνωσμένο και αποθήκευσης στη συνομιλία στην ειδοποίηση" - } - } - }, - "notification_blacklist": { - "name": "Μαύρη λίστα ειδοποιήσεων", - "description": "Επιλέξτε ποιες ειδοποιήσεις θα αποκλειστούν" - }, - "message_logger": { - "name": "Καταγραφέας μηνυμάτων", - "description": "Αποτρέπει τη διαγραφή μηνυμάτων", - "properties": { - "keep_my_own_messages": { - "name": "Διατήρηση των δικών μου μηνυμάτων", - "description": "Αποτρέπει τη διαγραφή των δικών σας μηνυμάτων" - }, - "auto_purge": { - "name": "Αυτόματη εκκαθάριση", - "description": "Διαγράφει αυτόματα τα προσωρινά αποθηκευμένα μηνύματα που είναι παλαιότερα από το καθορισμένο χρονικό διάστημα" - }, - "message_filter": { - "name": "Φίλτρο μηνυμάτων", - "description": "Επιλέξτε ποια μηνύματα θα καταγραφούν (κενό για όλα τα μηνύματα)" - }, - "deleted_message_color": { - "name": "Χρώμα διαγραμμένου μηνύματος", - "description": "Ορίζει το χρώμα των διαγραμμένων μηνυμάτων" - } - } - }, - "auto_save_messages_in_conversations": { - "name": "Αυτόματη αποθήκευση μηνυμάτων", - "description": "Αποθηκεύει αυτόματα κάθε μήνυμα στις συνομιλίες" - }, - "gallery_media_send_override": { - "name": "Παράκαμψη αποστολής πολυμέσων γκαλερί", - "description": "Παραποιεί την πηγή πολυμέσων κατά την αποστολή από τη Γκαλερί" - }, - "strip_media_metadata": { - "name": "Αφαίρεση μεταδεδομένων πολυμέσων", - "description": "Αφαιρεί τα μεταδεδομένα των πολυμέσων πριν από την αποστολή τους ως μήνυμα" - }, - "bypass_message_retention_policy": { - "name": "Παράκαμψη πολιτικής διατήρησης μηνυμάτων", - "description": "Αποτρέπει τη διαγραφή μηνυμάτων μετά την προβολή τους" - }, - "bypass_message_action_restrictions": { - "name": "Παράκαμψη περιορισμών ενέργειας μηνυμάτων", - "description": "Σας επιτρέπει να αντιδράσετε σε ένα snap χωρίς να το έχετε ανοίξει ή να αποθηκεύσετε ένα μη αποθηκεύσιμο μήνυμα" - }, - "remove_groups_locked_status": { - "name": "Κατάργηση κατάστασης κλειδώματος ομάδων", - "description": "Σας επιτρέπει να βλέπετε πληροφορίες ομάδας μετά την αποβολή σας" - }, - "double_tap_chat_action": { - "name": "Ενέργεια διπλού πατήματος στη συνομιλία", - "description": "Εκτελεί μια προσαρμοσμένη ενέργεια όταν πατάτε δύο φορές ένα μήνυμα στη συνομιλία" - }, - "double_tap_chat_action_custom_emoji": { - "name": "Προσαρμοσμένη αντίδραση emoji σε ενέργεια διπλού πατήματος στη συνομιλία", - "description": "Ορίζει μια προσαρμοσμένη αντίδραση emoji για την ενέργεια διπλού πατήματος στη συνομιλία" - } - } - }, - "global": { - "name": "Παγκόσμιο", - "description": "Προσαρμόστε τις παγκόσμιες ρυθμίσεις του Snapchat", - "properties": { - "better_location": { - "name": "Καλύτερη τοποθεσία", - "description": "Βελτιώνει την τοποθεσία του Snapchat", - "properties": { - "spoof_location": { - "name": "Παραποίηση τοποθεσίας", - "description": "Παραποιεί την τοποθεσία σας σε μια καθορισμένη" - }, - "coordinates": { - "name": "Συντεταγμένες", - "description": "Ορίστε τις συντεταγμένες της παραποιημένης τοποθεσίας" - }, - "walk_radius": { - "name": "Ακτίνα περπατήματος", - "description": "Περπατήστε τυχαία μέσα σε αυτήν την ακτίνα (πόδια)" - }, - "always_update_location": { - "name": "Πάντα ενημέρωση τοποθεσίας", - "description": "Εξαναγκάζει το Snapchat να ενημερώνει την τοποθεσία ακόμη και αν δεν λαμβάνονται δεδομένα GPS" - }, - "suspend_location_updates": { - "name": "Αναστολή ενημερώσεων τοποθεσίας", - "description": "Αποτρέπει την ενημέρωση της τοποθεσίας σας" - }, - "spoof_battery_level": { - "name": "Παραποίηση επιπέδου μπαταρίας", - "description": "Παραποιεί το επίπεδο της μπαταρίας της συσκευής σας στον χάρτη\nΗ τιμή πρέπει να είναι μεταξύ 0 και 100" - }, - "spoof_headphones": { - "name": "Παραποίηση ακουστικών", - "description": "Παραποιεί την κατάσταση ακρόασης μουσικής στον χάρτη" - }, - "show_battery_level": { - "name": "Εμφάνιση επιπέδου μπαταρίας", - "description": "Εμφανίζει το επίπεδο της μπαταρίας των φίλων σας στον χάρτη" - } - } - }, - "snapchat_plus": { - "name": "Snapchat Plus", - "description": "Ενεργοποιεί τις δυνατότητες του Snapchat Plus\nΟρισμένες δυνατότητες από την πλευρά του διακομιστή ενδέχεται να μην λειτουργούν" - }, - "media_upload_quality": { - "name": "Ποιότητα μεταφόρτωσης πολυμέσων", - "description": "Παρακάμπτει την ποιότητα μεταφόρτωσης πολυμέσων", - "properties": { - "force_video_upload_source_quality": { - "name": "Εξαναγκασμός ποιότητας πηγής μεταφόρτωσης βίντεο", - "description": "Εξαναγκάζει το Snapchat να χρησιμοποιεί την ποιότητα της πηγής κατά τη μεταφόρτωση βίντεο\nΛάβετε υπόψη ότι αυτό ενδέχεται να μην αφαιρέσει τα μεταδεδομένα από τα πολυμέσα" - }, - "disable_image_compression": { - "name": "Απενεργοποίηση συμπίεσης εικόνας", - "description": "Απενεργοποιεί τη συμπίεση εικόνας κατά τη μεταφόρτωση πολυμέσων" - }, - "custom_image_upload_format": { - "name": "Προσαρμοσμένη μορφή μεταφόρτωσης εικόνας", - "description": "Ορίζει μια προσαρμοσμένη μορφή μεταφόρτωσης εικόνας\nΕπιλέξτε μια μορφή χωρίς απώλειες (όπως PNG) για την καλύτερη ποιότητα" - } - } - }, - "disable_confirmation_dialogs": { - "name": "Απενεργοποίηση παραθύρων διαλόγου επιβεβαίωσης", - "description": "Επιβεβαιώνει αυτόματα τις επιλεγμένες ενέργειες" - }, - "auto_updater": { - "name": "Αυτόματος ενημερωτής", - "description": "Ελέγχει αυτόματα για νέες ενημερώσεις" - }, - "disable_metrics": { - "name": "Απενεργοποίηση μετρήσεων", - "description": "Αποκλείει την αποστολή συγκεκριμένων αναλυτικών δεδομένων στο Snapchat" - }, - "disable_story_sections": { - "name": "Απενεργοποίηση ενοτήτων ιστορίας", - "description": "Καταργεί ενότητες από τη σελίδα Ιστορίες\nΕνδέχεται να απαιτείται ανανέωση για να λειτουργήσει σωστά" - }, - "block_ads": { - "name": "Αποκλεισμός διαφημίσεων", - "description": "Αποτρέπει την εμφάνιση διαφημίσεων" - }, - "disable_custom_tabs": { - "name": "Απενεργοποίηση προσαρμοσμένων καρτελών", - "description": "Ανοίγει συνδέσμους σε υποστηριζόμενες εφαρμογές αντί για το πρόγραμμα περιήγησης ιστού" - }, - "disable_permission_requests": { - "name": "Απενεργοποίηση αιτημάτων άδειας", - "description": "Αποτρέπει το Snapchat από το να ζητά συγκεκριμένες άδειες" - }, - "disable_memories_snap_feed": { - "name": "Απενεργοποίηση ροής Snap αναμνήσεων", - "description": "Αποτρέπει το Snapchat από το να εμφανίζει πρόσφατες αναμνήσεις όταν σύρετε προς τα πάνω στην κάμερα" - }, - "spotlight_comments_username": { - "name": "Όνομα χρήστη σχολίων Spotlight", - "description": "Εμφανίζει το όνομα χρήστη του συγγραφέα στα σχόλια του Spotlight" - }, - "bypass_video_length_restriction": { - "name": "Παράκαμψη περιορισμού μήκους βίντεο", - "description": "Μεμονωμένο: στέλνει ένα μεμονωμένο βίντεο\nΔιαίρεση: διαίρεση βίντεο μετά την επεξεργασία" - }, - "default_video_playback_rate": { - "name": "Προεπιλεγμένος ρυθμός αναπαραγωγής βίντεο", - "description": "Ορίζει την προεπιλεγμένη ταχύτητα για την αναπαραγωγή βίντεο\nΗ τιμή πρέπει να είναι μεταξύ 0,1 και 4,0" - }, - "video_playback_rate_slider": { - "name": "Ρυθμιστικό ρυθμού αναπαραγωγής βίντεο", - "description": "Προσθέτει ένα ρυθμιστικό στο μενού περιβάλλοντος του opera για να αλλάξετε τον ρυθμό αναπαραγωγής του βίντεο\nΣημείωση: Οι αλλαγές ισχύουν μόνο για τα επόμενα βίντεο" - }, - "disable_google_play_dialogs": { - "name": "Απενεργοποίηση παραθύρων διαλόγου των Υπηρεσιών Google Play", - "description": "Αποτροπή εμφάνισης παραθύρων διαλόγου διαθεσιμότητας των Υπηρεσιών Google Play" - }, - "default_volume_controls": { - "name": "Προεπιλεγμένα στοιχεία ελέγχου έντασης", - "description": "Εξαναγκάζει το Snapchat να χρησιμοποιεί τα στοιχεία ελέγχου έντασης του συστήματος" - }, - "disable_telecom_framework": { - "name": "Απενεργοποίηση πλαισίου τηλεπικοινωνιών", - "description": "Αποτρέπει το Snapchat από τη χρήση του πλαισίου τηλεπικοινωνιών του Android\nΑυτό σας επιτρέπει να ακούτε μουσική κατά τη διάρκεια μιας κλήσης" - }, - "hide_active_music": { - "name": "Απόκρυψη ενεργής μουσικής", - "description": "Αποτρέπει το Snapchat από το να γνωρίζει ότι ακούτε μουσική\nΑυτό θα σας επιτρέψει να τραβήξετε snaps χρησιμοποιώντας τα κουμπιά ελέγχου έντασης ενώ ακούτε μουσική" - }, - "disable_snap_splitting": { - "name": "Απενεργοποίηση διαίρεσης Snap", - "description": "Αποτρέπει τη διαίρεση των Snaps σε πολλά μέρη\nΟι εικόνες που στέλνετε θα μετατραπούν σε βίντεο" - } - } - }, - "rules": { - "name": "Κανόνες", - "description": "Διαχείριση αυτόματων δυνατοτήτων για μεμονωμένα άτομα" - }, - "camera": { - "name": "Κάμερα", - "description": "Προσαρμόστε τις σωστές ρυθμίσεις για το τέλειο snap", - "properties": { - "disable_cameras": { - "name": "Απενεργοποίηση καμερών", - "description": "Αποτρέπει το Snapchat από τη χρήση των επιλεγμένων καμερών" - }, - "black_photos": { - "name": "Μαύρες φωτογραφίες", - "description": "Αντικαθιστά τις ληφθείσες φωτογραφίες με ένα μαύρο φόντο\nΤα βίντεο δεν επηρεάζονται" - }, - "immersive_camera_preview": { - "name": "Καθηλωτική προεπισκόπηση", - "description": "Αποτρέπει το Snapchat από την περικοπή της προεπισκόπησης της κάμερας\nΑυτό μπορεί να προκαλέσει τρεμόπαιγμα της κάμερας σε ορισμένες συσκευές" - }, - "override_front_resolution": { - "name": "Παράκαμψη ανάλυσης μπροστινής κάμερας", - "description": "Παρακάμπτει την ανάλυση της κάμερας για την μπροστινή κάμερα" - }, - "override_back_resolution": { - "name": "Παράκαμψη ανάλυσης πίσω κάμερας", - "description": "Παρακάμπτει την ανάλυση της κάμερας για την πίσω κάμερα" - }, - "custom_resolution": { - "name": "Προσαρμοσμένη ανάλυση", - "description": "Ορίζει μια προσαρμοσμένη ανάλυση κάμερας, πλάτος x ύψος (π.χ. 1920x1080).\nΗ προσαρμοσμένη ανάλυση πρέπει να υποστηρίζεται από τη συσκευή σας" - }, - "front_custom_frame_rate": { - "name": "Προσαρμοσμένος ρυθμός καρέ μπροστινής κάμερας", - "description": "Παρακάμπτει τον ρυθμό καρέ της μπροστινής κάμερας" - }, - "back_custom_frame_rate": { - "name": "Προσαρμοσμένος ρυθμός καρέ πίσω κάμερας", - "description": "Παρακάμπτει τον ρυθμό καρέ της πίσω κάμερας" - }, - "force_camera_source_encoding": { - "name": "Εξαναγκασμός κωδικοποίησης πηγής κάμερας", - "description": "Εξαναγκάζει την κωδικοποίηση της πηγής της κάμερας" - }, - "startup_default_camera": { - "name": "Προεπιλεγμένη κάμερα εκκίνησης", - "description": "Ορίζει την προεπιλεγμένη κάμερα κατά το άνοιγμα του Snapchat" - }, - "hevc_recording": { - "name": "Εγγραφή HEVC", - "description": "Χρησιμοποιεί τον κωδικοποιητή HEVC (H.265) για εγγραφή βίντεο" - } - } - }, - "streaks_reminder": { - "name": "Υπενθύμιση σερί", - "description": "Σας ειδοποιεί περιοδικά για τα σερί σας", - "properties": { - "interval": { - "name": "Διάστημα", - "description": "Το διάστημα μεταξύ κάθε υπενθύμισης (ώρες)" - }, - "remaining_hours": { - "name": "Υπολειπόμενος χρόνος", - "description": "Ο υπολειπόμενος χρόνος πριν από την εμφάνιση της ειδοποίησης (ώρες)" - }, - "group_notifications": { - "name": "Ειδοποιήσεις ομάδας", - "description": "Ομαδοποιεί τις ειδοποιήσεις σε μία" - } - } - }, - "experimental": { - "name": "Πειραματικό", - "description": "Πειραματικές δυνατότητες", - "properties": { - "native_hooks": { - "name": "Εγγενείς αγκίστρια", - "description": "Μη ασφαλείς δυνατότητες που συνδέονται με τον εγγενή κώδικα του Snapchat", - "properties": { - "composer_hooks": { - "name": "Αγκίστρια Composer", - "description": "Εισάγει κώδικα στο πλαίσιο διεπαφής χρήστη πολλαπλών πλατφορμών του Composer", - "properties": { - "show_first_created_username": { - "name": "Εμφάνιση πρώτου δημιουργημένου ονόματος χρήστη", - "description": "Εμφανίζει το πρώτο δημιουργημένο όνομα χρήστη δίπλα στο τρέχον όνομα χρήστη στη σελίδα του προφίλ" - }, - "bypass_camera_roll_limit": { - "name": "Παράκαμψη ορίου ρολού κάμερας", - "description": "Αυξάνει τη μέγιστη ποσότητα πολυμέσων που μπορείτε να στείλετε από το ρολό της κάμερας" - }, - "custom_self_destruct_snap_delay": { - "name": "Προσαρμοσμένη καθυστέρηση αυτοκαταστροφής Snap", - "description": "Παρέχει περισσότερες επιλογές για τον χρονοδιακόπτη αυτοκαταστροφής κατά την αποστολή ενός Snap" - }, - "composer_console": { - "name": "Κονσόλα Composer", - "description": "Σας επιτρέπει να εκτελείτε κώδικα JavaScript στο Composer (μόνο arm64)" - }, - "composer_logs": { - "name": "Αρχεία καταγραφής Composer", - "description": "Ανακατευθύνει τα αρχεία καταγραφής της κονσόλας του Composer στο PurrfectSnap" - } - } - }, - "disable_bitmoji": { - "name": "Απενεργοποίηση Bitmoji", - "description": "Απενεργοποιεί το Bitmoji του προφίλ φίλων" - }, - "custom_emoji_font": { - "name": "Προσαρμοσμένη γραμματοσειρά emoji", - "description": "Σας επιτρέπει να χρησιμοποιείτε μια προσαρμοσμένη γραμματοσειρά emoji. Λειτουργεί μόνο με γραμματοσειρές .ttf" - }, - "custom_shared_library": { - "name": "Προσαρμοσμένη κοινόχρηστη βιβλιοθήκη", - "description": "Φορτώνει μια προσαρμοσμένη κοινόχρηστη βιβλιοθήκη στο Snapchat. Αυτή η δυνατότητα είναι μόνο για δοκιμαστικούς σκοπούς" - } - } - }, - "spoof": { - "name": "Παραποίηση", - "description": "Παραποιήστε διάφορες πληροφορίες για εσάς", - "properties": { - "play_store_installer_package_name": { - "name": "Όνομα πακέτου εγκατάστασης του Play Store", - "description": "Παρακάμπτει το όνομα του πακέτου εγκατάστασης σε com.android.vending" - }, - "remove_vpn_transport_flag": { - "name": "Κατάργηση σημαίας μεταφοράς VPN", - "description": "Αποτρέπει το Snapchat από την ανίχνευση VPN" - }, - "remove_mock_location_flag": { - "name": "Κατάργηση σημαίας ψευδούς τοποθεσίας", - "description": "Αποτρέπει το Snapchat από την ανίχνευση ψευδούς τοποθεσίας" - } - } - }, - "convert_message_locally": { - "name": "Μετατροπή μηνύματος τοπικά", - "description": "Μετατρέπει τα snaps σε εξωτερικά πολυμέσα συνομιλίας τοπικά. Αυτό εμφανίζεται στο μενού περιβάλλοντος λήψης συνομιλίας" - }, - "media_file_picker": { - "name": "Επιλογέας αρχείων πολυμέσων", - "description": "Σας επιτρέπει να επιλέξετε οποιοδήποτε αρχείο βίντεο/ήχου από τη γκαλερί" - }, - "story_logger": { - "name": "Καταγραφέας ιστοριών", - "description": "Παρέχει ένα ιστορικό των ιστοριών των φίλων" - }, - "call_recorder": { - "name": "Εγγραφέας κλήσεων", - "description": "Καταγράφει αυτόματα τις ηχητικές κλήσεις" - }, - "account_switcher": { - "name": "Εναλλαγή λογαριασμών", - "description": "Σας επιτρέπει να κάνετε εναλλαγή μεταξύ λογαριασμών χωρίς να αποσυνδεθείτε\nΠατήστε παρατεταμένα το εικονίδιο αναζήτησης δίπλα στο προφίλ σας Bitmoji για να ανοίξετε το μενού\nΣημείωση: Αυτή η δυνατότητα είναι πειραματική και πιθανότατα θα αλλάξει στο μέλλον", - "properties": { - "auto_backup_current_account": { - "name": "Αυτόματη δημιουργία αντιγράφων ασφαλείας του τρέχοντος λογαριασμού", - "description": "Δημιουργεί αυτόματα αντίγραφα ασφαλείας του τρέχοντος λογαριασμού κατά την αποσύνδεση ή την εναλλαγή λογαριασμών" - } - } - }, - "better_transcript": { - "name": "Καλύτερη μεταγραφή", - "description": "Βελτιώνει τη μεταγραφή των φωνητικών σημειώσεων", - "properties": { - "force_transcription": { - "name": "Εξαναγκασμός μεταγραφής φωνητικής σημείωσης", - "description": "Επιτρέπει τη μεταγραφή όλων των φωνητικών σημειώσεων" - }, - "preferred_transcription_lang": { - "name": "Προτιμώμενη γλώσσα μεταγραφής", - "description": "Η προτιμώμενη γλώσσα για τη μεταγραφή της φωνητικής σημείωσης (π.χ. EN, ES, FR)" - }, - "notification_transcript": { - "name": "Μεταγραφή ειδοποίησης", - "description": "Μεταγράφει τις φωνητικές σημειώσεις στις ειδοποιήσεις\nΑυτή η δυνατότητα απαιτεί την ενεργοποίηση της δυνατότητας Προεπισκόπηση συνομιλίας στις Καλύτερες ειδοποιήσεις" - } - } - }, - "voice_note_auto_play": { - "name": "Αυτόματη αναπαραγωγή φωνητικής σημείωσης", - "description": "Αναπαράγει αυτόματα την επόμενη φωνητική σημείωση μετά την ολοκλήρωση της τρέχουσας" - }, - "friend_notes": { - "name": "Σημειώσεις φίλων", - "description": "Σας επιτρέπει να προσθέτετε σημειώσεις στα προφίλ των φίλων" - }, - "cof_experiments": { - "name": "Πειράματα COF", - "description": "Ενεργοποιεί ακυκλοφόρητες/beta δυνατότητες του Snapchat" - }, - "context_menu_fix": { - "name": "Διόρθωση μενού περιβάλλοντος", - "description": "Προσπάθεια επισκευής του μενού ροής φίλων, καθώς όταν η συσκευή είναι εκτός σύνδεσης, δεν μπορεί να εμφανιστεί σωστά" - }, - "app_lock": { - "name": "Κλείδωμα εφαρμογής", - "description": "Αποτρέπει την πρόσβαση στο Snapchat χωρίς κωδικό πρόσβασης", - "properties": { - "lock_on_resume": { - "name": "Κλείδωμα κατά την επαναφορά", - "description": "Κλειδώνει την εφαρμογή όταν ανοίγει ξανά" - } - } - }, - "infinite_story_boost": { - "name": "Απεριόριστη ενίσχυση ιστορίας", - "description": "Παράκαμψη της καθυστέρησης ορίου ενίσχυσης ιστορίας" - }, - "meo_passcode_bypass": { - "name": "Παράκαμψη κωδικού πρόσβασης My Eyes Only", - "description": "Παράκαμψη του κωδικού πρόσβασης My Eyes Only\nΑυτό θα λειτουργήσει μόνο εάν ο κωδικός πρόσβασης έχει εισαχθεί σωστά προηγουμένως" - }, - "no_friend_score_delay": { - "name": "Καμία καθυστέρηση βαθμολογίας φίλου", - "description": "Καταργεί την καθυστέρηση κατά την προβολή της βαθμολογίας ενός φίλου" - }, - "best_friend_pinning": { - "name": "Καρφίτσωμα καλύτερου φίλου", - "description": "Σας επιτρέπει να καρφιτσώσετε έναν φίλο ως τον νούμερο ένα καλύτερό σας φίλο. Σημείωση: Μόνο εσείς μπορείτε να δείτε τον καρφιτσωμένο καλύτερό σας φίλο" - }, - "e2ee": { - "name": "Κρυπτογράφηση από άκρο σε άκρο", - "description": "Κρυπτογραφεί τα μηνύματά σας με AES χρησιμοποιώντας ένα κοινό μυστικό κλειδί\nΒεβαιωθείτε ότι έχετε αποθηκεύσει το κλειδί σας κάπου ασφαλές!", - "properties": { - "encrypted_message_indicator": { - "name": "Ένδειξη κρυπτογραφημένου μηνύματος", - "description": "Προσθέτει ένα emoji 🔒 δίπλα στα κρυπτογραφημένα μηνύματα" - }, - "force_message_encryption": { - "name": "Εξαναγκασμός κρυπτογράφησης μηνυμάτων", - "description": "Αποτρέπει την αποστολή κρυπτογραφημένων μηνυμάτων σε άτομα που δεν έχουν ενεργοποιημένη την κρυπτογράφηση από άκρο σε άκρο μόνο όταν επιλέγονται πολλές συνομιλίες" - } - } - }, - "add_friend_source_spoof": { - "name": "Παραποίηση πηγής προσθήκης φίλου", - "description": "Παραποιεί την πηγή μιας αίτησης φιλίας" - }, - "hidden_snapchat_plus_features": { - "name": "Κρυφές δυνατότητες του Snapchat Plus", - "description": "Ενεργοποιεί ακυκλοφόρητες/beta δυνατότητες του Snapchat Plus\nΕνδέχεται να μην λειτουργεί σε παλαιότερες εκδόσεις του Snapchat" - }, - "custom_streaks_expiration_format": { - "name": "Προσαρμοσμένη μορφή λήξης σερί", - "description": "Προσαρμόζει τη μορφή λήξης των σερί\n\nΔιαθέσιμες μεταβλητές:\n - %c: Αριθμός σερί\n - %e: Emoji κλεψύδρας\n - %d: Ημέρες\n - %h: Ώρες\n - %m: Λεπτά\n - %s: Δευτερόλεπτα\n - %w: Υπολειπόμενος χρόνος" - }, - "prevent_forced_logout": { - "name": "Αποτροπή εξαναγκασμένης αποσύνδεσης", - "description": "Αποτρέπει το Snapchat από το να σας αποσυνδέσει όταν συνδέεστε σε άλλη συσκευή" - }, - "snapscore_changes": { - "name": "Αλλαγές Snapscore", - "description": "Παρακολουθεί τις αλλαγές στο Snapscore των φίλων\nΧρησιμοποιήστε αυτήν τη δυνατότητα μόνο σε νεότερες εκδόσεις του Snapchat" - } - } - }, - "scripting": { - "name": "Δημιουργία σεναρίων", - "description": "Εκτελέστε προσαρμοσμένα σενάρια για να επεκτείνετε το PurrfectSnap", - "properties": { - "developer_mode": { - "name": "Λειτουργία προγραμματιστή", - "description": "Εμφανίζει πληροφορίες εντοπισμού σφαλμάτων στη διεπαφή χρήστη του Snapchat" - }, - "module_folder": { - "name": "Φάκελος λειτουργικής μονάδας", - "description": "Ο φάκελος όπου βρίσκονται τα σενάρια" - }, - "auto_reload": { - "name": "Αυτόματη επαναφόρτωση", - "description": "Επαναφορτώνει αυτόματα τα σενάρια όταν αλλάζουν" - }, - "integrated_ui": { - "name": "Ενσωματωμένη διεπαφή χρήστη", - "description": "Επιτρέπει στα σενάρια να προσθέτουν προσαρμοσμένα στοιχεία διεπαφής χρήστη στο Snapchat" - }, - "disable_log_anonymization": { - "name": "Απενεργοποίηση ανωνυμοποίησης αρχείων καταγραφής", - "description": "Απενεργοποιεί την ανωνυμοποίηση των αρχείων καταγραφής" - }, - "disable_optimization": { - "name": "Απενεργοποίηση βελτιστοποίησης", - "description": "Απενεργοποιεί τη βελτιστοποίηση των σεναρίων. Αυτό μπορεί να προκαλέσει προβλήματα απόδοσης." - } - } - }, - "friend_tracker": { - "name": "Παρακολούθηση φίλων", - "description": "Καταγράφει τη δραστηριότητα των φίλων στο Snapchat", - "properties": { - "record_messaging_events": { - "name": "Καταγραφή συμβάντων μηνυμάτων", - "description": "Καταγράφει συμβάντα μηνυμάτων όπως το άνοιγμα ενός snap, την ανάγνωση ενός μηνύματος κ.λπ." - }, - "allow_running_in_background": { - "name": "Να επιτρέπεται η εκτέλεση στο παρασκήνιο", - "description": "Επιτρέπει στον ιχνηλάτη να εκτελείται στο παρασκήνιο. Σημείωση: Αυτό θα εξαντλήσει σημαντικά την μπαταρία σας" - }, - "auto_purge": { - "name": "Αυτόματη εκκαθάριση", - "description": "Διαγράφει αυτόματα τα προσωρινά αποθηκευμένα συμβάντα που είναι παλαιότερα από το καθορισμένο χρονικό διάστημα" - } - } - } - }, - "options": { - "app_appearance": { - "always_light": "Πάντα φωτεινό", - "always_dark": "Πάντα σκοτεινό" - }, - "friend_feed_menu_buttons": { - "auto_download": "⬇️ Αυτόματη λήψη", - "auto_save": "💬 Αυτόματη αποθήκευση μηνυμάτων", - "unsaveable_messages": "⬇️ Μη αποθηκεύσιμα μηνύματα", - "auto_open_snaps": "📸 Αυτόματο άνοιγμα Snaps", - "stealth": "👻 Λειτουργία μυστικότητας", - "mark_snaps_as_seen": "👀 Σήμανση Snaps ως αναγνωσμένων", - "mark_stories_as_seen_locally": "👀 Σήμανση ιστοριών ως αναγνωσμένων τοπικά", - "conversation_info": "🧑‍🤝‍🧑 Πληροφορίες συνομιλίας", - "e2e_encryption": "🔒 Χρήση κρυπτογράφησης E2E" - }, - "path_format": { - "create_author_folder": "Δημιουργία φακέλου για κάθε συγγραφέα", - "create_source_folder": "Δημιουργία φακέλου για κάθε τύπο πηγής πολυμέσων", - "append_hash": "Προσθήκη ενός μοναδικού hash στο όνομα του αρχείου", - "append_source": "Προσθήκη της πηγής πολυμέσων στο όνομα του αρχείου", - "append_username": "Προσθήκη του ονόματος χρήστη στο όνομα του αρχείου", - "append_date_time": "Προσθήκη της ημερομηνίας και της ώρας στο όνομα του αρχείου" - }, - "auto_download_sources": { - "friend_snaps": "Snaps φίλων", - "friend_stories": "Ιστορίες φίλων", - "public_stories": "Δημόσιες ιστορίες", - "spotlight": "Κέντρο προσοχής" - }, - "logging": { - "started": "Ξεκίνησε", - "success": "Επιτυχία", - "progress": "Πρόοδος", - "failure": "Αποτυχία" - }, - "notifications": { - "chat_screenshot": "Στιγμιότυπο οθόνης", - "chat_screen_record": "Εγγραφή οθόνης", - "snap_replay": "Επανάληψη Snap", - "camera_roll_save": "Αποθήκευση στο ρολό της κάμερας", - "chat": "Συνομιλία", - "chat_reply": "Απάντηση συνομιλίας", - "snap": "Θραύση", - "typing": "Πληκτρολογεί", - "stories": "Ιστορίες", - "speaking": "Μιλάει", - "chat_reaction": "Αντίδραση DM", - "group_chat_reaction": "Αντίδραση ομάδας", - "initiate_audio": "Εισερχόμενη ηχητική κλήση", - "abandon_audio": "Αναπάντητη ηχητική κλήση", - "initiate_video": "Εισερχόμενη βιντεοκλήση", - "abandon_video": "Αναπάντητη βιντεοκλήση", - "map_live_location": "Ζωντανή τοποθεσία στον χάρτη" - }, - "gallery_media_send_override": { - "always_ask": "Πάντα να ρωτάτε", - "ORIGINAL": "Πρωτότυπο πολυμέσο", - "NOTE": "Ηχητική σημείωση", - "SNAP": "Θραύση", - "SAVEABLE_SNAP": "Αποθηκεύσιμο Snap" - }, - "strip_media_metadata": { - "hide_caption_text": "Απόκρυψη κειμένου λεζάντας", - "hide_snap_filters": "Απόκρυψη φίλτρων Snap", - "hide_extras": "Απόκρυψη πρόσθετων (π.χ. αναφορές)", - "remove_audio_note_duration": "Κατάργηση διάρκειας ηχητικής σημείωσης", - "remove_audio_note_transcript_capability": "Κατάργηση δυνατότητας μεταγραφής ηχητικής σημείωσης" - }, - "hide_ui_components": { - "hide_profile_call_buttons": "Κατάργηση κουμπιών κλήσης προφίλ", - "hide_chat_call_buttons": "Κατάργηση κουμπιών κλήσης συνομιλίας", - "hide_live_location_share_button": "Κατάργηση κουμπιού κοινής χρήσης ζωντανής τοποθεσίας", - "hide_stickers_button": "Κατάργηση κουμπιού αυτοκόλλητων", - "hide_voice_record_button": "Κατάργηση κουμπιού εγγραφής φωνής", - "hide_unread_chat_hint": "Κατάργηση υπόδειξης μη αναγνωσμένης συνομιλίας", - "hide_post_to_story_buttons": "Κατάργηση κουμπιών δημοσίευσης στην ιστορία πριν από την αποστολή ενός Snap", - "hide_billboard_prompt": "Κατάργηση προτροπής billboard στη ροή φίλων", - "hide_snapchat_plus_gift_reminders": "Κατάργηση υπενθυμίσεων δώρων του Snapchat Plus στις συνομιλίες", - "hide_map_reactions": "Κατάργηση αντιδράσεων χάρτη" - }, - "hide_story_suggestions": { - "hide_suggested_friend_stories": "Απόκρυψη προτεινόμενων ιστοριών φίλων", - "hide_my_stories": "Απόκρυψη των ιστοριών μου" - }, - "home_tab": { - "map": "Χάρτης", - "chat": "Συνομιλία", - "camera": "Κάμερα", - "discover": "Ανακάλυψη", - "spotlight": "Κέντρο προσοχής" - }, - "add_friend_source_spoof": { - "added_by_username": "Κατά όνομα χρήστη", - "added_by_mention": "Κατά αναφορά", - "added_by_group_chat": "Κατά ομαδική συνομιλία", - "added_by_qr_code": "Κατά κωδικό QR", - "added_by_community": "Κατά κοινότητα", - "added_by_quick_add": "Κατά γρήγορη προσθήκη (υψηλός κίνδυνος αποκλεισμού)" - }, - "bypass_video_length_restriction": { - "single": "Μεμονωμένο πολυμέσο", - "split": "Διαίρεση πολυμέσων" - }, - "old_bitmoji_selfie": { - "2d": "2D Bitmoji", - "3d": "3D Bitmoji" - }, - "disable_confirmation_dialogs": { - "erase_message": "Διαγραφή μηνύματος", - "remove_friend": "Κατάργηση φίλου", - "block_friend": "Αποκλεισμός φίλου", - "ignore_friend": "Αγνόηση φίλου", - "hide_friend": "Απόκρυψη φίλου", - "hide_conversation": "Απόκρυψη συνομιλίας", - "clear_conversation": "Εκκαθάριση συνομιλίας από τη ροή φίλων" - }, - "auto_reload": { - "snapchat_only": "Μόνο Snapchat", - "all": "Όλα (Snapchat + PurrfectSnap)" - }, - "edit_text_override": { - "multi_line_chat_input": "Είσοδος συνομιλίας πολλαπλών γραμμών", - "bypass_text_input_limit": "Παράκαμψη ορίου εισαγωγής κειμένου" - }, - "auto_purge": { - "never": "Ποτέ", - "1_hour": "1 ώρα", - "3_hours": "3 ώρες", - "6_hours": "6 ώρες", - "12_hours": "12 ώρες", - "1_day": "1 ημέρα", - "3_days": "3 ημέρες", - "1_week": "1 εβδομάδα", - "2_weeks": "2 εβδομάδες", - "1_month": "1 μήνας", - "3_months": "3 μήνες", - "6_months": "6 μήνες" - }, - "disable_story_sections": { - "friends": "Φίλοι", - "suggested_stories": "Προτεινόμενες ιστορίες", - "following": "Ακολουθείτε", - "discover": "Ανακάλυψη" - }, - "disable_cameras": { - "front": "Μπροστινή κάμερα", - "back": "Πίσω κάμερα" - }, - "disable_permission_requests": { - "notifications": "Ειδοποιήσεις", - "read_media_images": "Ανάγνωση εικόνων πολυμέσων", - "read_media_video": "Ανάγνωση βίντεο πολυμέσων", - "camera": "Κάμερα", - "microphone": "Μικρόφωνο", - "location": "Τοποθεσία", - "read_contacts": "Ανάγνωση επαφών", - "nearby_devices": "Κοντινές συσκευές", - "phone_calls": "Τηλεφωνικές κλήσεις" - }, - "message_indicators": { - "encryption_indicator": "Προσθέτει ένα εικονίδιο 🔒 δίπλα στα μηνύματα που έχουν σταλεί μόνο σε εσάς", - "platform_indicator": "Προσθέτει το εικονίδιο της πλατφόρμας από την οποία στάλθηκε ένα πολυμέσο (π.χ. Android, iOS, Web)", - "location_indicator": "Προσθέτει ένα εικονίδιο 📍 στα snaps όταν έχουν σταλεί με ενεργοποιημένη την τοποθεσία", - "ovf_editor_indicator": "Υποδεικνύει εάν ένα snap έχει σταλεί με τον επεξεργαστή OVF", - "director_mode_indicator": "Προσθέτει ένα εικονίδιο 🎬 στα snaps όταν έχουν σταλεί με τη λειτουργία σκηνοθέτη, η οποία μπορεί να χρησιμοποιηθεί για την αποστολή εικόνων γκαλερί ως snaps" - }, - "auto_mark_as_read": { - "conversation_read": "Σήμανση της συνομιλίας ως αναγνωσμένης κατά την αποστολή ενός μηνύματος", - "snap_reply": "Σήμανση των snaps ως αναγνωσμένων κατά την απάντηση σε αυτά", - "save_snap_in_chat": "Σήμανση των snaps ως αναγνωσμένων κατά την αποθήκευσή τους στη συνομιλία σε λειτουργία μυστικότητας" - }, - "friend_mutation_notifier": { - "remove_friend": "Ειδοποίηση όταν κάποιος σας καταργεί ως φίλο", - "birthday_changes": "Ειδοποίηση όταν κάποιος αλλάζει τα γενέθλιά του", - "bitmoji_selfie_changes": "Ειδοποίηση όταν κάποιος αλλάζει το selfie του Bitmoji", - "bitmoji_avatar_changes": "Ειδοποίηση όταν κάποιος αλλάζει το avatar του Bitmoji", - "bitmoji_background_changes": "Ειδοποίηση όταν κάποιος αλλάζει το φόντο του Bitmoji", - "bitmoji_scene_changes": "Ειδοποίηση όταν κάποιος αλλάζει τη σκηνή του Bitmoji" - }, - "snapchat_plus": { - "not_subscribed": "Δεν έχετε εγγραφεί", - "basic": "Βασικό", - "ad_free": "Χωρίς διαφημίσεις" - }, - "double_tap_chat_action": { - "like_message": "Μου αρέσει το μήνυμα", - "copy_text": "Αντιγραφή κειμένου στο πρόχειρο", - "delete_message": "Διαγραφή μηνύματος", - "mark_as_read": "Σήμανση ως αναγνωσμένο", - "custom_emoji_reaction": "Προσαρμοσμένη αντίδραση emoji" - }, - "startup_default_camera": { - "front": "Μπροστινή κάμερα", - "back": "Πίσω κάμερα" - } - } - }, - "friend_menu_option": { - "mark_snaps_as_seen": "Σήμανση Snaps ως αναγνωσμένων", - "mark_stories_as_seen_locally": "Σήμανση ιστοριών ως αναγνωσμένων τοπικά", - "preview": "Προεπισκόπηση", - "stealth_mode": "Λειτουργία μυστικότητας", - "auto_download_blacklist": "Μαύρη λίστα αυτόματης λήψης", - "anti_auto_save": "Αντι-αυτόματη αποθήκευση" - }, - "content_type": { - "CHAT": "Συνομιλία", - "SNAP": "Θραύση", - "EXTERNAL_MEDIA": "Εξωτερικά πολυμέσα", - "NOTE": "Ηχητική σημείωση", - "STICKER": "Αυτοκόλλητο", - "SHARE": "Κοινή χρήση", - "STATUS": "Κατάσταση", - "LOCATION": "Τοποθεσία", - "STATUS_SAVE_TO_CAMERA_ROLL": "Αποθηκεύτηκε στο ρολό της κάμερας", - "STATUS_CONVERSATION_CAPTURE_SCREENSHOT": "Στιγμιότυπο οθόνης", - "STATUS_CONVERSATION_CAPTURE_RECORD": "Εγγραφή οθόνης", - "STATUS_CALL_MISSED_VIDEO": "Αναπάντητη βιντεοκλήση", - "STATUS_CALL_MISSED_AUDIO": "Αναπάντητη ηχητική κλήση", - "LIVE_LOCATION_SHARE": "Κοινή χρήση ζωντανής τοποθεσίας", - "CREATIVE_TOOL_ITEM": "Στοιχείο δημιουργικού εργαλείου", - "FAMILY_CENTER_INVITE": "Πρόσκληση στο Οικογενειακό Κέντρο", - "FAMILY_CENTER_ACCEPT": "Αποδοχή Οικογενειακού Κέντρου", - "FAMILY_CENTER_LEAVE": "Αποχώρηση από το Οικογενειακό Κέντρο", - "STATUS_PLUS_GIFT": "Δώρο Status Plus", - "TINY_SNAP": "Μικρό Snap", - "STATUS_COUNTDOWN": "Αντίστροφη μέτρηση", - "MAP_REACTION": "Αντίδραση χάρτη" - }, - "media_download_source": { - "none": "Κανένα", - "pending": "Σε εκκρεμότητα", - "chat_media": "Πολυμέσα συνομιλίας", - "story": "Ιστορία", - "public_story": "Δημόσια ιστορία", - "spotlight": "Κέντρο προσοχής", - "profile_picture": "Εικόνα προφίλ", - "story_logger": "Καταγραφέας ιστοριών", - "message_logger": "Καταγραφέας μηνυμάτων", - "merged": "Συγχωνεύτηκε", - "voice_call": "Φωνητική κλήση" - }, - "chat_action_menu": { - "preview_button": "Προεπισκόπηση", - "download_button": "Λήψη", - "delete_logged_message_button": "Διαγραφή καταγεγραμμένου μηνύματος", - "show_chat_edit_history": "Εμφάνιση ιστορικού επεξεργασίας συνομιλίας", - "convert_message": "Μετατροπή μηνύματος" - }, - "opera_context_menu": { - "download": "Λήψη πολυμέσων", - "sent_at": "Στάλθηκε στις {date}", - "created_at": "Δημιουργήθηκε στις {date}", - "expires_at": "Λήγει στις {date}", - "media_size": "Μέγεθος πολυμέσων: {size}", - "media_duration": "Διάρκεια πολυμέσων: {duration} ms", - "show_debug_info": "Εμφάνιση πληροφοριών εντοπισμού σφαλμάτων" - }, - "modal_option": { - "profile_info": "Πληροφορίες προφίλ", - "close": "Κλείσιμο" - }, - "gallery_media_send_override": { - "multiple_media_toast": "Μπορείτε να στείλετε μόνο ένα πολυμέσο κάθε φορά" - }, - "mark_as_seen": { - "no_unseen_snaps_toast": "Δεν βρέθηκαν μη αναγνωσμένα Snaps!", - "seen_toast": "Σημειώθηκε ως αναγνωσμένο!", - "unseen_toast": "Σημειώθηκε ως μη αναγνωσμένο!", - "already_seen_toast": "Έχει ήδη σημειωθεί ως αναγνωσμένο!", - "already_unseen_toast": "Έχει ήδη σημειωθεί ως μη αναγνωσμένο!" - }, - "conversation_preview": { - "streak_expiration": "λήγει σε {day} ημέρες {hour} ώρες {minute} λεπτά", - "total_messages": "Συνολικά απεσταλμένα/ληφθέντα μηνύματα: {count}", - "title": "Προεπισκόπηση", - "unknown_user": "Άγνωστος χρήστης", - "no_messages": "Δεν βρέθηκαν μηνύματα!" - }, - "profile_info": { - "title": "Πληροφορίες προφίλ", - "first_created_username": "Πρώτο δημιουργημένο όνομα χρήστη", - "mutable_username": "Μεταβλητό όνομα χρήστη", - "display_name": "Εμφανιζόμενο όνομα", - "added_date": "Ημερομηνία προσθήκης", - "birthday": "Γενέθλια: {day} {month}", - "hidden_birthday": "Γενέθλια: Κρυφό", - "friendship": "Φιλία", - "add_source": "Προσθήκη πηγής", - "snapchat_plus": "Snapchat Plus", - "snapchat_plus_state": { - "subscribed": "Εγγεγραμμένος", - "not_subscribed": "Μη εγγεγραμμένος" - } - }, - "friendship_link_type": { - "mutual": "Αμοιβαία", - "outgoing": "Εξερχόμενη", - "blocked": "Αποκλεισμένος", - "deleted": "Διαγραμμένος", - "following": "Ακολουθείτε", - "suggested": "Προτεινόμενος", - "incoming": "Εισερχόμενη", - "incoming_follower": "Εισερχόμενος ακόλουθος" - }, - "bulk_messaging_action": { - "choose_action_title": "Επιλέξτε μια ενέργεια", - "progress_status": "Επεξεργασία {index} από {total}", - "selection_dialog_continue_button": "Συνέχεια", - "confirmation_dialog": { - "title": "Είστε σίγουροι;", - "message": "Αυτό θα επηρεάσει όλους τους επιλεγμένους φίλους. Αυτή η ενέργεια δεν μπορεί να αναιρεθεί." - }, - "actions": { - "remove_friends": "Κατάργηση φίλων", - "clear_conversations": "Εκκαθάριση συνομιλιών" - } - }, - "chat_export": { - "exporter_dialog": { - "select_conversations_title": "Επιλογή συνομιλιών", - "text_field_selection": "{amount} επιλέχθηκαν", - "text_field_selection_all": "Όλα", - "export_file_format_title": "Εξαγωγή μορφής αρχείου", - "message_type_filter_title": "Φιλτράρισμα μηνυμάτων κατά τύπο", - "amount_of_messages_title": "Ποσότητα μηνυμάτων (αφήστε κενό για όλα)", - "download_medias_title": "Λήψη πολυμέσων" - }, - "dialog_negative_button": "Ακύρωση", - "dialog_positive_button": "Εξαγωγή", - "exported_to": "Εξήχθη στο {path}", - "exporting_chats": "Εξαγωγή συνομιλιών...", - "processing_chats": "Επεξεργασία {amount} συνομιλιών...", - "export_fail": "Η εξαγωγή της συνομιλίας {conversation} απέτυχε", - "writing_output": "Εγγραφή εξόδου...", - "finished": "Έγινε! Μπορείτε τώρα να κλείσετε αυτό το παράθυρο διαλόγου.", - "no_messages_found": "Δεν βρέθηκαν μηνύματα!", - "exporting_message": "Εξαγωγή {conversation}..." - }, - "button": { - "ok": "ΟΚ", - "positive": "Ναι", - "negative": "Όχι", - "cancel": "Ακύρωση", - "open": "Άνοιγμα", - "download": "Λήψη", - "send": "Αποστολή", - "restore_original": "Επαναφορά πρωτοτύπου", - "convert_external_media": "Μετατροπή εξωτερικών πολυμέσων", - "save": "Αποθήκευση" - }, - "tracker_events": { - "conversation_enter": "Είσοδος στη συνομιλία", - "conversation_exit": "Έξοδος από τη συνομιλία", - "started_typing": "Άρχισε να πληκτρολογεί", - "stopped_typing": "Σταμάτησε να πληκτρολογεί", - "started_speaking": "Άρχισε να μιλάει", - "stopped_speaking": "Σταμάτησε να μιλάει", - "started_peeking": "Άρχισε να κρυφοκοιτάζει", - "stopped_peeking": "Σταμάτησε να κρυφοκοιτάζει", - "message_read": "Το μήνυμα διαβάστηκε", - "message_deleted": "Το μήνυμα διαγράφηκε", - "message_saved": "Το μήνυμα αποθηκεύτηκε", - "message_unsaved": "Το μήνυμα δεν αποθηκεύτηκε", - "message_edited": "Το μήνυμα επεξεργάστηκε", - "message_reaction_add": "Προσθήκη αντίδρασης σε μήνυμα", - "message_reaction_remove": "Κατάργηση αντίδρασης σε μήνυμα", - "snap_opened": "Το Snap άνοιξε", - "snap_replayed": "Το Snap επαναλήφθηκε", - "snap_replayed_twice": "Το Snap επαναλήφθηκε δύο φορές", - "snap_screenshot": "Στιγμιότυπο οθόνης Snap", - "snap_screen_record": "Εγγραφή οθόνης Snap" - }, - "tracker_actions": { - "log": "Αρχείο καταγραφής", - "in_app_notification": "Ειδοποίηση εντός εφαρμογής", - "push_notification": "Ειδοποίηση push", - "custom": "Προσαρμοσμένο" - }, - "better_notifications": { - "button": { - "reply": "Απάντηση", - "download": "Λήψη", - "mark_as_read": "Σήμανση ως αναγνωσμένο" - } - }, - "profile_picture_downloader": { - "button": "Λήψη εικόνας προφίλ", - "title": "Λήπτης εικόνων προφίλ", - "avatar_option": "Είδωλο", - "background_option": "Φόντο" - }, - "call_start_confirmation": { - "dialog_title": "Έναρξη κλήσης", - "dialog_message": "Είστε βέβαιοι ότι θέλετε να ξεκινήσετε μια κλήση;" - }, - "half_swipe_notifier": { - "notification_channel_name": "Μισό σάρωμα", - "notification_content_dm": "Ο {friend} μόλις σάρωσε το μισό στη συνομιλία σας για {duration} δευτερόλεπτα", - "notification_content_group": "Ο {friend} μόλις σάρωσε το μισό στο {group} για {duration} δευτερόλεπτα" - }, - "download_processor": { - "attachment_type": { - "snap": "Θραύση", - "sticker": "Αυτοκόλλητο", - "gif": "Γειτονιά", - "external_media": "Εξωτερικά πολυμέσα", - "note": "Σημείωση", - "original_story": "Πρωτότυπη ιστορία" - }, - "select_attachments_title": "Επιλογή συνημμένων", - "download_started_toast": "Η λήψη ξεκίνησε", - "unsupported_content_type_toast": "Μη υποστηριζόμενος τύπος περιεχομένου!", - "failed_no_longer_available_toast": "Τα πολυμέσα δεν είναι πλέον διαθέσιμα", - "no_attachments_toast": "Δεν βρέθηκαν συνημμένα!", - "already_queued_toast": "Τα πολυμέσα βρίσκονται ήδη στην ουρά!", - "already_downloaded_toast": "Τα πολυμέσα έχουν ήδη ληφθεί!", - "content_saved_toast": "Αποθηκεύτηκε!", - "download_toast": "Λήψη {path}...", - "processing_toast": "Επεξεργασία {path}...", - "failed_generic_toast": "Η λήψη απέτυχε", - "failed_to_create_preview_toast": "Η δημιουργία προεπισκόπησης απέτυχε", - "failed_processing_toast": "Η επεξεργασία απέτυχε {error}", - "failed_gallery_toast": "Η αποθήκευση στη γκαλερί απέτυχε {error}", - "dash_no_chapter": "Δεν βρέθηκε κεφάλαιο", - "dash_dialog": { - "title": "Λήψη πολυμέσων dash", - "download_all": "Λήψη όλων", - "segment_text": "Τμήμα {from} - {to}" - } - }, - "streaks_reminder": { - "notification_title": "Σερί", - "notification_text": "Θα χάσετε το σερί σας με τον/την {friend} σε {hoursLeft} ώρες" - }, - "biometric_auth": { - "unlock_button": "Ξεκλείδωμα", - "title": "Ξεκλείδωμα του Snapchat", - "subtitle": "Παρακαλώ, επαληθεύστε την ταυτότητά σας για να ξεκλειδώσετε το Snapchat" - }, - "end_to_end_encryption": { - "toolbox": { - "no_shared_key": "Δεν έχετε ακόμη κοινό μυστικό κλειδί με αυτόν τον φίλο. Κάντε κλικ παρακάτω για να ξεκινήσετε ένα νέο.", - "shared_key_fingerprint": "Το δακτυλικό σας αποτύπωμα είναι:\n\n{fingerprint}\n\nΒεβαιωθείτε ότι ταιριάζει με το δακτυλικό αποτύπωμα του φίλου σας!", - "initiate_exchange_button": "Έναρξη ανταλλαγής κλειδιών" - }, - "confirmation_dialogs": { - "title": "Κρυπτογράφηση από άκρο σε άκρο", - "confirmation_1": "ΠΡΟΕΙΔΟΠΟΙΗΣΗ: Αυτό θα αντικαταστήσει το υπάρχον κλειδί σας. Θα χάσετε την πρόσβαση σε όλα τα κρυπτογραφημένα μηνύματα από αυτόν τον φίλο. Είστε βέβαιοι ότι θέλετε να συνεχίσετε;", - "confirmation_2": "Είστε ΠΡΑΓΜΑΤΙΚΑ βέβαιοι ότι θέλετε να συνεχίσετε; Αυτή είναι η τελευταία σας ευκαιρία να υπαναχωρήσετε." - }, - "unencrypted_conversation_send_failure_toast": "Δεν μπορείτε να στείλετε κρυπτογραφημένο περιεχόμενο τόσο σε κρυπτογραφημένες όσο και σε μη κρυπτογραφημένες συνομιλίες!", - "native_hooks_send_failure_toast": "Η αποστολή απέτυχε! Ενεργοποιήστε τα εγγενή αγκίστρια στις ρυθμίσεις.", - "no_participants_to_encrypt_toast": "Δεν έχετε φίλους σε αυτήν τη συνομιλία για να κρυπτογραφήσετε μηνύματα!", - "encryption_failed_toast": "Η κρυπτογράφηση του μηνύματος απέτυχε! Ελέγξτε το logcat για περισσότερες λεπτομέρειες.", - "accept_public_key_success_toast": "Το δημόσιο κλειδί έγινε αποδεκτό με επιτυχία!", - "accept_secret_key_success_toast": "Έγινε! Μπορείτε τώρα να στέλνετε και να λαμβάνετε κρυπτογραφημένα μηνύματα με αυτόν τον φίλο.", - "accept_public_key_failure_toast": "Η αποδοχή του δημόσιου κλειδιού απέτυχε", - "accept_secret_key_failure_toast": "Η αποδοχή του μυστικού κλειδιού απέτυχε", - "accept_secret_button": "Αποδοχή μυστικού", - "accept_public_key_button": "Αποδοχή δημόσιου κλειδιού", - "outgoing_pk_message": "Αίτημα ανταλλαγής κλειδιών", - "outgoing_secret_message": "Απάντηση ανταλλαγής κλειδιών", - "incoming_pk_message": "Μόλις λάβατε ένα αίτημα δημόσιου κλειδιού. Κάντε κλικ παρακάτω για να το αποδεχτείτε.", - "incoming_secret_message": "Ο φίλος σας μόλις αποδέχτηκε το δημόσιο κλειδί σας. Κάντε κλικ παρακάτω για να αποδεχτείτε το μυστικό." - }, - "auto_open_snaps": { - "title": "Αυτόματο άνοιγμα Snaps", - "notification_content": "{count} Snaps άνοιξαν" - }, - "friend_mutation_observer": { - "notification_channel_name": "Παρατηρητής μετάλλαξης φίλου", - "friend_removed": "Ο/Η {username} σας έχει καταργήσει ως φίλο", - "birthday_removed": "Ο/Η {username} έχει καταργήσει τα γενέθλιά του/της ({birthday})", - "birthday_added": "Ο/Η {username} έχει προσθέσει τα γενέθλιά του/της ({birthday})", - "birthday_changed": "Ο/Η {username} έχει αλλάξει τα γενέθλιά του/της από {oldBirthday} σε {newBirthday}", - "bitmoji_selfie_changed": "Ο/Η {username} έχει αλλάξει το selfie του/της Bitmoji", - "bitmoji_avatar_changed": "Ο/Η {username} έχει αλλάξει το avatar του/της Bitmoji", - "bitmoji_background_changed": "Ο/Η {username} έχει αλλάξει το φόντο του/της Bitmoji", - "bitmoji_scene_changed": "Ο/Η {username} έχει αλλάξει τη σκηνή του/της Bitmoji" - }, - "material3_strings": { - "date_range_picker_start_headline": "Από", - "date_range_picker_end_headline": "Έως", - "date_range_picker_title": "Επιλογή εύρους ημερομηνιών", - "date_picker_switch_to_calendar_mode": "Ημερολόγιο", - "date_picker_switch_to_input_mode": "Είσοδος", - "date_range_picker_scroll_to_previous_month": "Προηγούμενος μήνας", - "date_range_picker_scroll_to_next_month": "Επόμενος μήνας", - "date_picker_today_description": "Σήμερα", - "date_range_picker_day_in_range": "Επιλέχθηκε", - "date_input_invalid_for_pattern": "Μη έγκυρη ημερομηνία", - "date_input_invalid_year_range": "Μη έγκυρο έτος", - "date_input_invalid_not_allowed": "Μη έγκυρη ημερομηνία", - "date_range_input_invalid_range_input": "Μη έγκυρο εύρος ημερομηνιών" - }, - "send_override_dialog": { - "title": "Αποστολή πολυμέσων ως {type}", - "duration": "Διάρκεια: {duration}", - "saveable_snap_hint": "Κάντε το Snap αποθηκεύσιμο στη συνομιλία", - "unlimited_duration": "Απεριόριστο" - }, - "invalid_input_toast": "Μη έγκυρη εισαγωγή! Βεβαιωθείτε ότι έχετε εισαγάγει μια έγκυρη τιμή." -} \ No newline at end of file diff --git a/common/src/main/assets/lang/en_UK.json b/common/src/main/assets/lang/en_UK.json new file mode 100644 index 00000000..610fa3e6 --- /dev/null +++ b/common/src/main/assets/lang/en_UK.json @@ -0,0 +1,1559 @@ +{ + "setup": { + "dialogs": { + "select_language": "Select Language", + "select_save_folder_button": "Select Folder", + "save_folder": "PurrfectSnap requires Storage permissions to download and Save Media from Snapchat.\nPlease choose the location where media should be downloaded to." + }, + "mappings": { + "generate_failure_no_snapchat": "PurrfectSnap was unable to detect Snapchat, please try reinstalling Snapchat.", + "generate_failure": "An error occurred while trying to generate mappings, please try again.", + "dialog": "Generating Mappings..." + }, + "permissions": { + "notification_access": "Notification Access", + "request_button": "Request", + "dialog": "Complete these essentials to continue:", + "battery_optimization": "Battery Optimization", + "display_over_other_apps": "Display Over Other Apps" + } + }, + "manager": { + "routes": { + "tasks": "Tasks", + "features": "Features", + "home_logs": "Logs", + "home": "Home", + "home_settings": "Settings", + "logged_stories": "Logged Stories", + "social": "Social", + "manage_scope": "Manage Scope", + "scripts": "Scripts", + "logger_history": "Logger History", + "messaging_preview": "Preview", + "friend_tracker": "Friend Tracker", + "edit_rule": "Edit Rule", + "better_location": "Better Location", + "file_imports": "File Imports" + }, + "sections": { + "features": { + "disabled": "Disabled", + "export_option": "Export", + "import_option": "Import", + "config_import_success_toast": "Config imported Successfully", + "config_import_failure_toast": "Failed to import Config {error}", + "reset_option": "Reset", + "config_export_success_toast": "Config exported Successfully", + "saved_config_snackbar": "Config saved", + "config_export_failure_toast": "Failed to export config {error}" + }, + "tasks": { + "no_tasks": "No Tasks", + "merge_files_toast": "Merging {count} Files", + "remove_selected_tasks_title": "Are you sure you want to remove selected tasks?", + "remove_all_tasks_title": "Are you sure you want to remove all tasks?", + "delete_files_option": "Also Delete Files", + "remove_selected_tasks_confirm": "Remove {count} Tasks?", + "remove_all_tasks_confirm": "Remove All Tasks?", + "failed_to_open_file": "Failed to open file" + }, + "social": { + "streaks_expiration_short": "{hours}h", + "friends_tab": "Friends", + "groups_tab": "Groups", + "empty_hint": "(blank)" + }, + "home": { + "update_title": "PurrfectSnap Update", + "update_button": "Download", + "update_content": "Version {version} is Available!", + "debug_build_summary_title": "You are running a debug build of PurrfectSnap", + "version_title": "v{versionName} · by eternal", + "debug_build_summary_date": "Build date: {date} ({days} days ago)", + "debug_build_summary_content": "Version {versionName} ({versionCode})", + "quick_actions_title": "Quick Actions", + }, + "home_logs": { + "no_logs_hint": "No Logs Available", + "clear_logs_button": "Clear Logs", + "export_logs_button": "Export Logs", + "saving_logs_toast": "Saving logs, This may take a while ...", + "saved_logs_success_toast": "Logs saved successfully", + "saved_logs_failure_toast": "Failed to save logs" + }, + "home_settings": { + "debug_title": "Debug", + "success_toast": "Done!", + "message_logger_summary": "{messageCount} Messages\n{storyCount} Stories", + "export_button": "Export", + "clear_button": "Clear", + "view_logger_history_button": "View Logger History", + "actions_title": "Actions", + "message_logger_title": "Message Logger" + }, + "manage_scope": { + "logged_stories_button": "Show Logged Stories", + "e2ee_title": "End-to-End Encryption", + "participants_text": "{count} Participants", + "not_found": "Not Found", + "streaks_title": "Streaks", + "streaks_length_text": "Length: {length}", + "streaks_expiration_text": "Expires in {eta}", + "delete_scope_confirm_dialog_title": "Are you sure You want to Delete a {scope}?", + "rules_title": "Rules", + "streaks_expiration_text_expired": "Expired", + "reminder_button": "Set Reminder" + }, + "logged_stories": { + "story_failed_to_load": "Failed to load", + "save_from_cache_button": "Save From Cache", + "no_stories": "No stories found" + }, + "messaging_preview": { + "bridge_connection_failed": "Failed to connect to bridge. Make sure Snapchat is running in the background", + "bridge_connection_error": "Failed to connect to bridge. Make sure Snapchat is running in the background", + "message_fetch_failed": "Failed to fetch Messages", + "subtitle": "Hold to select", + "actions_title": "Conversation Actions", + "save_all_option": "Save All", + "unsave_all_option": "Unsave All", + "mark_selection_as_seen_option": "Mark Selected Snap As Seen", + "mark_all_as_seen_option": "Mark all Snaps As Seen", + "delete_selection_option": "Delete Selection", + "delete_all_option": "Delete All", + "bridge_init_failed": "Failed to initialize messaging bridge. Make sure Snapchat is running in the background", + "no_message_hint": "No Message", + "save_selection_option": "Save Selection", + "unsave_selection_option": "Unsave Selection", + "processed_message_toast": "Processed {count} messages", + "processed_messages_toast": "Processed {count} messages", + "processed_messages_text": "Processed {count}", + "close_button_description": "Clear selection" + }, + "logger_history": { + "list_friend_format": "Friend {name}", + "list_group_format": "Group {name}", + "no_more_messages": "No more Messages", + "reverse_order_checkbox": "Reverse Order", + "chat_attachment": "Attachment {index}", + "empty_message": "Empty Chat Message", + "message_parse_failed": "Failed to Parse Message", + "unknown_sender": "Unknown Sender", + "download_attachment_failed_toast": "Failed to Download Attachment" + }, + "file_imports": { + "file_import_failed": "Failed to import file: {error}", + "import_file_button": "Import File", + "file_not_found": "File not found", + "file_imported": "File imported successfully", + "file_delete_failed": "Failed to delete file", + "no_files_hint": "Here you can import files for use in Snapchat. Press the button below to import a file." + }, + "better_location": { + "spoofed_coordinates_title": "Lat {latitude}, Long {longitude}", + "spoof_location_toggle": "Spoof Location", + "no_saved_coordinates_hint": "No saved coordinates", + "teleport_to_friend_title": "Teleport to Friend", + "saved_name_dialog_hint": "Saved Name", + "save_dialog_button": "Save", + "saved_coordinates_title": "Saved Coordinates", + "delete_dialog_message": "Are you sure you want to delete this saved coordinate?", + "delete_dialog_title": "Delete Saved Coordinate", + "search_bar": "Search", + "no_friends_map": "No friends on the map", + "no_friends_found": "No friends found", + "save_coordinates_dialog_title": "Save Coordinates", + "choose_location_button": "Choose Location", + "teleport_to_friend_button": "Teleport to Friend", + "latitude_dialog_hint": "Latitude", + "longitude_dialog_hint": "Longitude", + "suspend_location_updates": "Suspend Location Updates" + } + }, + "dialogs": { + "add_friend": { + "title": "Add Friend or Group", + "search_hint": "Search", + "fetch_error": "Failed to fetch data", + "category_groups": "Groups", + "category_friends": "Friends" + }, + "scripting_warning": { + "title": "Warning", + "content": "PurrfectSnap includes a scripting tool, allowing the execution of user-defined code on your device. Use extreme caution and only install modules from known, reliable sources. Unauthorised or unverified modules may pose security risks to your system." + }, + "reset_config": { + "title": "Reset config", + "content": "Are you sure you want to reset the config?", + "success_toast": "Config reset successfully" + }, + "messaging_action": { + "title": "Choose content types to process", + "select_all_button": "Select All" + }, + "export_config": { + "content": "Do you want to export the config with sensitive data? (Such as location coordinates, etc.)", + "title": "Export Sensitive Data?" + }, + "file_imports": { + "settings_select_file_hint": "Select an imported file", + "no_files_settings_hint": "No files found. Make sure you have imported the required files in the File Imports section" + } + } + }, + "scopes": { + "friend": "Friend", + "group": "Group" + }, + "rules": { + "toasts": { + "enabled": "{ruleName} Enabled", + "disabled": "{ruleName} Disabled" + }, + "modes": { + "blacklist": "Blacklist mode", + "whitelist": "Whitelist mode" + }, + "properties": { + "auto_download": { + "name": "Auto Download", + "description": "Automatically download Snaps when viewing them", + "options": { + "blacklist": "Exclude from Auto Download", + "whitelist": "Auto Download" + } + }, + "stealth": { + "description": "Prevents anyone from knowing you've opened their Snaps/Chats and conversations", + "options": { + "blacklist": "Exclude from Stealth Mode", + "whitelist": "Stealth Mode" + }, + "name": "Stealth Mode" + }, + "auto_save": { + "name": "Auto Save", + "description": "Saves Chat Messages when viewing them", + "options": { + "blacklist": "Exclude from Auto save", + "whitelist": "Auto Save" + } + }, + "unsaveable_messages": { + "name": "Unsaveable Messages", + "description": "Prevents messages from being saved in chat by other people", + "options": { + "blacklist": "Exclude from Unsaveable Messages", + "whitelist": "Unsaveable Messages" + } + }, + "hide_friend_feed": { + "name": "Hide from Friend Feed" + }, + "e2e_encryption": { + "name": "Use E2E Encryption" + }, + "pin_conversation": { + "name": "Pin Conversation" + }, + "auto_open_snaps": { + "name": "Automatically Opens Snaps", + "description": "Automatically opens Snaps upon receiving them", + "options": { + "blacklist": "Exclude from Automatic Snap Opening", + "whitelist": "Automatically Opens Snaps" + } + } + } + }, + "actions": { + "export_memories": { + "name": "Export Memories", + "description": "Exports Memories into a ZIP file" + }, + "clean_snapchat_cache": { + "name": "Clean Snapchat Cache", + "description": "Cleans the Snapchat Cache" + }, + "manage_friend_list": { + "name": "Manage Friend List", + "description": "Import/export your friends list when backing up" + }, + "export_chat_messages": { + "description": "Exports conversation messages into a JSON/HTML/TXT file", + "name": "Export Chat Messages" + }, + "bulk_messaging_action": { + "name": "Bulk Messaging Action", + "description": "Performs operations such as deleting friends or mass deletion of conversations" + }, + "regen_mappings": { + "name": "Regenerate Mappings", + "description": "Manually Regenerate Mappings" + }, + "change_language": { + "name": "Change Language", + "description": "Change the Language of PurrfectSnap" + }, + "logger_history": { + "name": "Logger History", + "description": "View the history of logged messages" + }, + "file_imports": { + "name": "File Imports", + "description": "Import files for use in Snapchat" + }, + "friend_tracker": { + "name": "Friend Tracker", + "description": "Track your friends on Snapchat" + } + }, + "features": { + "notices": { + "ban_risk": "⚠ This feature may cause bans", + "unstable": "⚠ Unstable", + "internal_behavior": "⚠ This may break Snapchat's internal behavior" + }, + "properties": { + "downloader": { + "properties": { + "path_format": { + "name": "Path Format", + "description": "Specify the File Path Format" + }, + "merge_overlays": { + "name": "Merge Overlays", + "description": "Combines the Text and the media of a Snap into a single file" + }, + "download_profile_pictures": { + "name": "Download Profile Pictures", + "description": "Allows you to download Profile Pictures from the profile page" + }, + "download_context_menu": { + "description": "Allows you to download/preview messages from a conversation or a story using the context menu.\nLong press on buttons will force download", + "name": "Download Context Menu" + }, + "ffmpeg_options": { + "name": "FFmpeg Options", + "description": "Specify additional FFmpeg options", + "properties": { + "threads": { + "name": "Threads", + "description": "The amount of threads to use" + }, + "preset": { + "name": "Preset", + "description": "Set the speed of the conversion" + }, + "constant_rate_factor": { + "name": "Constant Rate Factor", + "description": "Set the constant rate factor for the video encoder\nFrom 0 to 51 for libx264" + }, + "video_bitrate": { + "name": "Video Bitrate", + "description": "Set the video bitrate (kbps)" + }, + "audio_bitrate": { + "description": "Set the audio bitrate (kbps)", + "name": "Audio Bitrate" + }, + "custom_video_codec": { + "name": "Custom Video Codec", + "description": "Set a custom Video Codec (e.g. libx264)" + }, + "custom_audio_codec": { + "name": "Custom Audio Codec", + "description": "Set a custom Audio Codec (e.g. AAC)" + } + } + }, + "save_folder": { + "name": "Save Folder", + "description": "Select the directory to which all media should be downloaded to" + }, + "auto_download_sources": { + "name": "Auto Download Sources", + "description": "Select the sources to automatically download from" + }, + "prevent_self_auto_download": { + "name": "Prevent Self Auto Download", + "description": "Prevents your own Snaps from being downloaded automatically" + }, + "allow_duplicate": { + "name": "Allow Duplicate", + "description": "Allows the same media to be downloaded multiple times" + }, + "force_voice_note_format": { + "name": "Force Voice Note Format", + "description": "Forces Voice Notes to be saved in a specified Format" + }, + "opera_download_button": { + "name": "Opera Download Button", + "description": "Adds a download button on the top right corner when viewing a Snap.\nLong press on buttons will force download" + }, + "force_image_format": { + "name": "Force Image Format", + "description": "Forces images to be saved in a specified Format" + }, + "logging": { + "name": "Logging", + "description": "Shows toasts when media is downloading" + }, + "custom_path_format": { + "name": "Custom Path Format", + "description": "Specify a custom path format for downloaded media\n\nAvailable variables:\n - %username%\n - %source%\n - %hash%\n - %date_time%" + } + }, + "name": "Downloader", + "description": "Download Snapchat Media" + }, + "user_interface": { + "properties": { + "friend_feed_message_preview": { + "properties": { + "amount": { + "description": "The amount of messages to get previewed", + "name": "Amount" + } + }, + "description": "Shows a preview of the last messages in the Friend Feed", + "name": "Friend Feed Message Preview" + }, + "snap_preview": { + "name": "Snap Preview", + "description": "Displays a small preview next to unseen Snaps in chat" + }, + "bootstrap_override": { + "description": "Overrides user interface bootstrap settings", + "properties": { + "app_appearance": { + "name": "App Appearance", + "description": "Sets a persistent App Appearance" + }, + "home_tab": { + "name": "Home Tab", + "description": "Overrides the startup tab when opening Snapchat" + } + }, + "name": "Bootstrap Override" + }, + "streak_expiration_info": { + "name": "Show Streak Expiration Info", + "description": "Shows a Streak Expiration timer next to the Streaks counter" + }, + "map_friend_nametags": { + "name": "Enhanced Friend Map Nametags", + "description": "Improves the Nametags of friends on the Snapmap" + }, + "prevent_message_list_auto_scroll": { + "name": "Prevent Message List Auto Scroll", + "description": "Prevents the message list from scrolling to the bottom when sending/receiving a message" + }, + "opera_media_quick_info": { + "name": "Opera Media Quick Info", + "description": "Shows useful information of media such as creation date in opera viewer context menu" + }, + "vertical_story_viewer": { + "description": "Enables the vertical story viewer for all stories", + "name": "Vertical Story Viewer" + }, + "friend_feed_menu_buttons": { + "name": "Friend Feed Menu Buttons", + "description": "Select which buttons to show in the Friend Feed Menu" + }, + "message_indicators": { + "name": "Message Indicators", + "description": "Adds specific indicators icons to messages\nNote: Indicators might not be 100% accurate" + }, + "stealth_mode_indicator": { + "name": "Stealth Mode Indicator", + "description": "Adds a 👻 emoji next to conversations in Stealth Mode" + }, + "enable_app_appearance": { + "name": "Enable App Appearance Settings", + "description": "Enables the hidden App Appearance Setting\nMay not be required on newer Snapchat versions" + }, + "hide_friend_feed_entry": { + "name": "Hide Friend Feed Entry", + "description": "Hides a specific friend from the Friend Feed\nUse the social tab to manage this feature" + }, + "hide_streak_restore": { + "description": "Hides the Restore button in the friend feed", + "name": "Hide Streak Restore" + }, + "hide_story_suggestions": { + "name": "Hide Story Suggestions", + "description": "Removes suggestions from the Stories page" + }, + "hide_ui_components": { + "description": "Select which UI components to hide", + "name": "Hide UI Components" + }, + "old_bitmoji_selfie": { + "name": "Old Bitmoji Selfie", + "description": "Brings back the Bitmoji selfies from older Snapchat versions" + }, + "disable_spotlight": { + "name": "Disable Spotlight", + "description": "Disables the Spotlight page" + }, + "enable_friend_feed_menu_bar": { + "name": "Friend Feed Menu Bar", + "description": "Enables the new Friend Feed Menu Bar" + }, + "edit_text_override": { + "name": "Edit Text Override", + "description": "Overrides text field behavior" + } + }, + "name": "User Interface", + "description": "Change the look and feel of Snapchat" + }, + "messaging": { + "name": "Messaging", + "properties": { + "bypass_screenshot_detection": { + "description": "Prevents Snapchat from detecting when you take a screenshot", + "name": "Bypass Screenshot Detection" + }, + "anonymous_story_viewing": { + "name": "Anonymous Story Viewing", + "description": "Prevents anyone from knowing you've seen their story" + }, + "hide_peek_a_peek": { + "description": "Prevents notification from being sent when you half swipe into a chat", + "name": "Hide Peek-a-Peek" + }, + "prevent_story_rewatch_indicator": { + "description": "Prevents anyone from knowing you've rewatched their story", + "name": "Prevent Story Rewatch Indicator" + }, + "hide_bitmoji_presence": { + "name": "Hide Bitmoji Presence", + "description": "Prevents your Bitmoji from popping up while in Chat" + }, + "hide_typing_notifications": { + "name": "Hide Typing Notifications", + "description": "Prevents anyone from knowing you're typing a message" + }, + "half_swipe_notifier": { + "name": "Half Swipe Notifier", + "description": "Notifies you when someone half swipes into a conversation", + "properties": { + "min_duration": { + "name": "Minimum Duration", + "description": "The minimum duration of the half swipe (in seconds)" + }, + "max_duration": { + "name": "Maximum Duration", + "description": "The maximum duration of the half swipe (in seconds)" + } + } + }, + "disable_replay_in_ff": { + "name": "Disable Replay in FF", + "description": "Disables the ability to replay with a long press from the Friend Feed" + }, + "call_start_confirmation": { + "name": "Call Start Confirmation", + "description": "Shows a confirmation dialog when starting a call" + }, + "auto_save_messages_in_conversations": { + "name": "Auto Save Messages", + "description": "Automatically saves every message in conversations" + }, + "remove_groups_locked_status": { + "name": "Remove Groups Locked Status", + "description": "Allows you to view group information after being kicked" + }, + "unlimited_snap_view_time": { + "name": "Unlimited Snap View Time", + "description": "Removes the Time Limit for viewing Snaps" + }, + "loop_media_playback": { + "name": "Loop Media Playback", + "description": "Loops media playback when viewing Snaps / Stories" + }, + "prevent_message_sending": { + "name": "Prevent Message Sending", + "description": "Prevents sending certain types of messages" + }, + "better_notifications": { + "name": "Better Notifications", + "description": "Adds more information in received notifications", + "properties": { + "media_preview": { + "name": "Media Preview", + "description": "Shows a preview of the selected media types in the notification" + }, + "media_caption": { + "name": "Media Caption", + "description": "Shows the attached caption of media in the notification" + }, + "stacked_media_messages": { + "name": "Stacked Media Messages", + "description": "Combines multiple media messages into one text notification when they cannot be previewed. Use in combination with Chat Preview" + }, + "friend_add_source": { + "name": "Friend Add Source", + "description": "Shows the source of a friend request in the notification" + }, + "reply_button": { + "name": "Reply Button", + "description": "Adds a reply button to the notification" + }, + "download_button": { + "name": "Download Button", + "description": "Allows you to download media from the notification" + }, + "mark_as_read_button": { + "name": "Mark as Read Button", + "description": "Allows you to mark a message as read from the notification" + }, + "group_notifications": { + "name": "Group Notifications", + "description": "Group notifications into a single one" + }, + "chat_preview": { + "name": "Chat Preview", + "description": "Shows a preview of received messages in the notification" + }, + "mark_as_read_and_save_in_chat": { + "name": "Mark as Read and Save in Chat", + "description": "Adds a mark as read and save in chat button to the notification" + }, + "smart_replies": { + "name": "Smart Replies", + "description": "Adds suggested replies to notifications (Android 10+). Use in combination with Reply Button" + } + } + }, + "notification_blacklist": { + "name": "Notification Blacklist", + "description": "Select notifications which should get blocked" + }, + "message_logger": { + "name": "Message Logger", + "description": "Prevents messages from being deleted", + "properties": { + "auto_purge": { + "name": "Auto Purge", + "description": "Automatically deletes cached messages that are older than the specified amount of time" + }, + "message_filter": { + "name": "Message Filter", + "description": "Select which messages should get logged (empty for all messages)" + }, + "keep_my_own_messages": { + "name": "Keep My Own Messages", + "description": "Prevents your own messages from being deleted" + } + } + }, + "gallery_media_send_override": { + "name": "Gallery Media Send Override", + "description": "Spoofs the media source when sending from the Gallery" + }, + "strip_media_metadata": { + "name": "Strip Media Metadata", + "description": "Removes metadata of media before sending as a message" + }, + "bypass_message_retention_policy": { + "name": "Bypass Message Retention Policy", + "description": "Prevents messages from being deleted after viewing them" + }, + "bypass_message_action_restrictions": { + "name": "Bypass Message Action Restrictions", + "description": "Allows you to react to a snap without having opened it or to save an unsaveable message" + }, + "auto_mark_as_read": { + "name": "Automatically Marks as Read", + "description": "Automatically marks messages/snaps as read even when Stealth Mode is enabled" + }, + "friend_mutation_notifier": { + "description": "Notifies you when something changes on a friend's profile", + "name": "Friend Mutation Notifier" + }, + "unlimited_conversation_pinning": { + "description": "Allows you to pin an unlimited amount of conversations locally", + "name": "Unlimited Conversation Pinning" + }, + "mark_snap_as_seen_button": { + "name": "Mark Snap as Seen Button", + "description": "Adds a button to mark a Snap as seen when viewing it.\nThis will work even when Stealth Mode is enabled" + }, + "skip_when_marking_as_seen": { + "name": "Skip When Marking as Seen", + "description": "Automatically skips to the next Snap when marking a Snap as seen.\nUse in combination with Mark Snap as Seen Button" + } + }, + "description": "Change how you interact with friends" + }, + "global": { + "name": "Global", + "description": "Tweak Global Snapchat Settings", + "properties": { + "better_location": { + "name": "Better Location", + "description": "Enhances the Snapchat Location", + "properties": { + "spoof_location": { + "name": "Spoof Location", + "description": "Spoofs your location to a specified one" + }, + "coordinates": { + "name": "Coordinates", + "description": "Set the coordinates of the spoofed location" + }, + "always_update_location": { + "name": "Always Update Location", + "description": "Force Snapchat to update location even if no GPS data is received" + }, + "suspend_location_updates": { + "description": "Prevents your location from being updated", + "name": "Suspend Location Updates" + }, + "spoof_battery_level": { + "description": "Spoofs the battery level of your device on map\nValue must be between 0 and 100", + "name": "Spoof Battery Level" + }, + "spoof_headphones": { + "name": "Spoof Headphones", + "description": "Spoofs the status of listening to music on map" + }, + "walk_radius": { + "name": "Walk Radius", + "description": "Randomly walk around within this radius (ft)" + } + } + }, + "disable_confirmation_dialogs": { + "name": "Disable Confirmation Dialogs", + "description": "Automatically confirms selected actions" + }, + "disable_metrics": { + "name": "Disable Metrics", + "description": "Blocks sending specific analytic data to Snapchat" + }, + "block_ads": { + "name": "Block Ads", + "description": "Prevents Advertisements from being displayed" + }, + "spotlight_comments_username": { + "description": "Shows author username in Spotlight comments", + "name": "Spotlight Comments Username" + }, + "bypass_video_length_restriction": { + "name": "Bypass Video Length Restrictions", + "description": "Single: sends a single video\nSplit: split videos after editing" + }, + "default_volume_controls": { + "name": "Default Volume Controls", + "description": "Forces Snapchat to use system volume controls" + }, + "snapchat_plus": { + "description": "Enables Snapchat Plus features\nSome Server-sided features may not work", + "name": "Snapchat Plus" + }, + "auto_updater": { + "name": "Auto Updater", + "description": "Automatically checks for new updates" + }, + "disable_story_sections": { + "name": "Disable Story Sections", + "description": "Removes sections from the Stories page\nMay require a refresh to work properly" + }, + "disable_permission_requests": { + "name": "Disable Permission Requests", + "description": "Prevents Snapchat from asking for specific permissions" + }, + "disable_memories_snap_feed": { + "name": "Disable Memories Snap Feed", + "description": "Prevents Snapchat from showing recent memories when you swipe up in camera" + }, + "default_video_playback_rate": { + "name": "Default Video Playback Rate", + "description": "Sets the default speed for the playback of videos\nValue must be between 0.1 and 4.0" + }, + "video_playback_rate_slider": { + "name": "Video Playback Rate Slider", + "description": "Adds a slider in opera context menu to change the video playback rate\nNote: Changes only apply to subsequent videos" + }, + "disable_snap_splitting": { + "name": "Disable Snap Splitting", + "description": "Prevents Snaps from being split into multiple parts\nPictures you send will turn into videos" + }, + "disable_google_play_dialogs": { + "name": "Disable Google Play Services Dialogs", + "description": "Prevent Google Play Services availability dialogs from being shown" + }, + "hide_active_music": { + "name": "Hide Active Music", + "description": "Prevents Snapchat from knowing you're listening to music\nThis will allow you to take snaps using control volume buttons while listening to music" + }, + "disable_custom_tabs": { + "name": "Disable Custom Tabs", + "description": "Opens links in supported applications rather than in the Web Browser" + }, + "media_upload_quality": { + "name": "Media Upload Quality", + "description": "Overrides the media upload quality", + "properties": { + "force_video_upload_source_quality": { + "name": "Force Video Upload Source Quality", + "description": "Forces Snapchat to use the source quality when uploading videos\nPlease note that this may not remove metadata from media" + }, + "disable_image_compression": { + "name": "Disable Image Compression", + "description": "Disables image compression when uploading media" + }, + "custom_image_upload_format": { + "name": "Custom Image Upload Format", + "description": "Sets a custom image upload format\nSelect a lossless format (like PNG) for the best quality" + } + } + }, + "disable_telecom_framework": { + "name": "Disable Telecom Framework", + "description": "Prevents Snapchat from using the Android Telecom framework\nThis allows you to listen to music while on a call" + } + } + }, + "camera": { + "name": "Camera", + "description": "Adjust the right settings for the perfect snap", + "properties": { + "immersive_camera_preview": { + "description": "Prevents Snapchat from Cropping the Camera preview\nThis might cause the camera to flicker on some devices", + "name": "Immersive Preview" + }, + "override_front_resolution": { + "name": "Override Front Resolution", + "description": "Overrides the camera resolution for the front camera" + }, + "disable_cameras": { + "name": "Disable Cameras", + "description": "Prevents Snapchat from using the selected cameras" + }, + "black_photos": { + "name": "Black Photos", + "description": "Replaces captured photos with a black background\nVideos are not affected" + }, + "override_back_resolution": { + "description": "Overrides the camera resolution for the back camera", + "name": "Override Back Resolution" + }, + "custom_resolution": { + "description": "Sets a custom camera resolution, width x height (e.g. 1920x1080).\nThe custom resolution must be supported by your device", + "name": "Custom Resolution" + }, + "front_custom_frame_rate": { + "name": "Front Custom Frame Rate", + "description": "Overrides the front camera frame rate" + }, + "back_custom_frame_rate": { + "name": "Back Custom Frame Rate", + "description": "Overrides the back camera frame rate" + }, + "force_camera_source_encoding": { + "name": "Force Camera Source Encoding", + "description": "Forces the camera source encoding" + }, + "hevc_recording": { + "name": "HEVC Recording", + "description": "Uses HEVC (H.265) codec for video recording" + } + } + }, + "streaks_reminder": { + "properties": { + "group_notifications": { + "description": "Group notifications into a single one", + "name": "Group Notifications" + }, + "interval": { + "name": "Interval", + "description": "The interval between each reminder (hours)" + }, + "remaining_hours": { + "name": "Remaining Time", + "description": "The remaining amount of time before the notification is shown (hours)" + } + }, + "name": "Streaks Reminder", + "description": "Periodically notifies you about your Streaks" + }, + "experimental": { + "description": "Experimental features", + "name": "Experimental", + "properties": { + "native_hooks": { + "name": "Native Hooks", + "description": "Unsafe Features that hook into Snapchat's native code", + "properties": { + "disable_bitmoji": { + "name": "Disable Bitmoji", + "description": "Disables Friends Profile Bitmoji" + }, + "composer_hooks": { + "properties": { + "composer_console": { + "name": "Composer Console", + "description": "Allows you to execute JavaScript code in Composer (arm64 only)" + }, + "bypass_camera_roll_limit": { + "name": "Bypass Camera Roll Limit", + "description": "Increases the maximum amount of media you can send from the camera roll" + }, + "composer_logs": { + "name": "Composer Logs", + "description": "Redirects console logs of Composer to PurrfectSnap" + }, + "show_first_created_username": { + "description": "Shows the first created username next to the current username in the profile page", + "name": "Show First Created Username" + } + }, + "name": "Composer Hooks", + "description": "Injects code into the Composer cross-platform UI framework" + }, + "custom_emoji_font": { + "description": "Allows you to use a custom emoji font. Only works with .ttf fonts", + "name": "Custom Emoji Font" + } + } + }, + "spoof": { + "properties": { + "remove_mock_location_flag": { + "name": "Remove Mock Location Flag", + "description": "Prevents Snapchat from detecting Mock location" + }, + "play_store_installer_package_name": { + "name": "Play Store Installer Package Name", + "description": "Overrides the installer package name to com.android.vending" + }, + "remove_vpn_transport_flag": { + "name": "Remove VPN Transport Flag", + "description": "Prevents Snapchat from detecting VPNs" + } + }, + "description": "Spoof various information about you", + "name": "Spoof" + }, + "media_file_picker": { + "name": "Media File Picker", + "description": "Allows you to pick any video/audio file from the gallery" + }, + "story_logger": { + "name": "Story Logger", + "description": "Provides a history of friends stories" + }, + "account_switcher": { + "name": "Account Switcher", + "description": "Allows you to switch between accounts without logging out\nLong press on the search icon next to your Bitmoji profile to open the menu\nNote: this feature is experimental and will likely change in the future", + "properties": { + "auto_backup_current_account": { + "description": "Automatically backs up the current account when logging out or switching accounts", + "name": "Auto Backup Current Account" + } + } + }, + "call_recorder": { + "name": "Call Recorder", + "description": "Automatically records audio calls" + }, + "convert_message_locally": { + "name": "Convert Message Locally", + "description": "Converts snaps to chat external media locally. This appears in chat download context menu" + }, + "edit_message": { + "name": "Edit Messages", + "description": "Allows you to edit messages in conversations" + }, + "infinite_story_boost": { + "description": "Bypass the Story Boost Limit delay", + "name": "Infinite Story Boost" + }, + "meo_passcode_bypass": { + "description": "Bypass the My Eyes Only passcode\nThis will only work if the passcode has been entered correctly before", + "name": "My Eyes Only Passcode Bypass" + }, + "no_friend_score_delay": { + "name": "No Friend Score Delay", + "description": "Removes the delay when viewing a Friends Score" + }, + "e2ee": { + "name": "End-To-End Encryption", + "description": "Encrypts your messages with AES using a shared secret key\nMake sure to save your key somewhere safe!", + "properties": { + "encrypted_message_indicator": { + "name": "Encrypted Message Indicator", + "description": "Adds a 🔒 emoji next to encrypted messages" + }, + "force_message_encryption": { + "name": "Force Message Encryption", + "description": "Prevents sending encrypted messages to people who don't have E2E Encryption enabled only when multiple conversations are selected" + } + } + }, + "add_friend_source_spoof": { + "description": "Spoofs the source of a Friend Request", + "name": "Add Friend Source Spoof" + }, + "hidden_snapchat_plus_features": { + "description": "Enables unreleased/beta Snapchat Plus features\nMight not work on older Snapchat versions", + "name": "Hidden Snapchat Plus Features" + }, + "prevent_forced_logout": { + "name": "Prevent Forced Logout", + "description": "Prevents Snapchat from logging you out when you login on another device" + }, + "app_lock": { + "name": "App Lock", + "description": "Prevents access to Snapchat without a passcode", + "properties": { + "lock_on_resume": { + "name": "Lock On Resume", + "description": "Locks the app when it's reopened" + } + } + }, + "custom_streaks_expiration_format": { + "name": "Bespoke Streak Expiry Format", + "description": "Customises the Streaks Expiry format\n\nAvailable variables:\n- %c: Streaks Count\n- %e: Hourglass Emoji\n- %d: Days\n- %h: Hours\n- %m: Minutes\n- %s: Seconds\n- %w: Remaining Time" + }, + "best_friend_pinning": { + "name": "Best Friend Pinning", + "description": "Allows you to pin a friend as you're number one best friend. Note: Only you can see you're pinned best friend" + }, + "cof_experiments": { + "description": "Enables unreleased/beta Snapchat features", + "name": "COF Experiments" + }, + "context_menu_fix": { + "name": "Context Menu Fix", + "description": "Attempts to repair the Friend Feed Menu when the device is offline, it cannot be displayed correctly" + }, + "better_transcript": { + "name": "Better Transcript", + "properties": { + "preferred_transcription_lang": { + "name": "Preferred Transcription Language", + "description": "The preferred language for the voice note transcript (e.g. EN, ES, FR)" + }, + "enhanced_transcript": { + "name": "Enhanced Transcript", + "description": "Improves the voice note transcript using DeepL.\nBefore using this feature, please ensure that you have read their privacy policy." + }, + "force_transcription": { + "description": "Allows all voice notes to be transcribed", + "name": "Force Voice Note Transcription" + } + }, + "description": "Improves the voice note transcript" + } + } + }, + "rules": { + "name": "Rules", + "description": "Manage Automatic Features for individual people" + }, + "scripting": { + "name": "Scripting", + "description": "Run custom scripts to extend PurrfectSnap", + "properties": { + "developer_mode": { + "name": "Developer Mode", + "description": "Shows debug info on Snapchat's UI" + }, + "module_folder": { + "name": "Module Folder", + "description": "The folder where the scripts are located" + }, + "integrated_ui": { + "name": "Integrated UI", + "description": "Allows scripts to add custom UI components to Snapchat" + }, + "disable_log_anonymization": { + "name": "Disable Log Anonymization", + "description": "Disables the anonymization of logs" + }, + "auto_reload": { + "name": "Auto Reload", + "description": "Automatically reloads scripts when they change" + } + } + }, + "friend_tracker": { + "description": "Records friend's activity on Snapchat", + "properties": { + "allow_running_in_background": { + "name": "Allow Running in Background", + "description": "Allows the tracker to run in the background. Note: This will significantly drain your battery" + }, + "record_messaging_events": { + "description": "Records messaging events such as opening a snap, reading a message, etc.", + "name": "Record Messaging Events" + }, + "auto_purge": { + "name": "Auto Purge", + "description": "Automatically deletes cached events that are older than the specified amount of time" + } + }, + "name": "Friend Tracker" + } + }, + "options": { + "add_friend_source_spoof": { + "added_by_group_chat": "By Group Chat", + "added_by_qr_code": "By QR Code", + "added_by_community": "By Community", + "added_by_username": "By Username", + "added_by_mention": "By Mention", + "added_by_quick_add": "By Quick Add (high risk of being banned)" + }, + "bypass_video_length_restriction": { + "single": "Single media", + "split": "Split media" + }, + "old_bitmoji_selfie": { + "2d": "2D Bitmoji", + "3d": "3D Bitmoji" + }, + "disable_permission_requests": { + "read_media_images": "Read Media Images", + "read_media_video": "Read Media Video", + "camera": "Camera", + "microphone": "Microphone", + "location": "Location", + "read_contacts": "Read Contacts", + "notifications": "Notifications", + "nearby_devices": "Nearby Devices", + "phone_calls": "Phone Calls" + }, + "app_appearance": { + "always_light": "Always Light", + "always_dark": "Always Dark" + }, + "friend_feed_menu_buttons": { + "auto_download": "⬇️ Auto Download", + "auto_save": "💬 Auto Save Messages", + "unsaveable_messages": "⬇️ Unsaveable Messages", + "e2e_encryption": "🔒 Use E2E Encryption", + "conversation_info": "👤 Conversation Info", + "stealth": "👻 Stealth Mode", + "mark_snaps_as_seen": "👀 Mark Snaps as seen", + "mark_stories_as_seen_locally": "👀 Mark Stories as seen locally", + "auto_open_snaps": "📷 Auto Open Snaps" + }, + "path_format": { + "create_author_folder": "Create folder for each author", + "append_username": "Add the username to the file name", + "append_date_time": "Add the date and time to the file name", + "create_source_folder": "Create folder for each media source type", + "append_source": "Add the media source to the file name", + "append_hash": "Add a unique hash to the file name" + }, + "auto_download_sources": { + "friend_stories": "Friend Stories", + "public_stories": "Public Stories", + "spotlight": "Spotlight", + "friend_snaps": "Friend Snaps" + }, + "logging": { + "started": "Started", + "success": "Success", + "progress": "Progress", + "failure": "Failure" + }, + "notifications": { + "chat_screenshot": "Screenshot", + "chat_screen_record": "Screen Record", + "snap_replay": "Snap Replay", + "camera_roll_save": "Camera Roll Save", + "chat": "Chat", + "chat_reply": "Chat Reply", + "snap": "Snap", + "typing": "Typing", + "stories": "Stories", + "chat_reaction": "DM Reaction", + "group_chat_reaction": "Group Reaction", + "initiate_audio": "Incoming Audio Call", + "abandon_audio": "Missed Audio Call", + "initiate_video": "Incoming Video Call", + "abandon_video": "Missed Video Call", + "speaking": "Talking" + }, + "gallery_media_send_override": { + "ORIGINAL": "Original", + "NOTE": "Audio Note", + "SNAP": "Snap", + "always_ask": "Always Ask" + }, + "strip_media_metadata": { + "hide_caption_text": "Hide Caption Text", + "hide_snap_filters": "Hide Snap Filters", + "hide_extras": "Hide Extras (e.g. mentions)", + "remove_audio_note_duration": "Remove Audio Note Duration", + "remove_audio_note_transcript_capability": "Remove Audio Note Transcript Capability" + }, + "hide_ui_components": { + "hide_profile_call_buttons": "Remove Profile Call Buttons", + "hide_chat_call_buttons": "Remove Chat Call Buttons", + "hide_live_location_share_button": "Remove Live Location Share Button", + "hide_stickers_button": "Remove Stickers Button", + "hide_voice_record_button": "Remove Voice Record Button", + "hide_unread_chat_hint": "Remove Unread Chat Hint", + "hide_post_to_story_buttons": "Remove Post to Story buttons before sending a Snap" + }, + "hide_story_suggestions": { + "hide_suggested_friend_stories": "Hide suggested friend stories", + "hide_my_stories": "Hide My Stories" + }, + "home_tab": { + "map": "Map", + "chat": "Chat", + "camera": "Camera", + "discover": "Discover", + "spotlight": "Spotlight" + }, + "disable_confirmation_dialogs": { + "remove_friend": "Remove Friend", + "block_friend": "Block Friend", + "ignore_friend": "Ignore Friend", + "hide_friend": "Hide Friend", + "hide_conversation": "Hide Conversation", + "clear_conversation": "Clear Conversation from Friend Feed", + "erase_message": "Erase Message" + }, + "auto_reload": { + "snapchat_only": "Snapchat Only", + "all": "All (Snapchat + PurrfectSnap)" + }, + "edit_text_override": { + "multi_line_chat_input": "Multi Line Chat Input", + "bypass_text_input_limit": "Bypass Text Input Limit" + }, + "auto_purge": { + "never": "Never", + "1_hour": "1 Hour", + "3_hours": "3 Hours", + "6_hours": "6 Hours", + "12_hours": "12 Hours", + "1_day": "1 Day", + "3_days": "3 Days", + "1_week": "1 Week", + "2_weeks": "2 Weeks", + "1_month": "1 Month", + "3_months": "3 Months", + "6_months": "6 Months" + }, + "disable_story_sections": { + "friends": "Friends", + "discover": "Discover", + "following": "Following" + }, + "disable_cameras": { + "back": "Back Camera", + "front": "Front Camera" + }, + "message_indicators": { + "encryption_indicator": "Adds a 🔒 icon next to messages that have been sent only to you", + "location_indicator": "Adds a 📍 icon to snaps when they have been sent with location enabled", + "platform_indicator": "Adds the platform icon from which a media was sent (e.g. Android, iOS, Web)", + "ovf_editor_indicator": "Indicates if a snap has been sent using OVF Editor", + "director_mode_indicator": "Adds a ✏️ icon to snaps when they have been sent using Director Mode, which can be used to send gallery images as snaps" + }, + "auto_mark_as_read": { + "conversation_read": "Mark conversation as read upon sending a message", + "snap_reply": "Mark snaps as read when replying to them" + }, + "friend_mutation_notifier": { + "remove_friend": "Notify when someone removes you as a friend", + "birthday_changes": "Notify when someone changes their birthday", + "bitmoji_selfie_changes": "Notify when someone changes their Bitmoji selfie", + "bitmoji_scene_changes": "Notify when someone changes their Bitmoji scene", + "bitmoji_avatar_changes": "Notify when someone changes their Bitmoji avatar", + "bitmoji_background_changes": "Notify when someone changes their Bitmoji background" + } + } + }, + "friend_menu_option": { + "preview": "Preview", + "mark_snaps_as_seen": "Mark Snaps as seen", + "mark_stories_as_seen_locally": "Mark Stories as seen locally", + "stealth_mode": "Stealth Mode", + "auto_download_blacklist": "Auto Download Blacklist", + "anti_auto_save": "Anti Auto Save" + }, + "content_type": { + "FAMILY_CENTER_INVITE": "Family Center Invite", + "CREATIVE_TOOL_ITEM": "Creative Tool Item", + "FAMILY_CENTER_ACCEPT": "Family Center Accept", + "FAMILY_CENTER_LEAVE": "Family Center Leave", + "STATUS_PLUS_GIFT": "Status Plus Gift", + "MAP_REACTION": "Map Reaction", + "TINY_SNAP": "­Tiny Snap", + "STATUS_COUNTDOWN": "Countdown", + "LOCATION": "Location", + "STATUS_SAVE_TO_CAMERA_ROLL": "Saved to Camera Roll", + "STATUS_CONVERSATION_CAPTURE_RECORD": "Screen Record", + "STATUS_CALL_MISSED_VIDEO": "Missed Video Call", + "STATUS_CONVERSATION_CAPTURE_SCREENSHOT": "Screenshot", + "STATUS_CALL_MISSED_AUDIO": "Missed Audio Call", + "LIVE_LOCATION_SHARE": "Live Location Share", + "CHAT": "Chat", + "SNAP": "Snap", + "EXTERNAL_MEDIA": "External Media", + "NOTE": "Audio Note", + "STICKER": "Sticker", + "STATUS": "Status", + "SHARE": "Share" + }, + "better_notifications": { + "button": { + "reply": "Reply", + "download": "Download", + "mark_as_read": "Mark as Read" + } + }, + "profile_picture_downloader": { + "button": "Download Profile Picture", + "title": "Profile Picture Downloader", + "avatar_option": "Avatar", + "background_option": "Background" + }, + "call_start_confirmation": { + "dialog_title": "Start Call", + "dialog_message": "Are you sure you want to start a call?" + }, + "download_processor": { + "attachment_type": { + "snap": "Snap", + "sticker": "Sticker", + "external_media": "External Media", + "note": "Note", + "original_story": "Original Story", + "gif": "GIF" + }, + "processing_toast": "Processing {path}...", + "failed_generic_toast": "Failed to download", + "failed_to_create_preview_toast": "Failed to create preview", + "failed_processing_toast": "Failed processing {error}", + "failed_gallery_toast": "Failed saving to gallery {error}", + "select_attachments_title": "Select attachments", + "download_started_toast": "Download started", + "unsupported_content_type_toast": "Unsupported content type!", + "failed_no_longer_available_toast": "Media no longer available", + "no_attachments_toast": "No attachments found!", + "already_queued_toast": "Media already in queue!", + "already_downloaded_toast": "Media already downloaded!", + "dash_no_chapter": "No chapter found", + "dash_dialog": { + "title": "Download dash media", + "segment_text": "Segment {from} - {to}", + "download_all": "Download All" + }, + "download_toast": "Downloading {path}..." + }, + "streaks_reminder": { + "notification_title": "Streaks", + "notification_text": "You will lose your Streak with {friend} in {hoursLeft} hours" + }, + "material3_strings": { + "date_range_picker_scroll_to_next_month": "Next Month", + "date_picker_today_description": "Today", + "date_range_picker_day_in_range": "Selected", + "date_input_invalid_for_pattern": "Invalid Date", + "date_input_invalid_year_range": "Invalid Year", + "date_input_invalid_not_allowed": "Invalid Date", + "date_range_input_invalid_range_input": "Invalid Date Range", + "date_range_picker_scroll_to_previous_month": "Previous month", + "date_range_picker_start_headline": "From", + "date_range_picker_end_headline": "To", + "date_picker_switch_to_input_mode": "Input", + "date_range_picker_title": "Select date range", + "date_picker_switch_to_calendar_mode": "Calendar" + }, + "send_override_dialog": { + "title": "Send media as", + "duration": "Duration: {duration}", + "saveable_snap_hint": "Make Snap saveable in the chat", + "unlimited_duration": "Unlimited", + "schedule": "Schedule", + "select_time": "Select time", + "select": "Select" + }, + "media_download_source": { + "none": "None", + "pending": "Pending", + "chat_media": "Chat Media", + "story": "Story", + "public_story": "Public Story", + "spotlight": "Spotlight", + "profile_picture": "Profile Picture", + "story_logger": "Story Logger", + "message_logger": "Message Logger", + "merged": "Merged", + "voice_call": "Voice Call" + }, + "chat_action_menu": { + "preview_button": "Preview", + "download_button": "Download", + "delete_logged_message_button": "Delete Logged Message", + "convert_message": "Convert Message", + "edit_message": "Edit Message", + "show_chat_edit_history": "Show Chat Edit History" + }, + "opera_context_menu": { + "download": "Download Media", + "show_debug_info": "Show Debug Info", + "sent_at": "Sent at {date}", + "expires_at": "Expires at {date}", + "created_at": "Created at {date}", + "media_size": "Media size: {size}", + "media_duration": "Media duration: {duration} ms" + }, + "modal_option": { + "profile_info": "Profile Info", + "close": "Close" + }, + "gallery_media_send_override": { + "multiple_media_toast": "You can only send one media at a time" + }, + "mark_as_seen": { + "no_unseen_snaps_toast": "No unseen Snaps found!", + "seen_toast": "Marked as seen!", + "unseen_toast": "Marked as unseen!", + "already_seen_toast": "Already marked as seen!", + "already_unseen_toast": "Already marked as unseen!" + }, + "conversation_preview": { + "streak_expiration": "expires in {day} days {hour} hours {minute} minutes", + "total_messages": "Total sent/received messages: {count}", + "title": "Preview", + "unknown_user": "Unknown User", + "no_messages": "No messages found!" + }, + "profile_info": { + "title": "Profile Info", + "first_created_username": "First Created Username", + "mutable_username": "Mutable Username", + "display_name": "Display Name", + "added_date": "Added Date", + "birthday": "Birthday : {month} {day}", + "hidden_birthday": "Birthday : Hidden", + "friendship": "Friendship", + "add_source": "Add Source", + "snapchat_plus_state": { + "subscribed": "Subscribed", + "not_subscribed": "Not Subscribed" + }, + "snapchat_plus": "Snapchat Plus" + }, + "friendship_link_type": { + "mutual": "Mutual", + "outgoing": "Outgoing", + "blocked": "Blocked", + "deleted": "Deleted", + "following": "Following", + "suggested": "Suggested", + "incoming": "Incoming", + "incoming_follower": "Incoming Follower" + }, + "bulk_messaging_action": { + "choose_action_title": "Choose an action", + "progress_status": "Processing {index} of {total}", + "selection_dialog_continue_button": "Continue", + "confirmation_dialog": { + "title": "Are you sure?", + "message": "This will affect all selected friends. This action cannot be undone." + }, + "actions": { + "remove_friends": "Remove Friends", + "clear_conversations": "Clear Conversations" + } + }, + "chat_export": { + "exporter_dialog": { + "select_conversations_title": "Select Conversations", + "text_field_selection": "{amount} Selected", + "text_field_selection_all": "All", + "export_file_format_title": "Export File Format", + "message_type_filter_title": "Filter Messages By Type", + "amount_of_messages_title": "Amount of Messages (leave it blank for all)", + "download_medias_title": "Download Media's" + }, + "dialog_negative_button": "Cancel", + "dialog_positive_button": "Export", + "exported_to": "Exported to {path}", + "exporting_chats": "Exporting Chats...", + "processing_chats": "Processing {amount} conversations...", + "export_fail": "Failed To Export Conversation {conversation}", + "writing_output": "Writing Output...", + "finished": "Done! You Can Now Close This Dialog.", + "no_messages_found": "No Messages Found!", + "exporting_message": "Exporting {conversation}..." + }, + "button": { + "ok": "OK", + "positive": "Yes", + "negative": "No", + "cancel": "Cancel", + "open": "Open", + "download": "Download" + }, + "half_swipe_notifier": { + "notification_channel_name": "Half Swipe", + "notification_content_dm": "{friend} Just Half-Swiped Into Your Chat For {duration} Seconds", + "notification_content_group": "{friend} Just Half-Swiped Into {group} For {duration} Seconds" + }, + "end_to_end_encryption": { + "confirmation_dialogs": { + "title": "End-to-end encryption", + "confirmation_1": "WARNING: This will overwrite your existing key. You will loose access to all encrypted messages from this friend. Are you sure you want to continue?", + "confirmation_2": "Are you REALLY sure you want to continue? This is your last chance to back out." + }, + "accept_secret_key_failure_toast": "Failed to accept secret key", + "outgoing_secret_message": "Key exchange response", + "toolbox": { + "no_shared_key": "You don't have a shared secret with this friend yet. Click below to initiate a new one.", + "shared_key_fingerprint": "Your fingerprint is:\n\n{fingerprint}\n\nMake sure to check if it matches your friend's fingerprint!", + "initiate_exchange_button": "Initiate Key Exchange" + }, + "unencrypted_conversation_send_failure_toast": "You can't send encrypted content to both encrypted and unencrypted conversations!", + "native_hooks_send_failure_toast": "Failed to send! Please enable Native Hooks in the settings.", + "no_participants_to_encrypt_toast": "You don't have any friends in this conversation to encrypt messages with!", + "encryption_failed_toast": "Failed to encrypt message! Check logcat for more details.", + "accept_public_key_success_toast": "Public key successfully accepted!", + "accept_secret_key_success_toast": "Done! You can now send and receive encrypted messages with this friend.", + "accept_public_key_failure_toast": "Failed to accept public key", + "accept_secret_button": "Accept Secret", + "accept_public_key_button": "Accept Public Key", + "outgoing_pk_message": "Key exchange request", + "incoming_pk_message": "You just received a public key request. Click below to accept it.", + "incoming_secret_message": "Your friend just accepted your public key. Click below to accept the secret." + }, + "biometric_auth": { + "subtitle": "Please authenticate to unlock Snapchat", + "unlock_button": "Unlock", + "title": "Unlock Snapchat" + }, + "auto_open_snaps": { + "title": "Auto Open Snaps", + "notification_content": "{count} Snaps opened" + }, + "friend_mutation_observer": { + "notification_channel_name": "Friend Mutation Observer", + "bitmoji_scene_changed": "{username} has changed their Bitmoji scene", + "friend_removed": "{username} has removed you as a friend", + "birthday_removed": "{username} has removed their birthday ({birthday})", + "birthday_added": "{username} has added their birthday ({birthday})", + "birthday_changed": "{username} has changed their birthday from {oldBirthday} to {newBirthday}", + "bitmoji_selfie_changed": "{username} has changed their Bitmoji selfie", + "bitmoji_avatar_changed": "{username} has changed their Bitmoji avatar", + "bitmoji_background_changed": "{username} has changed their Bitmoji background" + } +} diff --git a/common/src/main/assets/lang/en_US.json b/common/src/main/assets/lang/en_US.json index 6264233a..fbb294a1 100644 --- a/common/src/main/assets/lang/en_US.json +++ b/common/src/main/assets/lang/en_US.json @@ -2,16 +2,16 @@ "setup": { "dialogs": { "select_language": "Select Language", - "save_folder": "PurrfectSnap requires Storage permissions to download and Save Media from Snapchat.\nPlease choose the location where media should be downloaded to.", + "save_folder": "Choose where to save downloads", "select_save_folder_button": "Select Folder" }, "mappings": { - "dialog": "Generating Mappings, this may take a while ...", + "dialog": "Generating Mappings...", "generate_failure_no_snapchat": "PurrfectSnap was unable to detect Snapchat, please try reinstalling Snapchat.", "generate_failure": "An error occurred while trying to generate mappings, please try again." }, "permissions": { - "dialog": "To continue you need to fit the following requirements:", + "dialog": "Complete these essentials to continue:", "notification_access": "Notification Access", "battery_optimization": "Battery Optimization", "display_over_other_apps": "Display Over Other Apps", @@ -33,6 +33,8 @@ "logger_history": "Logger History", "logged_stories": "Logged Stories", "friend_tracker": "Friend Tracker", + "friend_tracker_catalog": "Friend Tracker Catalog", + "manage_friend_tracker_repos": "Manage Friend Tracker Repositories", "edit_rule": "Edit Rule", "file_imports": "File Imports", "manage_repos": "Manage Repositories", @@ -40,24 +42,28 @@ "manage_scope": "Manage Scope", "messaging_preview": "Preview", "scripts": "Scripts", + "manage_script_repos": "Manage Script Repositories", + "view_logger_history": "Logger History", "better_location": "Better Location" }, + "navigation": { + "customize_bottom_bar_title": "Customize Bottom Bar", + "customize_bottom_bar_subtitle": "Pick which tabs show on your home screen", + "available_tabs_title": "Available Tabs", + "shown_tabs_title": "Shown Tabs", + "reset_button": "Reset", + "done_button": "Done" + }, "sections": { "home": { - "version_title": "v{versionName} · forked by Eternal", + "version_title": "v{versionName} \u00b7 by Eternal", "update_title": "PurrfectSnap Update", "update_content": "Version {version} is available!", "update_button": "Download", "debug_build_summary_title": "You are running a debug build of PurrfectSnap", "debug_build_summary_content": "Version {versionName} ({versionCode})", "debug_build_summary_date": "Build date: {date} ({days} days ago)", - "quick_actions_title": "Quick Actions", - "download_icon_description": "Download", - "completed_icon_description": "Completed", - "failed_icon_description": "Failed", - "manage_quick_actions_description": "Manage Quick Actions", - "quick_actions_icon_description": "Quick Actions", - "add_quick_action_description": "Add Quick Action" + "quick_actions_title": "Quick Actions" }, "home_logs": { "no_logs_hint": "No logs available", @@ -74,47 +80,42 @@ "success_toast": "Done!", "message_logger_summary": "{messageCount} messages\n{storyCount} stories", "export_button": "Export", - "view_button": "View", "clear_button": "Clear", - "backup_button": "Backup", - "restore_button": "Restore", "view_logger_history_button": "View Logger History", - "friend_notes_title": "Friend Notes", - "friend_notes_description": "Backup or restore your friend notes.", - "friend_notes_backup_success": "Backup successful", - "friend_notes_backup_failure": "Failed to backup notes! {error}", - "friend_notes_restore_success": "Restore successful", - "friend_notes_restore_failure": "Failed to restore notes! {error}", - "friend_notes_no_notes_to_backup": "No notes to backup", + "ui_settings_title": "UI Settings", + "haptic_feedback_label": "Haptic Feedback", "updates_title": "Updates", - "auto_update_check": "Auto check for updates", - "update_check_frequency": "Update check frequency", + "auto_update_check": "Auto Update Check", "update_check_frequency_daily": "Daily", "update_check_frequency_weekly": "Weekly", "update_check_frequency_monthly": "Monthly", - "theme_icon_description": "Theme", + "update_notification_channel_name": "Updates", + "update_notification_channel_description": "Get notified when new releases are available", + "update_notification_title": "New update available", + "update_notification_text": "Tap to open PurrfectSnap and download the latest build.", "app_theme_title": "App Theme", + "theme_icon_description": "Open theme chooser", "theme_mode_system": "System", "theme_mode_light": "Light", "theme_mode_dark": "Dark", - "ui_settings_title": "UI Settings", - "haptic_feedback_label": "Haptic Feedback", - "test_mode_label": "Test Mode (FOR DEBUGGING ONLY)", + "friend_notes_title": "Friend Notes", + "friend_notes_description": "Manage and backup your friend notes", + "friend_notes_no_notes_to_backup": "No notes to back up yet", + "friend_notes_backup_success": "Friend notes backed up", + "friend_notes_restore_success": "Friend notes restored", + "backup_button": "Backup", + "restore_button": "Restore", + "view_button": "View", + "customize_bottom_bar_title": "Customize Bottom Bar", + "customize_bottom_bar_subtitle": "Pick which tabs show on your home screen", + "available_tabs_title": "Available Tabs", + "reset_button": "Reset", + "done_button": "Done", + "clear_friend_feed": "Clear Friend Feed", + "test_mode_label": "Enable PurrAura", "disable_feature_loading_label": "Disable Feature Loading", "disable_auto_mapper_label": "Disable Auto Mapper", - "disable_bypass_indicator_label": "Disable Bypass Status Indicator", - "update_notification_channel_name": "PurrfectSnap Updates", - "update_notification_channel_description": "Notifications for PurrfectSnap updates", - "update_notification_title": "PurrfectSnap Update Available", - "update_notification_text": "Version %s is now available.", - "export_database_failed_toast": "Failed to export database! {message}", - "clear_messages_failed_toast": "Failed to clear messages! {message}", - "clear_file_failed_toast": "Failed to clear file! {message}", - "debug_file_config": "Configuration", - "debug_file_mappings": "Mappings", - "debug_file_message_logger": "Message Logger", - "debug_file_pinned_best_friend": "Pinned Best Friend", - "debug_file_native_sig_cache": "Native Signature Cache" + "disable_bypass_indicator_label": "Disable Bypass Indicator" }, "tasks": { "no_tasks": "No tasks", @@ -125,21 +126,7 @@ "remove_all_tasks_title": "Are you sure you want to remove all tasks?", "delete_files_option": "Also delete files", "remove_selected_tasks_confirm": "Remove {count} tasks?", - "remove_all_tasks_confirm": "Remove all tasks?", - "clear_tasks_description": "Clear tasks", - "file_not_found_icon_description": "File not found", - "image_icon_description": "Image", - "video_icon_description": "Video", - "audio_icon_description": "Audio", - "file_icon_description": "File", - "download_icon_description": "Download", - "chat_action_icon_description": "Chat Action", - "cancel_icon_description": "Cancel", - "success_icon_description": "Success", - "failure_icon_description": "Failure", - "cancelled_icon_description": "Cancelled", - "task_status_failure": "Failure", - "task_status_cancelled": "Cancelled" + "remove_all_tasks_confirm": "Remove all tasks?" }, "features": { "disabled": "Disabled", @@ -153,7 +140,9 @@ "saved_config_snackbar": "Config saved", "older_required": "This feature requires Snapchat v{version} or older to work correctly", "newer_required": "This feature requires Snapchat v{version} or newer to work correctly", - "search_button": "Search" + "search_button": "Search", + "clear_history": "Clear search history", + "subtitle": "Search and manage features" }, "manage_rule_feature": { "disable_state_option": "Disabled", @@ -170,8 +159,12 @@ "social": { "friends_tab": "Friends", "groups_tab": "Groups", - "empty_hint": "(empty)", - "streaks_expiration_short": "{hours}h" + "empty_hint": "Your list is empty for now", + "friends_empty_title": "No friends added yet", + "groups_empty_title": "No groups synced yet", + "streaks_expiration_short": "{hours}h", + "social_tagline": "Manage scopes, streaks, and previews", + "social_empty_hint": "Tap the + button to sync friends or groups." }, "manage_scope": { "logged_stories_button": "Show Logged Stories", @@ -185,32 +178,21 @@ "streaks_expiration_text_expired": "Expired", "reminder_button": "Set Reminder", "delete_scope_confirm_dialog_title": "Are you sure you want to delete a {scope}?", - "notes_placeholder": "Click to add a note", - "invalid_key_size_32_bytes": "Invalid key size (must be 32 bytes)", - "successfully_imported_key": "Successfully imported key", - "failed_to_import_key": "Failed to import key: {message}", - "export_base64_button": "Export Base64", - "import_base64_button": "Import Base64" + "notes_placeholder": "Click to add a note" }, "logged_stories": { "story_failed_to_load": "Failed to load", "no_stories": "No stories found", - "save_from_cache_button": "Save from Cache", - "downloaded_to_path": "Downloaded to {path}", - "download_failed": "Download failed: {message}", - "posted_at": "Posted at {date}", - "created_at": "Created at {date}", - "failed_to_open_file": "Failed to open file. Check logs for more info", - "failed_to_get_file": "Failed to get file" + "save_from_cache_button": "Save from Cache" }, "messaging_preview": { - "processed_messages_toast": "Processed {count} messages", - "processed_messages_text": "Processed {count} messages", - "close_button_description": "Close", "bridge_connection_failed": "Failed to connect to bridge. Make sure Snapchat is running in the background", + "bridge_connection_error": "Failed to connect to bridge. Make sure Snapchat is running in the background", "bridge_init_failed": "Failed to initialize messaging bridge. Make sure Snapchat is running in the background", "message_fetch_failed": "Failed to fetch messages", "no_message_hint": "No message", + "subtitle": "Hold to select", + "actions_title": "Conversation Actions", "save_selection_option": "Save Selection", "save_all_option": "Save All", "unsave_selection_option": "Unsave Selection", @@ -218,17 +200,13 @@ "mark_selection_as_seen_option": "Mark selected Snap as seen", "mark_all_as_seen_option": "Mark all Snaps as seen", "delete_selection_option": "Delete Selection", - "delete_all_option": "Delete All" + "delete_all_option": "Delete All", + "processed_message_toast": "Processed {count} messages", + "processed_messages_toast": "Processed {count} messages", + "processed_messages_text": "Processed {count}", + "close_button_description": "Clear selection" }, "logger_history": { - "download_started_toast": "Download started!", - "download_success_toast": "Downloaded to {path}", - "download_failed_toast": "Failed to download {message}", - "edited_at_text": "{message} (edited at {date})", - "download_button": "Download", - "select_conversation_placeholder": "Select a conversation", - "close_button_description": "Close", - "search_button_description": "Search", "list_friend_format": "Friend {name}", "list_group_format": "Group {name}", "no_more_messages": "No more messages", @@ -237,8 +215,7 @@ "empty_message": "Empty Chat Message", "message_parse_failed": "Failed to parse message", "unknown_sender": "Unknown Sender", - "download_attachment_failed_toast": "Failed to download attachment", - "log_header_format": "{username} ({type}) - {date}" + "download_attachment_failed_toast": "Failed to download attachment" }, "file_imports": { "import_file_button": "Import File", @@ -255,7 +232,9 @@ "latitude_dialog_hint": "Latitude", "longitude_dialog_hint": "Longitude", "save_dialog_button": "Save", - "choose_location_button": "Choose Location", + "choose_location_button": "Pick a Location", + "manual_coordinates_hint": "Fine-tune the coordinates manually.", + "saved_coordinates_subtitle": "Manage your saved spoof locations", "teleport_to_friend_button": "Teleport to Friend", "spoof_location_toggle": "Spoof Location", "suspend_location_updates": "Suspend Location Updates", @@ -266,11 +245,7 @@ "teleport_to_friend_title": "Teleport to Friend", "search_bar": "Search", "no_friends_map": "No friends on the map", - "no_friends_found": "No friends found", - "edit_location_button_description": "Edit Location", - "add_icon_description": "Add", - "edit_icon_description": "Edit", - "delete_icon_description": "Delete" + "no_friends_found": "No friends found" } }, "dialogs": { @@ -280,8 +255,10 @@ "fetch_error": "Failed to fetch data", "category_groups": "Groups", "category_friends": "Friends", - "participants_text": "{count} participants", - "search_icon_description": "Search" + "participants_text": "{count} participants" + }, + "scripting": { + "repo_hint": "Paste a repository URL" }, "scripting_warning": { "title": "Warning", @@ -292,6 +269,10 @@ "content": "Are you sure you want to reset the config?", "success_toast": "Config reset successfully" }, + "quick_actions_dialog": { + "title": "Quick Actions", + "subtitle": "Access your favorite tools faster" + }, "export_config": { "title": "Export Sensitive Data?", "content": "Do you want to export the config with sensitive data? (Such as location coordinates, etc.)" @@ -303,252 +284,192 @@ "file_imports": { "no_files_settings_hint": "No files found. Make sure you have imported the required files in the File Imports section", "settings_select_file_hint": "Select an imported file" - }, - "quick_actions_dialog": { - "title": "Edit Quick Actions", - "subtitle": "Select and size your quick actions." } }, - "friend_tracker": { - "rules_tab": "Rules", - "logs_tab": "Logs", - "export_dialog_title": "Export", - "bulk_export_button": "Bulk Export", - "individual_export_button": "Individual Export", - "invalid_import_type_dialog_title": "Invalid Import Type", - "invalid_import_type_dialog_text": "The selected file is not compatible with this import type. Please select the correct import type.", - "import_dialog_title": "Import", - "bulk_import_button": "Bulk Import", - "individual_import_button": "Individual Import", - "import_button_description": "Import", - "export_button_description": "Export", - "export_button": "Export", - "delete_button_description": "Delete", - "delete_button": "Delete", - "catalog_button_description": "Catalog", - "catalog_button": "Catalog", - "add_rule_button_description": "Add Rule", - "add_rule_button": "Add Rule", - "no_rules_found": "No rules found", - "empty_rule_name": "(empty)", - "events_suffix": "events", - "scopes_suffix": "scopes", - "select_rule_to_export_title": "Select Rule to Export", - "deleted_logs_toast": "Deleted {count} logs", - "delete_logs_dialog_title": "Delete logs?", - "deleting_logs_dialog_text": "Deleting {count} logs...", - "delete_logs_dialog_confirm_text": "This will delete logs based on the current filter and the search query. This action cannot be undone.", - "exported_logs_toast": "Exported logs!", - "export_logs_failed_toast": "Failed to export logs. Check logcat for more details.", - "export_logs_dialog_title": "Export logs?", - "exporting_logs_dialog_text": "Exporting logs...", - "export_logs_dialog_confirm_text": "This will export logs based on the current filter and the search query.", - "export_as_button": "Export as {type}", - "filters_title": "Filters", - "search_by_label": "Search by", - "newest_first_label": "Newest first", - "since_label": "Since", - "until_label": "Until", - "pick_a_date_button": "Pick a date", - "search_placeholder": "Search", - "filter_button_description": "Filter", - "clear_button_description": "Clear", - "no_logs_found": "No logs found", - "log_event_format": "{event} in {conversation}", - "condition_only_inside_conversation": "Only when I'm inside conversation", - "condition_only_outside_conversation": "Only when I'm outside conversation", - "condition_only_when_app_active": "Only when Snapchat is active", - "condition_only_when_app_inactive": "Only when Snapchat is inactive", - "condition_no_push_notification_when_app_active": "No notification when Snapchat is active", - "add_event_dialog_title": "Add Event", - "event_type_label": "Event type", - "triggers_title": "Triggers", - "conditions_title": "Conditions", - "add_button": "Add", - "default_rule_name": "Custom Rule", - "discard_changes_dialog_title": "Discard Changes?", - "discard_changes_dialog_text": "You have unsaved changes. Are you sure you want to discard them?", - "discard_button": "Discard", - "cannot_save_rule_dialog_title": "Cannot Save Rule", - "cannot_save_rule_dialog_text": "A rule must have at least one event to save.", - "duplicate_rule_name_dialog_title": "Duplicate Rule Name", - "duplicate_rule_name_dialog_text": "A rule with this name already exists. Please choose a different name.", - "delete_rule_dialog_title": "Delete Rule", - "delete_rule_dialog_text": "Are you sure you want to delete this rule?", - "new_rule_title": "New Rule", - "edit_rule_title": "Edit Rule", - "back_button_description": "Back", - "save_button_description": "Save", - "general_section_title": "General", - "rule_name_label": "Rule Name", - "author_name_label": "Author Name", - "scope_section_title": "Scope", - "scope_all": "All", - "scope_whitelist": "Whitelist", - "scope_blacklist": "Blacklist", - "select_friends_groups_button": "Select Friends/Groups ({count})", - "events_section_title": "Events", - "add_event_button": "Add Event", - "no_events_text": "No events" - }, - "friend_tracker_catalog": { - "download_failed": "Failed download: {code}", - "error": "Error: {message}", - "no_repos_added": "No repositories added.", - "no_rules_available": "No rules available from any repo.", - "by_author": "by {author}", - "imported_button": "Imported", - "import_button": "Import", - "title": "Friend Tracker Catalog", - "manage_repos_description": "Manage Repositories" - }, - "friend_tracker_export": { - "title": "Export Rules", - "back_button_description": "Back", - "exported_toast": "Friend Tracker Rules Exported!", - "export_failed_toast": "Failed to export rules: {message}", - "save_button": "Save", - "expand_button_description": "Expand" - }, - "friend_tracker_import": { - "title": "Import Rules", - "back_button_description": "Back", - "imported_toast": "Friend Tracker Rules Imported!", - "import_failed_toast": "Failed to import rules: {message}", - "confirm_button": "Confirm", - "expand_button_description": "Expand" - }, - "friend_tracker_repos": { - "invalid_repo_title": "Invalid Repository", - "add_repo_button": "Add Repository", - "add_repo_dialog_title": "Add Repository URL", - "repo_url_label": "Repository URL", - "repo_added_toast": "Repository added successfully!", - "invalid_repo_error": "This does not appear to be a valid Friend Tracker repository.", - "add_repo_failed_toast": "Failed to add repository: {message}", - "add_button": "Add", - "no_repos_added": "No repositories added", - "remove_button": "Remove", - "remove_repo_dialog_title": "Remove Repository", - "remove_repo_dialog_text": "Are you sure you want to remove this repository?" - }, - "navigation": { - "tracker_tab_label": "Tracker", - "customize_bottom_bar_title": "Customize Bottom Bar", - "customize_bottom_bar_subtitle": "Reorder, add or remove tabs. Max of five.", - "shown_tabs_title": "Shown Tabs", - "no_tabs_selected_text": "No tabs selected", - "available_tabs_title": "Available Tabs", - "reset_button": "Reset", - "done_button": "Done" - }, "scripting": { - "script_already_installed": "Script already installed!", - "downloading_script": "Downloading script...", - "script_downloaded": "Script {name} downloaded!", - "download_script_failed": "Failed to download script. Check logs for more details", - "import_script_from_url_title": "Import Script from URL", - "import_script_warning": "Warning: Imported scripts can be harmful to your device. Only import scripts from trusted sources.", - "enter_url_label": "Enter URL here:", - "script_imported": "Script {name} imported!", - "import_failed": "Failed to import script. {message}. Check logs for more details", - "import_button": "Import", - "update_module_button": "Update Module", - "updating_script": "Updating script {name}...", - "module_not_found": "Module not found", - "updated_script": "Updated {name} to version {version}", - "update_module_failed": "Failed to update module. Check logs for more details", - "edit_module_button": "Edit Module", - "open_module_failed": "Failed to open module file. Check logs for more details", - "clear_module_data_button": "Clear Module Data", - "module_data_cleared": "Module data cleared!", - "clear_module_data_failed": "Failed to clear module data. Check logs for more details", - "delete_module_button": "Delete Module", - "deleted_script": "Deleted script {name}!", - "delete_module_failed": "Failed to delete module. Check logs for more details", - "actions_title": "Actions", - "no_description": "No description", - "update_available": "Update available: {version}", "actions_button": "Actions", - "loaded_script": "Loaded script {name}", - "unloaded_script": "Unloaded script {name}", - "enable_script_failed": "Failed to enable script. Check logs for more details", - "disable_script_failed": "Failed to disable script. Check logs for more details", - "select_scripts_folder_toast": "Please select your scripts folder!", - "manage_repos_button": "Manage Repos", - "import_from_url_button": "Import from URL", - "open_scripts_folder_button": "Open Scripts Folder", - "no_settings_for_module": "This module does not have any settings", - "installed_scripts_tab": "Installed Scripts", + "actions_title": "Actions", "catalog_tab": "Catalog", - "no_scripts_folder_selected_title": "No scripts folder selected", - "select_folder_button": "Select folder", - "no_scripts_found_title": "No scripts found.", - "use_catalog_to_add_scripts": "Use the catalog tab to add scripts!", - "ok_button_timeout": "OK ({timeout})", - "documentation_button": "Documentation", + "clear_module_data_button": "Clear data", + "clear_module_data_failed": "Failed to clear module data", + "delete_module_button": "Delete", + "delete_module_failed": "Failed to delete module", + "documentation_button": "Docs", + "download_script_failed": "Failed to download script", + "downloading_script": "Downloading script...", + "edit_module_button": "Edit", + "enter_url_label": "Enter URL", + "import_button": "Import", + "import_from_url_button": "Import from URL", + "import_script_from_url_title": "Import Script from URL", + "import_script_warning": "Only install scripts from sources you trust.", + "installed_scripts_tab": "Installed", + "manage_repos_button": "Manage repos", + "module_data_cleared": "Module data cleared!", + "module_not_found": "Module not found", + "no_description": "No description", + "no_scripts_folder_selected_title": "Select your scripts folder to get started", + "no_scripts_found_title": "No scripts found", + "no_settings_for_module": "This module does not have any settings", + "open_module_failed": "Failed to open module file", + "open_scripts_folder_button": "Open scripts folder", + "script_already_installed": "Script already installed", + "select_folder_button": "Choose Folder", + "select_scripts_folder_toast": "Please select a scripts folder first", + "update_module_button": "Update module", + "update_module_failed": "Failed to update module", + "use_catalog_to_add_scripts": "Use the catalog to add scripts", + "ok_button_timeout": "OK {timeout}", "catalog": { - "script_already_installed": "Script already installed!", - "download_failed": "Failed download: {code}", - "script_downloaded": "Script downloaded!", - "could_not_create_file": "Could not create file.", - "no_scripts_folder_selected": "No scripts folder selected.", - "error": "Error: {message}", - "no_repos_added": "No repositories added.", - "repo_list_info": "Here you can find a list of repos: ", - "link_text": "Link", - "no_scripts_available": "No scripts available from any repo.", - "by_author": "by {author}", - "version": "Version: {version}", + "no_repos_added": "No repositories added", + "repo_list_info": "Find repositories here:", + "link_text": "Repository list", + "script_already_installed": "Script already installed", + "script_downloaded": "Script downloaded", + "could_not_create_file": "Could not create file", + "no_scripts_folder_selected": "Select a scripts folder first", + "no_scripts_available": "No scripts available", "installed_button": "Installed", "download_button": "Download" }, "repos": { - "invalid_repo_title": "Invalid Repository", - "add_repo_button": "Add Repository", - "add_repo_dialog_title": "Add Repository URL", - "repo_url_label": "Repository URL", - "repo_added_toast": "Repository added successfully!", - "invalid_repo_error": "This does not appear to be a valid Script repository.", - "add_repo_failed_toast": "Failed to add repository: {message}", - "add_button": "Add", "no_repos_added": "No repositories added", + "add_repo_button": "Add Repository", + "add_repo_dialog_title": "Add Repository", + "repo_url_label": "Repository URL", + "add_button": "Add", + "invalid_repo_title": "Invalid Repository", + "invalid_repo_error": "This repository is missing required data.", + "repo_added_toast": "Repository added", + "add_repo_failed_toast": "Failed to add repository: {message}", "remove_button": "Remove", "remove_repo_dialog_title": "Remove Repository", "remove_repo_dialog_text": "Are you sure you want to remove this repository?" } }, - "features": { - "config_import": { - "title": "Confirm Import", - "back_button_description": "Back", - "config_imported_toast": "Config Imported!", - "confirm_button": "Confirm", - "expand_button_description": "Expand", - "enable_feature": "Enable Feature", - "enabled": "Enabled", - "disabled": "Disabled" - }, - "config_export": { - "title": "Export Summary", - "back_button_description": "Back", - "save_button": "Save", - "expand_button_description": "Expand", - "enable_feature": "Enable Feature", - "enabled": "Enabled", - "disabled": "Disabled" - } - }, - "manage_repos": { - "title": "Manage {type} Repositories", - "add_repo_button": "Add Repository", - "add_repo_dialog_title": "Add Repository URL", - "repo_url_label": "Repository URL", - "repo_added_successfully": "Repository added successfully!", - "add_repo_failed": "Failed to add repository: {message}", + "friend_tracker": { + "rules_tab": "Rules", + "logs_tab": "Logs", + "catalog_button": "Catalog", + "add_rule_button": "Add Rule", + "import_button": "Import", + "filters_title": "Filters", + "search_by_label": "Search by", + "newest_first_label": "Newest first", + "since_label": "Since", + "pick_a_date_button": "Pick a date", + "export_button": "Export", + "delete_button": "Delete", + "search_placeholder": "Search", + "no_logs_found": "No logs found", + "no_rules_found": "No rules found", + "export_logs_dialog_title": "Export Logs", + "export_logs_dialog_confirm_text": "Export logs using current filters?", + "export_as_button": "Export as {type}", + "new_rule_title": "New Rule", + "edit_rule_title": "Edit Rule", + "general_section_title": "General", + "rule_name_label": "Rule Name", + "default_rule_name": "New Rule", + "author_name_label": "Author", + "scope_section_title": "Scope", + "scope_all": "All Friends/Groups", + "scope_whitelist": "No one except", + "scope_blacklist": "Everyone except", + "events_section_title": "Events", + "events_suffix": "events", + "no_events_text": "No events added yet", + "add_event_dialog_title": "Add Event", + "event_type_label": "Event Type", + "triggers_title": "Triggers", + "conditions_title": "Conditions", + "condition_only_inside_conversation": "Only when I'm inside conversation", + "condition_only_outside_conversation": "Only when I'm outside conversation", + "condition_only_when_app_active": "Only when Snapchat is active", + "condition_only_when_app_inactive": "Only when Snapchat is inactive", + "condition_no_push_notification_when_app_active": "No notification when Snapchat is active", "add_button": "Add", + "cannot_save_rule_dialog_title": "Cannot Save Rule", + "cannot_save_rule_dialog_text": "Fill in the missing fields to save this rule.", + "discard_changes_dialog_title": "Discard changes?", + "discard_changes_dialog_text": "You have unsaved changes. Discard them?", + "rule_subtitle": "Configure triggers and scopes for this rule.", + "discard_button": "Discard", + "enabled_label": "Enabled", + "delete_rule_dialog_title": "Delete Rule", + "delete_rule_dialog_text": "Are you sure you want to delete this rule?", "no_repos_added": "No repositories added", - "remove_button": "Remove" + "import_dialog_title": "Import Rules", + "bulk_import_button": "Bulk import", + "individual_import_button": "Single import", + "invalid_import_type_dialog_title": "Invalid import", + "invalid_import_type_dialog_text": "The selected file type doesn't match the import mode.", + "export_dialog_title": "Export Rules", + "bulk_export_button": "Bulk export", + "individual_export_button": "Single export", + "reverse_order_checkbox": "Reverse Order", + "delete_logs_dialog_title": "Delete Logs", + "delete_logs_dialog_confirm_text": "Delete all logs that match the current filters?", + "select_friends_groups_button": "Select friends / groups" + }, + "friend_tracker_export": { + "title": "Export Friend Tracker", + "save_button": "Save", + "back_button_description": "Go back", + "expand_button_description": "Expand or collapse category", + "exported_toast": "Tracker configuration exported", + "export_failed_toast": "Failed to export tracker: {message}" + }, + "friend_tracker_import": { + "title": "Import Friend Tracker", + "confirm_button": "Import", + "back_button_description": "Go back", + "expand_button_description": "Expand or collapse category", + "imported_toast": "Tracker imported", + "import_failed_toast": "Failed to import tracker: {message}" + }, + "friend_tracker_catalog": { + "title": "Friend Tracker Catalog", + "no_repos_added": "No repositories added" + }, + "friend_tracker_repos": { + "no_repos_added": "No repositories added", + "add_repo_button": "Add Repository", + "add_repo_dialog_title": "Add Repository", + "repo_url_label": "Repository URL", + "add_button": "Add", + "invalid_repo_title": "Invalid Repository", + "invalid_repo_error": "This repository is missing required data.", + "repo_added_toast": "Repository added", + "add_repo_failed_toast": "Failed to add repository: {message}", + "remove_button": "Remove", + "remove_repo_dialog_title": "Remove Repository", + "remove_repo_dialog_text": "Are you sure you want to remove this repository?" + }, + "logger_history": { + "select_conversation_placeholder": "Select a conversation" + }, + "features": { + "config_export": { + "title": "Export Config Summary", + "back_button_description": "Go back", + "save_button": "Save", + "expand_button_description": "Expand or collapse category", + "enabled": "Enabled", + "disabled": "Disabled", + "enable_feature": "Enable Feature" + }, + "config_import": { + "title": "Import Config Summary", + "back_button_description": "Go back", + "confirm_button": "Import", + "expand_button_description": "Expand or collapse category", + "enabled": "Enabled", + "disabled": "Disabled", + "enable_feature": "Enable Feature", + "config_imported_toast": "Config imported successfully", + "config_import_failure_toast": "Failed to import config {error}" + } } }, "rules": { @@ -577,14 +498,6 @@ "whitelist": "Stealth mode" } }, - "hide_typing_indicator": { - "name": "Hide Typing Indicator", - "description": "Prevents anyone from knowing you're typing", - "options": { - "blacklist": "Exclude from Hide Typing Indicator", - "whitelist": "Hide Typing Indicator" - } - }, "auto_save": { "name": "Auto Save", "description": "Saves Chat Messages when viewing them", @@ -620,6 +533,46 @@ }, "exclude_message_logger": { "name": "Exclude From Message Logger" + }, + "auto_reply": { + "name": "Auto Reply", + "description": "Automatically sends replies to incoming messages when you're away", + "options": { + "blacklist": "Exclude from Auto Reply", + "whitelist": "Auto Reply" + } + }, + "auto_delete_sent_messages": { + "name": "Auto Delete Sent Messages", + "description": "Automatically deletes sent messages after a specified time period", + "options": { + "blacklist": "Exclude from Auto Delete Sent Messages", + "whitelist": "Auto Delete Sent Messages" + } + }, + "message_logger": { + "name": "Message Logger", + "description": "Keep a copy of messages even if they are deleted", + "options": { + "blacklist": "Exclude from Message Logger", + "whitelist": "Message Logger" + } + }, + "auto_read": { + "name": "Auto Read", + "description": "Automatically mark snaps and chats as read", + "options": { + "blacklist": "Exclude from Auto Read", + "whitelist": "Auto Read" + } + }, + "hide_typing_indicator": { + "name": "Hide Typing Indicator", + "description": "Prevent others from seeing when you are typing", + "options": { + "blacklist": "Exclude from Hide Typing Indicator", + "whitelist": "Hide typing indicator" + } } } }, @@ -666,13 +619,54 @@ } }, "features": { - "friend_notes": { - "placeholder": "Click to add a note" - }, "notices": { - "unstable": "⚠ Unstable", - "ban_risk": "⚠ This feature may cause bans", - "internal_behavior": "⚠ This may break Snapchat internal behavior" + "unstable": "\u26a0 Unstable", + "ban_risk": "\u26a0 This feature may cause bans", + "internal_behavior": "\u26a0 This may break Snapchat internal behavior" + }, + "options": { + "empty": "Empty", + "walk_radius": { + "empty": "Empty" + }, + "spoof_battery_level": { + "empty": "Empty" + }, + "custom_android_id": { + "empty": "Empty" + }, + "custom_streaks_expiration_format": { + "empty": "Empty" + }, + "preferred_transcription_lang": { + "empty": "Empty" + }, + "custom_emoji_font": { + "empty": "Empty" + }, + "custom_shared_library": { + "empty": "Empty" + }, + "custom_resolution": { + "empty": "Empty" + }, + "custom_path_format": { + "empty": "Empty" + }, + "custom_video_codec": { + "empty": "Empty" + }, + "custom_audio_codec": { + "empty": "Empty" + }, + "double_tap_chat_action_custom_emoji": { + "empty": "Empty" + }, + "unsaveable_messages": { + "blacklist": "Blacklist mode", + "whitelist": "Whitelist mode", + "null": "Disabled" + } }, "properties": { "downloader": { @@ -807,10 +801,6 @@ } } }, - "force_amoled_theme": { - "name": "Amoled Dark Mode", - "description": "Uses a true black background for the dark theme" - }, "map_friend_nametags": { "name": "Enhanced Friend Map Nametags", "description": "Improves the Nametags of friends on the Snapmap" @@ -877,7 +867,7 @@ }, "stealth_mode_indicator": { "name": "Stealth Mode Indicator", - "description": "Adds a 👻 emoji next to conversations in stealth mode" + "description": "Adds a \ud83d\udc7b emoji next to conversations in stealth mode" }, "edit_text_override": { "name": "Edit Text Override", @@ -887,13 +877,13 @@ "name": "Prevent Forced Keyboard", "description": "Prevents Snapchat from automatically popping up the keyboard when you open a conversation" }, + "force_amoled_theme": { + "name": "Force AMOLED Theme", + "description": "Force a true black AMOLED theme across the app UI" + }, "settings_menu": { "name": "Settings Menu", - "description": "Changes the way you open the PurrfectSnap menu", - "options": { - "default": "Default", - "legacy": "Legacy" - } + "description": "Choose between the new and legacy settings menu layouts" } } }, @@ -921,6 +911,10 @@ "name": "Hide Bitmoji Presence", "description": "Prevents your Bitmoji from popping up while in Chat" }, + "hide_typing_notifications": { + "name": "Hide Typing Notifications", + "description": "Prevents anyone from knowing you're typing a message" + }, "unlimited_snap_view_time": { "name": "Unlimited Snap View Time", "description": "Removes the Time Limit for viewing Snaps" @@ -1086,6 +1080,274 @@ "double_tap_chat_action_custom_emoji": { "name": "Double Tap Chat Action Custom Emoji Reaction", "description": "Sets a custom emoji reaction for the double tap chat action" + }, + "auto_reply": { + "name": "Auto Reply", + "description": "Automatically sends replies to incoming messages when you're away", + "properties": { + "allow_running_in_background": { + "name": "Allow Running in Background", + "description": "Allows Auto Reply to run in the background. Note: This will significantly drain your battery" + }, + "cooldown_seconds": { + "name": "Cooldown Seconds", + "description": "Minimum time between auto-replies to the same conversation (in seconds)" + }, + "message_age_threshold": { + "name": "Message Age Threshold", + "description": "Only reply to messages received within this timeframe (in seconds)" + }, + "ai_config": { + "name": "AI Configuration", + "description": "Settings for AI-powered auto-replies", + "properties": { + "enable_ai_replies": { + "name": "Enable AI Replies", + "description": "Use AI to generate intelligent auto-replies instead of template messages" + }, + "ai_provider": { + "name": "AI Provider", + "description": "Select which AI service to use for generating replies" + }, + "ai_endpoint_url": { + "name": "AI Endpoint URL", + "description": "API endpoint URL for the AI service (e.g., OpenAI, local AI server)" + }, + "ai_model": { + "name": "AI Model", + "description": "AI model to use for generating replies (e.g., gpt-3.5-turbo, gpt-4)" + }, + "ai_api_key": { + "name": "AI API Key", + "description": "API key for authenticating with the AI service" + }, + "ai_system_prompt": { + "name": "AI System Prompt", + "description": "System prompt that defines the AI's personality and behavior" + }, + "ai_max_tokens": { + "name": "AI Max Tokens", + "description": "Maximum number of tokens (words) the AI can use in responses" + }, + "ai_temperature": { + "name": "AI Temperature", + "description": "Controls randomness in AI responses (0.0 = deterministic, 2.0 = very random)" + }, + "ai_context_length": { + "name": "AI Context Length", + "description": "Number of previous messages to include as context for AI responses" + }, + "ai_personality_traits": { + "name": "AI Personality Traits", + "description": "Comma-separated personality traits for the AI (e.g., friendly, casual, helpful)" + }, + "ai_response_style": { + "name": "AI Response Style", + "description": "Overall style for AI responses" + }, + "ai_response_language": { + "name": "AI Response Language", + "description": "Language for AI responses (auto = same as received message)" + }, + "ai_use_conversation_history": { + "name": "Use Conversation History", + "description": "Include previous messages as context for more relevant AI responses" + }, + "ai_include_friend_info": { + "name": "Include Friend Info", + "description": "Include friend's name and other available info in AI context" + }, + "ai_fallback_to_template": { + "name": "Fallback to Template", + "description": "Use template messages if AI fails to generate a response" + }, + "ai_request_timeout": { + "name": "AI Request Timeout", + "description": "Maximum time to wait for AI response (in seconds)" + }, + "ai_retry_attempts": { + "name": "AI Retry Attempts", + "description": "Number of times to retry AI requests if they fail" + } + } + }, + "auto_trigger_config": { + "name": "Auto Trigger Configuration", + "description": "Settings for auto-reply triggers and message templates", + "properties": { + "friendSpecificGreeting": { + "name": "Friend Specific Greeting", + "description": "Add friend's name to auto-replies for personalization" + }, + "friendGreeting": { + "name": "Friend Greeting", + "description": "Greeting text to use when friend specific greeting is enabled" + }, + "auto_reply_content_types": { + "name": "Auto Reply Triggers", + "description": "Select which message types should trigger auto-replies" + }, + "chat_messages": { + "name": "Chat Message Replies", + "description": "Auto-reply messages for text chat messages" + }, + "snap_messages": { + "name": "Snap Replies", + "description": "Auto-reply messages for snaps" + }, + "story_share_messages": { + "name": "Story Share Replies", + "description": "Auto-reply messages for story shares" + }, + "story_reply_messages": { + "name": "Story Reply Responses", + "description": "Auto-reply messages for story replies" + }, + "external_media_messages": { + "name": "External Media Replies", + "description": "Auto-reply messages for external media" + }, + "voice_note_messages": { + "name": "Voice Note Replies", + "description": "Auto-reply messages for voice notes" + }, + "sticker_messages": { + "name": "Sticker Replies", + "description": "Auto-reply messages for stickers" + }, + "tiny_snap_messages": { + "name": "Tiny Snap Replies", + "description": "Auto-reply messages for tiny snaps" + }, + "map_reaction_messages": { + "name": "Map Reaction Replies", + "description": "Auto-reply messages for map reactions" + }, + "half_swipe_messages": { + "name": "Half Swipe Messages", + "description": "Auto-reply messages for half swipes" + } + } + } + } + }, + "auto_open_snaps": { + "name": "Auto Open Snaps Settings", + "description": "Configure delay and queue settings for Auto Open Snaps", + "properties": { + "allow_running_in_background": { + "name": "Allow Running in Background", + "description": "Allows Auto Open Snaps to run in the background. Note: This will significantly drain your battery" + }, + "min_delay": { + "name": "Min Delay (ms)", + "description": "Minimum delay in milliseconds before opening a snap" + }, + "max_delay_ms": { + "name": "Max Delay (ms)", + "description": "Maximum delay in milliseconds before opening a snap" + }, + "queue_size": { + "name": "Queue Size", + "description": "Maximum number of snaps to keep in queue" + }, + "retry_attempts": { + "name": "Retry Attempts", + "description": "Number of times to retry opening a snap if it fails" + }, + "retry_delay": { + "name": "Retry Delay (ms)", + "description": "Delay in milliseconds between retry attempts" + } + } + }, + "auto_delete_sent_messages": { + "name": "Auto Delete Sent Messages", + "description": "Automatically deletes sent messages after a specified time period", + "properties": { + "allow_running_in_background": { + "name": "Allow Running in Background", + "description": "Allows Auto Delete Sent Messages to run in the background. Note: This will significantly drain your battery" + }, + "delete_after_value": { + "name": "Delete After (value)", + "description": "Time value before deleting the sent message" + }, + "delete_after_unit": { + "name": "Time Unit", + "description": "Select the time unit for deletion delay" + }, + "message_types": { + "name": "Message Types", + "description": "Select which message types should be auto-deleted" + }, + "show_countdown": { + "name": "Show Countdown", + "description": "Show countdown before deleting the message" + }, + "show_notification": { + "name": "Show Notification", + "description": "Show notification during countdown" + } + } + }, + "instant_translation": { + "name": "Message Translator", + "description": "Automatically translate incoming messages to your preferred language", + "properties": { + "enabled": { + "name": "Enable Message Translator", + "description": "Enable automatic translation of messages" + }, + "source_language": { + "name": "Source Language", + "description": "Language to translate from (use 'auto' for automatic detection)" + }, + "target_language": { + "name": "Target Language", + "description": "Language to translate to" + }, + "show_original": { + "name": "Show Original Text", + "description": "Display the original message text" + }, + "show_translation": { + "name": "Show Translation", + "description": "Display the translated text" + }, + "translation_position": { + "name": "Translation Position", + "description": "Where to display the translation relative to original text" + }, + "auto_translate": { + "name": "Auto Translate", + "description": "Automatically translate messages when received" + }, + "translate_on_tap": { + "name": "Translate on Tap", + "description": "Translate messages when tapped" + }, + "supported_languages": { + "name": "Supported Languages", + "description": "Languages available for translation" + }, + "pause_on_error": { + "name": "Pause on Error", + "description": "Pause translation when service is blocked" + }, + "max_retries": { + "name": "Max Retries", + "description": "Maximum number of retry attempts" + }, + "retry_delay": { + "name": "Retry Delay", + "description": "Delay between retry attempts (milliseconds)" + } + } + }, + "scheduled_send_allow_running_in_background": { + "name": "Allow Scheduled Send to Run in Background", + "description": "Keep scheduled messages processing while Snapchat is in the background" } } }, @@ -1161,6 +1423,26 @@ "name": "Auto Updater", "description": "Automatically checks for new updates" }, + "update_settings": { + "name": "Update Settings", + "description": "Control how PurrfectSnap checks for updates", + "properties": { + "auto_update_check": { + "name": "Auto Update Check" + }, + "update_check_frequency": { + "name": "Update Check Frequency" + } + } + }, + "ui_settings": { + "name": "UI Settings", + "properties": { + "haptic_feedback": { + "name": "Haptic Feedback" + } + } + }, "disable_metrics": { "name": "Disable Metrics", "description": "Blocks sending specific analytic data to Snapchat" @@ -1189,6 +1471,10 @@ "name": "Spotlight Comments Username", "description": "Shows author username in Spotlight comments" }, + "spotlight_comments_username_icon": { + "name": "Spotlight Comments Username Icon", + "description": "Choose which icon is displayed next to usernames in Spotlight comments" + }, "bypass_video_length_restriction": { "name": "Bypass Video Length Restrictions", "description": "Single: sends a single video\nSplit: split videos after editing" @@ -1225,7 +1511,36 @@ }, "rules": { "name": "Rules", - "description": "Manage Automatic Features for individual people" + "description": "Configure automation rules", + "properties": { + "auto_read": { + "name": "Auto Read" + }, + "hide_typing_indicator": { + "name": "Hide Typing Indicator" + }, + "auto_reply": { + "name": "Auto Reply" + }, + "auto_delete_sent_messages": { + "name": "Auto Delete Sent Messages" + }, + "auto_download": { + "name": "Auto Download" + }, + "stealth": { + "name": "Stealth Mode" + }, + "auto_save": { + "name": "Auto Save" + }, + "message_logger": { + "name": "Message Logger" + }, + "unsaveable_messages": { + "name": "Unsaveable Messages" + } + } }, "camera": { "name": "Camera", @@ -1358,6 +1673,26 @@ "remove_mock_location_flag": { "name": "Remove Mock Location Flag", "description": "Prevents Snapchat from detecting Mock location" + }, + "force_wifi_transport_flag": { + "name": "Force Wi-Fi Transport Flag", + "description": "Force network transport to report Wi-Fi instead of mobile data" + }, + "spoof_android_id": { + "name": "Spoof Android ID", + "description": "Override the Android ID sent to Snapchat with a custom value" + }, + "custom_android_id": { + "name": "Custom Android ID", + "description": "Value to use when spoofing the Android ID" + }, + "spoof_device": { + "name": "Spoof Device", + "description": "Present Snapchat as running on another device model" + }, + "device_model": { + "name": "Device Model", + "description": "Choose which device model to spoof" } } }, @@ -1453,7 +1788,7 @@ "properties": { "encrypted_message_indicator": { "name": "Encrypted Message Indicator", - "description": "Adds a 🔒 emoji next to encrypted messages" + "description": "Adds a \ud83d\udd12 emoji next to encrypted messages" }, "force_message_encryption": { "name": "Force Message Encryption", @@ -1535,18 +1870,48 @@ "options": { "app_appearance": { "always_light": "Always Light", - "always_dark": "Always Dark" + "always_dark": "Always Dark", + "null": "Match System" + }, + "auto_reload": { + "snapchat_only": "Reload Snapchat only", + "all": "Reload Snapchat + PurrfectSnap", + "null": "Default" + }, + "walk_radius": { + "null": "Use default radius" + }, + "spoof_battery_level": { + "null": "Use real battery level" }, "friend_feed_menu_buttons": { - "auto_download": "⬇️ Auto Download", - "auto_save": "💬 Auto Save Messages", - "unsaveable_messages": "⬇️ Unsaveable Messages", - "auto_open_snaps": "📷 Auto Open Snaps", - "stealth": "👻 Stealth Mode", - "mark_snaps_as_seen": "👀 Mark Snaps as seen", - "mark_stories_as_seen_locally": "👀 Mark Stories as seen locally", - "conversation_info": "👤 Conversation Info", - "e2e_encryption": "🔒 Use E2E Encryption" + "auto_download": "\u2b07\ufe0f Auto Download", + "auto_save": "\ud83d\udcac Auto Save Messages", + "unsaveable_messages": "\u2b07\ufe0f Unsaveable Messages", + "auto_open_snaps": "\ud83d\udcf7 Auto Open Snaps", + "stealth": "\ud83d\udc7b Stealth Mode", + "auto_reply": "\ud83d\udce8 Auto Reply", + "auto_delete_sent_messages": "\ud83d\uddd1\ufe0f Auto Delete Sent Messages", + "mark_snaps_as_seen": "\ud83d\udc40 Mark Snaps as seen", + "mark_stories_as_seen_locally": "\ud83d\udc40 Mark Stories as seen locally", + "conversation_info": "\ud83d\udc64 Conversation Info", + "e2e_encryption": "\ud83d\udd12 Use E2E Encryption", + "message_logger": "\ud83d\udcdd Message Logger", + "auto_read": "\u2705 Auto Read", + "hide_typing_indicator": "\ud83d\ude48 Hide Typing Indicator" + }, + "schedule_scheduled_for": "Scheduled for {time}", + "schedule_sent_to": "Sent to {recipient}", + "device_model": { + "samsung_s25_ultra": "Samsung Galaxy S25 Ultra", + "google_pixel_10_pro": "Google Pixel 10 Pro", + "oneplus_13": "OnePlus 13", + "xiaomi_15_ultra": "Xiaomi 15 Ultra", + "null": "Device Default" + }, + "settings_menu": { + "default": "Default", + "legacy": "Legacy" }, "path_format": { "create_author_folder": "Create folder for each author", @@ -1554,7 +1919,8 @@ "append_hash": "Add a unique hash to the file name", "append_source": "Add the media source to the file name", "append_username": "Add the username to the file name", - "append_date_time": "Add the date and time to the file name" + "append_date_time": "Add the date and time to the file name", + "append_type": "Add the media type to the file name" }, "auto_download_sources": { "friend_snaps": "Friend Snaps", @@ -1587,12 +1953,119 @@ "abandon_video": "Missed Video Call", "map_live_location": "Map Live Location" }, + "auto_read": { + "blacklist": "Blacklist", + "whitelist": "Whitelist", + "disabled": "Disabled" + }, + "hide_typing_indicator": { + "blacklist": "Blacklist", + "whitelist": "Whitelist", + "disabled": "Disabled" + }, + "auto_delete_sent_messages": { + "blacklist": "Blacklist", + "whitelist": "Whitelist", + "disabled": "Disabled" + }, + "auto_download": { + "blacklist": "Blacklist", + "whitelist": "Whitelist", + "disabled": "Disabled" + }, + "stealth": { + "blacklist": "Blacklist", + "whitelist": "Whitelist", + "disabled": "Disabled" + }, + "auto_save": { + "blacklist": "Blacklist", + "whitelist": "Whitelist", + "disabled": "Disabled" + }, + "message_logger": { + "blacklist": "Blacklist", + "whitelist": "Whitelist", + "disabled": "Disabled" + }, + "auto_reply": { + "blacklist": "Blacklist", + "whitelist": "Whitelist", + "disabled": "Disabled" + }, + "custom_android_id": { + "null": "Use real Android ID" + }, + "add_friend_source_spoof": { + "added_by_username": "By Username", + "added_by_mention": "By Mention", + "added_by_group_chat": "By Group Chat", + "added_by_qr_code": "By QR Code", + "added_by_community": "By Community", + "added_by_quick_add": "By Quick Add (high risk of being banned)", + "added_by_spotlight": "By Spotlight", + "null": "Don't spoof source" + }, + "custom_streaks_expiration_format": { + "null": "System Default" + }, + "preferred_transcription_lang": { + "null": "Use Snapchat Default" + }, + "custom_emoji_font": { + "null": "Default Emoji Font" + }, + "custom_shared_library": { + "null": "Use default library" + }, + "override_front_resolution": { + "null": "Use device default" + }, + "override_back_resolution": { + "null": "Use device default" + }, + "custom_resolution": { + "null": "Use automatic resolution" + }, + "startup_default_camera": { + "front": "Front Camera", + "back": "Back Camera", + "null": "Remember last used" + }, + "front_custom_frame_rate": { + "null": "Device default FPS" + }, + "back_custom_frame_rate": { + "null": "Device default FPS" + }, + "force_voice_note_format": { + "null": "Use Snapchat default" + }, + "custom_path_format": { + "null": "Use default pattern" + }, + "force_image_format": { + "null": "Use Snapchat default" + }, + "custom_video_codec": { + "null": "Default Codec" + }, + "custom_audio_codec": { + "null": "Default Codec" + }, + "preset": { + "null": "Default Preset" + }, + "app_appearance_override": { + "title": "Appearance" + }, "gallery_media_send_override": { "always_ask": "Always Ask", "ORIGINAL": "Original Media", "NOTE": "Audio Note", "SNAP": "Snap", - "SAVEABLE_SNAP": "Saveable Snap" + "SAVEABLE_SNAP": "Saveable Snap", + "null": "Snapchat Default" }, "strip_media_metadata": { "hide_caption_text": "Hide Caption Text", @@ -1622,23 +2095,37 @@ "chat": "Chat", "camera": "Camera", "discover": "Discover", - "spotlight": "Spotlight" + "spotlight": "Spotlight", + "null": "Snapchat Default" }, - "add_friend_source_spoof": { - "added_by_username": "By Username", - "added_by_mention": "By Mention", - "added_by_group_chat": "By Group Chat", - "added_by_qr_code": "By QR Code", - "added_by_community": "By Community", - "added_by_quick_add": "By Quick Add (high risk of being banned)" + "spotlight_comments_username_icon": { + "user": "Username Icon", + "\ud83d\udc64": "Username Icon", + "[\ud83d\udc64]": "Username Icon", + "default": "Username Icon", + "no_icon": "No icon" + }, + "custom_image_upload_format": { + "null": "Automatic" + }, + "update_check_frequency": { + "null": "Auto" + }, + "snapchat_plus": { + "not_subscribed": "Not Subscribed", + "basic": "Basic", + "ad_free": "Ad Free", + "null": "Default" }, "bypass_video_length_restriction": { "single": "Single media", - "split": "Split media" + "split": "Split media", + "null": "Default" }, "old_bitmoji_selfie": { "2d": "2D Bitmoji", - "3d": "3D Bitmoji" + "3d": "3D Bitmoji", + "null": "Default Bitmoji" }, "disable_confirmation_dialogs": { "erase_message": "Erase Message", @@ -1649,10 +2136,6 @@ "hide_conversation": "Hide Conversation", "clear_conversation": "Clear Conversation from Friend Feed" }, - "auto_reload": { - "snapchat_only": "Snapchat Only", - "all": "All (Snapchat + PurrfectSnap)" - }, "edit_text_override": { "multi_line_chat_input": "Multi Line Chat Input", "bypass_text_input_limit": "Bypass Text Input Limit" @@ -1671,6 +2154,11 @@ "3_months": "3 Months", "6_months": "6 Months" }, + "delete_after_unit": { + "seconds": "Seconds", + "minutes": "Minutes", + "hours": "Hours" + }, "disable_story_sections": { "friends": "Friends", "suggested_stories": "Suggested Stories", @@ -1693,11 +2181,11 @@ "phone_calls": "Phone Calls" }, "message_indicators": { - "encryption_indicator": "Adds a 🔒 icon next to messages that have been sent only to you", + "encryption_indicator": "Adds a \ud83d\udd12 icon next to messages that have been sent only to you", "platform_indicator": "Adds the platform icon from which a media was sent (e.g. Android, iOS, Web)", - "location_indicator": "Adds a 📍 icon to snaps when they have been sent with location enabled", + "location_indicator": "Adds a \ud83d\udccd icon to snaps when they have been sent with location enabled", "ovf_editor_indicator": "Indicates if a snap has been sent using OVF Editor", - "director_mode_indicator": "Adds a ✏️ icon to snaps when they have been sent using Director Mode, which can be used to send gallery images as snaps" + "director_mode_indicator": "Adds a \u270f\ufe0f icon to snaps when they have been sent using Director Mode, which can be used to send gallery images as snaps" }, "auto_mark_as_read": { "conversation_read": "Mark conversation as read when sending a message", @@ -1712,22 +2200,149 @@ "bitmoji_background_changes": "Notify when someone changes their Bitmoji background", "bitmoji_scene_changes": "Notify when someone changes their Bitmoji scene" }, - "snapchat_plus": { - "not_subscribed": "Not Subscribed", - "basic": "Basic", - "ad_free": "Ad Free" - }, "double_tap_chat_action": { "like_message": "Like Message", "copy_text": "Copy Text to Clipboard", "delete_message": "Delete Message", "mark_as_read": "Mark as Read", - "custom_emoji_reaction": "Custom Emoji Reaction" + "custom_emoji_reaction": "Custom Emoji Reaction", + "null": "Default" }, - "startup_default_camera": { - "front": "Front Camera", - "back": "Back Camera" + "message_types": { + "CHAT": "Chat", + "SNAP": "Snap", + "NOTE": "Note", + "EXTERNAL_MEDIA": "External Media", + "STICKER": "Sticker" + }, + "double_tap_chat_action_custom_emoji": { + "Custom emoji reaction": "Custom emoji reaction" + }, + "ai_model": { + "gemini-2.5-flash": "Gemini 2.5 Flash" + }, + "ai_api_key": { + "": "Not set" + }, + "ai_system_prompt": { + "You are a helpful and friendly assistant responding to messages on Snapchat. Keep responses natural, casual, and conversational. Avoid being overly formal or robotic. Respond as if you're a real person having a normal conversation.": "You are a helpful and friendly assistant responding to messages on Snapchat. Keep responses natural, casual, and conversational. Avoid being overly formal or robotic. Respond as if you're a real person having a normal conversation." + }, + "ai_provider": { + "gemini": "Gemini", + "deepseek": "DeepSeek", + "openai": "OpenAI" + }, + "ai_personality_traits": { + "friendly, casual, helpful, empathetic": "friendly, casual, helpful, empathetic" + }, + "ai_response_style": { + "casual": "Casual", + "formal": "Formal", + "friendly": "Friendly", + "humorous": "Humorous", + "empathetic": "Empathetic", + "toxic": "Edgy", + "busy": "Busy" + }, + "ai_temperature": { + "0.7": "Balanced (0.7)" + }, + "ai_response_language": { + "auto": "Auto", + "en": "English", + "es": "Spanish", + "fr": "French", + "de": "German", + "it": "Italian", + "pt": "Portuguese", + "ru": "Russian", + "ja": "Japanese", + "ko": "Korean", + "zh": "Chinese", + "ar": "Arabic", + "hi": "Hindi", + "tr": "Turkish", + "pl": "Polish", + "nl": "Dutch", + "sv": "Swedish", + "da": "Danish", + "no": "Norwegian", + "fi": "Finnish" + }, + "friendGreeting": { + "Hey": "Hey" + }, + "half_swipe_messages": { + "[\"I noticed you half-swiped! I'll respond soon.\"]": "I noticed you half-swiped! I'll respond soon." + }, + "tiny_snap_messages": { + "Thanks for the tiny snap!": "Thanks for the tiny snap!" + }, + "voice_note_messages": { + "Thanks for the voice note!": "Thanks for the voice note!" + }, + "chat_messages": { + "Hello! How are you?": "Hello! How are you?" + }, + "story_reply_messages": { + "Thanks for the story reply!": "Thanks for the story reply!" + }, + "external_media_messages": { + "Nice media!": "Nice media!" + }, + "sticker_messages": { + "Cool sticker!": "Cool sticker!" + }, + "snap_messages": { + "Thanks for the snap!": "Thanks for the snap!" + }, + "story_share_messages": { + "Thanks for sharing!": "Thanks for sharing!" + }, + "map_reaction_messages": { + "Thanks for the map reaction!": "Thanks for the map reaction!" + }, + "auto_reply_content_types": { + "chat_messages": "Chat Messages", + "snap_messages": "Snaps", + "story_share_messages": "Story Shares", + "story_reply_messages": "Story Replies", + "external_media_messages": "External Media", + "voice_note_messages": "Voice Notes", + "sticker_messages": "Stickers", + "tiny_snap_messages": "Tiny Snaps", + "map_reaction_messages": "Map Reactions", + "half_swipes": "Half Swipes" + }, + "supported_languages": { + "en": "English", + "es": "Spanish", + "fr": "French", + "de": "German", + "it": "Italian", + "pt": "Portuguese", + "ru": "Russian", + "ja": "Japanese", + "ko": "Korean", + "zh": "Chinese", + "ar": "Arabic", + "hi": "Hindi", + "tr": "Turkish" + }, + "translation_position": { + "above": "Above text", + "below": "Below text", + "inline": "Inline" + }, + "source_language": { + "auto": "Detect automatically" + }, + "target_language": { + "en": "English" } + }, + "friend_notes": { + "placeholder": "Add a note..." } }, "friend_menu_option": { @@ -1760,7 +2375,17 @@ "STATUS_PLUS_GIFT": "Status Plus Gift", "TINY_SNAP": "Tiny Snap", "STATUS_COUNTDOWN": "Countdown", - "MAP_REACTION": "Map Reaction" + "MAP_REACTION": "Map Reaction", + "chat_messages": "Chat Messages", + "snap_messages": "Snaps", + "story_share_messages": "Story Shares", + "story_reply_messages": "Story Replies", + "external_media_messages": "External Media", + "voice_note_messages": "Voice Note", + "sticker_messages": "Sticker", + "tiny_snap_messages": "Tiny Snap", + "map_reaction_messages": "Map Reaction", + "half_swipes": "Half Swipes" }, "media_download_source": { "none": "None", @@ -1839,16 +2464,70 @@ "incoming_follower": "Incoming Follower" }, "bulk_messaging_action": { + "actions.title": "Actions", "choose_action_title": "Choose an action", "progress_status": "Processing {index} of {total}", "selection_dialog_continue_button": "Continue", "confirmation_dialog": { "title": "Are you sure?", - "message": "This will affect all selected friends. This action cannot be undone." + "message": "This will affect all selected , This action cannot be undone." }, "actions": { "remove_friends": "Remove Friends", - "clear_conversations": "Clear Conversations" + "clear_conversations": "Clear Conversations", + "clear_friend_feed": "Clear Friend Feed ({count})", + "unfollow": "Unfollow", + "remove": "Remove" + }, + "leave_groups": "Leave {count} groups", + "left_group_success": "Left group successfully", + "failed_to_leave_group": "Failed to leave group: {error}", + "conversation_types": { + "friends_only": "Friends Only", + "groups_only": "Groups Only", + "both": "Friends & Groups" + }, + "sort_by": "Sort by", + "reverse_order": "Reverse order", + "search_by_name": "Search by name", + "no_friends_found": "No friends found", + "no_groups_found": "No groups found", + "no_friends_or_groups_found": "No friends or groups found", + "relationship": "Relationship: ", + "unknown_group": "Unknown Group", + "type_group_chat": "Type: Group Chat", + "clean_conversations": "Clean {count} conversations", + "remove_friends": "Remove {count} friends", + "clean_conversations_and_remove_friends": "Clean {count} conversations and remove {count} friends", + "clean_group_conversations": "Clean {count} group conversations", + "clean_all_conversations": "Clean {count} conversations", + "failed_to_fetch_conversations": "Failed to fetch conversations: {error}", + "failed_to_fetch_friend_conversations": "Failed to fetch friend conversations: {error}", + "failed_to_process": "Failed to process {id}", + "deleted_messages": "{count} deleted messages", + "filters": { + "all": "All", + "my_friends": "My Friends", + "blocked": "Blocked", + "removed_me": "Removed Me", + "suggested": "Suggested", + "deleted": "Deleted", + "business_accounts": "Business Accounts", + "streaks": "Streaks", + "non_streaks": "Non Streaks", + "followed": "Followed", + "following": "Following", + "location_on_map": "Location on Map" + }, + "sort_options": { + "none": "None", + "username": "Username", + "added_timestamp": "Added Timestamp", + "snap_score": "Snap Score", + "streak_length": "Streak Length", + "most_messages_sent": "Most Messages Sent", + "most_recent_message": "Most Recent Message", + "nearest_location": "Nearest Location" } }, "chat_export": { @@ -1858,8 +2537,8 @@ "text_field_selection_all": "All", "export_file_format_title": "Export File Format", "message_type_filter_title": "Filter Messages by Type", - "amount_of_messages_title": "Amount of Messages (leave it blank for all)", - "download_medias_title": "Download Medias" + "amount_of_messages_title": "Message Count (leave blank for all)", + "download_medias_title": "Download Media" }, "dialog_negative_button": "Cancel", "dialog_positive_button": "Export", @@ -1877,12 +2556,12 @@ "positive": "Yes", "negative": "No", "cancel": "Cancel", + "save": "Save", "open": "Open", "download": "Download", "send": "Send", "restore_original": "Restore Original", - "convert_external_media": "Convert External Media", - "save": "Save" + "convert_external_media": "Convert External Media" }, "tracker_events": { "conversation_enter": "Conversation Enter", @@ -1904,7 +2583,8 @@ "snap_replayed": "Snap Replayed", "snap_replayed_twice": "Snap Replayed Twice", "snap_screenshot": "Snap Screenshot", - "snap_screen_record": "Snap Screen Record" + "snap_screen_record": "Snap Screen Record", + "i_can_see_you": "I Can See You" }, "tracker_actions": { "log": "Log", @@ -2001,7 +2681,113 @@ }, "auto_open_snaps": { "title": "Auto Open Snaps", - "notification_content": "{count} Snaps opened" + "priority_title": "Auto Open Snaps (Priority)", + "error_title": "Auto Open Snaps (Errors)", + "channel_description": "Notifications for auto-opening snaps queue status", + "priority_channel_description": "High priority notifications for auto-opening snaps", + "error_channel_description": "Error notifications when auto-opening snaps fails", + "paused_status": "Auto Open Snaps paused", + "processing_status": "Processing snaps: {queued} in queue, {processed} processed", + "monitor_status": "Monitoring...", + "recent_snaps": "Recent Snaps", + "action_pause": "Pause", + "action_resume": "Resume", + "action_clear": "Clear Queue", + "action_reset": "Reset Count", + "error_content": "Failed to open snap from {sender}: {error}", + "resumed_feedback": "Auto Open Resumed", + "paused_feedback": "Auto Open Paused", + "resumed_message": "Processing will continue automatically for queued snaps", + "paused_message": "Processing paused. Queue preserved ({count} snaps)", + "status_paused": "Paused", + "status_monitoring": "Monitoring", + "status_active": "Active", + "queue_cleared": "Queue cleared and statistics reset", + "queue_cleared_title": "Queue cleared", + "queue_cleared_reset": "Queue Cleared & Reset", + "queue_cleared_feedback": "Cleared {count} queued snaps \u2022 Reset {processed} processed count", + "queue_cleared_feedback_simple": "Reset {processed} processed count", + "unknown_sender": "Unknown", + "unknown_user": "Unknown User", + "content_type_external_media": "External Media", + "content_type_snap": "Snap", + "conversation_type_friend_dm": "Friend DM", + "conversation_type_dm": "DM", + "conversation_type_group_chat": "Group Chat", + "conversation_type_chat": "Chat", + "notification_status": "Status", + "notification_statistics": "STATISTICS", + "notification_queue_size": "Queue Size", + "notification_total_opened": "Total Snaps Opened", + "notification_queue_preview": "QUEUE PREVIEW", + "notification_processing_continue": "Processing will continue automatically...", + "notification_no_snaps_queue": "No snaps in queue.", + "notification_queue_cleared_opened": "Queue cleared ({opened} opened)", + "content_type_photo_video_snap": "Photo/Video Snap", + "conversation_type_group_with_name": "Group: {name}", + "delete_logs_title": "Delete logs?", + "delete_logs_progress": "Deleting {count} logs...", + "delete_logs_description": "This will delete logs based on the current filter and the search query. This action cannot be undone.", + "export_logs_title": "Export logs?", + "export_logs_progress": "Exporting logs...", + "export_logs_description": "This will export logs based on the current filter and the search query.", + "export_logs_as": "Export as {type}", + "export_logs_success": "Exported logs!", + "export_logs_failure": "Failed to export logs. Check logcat for more details.", + "deleted_logs_count": "Deleted {count} logs" + }, + "script_imported": "Script {name} imported!", + "script_import_failed": "Failed to import script. {error}. Check logs for more details", + "script_updating": "Updating script {name}...", + "script_updated": "Updated {name} to version {version}", + "script_update_failed": "Failed to update module. Check logs for more details", + "script_edit_failed": "Failed to open module file. Check logs for more details", + "script_data_cleared": "Module data cleared!", + "script_data_clear_failed": "Failed to clear module data. Check logs for more details", + "script_deleted": "Deleted script {name}!", + "script_delete_failed": "Failed to delete module. Check logs for more details", + "script_actions": "Actions", + "script_no_description": "No description", + "script_update_available": "Update available: {version}", + "script_loaded": "Loaded script {name}", + "script_unloaded": "Unloaded script {name}", + "script_enable_disable_failed": "Failed to {action} script. Check logs for more details", + "script_no_settings": "This module does not have any settings", + "script_no_scripts_found": "No scripts found", + "script_ok_timeout": "OK {timeout}", + "scripting_tagline": "Manage scripts, imports, and folders", + "installed_scripts_tab": "Installed", + "catalog_tab": "Catalog", + "no_scripts_folder_selected_title": "Select your scripts folder to get started", + "select_folder_button": "Choose Folder", + "select_scripts_folder_toast": "Please select a scripts folder first", + "delete_rule_title": "Delete Rule", + "delete_rule_description": "Are you sure you want to delete this rule?", + "rule_name": "Rule Name", + "friend_tracker_notifications": { + "notification_channel_name": "Friend Tracker", + "notification_title": "Friend Activity", + "conversation_enter": "{friend} entered {conversation}", + "conversation_exit": "{friend} left {conversation}", + "started_typing": "{friend} started typing in {conversation}", + "stopped_typing": "{friend} stopped typing in {conversation}", + "started_speaking": "{friend} started speaking in {conversation}", + "stopped_speaking": "{friend} stopped speaking in {conversation}", + "started_peeking": "{friend} started peeking in {conversation}", + "stopped_peeking": "{friend} stopped peeking in {conversation}", + "message_read": "{friend} read a message in {conversation}", + "message_deleted": "{friend} deleted a message in {conversation}", + "message_saved": "{friend} saved a message in {conversation}", + "message_unsaved": "{friend} unsaved a message in {conversation}", + "message_edited": "{friend} edited a message in {conversation}", + "message_reaction_add": "{friend} added a reaction in {conversation}", + "message_reaction_remove": "{friend} removed a reaction in {conversation}", + "snap_opened": "{friend} opened a snap in {conversation}", + "snap_replayed": "{friend} replayed a snap in {conversation}", + "snap_replayed_twice": "{friend} replayed a snap twice in {conversation}", + "snap_screenshot": "{friend} took a screenshot in {conversation}", + "snap_screen_record": "{friend} screen recorded in {conversation}", + "i_can_see_you": "{friend} activity in {conversation}: {details}" }, "friend_mutation_observer": { "notification_channel_name": "Friend Mutation Observer", @@ -2030,10 +2816,355 @@ "date_range_input_invalid_range_input": "Invalid date range" }, "send_override_dialog": { - "title": "Send media as {type}", + "title": "Send media as", "duration": "Duration: {duration}", "saveable_snap_hint": "Make Snap saveable in the chat", - "unlimited_duration": "Unlimited" + "unlimited_duration": "Unlimited", + "schedule": "Schedule", + "select_time": "Select time", + "select": "Select" }, - "invalid_input_toast": "Invalid input! Make sure you entered a valid value." -} \ No newline at end of file + "auto_reply_messages": { + "dialog": { + "add_message": "Add Message", + "edit_message": "Edit Message", + "message_label": "Message", + "no_messages": "No messages yet. Add your first message!", + "message_placeholder": "Enter your auto-reply message..." + } + }, + "auto_delete_sent_messages": { + "countdown_toast": "Message will be deleted in {time}", + "delete_success_toast": "Message deleted successfully", + "delete_failed_toast": "Failed to delete message" + }, + "translation_position": { + "above": "Above", + "below": "Below", + "inline": "Inline" + }, + "language_codes": { + "en": "English", + "es": "Spanish", + "fr": "French", + "de": "German", + "it": "Italian", + "pt": "Portuguese", + "ru": "Russian", + "ja": "Japanese", + "ko": "Korean", + "zh": "Chinese", + "ar": "Arabic", + "hi": "Hindi", + "tr": "Turkish", + "nl": "Dutch", + "pl": "Polish", + "sv": "Swedish", + "da": "Danish", + "no": "Norwegian", + "fi": "Finnish", + "cs": "Czech", + "hu": "Hungarian", + "ro": "Romanian", + "bg": "Bulgarian", + "hr": "Croatian", + "sk": "Slovak", + "sl": "Slovenian", + "et": "Estonian", + "lv": "Latvian", + "lt": "Lithuanian", + "mt": "Maltese", + "ga": "Irish", + "cy": "Welsh" + }, + "tracker": { + "tabs": { + "logs": "Logs", + "rules": "Rules" + }, + "actions": { + "export": "Export", + "delete": "Delete", + "add_rule": "Add Rule", + "save_rule": "Save Rule" + }, + "messages": { + "no_logs_found": "No logs found", + "no_rules_found": "No rules found", + "no_events": "No events" + }, + "search": { + "placeholder": "Search" + }, + "filters": { + "newest_first": "Newest first", + "pick_a_date": "Pick a date", + "title": "Filters", + "search_by": "Search by", + "since": "Since", + "until": "Until", + "types": { + "username": "Username", + "conversation": "Conversation", + "event": "Event" + }, + "event_types": { + "conversation_enter": "Entered conversation", + "conversation_exit": "Left conversation", + "started_typing": "Started typing", + "stopped_typing": "Stopped typing", + "started_speaking": "Started speaking", + "stopped_speaking": "Stopped speaking", + "started_peeking": "Started peeking", + "stopped_peeking": "Stopped peeking", + "message_read": "Read message", + "message_deleted": "Deleted message", + "message_saved": "Saved message", + "message_unsaved": "Unsaved message", + "message_edited": "Edited message", + "message_reaction_add": "Added reaction", + "message_reaction_remove": "Removed reaction", + "snap_opened": "Opened snap", + "snap_replayed": "Replayed snap", + "snap_replayed_twice": "Replayed snap twice", + "snap_screenshot": "Took screenshot", + "snap_screen_record": "Screen recorded" + } + }, + "logs": { + "export_dialog": { + "title": "Export Logs", + "description": "Export your friend tracker logs to a file", + "progress": "Exporting logs...", + "export_as": "Export as {type}", + "format_json": "JSON", + "format_csv": "CSV" + }, + "delete_dialog": { + "title": "Delete Logs", + "message": "Are you sure you want to delete all logs? This action cannot be undone.", + "confirm": "Delete All", + "cancel": "Cancel", + "progress": "Deleting {count} logs..." + }, + "log_entry": { + "in_conversation": "in {conversation}", + "unknown_user": "Unknown", + "unknown_conversation": "DMs", + "i_can_see_you_entered": "Entered", + "i_can_see_you_left": "Left", + "i_can_see_you_duration": "Duration", + "i_can_see_you_not_available": "N/A", + "i_can_see_you_unit_hour": "h", + "i_can_see_you_unit_minute": "m", + "i_can_see_you_unit_second": "s", + "event_text": "{friend} {event} in {conversation}", + "events": { + "conversation_enter": "entered", + "conversation_exit": "left", + "started_typing": "started typing", + "stopped_typing": "stopped typing", + "started_speaking": "started speaking", + "stopped_speaking": "stopped speaking", + "started_peeking": "started peeking", + "stopped_peeking": "stopped peeking", + "message_read": "read a message", + "message_deleted": "deleted a message", + "message_saved": "saved a message", + "message_unsaved": "unsaved a message", + "message_edited": "edited a message", + "message_reaction_add": "added a reaction", + "message_reaction_remove": "removed a reaction", + "snap_opened": "opened a snap", + "snap_replayed": "replayed a snap", + "snap_replayed_twice": "replayed a snap twice", + "snap_screenshot": "took a screenshot", + "snap_screen_record": "screen recorded", + "i_can_see_you": "was active" + } + } + }, + "edit_rule": { + "custom_rule": "Custom Rule", + "scope": "Scope", + "events": "Events", + "add_event": "Add Event", + "type": "Type", + "triggers": "Triggers", + "conditions": "Conditions", + "only_inside_conversation": "Only when I'm inside conversation", + "only_outside_conversation": "Only when I'm outside conversation", + "only_when_app_active": "Only when Snapchat is active", + "only_when_app_inactive": "Only when Snapchat is inactive", + "no_notification_when_app_active": "No notification when Snapchat is active", + "scope_options": { + "all_friends_groups": "All Friends/Groups", + "no_one_except": "No one except", + "everyone_except": "Everyone except" + } + } + }, + "debug": { + "title": "Debug", + "clear": "Clear", + "files": { + "config_json": "Configuration File", + "mappings_json": "Mappings File", + "message_logger_db": "Message Logger Database", + "pinned_best_friend_txt": "Pinned Best Friend File", + "native_sig_cache_txt": "Native Signature Cache File" + }, + "settings": { + "test_mode": "Test Mode (FOR DEBUGGING ONLY)", + "disable_feature_loading": "Disable Feature Loading", + "disable_auto_mapper": "Disable Auto Mapper", + "disable_bypass_status_indicator": "Disable Bypass Status Indicator" + } + }, + "ui_settings_title": "UI Settings", + "haptic_feedback_label": "Haptic Feedback", + "updates_title": "Updates", + "auto_update_check": "Auto Update Check", + "update_check_frequency_daily": "Daily", + "update_check_frequency_weekly": "Weekly", + "update_check_frequency_monthly": "Monthly", + "friend_notes_title": "Friend Notes", + "friend_notes_description": "Manage and backup your friend notes", + "app_theme_title": "App Theme", + "theme_mode_system": "System", + "theme_mode_light": "Light", + "theme_mode_dark": "Dark", + "test_mode_label": "Enable PurrAura", + "disable_feature_loading_label": "Disable Feature Loading", + "disable_auto_mapper_label": "Disable Auto Mapper", + "disable_bypass_indicator_label": "Disable Bypass Indicator", + "friend_list": { + "manage_title": "Manage Friend List", + "export_description": "Export friends allows you to save a list of your friends' IDs in a text file. Importing from a file will display the friends in a list where you can add them.", + "export_friends": "Export friends", + "import_from_file": "Import from file", + "add": "Add" + }, + "memories": { + "export_title": "Export memories", + "total_memories": "Total memories: {count}", + "date_range": "Date Range", + "select": "Select", + "sort_by_folder": "Sort by folder", + "include_my_eyes_only": "Include My Eyes Only", + "cancel": "Cancel", + "export": "Export", + "quit": "Quit", + "done": "Done", + "ok": "OK", + "exporting_memories": "Exporting memories... ({failed} failed)" + }, + "scripting_ui": { + "no_scripts_folder_selected": "No scripts folder selected", + "select_folder": "Select folder", + "import_from_url": "Import from URL", + "open_scripts_folder": "Open Scripts Folder", + "import_script_from_url": "Import Script from URL", + "warning_imported_scripts": "Warning: Imported scripts can be harmful to your device. Only import scripts from trusted sources.", + "enter_url_here": "Enter URL here:", + "import": "Import", + "cancel": "Cancel", + "documentation": "Documentation" + }, + "common": { + "cancel": "Cancel", + "add": "Add", + "ok": "OK", + "quit": "Quit", + "done": "Done", + "back": "Back", + "unknown": "Unknown", + "added": "Added", + "no_friends_found": "No friends found", + "exporting_memories": "Exporting memories... ({failed} failed)" + }, + "clear_friend_feed": "Clear Friend Feed", + "schedule_scheduled_for": "Scheduled for {time}", + "schedule_sent_to": "Sent to {recipient}", + "by_author": "by {author}", + "version": "Version {version}", + "delete_button": "Delete", + "logger_history": { + "download_started": "Download started!", + "downloaded_to": "Downloaded to {path}", + "failed_to_download": "Failed to download {message}", + "select_conversation": "Select a conversation", + "select_conversation_placeholder": "Select a conversation", + "edited_at": "edited at {date}", + "download_attachment_failed_toast": "Failed to download attachment", + "message_parse_failed": "Message parse failed", + "empty_message": "Empty message", + "no_more_messages": "No more messages", + "reverse_order_checkbox": "Reverse order", + "view_logger_history_button": "View Logger History", + "posted_at": "Posted at {date}", + "created_at": "Created at {date}", + "failed_to_open_file": "Failed to open file. Check logs for more info", + "failed_to_get_file": "Failed to get file", + "download_button": "Download", + "chat_attachment": "Attachment {index}", + "log_header_format": "{username} ? {type} ? {date}", + "edited_at_text": "Edited to \"{message}\" at {date}", + "list_group_format": "Group {name}", + "list_friend_format": "Friend {name}", + "download_started_toast": "Download started", + "download_success_toast": "Downloaded to {path}", + "download_failed_toast": "Download failed: {message}", + "close_button_description": "Close search", + "search_button_description": "Search messages" + }, + "debug_dialogs": { + "info": "Info", + "refs": "Refs", + "arroyo": "Arroyo", + "message": "Message", + "media_references": "Media References", + "arroyo_proto": "Arroyo proto", + "message_proto": "Message proto" + }, + "error_messages": { + "failed_to_fetch_message": "Failed to fetch message: {error}", + "failed_to_edit_message": "Failed to edit message: {error}" + }, + "ai_response_style": { + "casual": "Casual", + "formal": "Formal", + "friendly": "Friendly", + "humorous": "Humorous", + "empathetic": "Empathetic", + "busy": "Busy", + "toxic": "Toxic" + }, + "ai_response_language": { + "auto": "Auto (Same as received)", + "en": "English", + "es": "Spanish", + "fr": "French", + "de": "German", + "it": "Italian", + "pt": "Portuguese", + "ru": "Russian", + "ja": "Japanese", + "ko": "Korean", + "zh": "Chinese", + "ar": "Arabic (UAE) and (KSA)", + "hi": "Hindi", + "tr": "Turkish", + "pl": "Polish", + "nl": "Dutch", + "sv": "Swedish", + "da": "Danish", + "no": "Norwegian", + "fi": "Finnish" + }, + "ai_provider": { + "gemini": "Gemini", + "deepseek": "DeepSeek", + "openai": "OpenAI" + } +} diff --git a/common/src/main/assets/lang/es_ES.json b/common/src/main/assets/lang/es_ES.json new file mode 100644 index 00000000..913fe86c --- /dev/null +++ b/common/src/main/assets/lang/es_ES.json @@ -0,0 +1,1656 @@ +{ + "setup": { + "mappings": { + "dialog": "Generando mapeos, esto puede tardar un rato ...", + "generate_failure_no_snapchat": "SnapEnhance no pudo detectar Snapchat, por favor intenta reinstalar Snapchat.", + "generate_failure": "Ocurrió un error al intentar generar mapeos, por favor intenta de nuevo." + }, + "dialogs": { + "select_save_folder_button": "Elige la carpeta", + "select_language": "Elige un idioma", + "save_folder": "Snapenhance necesita permisos de almacenamiento para descargar y guardar medios desde Snapchat.\nPor favor elige la ubicación dónde se deben descargar los medios." + }, + "permissions": { + "dialog": "Para continuar hay que cumplir los siguientes requisitos:", + "request_button": "Solicitar", + "notification_access": "Acceso a notificaciones", + "battery_optimization": "Optimización de la Batería", + "display_over_other_apps": "Mostrar sobre otras aplicaciones" + } + }, + "manager": { + "routes": { + "social": "Social", + "manage_scope": "Gestionar el alcance", + "messaging_preview": "Vista previa", + "scripts": "Secuencias", + "logger_history": "Historial del registro", + "logged_stories": "Historias registradas", + "tasks": "Tareas", + "features": "Características", + "home": "Página principal", + "home_logs": "Registros", + "home_settings": "Ajustes", + "friend_tracker": "Rastreador de amigos", + "edit_rule": "Editar regla", + "file_imports": "Importación de archivos", + "better_location": "Mejor ubicación", + "theming": "Temática", + "edit_theme": "Editar tema", + "manage_repos": "Administrar repositorios", + "manage_rule_feature": "Gestionar las reglas" + }, + "sections": { + "home": { + "update_title": "Actualización de SnapEnhance", + "update_content": "¡Versión {version} está disponible!", + "update_button": "Descargar", + "debug_build_summary_date": "Fecha de desarrollo: {date} (hace{days} día(s))", + "quick_actions_title": "Acciones rápidas", + "version_title": "v{versionName} · por eternal", + "debug_build_summary_title": "Estás ejecutando una versión de depuración de SnapEnhance", + "debug_build_summary_content": "Versión {versionName} ({versionCode})" + }, + "home_logs": { + "no_logs_hint": "Registros no disponibles", + "clear_logs_button": "Borrar Registros", + "export_logs_button": "Exportar Registros", + "saving_logs_toast": "Guardando los registros, esto puede tardar un rato…", + "saved_logs_success_toast": "Registros guardados con éxito", + "saved_logs_failure_toast": "Error al guardar los registros" + }, + "home_settings": { + "actions_title": "Acciones", + "message_logger_title": "Registrador de mensajes", + "debug_title": "Depurar", + "success_toast": "¡Hecho!", + "message_logger_summary": "{messageCount} mensajes\n{storyCount} historias", + "export_button": "Exportar", + "clear_button": "Borrar", + "view_logger_history_button": "Ver historial del registrador" + }, + "tasks": { + "remove_selected_tasks_title": "¿Estás segura/o que quieres borrar las tareas seleccionadas?", + "remove_all_tasks_title": "¿Estás segura/o que quieres borrar todas las tareas?", + "delete_files_option": "También borrar archivos", + "remove_selected_tasks_confirm": "¿Borrar {count} tareas?", + "remove_all_tasks_confirm": "¿Borrar todas las tareas?", + "merge_files_toast": "Incorporando {count} archivos", + "no_tasks": "Sin tareas", + "failed_to_open_file": "Error al abrir el archivo" + }, + "features": { + "disabled": "Desactivado", + "export_option": "Exportar", + "import_option": "Importar", + "reset_option": "Restablecer", + "config_export_success_toast": "Configuración exportada con éxito", + "config_import_success_toast": "Configuración importada con éxito", + "config_import_failure_toast": "Error al importar la configuración {error}", + "saved_config_snackbar": "Configuración guardada", + "config_export_failure_toast": "No se pudo exportar la configuración {error}" + }, + "social": { + "friends_tab": "Amigxs", + "empty_hint": "(Vacío)", + "streaks_expiration_short": "{hours}h", + "groups_tab": "Grupos" + }, + "manage_scope": { + "rules_title": "Normas", + "participants_text": "{count} participantes", + "not_found": "No encontrado", + "streaks_length_text": "Longitud: {length}", + "streaks_expiration_text": "Caduca en {eta}", + "streaks_expiration_text_expired": "Caducado", + "reminder_button": "Establecer recordatorio", + "logged_stories_button": "Mostrar historias en el registro", + "delete_scope_confirm_dialog_title": "¿Segura/o de que quieres borrar un {scope}?", + "e2ee_title": "Cifrado de extremo a extremo", + "streaks_title": "Rachas" + }, + "logged_stories": { + "story_failed_to_load": "Error al cargar", + "no_stories": "Ningunas historias encontradas", + "save_from_cache_button": "Guardar desde el cache" + }, + "messaging_preview": { + "bridge_connection_failed": "No se pudo conectar al puente. Asegúrate de que Snapchat se esté ejecutando en segundo plano", + "bridge_init_failed": "No se pudo inicializar el puente de mensajería. Asegúrate de que Snapchat se esté ejecutando en segundo plano", + "message_fetch_failed": "Error al recuperar mensajes", + "no_message_hint": "Sin mensaje", + "save_selection_option": "Guardar selección", + "save_all_option": "Guardar Todo", + "delete_selection_option": "Borrar selección", + "delete_all_option": "Borrar todo", + "unsave_selection_option": "No guardar seleccion", + "unsave_all_option": "No guardar nada", + "mark_selection_as_seen_option": "Marca el Snap seleccionado como visto", + "mark_all_as_seen_option": "Marcar todos los Snaps como vistos" + }, + "logger_history": { + "list_friend_format": "Amigx {name}", + "no_more_messages": "Sin más mensajes", + "reverse_order_checkbox": "Orden al revés", + "chat_attachment": "Atajo {index}", + "empty_message": "Mensaje vacío", + "unknown_sender": "Remitente desconocido", + "download_attachment_failed_toast": "Error al descargar atajo", + "list_group_format": "Grupo {name}", + "message_parse_failed": "Error al analizar mensaje" + }, + "file_imports": { + "file_import_failed": "No se pudo importar el archivo: {error}", + "file_delete_failed": "No se pudo eliminar el archivo", + "import_file_button": "Importar archivo", + "file_not_found": "Archivo no encontrado", + "file_imported": "Archivo importado exitosamente", + "no_files_hint": "Aquí puedes importar los archivos para usarlos en Snapchat. Presiona el botón a continuación para importar un archivo." + }, + "better_location": { + "save_dialog_button": "Guardar", + "saved_name_dialog_hint": "Nombre guardado", + "no_friends_found": "No se encontraron amigos", + "saved_coordinates_title": "Coordenadas guardadas", + "delete_dialog_title": "Eliminar coordenadas guardadas", + "search_bar": "Buscar", + "spoofed_coordinates_title": "Lat {latitude}, Lng {longitude}", + "save_coordinates_dialog_title": "Guardar coordenadas", + "choose_location_button": "Elegir la ubicación", + "spoof_location_toggle": "Ubicación falsa", + "no_saved_coordinates_hint": "No hay coordenadas guardadas", + "delete_dialog_message": "¿Está seguro de que desea eliminar esta coordenada guardada?", + "no_friends_map": "No hay amigos en el mapa", + "teleport_to_friend_button": "Teletransportar a un amigo", + "teleport_to_friend_title": "Teletransportar a un amigo", + "latitude_dialog_hint": "Latitud", + "longitude_dialog_hint": "Longitud", + "suspend_location_updates": "Suspender las actualizaciones de ubicación" + }, + "theming": { + "no_themes_hint": "No se encontraron temas" + }, + "manage_rule_feature": { + "whitelist_state_button": "Seleccionar amig@s/grupos permitidos", + "blacklist_state_option": "Todo el mundo excepto ...", + "blacklist_state_subtext": "Todos excepto {count} amig@s/grupos se verán afectados por esta regla", + "blacklist_state_button": "Seleccionar amig@s/grupos excluidos", + "clear_list_button": "Borrar la lista de amig@s/grupos", + "disable_state_option": "Desactivado", + "disable_state_subtext": "Ningun@s amig@s/grupos se verán afectados", + "dialog_clear_confirmation_text": "¿Seguro que quieres borrar la lista?", + "whitelist_state_option": "Nadie excepto...", + "whitelist_state_subtext": "Solo {count} amig@s/grupos se verán afectados por esta regla" + } + }, + "dialogs": { + "add_friend": { + "title": "Añadir amigx o grupo", + "search_hint": "Buscar", + "fetch_error": "Error al cargar datos", + "category_groups": "Grupos", + "category_friends": "Amigxs" + }, + "scripting_warning": { + "title": "Aviso", + "content": "SnapEnhance incluye una herramienta de escribir comandos, que permite la ejecución de código definido por el usuario. Exige precaución extrema y asegúrese de sólo instalar módulos de fuentes conocidos y confiables. Módulos no verificados o autorizados pueden arriesgar la seguridad de tu sistema." + }, + "reset_config": { + "content": "¿Segura/o que quieres restablecer la configuración?", + "success_toast": "Configuración restablecida con éxito", + "title": "Restablecer configuración" + }, + "messaging_action": { + "select_all_button": "Seleccionar todo", + "title": "Elige el tipo de contenido para procesarlo" + }, + "file_imports": { + "no_files_settings_hint": "No se encontraron archivos. Asegúrate de haber importado los archivos requeridos en la sección Importaciones de archivos", + "settings_select_file_hint": "Selecciona un archivo importado" + }, + "export_config": { + "title": "¿Exportar datos confidenciales?", + "content": "¿Quieres exportar la configuración con tus datos privados? (Como coordenadas de la ubicación, etc.)" + } + } + }, + "rules": { + "toasts": { + "enabled": "{ruleName} activado", + "disabled": "{ruleName} desactivado" + }, + "modes": { + "blacklist": "Modo de lista negra", + "whitelist": "Modo de lista blanca" + }, + "properties": { + "auto_download": { + "name": "Descargar automáticamente", + "options": { + "blacklist": "Excluir de descargas automáticas", + "whitelist": "Descargar automáticamente" + }, + "description": "Descargar Snaps automáticamente mientras los ves" + }, + "stealth": { + "name": "Modo sigilo", + "description": "Impide que nadie sepa que hayas abierto sus Snaps/Chats y conversaciones", + "options": { + "blacklist": "Excluir de modo sigilo", + "whitelist": "Modo sigilo" + } + }, + "auto_save": { + "name": "Guardar automáticamente", + "description": "Guarda mensajes de chat mientras verlos", + "options": { + "blacklist": "Excluir de guardar automáticamente", + "whitelist": "Guardar automáticamente" + } + }, + "unsaveable_messages": { + "name": "Mensajes que no se puede guardar", + "options": { + "blacklist": "Excluir de mensajes que no se puede guardar", + "whitelist": "Mensajes que no se puede guardar" + }, + "description": "Impide poder guardar mensajes en el chat por otras personas" + }, + "auto_open_snaps": { + "name": "Automáticamente abrir los Snaps", + "description": "Automáticamente abre los Snaps al recibirlos", + "options": { + "blacklist": "Excluir de abrir Snaps automáticamente", + "whitelist": "Abrir Snaps automáticamente" + } + }, + "hide_friend_feed": { + "name": "Ocultar de la lista de amigxs" + }, + "e2e_encryption": { + "name": "Usa cifración de extremo a extremo" + }, + "pin_conversation": { + "name": "Fijar conversación" + } + } + }, + "actions": { + "clean_snapchat_cache": { + "description": "Borra cache de Snapchat", + "name": "Borrar cache de Snapchat" + }, + "change_language": { + "name": "Cambiar idioma", + "description": "Cambiar el idioma de SnapEnhance" + }, + "manage_friend_list": { + "name": "Administrar lista de amigxs", + "description": "Importar/exportar tu lista de amigxs al crear un respaldo" + }, + "export_chat_messages": { + "name": "Exportar mensajes de chat", + "description": "Exporta mensajes a un archivo de tipo JSON/HTML/TXT" + }, + "export_memories": { + "name": "Exportar memorias", + "description": "Exporta memorias a un archivo ZIP" + }, + "bulk_messaging_action": { + "name": "acción de mensajería a granel", + "description": "realiza operaciones como borrar amigxs o eliminar conversaciones en masa" + }, + "regen_mappings": { + "name": "regenerar mapeos", + "description": "regenerar mapeos a mano" + }, + "file_imports": { + "description": "Importar archivos para usar en Snapchat", + "name": "Importación de archivos" + }, + "friend_tracker": { + "name": "Rastreador de amigos", + "description": "Sigue a tus amigos en Snapchat" + }, + "logger_history": { + "description": "Ver el historial de mensajes guardados", + "name": "Historial del registro" + }, + "theming": { + "description": "Personaliza la apariencia de Snapchat", + "name": "Temática" + }, + "security_features": { + "name": "Características de seguridad", + "description": "Cambiar las preferencias de las funciones de seguridad" + } + }, + "scopes": { + "friend": "Amigx", + "group": "Grupo" + }, + "features": { + "properties": { + "user_interface": { + "properties": { + "bootstrap_override": { + "properties": { + "app_appearance": { + "name": "Apariencia de la aplicación", + "description": "Establece una apariencia persistente de la aplicación" + }, + "home_tab": { + "name": "Pestaña de inicio", + "description": "Anula la pestaña en la que se abre la app al abrir Snapchat" + } + }, + "name": "Anular Bootstrap", + "description": "Anula los ajustes de bootstrap de la interfaz de usuario" + }, + "enable_app_appearance": { + "name": "Habilitar ajustes de apariencia de la app", + "description": "Habilita los ajustes de apariencia de la app escondidos\nPuede que no sea necesario en nuevas versiones de Snapchat" + }, + "friend_feed_message_preview": { + "name": "Vista previa de mensajes en la lista de amigxs", + "description": "Muestra una vista previa de los últimos mensajes en la lista de amigxs", + "properties": { + "amount": { + "name": "Cantidad", + "description": "La cantidad de mensajes para hacer una vista previa" + } + } + }, + "snap_preview": { + "name": "Vista previa de Snap", + "description": "Muestra una pequeña vista previa al lado de Snaps no vistos en el chat" + }, + "hide_friend_feed_entry": { + "description": "Oculta un amigx específico de la lista de amigxs\nUsa la pestaña social para administrar esta característica", + "name": "Ocultar entrada de lista de amigxs" + }, + "hide_streak_restore": { + "description": "Oculta el botón de restablecer en la lista de amigxs", + "name": "Ocultar restablecer Snapracha" + }, + "opera_media_quick_info": { + "name": "Multimedias de Opera información rápida", + "description": "Muestra información útil sobre multimedias como la fecha de creación en el menú contextual de Opera Viewer" + }, + "enable_friend_feed_menu_bar": { + "name": "Barra de menú en la lista de amigxs", + "description": "Habilita la nueva barra de menú en la lista de amigxs" + }, + "stealth_mode_indicator": { + "name": "Indicador de modo sigilo", + "description": "Añade un 👻 emoji al lado de una conversación en modo sigilo" + }, + "map_friend_nametags": { + "name": "Etiquetas de nombre mejoradas en el mapa de amigxs", + "description": "Mejora las etiquetas de nombre de amigxs en el mapa de Snaps" + }, + "prevent_message_list_auto_scroll": { + "name": "Prevenir que la lista de mensajes se desplaza automáticamente", + "description": "Previene que la lista de mensajes se desplaza hasta el fondo al enviar/recibir un mensaje" + }, + "streak_expiration_info": { + "name": "Mostrar información de caducidad de la racha", + "description": "Muestra un temporizador de caducidad al lado del contador de racha" + }, + "hide_story_suggestions": { + "name": "Ocultar sugerencias de historias", + "description": "Elimina las sugerencias de la página de historias" + }, + "hide_ui_components": { + "name": "Ocultar componentes de la interfaz de usuario", + "description": "Elige que componentes de interfaz de usuario ocultar" + }, + "old_bitmoji_selfie": { + "name": "Retrato de Bitmoji viejo", + "description": "Trae de vuelta los retratos de Bitmoji de versiónes más antiguos de Snapchat" + }, + "disable_spotlight": { + "name": "Deshabilitar Spotlight", + "description": "Deshabilita la página de Spotlight" + }, + "friend_feed_menu_buttons": { + "name": "Botones de menú de la lista de amigxs", + "description": "Elige que botones mostrar en el menú de la lista de amigxs" + }, + "vertical_story_viewer": { + "name": "Ver las historias de forma vertical", + "description": "Permite ver todas las historias de forma vertical" + }, + "message_indicators": { + "name": "Indicadores de mensajes", + "description": "Añade iconos indicadores específicos a los mensajes\nTen en cuenta: Puede que los indicadores no sean 100% precisos" + }, + "edit_text_override": { + "name": "Editar anulación de texto", + "description": "Anula el comportamiento de entradas de texto" + }, + "auto_close_friend_feed_menu": { + "name": "Menú de feed de amigos cercanos automáticos", + "description": "Cierra automáticamente el menú de Feed de amigos después de presionar un botón de configuración" + }, + "custom_theme": { + "name": "Tema personalizado", + "description": "Personalizar los colores de Snapchat\nNota: si eliges un tema oscuro (como Amoled), es posible que tengas que activar el modo oscuro en los ajustes de Snapchat para obtener mejores resultados" + } + }, + "name": "Interfaz de usuario", + "description": "Cambia la apariencia y sensación Snapchat" + }, + "downloader": { + "properties": { + "force_voice_note_format": { + "description": "Obliga guardar las notas de voz en un formato específico", + "name": "Obligar formato de notas de voz" + }, + "download_profile_pictures": { + "name": "Descargar fotos de perfil", + "description": "Te permite guardar las fotos de perfil desde la página del perfil" + }, + "opera_download_button": { + "name": "Botón de descarga Opera", + "description": "Añade un botón de descarga en la esquina derecha superior al ver un Snap.\nUn pulso largo forzará la descarga" + }, + "ffmpeg_options": { + "name": "Opciones de FFmpeg", + "properties": { + "threads": { + "name": "Hilos", + "description": "La cantidad de hilos a utilizar" + }, + "preset": { + "name": "preestablecido", + "description": "Establecer la velocidad de la conversación" + }, + "constant_rate_factor": { + "name": "Factor de tasa constante", + "description": "Establecer el factor de tasa constante para el codificador de vídeo\nDesde 0 hasta 51 para libx264" + }, + "video_bitrate": { + "description": "Establecer el bitrate de vídeo (kbps)", + "name": "Bitrate de vídeo" + }, + "audio_bitrate": { + "name": "Bitrate de audio", + "description": "Establecer el bitrate de audio (kbps)" + }, + "custom_video_codec": { + "name": "Códec de vídeo personalizado", + "description": "Establecer un códec de vídeo personalizado (por ejemplo, libx264)" + }, + "custom_audio_codec": { + "name": "Códec de audio personalizado", + "description": "Establecer un códec de audio personalizado (por ejemplo, AAC)" + } + }, + "description": "especificar opciones de FFmpeg adicionales" + }, + "download_context_menu": { + "name": "Descargar menú contextual", + "description": "Te permite descargar/hacer una vista previa desde una conversación o historia usando el menú contextual.\nUn pulso largo en los botones forzará la descarga" + }, + "logging": { + "name": "Registrando", + "description": "muestra toasts mientras multimedia se está descargando" + }, + "custom_path_format": { + "name": "Ruta de archivo personalizada", + "description": "Especificar una ruta de archivo personalizada para multimedia descargada\n\nVariables disponibles:\n - %username%\n - %source%\n - %hash%\n - %date_time%" + }, + "merge_overlays": { + "description": "Une el texto y la multimedio de un Snap en un solo archivo", + "name": "Fusionar superposiciones" + }, + "save_folder": { + "name": "Guardar carpeta", + "description": "Seleccione el directorio al que se deben descargar todos los multimedios" + }, + "auto_download_sources": { + "name": "Descargar fuentes automáticamente", + "description": "Seleccione desde que fuentes descargar automáticamente" + }, + "prevent_self_auto_download": { + "name": "Evitar autodescarga automática", + "description": "Evita que tus propios Snaps se descarguen automáticamente" + }, + "path_format": { + "name": "Formato de ruta", + "description": "Especificar el formato de la ruta de archivos" + }, + "allow_duplicate": { + "name": "Permitir duplicado", + "description": "Permite que la misma multimedia se descarga múltiples veces" + }, + "force_image_format": { + "name": "Forzar formato de imagen", + "description": "Obliga que los imágenes se guardan en un formato especificado" + }, + "auto_download_voice_notes": { + "description": "Descarga automáticamente las notas de voz al reproducirlas", + "name": "Descarga automática de notas de voz" + } + }, + "description": "Descargar multimedios de Snapchat", + "name": "Descargador" + }, + "messaging": { + "properties": { + "prevent_story_rewatch_indicator": { + "name": "Deshabilitar el indicador de ver la historia de nuevo", + "description": "Evita que nadie sepa que has visto su historia de nuevo" + }, + "bypass_screenshot_detection": { + "name": "Anular detección de capturas de pantalla", + "description": "Evita que Snapchat pueda detectar cuando hagas una captura de pantalla" + }, + "anonymous_story_viewing": { + "name": "Viendo historias anónimamente", + "description": "Evita que nadie sepa que has visto su historia" + }, + "hide_peek_a_peek": { + "name": "Ocultar Peek-a-Peek", + "description": "Evita que se envía una notificación si no acabas de deslizar por completo en un chat" + }, + "hide_bitmoji_presence": { + "name": "Ocultar presencia de Bitmoji", + "description": "Evita que se muestra tu Bitmoji mientras estás en el chat" + }, + "hide_typing_notifications": { + "name": "Ocultar notificaciones de escribiendo", + "description": "Evita que nadie sepa que estás escribiendo un mensaje" + }, + "unlimited_snap_view_time": { + "name": "Ver Snaps sin límite de tiempo", + "description": "Quita el límite de tiempo para ver Snaps" + }, + "auto_mark_as_read": { + "name": "Marcar como leído automáticamente", + "description": "Automáticamente marca los mensajes/Snaps como leído incluso cuando el modo sigilo esté habilitado" + }, + "loop_media_playback": { + "name": "Reproducción de Multimedia en bucle", + "description": "Reproduce Multimedias en bucle al ver Snaps/Historias" + }, + "disable_replay_in_ff": { + "name": "Deshabilitar repetir en la lista de amigxs", + "description": "Deshabilita la posibilidad de repetir al mantener pulsado desde la lista de amigxs" + }, + "half_swipe_notifier": { + "name": "Notificación de no acabar de deslizar por completo en un chat", + "properties": { + "min_duration": { + "name": "Duración mínima", + "description": "La duración mínima de no acabar de deslizar por completo (en segundos)" + }, + "max_duration": { + "name": "duración máxima", + "description": "La duración máxima de no acabar de deslizar por completo (en segundos)" + } + }, + "description": "Te notifica cuando alguien no acaba de deslizar por completo a una conversación" + }, + "call_start_confirmation": { + "name": "Confirmación de empezar llamada", + "description": "Muestra un diálogo de confirmación al empezar una llamada" + }, + "notification_blacklist": { + "description": "Elige las notificaciones que deben ser bloqueadas", + "name": "Lista negra de notificaciones" + }, + "message_logger": { + "description": "Evita que se pueda borrar un mensaje", + "name": "Registro de mensajes", + "properties": { + "keep_my_own_messages": { + "name": "Guardar mis mensajes", + "description": "Evita que se pueda borrar tus mensajes" + }, + "auto_purge": { + "name": "purga automática", + "description": "Automáticamente borra los mensajes en el cache que son más antiguos que la duración del tiempo especificado" + }, + "message_filter": { + "name": "Filtro de mensajes", + "description": "Seleccione que mensajes deben ser registrados (vacío para todos los mensajes)" + } + } + }, + "auto_save_messages_in_conversations": { + "name": "Guardar mensajes automáticamente", + "description": "Automáticamente guarda cada mensaje en una conversación" + }, + "unlimited_conversation_pinning": { + "name": "Fijar conversaciones ilimitadas", + "description": "Te permite fijar una cantidad de conversaciones ilimitada localmente" + }, + "prevent_message_sending": { + "name": "Evitar el envío de mensajes", + "description": "Evita el envío de algunos tipos de mensajes" + }, + "friend_mutation_notifier": { + "name": "Notificación de mutación de amigx", + "description": "Te notifica si algo cambia en el perfil de un amigx" + }, + "better_notifications": { + "name": "Mejores notificaciones", + "description": "Agrega más información a notificaciones recibidas", + "properties": { + "chat_preview": { + "name": "Vista previa del chat", + "description": "Muestra una vista previa de los mensajes recibidos en la notificación" + }, + "media_preview": { + "name": "Vista previa del archivo multimedia", + "description": "Muestra una vista previa de los archivos multimedia seleccionados en la notificación" + }, + "media_caption": { + "name": "Título multimedia", + "description": "Muestra el título adjunto de los archivos multimedia en la notificación" + }, + "stacked_media_messages": { + "name": "Amontonar los mensajes multimedia", + "description": "Combina varios mensajes multimedia en una notificación de texto cuando no se pueden obtener una vista previa. Usar en combinación con la vista previa del chat" + }, + "download_button": { + "name": "Botón descargar", + "description": "Le permite descargar medios desde la notificación" + }, + "mark_as_read_button": { + "name": "Botón marcar como leído", + "description": "Te permite marcar un mensaje como leído desde la notificación" + }, + "group_notifications": { + "name": "Agrupar notificaciones", + "description": "Agrupa notificaciones en una sola notificación" + }, + "friend_add_source": { + "description": "Muestra la fuente de una solicitud de amistad en la notificación", + "name": "Fuente de solicitud de amistad" + }, + "reply_button": { + "name": "Botón responder", + "description": "Agrega un botón de responder a la notificación" + }, + "mark_as_read_and_save_in_chat": { + "name": "Marcar como leído y guardar en el chat", + "description": "Agrega un botón marcar como leído y guardar en el chat a la notificación" + }, + "smart_replies": { + "description": "Agregar respuestas sugeridas a las notificaciones (Android 10+). Usar en combinación con el botón Responder", + "name": "Respuestas inteligentes" + } + } + }, + "gallery_media_send_override": { + "name": "Anulación de envío de medios de la galería", + "description": "Falsifica el fuente de multimedia al enviar desde la galería" + }, + "strip_media_metadata": { + "name": "Borrar metadatos de medios", + "description": "Elimina los metadatos de la multimedia antes de enviar como un mensaje" + }, + "bypass_message_retention_policy": { + "name": "Pasar por alto la política de retención de mensajes", + "description": "Evita que se pueda borrar mensajes después de verlos" + }, + "bypass_message_action_restrictions": { + "name": "Pasar por alto restricciones de acciones de mensajería", + "description": "Te permite reaccionar a un Snap sin haberlo abierto o guardar un mensaje no guardable" + }, + "remove_groups_locked_status": { + "name": "Elimina el estatus de grupos bloqueados", + "description": "Te permite ver información del grupo después de ser expulsada/o" + }, + "mark_snap_as_seen_button": { + "description": "Agrega un botón para marcar un Snap como visto al visualizarlo.\nEsto funcionará incluso cuando el modo oculto esté habilitado", + "name": "Botón Marcar Snap como visto" + }, + "skip_when_marking_as_seen": { + "description": "Salta automáticamente al siguiente Snap al marcar un Snap como visto.\nUsar en combinación con el botón Marcar como visto", + "name": "Saltar al marcar como visto" + } + }, + "name": "mensajería", + "description": "Cambiar como interactúas con amigxs" + }, + "global": { + "properties": { + "disable_confirmation_dialogs": { + "name": "Deshabilita diálogos de confirmación", + "description": "Automáticamente verifica acciones seleccionadas" + }, + "disable_story_sections": { + "name": "Deshabilitar secciones de historias", + "description": "Descarta secciones de la página de historias\nPuede que se necesita recargar para funcionar correctamente" + }, + "block_ads": { + "name": "bloquear anuncios", + "description": "Evita que se muestran anuncios" + }, + "better_location": { + "properties": { + "walk_radius": { + "name": "Radio de caminata", + "description": "Andar dentro de este radio (en pies) al azar" + }, + "spoof_location": { + "name": "Falsificar ubicación", + "description": "Falsifica tu ubicación a una predeterminada" + }, + "coordinates": { + "name": "Coordenadas", + "description": "Establece las coordenadas de la ubicación falsificada" + }, + "always_update_location": { + "name": "Siempre actualizar ubicación", + "description": "Forzar a Snapchat a actualizar la ubicación incluso cuando no se ha recibido ninguna información del GPS" + }, + "suspend_location_updates": { + "name": "Suspender actualizaciones de la ubicación", + "description": "Evita que se actualice tu ubicación" + }, + "spoof_battery_level": { + "name": "Falsificar nivel de carga", + "description": "Falsifica nivel de carga de tu dispositivo en el mapa\nEl valor tiene que ser entre 0 y 100" + }, + "spoof_headphones": { + "name": "Falsificar auriculares", + "description": "Falsifica el estado de escuchar a música en el mapa" + }, + "show_battery_level": { + "name": "Mostrar nivel de bateria", + "description": "Muestta el nivel de bateria de tu amigos en el mapa" + } + }, + "name": "Mejor ubicación", + "description": "Mejora la ubicación de Snapchat" + }, + "snapchat_plus": { + "name": "Snapchat Plus", + "description": "Habilita funciones de Snapchat Plus\nAlgunas funciones del lado del servidor pueden no funcionar" + }, + "auto_updater": { + "name": "Actualizador automático", + "description": "Comprueba automáticamente si hay actualizaciones nuevas" + }, + "disable_metrics": { + "name": "Deshabilitar métricos", + "description": "Prohíbe enviar datos específicos de análisis a Snapchat" + }, + "media_upload_quality": { + "name": "Calidad de multimedia al subir", + "description": "Anula la calidad de subida de multimedias", + "properties": { + "force_video_upload_source_quality": { + "name": "Forzar calidad del fuente al subir vídeos", + "description": "Obliga a Snapchat usar la calidad del fuente al subir vídeos\nPor favor ten en cuenta que puede que esta opción no quitará los metadatos de los multimedios" + }, + "custom_image_upload_format": { + "description": "Establece un formato personalizado de subir imágenes\nElige un formato sin pérdida (como PNG) para la mayor calidad", + "name": "Formato personalizado de subir imágenes" + }, + "disable_image_compression": { + "name": "Deshabilitar compresión de imágenes", + "description": "Deshabilita compresión de imágenes al subir multimedios" + } + } + }, + "disable_custom_tabs": { + "name": "Deshabilitar pestañas personalizadas", + "description": "Abre enlaces en aplicaciones soportadas en cambio de en el navegador" + }, + "disable_memories_snap_feed": { + "description": "Impide que Snapchat te muestra memorias recientes al deslizar hacia arriba en la cámara", + "name": "Deshabilitar memorias en el Snap Feed" + }, + "disable_permission_requests": { + "name": "Deshabilitar solicitaciones de permisiones", + "description": "Impide que Snapchat pueda preguntar para permisiones especificas" + }, + "spotlight_comments_username": { + "description": "Muestra el usuario del autor en los comentarios de Spotlight", + "name": "Nombre de usuarios en comentarios de Spotlight" + }, + "bypass_video_length_restriction": { + "name": "Saltar restricciones de longitud de vídeo", + "description": "individuo: envía un solo vídeo\nDividido: divide los vídeos después de editar" + }, + "default_video_playback_rate": { + "name": "Tasa de reproducción de video por defecto", + "description": "Establece la velocidad por defecto para vídeos\nEl valor tiene que ser entre 0.1 y 4.0" + }, + "video_playback_rate_slider": { + "name": "Control deslizante de velocidad de reproducción de vídeo", + "description": "añade control deslizante en el menú de contexto de Opera para cambiar la velocidad de reproducción de vídeos\nTen en cuenta: Cambios solo se aplican a vídeos posteriores" + }, + "disable_google_play_dialogs": { + "name": "Deshabilitar diálogos de servicio de Google Play", + "description": "Prohíbe que Servicios de Google Play muestran diálogos de disponibilidad" + }, + "disable_snap_splitting": { + "description": "Evita que los Snaps se dividan en varias partes\nLas fotos que envíes se convertirán en vídeos", + "name": "Deshabilitar que los Snaps se dividen" + }, + "default_volume_controls": { + "name": "Controles de volumen por defecto", + "description": "Fuerza que Snapchat tenga que usar controles de volumen del sistema" + }, + "hide_active_music": { + "name": "Ocultar música activa", + "description": "Evita que Snapchat sepa que estás escuchando a música\nEsto te permitirá capturar Snaps usando los botones de volumen mientras escuchas a música" + }, + "disable_telecom_framework": { + "name": "Deshabilitar el marco de telecomunicaciones", + "description": "Impide que Snapchat utilice el marco de Android Telecom\nEsto te permite escuchar música durante una llamada" + } + }, + "name": "Global", + "description": "Cambiar ajustes globales de Snapchat" + }, + "camera": { + "properties": { + "immersive_camera_preview": { + "name": "Vista previa inmersiva", + "description": "Evita que Snapchat recorte la vista previa de la cámara\nEsto podría hacer que la cámara parpadee en algunos dispositivos" + }, + "override_front_resolution": { + "name": "Anular la resolución frontal", + "description": "Anula la resolución de la cámara frontal" + }, + "disable_cameras": { + "name": "Deshabilitar cámaras", + "description": "Evita que Snapchat use las cámaras seleccionadas" + }, + "black_photos": { + "name": "Fotos negras", + "description": "Sustituye las fotos capturadas por un fondo negro\nLos vídeos no se ven afectados" + }, + "override_back_resolution": { + "name": "Anular resolución anterior", + "description": "Anula la resolución de la cámara trasera" + }, + "custom_resolution": { + "name": "Resolución personalizada", + "description": "Establece una resolución de cámara personalizada, Ancho x altura (por ejemplo 1920x1080)\nLa resolución personalizada tiene que ser soportada por tu dispositivo" + }, + "front_custom_frame_rate": { + "name": "Velocidad de fotogramas personalizada frontal", + "description": "Anula la velocidad de fotogramas de la cámara frontal" + }, + "force_camera_source_encoding": { + "name": "Forzar codificación de fuente de la cámara", + "description": "Fuerza la codificación de la fuente de la cámara" + }, + "hevc_recording": { + "name": "Grabación HEVC", + "description": "Usa el códec HEVC (H.265) para grabaciones de vídeos" + }, + "back_custom_frame_rate": { + "description": "Anula la velocidad de fotogramas de la cámara trasera", + "name": "Velocidad de fotogramas trasera" + } + }, + "name": "Cámara", + "description": "Ajustar los ajustes correctos para el Snap prefecto" + }, + "rules": { + "name": "Normas", + "description": "Gestionar funciones automáticas para personas individuales" + }, + "streaks_reminder": { + "description": "Le notifica periódicamente de tus rachas", + "name": "Recordatorio de rachas", + "properties": { + "interval": { + "name": "Intervalo", + "description": "El intervalo entre cada recordatorio (horas)" + }, + "group_notifications": { + "description": "Agrupa notificaciones en una sola notificación", + "name": "Agrupar notificaciones" + }, + "remaining_hours": { + "name": "Tiempo restante", + "description": "El tiempo que queda antes de que la notificación se muestra (horas)" + } + } + }, + "experimental": { + "description": "Funciones experimentales", + "properties": { + "native_hooks": { + "name": "Ganchos nativos", + "properties": { + "composer_hooks": { + "properties": { + "show_first_created_username": { + "description": "Muestra el primer nombre de usuario creado al lado del usuario actual en la página de perfil", + "name": "Muestra el primer nombre de usuario creado" + }, + "bypass_camera_roll_limit": { + "name": "Saltar el límite del álbum de cámara", + "description": "Aumenta la cantidad máxima de archivos multimedia que puedes enviar desde el álbum de cámara" + }, + "composer_console": { + "name": "Consola del compositor", + "description": "Le permite ejecutar código de JavaScript en el compositor (sólo arm64)" + }, + "composer_logs": { + "name": "Registro del compositor", + "description": "Redirige los registros de la consola del compositor a SnapEnhance" + } + }, + "name": "Ganchas de compositor", + "description": "Inyecta código al marco multiplataforma de interfaz de usuario de Composer" + }, + "disable_bitmoji": { + "name": "Deshabilitar Bitmoji", + "description": "Deshabilita Bitmoji en perfiles de amigxs" + }, + "custom_emoji_font": { + "name": "Fuente de los emoji personalizada", + "description": "Te permite utilizar una fuente para los emoji personalizada. Sólo funciona con fuentes .ttf" + }, + "custom_shared_library": { + "name": "Libreria compartida customizada", + "description": "Carga una biblioteca compartida personalizada en Snapchat. Esta función es solo para fines de prueba." + } + }, + "description": "Funciones inseguras que se integran al código nativo de Snapchat" + }, + "media_file_picker": { + "description": "Le permite elegir cualquier archivo de vídeo/audio de la galería", + "name": "Selector de archivos multimedia" + }, + "spoof": { + "properties": { + "remove_vpn_transport_flag": { + "name": "Quitar bandera de transporte de VPN", + "description": "Impide que Snapchat pueda detectar VPNs" + }, + "play_store_installer_package_name": { + "name": "Nombre del paquete de instalación del Play Store", + "description": "Convierte el nombre del paquete de instalación a com.android.vending" + }, + "remove_mock_location_flag": { + "name": "Quitar bandera de ubicación falsificada", + "description": "Impide que Snapchat pueda detectar ubicación falsificada" + } + }, + "name": "Falsificar", + "description": "Falsifica diversa información sobre usted" + }, + "convert_message_locally": { + "name": "Convertir mensaje localmente", + "description": "Convierte Snaps a chat multimedia externas localmente. Esto aparece en el menú de contexto de las descargas" + }, + "story_logger": { + "name": "Registro de historias", + "description": "Proporciona un historial de historias de amigxs" + }, + "e2ee": { + "description": "Cifra tus mensajes con AES usando una clave secreta compartida\n¡Asegúrate de guardar tu clave en un lugar seguro!", + "name": "Cifrado de extremo a extremo", + "properties": { + "force_message_encryption": { + "description": "Impide enviar mensajes cifrados a personas que no tienen la cifración de extremo a extremo habilitada solo cuando haya varias conversaciones seleccionadas", + "name": "Forzar el cifrado de mensajes" + }, + "encrypted_message_indicator": { + "name": "Indicador de mensajes cifrados", + "description": "Añade el emoji 🔒 al lado de mensajes cifrados" + } + } + }, + "call_recorder": { + "name": "Grabador de llamadas", + "description": "Grabar llamadas de audio automáticamente" + }, + "account_switcher": { + "name": "Cambiar cuenta", + "description": "Le permite cambiar entre cuentas sin cerrar la sesión\nHaz un pulso largo en el icono de buscar al lado de tu perfil de Bitmoji para abrir el menú\nTen en cuenta: esta función es experimental y probablemente cambiará en el futuro", + "properties": { + "auto_backup_current_account": { + "name": "Automáticamente respaldar la centa actual", + "description": "Automáticamente crea respaldos al cerrar sesión o cambiar de cuenta" + } + } + }, + "edit_message": { + "name": "Editar mensajes", + "description": "Le permite editar mensajes en conversaciones" + }, + "app_lock": { + "name": "Bloqueo de aplicación", + "description": "Impide el acceso a Snapchat sin contraseña", + "properties": { + "lock_on_resume": { + "name": "Bloquear al reanudar", + "description": "Bloquea la app al reabrirla" + } + } + }, + "infinite_story_boost": { + "name": "Promoción de historias infinita", + "description": "Omitir el retraso del límite de promoción de historia" + }, + "meo_passcode_bypass": { + "name": "Omitir contraseña de solo para mí", + "description": "Omite la contraseña del área privada\nSolo funciona si ya se ha ingresado la contraseña correcta" + }, + "no_friend_score_delay": { + "name": "Puntos de amigxs sin demora", + "description": "Elimina la demora al ver una puntuación de los amigos" + }, + "best_friend_pinning": { + "name": "Fijar mejor amigo", + "description": "Te permite fijar a un mejor amigx como tu mejor amigx número uno. Ten en cuenta: solo tú puedes ver a tu mejor amigx fijado" + }, + "custom_streaks_expiration_format": { + "description": "Personaliza el formato de caducidad de rachas\n\nVariables disponibles:\n - %c: Número de rachas\n - %e: Reloj de arena emoji\n - %d: Dían\n - %h: Horas\n - %m: Minutos\n - %s: Segundos\n - %w: Tiempo restante", + "name": "Formato de caducidad de rachas personalizado" + }, + "add_friend_source_spoof": { + "name": "Falsificación de fuente de añadir amigx", + "description": "Falsifica la fuente de dónde viene la solicitud de amistad" + }, + "hidden_snapchat_plus_features": { + "name": "Funciones de Snapchat Plus ocultas", + "description": "Habilita funciones inéditas/beta de Snapchat Plus\nPuede no funcionar en versiones antiguas de Snapchat" + }, + "prevent_forced_logout": { + "name": "Impedir el cierre de sesión forzado", + "description": "Impide que Snapchat pueda cerrar la sesión cuando inicies sesión en otro dispositivo" + }, + "cof_experiments": { + "name": "Experimentos COF", + "description": "Habilita funciones inéditas/beta de Snapchat" + }, + "context_menu_fix": { + "description": "Intente reparar el menú Friend Feed ya que cuando el dispositivo está sin conexión no se mostraba correctamente", + "name": "Corrección del menú contextual" + }, + "better_transcript": { + "properties": { + "enhanced_transcript": { + "description": "Mejora la transcripción de notas de voz usando DeepL.\nAntes de utilizar esta función, asegúrese de haber leído su política de privacidad.", + "name": "Transcripción mejorada" + }, + "enhanced_transcript_in_notifications": { + "name": "Transcripción mejorada en las notificaciones", + "description": "Transcribe notas de voz en notificaciones utilizando la dirección DeepL. Esto requiere que la función Vista previa del chat esté habilitada en Mejores notificaciones" + }, + "force_transcription": { + "description": "Permitir transcribir todas las notas de voz", + "name": "Forzar transcripción de notas de voz" + }, + "preferred_transcription_lang": { + "name": "Idioma prefiero para la transcripción", + "description": "El idioma preferido para la transcripción de la nota de voz (por ejemplo EN, ES, FR)" + } + }, + "description": "Mejora la transcripción de notas de voz", + "name": "Mejor transcripción" + }, + "voice_note_auto_play": { + "description": "Reproducir automáticamente la siguiente nota de voz después de que finalice la actual", + "name": "Reproducir automáticamente las notas de voz" + } + }, + "name": "Experimental" + }, + "scripting": { + "description": "Ejecuta código personalizado para mejorar SnapEnhance", + "properties": { + "module_folder": { + "description": "La carpeta dónde está ubicado el código", + "name": "Carpeta de módulos" + }, + "auto_reload": { + "name": "Recargar automáticamente", + "description": "Recargar código automáticamente cuando cambie" + }, + "developer_mode": { + "name": "Modo de desarrollador", + "description": "Muestra información de depuración en la interfaz de usuario de Snapchat" + }, + "integrated_ui": { + "name": "Interfaz de Usuario integrado", + "description": "Permite al código de usuarios añadir componentes de la interfaz de usuario personalizados a Snapchat" + }, + "disable_log_anonymization": { + "description": "Deshabilita la anonimización de los registros", + "name": "Deshabilitar anonimización de reegistros" + } + }, + "name": "Codificando" + }, + "friend_tracker": { + "name": "Rastreador de amigos", + "properties": { + "record_messaging_events": { + "description": "Registra eventos de mensajería como la apertura de un snap, la lectura de un mensaje, etc.", + "name": "Registra eventos de mensajería" + }, + "allow_running_in_background": { + "name": "Permitir la ejecución en segundo plano", + "description": "Permite que el rastreador se ejecute en segundo plano. Nota: Esto agotará significativamente la batería" + }, + "auto_purge": { + "name": "Purga automática", + "description": "Elimina automáticamente los eventos almacenados en caché que son más antiguos que la cantidad de tiempo especificada" + } + }, + "description": "Registra la actividad de un amigo en Snapchat" + } + }, + "notices": { + "ban_risk": "⚠ Esta característica puede causar baneos", + "unstable": "⚠ inestable", + "internal_behavior": "⚠ Esto puede romper el funcionamiento interno de Snapchat" + }, + "options": { + "app_appearance": { + "always_light": "Siempre claro", + "always_dark": "Siempre oscuro" + }, + "friend_feed_menu_buttons": { + "conversation_info": "👤 Información de conversación", + "auto_save": "💬 Guardar mensajes automáticamente", + "unsaveable_messages": "⬇️ Mensajes no guardables", + "auto_download": "⬇️ Descarga automática", + "auto_open_snaps": "📷 Automáticamente abrir Snaps", + "stealth": "👻 Modo sigilo", + "mark_snaps_as_seen": "👀 Marca Snaps como vistos", + "mark_stories_as_seen_locally": "👀 Marcar historias como vistas localmente", + "e2e_encryption": "🔒 Usar cifración de extremo a extremo" + }, + "hide_ui_components": { + "hide_profile_call_buttons": "Quitar botones de llamada de perfil", + "hide_live_location_share_button": "Quitar botón de compartir ubicación en vivo", + "hide_stickers_button": "Quitar botón de pegatinas", + "hide_voice_record_button": "Quitar botón de Grabar voz", + "hide_unread_chat_hint": "Quitar indicación de chat no leído", + "hide_chat_call_buttons": "Quitar botones de llamada de chat", + "hide_post_to_story_buttons": "Eliminar los botones Publicar en la historia antes de enviar un Snap", + "hide_billboard_prompt": "Eliminar el aviso de la página principal en el feed de amigos", + "hide_snapchat_plus_gift_reminders": "Eliminar los recordatorios de regalo de Snapchat Plus en las conversaciones", + "hide_map_reactions": "Eliminar reacciones del mapa" + }, + "hide_story_suggestions": { + "hide_my_stories": "Ocultar mis historias", + "hide_suggested_friend_stories": "Ocultar historias de amigxs sugeridas" + }, + "home_tab": { + "camera": "Cámara", + "spotlight": "Spotlight", + "map": "Mapa", + "chat": "Chat", + "discover": "Descubrir" + }, + "add_friend_source_spoof": { + "added_by_username": "Por nombre de usuario", + "added_by_mention": "Por mención", + "added_by_community": "Por comunidad", + "added_by_group_chat": "Por Grupo", + "added_by_qr_code": "Por Código QR", + "added_by_quick_add": "Por Quick Add (alto riesgo de ser baneado)" + }, + "edit_text_override": { + "multi_line_chat_input": "Entrada de chat multilínea", + "bypass_text_input_limit": "Omitir límite de entrada de texto" + }, + "disable_permission_requests": { + "notifications": "Notificaciones", + "read_media_images": "Leer imágenes de medios", + "location": "Ubicación", + "read_media_video": "Leer vídeos de medios", + "camera": "Cámara", + "microphone": "Micrófono", + "read_contacts": "Leer contactos", + "nearby_devices": "Dispositivos cercanos", + "phone_calls": "Llamadas" + }, + "message_indicators": { + "ovf_editor_indicator": "Indica si un Snap se envió usando un editor OVF", + "encryption_indicator": "Añade un icono de 🔒 al lado de mensajes que han sido enviados solo a ti", + "platform_indicator": "Añade el icono de la plataforma desde cual se envió el mensaje (por ejemplo Android, iOS, Web)", + "location_indicator": "Añade un icono de 📍 a Snaps si han sido enviados con la ubicación habilitada", + "director_mode_indicator": "Añade un icono de ✏️ a Snaps si han sido enviados usando el modo director, que se puede usar para enviar imágenes de la galería como Snaps" + }, + "bypass_video_length_restriction": { + "single": "Archivo de Media único", + "split": "Archivos de media divididos" + }, + "path_format": { + "append_username": "Añadir el usuario al nombre del archivo", + "create_author_folder": "Crear carpeta para cada autor", + "create_source_folder": "Crear carpeta para cada tipo de fuente de los archivos media", + "append_hash": "Añadir un hash único al nombre del archivo", + "append_source": "Añadir la fuente de archivo de media al nombre del archivo", + "append_date_time": "Añadir la fecha y hora al nombre del archivo" + }, + "auto_download_sources": { + "friend_snaps": "Snaps de amigxs", + "friend_stories": "Historias de amigxs", + "public_stories": "Historias públicas", + "spotlight": "Spotlight" + }, + "logging": { + "started": "Iniciado", + "success": "Finalizado con éxito", + "progress": "Progreso", + "failure": "Fallo" + }, + "notifications": { + "initiate_audio": "Llamada de audio entrante", + "chat_screenshot": "Captura de pantalla", + "chat_screen_record": "Grabación de pantalla", + "snap_replay": "Snap visto de nuevo", + "camera_roll_save": "Guardado en álbum de cámara", + "chat": "Chat", + "chat_reply": "Chat visto de nuevo", + "snap": "Snap", + "typing": "Escribiendo", + "stories": "Historias", + "speaking": "Hablando", + "chat_reaction": "Reacción a mensaje directo", + "group_chat_reaction": "Reacción de grupo", + "abandon_audio": "Llamada de audio perdida", + "initiate_video": "Llamada de vídeo entrante", + "abandon_video": "Llamada de vídeo perdida" + }, + "gallery_media_send_override": { + "always_ask": "Preguntar siempre", + "ORIGINAL": "Archivo multimedia original", + "NOTE": "Nota de voz", + "SNAP": "Snap", + "SAVEABLE_SNAP": "Snap guardable" + }, + "strip_media_metadata": { + "hide_caption_text": "Ocultar texto de subtítulos", + "hide_snap_filters": "Ocultar filtros de Snap", + "hide_extras": "Ocultar extras (por ejemplo menciones)", + "remove_audio_note_duration": "Quitar duración de nota de voz", + "remove_audio_note_transcript_capability": "Quitar capacidad de transcribir nota de voz" + }, + "old_bitmoji_selfie": { + "2d": "Bitmoji 2D", + "3d": "Bitmoji 3D" + }, + "disable_confirmation_dialogs": { + "erase_message": "Borrar mensaje", + "remove_friend": "Eliminar amigx", + "block_friend": "Bloquear amigx", + "ignore_friend": "Ignorar amigx", + "hide_friend": "Ocultar amigx", + "hide_conversation": "Ocultar conversación", + "clear_conversation": "Borrar conversación desde la lista de amigxs" + }, + "auto_reload": { + "snapchat_only": "Solo Snapchat", + "all": "Todo (Snapchat + SnapEnhance)" + }, + "auto_purge": { + "never": "Nunca", + "1_hour": "1 Hora", + "3_hours": "3 Horas", + "6_hours": "6 Horas", + "12_hours": "12 Horas", + "1_day": "1 día", + "3_days": "3 Días", + "1_week": "1 Semana", + "2_weeks": "2 Semanas", + "1_month": "1 Mes", + "3_months": "3 Meses", + "6_months": "6 Meses" + }, + "disable_story_sections": { + "discover": "Descubrir", + "friends": "Amigxs", + "following": "Siguiendo", + "suggested_stories": "Historias recomendadas" + }, + "disable_cameras": { + "front": "Cámara frontal", + "back": "Cámara trasera" + }, + "auto_mark_as_read": { + "conversation_read": "Marcar conversaciones como leídos al enviar un mensaje", + "snap_reply": "Marcar Snaps como leídos al responder" + }, + "friend_mutation_notifier": { + "remove_friend": "Notificar si alguien te elimina como amigx", + "birthday_changes": "Notificar si alguien cambia sus cumpleaños", + "bitmoji_selfie_changes": "Notificar si alguien cambia su retrato de Bitmoji", + "bitmoji_avatar_changes": "Notificar si alguien cambia su avatar de Bitmoji", + "bitmoji_background_changes": "Notificar si alguien cambia el fondo de su Bitmoji", + "bitmoji_scene_changes": "Notificar si alguien cambia su escena de Bitmoji" + }, + "custom_theme": { + "custom": "Temas personalizados (utilice las acciones rápidas para gestionar los temas)", + "material_you_dark": "Material You oscuro (Android 12+)", + "amoled_dark_mode": "Modo oscuro Amoled", + "material_you_light": "Material You claro (Android 12+)" + } + } + }, + "content_type": { + "STICKER": "Pegatina", + "STATUS_SAVE_TO_CAMERA_ROLL": "Guardado al álbum de cámara", + "STATUS_CONVERSATION_CAPTURE_SCREENSHOT": "Captura de pantalla", + "STATUS": "Estado", + "STATUS_CONVERSATION_CAPTURE_RECORD": "Grabación de pantalla", + "STATUS_CALL_MISSED_VIDEO": "Llamada de vídeo perdida", + "STATUS_CALL_MISSED_AUDIO": "Llamada de Audio perdida", + "LOCATION": "Ubicación", + "LIVE_LOCATION_SHARE": "Compartir ubicación en vivo", + "CHAT": "Chat", + "SNAP": "Snap", + "EXTERNAL_MEDIA": "Archivos de media externos", + "NOTE": "Nota de voz", + "CREATIVE_TOOL_ITEM": "Elemento de herramienta creativa", + "FAMILY_CENTER_INVITE": "Invitación de centro de familia", + "FAMILY_CENTER_ACCEPT": "Aceptar centro de familia", + "FAMILY_CENTER_LEAVE": "Salir del centro de familia", + "STATUS_PLUS_GIFT": "Regalo de estado plus", + "TINY_SNAP": "Snap diminuto", + "STATUS_COUNTDOWN": "Cuenta atrás", + "MAP_REACTION": "Reacción de mapa", + "SHARE": "Compartir" + }, + "mark_as_seen": { + "already_unseen_toast": "¡Ya marcado como no visto!", + "already_seen_toast": "¡Ya marcado como visto!", + "no_unseen_snaps_toast": "¡No se han encontrado Snaps no vistos!", + "seen_toast": "¡Marcado como visto!", + "unseen_toast": "¡Marcado como no visto!" + }, + "bulk_messaging_action": { + "choose_action_title": "Elegir una acción", + "progress_status": "Procesando {index} de {total}", + "selection_dialog_continue_button": "Continuar", + "confirmation_dialog": { + "title": "¿Estás segura/o?", + "message": "Esto afectará todos los amigxs seleccionados. Esta acción no se puede deshacer." + }, + "actions": { + "remove_friends": "Quitar amigxs", + "clear_conversations": "Borrar conversaciones" + } + }, + "chat_export": { + "exporter_dialog": { + "select_conversations_title": "Seleccionar conversaciones", + "text_field_selection": "{amount} seleccionado", + "text_field_selection_all": "Todo", + "export_file_format_title": "Exportar formato de archivo", + "message_type_filter_title": "Filtrar mensajes por tipo", + "amount_of_messages_title": "Cantidad de mensajes (dejar vacío para todos)", + "download_medias_title": "Descargar archivos de media" + }, + "dialog_negative_button": "Cancelar", + "dialog_positive_button": "Exportar", + "exported_to": "Exportado a {path}", + "exporting_chats": "Exportando Chats...", + "processing_chats": "Procesando {amount} conversaciones...", + "export_fail": "Fallo al exportar conversación {conversation}", + "writing_output": "Escribiendo salida...", + "finished": "¡Hecho! Puedes cerrar este diálogo.", + "no_messages_found": "¡No se han encontrado ningunos mensajes!", + "exporting_message": "Exportando{conversation}..." + }, + "button": { + "download": "Descargar", + "cancel": "Cancelar", + "open": "Abrir", + "positive": "Sí", + "negative": "No", + "ok": "Vale", + "send": "Enviar" + }, + "better_notifications": { + "button": { + "reply": "Responder", + "download": "Descargar", + "mark_as_read": "Marcar como leído" + } + }, + "download_processor": { + "select_attachments_title": "Seleccionar atajos", + "already_downloaded_toast": "¡Archivo de media ya descargado!", + "attachment_type": { + "snap": "Snap", + "sticker": "Pegatina", + "gif": "GIF", + "external_media": "Archivos de media externos", + "note": "Nota", + "original_story": "Historia original" + }, + "download_started_toast": "Descarga iniciada", + "unsupported_content_type_toast": "¡Tipo de contenido no compatible!", + "failed_no_longer_available_toast": "Archivos de media ya no disponibles", + "no_attachments_toast": "¡No se han encontrado atajos!", + "already_queued_toast": "¡Archivo de media ya en cola!", + "download_toast": "Descargando {path}...", + "processing_toast": "Procesando {path}...", + "failed_generic_toast": "Error al descargar", + "failed_to_create_preview_toast": "Fallo al crear vista previa", + "failed_processing_toast": "Fallo de procesar {error}", + "failed_gallery_toast": "No se pudo guardar a la galería {error}", + "dash_no_chapter": "No se encontró ningún capítulo", + "dash_dialog": { + "title": "Descargar archivos de media del tablero", + "download_all": "Descargar todo", + "segment_text": "Segmento {from} - {to}" + } + }, + "biometric_auth": { + "subtitle": "Por favor, autentícate para desbloquear Snapchat", + "unlock_button": "Desbloquear", + "title": "Desbloquear Snapchat" + }, + "end_to_end_encryption": { + "toolbox": { + "initiate_exchange_button": "Iniciar intercambio de clave", + "no_shared_key": "Aún no tienes un secreto compartido con este amigx. Pulsa abajo para iniciar un secreto nuevo.", + "shared_key_fingerprint": "Tu huella digital es:\n\n{fingerprint}\n\n¡Asegúrese de comprobar si coincide con la huella de tu amigx!" + }, + "confirmation_dialogs": { + "confirmation_2": "¿De VERDAD estás segura/o que quieres continuar? Esta es tu última oportunidad para retroceder.", + "title": "Cifrado de extremo a extremo", + "confirmation_1": "ADVERTENCIA: Esto sobrescribirá su clave existente. Perderás el acceso a todos los mensajes cifrados de este amigx. ¿Estás segura/o de que quieres continuar?" + }, + "no_participants_to_encrypt_toast": "¡No tienes ningunos amigxs en esta conversación con quien cifrar mensajes!", + "accept_public_key_failure_toast": "Fallo al aceptar clave pública", + "accept_secret_button": "Aceptar secreto", + "encryption_failed_toast": "¡Error al cifrar el mensaje! Comprueba el logcat para más detalles.", + "incoming_pk_message": "Acabas de recibir una solicitud de clave pública. Haga clic a continuación para aceptarla.", + "incoming_secret_message": "Tu amig@ acaba de aceptar tu clave pública. Haz clic abajo para aceptar el secreto.", + "accept_secret_key_success_toast": "¡Hecho! Ahora puedes enviar y recibir mensajes cifrados con este amigx.", + "accept_secret_key_failure_toast": "Fallo al aceptar clave secreta", + "accept_public_key_button": "Aceptar clave pública", + "outgoing_pk_message": "Solicitud de cambio de clave", + "outgoing_secret_message": "Respuesta de cambio de clave", + "unencrypted_conversation_send_failure_toast": "¡No puedes enviar contenido cifrado a conversaciones cifradas y no cifradas!", + "native_hooks_send_failure_toast": "¡Fallo al enviar! Por favor habilita Ganchos Nativos en los ajustes.", + "accept_public_key_success_toast": "¡Clave pública aceptada exitosamente!" + }, + "chat_action_menu": { + "delete_logged_message_button": "Borrar mensaje registrado", + "edit_message": "Editar mensaje", + "convert_message": "Convertir mensaje", + "preview_button": "Vista previa", + "download_button": "Descargar", + "show_chat_edit_history": "Mostrar el historial de edición del chat" + }, + "opera_context_menu": { + "download": "Descargar archivos de media", + "created_at": "Creado {date}", + "expires_at": "Caduca {date}", + "media_size": "Tamaño de media: {size}", + "media_duration": "Duración de media: {duration} ms", + "sent_at": "Enviado {date}", + "show_debug_info": "Mostrar información de depuración" + }, + "profile_picture_downloader": { + "title": "Descargador de imagenes de perfil", + "button": "Descargar imagen de perfil", + "avatar_option": "Avatar", + "background_option": "Fondo" + }, + "call_start_confirmation": { + "dialog_title": "Iniciar llamada", + "dialog_message": "¿Segura/o que quieres empezar una llamada?" + }, + "auto_open_snaps": { + "title": "Abrir Snaps automáticamente", + "notification_content": "{count} Snaps abiertos" + }, + "material3_strings": { + "date_input_invalid_not_allowed": "Fecha invalida", + "date_range_picker_start_headline": "Desde", + "date_range_picker_end_headline": "A", + "date_range_picker_title": "Elegir rango de fechas", + "date_picker_switch_to_calendar_mode": "Calendario", + "date_picker_switch_to_input_mode": "Entrada", + "date_range_picker_scroll_to_previous_month": "Último mes", + "date_range_picker_scroll_to_next_month": "Próximo mes", + "date_picker_today_description": "Hoy", + "date_range_picker_day_in_range": "Seleccionado", + "date_input_invalid_for_pattern": "Fecha invalida", + "date_input_invalid_year_range": "Año invalido", + "date_range_input_invalid_range_input": "Rango de fechas invalido" + }, + "friend_menu_option": { + "anti_auto_save": "Evitar el guardado automático", + "mark_snaps_as_seen": "Marcar Snap como leído", + "mark_stories_as_seen_locally": "Marcar historias como vistos localmente", + "preview": "Prevista", + "stealth_mode": "Modo sigilo", + "auto_download_blacklist": "Lista negra de descargas automáticas" + }, + "friend_mutation_observer": { + "notification_channel_name": "Observador de mutación de amigx", + "friend_removed": "{username} te ha eliminado como amigx", + "birthday_removed": "{username} ha eliminado su cumpleaños ({birthday})", + "birthday_added": "{username} ha añadido su cumpleaños ({birthday})", + "birthday_changed": "{username} ha cambiado su cumpleaños de {oldBirthday} a {newBirthday}", + "bitmoji_selfie_changed": "{username} ha cambiado su retrato de Bitmoji", + "bitmoji_avatar_changed": "{username} ha cambiado su avatar de Bitmoji", + "bitmoji_background_changed": "{username} ha cambiado el fondo de su Bitmoji", + "bitmoji_scene_changed": "{username} ha cambiado la escena de su Bitmoji" + }, + "media_download_source": { + "none": "Ninguno", + "pending": "Pendiente", + "chat_media": "Archivos de media de chat", + "story": "Historia", + "public_story": "Historia pública", + "spotlight": "Spotlight", + "profile_picture": "Imagen de perfil", + "story_logger": "Registrador de Historias", + "message_logger": "Registrador de mensajes", + "merged": "Mezclado", + "voice_call": "Llamada de voz" + }, + "modal_option": { + "profile_info": "Información de perfil", + "close": "Cerrar" + }, + "gallery_media_send_override": { + "multiple_media_toast": "Solo puedes enviar un medio a la vez" + }, + "conversation_preview": { + "streak_expiration": "Caduca en {day} días {hour} horas {minute} minutos", + "total_messages": "Suma de mensajes enviados/recibidos: {count}", + "title": "Vista previa", + "unknown_user": "Usuario desconocido", + "no_messages": "¡No se han encontrado mensajes!" + }, + "profile_info": { + "title": "Información de perfil", + "first_created_username": "Primer nombre de usuario creado", + "mutable_username": "Nombre de usuario mutable", + "display_name": "Nombre para mostrar", + "added_date": "Fecha añadida", + "birthday": "Cumpleaños: {month} {day}", + "hidden_birthday": "Cumpleaños: Ocultado", + "friendship": "Amistad", + "add_source": "Fuente de añadir", + "snapchat_plus": "Snapchat Plus", + "snapchat_plus_state": { + "subscribed": "Suscrito", + "not_subscribed": "No suscrito" + } + }, + "friendship_link_type": { + "mutual": "Mutuo", + "outgoing": "Saliente", + "blocked": "Bloqueado", + "deleted": "Borrado", + "following": "Siguiendo", + "suggested": "Sugerido", + "incoming": "Entrante", + "incoming_follower": "Seguidor entrante" + }, + "half_swipe_notifier": { + "notification_channel_name": "No acabar de deslizar por completo en un chat", + "notification_content_dm": "{friend} acaba de no acabar de deslizar por completo en tu chat durante {duration} segundos", + "notification_content_group": "{friend} Acaba de no acabar de deslizar por completo en {group} durante {duration} segundos" + }, + "streaks_reminder": { + "notification_title": "Rachas", + "notification_text": "Perderás tu racha con {friend} en {hoursLeft} horas" + }, + "theming_attributes": { + "sigColorTextPrimary": "Color principal del texto", + "sigColorBackgroundSurface": "Color del fondo", + "sigColorChatSnapWithSound": "Color del contenido de los Snaps de voz", + "sigColorChatSnapWithoutSound": "Color del contenido de los Snaps de texto", + "sigColorBackgroundMain": "Color de fondo", + "actionSheetBackgroundDrawable": "Color de fondo del Menú de acciones", + "actionSheetRoundedBackgroundDrawable": "Color de fondo redondeado del menú de acciones", + "sigExceptionColorCameraGridLines": "Color de las cuadrículas de la cámara", + "listDivider": "Color del separador de las listas", + "actionSheetDescriptionTextColor": "Color del texto de la descripción", + "listBackgroundDrawable": "Fondo de lista de la conversación", + "sigColorIconSecondary": "Color secundario del icono", + "sigColorChatConversationsLine": "Color de la línea de la conversación", + "sigColorIconPrimary": "Color del icono del menú de acciones", + "itemShapeFillColor": "Color de relleno de la forma del elemento", + "boxBackgroundColor": "Color de fondo del cuadro", + "recipientInputStyle": "Forma de entrada del destinatario", + "rangeFillColor": "Color de relleno para el rango", + "statusBarForeground": "Color en primer plano de la barra de estado", + "statusBarBackground": "Color en segundo plano de la barra de estado", + "sigColorButtonPrimary": "Color del botón principal", + "editTextColor": "Editar color del texto", + "pstsTabBackground": "Fondo de la pestaña PSTS", + "pstsDividerColor": "Color del divisor PSTS", + "tabTextColor": "Color del texto de la pestaña", + "pstsIndicatorColor": "Color del indicador PSTS", + "strokeColor": "Color del trazo", + "scButtonColor": "Color del botón de Snapchat", + "sigColorBaseAppYellow": "Aplicación principal de color amarillo", + "sigColorBackgroundSurfaceTranslucent": "Color del fondo translúcido", + "sigColorChatChat": "Color del texto del feed del amigo principal", + "sigColorChatPendingSending": "Color del texto del feed para otros amigos", + "ringColor": "Color del anillo", + "sigColorLayoutPlaceholder": "Color del marcador de posición", + "chipBackgroundColor": "Color de fondo del chip", + "ringStartColor": "Color inicial del anillo", + "storyReplayViewRingColor": "Repetición del historial Ver el color del círculo", + "sigColorStoryRingFriendsFeedStoryRing": "Color del círculo del feed de los amigos y las historias" + }, + "send_override_dialog": { + "title": "Enviar medios como {type}", + "unlimited_duration": "Ilimitado", + "duration": "Duración: {duration}", + "saveable_snap_hint": "Hacer que Snap se pueda guardar en el chat" + } +} diff --git a/common/src/main/assets/lang/fi.json b/common/src/main/assets/lang/fi.json index 8d822292..4a79737c 100644 --- a/common/src/main/assets/lang/fi.json +++ b/common/src/main/assets/lang/fi.json @@ -1,726 +1,339 @@ { "setup": { "dialogs": { - "select_language": "Valitse kieli", - "save_folder": "PurrfectSnap vaatii tallennusoikeudet median lataamiseen ja tallentamiseen Snapchatista.\nValitse sijainti, johon media ladataan.", + "select_language": "Valitse Kieli", + "save_folder": "SnapEnhance vaatii tallennus oikeudet ladatakseen mediaa Snapchatista.\nValitse sijainti mihin media tallennetaan.", "select_save_folder_button": "Valitse kansio" }, "mappings": { - "dialog": "Luodaan kartoituksia, tämä voi kestää hetken...", - "generate_failure_no_snapchat": "PurrfectSnap ei tunnistanut Snapchatia, yritä asentaa Snapchat uudelleen.", - "generate_failure": "Kartoitusten luomisessa tapahtui virhe, yritä uudelleen." + "dialog": "Luodaan kartoituksia, tämä voi kestää jonkin aikaa...", + "generate_failure_no_snapchat": "SnapEnhance ei havainnut Snapchattia, yritä asentaa Snapchat uudelleen.", + "generate_failure": "Kartoituksien luomisessa tapahtui virhe. Yritä uudelleen." }, "permissions": { "dialog": "Jatkaaksesi sinun on täytettävä seuraavat vaatimukset:", - "notification_access": "Ilmoitusten käyttöoikeus", - "battery_optimization": "Akun optimointi", - "display_over_other_apps": "Näyttö muiden sovellusten päällä", + "notification_access": "Ilmoitusten Käyttöoikeus", + "battery_optimization": "Akun Optimointi", + "display_over_other_apps": "Näytä Muiden Sovellusten Päällä", "request_button": "Pyydä" } }, - "scopes": { - "friend": "Ystävä", - "group": "Ryhmä" - }, "manager": { "routes": { - "tasks": "Tehtävät", "features": "Ominaisuudet", - "manage_rule_feature": "Hallitse sääntöominaisuutta", - "home": "Koti", + "home": "Etusivu", "home_settings": "Asetukset", "home_logs": "Lokit", - "logger_history": "Lokihistoria", - "logged_stories": "Kirjatut tarinat", - "friend_tracker": "Ystäväseuranta", - "edit_rule": "Muokkaa sääntöä", - "file_imports": "Tiedostojen tuonnit", - "manage_repos": "Hallitse arkistoja", "social": "Sosiaalinen", - "manage_scope": "Hallitse laajuutta", - "messaging_preview": "Esikatselu", - "scripts": "Skriptit", - "better_location": "Parempi sijainti" + "scripts": "Komentosarjat", + "tasks": "Tehtävät", + "logger_history": "Lokejen historia", + "logged_stories": "kirjattuja tarinoita", + "manage_scope": "Muokkaa laajuutta", + "messaging_preview": "Esikatsoa", + "friend_tracker": "Kavereiden Seuranta", + "edit_rule": "Muokkaa Sääntöä", + "better_location": "Parempi sijainti", + "manage_rule_feature": "Hallitse sääntöominaisuutta", + "file_imports": "Tiedostojen tuonnit", + "theming": "Teema", + "edit_theme": "Muokkaa teemaa", + "manage_repos": "Hallinnoi tietovarastoja" }, "sections": { - "home": { - "version_title": "v{versionName} · haarautunut Eternalilta", - "update_title": "PurrfectSnap-päivitys", - "update_content": "Versio {version} on saatavilla!", - "update_button": "Lataa", - "debug_build_summary_title": "Käytät PurrfectSnapin virheenkorjausversiota", - "debug_build_summary_content": "Versio {versionName} ({versionCode})", - "debug_build_summary_date": "Koontipäivä: {date} ({days} päivää sitten)", - "quick_actions_title": "Pikatoiminnot", - "download_icon_description": "Lataa", - "completed_icon_description": "Valmis", - "failed_icon_description": "Epäonnistui", - "manage_quick_actions_description": "Hallitse pikatoimintoja", - "quick_actions_icon_description": "Pikatoiminnot", - "add_quick_action_description": "Lisää pikatoiminto" + "features": { + "disabled": "Pois päältä", + "export_option": "Exporttaa", + "import_option": "Importtaa", + "reset_option": "Resetoida", + "saved_config_snackbar": "Config tallennettu", + "config_import_failure_toast": "Configin tuonti epäonnistui {error}", + "config_import_success_toast": "Config tuotu onnistuneesti", + "config_export_success_toast": "Config viety onnistuneesti", + "config_export_failure_toast": "Määrityksen vienti epäonnistui {error}" + }, + "social": { + "streaks_expiration_short": "{Tunnit}h", + "friends_tab": "Kaverit", + "groups_tab": "Ryhmät", + "empty_hint": "Tyhjä" }, "home_logs": { + "saved_logs_success_toast": "Lokit tallennettu onnistuneesti", + "saved_logs_failure_toast": "Epäonnistui tallentamaan lokit", "no_logs_hint": "Ei lokeja saatavilla", "clear_logs_button": "Tyhjennä lokit", - "export_logs_button": "Vie lokit", - "saving_logs_toast": "Tallennetaan lokeja, tämä voi kestää hetken...", - "saved_logs_success_toast": "Lokit tallennettu onnistuneesti", - "saved_logs_failure_toast": "Lokien tallentaminen epäonnistui" + "export_logs_button": "Exporttaa lokit", + "saving_logs_toast": "Tallennetaan lokeja, tämä voi kestää hetken ..." }, "home_settings": { - "actions_title": "Toiminnot", - "message_logger_title": "Viestiloki", - "debug_title": "Virheenkorjaus", + "actions_title": "Tapahtumat", + "message_logger_title": "viestiloggeri", + "debug_title": "debug", "success_toast": "Valmis!", - "message_logger_summary": "{messageCount} viestiä\n{storyCount} tarinaa", - "export_button": "Vie", - "clear_button": "Tyhjennä", - "view_logger_history_button": "Näytä lokihistoria", - "updates_title": "Päivitykset", - "auto_update_check": "Tarkista päivitykset automaattisesti", - "update_check_frequency": "Päivitysten tarkistustiheys", - "update_check_frequency_daily": "Päivittäin", - "update_check_frequency_weekly": "Viikoittain", - "update_check_frequency_monthly": "Kuukausittain", - "theme_icon_description": "Teema", - "app_theme_title": "Sovelluksen teema", - "theme_mode_system": "Järjestelmä", - "theme_mode_light": "Vaalea", - "theme_mode_dark": "Tumma", - "ui_settings_title": "Käyttöliittymän asetukset", - "haptic_feedback_label": "Haptinen palaute", - "test_mode_label": "Testitila (VAIN VIRHEENKORJAUKSEEN)", - "disable_feature_loading_label": "Poista ominaisuuksien lataus käytöstä", - "disable_auto_mapper_label": "Poista automaattinen kartoitus käytöstä", - "disable_bypass_indicator_label": "Poista ohitustilan ilmaisin käytöstä", - "update_notification_channel_name": "PurrfectSnap-päivitykset", - "update_notification_channel_description": "Ilmoitukset PurrfectSnap-päivityksistä", - "update_notification_title": "PurrfectSnap-päivitys saatavilla", - "update_notification_text": "Versio %s on nyt saatavilla.", - "export_database_failed_toast": "Tietokannan vienti epäonnistui! {message}", - "clear_messages_failed_toast": "Viestien tyhjentäminen epäonnistui! {message}", - "clear_file_failed_toast": "Tiedoston tyhjentäminen epäonnistui! {message}", - "debug_file_config": "Määritys", - "debug_file_mappings": "Kartoitukset", - "debug_file_message_logger": "Viestiloki", - "debug_file_pinned_best_friend": "Kiinnitetty paras ystävä", - "debug_file_native_sig_cache": "Natiiviallekirjoitusten välimuisti" + "message_logger_summary": "Tekstit\ntarinat", + "export_button": "Exporttaa", + "clear_button": "Tyhjentää", + "view_logger_history_button": "Katso logger historia" + }, + "home": { + "update_title": "SnapEnchance päivitys", + "update_content": "Versio on saatavilla", + "update_button": "Lataa", + "debug_build_summary_title": "Käytössäsi on SnapEnhance-virheenkorjaus", + "debug_build_summary_date": "Koontipäivämäärä: {date} ({days} päivää sitten)", + "quick_actions_title": "Pikatoimet" }, "tasks": { "no_tasks": "Ei tehtäviä", - "merge_button": "Yhdistä", - "failed_to_open_file": "Tiedoston avaaminen epäonnistui", - "merge_files_toast": "Yhdistetään {count} tiedostoa", - "remove_selected_tasks_title": "Haluatko varmasti poistaa valitut tehtävät?", - "remove_all_tasks_title": "Haluatko varmasti poistaa kaikki tehtävät?", - "delete_files_option": "Poista myös tiedostot", - "remove_selected_tasks_confirm": "Poistetaanko {count} tehtävää?", - "remove_all_tasks_confirm": "Poistetaanko kaikki tehtävät?", - "clear_tasks_description": "Tyhjennä tehtävät", - "file_not_found_icon_description": "Tiedostoa ei löytynyt", - "image_icon_description": "Kuva", - "video_icon_description": "Video", - "audio_icon_description": "Ääni", - "file_icon_description": "Tiedosto", - "download_icon_description": "Lataa", - "chat_action_icon_description": "Keskustelutoiminto", - "cancel_icon_description": "Peruuta", - "success_icon_description": "Onnistui", - "failure_icon_description": "Epäonnistui", - "cancelled_icon_description": "Peruutettu", - "task_status_failure": "Epäonnistui", - "task_status_cancelled": "Peruutettu" - }, - "features": { - "disabled": "Pois käytöstä", - "export_option": "Vie", - "import_option": "Tuo", - "reset_option": "Nollaa", - "config_export_success_toast": "Määritys viety onnistuneesti", - "config_import_success_toast": "Määritys tuotu onnistuneesti", - "config_import_failure_toast": "Määrityksen tuonti epäonnistui {error}", - "config_export_failure_toast": "Määrityksen vienti epäonnistui {error}", - "saved_config_snackbar": "Määritys tallennettu", - "older_required": "Tämä ominaisuus vaatii Snapchat v{version} tai vanhemman toimiakseen oikein", - "newer_required": "Tämä ominaisuus vaatii Snapchat v{version} tai uudemman toimiakseen oikein", - "search_button": "Hae" - }, - "manage_rule_feature": { - "disable_state_option": "Pois käytöstä", - "disable_state_subtext": "Yksikään ystävä/ryhmä ei vaikuta", - "whitelist_state_option": "Ei ketään paitsi...", - "whitelist_state_subtext": "Vain {count} ystävää/ryhmää vaikuttaa tähän sääntöön", - "whitelist_state_button": "Valitse sallitut ystävät/ryhmät", - "blacklist_state_option": "Kaikki paitsi...", - "blacklist_state_subtext": "Kaikki paitsi {count} ystävää/ryhmää vaikuttaa tähän sääntöön", - "blacklist_state_button": "Valitse poissuljetut ystävät/ryhmät", - "clear_list_button": "Tyhjennä ystävä-/ryhmäluettelo", - "dialog_clear_confirmation_text": "Haluatko varmasti tyhjentää luettelon?" - }, - "social": { - "friends_tab": "Ystävät", - "groups_tab": "Ryhmät", - "empty_hint": "(tyhjä)", - "streaks_expiration_short": "{hours}h" + "merge_files_toast": "Yhdistetään tiedostoja", + "remove_selected_tasks_title": "Oletko varma että haluat poistaa valitut tehtävät?", + "remove_all_tasks_title": "Oletko varma että haluat poistaa kaikki tehtävät?", + "delete_files_option": "Myös poista tiedostot", + "remove_selected_tasks_confirm": "Poista tehtävät?", + "remove_all_tasks_confirm": "Poista kaikki tehtävät?", + "failed_to_open_file": "Tiedoston avaaminen epäonnistui" }, "manage_scope": { - "logged_stories_button": "Näytä kirjatut tarinat", - "e2ee_title": "Päästä päähän -salaus", + "logged_stories_button": "Näytä logatut tarinat", "rules_title": "Säännöt", - "participants_text": "{count} osallistujaa", - "not_found": "Ei löytynyt", - "streaks_title": "Putket", - "streaks_length_text": "Pituus: {length}", - "streaks_expiration_text": "Vanhenee {eta}", + "not_found": "Ei löydetty", "streaks_expiration_text_expired": "Vanhentunut", "reminder_button": "Aseta muistutus", - "delete_scope_confirm_dialog_title": "Haluatko varmasti poistaa {scope}?", - "notes_placeholder": "Lisää muistiinpano napsauttamalla", - "invalid_key_size_32_bytes": "Virheellinen avaimen koko (oltava 32 tavua)", - "successfully_imported_key": "Avain tuotu onnistuneesti", - "failed_to_import_key": "Avaimen tuonti epäonnistui: {message}", - "export_base64_button": "Vie Base64", - "import_base64_button": "Tuo Base64" + "delete_scope_confirm_dialog_title": "Oletko varma että haluat poistaa {scope}?", + "streaks_title": "Striikit", + "streaks_length_text": "Pituus: {length}", + "streaks_expiration_text": "Vanhentuu {eta}", + "e2ee_title": "Päästä päähän salaus", + "participants_text": "{count} osallistujat" }, "logged_stories": { - "story_failed_to_load": "Lataaminen epäonnistui", - "no_stories": "Ei tarinoita löytynyt", - "save_from_cache_button": "Tallenna välimuistista", - "downloaded_to_path": "Ladattu kohteeseen {path}", - "download_failed": "Lataus epäonnistui: {message}", - "posted_at": "Julkaistu {date}", - "created_at": "Luotu {date}", - "failed_to_open_file": "Tiedoston avaaminen epäonnistui. Tarkista lokit lisätietoja varten", - "failed_to_get_file": "Tiedoston noutaminen epäonnistui" - }, - "messaging_preview": { - "processed_messages_toast": "Käsitelty {count} viestiä", - "processed_messages_text": "Käsitelty {count} viestiä", - "close_button_description": "Sulje", - "bridge_connection_failed": "Yhteyden muodostaminen siltaan epäonnistui. Varmista, että Snapchat on käynnissä taustalla", - "bridge_init_failed": "Viestisillan alustaminen epäonnistui. Varmista, että Snapchat on käynnissä taustalla", - "message_fetch_failed": "Viestien nouto epäonnistui", - "no_message_hint": "Ei viestiä", - "save_selection_option": "Tallenna valinta", - "save_all_option": "Tallenna kaikki", - "unsave_selection_option": "Poista valinnan tallennus", - "unsave_all_option": "Poista kaikkien tallennus", - "mark_selection_as_seen_option": "Merkitse valittu Snap nähdyksi", - "mark_all_as_seen_option": "Merkitse kaikki Snapit nähdyiksi", - "delete_selection_option": "Poista valinta", - "delete_all_option": "Poista kaikki" + "story_failed_to_load": "Epäonnistui lataamaan", + "no_stories": "Ei tarinoita löydetty", + "save_from_cache_button": "Tallenna Välimuistista" }, "logger_history": { - "download_started_toast": "Lataus aloitettu!", - "download_success_toast": "Ladattu kohteeseen {path}", - "download_failed_toast": "Lataus epäonnistui {message}", - "edited_at_text": "{message} (muokattu {date})", - "download_button": "Lataa", - "select_conversation_placeholder": "Valitse keskustelu", - "close_button_description": "Sulje", - "search_button_description": "Hae", - "list_friend_format": "Ystävä {name}", - "list_group_format": "Ryhmä {name}", - "no_more_messages": "Ei enempää viestejä", - "reverse_order_checkbox": "Käänteinen järjestys", - "chat_attachment": "Liite {index}", - "empty_message": "Tyhjä keskusteluviesti", + "list_friend_format": "Kaveri {name}", + "list_group_format": "Ryhmä {group}", + "unknown_sender": "Tuntematon Lähettäjä", "message_parse_failed": "Viestin jäsentäminen epäonnistui", - "unknown_sender": "Tuntematon lähettäjä", + "no_more_messages": "Ei lisää viestejä", + "chat_attachment": "Liite {index}", + "empty_message": "Tyhjä Keskustelu Viesti", "download_attachment_failed_toast": "Liitteen lataaminen epäonnistui", - "log_header_format": "{username} ({type}) - {date}" + "reverse_order_checkbox": "Järjestyksen flippaaminen" }, - "file_imports": { - "import_file_button": "Tuo tiedosto", - "file_not_found": "Tiedostoa ei löytynyt", - "file_import_failed": "Tiedoston tuonti epäonnistui: {error}", - "file_imported": "Tiedosto tuotu onnistuneesti", - "file_delete_failed": "Tiedoston poistaminen epäonnistui", - "no_files_hint": "Täällä voit tuoda tiedostoja käytettäväksi Snapchatissa. Tuo tiedosto painamalla alla olevaa painiketta." + "messaging_preview": { + "save_selection_option": "Tallenna Valinta", + "save_all_option": "Tallenna Kaikki", + "mark_all_as_seen_option": "Merkitse kaikki Snäpit nähdyksi", + "delete_selection_option": "Poista Valinta", + "delete_all_option": "Poista Kaikki", + "bridge_connection_failed": "Yhteyden muodostaminen siltaan epäonnistui. Varmista, että Snapchat on käynnissä taustalla", + "unsave_selection_option": "Poista valittu Tallennus", + "unsave_all_option": "Poista tallennus Kaikista", + "mark_selection_as_seen_option": "Merkitse valittu Snäppi nähdyksi", + "bridge_init_failed": "Viestintäsillan alustaminen epäonnistui. Varmista, että Snapchat on käynnissä taustalla", + "message_fetch_failed": "Viestien haku epäonnistui", + "no_message_hint": "Ei viestiä" }, "better_location": { - "spoofed_coordinates_title": "Lat {latitude}, LNG {longitude}", + "search_bar": "Etsi", "save_coordinates_dialog_title": "Tallenna koordinaatit", - "saved_name_dialog_hint": "Tallennettu nimi", "latitude_dialog_hint": "Leveysaste", - "longitude_dialog_hint": "Pituusaste", - "save_dialog_button": "Tallenna", - "choose_location_button": "Valitse sijainti", - "teleport_to_friend_button": "Teleporttaa ystävän luo", - "spoof_location_toggle": "Väärennä sijainti", - "suspend_location_updates": "Keskeytä sijaintipäivitykset", "saved_coordinates_title": "Tallennetut koordinaatit", - "no_saved_coordinates_hint": "Ei tallennettuja koordinaatteja", - "delete_dialog_title": "Poista tallennettu koordinaatti", - "delete_dialog_message": "Haluatko varmasti poistaa tämän tallennetun koordinaatin?", - "teleport_to_friend_title": "Teleporttaa ystävän luo", - "search_bar": "Hae", "no_friends_map": "Ei ystäviä kartalla", - "no_friends_found": "Ei ystäviä löytynyt", - "edit_location_button_description": "Muokkaa sijaintia", - "add_icon_description": "Lisää", - "edit_icon_description": "Muokkaa", - "delete_icon_description": "Poista" + "teleport_to_friend_title": "Teleporttaa ystävälle", + "save_dialog_button": "Tallenna", + "delete_dialog_message": "Oletko varma, että haluat poistaa tämän tallennetun koordinaatin?", + "no_friends_found": "Ystäviä ei löytynyt", + "choose_location_button": "Valitse sijainti", + "teleport_to_friend_button": "Teleporttaa ystävälle", + "suspend_location_updates": "Keskeytä sijaintipäivitykset", + "delete_dialog_title": "Poista tallennettu koordinaatti", + "saved_name_dialog_hint": "Tallennettu nimi", + "longitude_dialog_hint": "Pituusaste", + "spoof_location_toggle": "Huijaa sijaintia", + "no_saved_coordinates_hint": "Ei tallennettuja koordinaatteja" + }, + "file_imports": { + "no_files_hint": "Täältä voit tuoda tiedostoja käytettäväksi Snapchatissa. Tuo tiedosto painamalla alla olevaa painiketta.", + "import_file_button": "Tuo tiedosto", + "file_delete_failed": "Tiedoston poistaminen epäonnistui", + "file_import_failed": "Tiedoston tuonti epäonnistui: {error}", + "file_not_found": "Tiedostoa ei löytynyt", + "file_imported": "Tiedoston tuonti onnistui" + }, + "manage_rule_feature": { + "disable_state_option": "Poistettu käytöstä", + "disable_state_subtext": "Ei vaikuta ystäviin/ryhmiin", + "whitelist_state_subtext": "Tämä sääntö vaikuttaa vain {count} kaveriin/ryhmään", + "blacklist_state_option": "Kaikki paitsi...", + "blacklist_state_button": "Valitse poissuljetut ystävät/ryhmät", + "whitelist_state_option": "Kukaan paitsi...", + "whitelist_state_button": "Valitse sallitut ystävät/ryhmät", + "blacklist_state_subtext": "Tämä sääntö vaikuttaa kaikkiin paitsi {count} kaveriin/ryhmään", + "clear_list_button": "Tyhjennä ystävä-/ryhmäluettelo", + "dialog_clear_confirmation_text": "Oletko varma, että haluat tyhjentää luettelon?" + }, + "theming": { + "no_themes_hint": "Teemoja ei löytynyt" } }, "dialogs": { "add_friend": { - "title": "Lisää ystävä tai ryhmä", - "search_hint": "Hae", - "fetch_error": "Tietojen nouto epäonnistui", + "title": "Lisää Kaveri tai Ryhmä", + "search_hint": "Etsi", + "fetch_error": "Tietojen noutaminen epäonnistui", "category_groups": "Ryhmät", - "category_friends": "Ystävät", - "participants_text": "{count} osallistujaa", - "search_icon_description": "Hae" + "category_friends": "Kaverit" + }, + "messaging_action": { + "select_all_button": "Valitse Kaikki", + "title": "Valitse sisältö tyypit toimintoon" + }, + "reset_config": { + "title": "Alusta config", + "content": "Oletko varma että haluat alustaa configin?", + "success_toast": "Config alustettu onnistuneesti" }, "scripting_warning": { "title": "Varoitus", - "content": "PurrfectSnap sisältää komentosarjatyökalun, joka mahdollistaa käyttäjän määrittämän koodin suorittamisen laitteellasi. Ole erittäin varovainen ja asenna moduuleja vain tunnetuista, luotettavista lähteistä. Luvattomat tai vahvistamattomat moduulit voivat aiheuttaa turvallisuusriskejä järjestelmällesi." - }, - "reset_config": { - "title": "Nollaa määritys", - "content": "Haluatko varmasti nollata määrityksen?", - "success_toast": "Määritys nollattu onnistuneesti" - }, - "export_config": { - "title": "Vie arkaluontoiset tiedot?", - "content": "Haluatko viedä määrityksen arkaluontoisilla tiedoilla? (Kuten sijaintikoordinaatit jne.)" - }, - "messaging_action": { - "title": "Valitse käsiteltävät sisältötyypit", - "select_all_button": "Valitse kaikki" + "content": "SnapEnhance sisältää skriptityökalun, joka mahdollistaa käyttäjän määrittämän koodin suorittamisen. Ole erittäin varovainen ja asenna moduuleja vain tunnetuista ja luotettavista lähteistä. Luottamattomat moduulit voivat aiheuttaa tietoturvariskejä järjestelmällesi." }, "file_imports": { - "no_files_settings_hint": "Tiedostoja ei löytynyt. Varmista, että olet tuonut vaaditut tiedostot Tiedostojen tuonnit -osiossa", + "no_files_settings_hint": "Tiedostoja ei löytynyt. Varmista, että olet tuonut tarvittavat tiedostot Tiedostojen tuonti -osiossa", "settings_select_file_hint": "Valitse tuotu tiedosto" }, - "quick_actions_dialog": { - "title": "Muokkaa pikatoimintoja", - "subtitle": "Valitse ja muuta pikatoimintojesi kokoa." + "export_config": { + "title": "Viedäänkö arkaluonteisia tietoja?", + "content": "Haluatko viedä kokoonpanon arkaluontoisilla tiedoilla? (kuten sijaintikoordinaatit jne.)" } - }, - "friend_tracker": { - "rules_tab": "Säännöt", - "logs_tab": "Lokit", - "export_dialog_title": "Vie", - "bulk_export_button": "Massavienti", - "individual_export_button": "Yksittäinen vienti", - "invalid_import_type_dialog_title": "Virheellinen tuontityyppi", - "invalid_import_type_dialog_text": "Valittu tiedosto ei ole yhteensopiva tämän tuontityypin kanssa. Valitse oikea tuontityyppi.", - "import_dialog_title": "Tuo", - "bulk_import_button": "Massatuonti", - "individual_import_button": "Yksittäinen tuonti", - "import_button_description": "Tuo", - "export_button_description": "Vie", - "export_button": "Vie", - "delete_button_description": "Poista", - "delete_button": "Poista", - "catalog_button_description": "Luettelo", - "catalog_button": "Luettelo", - "add_rule_button_description": "Lisää sääntö", - "add_rule_button": "Lisää sääntö", - "no_rules_found": "Sääntöjä ei löytynyt", - "empty_rule_name": "(tyhjä)", - "events_suffix": "tapahtumaa", - "scopes_suffix": "laajuutta", - "select_rule_to_export_title": "Valitse vietävä sääntö", - "deleted_logs_toast": "Poistettu {count} lokia", - "delete_logs_dialog_title": "Poistetaanko lokit?", - "deleting_logs_dialog_text": "Poistetaan {count} lokia...", - "delete_logs_dialog_confirm_text": "Tämä poistaa lokit nykyisen suodattimen ja hakukyselyn perusteella. Tätä toimintoa ei voi kumota.", - "exported_logs_toast": "Lokit viety!", - "export_logs_failed_toast": "Lokien vienti epäonnistui. Tarkista logcat lisätietoja varten.", - "export_logs_dialog_title": "Viedäänkö lokit?", - "exporting_logs_dialog_text": "Viedään lokeja...", - "export_logs_dialog_confirm_text": "Tämä vie lokit nykyisen suodattimen ja hakukyselyn perusteella.", - "export_as_button": "Vie nimellä {type}", - "filters_title": "Suodattimet", - "search_by_label": "Hae", - "newest_first_label": "Uusimmat ensin", - "since_label": "Alkaen", - "until_label": "Asti", - "pick_a_date_button": "Valitse päivämäärä", - "search_placeholder": "Hae", - "filter_button_description": "Suodatin", - "clear_button_description": "Tyhjennä", - "no_logs_found": "Lokeja ei löytynyt", - "log_event_format": "{event} kohteessa {conversation}", - "condition_only_inside_conversation": "Vain kun olen keskustelussa", - "condition_only_outside_conversation": "Vain kun olen keskustelun ulkopuolella", - "condition_only_when_app_active": "Vain kun Snapchat on aktiivinen", - "condition_only_when_app_inactive": "Vain kun Snapchat on passiivinen", - "condition_no_push_notification_when_app_active": "Ei push-ilmoitusta, kun Snapchat on aktiivinen", - "add_event_dialog_title": "Lisää tapahtuma", - "event_type_label": "Tapahtuman tyyppi", - "triggers_title": "Laukaisimet", - "conditions_title": "Ehdot", - "add_button": "Lisää", - "default_rule_name": "Mukautettu sääntö", - "discard_changes_dialog_title": "Hylätäänkö muutokset?", - "discard_changes_dialog_text": "Sinulla on tallentamattomia muutoksia. Haluatko varmasti hylätä ne?", - "discard_button": "Hylkää", - "cannot_save_rule_dialog_title": "Sääntöä ei voi tallentaa", - "cannot_save_rule_dialog_text": "Säännössä on oltava vähintään yksi tapahtuma, jotta se voidaan tallentaa.", - "duplicate_rule_name_dialog_title": "Säännön nimi on jo olemassa", - "duplicate_rule_name_dialog_text": "Tällä nimellä on jo sääntö. Valitse toinen nimi.", - "delete_rule_dialog_title": "Poista sääntö", - "delete_rule_dialog_text": "Haluatko varmasti poistaa tämän säännön?", - "new_rule_title": "Uusi sääntö", - "edit_rule_title": "Muokkaa sääntöä", - "back_button_description": "Takaisin", - "save_button_description": "Tallenna", - "general_section_title": "Yleistä", - "rule_name_label": "Säännön nimi", - "author_name_label": "Tekijän nimi", - "scope_section_title": "Laajuus", - "scope_all": "Kaikki", - "scope_whitelist": "Sallittujen luettelo", - "scope_blacklist": "Estettyjen luettelo", - "select_friends_groups_button": "Valitse ystävät/ryhmät ({count})", - "events_section_title": "Tapahtumat", - "add_event_button": "Lisää tapahtuma", - "no_events_text": "Ei tapahtumia" - }, - "friend_tracker_catalog": { - "download_failed": "Lataus epäonnistui: {code}", - "error": "Virhe: {message}", - "no_repos_added": "Arkistoja ei ole lisätty.", - "no_rules_available": "Yhdestäkään arkistosta ei ole saatavilla sääntöjä.", - "by_author": "tekijä: {author}", - "imported_button": "Tuotu", - "import_button": "Tuo", - "title": "Ystäväseurannan luettelo", - "manage_repos_description": "Hallitse arkistoja" - }, - "friend_tracker_export": { - "title": "Vie säännöt", - "back_button_description": "Takaisin", - "exported_toast": "Ystäväseurannan säännöt viety!", - "export_failed_toast": "Sääntöjen vienti epäonnistui: {message}", - "save_button": "Tallenna", - "expand_button_description": "Laajenna" - }, - "friend_tracker_import": { - "title": "Tuo säännöt", - "back_button_description": "Takaisin", - "imported_toast": "Ystäväseurannan säännöt tuotu!", - "import_failed_toast": "Sääntöjen tuonti epäonnistui: {message}", - "confirm_button": "Vahvista", - "expand_button_description": "Laajenna" - }, - "friend_tracker_repos": { - "invalid_repo_title": "Virheellinen arkisto", - "add_repo_button": "Lisää arkisto", - "add_repo_dialog_title": "Lisää arkiston URL-osoite", - "repo_url_label": "Arkiston URL-osoite", - "repo_added_toast": "Arkisto lisätty onnistuneesti!", - "invalid_repo_error": "Tämä ei näytä olevan kelvollinen ystäväseuranta-arkisto.", - "add_repo_failed_toast": "Arkiston lisääminen epäonnistui: {message}", - "add_button": "Lisää", - "no_repos_added": "Arkistoja ei ole lisätty", - "remove_button": "Poista", - "remove_repo_dialog_title": "Poista arkisto", - "remove_repo_dialog_text": "Haluatko varmasti poistaa tämän arkiston?" - }, - "navigation": { - "tracker_tab_label": "Seuranta", - "customize_bottom_bar_title": "Mukauta alapalkkia", - "customize_bottom_bar_subtitle": "Järjestä, lisää tai poista välilehtiä. Enintään viisi.", - "shown_tabs_title": "Näytetyt välilehdet", - "no_tabs_selected_text": "Välilehtiä ei ole valittu", - "available_tabs_title": "Käytettävissä olevat välilehdet", - "reset_button": "Nollaa", - "done_button": "Valmis" - }, - "scripting": { - "script_already_installed": "Skripti on jo asennettu!", - "downloading_script": "Ladataan skriptiä...", - "script_downloaded": "Skripti {name} ladattu!", - "download_script_failed": "Skriptin lataaminen epäonnistui. Tarkista lokit lisätietoja varten", - "import_script_from_url_title": "Tuo skripti URL-osoitteesta", - "import_script_warning": "Varoitus: Tuodut skriptit voivat olla haitallisia laitteellesi. Tuo skriptejä vain luotettavista lähteistä.", - "enter_url_label": "Anna URL-osoite tähän:", - "script_imported": "Skripti {name} tuotu!", - "import_failed": "Skriptin tuonti epäonnistui. {message}. Tarkista lokit lisätietoja varten", - "import_button": "Tuo", - "update_module_button": "Päivitä moduuli", - "updating_script": "Päivitetään skriptiä {name}...", - "module_not_found": "Moduulia ei löytynyt", - "updated_script": "Päivitetty {name} versioon {version}", - "update_module_failed": "Moduulin päivitys epäonnistui. Tarkista lokit lisätietoja varten", - "edit_module_button": "Muokkaa moduulia", - "open_module_failed": "Moduulitiedoston avaaminen epäonnistui. Tarkista lokit lisätietoja varten", - "clear_module_data_button": "Tyhjennä moduulin tiedot", - "module_data_cleared": "Moduulin tiedot tyhjennetty!", - "clear_module_data_failed": "Moduulin tietojen tyhjentäminen epäonnistui. Tarkista lokit lisätietoja varten", - "delete_module_button": "Poista moduuli", - "deleted_script": "Poistettu skripti {name}!", - "delete_module_failed": "Moduulin poistaminen epäonnistui. Tarkista lokit lisätietoja varten", - "actions_title": "Toiminnot", - "no_description": "Ei kuvausta", - "update_available": "Päivitys saatavilla: {version}", - "actions_button": "Toiminnot", - "loaded_script": "Ladattu skripti {name}", - "unloaded_script": "Poistettu skripti {name}", - "enable_script_failed": "Skriptin käyttöönotto epäonnistui. Tarkista lokit lisätietoja varten", - "disable_script_failed": "Skriptin käytöstä poistaminen epäonnistui. Tarkista lokit lisätietoja varten", - "select_scripts_folder_toast": "Valitse skriptikansiosi!", - "manage_repos_button": "Hallitse arkistoja", - "import_from_url_button": "Tuo URL-osoitteesta", - "open_scripts_folder_button": "Avaa skriptikansio", - "no_settings_for_module": "Tällä moduulilla ei ole asetuksia", - "installed_scripts_tab": "Asennetut skriptit", - "catalog_tab": "Luettelo", - "no_scripts_folder_selected_title": "Skriptikansiota ei ole valittu", - "select_folder_button": "Valitse kansio", - "no_scripts_found_title": "Skriptejä ei löytynyt.", - "use_catalog_to_add_scripts": "Lisää skriptejä luettelovälilehdeltä!", - "ok_button_timeout": "OK ({timeout})", - "documentation_button": "Dokumentaatio", - "catalog": { - "script_already_installed": "Skripti on jo asennettu!", - "download_failed": "Lataus epäonnistui: {code}", - "script_downloaded": "Skripti ladattu!", - "could_not_create_file": "Tiedostoa ei voitu luoda.", - "no_scripts_folder_selected": "Skriptikansiota ei ole valittu.", - "error": "Virhe: {message}", - "no_repos_added": "Arkistoja ei ole lisätty.", - "repo_list_info": "Täältä löydät luettelon arkistoista: ", - "link_text": "Linkki", - "no_scripts_available": "Yhdestäkään arkistosta ei ole saatavilla skriptejä.", - "by_author": "tekijä: {author}", - "version": "Versio: {version}", - "installed_button": "Asennettu", - "download_button": "Lataa" - }, - "repos": { - "invalid_repo_title": "Virheellinen arkisto", - "add_repo_button": "Lisää arkisto", - "add_repo_dialog_title": "Lisää arkiston URL-osoite", - "repo_url_label": "Arkiston URL-osoite", - "repo_added_toast": "Arkisto lisätty onnistuneesti!", - "invalid_repo_error": "Tämä ei näytä olevan kelvollinen skriptiarkisto.", - "add_repo_failed_toast": "Arkiston lisääminen epäonnistui: {message}", - "add_button": "Lisää", - "no_repos_added": "Arkistoja ei ole lisätty", - "remove_button": "Poista", - "remove_repo_dialog_title": "Poista arkisto", - "remove_repo_dialog_text": "Haluatko varmasti poistaa tämän arkiston?" - } - }, - "features": { - "config_import": { - "title": "Vahvista tuonti", - "back_button_description": "Takaisin", - "config_imported_toast": "Määritys tuotu!", - "confirm_button": "Vahvista", - "expand_button_description": "Laajenna", - "enable_feature": "Ota ominaisuus käyttöön", - "enabled": "Käytössä", - "disabled": "Pois käytöstä" - }, - "config_export": { - "title": "Viennin yhteenveto", - "back_button_description": "Takaisin", - "save_button": "Tallenna", - "expand_button_description": "Laajenna", - "enable_feature": "Ota ominaisuus käyttöön", - "enabled": "Käytössä", - "disabled": "Pois käytöstä" - } - }, - "manage_repos": { - "title": "Hallitse {type} arkistoja", - "add_repo_button": "Lisää arkisto", - "add_repo_dialog_title": "Lisää arkiston URL-osoite", - "repo_url_label": "Arkiston URL-osoite", - "repo_added_successfully": "Arkisto lisätty onnistuneesti!", - "add_repo_failed": "Arkiston lisääminen epäonnistui: {message}", - "add_button": "Lisää", - "no_repos_added": "Arkistoja ei ole lisätty", - "remove_button": "Poista" } }, "rules": { - "toasts": { - "enabled": "{ruleName} käytössä", - "disabled": "{ruleName} pois käytöstä" - }, "modes": { - "blacklist": "Mustan listan tila", - "whitelist": "Valkoisen listan tila" + "blacklist": "Blacklist tila", + "whitelist": "Whitelist tila" }, "properties": { "auto_download": { - "name": "Automaattinen lataus", - "description": "Lataa Snapit automaattisesti, kun katsot niitä", + "name": "Automaattinen Lataus", + "description": "Lataa automaattisesti vastaanotetun snäpin avauksen yhteydessä", "options": { "blacklist": "Sulje pois automaattisesta latauksesta", - "whitelist": "Automaattinen lataus" + "whitelist": "Automaattinen Lataus" } }, "stealth": { - "name": "Piilotila", - "description": "Estää ketään tietämästä, että olet avannut heidän Snapinsa/keskustelunsa", + "name": "Haamutila", + "description": "Estää ketään tietämästä, että olet avannut heidän snäpin tai chatin", "options": { - "blacklist": "Sulje pois piilotilasta", - "whitelist": "Piilotila" + "blacklist": "Sulje pois haamutilasta", + "whitelist": "Haamutila" } }, "auto_save": { - "name": "Automaattinen tallennus", - "description": "Tallentaa keskusteluviestit, kun katsot niitä", + "name": "Automaattinen Tallennus", + "description": "Tallentaa chat-viestit katselun yhteydessä", "options": { - "blacklist": "Sulje pois automaattisesta tallennuksesta", + "blacklist": "Sulje pois automaattinen tallentaminen", "whitelist": "Automaattinen tallennus" } }, - "unsaveable_messages": { - "name": "Tallentamattomat viestit", - "description": "Estää muiden tallentamasta viestejä keskusteluun", - "options": { - "blacklist": "Sulje pois tallentamattomista viesteistä", - "whitelist": "Tallentamattomat viestit" - } - }, - "auto_open_snaps": { - "name": "Avaa Snapit automaattisesti", - "description": "Avaa Snapit automaattisesti, kun vastaanotat ne", - "options": { - "blacklist": "Sulje pois automaattisesta Snapien avaamisesta", - "whitelist": "Avaa Snapit automaattisesti" - } - }, "hide_friend_feed": { - "name": "Piilota ystäväsyötteestä" + "name": "Piilota Ystäväsyötteestä" }, "e2e_encryption": { "name": "Käytä E2E-salausta" }, "pin_conversation": { - "name": "Kiinnitä keskustelu" + "name": "Kiinnitä Keskustelu" }, - "exclude_message_logger": { - "name": "Sulje pois viestilokista" + "unsaveable_messages": { + "options": { + "blacklist": "Jätä pois tallentamattomista viesteistä", + "whitelist": "Tallentamattomat viestit" + }, + "name": "Tallentamattomat viestit", + "description": "Estää muita ihmisiä tallentamasta viestejä pikakeskusteluissa" + }, + "auto_open_snaps": { + "name": "Avaa Snäpit Automaattisesti", + "options": { + "whitelist": "Avaa Snäpit Automaattisesti", + "blacklist": "Poislue Automaattisesta Snäppien Avaamisesta" + }, + "description": "Avaa snäpit automaattisesti vastaanottaessa" } - } - }, - "actions": { - "clean_snapchat_cache": { - "name": "Tyhjennä Snapchatin välimuisti", - "description": "Tyhjentää Snapchatin välimuistin" }, - "manage_friend_list": { - "name": "Hallitse ystäväluetteloa", - "description": "Tuo/vie ystäväluettelosi varmuuskopioinnin yhteydessä" - }, - "export_chat_messages": { - "name": "Vie keskusteluviestit", - "description": "Vie keskusteluviestit JSON/HTML/TXT-tiedostoon" - }, - "export_memories": { - "name": "Vie muistot", - "description": "Vie muistot ZIP-tiedostoon" - }, - "bulk_messaging_action": { - "name": "Massaviestintätoiminto", - "description": "Suorittaa toimintoja, kuten ystävien poistaminen tai keskustelujen massapoisto" - }, - "regen_mappings": { - "name": "Luo kartoitukset uudelleen", - "description": "Luo kartoitukset uudelleen manuaalisesti" - }, - "change_language": { - "name": "Vaihda kieltä", - "description": "Vaihda PurrfectSnapin kieltä" - }, - "file_imports": { - "name": "Tiedostojen tuonnit", - "description": "Tuo tiedostoja käytettäväksi Snapchatissa" - }, - "friend_tracker": { - "name": "Ystäväseuranta", - "description": "Seuraa ystäviäsi Snapchatissa" - }, - "logger_history": { - "name": "Lokihistoria", - "description": "Näytä kirjattujen viestien historia" + "toasts": { + "disabled": "{ruleName} Poissa päältä", + "enabled": "{ruleName} Päällä" } }, "features": { "notices": { - "unstable": "⚠️ Epävakaa", - "ban_risk": "⚠️ Tämä ominaisuus voi aiheuttaa porttikieltoja", - "internal_behavior": "⚠️ Tämä voi rikkoa Snapchatin sisäisen toiminnan" + "unstable": "⚠ Epävakaa", + "ban_risk": "⚠ Voi aiheuttaa eston tilillesi", + "internal_behavior": "⚠ Voi rikkoa Snapchatin sisäisiä toiminnallisuuksia" }, "properties": { "downloader": { "name": "Lataaja", - "description": "Lataa Snapchat-mediaa", + "description": "Lataa Snapchat Mediaa", "properties": { "save_folder": { - "name": "Tallenna kansio", - "description": "Valitse hakemisto, johon kaikki media ladataan" + "name": "Tallennus Kansio", + "description": "Valitse kansio, johon kaikki media ladataan" }, "auto_download_sources": { - "name": "Automaattiset latauslähteet", + "name": "Automaattiset Latauslähteet", "description": "Valitse lähteet, joista ladataan automaattisesti" }, "prevent_self_auto_download": { - "name": "Estä oman median automaattinen lataus", - "description": "Estää omien Snappien automaattisen lataamisen" + "name": "Estä Automaattiset Lataukset Itseltä", + "description": "Estää omia Snappejasi latautumasta automaattisesti" }, "path_format": { - "name": "Polun muoto", + "name": "Polun Muoto", "description": "Määritä tiedostopolun muoto" }, "allow_duplicate": { - "name": "Salli kaksoiskappaleet", - "description": "Sallii saman median lataamisen useita kertoja" + "name": "Salli Kaksoiskappaleet", + "description": "Salli saman median lataamisen useita kertoja" }, "merge_overlays": { - "name": "Yhdistä peittokuvat", - "description": "Yhdistää Snapin tekstin ja median yhdeksi tiedostoksi" + "name": "Yhdistä Päälitasot", + "description": "Yhdistää snäpin tekstin ja median yhdeksi tiedostoksi" }, "force_image_format": { - "name": "Pakota kuvamuoto", - "description": "Pakottaa kuvat tallennettavaksi määritettyyn muotoon" + "name": "Pakota Kuvan Formaatti", + "description": "Pakottaa tallentamaan kuvat valitussa formaatissa" }, "force_voice_note_format": { - "name": "Pakota äänimuistiinpanon muoto", - "description": "Pakottaa äänimuistiinpanot tallennettavaksi määritettyyn muotoon" - }, - "auto_download_voice_notes": { - "name": "Lataa äänimuistiinpanot automaattisesti", - "description": "Lataa äänimuistiinpanot automaattisesti, kun niitä toistetaan" + "name": "Pakota äänimuistiinpanomuoto", + "description": "Pakottaa äänimuistiinpanot tallentamaan tietyssä muodossa" }, "download_profile_pictures": { "name": "Lataa profiilikuvat", - "description": "Mahdollistaa profiilikuvien lataamisen profiilisivulta" - }, - "opera_download_button": { - "name": "Opera-latauspainike", - "description": "Lisää latauspainikkeen oikeaan yläkulmaan, kun katsot Snappia.\nPainikkeiden pitkä painallus pakottaa latauksen" - }, - "download_context_menu": { - "name": "Latauskontekstivalikko", - "description": "Mahdollistaa viestien lataamisen/esikatselun keskustelusta tai tarinasta kontekstivalikon avulla.\nPainikkeiden pitkä painallus pakottaa latauksen" + "description": "Antaa sinun ladata profiilikuvia profiilin sivulta" }, "ffmpeg_options": { - "name": "FFmpeg-asetukset", - "description": "Määritä lisäasetuksia FFmpegille", + "name": "FFmpeg Asetukset", + "description": "Määritä FFmpeg-lisäasetukset", "properties": { "threads": { "name": "Säikeet", - "description": "Käytettävien säikeiden määrä" + "description": "Määritä rinnakkaisten säikeiden määrä" }, "preset": { "name": "Esiasetus", "description": "Aseta muunnoksen nopeus" }, "constant_rate_factor": { - "name": "Vakiolaatukerroin", - "description": "Aseta videokooderin vakiolaatukerroin\n0-51 libx264:lle" + "name": "Vakionopeustekijä", + "description": "Aseta videoenkooderin vakionopeuskerroin\n 0-51 libx264: lle" }, "video_bitrate": { "name": "Videon bittinopeus", @@ -731,36 +344,44 @@ "description": "Aseta äänen bittinopeus (kbps)" }, "custom_video_codec": { - "name": "Mukautettu videokoodekki", + "name": "Mukautettu Videokoodekki", "description": "Aseta mukautettu videokoodekki (esim. libx264)" }, "custom_audio_codec": { - "name": "Mukautettu äänikoodekki", + "name": "Mukautettu Äänikoodekki", "description": "Aseta mukautettu äänikoodekki (esim. AAC)" } } }, "logging": { - "name": "Lokitus", - "description": "Näyttää ilmoituksia, kun mediaa ladataan" + "name": "Lokiin kirjaus", + "description": "Näytä pieni ilmoitus kun lataus on käynnissä" + }, + "download_context_menu": { + "name": "Latauksen lisävalikko", + "description": "Mahdollistaa keskustelun tai tarinan viestien lataamisen/esikatselun kontekstivalikon avulla.\nPainikkeiden pitkä painallus pakottaa latauksen" }, "custom_path_format": { - "name": "Mukautettu polun muoto", - "description": "Määritä mukautettu polun muoto ladatulle medialle\n\nKäytettävissä olevat muuttujat:\n - %username%\n - %source%\n - %hash%\n - %date_time%" + "description": "Määritä mukautettu polkumuoto ladatulle medialle\n\nSaatavilla olevat muuttujat:\n - %username%\n - %source%\n - %hash%\n - %date_time%", + "name": "Mukautettu polkurakenne" + }, + "opera_download_button": { + "description": "Lisää latauspainikkeen oikeaan yläkulmaan, kun katselet Snapia.\nPainikkeiden pitkä painallus pakottaa latauksen", + "name": "Opera Lataus Painike" } } }, "user_interface": { - "name": "Käyttöliittymä", - "description": "Muuta Snapchatin ulkoasua", + "name": "Ulkoasu", + "description": "Muuta Snapchatin ulkoasua ja tuntumaa", "properties": { "enable_app_appearance": { - "name": "Ota sovelluksen ulkoasuasetukset käyttöön", + "name": "Ota käyttöön sovelluksen ulkoasuasetukset", "description": "Ottaa käyttöön piilotetun sovelluksen ulkoasuasetuksen\nEi välttämättä vaadita uudemmissa Snapchat-versioissa" }, "friend_feed_message_preview": { - "name": "Ystäväsyötteen viestin esikatselu", - "description": "Näyttää esikatselun viimeisimmistä viesteistä ystäväsyötteessä", + "name": "Ystäväsyötteen Viestien Esikatselu", + "description": "Näyttää esikatselun ystäväsyötteen viimeisimmistä viesteistä", "properties": { "amount": { "name": "Määrä", @@ -768,1255 +389,464 @@ } } }, - "snap_preview": { - "name": "Snap-esikatselu", - "description": "Näyttää pienen esikatselun näkemättömien Snappien vieressä keskustelussa" - }, "bootstrap_override": { - "name": "Bootstrap-ohitus", + "name": "Bootstrap Ohitus", "description": "Ohittaa käyttöliittymän bootstrap-asetukset", "properties": { "app_appearance": { - "name": "Sovelluksen ulkoasu", + "name": "Sovelluksen Ulkoasu", "description": "Asettaa pysyvän sovelluksen ulkoasun" }, "home_tab": { "name": "Koti-välilehti", - "description": "Ohittaa aloitusvälilehden, kun Snapchat avataan" + "description": "Valitse välilehti mikä aukeaa Snapchatin käynnistyessä" } } }, - "force_amoled_theme": { - "name": "Amoled-tumma tila", - "description": "Käyttää aitoa mustaa taustaa tummalle teemalle" - }, "map_friend_nametags": { "name": "Parannetut ystäväkartan nimilaput", - "description": "Parantaa ystävien nimilappuja Snapmapissa" - }, - "prevent_message_list_auto_scroll": { - "name": "Estä viestiluettelon automaattinen vieritys", - "description": "Estää viestiluettelon vierittymisen alas, kun lähetetään/vastaanotetaan viesti" + "description": "Parantaa ystävien nimilappuja Snapkartassa" }, "streak_expiration_info": { - "name": "Näytä putken vanhenemistiedot", - "description": "Näyttää putken vanhenemisajastimen putkilaskurin vieressä" + "name": "Näytä Striikkien Vanhenemistiedot", + "description": "Näyttää striikkien loppumisajastin streakkilaskurin vieressä" }, "hide_friend_feed_entry": { - "name": "Piilota ystäväsyötteen merkintä", - "description": "Piilottaa tietyn ystävän ystäväsyötteestä\nHallitse tätä ominaisuutta sosiaalisella välilehdellä" + "name": "Piilota ystäväsyöte", + "description": "Piilottaa tietyn ystävän ystäväsyötteestä\n Käytä sosiaalisen median välilehteä hallitaksesi tätä ominaisuutta" }, "hide_streak_restore": { - "name": "Piilota putken palautus", - "description": "Piilottaa Palauta-painikkeen ystäväsyötteestä" - }, - "hide_quick_add_suggestions": { - "name": "Piilota pikalisäysehdotukset", - "description": "Poistaa pikalisäysystäväehdotukset" - }, - "hide_story_suggestions": { - "name": "Piilota tarinaehdotukset", - "description": "Poistaa ehdotukset Tarinat-sivulta" + "name": "Piilota streakkien palautus", + "description": "Piilottaa Palauta-painikkeen ystäväsyötteessä" }, "hide_ui_components": { - "name": "Piilota käyttöliittymän komponentit", - "description": "Valitse, mitkä käyttöliittymän komponentit piilotetaan" - }, - "opera_media_quick_info": { - "name": "Opera-median pikatiedot", - "description": "Näyttää hyödyllisiä tietoja mediasta, kuten luontipäivämäärän, operan katseluohjelman kontekstivalikossa" - }, - "old_bitmoji_selfie": { - "name": "Vanha Bitmoji-selfie", - "description": "Palauttaa Bitmoji-selfiet vanhemmista Snapchat-versioista" + "name": "Piilota käyttöliittymäkomponentit", + "description": "Valitse piilotettavat käyttöliittymäkomponentit" }, "disable_spotlight": { - "name": "Poista Spotlight käytöstä", - "description": "Poistaa Spotlight-sivun käytöstä" + "name": "Poista Valokeila Käytöstä", + "description": "Poistaa Valokeila-sivun käytöstä" }, "friend_feed_menu_buttons": { - "name": "Ystäväsyötteen valikkopainikkeet", - "description": "Valitse, mitkä painikkeet näytetään ystäväsyötteen valikossa" - }, - "auto_close_friend_feed_menu": { - "name": "Sulje ystäväsyötteen valikko automaattisesti", - "description": "Sulkee ystäväsyötteen valikon automaattisesti asetuspainikkeen painamisen jälkeen" - }, - "vertical_story_viewer": { - "name": "Pystysuuntainen tarinankatseluohjelma", - "description": "Ottaa käyttöön pystysuuntaisen tarinankatseluohjelman kaikille tarinoille" + "name": "Ystävän syötteen valikkopainikkeet", + "description": "Valitse, mitkä painikkeet näytetään ystäväsyötteen valikkopalkissa" }, "enable_friend_feed_menu_bar": { "name": "Ystäväsyötteen valikkopalkki", "description": "Ottaa käyttöön uuden ystäväsyötteen valikkopalkin" }, - "message_indicators": { - "name": "Viestien ilmaisimet", - "description": "Lisää tiettyjä ilmaisinkuvakkeita viesteihin\nHuomautus: Ilmaisimet eivät välttämättä ole 100 % tarkkoja" - }, - "stealth_mode_indicator": { - "name": "Piilotilan ilmaisin", - "description": "Lisää 👻-emojin piilotilassa olevien keskustelujen viereen" - }, - "edit_text_override": { - "name": "Muokkaa tekstin ohitusta", - "description": "Ohittaa tekstikentän toiminnan" - }, - "prevent_forced_keyboard": { - "name": "Estä pakotettu näppäimistö", - "description": "Estää Snapchatia avaamasta näppäimistöä automaattisesti, kun avaat keskustelun" - }, - "settings_menu": { - "name": "Asetusvalikko", - "description": "Muuttaa tapaa, jolla avaat PurrfectSnap-valikon", - "options": { - "default": "Oletus", - "legacy": "Vanha" - } + "snap_preview": { + "name": "Snapin esikatselu" } } }, "messaging": { - "name": "Viestit", + "name": "Viestintä", "description": "Muuta tapaa, jolla olet vuorovaikutuksessa ystävien kanssa", "properties": { - "bypass_screenshot_detection": { - "name": "Ohita kuvakaappauksen tunnistus", - "description": "Estää Snapchatia tunnistamasta, kun otat kuvakaappauksen" - }, "anonymous_story_viewing": { - "name": "Anonyymi tarinankatselu", - "description": "Estää ketään tietämästä, että olet nähnyt hänen tarinansa" - }, - "prevent_story_rewatch_indicator": { - "name": "Estä tarinan uudelleenkatselun ilmaisin", - "description": "Estää ketään tietämästä, että olet katsonut hänen tarinansa uudelleen" - }, - "hide_peek_a_peek": { - "name": "Piilota Peek-a-Peek", - "description": "Estää ilmoituksen lähettämisen, kun pyyhkäiset puoliksi keskusteluun" + "name": "Nimetön tarinan katselu", + "description": "Estää ketään tietämästä, että olet nähnyt heidän tarinansa" }, "hide_bitmoji_presence": { "name": "Piilota Bitmojin läsnäolo", - "description": "Estää Bitmojisi ilmestymisen keskustelun aikana" + "description": "Estää Bitmojia ponnahtamasta esiin chatissa" }, "hide_typing_notifications": { - "name": "Piilota kirjoitusilmoitukset", - "description": "Estää ketään tietämästä, että kirjoitat viestiä" + "name": "Piilota Kirjoitusilmoitukset", + "description": "Estää ketään huomaamasta, että kirjoitat viestiä" }, "unlimited_snap_view_time": { - "name": "Rajoittamaton Snapin katseluaika", - "description": "Poistaa aikarajoituksen Snappien katselusta" - }, - "auto_mark_as_read": { - "name": "Merkitse automaattisesti luetuksi", - "description": "Merkitsee viestit/snapit automaattisesti luetuiksi, vaikka piilotila olisi käytössä" - }, - "mark_snap_as_seen_button": { - "name": "Merkitse Snap nähdyksi -painike", - "description": "Lisää painikkeen, jolla Snap merkitään nähdyksi, kun sitä katsotaan.\nTämä toimii myös, kun piilotila on käytössä" - }, - "skip_when_marking_as_seen": { - "name": "Ohita, kun merkitään nähdyksi", - "description": "Ohittaa automaattisesti seuraavaan Snapiin, kun Snap merkitään nähdyksi.\nKäytä yhdessä Merkitse Snap nähdyksi -painikkeen kanssa" - }, - "loop_media_playback": { - "name": "Toista mediaa silmukassa", - "description": "Toistaa mediaa silmukassa, kun katsot Snappeja/tarinoita" + "name": "Rajatot Snapin Katseluaika", + "description": "Poistaa snäppien katselun aikarajan käytöstä" }, "disable_replay_in_ff": { - "name": "Poista toisto käytöstä FF:ssä", - "description": "Poistaa mahdollisuuden toistaa pitkällä painalluksella ystäväsyötteestä" - }, - "half_swipe_notifier": { - "name": "Puolittaisen pyyhkäisyn ilmoitin", - "description": "Ilmoittaa, kun joku pyyhkäisee puoliksi keskusteluun", - "properties": { - "min_duration": { - "name": "Vähimmäiskesto", - "description": "Puolittaisen pyyhkäisyn vähimmäiskesto (sekunteina)" - }, - "max_duration": { - "name": "Enimmäiskesto", - "description": "Puolittaisen pyyhkäisyn enimmäiskesto (sekunteina)" - } - } - }, - "call_start_confirmation": { - "name": "Puhelun aloitusvahvistus", - "description": "Näyttää vahvistusikkunan, kun puhelu aloitetaan" - }, - "unlimited_conversation_pinning": { - "name": "Rajoittamaton keskustelujen kiinnitys", - "description": "Mahdollistaa rajoittamattoman määrän keskustelujen kiinnittämisen paikallisesti" - }, - "disable_snap_mode_restrictions": { - "name": "Poista Snap-tilan rajoitukset käytöstä", - "description": "Mahdollistaa itsestään tuhoutuvien Snappien katselun ilman rajoituksia" + "name": "Poista uusinta käytöstä FF: ssä", + "description": "Poistaa käytöstä mahdollisuuden toistaa kaverisyötteestä pitkällä painalluksella" }, "prevent_message_sending": { - "name": "Estä viestien lähettäminen", - "description": "Estää tiettyjen viestityyppien lähettämisen" - }, - "friend_mutation_notifier": { - "name": "Ystävän muutoksen ilmoitin", - "description": "Ilmoittaa, kun jotain muuttuu ystävän profiilissa" + "name": "Estä Viestien Lähettäminen", + "description": "Estää tietyntyyppisten viestien lähettämisen" }, "better_notifications": { "name": "Paremmat ilmoitukset", - "description": "Lisää tietoja vastaanotettuihin ilmoituksiin", - "properties": { - "group_notifications": { - "name": "Ryhmäilmoitukset", - "description": "Ryhmittele ilmoitukset yhdeksi" - }, - "chat_preview": { - "name": "Keskustelun esikatselu", - "description": "Näyttää esikatselun vastaanotetuista viesteistä ilmoituksessa" - }, - "media_preview": { - "name": "Median esikatselu", - "description": "Näyttää esikatselun valituista mediatyypeistä ilmoituksessa" - }, - "media_caption": { - "name": "Median kuvateksti", - "description": "Näyttää median liitetyn kuvatekstin ilmoituksessa" - }, - "stacked_media_messages": { - "name": "Pinotut mediaviestit", - "description": "Yhdistää useita mediaviestejä yhdeksi tekstiviestiksi, kun niitä ei voi esikatsella. Käytä yhdessä keskustelun esikatselun kanssa" - }, - "friend_add_source": { - "name": "Ystävän lisäyslähde", - "description": "Näyttää ystäväpyynnön lähteen ilmoituksessa" - }, - "reply_button": { - "name": "Vastaa-painike", - "description": "Lisää vastauspainikkeen ilmoitukseen" - }, - "smart_replies": { - "name": "Älykkäät vastaukset", - "description": "Lisää ehdotettuja vastauksia ilmoituksiin (Android 10+). Käytä yhdessä vastauspainikkeen kanssa" - }, - "download_button": { - "name": "Lataa-painike", - "description": "Mahdollistaa median lataamisen ilmoituksesta" - }, - "mark_as_read_button": { - "name": "Merkitse luetuksi -painike", - "description": "Mahdollistaa viestin merkitsemisen luetuksi ilmoituksesta" - }, - "mark_as_read_and_save_in_chat": { - "name": "Merkitse luetuksi ja tallenna keskusteluun", - "description": "Lisää ilmoitukseen painikkeen, jolla viesti merkitään luetuksi ja tallennetaan keskusteluun" - } - } + "description": "Antaa enemmän tietoja vastaanotetuissa ilmoituksissa" }, "notification_blacklist": { - "name": "Ilmoitusten musta lista", - "description": "Valitse, mitkä ilmoitukset estetään" + "name": "Ilmoitusten Esto Lista", + "description": "Valitse ilmoitukset joita et halua nähdä" }, "message_logger": { "name": "Viestiloki", - "description": "Estää viestien poistamisen", - "properties": { - "keep_my_own_messages": { - "name": "Säilytä omat viestini", - "description": "Estää omien viestien poistamisen" - }, - "auto_purge": { - "name": "Automaattinen tyhjennys", - "description": "Poistaa automaattisesti välimuistissa olevat viestit, jotka ovat vanhempia kuin määritetty aika" - }, - "message_filter": { - "name": "Viestisuodatin", - "description": "Valitse, mitkä viestit kirjataan (tyhjä kaikille viesteille)" - }, - "deleted_message_color": { - "name": "Poistetun viestin väri", - "description": "Asettaa poistettujen viestien värin" - } - } + "description": "Estää viestien poistamisen" }, "auto_save_messages_in_conversations": { - "name": "Tallenna viestit automaattisesti", - "description": "Tallentaa automaattisesti kaikki viestit keskusteluissa" + "name": "Automaattinen Viestien Tallennus", + "description": "Tallentaa automaattisesti jokaisen keskustelun viestin" }, "gallery_media_send_override": { - "name": "Gallerian median lähetyksen ohitus", - "description": "Väärentää median lähteen, kun lähetetään galleriasta" - }, - "strip_media_metadata": { - "name": "Poista median metatiedot", - "description": "Poistaa median metatiedot ennen lähettämistä viestinä" - }, - "bypass_message_retention_policy": { - "name": "Ohita viestien säilytyskäytäntö", - "description": "Estää viestien poistamisen niiden katselun jälkeen" - }, - "bypass_message_action_restrictions": { - "name": "Ohita viestitoimintojen rajoitukset", - "description": "Mahdollistaa reagoimisen snapiin avaamatta sitä tai tallentamattoman viestin tallentamisen" - }, - "remove_groups_locked_status": { - "name": "Poista ryhmien lukittu tila", - "description": "Mahdollistaa ryhmätietojen tarkastelun potkujen jälkeen" - }, - "double_tap_chat_action": { - "name": "Kaksoisnapautuskeskustelutoiminto", - "description": "Suorittaa mukautetun toiminnon, kun kaksoisnapautat viestiä keskustelussa" - }, - "double_tap_chat_action_custom_emoji": { - "name": "Kaksoisnapautuskeskustelutoiminnon mukautettu emoji-reaktio", - "description": "Asettaa mukautetun emoji-reaktion kaksoisnapautuskeskustelutoiminnolle" + "name": "Gallerian Medialähetyksen Ohitus", + "description": "Väärennä median lähde lähetettäessä galleriasta" } } }, "global": { - "name": "Yleinen", - "description": "Muokkaa yleisiä Snapchat-asetuksia", + "name": "Globaali", + "description": "Säädä Globaaleja Snapchatin Asetuksia", "properties": { - "better_location": { - "name": "Parempi sijainti", - "description": "Parantaa Snapchatin sijaintia", - "properties": { - "spoof_location": { - "name": "Väärennä sijainti", - "description": "Väärentää sijaintisi määritettyyn sijaintiin" - }, - "coordinates": { - "name": "Koordinaatit", - "description": "Aseta väärennetyn sijainnin koordinaatit" - }, - "walk_radius": { - "name": "Kävelysäde", - "description": "Kävele satunnaisesti tämän säteen sisällä (jalkaa)" - }, - "always_update_location": { - "name": "Päivitä sijainti aina", - "description": "Pakota Snapchat päivittämään sijainti, vaikka GPS-tietoja ei vastaanotettaisi" - }, - "suspend_location_updates": { - "name": "Keskeytä sijaintipäivitykset", - "description": "Estää sijaintisi päivittymisen" - }, - "spoof_battery_level": { - "name": "Väärennä akun varaustaso", - "description": "Väärentää laitteesi akun varaustason kartalla\nArvon on oltava välillä 0–100" - }, - "spoof_headphones": { - "name": "Väärennä kuulokkeet", - "description": "Väärentää musiikin kuuntelun tilan kartalla" - }, - "show_battery_level": { - "name": "Näytä akun varaustaso", - "description": "Näyttää ystäviesi akun varaustason kartalla" - } - } - }, "snapchat_plus": { "name": "Snapchat Plus", - "description": "Ottaa käyttöön Snapchat Plus -ominaisuudet\nJotkin palvelinpuolen ominaisuudet eivät välttämättä toimi" - }, - "media_upload_quality": { - "name": "Median latauslaatu", - "description": "Ohittaa median latauslaadun", - "properties": { - "force_video_upload_source_quality": { - "name": "Pakota videon latauksen lähdelaatu", - "description": "Pakottaa Snapchatin käyttämään lähdelaatua videoita ladattaessa\nHuomaa, että tämä ei välttämättä poista metatietoja mediasta" - }, - "disable_image_compression": { - "name": "Poista kuvan pakkaus käytöstä", - "description": "Poistaa kuvan pakkauksen käytöstä mediaa ladattaessa" - }, - "custom_image_upload_format": { - "name": "Mukautettu kuvan latausmuoto", - "description": "Asettaa mukautetun kuvan latausmuodon\nValitse häviötön muoto (kuten PNG) parhaan laadun saavuttamiseksi" - } - } - }, - "disable_confirmation_dialogs": { - "name": "Poista vahvistusikkunat käytöstä", - "description": "Vahvistaa valitut toiminnot automaattisesti" + "description": "Ota käyttöön Snapchat Plus ominaisuudet\nJotkin palvelinpohjaiset ominaisuudet eivät välttämättä toimi" }, "auto_updater": { - "name": "Automaattinen päivitys", - "description": "Tarkistaa uudet päivitykset automaattisesti" + "name": "Automaattiset Päivitykset", + "description": "Tarkistaa automaattisesti uudet päivitykset" }, "disable_metrics": { - "name": "Poista mittarit käytöstä", - "description": "Estää tiettyjen analytiikkatietojen lähettämisen Snapchatille" - }, - "disable_story_sections": { - "name": "Poista tarinaosiot käytöstä", - "description": "Poistaa osioita Tarinat-sivulta\nSaattaa vaatia päivityksen toimiakseen oikein" + "name": "Poista Analytiikka Käytöstä", + "description": "Estä analyyttisten tietojen lähettäminen Snapchatille" }, "block_ads": { - "name": "Estä mainokset", - "description": "Estää mainosten näyttämisen" - }, - "disable_custom_tabs": { - "name": "Poista mukautetut välilehdet käytöstä", - "description": "Avaa linkit tuetuissa sovelluksissa verkkoselaimen sijaan" - }, - "disable_permission_requests": { - "name": "Poista lupapyynnöt käytöstä", - "description": "Estää Snapchatia pyytämästä tiettyjä lupia" - }, - "disable_memories_snap_feed": { - "name": "Poista muistojen Snap-syöte käytöstä", - "description": "Estää Snapchatia näyttämästä viimeaikaisia muistoja, kun pyyhkäiset ylös kamerassa" - }, - "spotlight_comments_username": { - "name": "Spotlight-kommenttien käyttäjätunnus", - "description": "Näyttää tekijän käyttäjätunnuksen Spotlight-kommenteissa" + "name": "Estä Mainokset", + "description": "Estää mainoksia näkymästä" }, "bypass_video_length_restriction": { - "name": "Ohita videon pituusrajoitus", - "description": "Yksittäinen: lähettää yhden videon\nJaettu: jakaa videot editoinnin jälkeen" - }, - "default_video_playback_rate": { - "name": "Oletusvideon toistonopeus", - "description": "Asettaa videoiden toiston oletusnopeuden\nArvon on oltava välillä 0,1–4,0" - }, - "video_playback_rate_slider": { - "name": "Videon toistonopeuden liukusäädin", - "description": "Lisää liukusäätimen operan kontekstivalikkoon videon toistonopeuden muuttamiseksi\nHuomautus: Muutokset koskevat vain seuraavia videoita" + "name": "Ohita videon pituus rajoitukset", + "description": "Yksittäinen: lähettää yhden videon\nKatkottu: katkaise videot muokkauksen jälkeen" }, "disable_google_play_dialogs": { "name": "Poista Google Play -palveluiden valintaikkunat käytöstä", "description": "Estä Google Play -palveluiden saatavuusvalintaikkunoiden näyttäminen" }, - "default_volume_controls": { - "name": "Oletusäänenvoimakkuuden säätimet", - "description": "Pakottaa Snapchatin käyttämään järjestelmän äänenvoimakkuuden säätimiä" - }, - "disable_telecom_framework": { - "name": "Poista tietoliikennekehys käytöstä", - "description": "Estää Snapchatia käyttämästä Androidin tietoliikennekehystä\nTämä mahdollistaa musiikin kuuntelun puhelun aikana" - }, - "hide_active_music": { - "name": "Piilota aktiivinen musiikki", - "description": "Estää Snapchatia tietämästä, että kuuntelet musiikkia\nTämä mahdollistaa snappien ottamisen äänenvoimakkuuden säätöpainikkeilla musiikkia kuunnellessa" - }, "disable_snap_splitting": { - "name": "Poista Snapin jakaminen käytöstä", - "description": "Estää Snappien jakamisen useisiin osiin\nLähettämäsi kuvat muuttuvat videoiksi" + "name": "Poista Snäppien katkominen käytöstä", + "description": "Estää Snäppejä jakautumasta useisiin osiin\nLähettämäsi kuvat muuttuvat videoiksi" } } }, "rules": { "name": "Säännöt", - "description": "Hallitse automaattisia ominaisuuksia yksittäisille ihmisille" + "description": "Hallitse yksittäisten henkilöiden automaattisia ominaisuuksia" }, "camera": { "name": "Kamera", - "description": "Säädä oikeat asetukset täydellistä snappia varten", + "description": "Säädä oikeat asetukset täydellisen kuvan saamiseksi", "properties": { - "disable_cameras": { - "name": "Poista kamerat käytöstä", - "description": "Estää Snapchatia käyttämästä valittuja kameroita" - }, - "black_photos": { - "name": "Mustat valokuvat", - "description": "Korvaa otetut valokuvat mustalla taustalla\nVideot eivät vaikuta" - }, "immersive_camera_preview": { "name": "Mukaansatempaava esikatselu", - "description": "Estää Snapchatia rajaamasta kameran esikatselua\nTämä saattaa aiheuttaa kameran välkkymistä joissakin laitteissa" - }, - "override_front_resolution": { - "name": "Ohita etukameran tarkkuus", - "description": "Ohittaa etukameran kameran tarkkuuden" - }, - "override_back_resolution": { - "name": "Ohita takakameran tarkkuus", - "description": "Ohittaa takakameran kameran tarkkuuden" - }, - "custom_resolution": { - "name": "Mukautettu tarkkuus", - "description": "Asettaa mukautetun kameran tarkkuuden, leveys x korkeus (esim. 1920x1080).\nMukautetun tarkkuuden on oltava laitteesi tukema" - }, - "front_custom_frame_rate": { - "name": "Etukameran mukautettu kuvataajuus", - "description": "Ohittaa etukameran kuvataajuuden" - }, - "back_custom_frame_rate": { - "name": "Takakameran mukautettu kuvataajuus", - "description": "Ohittaa takakameran kuvataajuuden" + "description": "Estää Snapchatia rajaamasta kameran esikatselua.\nTämä saattaa aiheuttaa kameran välkkymistä joissakin laitteissa" }, "force_camera_source_encoding": { - "name": "Pakota kameran lähteen koodaus", - "description": "Pakottaa kameran lähteen koodauksen" - }, - "startup_default_camera": { - "name": "Oletuskamera käynnistyksessä", - "description": "Asettaa oletuskameran, kun Snapchat avataan" - }, - "hevc_recording": { - "name": "HEVC-tallennus", - "description": "Käyttää HEVC (H.265) -koodekkia videotallennukseen" + "name": "Pakota kameran lähdekoodaus", + "description": "Pakottaa kameran lähdekoodauksen" } } }, "streaks_reminder": { - "name": "Putkien muistutus", - "description": "Ilmoittaa sinulle säännöllisesti putkistasi", + "name": "Striikkien muistutukset", + "description": "Muistuttaa sinua loppuvista striikeistä", "properties": { "interval": { - "name": "Väli", - "description": "Väli kunkin muistutuksen välillä (tuntia)" + "name": "Aikaväli", + "description": "Kuinka usein sinua muistutetaan (tunneissa)" }, "remaining_hours": { - "name": "Jäljellä oleva aika", - "description": "Jäljellä oleva aika ennen ilmoituksen näyttämistä (tuntia)" + "name": "Jäljellä Oleva Aika", + "description": "Jäljellä oleva aika ennen ilmoituksen näyttämistä (tunteja)" }, "group_notifications": { - "name": "Ryhmäilmoitukset", - "description": "Ryhmittele ilmoitukset yhdeksi" + "name": "Ryhmä ilmoitukset", + "description": "Näytä ilmoitukset yhdessä ryhmässä" } } }, "experimental": { - "name": "Kokeellinen", + "name": "Kokeelliset", "description": "Kokeelliset ominaisuudet", "properties": { "native_hooks": { - "name": "Natiivikoukut", - "description": "Turvattomat ominaisuudet, jotka koukuttavat Snapchatin natiivikoodiin", + "name": "Native Hooks", + "description": "Vaarallinen ominaisuus joka kytkeytyy Snapchatin alkuperäiseen koodiin", "properties": { - "composer_hooks": { - "name": "Säveltäjäkoukut", - "description": "Ruiskuttaa koodia Composerin monialustaiseen käyttöliittymäkehykseen", - "properties": { - "show_first_created_username": { - "name": "Näytä ensimmäinen luotu käyttäjätunnus", - "description": "Näyttää ensimmäisen luodun käyttäjätunnuksen nykyisen käyttäjätunnuksen vieressä profiilisivulla" - }, - "bypass_camera_roll_limit": { - "name": "Ohita kamerarullan raja", - "description": "Lisää kamerarullasta lähetettävän median enimmäismäärää" - }, - "custom_self_destruct_snap_delay": { - "name": "Mukautettu itsestään tuhoutuvan Snapin viive", - "description": "Antaa enemmän vaihtoehtoja itsestään tuhoutuvalle ajastimelle, kun lähetetään Snap" - }, - "composer_console": { - "name": "Säveltäjäkonsoli", - "description": "Mahdollistaa JavaScript-koodin suorittamisen Composerissa (vain arm64)" - }, - "composer_logs": { - "name": "Säveltäjälokit", - "description": "Ohjaa Composerin konsolilokit PurrfectSnapiin" - } - } - }, "disable_bitmoji": { - "name": "Poista Bitmoji käytöstä", - "description": "Poistaa ystävien profiilin Bitmojin käytöstä" - }, - "custom_emoji_font": { - "name": "Mukautettu emoji-fontti", - "description": "Mahdollistaa mukautetun emoji-fontin käytön. Toimii vain .ttf-fonttien kanssa" - }, - "custom_shared_library": { - "name": "Mukautettu jaettu kirjasto", - "description": "Lataa mukautetun jaetun kirjaston Snapchatiin. Tämä ominaisuus on vain testaustarkoituksiin" + "name": "Poista Bitmoji Käytöstä", + "description": "Poista kavereiden profiili Bitmojit käytöstä" } } }, "spoof": { - "name": "Väärennös", - "description": "Väärennä erilaisia tietoja sinusta", - "properties": { - "play_store_installer_package_name": { - "name": "Play Kaupan asennusohjelman paketin nimi", - "description": "Ohittaa asennusohjelman paketin nimen arvoon com.android.vending" - }, - "remove_vpn_transport_flag": { - "name": "Poista VPN-siirtolippu", - "description": "Estää Snapchatia tunnistamasta VPN-verkkoja" - }, - "remove_mock_location_flag": { - "name": "Poista vale-sijainnin lippu", - "description": "Estää Snapchatia tunnistamasta vale-sijaintia" - } - } - }, - "convert_message_locally": { - "name": "Muunna viesti paikallisesti", - "description": "Muuntaa snapit keskustelun ulkoiseksi mediaksi paikallisesti. Tämä näkyy keskustelun latauskontekstivalikossa" - }, - "media_file_picker": { - "name": "Mediatiedostojen valitsin", - "description": "Mahdollistaa minkä tahansa video-/äänitiedoston valitsemisen galleriasta" - }, - "story_logger": { - "name": "Tarinoiden loki", - "description": "Tarjoaa ystävien tarinoiden historian" - }, - "call_recorder": { - "name": "Puhelun tallennin", - "description": "Tallentaa äänipuhelut automaattisesti" - }, - "account_switcher": { - "name": "Tilin vaihtaja", - "description": "Mahdollistaa tilien vaihtamisen kirjautumatta ulos\nPaina pitkään hakukuvaketta Bitmoji-profiilisi vieressä avataksesi valikon\nHuomautus: Tämä ominaisuus on kokeellinen ja todennäköisesti muuttuu tulevaisuudessa", - "properties": { - "auto_backup_current_account": { - "name": "Varmuuskopioi nykyinen tili automaattisesti", - "description": "Varmuuskopioi nykyisen tilin automaattisesti, kun kirjaudut ulos tai vaihdat tiliä" - } - } - }, - "better_transcript": { - "name": "Parempi transkriptio", - "description": "Parantaa äänimuistiinpanon transkriptiota", - "properties": { - "force_transcription": { - "name": "Pakota äänimuistiinpanon transkriptio", - "description": "Mahdollistaa kaikkien äänimuistiinpanojen transkription" - }, - "preferred_transcription_lang": { - "name": "Ensisijainen transkriptiokieli", - "description": "Äänimuistiinpanon transkription ensisijainen kieli (esim. EN, ES, FR)" - }, - "notification_transcript": { - "name": "Ilmoituksen transkriptio", - "description": "Transkriboi äänimuistiinpanot ilmoituksissa\nTämä ominaisuus edellyttää, että keskustelun esikatseluominaisuus on käytössä paremmissa ilmoituksissa" - } - } - }, - "voice_note_auto_play": { - "name": "Äänimuistiinpanon automaattinen toisto", - "description": "Toistaa seuraavan äänimuistiinpanon automaattisesti, kun nykyinen on päättynyt" - }, - "friend_notes": { - "name": "Ystävämuistiinpanot", - "description": "Mahdollistaa muistiinpanojen lisäämisen ystävien profiileihin" - }, - "cof_experiments": { - "name": "COF-kokeet", - "description": "Ottaa käyttöön julkaisemattomia/beta-Snapchat-ominaisuuksia" - }, - "context_menu_fix": { - "name": "Kontekstivalikon korjaus", - "description": "Yritä korjata ystäväsyötteen valikko, koska kun laite on offline-tilassa, sitä ei voi näyttää oikein" - }, - "app_lock": { - "name": "Sovelluksen lukitus", - "description": "Estää pääsyn Snapchatiin ilman salasanaa", - "properties": { - "lock_on_resume": { - "name": "Lukitse jatkettaessa", - "description": "Lukitsee sovelluksen, kun se avataan uudelleen" - } - } + "name": "Väärennä", + "description": "Väärennä erinäisiä tietoja sinusta" }, "infinite_story_boost": { - "name": "Ääretön tarinan tehostus", - "description": "Ohita tarinan tehostusrajan viive" + "name": "Loputon Tarinan Tehostus", + "description": "Ohita Story Boost Limit -viive" }, "meo_passcode_bypass": { - "name": "Ohita My Eyes Only -salasana", - "description": "Ohita My Eyes Only -salasana\nTämä toimii vain, jos salasana on syötetty oikein aiemmin" + "name": "Vain Omille Silmille- Tunnuskoodin Ohitus", + "description": "Ohittaa salasanan \"Vain omille silmille\" osioon\nTämä toimii vain, jos salasana on syötetty oikein aiemmin" }, "no_friend_score_delay": { - "name": "Ei ystäväpisteiden viivettä", - "description": "Poistaa viiveen, kun tarkastellaan ystävän pisteitä" - }, - "best_friend_pinning": { - "name": "Parhaan ystävän kiinnitys", - "description": "Mahdollistaa ystävän kiinnittämisen parhaaksi ystäväksesi. Huomautus: Vain sinä voit nähdä kiinnitetyn parhaan ystäväsi" + "name": "Ei Snäppi-Score Viivettä", + "description": "Poistaa viiveen katsottaessa Snäppi-scorea" }, "e2ee": { - "name": "Päästä päähän -salaus", - "description": "Salaa viestisi AES:llä käyttämällä jaettua salaista avainta\nVarmista, että tallennat avaimesi turvalliseen paikkaan!", + "name": "End-To-End Salaus", + "description": "Salaa viestisi AES: llä jaetun salaisen avaimen avulla\n Muista tallentaa avaimesi turvalliseen paikkaan!", "properties": { "encrypted_message_indicator": { "name": "Salatun viestin ilmaisin", - "description": "Lisää 🔒-emojin salattujen viestien viereen" + "description": "Lisää 🔒 emoji salattujen viestien viereen" }, "force_message_encryption": { - "name": "Pakota viestin salaus", - "description": "Estää salattujen viestien lähettämisen ihmisille, joilla ei ole E2E-salausta käytössä, vain kun useita keskusteluja on valittu" + "name": "Pakota Viestien Salaus", + "description": "Estää salattujen viestien lähettämisen ihmisille, joilla ei ole E2E-salausta käytössä vain kun useita keskusteluja on valittu" } } }, "add_friend_source_spoof": { - "name": "Lisää ystävän lähteen väärennös", - "description": "Väärentää ystäväpyynnön lähteen" + "name": "Lisää ystävälähteen huijaus", + "description": "Väärentää mistä kaveripyyntö on peräisin" }, "hidden_snapchat_plus_features": { "name": "Piilotetut Snapchat Plus -ominaisuudet", - "description": "Ottaa käyttöön julkaisemattomia/beta-Snapchat Plus -ominaisuuksia\nEi välttämättä toimi vanhemmissa Snapchat-versioissa" - }, - "custom_streaks_expiration_format": { - "name": "Mukautettu putkien vanhenemismuoto", - "description": "Mukauttaa putkien vanhenemismuotoa\n\nKäytettävissä olevat muuttujat:\n - %c: Putkien määrä\n - %e: Tiimalasi-emoji\n - %d: Päivät\n - %h: Tunnit\n - %m: Minuutit\n - %s: Sekunnit\n - %w: Jäljellä oleva aika" - }, - "prevent_forced_logout": { - "name": "Estä pakotettu uloskirjautuminen", - "description": "Estää Snapchatia kirjautumasta sinut ulos, kun kirjaudut sisään toisella laitteella" - }, - "snapscore_changes": { - "name": "Snapscore-muutokset", - "description": "Seuraa ystävien Snapscore-muutoksia\nKäytä tätä ominaisuutta vain Snapchatin uudemmissa versioissa" + "description": "Ottaa käyttöön julkaisemattomat/beta Snapchat Plus -ominaisuudet\nEi ehkä toimi vanhemmissa Snapchat-versioissa" } } }, "scripting": { - "name": "Skriptaus", - "description": "Suorita mukautettuja skriptejä laajentaaksesi PurrfectSnapia", + "name": "Komentojono", + "description": "Suorita mukautettuja komentosarjoja laajentaaksesi SnapEnhancea", "properties": { "developer_mode": { "name": "Kehittäjätila", - "description": "Näyttää virheenkorjaustietoja Snapchatin käyttöliittymässä" + "description": "Näyttää virheenkorjaustiedot Snapchatin käyttöliittymässä" }, "module_folder": { - "name": "Moduulikansio", - "description": "Kansio, jossa skriptit sijaitsevat" - }, - "auto_reload": { - "name": "Automaattinen uudelleenlataus", - "description": "Lataa skriptit automaattisesti uudelleen, kun ne muuttuvat" - }, - "integrated_ui": { - "name": "Integroitu käyttöliittymä", - "description": "Mahdollistaa skriptien lisäämisen mukautettuja käyttöliittymäkomponentteja Snapchatiin" - }, - "disable_log_anonymization": { - "name": "Poista lokien anonymisointi käytöstä", - "description": "Poistaa lokien anonymisoinnin käytöstä" - }, - "disable_optimization": { - "name": "Poista optimointi käytöstä", - "description": "Poistaa skriptien optimoinnin käytöstä. Tämä voi aiheuttaa suorituskykyongelmia." - } - } - }, - "friend_tracker": { - "name": "Ystäväseuranta", - "description": "Tallentaa ystävien toimintaa Snapchatissa", - "properties": { - "record_messaging_events": { - "name": "Tallenna viestitapahtumat", - "description": "Tallentaa viestitapahtumia, kuten snapin avaamisen, viestin lukemisen jne." - }, - "allow_running_in_background": { - "name": "Salli taustalla suorittaminen", - "description": "Sallii seurannan suorittamisen taustalla. Huomautus: Tämä kuluttaa akkua merkittävästi" - }, - "auto_purge": { - "name": "Automaattinen tyhjennys", - "description": "Poistaa automaattisesti välimuistissa olevat tapahtumat, jotka ovat vanhempia kuin määritetty aika" + "name": "Moduulin kansio", + "description": "Kansio, jossa komentosarjat sijaitsevat" } } } }, "options": { "app_appearance": { - "always_light": "Aina vaalea", - "always_dark": "Aina tumma" + "always_light": "Aina Vaalea", + "always_dark": "Aina Tumma" }, "friend_feed_menu_buttons": { - "auto_download": "⬇️ Automaattinen lataus", - "auto_save": "💬 Tallenna viestit automaattisesti", - "unsaveable_messages": "⬇️ Tallentamattomat viestit", - "auto_open_snaps": "📸 Avaa Snapit automaattisesti", - "stealth": "👻 Piilotila", - "mark_snaps_as_seen": "👀 Merkitse Snapit nähdyiksi", - "mark_stories_as_seen_locally": "👀 Merkitse tarinat nähdyiksi paikallisesti", - "conversation_info": "🧑‍🤝‍🧑 Keskustelun tiedot", + "auto_download": "⬇️ Automaattinen Lataus", + "auto_save": "💬 Automaattinen Viestien Tallennus", + "stealth": "👻 Haamutila", + "conversation_info": "👤 Keskustelun Tiedot", "e2e_encryption": "🔒 Käytä E2E-salausta" }, "path_format": { - "create_author_folder": "Luo kansio jokaiselle tekijälle", - "create_source_folder": "Luo kansio jokaiselle medialähteelle", - "append_hash": "Lisää yksilöllinen hajautusarvo tiedostonimeen", - "append_source": "Lisää medialähde tiedostonimeen", - "append_username": "Lisää käyttäjätunnus tiedostonimeen", - "append_date_time": "Lisää päivämäärä ja kellonaika tiedostonimeen" + "create_author_folder": "Luo kansio jokaiselle kirjoittajalle", + "create_source_folder": "Luo oma kansio jokaiselle median lähdetyypille", + "append_hash": "Lisää tiedoston nimeen yksilöllinen tiiviste", + "append_source": "Lisää median lähde tiedoston nimeen", + "append_username": "Lisää käyttäjänimi tiedoston nimeen", + "append_date_time": "Lisää päivämäärä ja aika tiedoston nimeen" }, "auto_download_sources": { - "friend_snaps": "Ystävien Snapit", - "friend_stories": "Ystävien tarinat", - "public_stories": "Julkiset tarinat", - "spotlight": "Valonheittymä" + "friend_snaps": "Kaverien Snäpit", + "friend_stories": "Kaverien Tarinat", + "public_stories": "Julkiset Tarinat", + "spotlight": "Valokeila" }, "logging": { "started": "Aloitettu", - "success": "Onnistui", + "success": "Suoritettu", "progress": "Edistyminen", "failure": "Epäonnistui" }, "notifications": { "chat_screenshot": "Kuvakaappaus", - "chat_screen_record": "Näytön tallennus", - "snap_replay": "Snapin toisto", - "camera_roll_save": "Tallenna kameran rullaan", - "chat": "Keskustelu", - "chat_reply": "Keskustelun vastaus", - "snap": "Napsauttaa", + "chat_screen_record": "Näytön Tallennus", + "snap_replay": "Snapin Uudelleenkatselu", + "camera_roll_save": "Tallennettu kameranrullaan", + "chat": "Chatti", + "chat_reply": "Chatin Vastaus", + "snap": "Snap", "typing": "Kirjoittaa", "stories": "Tarinat", - "speaking": "Puhuu", - "chat_reaction": "DM-reaktio", - "group_chat_reaction": "Ryhmäreaktio", - "initiate_audio": "Saapuva äänipuhelu", - "abandon_audio": "Vastaamaton äänipuhelu", - "initiate_video": "Saapuva videopuhelu", - "abandon_video": "Vastaamaton videopuhelu", - "map_live_location": "Kartan live-sijainti" + "chat_reaction": "DM Reaktio", + "group_chat_reaction": "Ryhmän Reaktio", + "initiate_audio": "Saapuva Äänipuhelu", + "abandon_audio": "Vastaamaton Äänipuhelu", + "initiate_video": "Saapuva Videopuhelu", + "abandon_video": "Vastaamaton Videopuhelu" }, "gallery_media_send_override": { - "always_ask": "Kysy aina", "ORIGINAL": "Alkuperäinen media", - "NOTE": "Äänimuistiinpano", - "SNAP": "Napsauttaa", - "SAVEABLE_SNAP": "Tallennettava Snap" - }, - "strip_media_metadata": { - "hide_caption_text": "Piilota kuvateksti", - "hide_snap_filters": "Piilota Snap-suodattimet", - "hide_extras": "Piilota lisäosat (esim. maininnat)", - "remove_audio_note_duration": "Poista äänimuistiinpanon kesto", - "remove_audio_note_transcript_capability": "Poista äänimuistiinpanon transkriptiokyky" + "NOTE": "Ääniviesti", + "SNAP": "Snap" }, "hide_ui_components": { - "hide_profile_call_buttons": "Poista profiilin puhelupainikkeet", - "hide_chat_call_buttons": "Poista keskustelun puhelupainikkeet", - "hide_live_location_share_button": "Poista live-sijainnin jakamispainike", - "hide_stickers_button": "Poista tarrapainike", - "hide_voice_record_button": "Poista äänityspainike", - "hide_unread_chat_hint": "Poista lukemattoman keskustelun vihje", - "hide_post_to_story_buttons": "Poista julkaise tarinaan -painikkeet ennen Snapin lähettämistä", - "hide_billboard_prompt": "Poista mainostaulu ystäväsyötteestä", - "hide_snapchat_plus_gift_reminders": "Poista Snapchat Plus -lahjamuistutukset keskusteluista", - "hide_map_reactions": "Poista karttareaktiot" - }, - "hide_story_suggestions": { - "hide_suggested_friend_stories": "Piilota ehdotetut ystävätarinat", - "hide_my_stories": "Piilota omat tarinani" + "hide_profile_call_buttons": "Poista Profiilin Soittopainikkeet", + "hide_chat_call_buttons": "Poista Chatin Puhelupainikkeet", + "hide_live_location_share_button": "Poista Sijainnin Jakopainike", + "hide_stickers_button": "Poista Tarrat -painike", + "hide_voice_record_button": "Poista Äänityspainike" }, "home_tab": { "map": "Kartta", - "chat": "Keskustelu", + "chat": "Chatti", "camera": "Kamera", - "discover": "Löydä", - "spotlight": "Valonheitin" + "discover": "Tutustu", + "spotlight": "Valokeila" }, "add_friend_source_spoof": { - "added_by_username": "Käyttäjätunnuksella", - "added_by_mention": "Maininnalla", - "added_by_group_chat": "Ryhmäkeskustelulla", + "added_by_username": "Käyttäjänimellä", + "added_by_mention": "Maininnasta", + "added_by_group_chat": "Ryhmäkeskustelusta", "added_by_qr_code": "QR-koodilla", - "added_by_community": "Yhteisöllä", - "added_by_quick_add": "Pikalisäyksellä (suuri riski saada porttikielto)" + "added_by_community": "Yhteisöstä" }, "bypass_video_length_restriction": { - "single": "Yksi media", + "single": "Yksittäinen media", "split": "Jaettu media" - }, - "old_bitmoji_selfie": { - "2d": "2D-Bitmoji", - "3d": "3D-Bitmoji" - }, - "disable_confirmation_dialogs": { - "erase_message": "Poista viesti", - "remove_friend": "Poista ystävä", - "block_friend": "Estä ystävä", - "ignore_friend": "Ohita ystävä", - "hide_friend": "Piilota ystävä", - "hide_conversation": "Piilota keskustelu", - "clear_conversation": "Tyhjennä keskustelu ystäväsyötteestä" - }, - "auto_reload": { - "snapchat_only": "Vain Snapchat", - "all": "Kaikki (Snapchat + PurrfectSnap)" - }, - "edit_text_override": { - "multi_line_chat_input": "Monirivinen keskustelusyöte", - "bypass_text_input_limit": "Ohita tekstinsyöttöraja" - }, - "auto_purge": { - "never": "Ei koskaan", - "1_hour": "1 tunti", - "3_hours": "3 tuntia", - "6_hours": "6 tuntia", - "12_hours": "12 tuntia", - "1_day": "1 päivä", - "3_days": "3 päivää", - "1_week": "1 viikko", - "2_weeks": "2 viikkoa", - "1_month": "1 kuukausi", - "3_months": "3 kuukautta", - "6_months": "6 kuukautta" - }, - "disable_story_sections": { - "friends": "Ystävät", - "suggested_stories": "Ehdotetut tarinat", - "following": "Seurataan", - "discover": "Löydä" - }, - "disable_cameras": { - "front": "Etukamera", - "back": "Takakamera" - }, - "disable_permission_requests": { - "notifications": "Ilmoitukset", - "read_media_images": "Lue mediakuvat", - "read_media_video": "Lue mediavideo", - "camera": "Kamera", - "microphone": "Mikrofoni", - "location": "Sijainti", - "read_contacts": "Lue yhteystiedot", - "nearby_devices": "Lähistöllä olevat laitteet", - "phone_calls": "Puhelut" - }, - "message_indicators": { - "encryption_indicator": "Lisää 🔒-kuvakkeen vain sinulle lähetettyjen viestien viereen", - "platform_indicator": "Lisää alustakuvakkeen, josta media on lähetetty (esim. Android, iOS, Web)", - "location_indicator": "Lisää 📍-kuvakkeen snappeihin, kun ne on lähetetty sijainnin ollessa käytössä", - "ovf_editor_indicator": "Osoittaa, onko snap lähetetty OVF-editorilla", - "director_mode_indicator": "Lisää 🎬-kuvakkeen snappeihin, kun ne on lähetetty ohjaajatilassa, jota voidaan käyttää galleriakuvien lähettämiseen snappeina" - }, - "auto_mark_as_read": { - "conversation_read": "Merkitse keskustelu luetuksi, kun lähetät viestin", - "snap_reply": "Merkitse snapit luetuiksi, kun vastaat niihin", - "save_snap_in_chat": "Merkitse snapit luetuiksi, kun tallennat ne keskusteluun piilotilassa" - }, - "friend_mutation_notifier": { - "remove_friend": "Ilmoita, kun joku poistaa sinut ystävänä", - "birthday_changes": "Ilmoita, kun joku muuttaa syntymäpäiväänsä", - "bitmoji_selfie_changes": "Ilmoita, kun joku muuttaa Bitmoji-selfieään", - "bitmoji_avatar_changes": "Ilmoita, kun joku muuttaa Bitmoji-avatariaan", - "bitmoji_background_changes": "Ilmoita, kun joku muuttaa Bitmoji-taustaansa", - "bitmoji_scene_changes": "Ilmoita, kun joku muuttaa Bitmoji-näkymäänsä" - }, - "snapchat_plus": { - "not_subscribed": "Ei tilattu", - "basic": "Perus", - "ad_free": "Mainokseton" - }, - "double_tap_chat_action": { - "like_message": "Tykkää viestistä", - "copy_text": "Kopioi teksti leikepöydälle", - "delete_message": "Poista viesti", - "mark_as_read": "Merkitse luetuksi", - "custom_emoji_reaction": "Mukautettu emoji-reaktio" - }, - "startup_default_camera": { - "front": "Etukamera", - "back": "Takakamera" } } }, "friend_menu_option": { - "mark_snaps_as_seen": "Merkitse Snapit nähdyiksi", - "mark_stories_as_seen_locally": "Merkitse tarinat nähdyiksi paikallisesti", "preview": "Esikatselu", - "stealth_mode": "Piilotila", - "auto_download_blacklist": "Automaattisen latauksen musta lista", - "anti_auto_save": "Estä automaattinen tallennus" - }, - "content_type": { - "CHAT": "Keskustelu", - "SNAP": "Napsauttaa", - "EXTERNAL_MEDIA": "Ulkoinen media", - "NOTE": "Äänimuistiinpano", - "STICKER": "Tarra", - "SHARE": "Jaa", - "STATUS": "Tila", - "LOCATION": "Sijainti", - "STATUS_SAVE_TO_CAMERA_ROLL": "Tallennettu kameran rullaan", - "STATUS_CONVERSATION_CAPTURE_SCREENSHOT": "Kuvakaappaus", - "STATUS_CONVERSATION_CAPTURE_RECORD": "Näytön tallennus", - "STATUS_CALL_MISSED_VIDEO": "Vastaamaton videopuhelu", - "STATUS_CALL_MISSED_AUDIO": "Vastaamaton äänipuhelu", - "LIVE_LOCATION_SHARE": "Jaa live-sijainti", - "CREATIVE_TOOL_ITEM": "Luovan työkalun kohde", - "FAMILY_CENTER_INVITE": "Perhekeskuksen kutsu", - "FAMILY_CENTER_ACCEPT": "Hyväksy perhekeskus", - "FAMILY_CENTER_LEAVE": "Poistu perhekeskuksesta", - "STATUS_PLUS_GIFT": "Status Plus -lahja", - "TINY_SNAP": "Pieni Snap", - "STATUS_COUNTDOWN": "Lähtölaskenta", - "MAP_REACTION": "Karttareaktio" - }, - "media_download_source": { - "none": "Ei mitään", - "pending": "Odottaa", - "chat_media": "Keskustelumedia", - "story": "Tarina", - "public_story": "Julkinen tarina", - "spotlight": "Valonheittymä", - "profile_picture": "Profiilikuva", - "story_logger": "Tarinoiden loki", - "message_logger": "Viestiloki", - "merged": "Yhdistetty", - "voice_call": "Äänipuhelu" + "stealth_mode": "Haamutila", + "auto_download_blacklist": "Automaattisen latauksen esto lista", + "anti_auto_save": "Automaattisen tallennuksen esto" }, "chat_action_menu": { "preview_button": "Esikatselu", "download_button": "Lataa", - "delete_logged_message_button": "Poista kirjattu viesti", - "show_chat_edit_history": "Näytä keskustelun muokkaushistoria", - "convert_message": "Muunna viesti" + "delete_logged_message_button": "Poista kirjattu viesti" }, "opera_context_menu": { - "download": "Lataa media", - "sent_at": "Lähetetty {date}", - "created_at": "Luotu {date}", - "expires_at": "Vanhenee {date}", - "media_size": "Median koko: {size}", - "media_duration": "Median kesto: {duration} ms", - "show_debug_info": "Näytä virheenkorjaustiedot" + "download": "Lataa Media" }, "modal_option": { - "profile_info": "Profiilin tiedot", + "profile_info": "Profiilin Tiedot", "close": "Sulje" }, "gallery_media_send_override": { "multiple_media_toast": "Voit lähettää vain yhden median kerrallaan" }, - "mark_as_seen": { - "no_unseen_snaps_toast": "Ei näkemättömiä Snappeja!", - "seen_toast": "Merkitty nähdyksi!", - "unseen_toast": "Merkitty näkemättömäksi!", - "already_seen_toast": "Jo merkitty nähdyksi!", - "already_unseen_toast": "Jo merkitty näkemättömäksi!" - }, "conversation_preview": { - "streak_expiration": "vanhenee {day} päivän {hour} tunnin {minute} minuutin kuluttua", - "total_messages": "Lähetettyjen/vastaanotettujen viestien kokonaismäärä: {count}", + "streak_expiration": "loppuu {day} päivän {hour} tunnin {minute} minuutin kuluttua", + "total_messages": "Lähetetyt/vastaanotetut viestit yhteensä: {count}", "title": "Esikatselu", - "unknown_user": "Tuntematon käyttäjä", - "no_messages": "Ei viestejä löytynyt!" + "unknown_user": "Tuntematon käyttäjä" }, "profile_info": { "title": "Profiilin tiedot", - "first_created_username": "Ensimmäinen luotu käyttäjätunnus", - "mutable_username": "Muutettava käyttäjätunnus", + "first_created_username": "Ensimmäinen Käyttäjätunnus", + "mutable_username": "Muutettava Käyttäjätunnus", "display_name": "Näyttönimi", - "added_date": "Lisäyspäivämäärä", - "birthday": "Syntymäpäivä: {day} {month}", - "hidden_birthday": "Syntymäpäivä: Piilotettu", + "added_date": "Lisätty Päivämäärä", + "birthday": "Syntymäpäivä: {month} {day}", "friendship": "Ystävyys", "add_source": "Lisää lähde", "snapchat_plus": "Snapchat Plus", "snapchat_plus_state": { "subscribed": "Tilattu", - "not_subscribed": "Ei tilattu" - } - }, - "friendship_link_type": { - "mutual": "Keskinäinen", - "outgoing": "Lähtevä", - "blocked": "Estetty", - "deleted": "Poistettu", - "following": "Seurataan", - "suggested": "Ehdotettu", - "incoming": "Saapuva", - "incoming_follower": "Saapuva seuraaja" - }, - "bulk_messaging_action": { - "choose_action_title": "Valitse toiminto", - "progress_status": "Käsitellään {index}/{total}", - "selection_dialog_continue_button": "Jatka", - "confirmation_dialog": { - "title": "Oletko varma?", - "message": "Tämä vaikuttaa kaikkiin valittuihin ystäviin. Tätä toimintoa ei voi kumota." - }, - "actions": { - "remove_friends": "Poista ystävät", - "clear_conversations": "Tyhjennä keskustelut" + "not_subscribed": "Ei Tilattu" } }, "chat_export": { - "exporter_dialog": { - "select_conversations_title": "Valitse keskustelut", - "text_field_selection": "{amount} valittu", - "text_field_selection_all": "Kaikki", - "export_file_format_title": "Vie tiedostomuoto", - "message_type_filter_title": "Suodata viestit tyypin mukaan", - "amount_of_messages_title": "Viestien määrä (jätä tyhjäksi kaikille)", - "download_medias_title": "Lataa mediat" - }, "dialog_negative_button": "Peruuta", "dialog_positive_button": "Vie", - "exported_to": "Viety kohteeseen {path}", - "exporting_chats": "Viedään keskusteluja...", - "processing_chats": "Käsitellään {amount} keskustelua...", - "export_fail": "Keskustelun {conversation} vienti epäonnistui", - "writing_output": "Kirjoitetaan tulostetta...", - "finished": "Valmis! Voit nyt sulkea tämän valintaikkunan.", - "no_messages_found": "Ei viestejä löytynyt!", + "exported_to": "Viety {path}", + "exporting_chats": "Viedään Keskusteluja...", + "processing_chats": "Käsitellään {amount} keskustelu(a)...", + "export_fail": "Ei voitu viedä keskustelua {conversation}", + "writing_output": "Tulostetta kirjoitetaan...", + "finished": "Valmis! Voit nyt sulkea tämän ikkunan.", + "no_messages_found": "Viestejä ei löytynyt!", "exporting_message": "Viedään {conversation}..." }, "button": { - "ok": "Hyvä", + "ok": "OK", "positive": "Kyllä", "negative": "Ei", "cancel": "Peruuta", "open": "Avaa", - "download": "Lataa", - "send": "Lähetä", - "restore_original": "Palauta alkuperäinen", - "convert_external_media": "Muunna ulkoinen media", - "save": "Tallenna" - }, - "tracker_events": { - "conversation_enter": "Keskusteluun liittyminen", - "conversation_exit": "Keskustelusta poistuminen", - "started_typing": "Aloitti kirjoittamisen", - "stopped_typing": "Lopetti kirjoittamisen", - "started_speaking": "Aloitti puhumisen", - "stopped_speaking": "Lopetti puhumisen", - "started_peeking": "Aloitti kurkkimisen", - "stopped_peeking": "Lopetti kurkkimisen", - "message_read": "Viesti luettu", - "message_deleted": "Viesti poistettu", - "message_saved": "Viesti tallennettu", - "message_unsaved": "Viestiä ei tallennettu", - "message_edited": "Viesti muokattu", - "message_reaction_add": "Lisää viestireaktio", - "message_reaction_remove": "Poista viestireaktio", - "snap_opened": "Snap avattu", - "snap_replayed": "Snap toistettu uudelleen", - "snap_replayed_twice": "Snap toistettu uudelleen kahdesti", - "snap_screenshot": "Snapin kuvakaappaus", - "snap_screen_record": "Snapin näyttötallennus" - }, - "tracker_actions": { - "log": "Loki", - "in_app_notification": "Sovelluksen sisäinen ilmoitus", - "push_notification": "Push-ilmoitus", - "custom": "Mukautettu" - }, - "better_notifications": { - "button": { - "reply": "Vastaa", - "download": "Lataa", - "mark_as_read": "Merkitse luetuksi" - } + "download": "Lataa" }, "profile_picture_downloader": { - "button": "Lataa profiilikuva", - "title": "Profiilikuvien lataaja", - "avatar_option": "Avataari", + "button": "Lataa Profiilikuva", + "title": "Profiilikuvan Lataaja", + "avatar_option": "Hahmo", "background_option": "Tausta" }, - "call_start_confirmation": { - "dialog_title": "Aloita puhelu", - "dialog_message": "Haluatko varmasti aloittaa puhelun?" - }, - "half_swipe_notifier": { - "notification_channel_name": "Puolittainen pyyhkäisy", - "notification_content_dm": "{friend} pyyhkäisi juuri puoliksi keskusteluusi {duration} sekunnin ajan", - "notification_content_group": "{friend} pyyhkäisi juuri puoliksi kohteeseen {group} {duration} sekunnin ajan" - }, "download_processor": { "attachment_type": { - "snap": "Napsauttaa", + "snap": "Snap", "sticker": "Tarra", - "gif": "Gif", - "external_media": "Ulkoinen media", - "note": "Muistiinpano", - "original_story": "Alkuperäinen tarina" + "external_media": "Ulkoinen Media", + "note": "Merkintä", + "original_story": "Alkuperäinen Tarina" }, "select_attachments_title": "Valitse liitteet", "download_started_toast": "Lataus aloitettu", - "unsupported_content_type_toast": "Tukematon sisältötyyppi!", + "unsupported_content_type_toast": "Sisältötyyppiä ei tueta!", "failed_no_longer_available_toast": "Media ei ole enää saatavilla", "no_attachments_toast": "Liitteitä ei löytynyt!", "already_queued_toast": "Media on jo jonossa!", "already_downloaded_toast": "Media on jo ladattu!", - "content_saved_toast": "Tallennettu!", "download_toast": "Ladataan {path}...", "processing_toast": "Käsitellään {path}...", "failed_generic_toast": "Lataus epäonnistui", "failed_to_create_preview_toast": "Esikatselun luominen epäonnistui", "failed_processing_toast": "Käsittely epäonnistui {error}", - "failed_gallery_toast": "Tallennus galleriaan epäonnistui {error}", - "dash_no_chapter": "Lukua ei löytynyt", - "dash_dialog": { - "title": "Lataa dash-mediaa", - "download_all": "Lataa kaikki", - "segment_text": "Segmentti {from} - {to}" - } + "failed_gallery_toast": "Tallennus galleriaan epäonnistui {error}" }, "streaks_reminder": { - "notification_title": "Putket", - "notification_text": "Menetät putkesi käyttäjän {friend} kanssa {hoursLeft} tunnin kuluttua" + "notification_title": "Striikit", + "notification_text": "Menetät Striikit {Kaveri}: n kanssa {hoursLeft} tunnin kuluttua" }, - "biometric_auth": { - "unlock_button": "Avaa lukitus", - "title": "Avaa Snapchatin lukitus", - "subtitle": "Vahvista henkilöllisyytesi avataksesi Snapchatin lukituksen" + "scopes": { + "friend": "Kaveri", + "group": "Ryhmä" }, - "end_to_end_encryption": { - "toolbox": { - "no_shared_key": "Sinulla ei ole vielä jaettua salaista avainta tämän ystävän kanssa. Napsauta alla aloittaaksesi uuden.", - "shared_key_fingerprint": "Sormenjälkesi on:\n\n{fingerprint}\n\nVarmista, että se vastaa ystäväsi sormenjälkeä!", - "initiate_exchange_button": "Aloita avaimenvaihto" + "actions": { + "bulk_messaging_action": { + "description": "Tee operaatiota kuten kavereiden poistaminen tai useiden keskuteluiden poisto" }, - "confirmation_dialogs": { - "title": "Päästä päähän -salaus", - "confirmation_1": "VAROITUS: Tämä korvaa olemassa olevan avaimesi. Menetät pääsyn kaikkiin tämän ystävän salattuihin viesteihin. Haluatko varmasti jatkaa?", - "confirmation_2": "Oletko VARMA, että haluat jatkaa? Tämä on viimeinen tilaisuutesi perääntyä." + "regen_mappings": { + "name": "Tee uudelleen Kartoitus", + "description": "Tee kartoitus uudestaan manuaalisesti" }, - "unencrypted_conversation_send_failure_toast": "Et voi lähettää salattua sisältöä sekä salattuihin että salaamattomiin keskusteluihin!", - "native_hooks_send_failure_toast": "Lähetys epäonnistui! Ota natiivikoukut käyttöön asetuksista.", - "no_participants_to_encrypt_toast": "Sinulla ei ole ystäviä tässä keskustelussa, joiden kanssa voisit salata viestejä!", - "encryption_failed_toast": "Viestin salaaminen epäonnistui! Tarkista logcat lisätietoja varten.", - "accept_public_key_success_toast": "Julkinen avain hyväksytty onnistuneesti!", - "accept_secret_key_success_toast": "Valmis! Voit nyt lähettää ja vastaanottaa salattuja viestejä tämän ystävän kanssa.", - "accept_public_key_failure_toast": "Julkisen avaimen hyväksyminen epäonnistui", - "accept_secret_key_failure_toast": "Salaisen avaimen hyväksyminen epäonnistui", - "accept_secret_button": "Hyväksy salaisuus", - "accept_public_key_button": "Hyväksy julkinen avain", - "outgoing_pk_message": "Avaimenvaihtopyyntö", - "outgoing_secret_message": "Avaimenvaihtovastaus", - "incoming_pk_message": "Sait juuri julkisen avaimen pyynnön. Napsauta alla hyväksyäksesi sen.", - "incoming_secret_message": "Ystäväsi hyväksyi juuri julkisen avaimesi. Napsauta alla hyväksyäksesi salaisuuden." - }, - "auto_open_snaps": { - "title": "Avaa Snapit automaattisesti", - "notification_content": "{count} Snappia avattu" - }, - "friend_mutation_observer": { - "notification_channel_name": "Ystävän muutoksen tarkkailija", - "friend_removed": "{username} on poistanut sinut ystävänä", - "birthday_removed": "{username} on poistanut syntymäpäivänsä ({birthday})", - "birthday_added": "{username} on lisännyt syntymäpäivänsä ({birthday})", - "birthday_changed": "{username} on muuttanut syntymäpäivänsä {oldBirthday} -> {newBirthday}", - "bitmoji_selfie_changed": "{username} on muuttanut Bitmoji-selfiensä", - "bitmoji_avatar_changed": "{username} on muuttanut Bitmoji-avatarinsa", - "bitmoji_background_changed": "{username} on muuttanut Bitmoji-taustansa", - "bitmoji_scene_changed": "{username} on muuttanut Bitmoji-näkymänsä" - }, - "material3_strings": { - "date_range_picker_start_headline": "Alkaen", - "date_range_picker_end_headline": "Asti", - "date_range_picker_title": "Valitse päivämääräväli", - "date_picker_switch_to_calendar_mode": "Kalenteri", - "date_picker_switch_to_input_mode": "Syöte", - "date_range_picker_scroll_to_previous_month": "Edellinen kuukausi", - "date_range_picker_scroll_to_next_month": "Seuraava kuukausi", - "date_picker_today_description": "Tänään", - "date_range_picker_day_in_range": "Valittu", - "date_input_invalid_for_pattern": "Virheellinen päivämäärä", - "date_input_invalid_year_range": "Virheellinen vuosi", - "date_input_invalid_not_allowed": "Virheellinen päivämäärä", - "date_range_input_invalid_range_input": "Virheellinen päivämääräväli" - }, - "send_override_dialog": { - "title": "Lähetä media muodossa {type}", - "duration": "Kesto: {duration}", - "saveable_snap_hint": "Tee Snapista tallennettava keskusteluun", - "unlimited_duration": "Rajoittamaton" - }, - "invalid_input_toast": "Virheellinen syöte! Varmista, että olet syöttänyt kelvollisen arvon." -} \ No newline at end of file + "export_memories": { + "description": "Vie Muistot ZIP tiedostoon", + "name": "Vie Muistot" + }, + "change_language": { + "description": "Vaihda SnapEnchancen kieli", + "name": "Vaihda Kieli" + }, + "export_chat_messages": { + "name": "Vie Chatti Viestit", + "description": "Vie keskustelun viestit JSON/HTML/TXT formaattiseen tiedostoon" + }, + "manage_friend_list": { + "name": "Hallitse Kaveri Listaa", + "description": "Tuo/Vie kaveri lista varmuuskopiota tehdessä" + }, + "clean_snapchat_cache": { + "name": "Puhdista Snapchatin Välimuisti", + "description": "Puhdistaa Snapchatin Välimuistin" + }, + "friend_tracker": { + "name": "Ystävien seuranta", + "description": "Seuraa ystäviäsi Snapchatissa" + }, + "security_features": { + "name": "Turvaominaisuudet", + "description": "Muuta turvaominaisuuksien asetuksia" + }, + "file_imports": { + "description": "Tuo tiedostoja Snapchatissa käytettäväksi", + "name": "Tiedostojen tuonnit" + } + } +} diff --git a/common/src/main/assets/lang/fr_FR.json b/common/src/main/assets/lang/fr_FR.json index b62529c7..6fd1d761 100644 --- a/common/src/main/assets/lang/fr_FR.json +++ b/common/src/main/assets/lang/fr_FR.json @@ -1,136 +1,46 @@ { "setup": { "dialogs": { - "select_language": "Sélectionner la langue", - "save_folder": "PurrfectSnap nécessite des autorisations de stockage pour télécharger et enregistrer des médias depuis Snapchat.\nVeuillez choisir l'emplacement où les médias doivent être téléchargés.", - "select_save_folder_button": "Sélectionner le dossier" + "select_language": "Choisir la langue", + "select_save_folder_button": "Sélectionner un dossier", + "save_folder": "SnapEnhance requiert des autorisations de stockage pour télécharger et enregistrer des médias depuis Snapchat.\nVeuillez choisir l'emplacement où les médias doivent être téléchargés." }, "mappings": { - "dialog": "Génération des mappages, cela peut prendre un certain temps...", - "generate_failure_no_snapchat": "PurrfectSnap n'a pas pu détecter Snapchat, veuillez essayer de réinstaller Snapchat.", - "generate_failure": "Une erreur s'est produite lors de la génération des mappages, veuillez réessayer." + "dialog": "Génération des mappings, cela peut prendre un certain temps...", + "generate_failure_no_snapchat": "SnapEnhance n'a pas pu détecter Snapchat, essayez de réinstaller Snapchat.", + "generate_failure": "Une erreur s'est produite lors de la génération des mappings, veuillez réessayer." }, "permissions": { - "dialog": "Pour continuer, vous devez satisfaire aux exigences suivantes :", + "dialog": "Pour continuer, vous devez remplir les conditions suivantes :", "notification_access": "Accès aux notifications", "battery_optimization": "Optimisation de la batterie", - "display_over_other_apps": "Affichage par-dessus d'autres applications", - "request_button": "Demander" + "display_over_other_apps": "Superposer aux autres applis", + "request_button": "Autoriser" } }, - "scopes": { - "friend": "Ami", - "group": "Groupe" - }, "manager": { "routes": { - "tasks": "Tâches", "features": "Fonctionnalités", - "manage_rule_feature": "Gérer la fonctionnalité de règle", "home": "Accueil", "home_settings": "Paramètres", "home_logs": "Journaux", - "logger_history": "Historique du journal", - "logged_stories": "Histoires enregistrées", - "friend_tracker": "Suivi d'amis", - "edit_rule": "Modifier la règle", - "file_imports": "Importations de fichiers", - "manage_repos": "Gérer les dépôts", - "social": "Sociale", - "manage_scope": "Gérer la portée", - "messaging_preview": "Aperçu", + "social": "Social", "scripts": "Scripts", - "better_location": "Meilleur emplacement" + "tasks": "Tâches", + "logger_history": "Historique du journal", + "logged_stories": "Stories enregistrées", + "manage_scope": "Gérer le champ d'application", + "messaging_preview": "Aperçu", + "edit_rule": "Modifier la règle", + "friend_tracker": "Traqueur d'amis", + "file_imports": "Importations de fichiers", + "better_location": "Localisation Améliorée", + "theming": "Thèmes", + "edit_theme": "Modifier le thème", + "manage_repos": "Gérer les dépots", + "manage_rule_feature": "Gérer la règle de la fonctionnalité" }, "sections": { - "home": { - "version_title": "v{versionName} · forké par Eternal", - "update_title": "Mise à jour de PurrfectSnap", - "update_content": "La version {version} est disponible !", - "update_button": "Télécharger", - "debug_build_summary_title": "Vous exécutez une version de débogage de PurrfectSnap", - "debug_build_summary_content": "Version {versionName} ({versionCode})", - "debug_build_summary_date": "Date de construction : {date} (il y a {days} jours)", - "quick_actions_title": "Actions rapides", - "download_icon_description": "Télécharger", - "completed_icon_description": "Terminé", - "failed_icon_description": "Échec", - "manage_quick_actions_description": "Gérer les actions rapides", - "quick_actions_icon_description": "Actions rapides", - "add_quick_action_description": "Ajouter une action rapide" - }, - "home_logs": { - "no_logs_hint": "Aucun journal disponible", - "clear_logs_button": "Effacer les journaux", - "export_logs_button": "Exporter les journaux", - "saving_logs_toast": "Enregistrement des journaux, cela peut prendre un certain temps...", - "saved_logs_success_toast": "Journaux enregistrés avec succès", - "saved_logs_failure_toast": "Échec de l'enregistrement des journaux" - }, - "home_settings": { - "actions_title": "Actes", - "message_logger_title": "Journal des messages", - "debug_title": "Débogage", - "success_toast": "Terminé !", - "message_logger_summary": "{messageCount} messages\n{storyCount} histoires", - "export_button": "Exporter", - "clear_button": "Effacer", - "view_logger_history_button": "Afficher l'historique du journal", - "updates_title": "Mises à jour", - "auto_update_check": "Vérifier automatiquement les mises à jour", - "update_check_frequency": "Fréquence de vérification des mises à jour", - "update_check_frequency_daily": "Quotidiennement", - "update_check_frequency_weekly": "Hebdomadairement", - "update_check_frequency_monthly": "Mensuellement", - "theme_icon_description": "Thème", - "app_theme_title": "Thème de l'application", - "theme_mode_system": "Système", - "theme_mode_light": "Clair", - "theme_mode_dark": "Sombre", - "ui_settings_title": "Paramètres de l'interface utilisateur", - "haptic_feedback_label": "Retour haptique", - "test_mode_label": "Mode test (POUR LE DÉBOGAGE UNIQUEMENT)", - "disable_feature_loading_label": "Désactiver le chargement des fonctionnalités", - "disable_auto_mapper_label": "Désactiver le mappeur automatique", - "disable_bypass_indicator_label": "Désactiver l'indicateur d'état de contournement", - "update_notification_channel_name": "Mises à jour de PurrfectSnap", - "update_notification_channel_description": "Notifications pour les mises à jour de PurrfectSnap", - "update_notification_title": "Mise à jour de PurrfectSnap disponible", - "update_notification_text": "La version %s est maintenant disponible.", - "export_database_failed_toast": "Échec de l'exportation de la base de données ! {message}", - "clear_messages_failed_toast": "Échec de l'effacement des messages ! {message}", - "clear_file_failed_toast": "Échec de l'effacement du fichier ! {message}", - "debug_file_config": "Configuration", - "debug_file_mappings": "Mappages", - "debug_file_message_logger": "Journal des messages", - "debug_file_pinned_best_friend": "Meilleur ami épinglé", - "debug_file_native_sig_cache": "Cache de signature natif" - }, - "tasks": { - "no_tasks": "Aucune tâche", - "merge_button": "Fusionner", - "failed_to_open_file": "Échec de l'ouverture du fichier", - "merge_files_toast": "Fusion de {count} fichiers", - "remove_selected_tasks_title": "Êtes-vous sûr de vouloir supprimer les tâches sélectionnées ?", - "remove_all_tasks_title": "Êtes-vous sûr de vouloir supprimer toutes les tâches ?", - "delete_files_option": "Supprimer également les fichiers", - "remove_selected_tasks_confirm": "Supprimer {count} tâches ?", - "remove_all_tasks_confirm": "Supprimer toutes les tâches ?", - "clear_tasks_description": "Effacer les tâches", - "file_not_found_icon_description": "Fichier non trouvé", - "image_icon_description": "Image", - "video_icon_description": "Vidéo", - "audio_icon_description": "Audio", - "file_icon_description": "Fichier", - "download_icon_description": "Télécharger", - "chat_action_icon_description": "Action de discussion", - "cancel_icon_description": "Annuler", - "success_icon_description": "Succès", - "failure_icon_description": "Échec", - "cancelled_icon_description": "Annulé", - "task_status_failure": "Échec", - "task_status_cancelled": "Annulé" - }, "features": { "disabled": "Désactivé", "export_option": "Exporter", @@ -139,413 +49,178 @@ "config_export_success_toast": "Configuration exportée avec succès", "config_import_success_toast": "Configuration importée avec succès", "config_import_failure_toast": "Échec de l'importation de la configuration {error}", - "config_export_failure_toast": "Échec de l'exportation de la configuration {error}", "saved_config_snackbar": "Configuration enregistrée", + "config_export_failure_toast": "Échec de l'exportation de la configuration {error}", "older_required": "Cette fonctionnalité nécessite Snapchat v{version} ou une version antérieure pour fonctionner correctement", - "newer_required": "Cette fonctionnalité nécessite Snapchat v{version} ou une version ultérieure pour fonctionner correctement", - "search_button": "Rechercher" - }, - "manage_rule_feature": { - "disable_state_option": "Désactivé", - "disable_state_subtext": "Aucun ami/groupe ne sera affecté", - "whitelist_state_option": "Personne sauf...", - "whitelist_state_subtext": "Seuls {count} amis/groupes seront affectés par cette règle", - "whitelist_state_button": "Sélectionner les amis/groupes autorisés", - "blacklist_state_option": "Tout le monde sauf...", - "blacklist_state_subtext": "Tout le monde sauf {count} amis/groupes sera affecté par cette règle", - "blacklist_state_button": "Sélectionner les amis/groupes exclus", - "clear_list_button": "Effacer la liste des amis/groupes", - "dialog_clear_confirmation_text": "Êtes-vous sûr de vouloir effacer la liste ?" + "newer_required": "Cette fonctionnalité nécessite Snapchat v{version} ou une version plus récente pour fonctionner correctement", + "search_button": "Recherche" }, "social": { - "friends_tab": "Amis", + "streaks_expiration_short": "{hours}h", "groups_tab": "Groupes", "empty_hint": "(vide)", - "streaks_expiration_short": "{hours}h" + "friends_tab": "Amis" + }, + "tasks": { + "no_tasks": "Aucune tâche", + "merge_files_toast": "Fusion de {count} fichiers", + "remove_selected_tasks_title": "Êtes-vous sûr de vouloir supprimer les tâches sélectionnées ?", + "remove_all_tasks_title": "Êtes-vous sûr de vouloir supprimer toutes les tâches ?", + "delete_files_option": "Supprimer également les fichiers", + "remove_selected_tasks_confirm": "Supprimer {count} tâches ?", + "remove_all_tasks_confirm": "Supprimer toutes les tâches ?", + "failed_to_open_file": "Échec de l'ouverture du fichier", + "merge_button": "Fusionner" + }, + "home": { + "update_content": "La version {version} est disponible !", + "update_button": "Télécharger", + "update_title": "Mise à jour SnapEnhance", + "version_title": "v{versionName} · par eternal", + "debug_build_summary_title": "Vous utilisez une version de debug de SnapEnhance", + "debug_build_summary_content": "Version {versionName} ({versionCode})", + "debug_build_summary_date": "Date de création: {date} (Il y a {days} jours)", + "quick_actions_title": "Actions rapides" }, "manage_scope": { - "logged_stories_button": "Afficher les histoires enregistrées", + "logged_stories_button": "Afficher les stories enregistrées", "e2ee_title": "Chiffrement de bout en bout", "rules_title": "Règles", - "participants_text": "{count} participants", - "not_found": "Non trouvé", - "streaks_title": "Séries", - "streaks_length_text": "Longueur : {length}", + "participants_text": "{count} participant(s)", + "not_found": "Pas trouvé", + "streaks_title": "Flammes", + "streaks_length_text": "Longueur: {length}", "streaks_expiration_text": "Expire dans {eta}", "streaks_expiration_text_expired": "Expiré", "reminder_button": "Définir un rappel", - "delete_scope_confirm_dialog_title": "Êtes-vous sûr de vouloir supprimer un {scope} ?", - "notes_placeholder": "Cliquez pour ajouter une note", - "invalid_key_size_32_bytes": "Taille de clé non valide (doit être de 32 octets)", - "successfully_imported_key": "Clé importée avec succès", - "failed_to_import_key": "Échec de l'importation de la clé : {message}", - "export_base64_button": "Exporter en Base64", - "import_base64_button": "Importer depuis Base64" + "delete_scope_confirm_dialog_title": "Êtes-vous sûr de vouloir supprimer ce {scope} ?", + "notes_placeholder": "Cliquez pour ajouter une note" + }, + "home_logs": { + "no_logs_hint": "Aucun journal disponible", + "clear_logs_button": "Effacer les journaux", + "export_logs_button": "Exporter les journaux", + "saving_logs_toast": "Sauvegarde des journaux, cela peut prendre un certain temps ...", + "saved_logs_success_toast": "Journaux enregistrés avec succès", + "saved_logs_failure_toast": "Échec de l'enregistrement des journaux" + }, + "home_settings": { + "actions_title": "Actions", + "message_logger_title": "Loggeur de messages", + "debug_title": "Déboguer", + "success_toast": "Succès !", + "message_logger_summary": "{messageCount} message(s)\n{storyCount} stories", + "export_button": "Exporter", + "clear_button": "Vider", + "view_logger_history_button": "Afficher l'historique de l'enregistreur" }, "logged_stories": { "story_failed_to_load": "Échec du chargement", - "no_stories": "Aucune histoire trouvée", - "save_from_cache_button": "Enregistrer depuis le cache", - "downloaded_to_path": "Téléchargé dans {path}", - "download_failed": "Échec du téléchargement : {message}", - "posted_at": "Publié le {date}", - "created_at": "Créé le {date}", - "failed_to_open_file": "Échec de l'ouverture du fichier. Consultez les journaux pour plus d'informations", - "failed_to_get_file": "Échec de la récupération du fichier" + "no_stories": "Aucune story trouvée", + "save_from_cache_button": "Enregistrer depuis le cache" }, "messaging_preview": { - "processed_messages_toast": "{count} messages traités", - "processed_messages_text": "{count} messages traités", - "close_button_description": "Fermer", - "bridge_connection_failed": "Échec de la connexion au pont. Assurez-vous que Snapchat est en cours d'exécution en arrière-plan", - "bridge_init_failed": "Échec de l'initialisation du pont de messagerie. Assurez-vous que Snapchat est en cours d'exécution en arrière-plan", + "bridge_connection_failed": "Échec de la connexion au pont. Assurez-vous que Snapchat s'exécute en arrière-plan", + "bridge_init_failed": "Échec de l'initialisation du pont de messagerie. Assurez-vous que Snapchat s'exécute en arrière-plan", "message_fetch_failed": "Échec de la récupération des messages", - "no_message_hint": "Aucun message", + "no_message_hint": "Pas de message", "save_selection_option": "Enregistrer la sélection", - "save_all_option": "Tout enregistrer", + "save_all_option": "Enregistrer tout", "unsave_selection_option": "Désenregistrer la sélection", "unsave_all_option": "Tout désenregistrer", "mark_selection_as_seen_option": "Marquer le Snap sélectionné comme vu", "mark_all_as_seen_option": "Marquer tous les Snaps comme vus", "delete_selection_option": "Supprimer la sélection", - "delete_all_option": "Tout supprimer" + "delete_all_option": "Supprimer tout" }, "logger_history": { - "download_started_toast": "Téléchargement démarré !", - "download_success_toast": "Téléchargé dans {path}", - "download_failed_toast": "Échec du téléchargement de {message}", - "edited_at_text": "{message} (modifié le {date})", - "download_button": "Télécharger", - "select_conversation_placeholder": "Sélectionner une conversation", - "close_button_description": "Fermer", - "search_button_description": "Rechercher", - "list_friend_format": "Ami {name}", + "list_friend_format": "Ami(e) {name}", "list_group_format": "Groupe {name}", "no_more_messages": "Plus de messages", "reverse_order_checkbox": "Ordre inverse", - "chat_attachment": "Pièce jointe {index}", - "empty_message": "Message de discussion vide", + "chat_attachment": "Pièce jointe n°{index}", + "empty_message": "Message vide", "message_parse_failed": "Échec de l'analyse du message", "unknown_sender": "Expéditeur inconnu", - "download_attachment_failed_toast": "Échec du téléchargement de la pièce jointe", - "log_header_format": "{username} ({type}) - {date}" + "download_attachment_failed_toast": "Échec du téléchargement de la pièce jointe" }, "file_imports": { + "no_files_hint": "Ici, vous pouvez importer des fichiers à utiliser dans Snapchat. Appuyez sur le bouton ci-dessous pour importer un fichier.", "import_file_button": "Importer un fichier", - "file_not_found": "Fichier non trouvé", - "file_import_failed": "Échec de l'importation du fichier : {error}", + "file_not_found": "Fichier introuvable", + "file_import_failed": "Échec de l'importation du fichier : {error}", "file_imported": "Fichier importé avec succès", - "file_delete_failed": "Échec de la suppression du fichier", - "no_files_hint": "Ici, vous pouvez importer des fichiers à utiliser dans Snapchat. Appuyez sur le bouton ci-dessous pour importer un fichier." + "file_delete_failed": "Échec de la suppression du fichier" }, "better_location": { "spoofed_coordinates_title": "Lat {latitude}, Lng {longitude}", "save_coordinates_dialog_title": "Enregistrer les coordonnées", "saved_name_dialog_hint": "Nom enregistré", + "delete_dialog_title": "Supprimer une coordonnée enregistrée", + "spoof_location_toggle": "Usurpation de la localisation", + "saved_coordinates_title": "Coordonnées enregistrées", + "teleport_to_friend_title": "Se téléporter à un ami", + "delete_dialog_message": "Êtes-vous sûr de vouloir supprimer cette coordonnée enregistrée ?", + "search_bar": "Rechercher", + "no_friends_found": "Aucun ami trouvé", + "save_dialog_button": "Sauvegarder", + "choose_location_button": "Choisir un emplacement", + "teleport_to_friend_button": "Se téléporter à un ami", + "no_saved_coordinates_hint": "Aucune coordonnée enregistrée", + "no_friends_map": "Pas d'amis sur la carte", "latitude_dialog_hint": "Latitude", "longitude_dialog_hint": "Longitude", - "save_dialog_button": "Enregistrer", - "choose_location_button": "Choisir l'emplacement", - "teleport_to_friend_button": "Se téléporter vers un ami", - "spoof_location_toggle": "Falsifier l'emplacement", - "suspend_location_updates": "Suspendre les mises à jour de l'emplacement", - "saved_coordinates_title": "Coordonnées enregistrées", - "no_saved_coordinates_hint": "Aucune coordonnée enregistrée", - "delete_dialog_title": "Supprimer la coordonnée enregistrée", - "delete_dialog_message": "Êtes-vous sûr de vouloir supprimer cette coordonnée enregistrée ?", - "teleport_to_friend_title": "Se téléporter vers un ami", - "search_bar": "Rechercher", - "no_friends_map": "Aucun ami sur la carte", - "no_friends_found": "Aucun ami trouvé", - "edit_location_button_description": "Modifier l'emplacement", - "add_icon_description": "Ajouter", - "edit_icon_description": "Modifier", - "delete_icon_description": "Supprimer" + "suspend_location_updates": "Suspendre les mises à jour de localisation" + }, + "theming": { + "no_themes_hint": "Aucun thème trouvé" + }, + "manage_rule_feature": { + "disable_state_option": "Désactivé", + "disable_state_subtext": "Aucun ami/groupe ne sera concerné", + "whitelist_state_option": "Personne sauf ...", + "blacklist_state_option": "Tout le monde sauf ...", + "blacklist_state_button": "Sélectionner les amis/groupes exclus", + "clear_list_button": "Effacer la liste des amis/groupes", + "dialog_clear_confirmation_text": "Êtes-vous sûr de vouloir effacer la liste ?", + "whitelist_state_button": "Sélectionner les amis/groupes autorisés", + "whitelist_state_subtext": "Seuls {count} amis/groupes seront affectés par cette règle", + "blacklist_state_subtext": "Tout le monde, sauf {count} amis/groupes, seront concernés par cette règle" } }, "dialogs": { "add_friend": { - "title": "Ajouter un ami ou un groupe", + "title": "Ajouter des amis ou des groupes", "search_hint": "Rechercher", "fetch_error": "Échec de la récupération des données", "category_groups": "Groupes", "category_friends": "Amis", - "participants_text": "{count} participants", - "search_icon_description": "Rechercher" + "participants_text": "{count} participants" }, "scripting_warning": { - "title": "Avertissement", - "content": "PurrfectSnap inclut un outil de script, permettant l'exécution de code défini par l'utilisateur sur votre appareil. Soyez extrêmement prudent et n'installez que des modules provenant de sources connues et fiables. Les modules non autorisés ou non vérifiés peuvent présenter des risques pour la sécurité de votre système." - }, - "reset_config": { - "title": "Réinitialiser la configuration", - "content": "Êtes-vous sûr de vouloir réinitialiser la configuration ?", - "success_toast": "Configuration réinitialisée avec succès" - }, - "export_config": { - "title": "Exporter des données sensibles ?", - "content": "Voulez-vous exporter la configuration avec des données sensibles ? (Telles que les coordonnées de localisation, etc.)" + "content": "SnapEnhance inclut un outil de développement de scripts, permettant l'exécution d'un code défini par l'utilisateur sur votre appareil. Soyez extrêmement prudent et n'installez que des modules provenant de sources connues et fiables. Les modules non autorisés ou non vérifiés peuvent présenter des risques pour la sécurité de votre système.", + "title": "Attention" }, "messaging_action": { "title": "Choisissez les types de contenu à traiter", "select_all_button": "Tout sélectionner" }, + "reset_config": { + "title": "Réinitialiser la configuration", + "content": "Êtes-vous sûr de vouloir réinitialiser la configuration ?", + "success_toast": "La configuration a été réinitialisée avec succès" + }, "file_imports": { "no_files_settings_hint": "Aucun fichier trouvé. Assurez-vous d'avoir importé les fichiers requis dans la section Importations de fichiers", - "settings_select_file_hint": "Sélectionner un fichier importé" + "settings_select_file_hint": "Sélectionnez un fichier importé" }, - "quick_actions_dialog": { - "title": "Modifier les actions rapides", - "subtitle": "Sélectionnez et dimensionnez vos actions rapides." + "export_config": { + "title": "Exporter des données sensibles ?", + "content": "Voulez-vous exporter la configuration avec des données sensibles ? (Comme les coordonnées de localisation, etc.)" } - }, - "friend_tracker": { - "rules_tab": "Règles", - "logs_tab": "Journaux", - "export_dialog_title": "Exporter", - "bulk_export_button": "Exportation en masse", - "individual_export_button": "Exportation individuelle", - "invalid_import_type_dialog_title": "Type d'importation non valide", - "invalid_import_type_dialog_text": "Le fichier sélectionné n'est pas compatible avec ce type d'importation. Veuillez sélectionner le type d'importation correct.", - "import_dialog_title": "Importer", - "bulk_import_button": "Importation en masse", - "individual_import_button": "Importation individuelle", - "import_button_description": "Importer", - "export_button_description": "Exporter", - "export_button": "Exporter", - "delete_button_description": "Supprimer", - "delete_button": "Supprimer", - "catalog_button_description": "Catalogue", - "catalog_button": "Catalogue", - "add_rule_button_description": "Ajouter une règle", - "add_rule_button": "Ajouter une règle", - "no_rules_found": "Aucune règle trouvée", - "empty_rule_name": "(vide)", - "events_suffix": "événements", - "scopes_suffix": "portées", - "select_rule_to_export_title": "Sélectionner la règle à exporter", - "deleted_logs_toast": "{count} journaux supprimés", - "delete_logs_dialog_title": "Supprimer les journaux ?", - "deleting_logs_dialog_text": "Suppression de {count} journaux...", - "delete_logs_dialog_confirm_text": "Cela supprimera les journaux en fonction du filtre actuel et de la requête de recherche. Cette action ne peut pas être annulée.", - "exported_logs_toast": "Journaux exportés !", - "export_logs_failed_toast": "Échec de l'exportation des journaux. Consultez logcat pour plus de détails.", - "export_logs_dialog_title": "Exporter les journaux ?", - "exporting_logs_dialog_text": "Exportation des journaux...", - "export_logs_dialog_confirm_text": "Cela exportera les journaux en fonction du filtre actuel et de la requête de recherche.", - "export_as_button": "Exporter en tant que {type}", - "filters_title": "Filtres", - "search_by_label": "Rechercher par", - "newest_first_label": "Les plus récents d'abord", - "since_label": "Depuis", - "until_label": "Jusqu'à", - "pick_a_date_button": "Choisir une date", - "search_placeholder": "Rechercher", - "filter_button_description": "Filtre", - "clear_button_description": "Effacer", - "no_logs_found": "Aucun journal trouvé", - "log_event_format": "{event} dans {conversation}", - "condition_only_inside_conversation": "Seulement lorsque je suis dans la conversation", - "condition_only_outside_conversation": "Seulement lorsque je suis en dehors de la conversation", - "condition_only_when_app_active": "Seulement lorsque Snapchat est actif", - "condition_only_when_app_inactive": "Seulement lorsque Snapchat est inactif", - "condition_no_push_notification_when_app_active": "Pas de notification push lorsque Snapchat est actif", - "add_event_dialog_title": "Ajouter un événement", - "event_type_label": "Type d'événement", - "triggers_title": "Déclencheurs", - "conditions_title": "Conditions", - "add_button": "Ajouter", - "default_rule_name": "Règle personnalisée", - "discard_changes_dialog_title": "Annuler les modifications ?", - "discard_changes_dialog_text": "Vous avez des modifications non enregistrées. Êtes-vous sûr de vouloir les annuler ?", - "discard_button": "Annuler", - "cannot_save_rule_dialog_title": "Impossible d'enregistrer la règle", - "cannot_save_rule_dialog_text": "Une règle doit avoir au moins un événement pour être enregistrée.", - "duplicate_rule_name_dialog_title": "Nom de règle en double", - "duplicate_rule_name_dialog_text": "Une règle avec ce nom existe déjà. Veuillez choisir un nom différent.", - "delete_rule_dialog_title": "Supprimer la règle", - "delete_rule_dialog_text": "Êtes-vous sûr de vouloir supprimer cette règle ?", - "new_rule_title": "Nouvelle règle", - "edit_rule_title": "Modifier la règle", - "back_button_description": "Retour", - "save_button_description": "Enregistrer", - "general_section_title": "Général", - "rule_name_label": "Nom de la règle", - "author_name_label": "Nom de l'auteur", - "scope_section_title": "Portée", - "scope_all": "Tous", - "scope_whitelist": "Liste blanche", - "scope_blacklist": "Liste noire", - "select_friends_groups_button": "Sélectionner des amis/groupes ({count})", - "events_section_title": "Événements", - "add_event_button": "Ajouter un événement", - "no_events_text": "Aucun événement" - }, - "friend_tracker_catalog": { - "download_failed": "Échec du téléchargement : {code}", - "error": "Erreur : {message}", - "no_repos_added": "Aucun dépôt ajouté.", - "no_rules_available": "Aucune règle disponible dans aucun dépôt.", - "by_author": "par {author}", - "imported_button": "Importé", - "import_button": "Importer", - "title": "Catalogue du suivi d'amis", - "manage_repos_description": "Gérer les dépôts" - }, - "friend_tracker_export": { - "title": "Exporter les règles", - "back_button_description": "Retour", - "exported_toast": "Règles du suivi d'amis exportées !", - "export_failed_toast": "Échec de l'exportation des règles : {message}", - "save_button": "Enregistrer", - "expand_button_description": "Développer" - }, - "friend_tracker_import": { - "title": "Importer les règles", - "back_button_description": "Retour", - "imported_toast": "Règles du suivi d'amis importées !", - "import_failed_toast": "Échec de l'importation des règles : {message}", - "confirm_button": "Confirmer", - "expand_button_description": "Développer" - }, - "friend_tracker_repos": { - "invalid_repo_title": "Dépôt non valide", - "add_repo_button": "Ajouter un dépôt", - "add_repo_dialog_title": "Ajouter l'URL du dépôt", - "repo_url_label": "URL du dépôt", - "repo_added_toast": "Dépôt ajouté avec succès !", - "invalid_repo_error": "Cela ne semble pas être un dépôt de suivi d'amis valide.", - "add_repo_failed_toast": "Échec de l'ajout du dépôt : {message}", - "add_button": "Ajouter", - "no_repos_added": "Aucun dépôt ajouté", - "remove_button": "Supprimer", - "remove_repo_dialog_title": "Supprimer le dépôt", - "remove_repo_dialog_text": "Êtes-vous sûr de vouloir supprimer ce dépôt ?" - }, - "navigation": { - "tracker_tab_label": "Suivi", - "customize_bottom_bar_title": "Personnaliser la barre inférieure", - "customize_bottom_bar_subtitle": "Réorganiser, ajouter ou supprimer des onglets. Cinq au maximum.", - "shown_tabs_title": "Onglets affichés", - "no_tabs_selected_text": "Aucun onglet sélectionné", - "available_tabs_title": "Onglets disponibles", - "reset_button": "Réinitialiser", - "done_button": "Terminé" - }, - "scripting": { - "script_already_installed": "Script déjà installé !", - "downloading_script": "Téléchargement du script...", - "script_downloaded": "Script {name} téléchargé !", - "download_script_failed": "Échec du téléchargement du script. Consultez les journaux pour plus de détails", - "import_script_from_url_title": "Importer un script depuis une URL", - "import_script_warning": "Avertissement : Les scripts importés peuvent être dangereux pour votre appareil. N'importez que des scripts provenant de sources fiables.", - "enter_url_label": "Entrez l'URL ici :", - "script_imported": "Script {name} importé !", - "import_failed": "Échec de l'importation du script. {message}. Consultez les journaux pour plus de détails", - "import_button": "Importer", - "update_module_button": "Mettre à jour le module", - "updating_script": "Mise à jour du script {name}...", - "module_not_found": "Module non trouvé", - "updated_script": "Mise à jour de {name} vers la version {version}", - "update_module_failed": "Échec de la mise à jour du module. Consultez les journaux pour plus de détails", - "edit_module_button": "Modifier le module", - "open_module_failed": "Échec de l'ouverture du fichier du module. Consultez les journaux pour plus de détails", - "clear_module_data_button": "Effacer les données du module", - "module_data_cleared": "Données du module effacées !", - "clear_module_data_failed": "Échec de l'effacement des données du module. Consultez les journaux pour plus de détails", - "delete_module_button": "Supprimer le module", - "deleted_script": "Script {name} supprimé !", - "delete_module_failed": "Échec de la suppression du module. Consultez les journaux pour plus de détails", - "actions_title": "Actes", - "no_description": "Aucune description", - "update_available": "Mise à jour disponible : {version}", - "actions_button": "Actes", - "loaded_script": "Script {name} chargé", - "unloaded_script": "Script {name} déchargé", - "enable_script_failed": "Échec de l'activation du script. Consultez les journaux pour plus de détails", - "disable_script_failed": "Échec de la désactivation du script. Consultez les journaux pour plus de détails", - "select_scripts_folder_toast": "Veuillez sélectionner votre dossier de scripts !", - "manage_repos_button": "Gérer les dépôts", - "import_from_url_button": "Importer depuis une URL", - "open_scripts_folder_button": "Ouvrir le dossier des scripts", - "no_settings_for_module": "Ce module n'a pas de paramètres", - "installed_scripts_tab": "Scripts installés", - "catalog_tab": "Catalogue", - "no_scripts_folder_selected_title": "Aucun dossier de scripts sélectionné", - "select_folder_button": "Sélectionner un dossier", - "no_scripts_found_title": "Aucun script trouvé.", - "use_catalog_to_add_scripts": "Utilisez l'onglet catalogue pour ajouter des scripts !", - "ok_button_timeout": "D'accord ({timeout})", - "documentation_button": "Documentation", - "catalog": { - "script_already_installed": "Script déjà installé !", - "download_failed": "Échec du téléchargement : {code}", - "script_downloaded": "Script téléchargé !", - "could_not_create_file": "Impossible de créer le fichier.", - "no_scripts_folder_selected": "Aucun dossier de scripts sélectionné.", - "error": "Erreur : {message}", - "no_repos_added": "Aucun dépôt ajouté.", - "repo_list_info": "Vous trouverez ici une liste de dépôts : ", - "link_text": "Lien", - "no_scripts_available": "Aucun script disponible dans aucun dépôt.", - "by_author": "par {author}", - "version": "Version : {version}", - "installed_button": "Installé", - "download_button": "Télécharger" - }, - "repos": { - "invalid_repo_title": "Dépôt non valide", - "add_repo_button": "Ajouter un dépôt", - "add_repo_dialog_title": "Ajouter l'URL du dépôt", - "repo_url_label": "URL du dépôt", - "repo_added_toast": "Dépôt ajouté avec succès !", - "invalid_repo_error": "Cela ne semble pas être un dépôt de scripts valide.", - "add_repo_failed_toast": "Échec de l'ajout du dépôt : {message}", - "add_button": "Ajouter", - "no_repos_added": "Aucun dépôt ajouté", - "remove_button": "Supprimer", - "remove_repo_dialog_title": "Supprimer le dépôt", - "remove_repo_dialog_text": "Êtes-vous sûr de vouloir supprimer ce dépôt ?" - } - }, - "features": { - "config_import": { - "title": "Confirmer l'importation", - "back_button_description": "Retour", - "config_imported_toast": "Configuration importée !", - "confirm_button": "Confirmer", - "expand_button_description": "Développer", - "enable_feature": "Activer la fonctionnalité", - "enabled": "Activé", - "disabled": "Désactivé" - }, - "config_export": { - "title": "Résumé de l'exportation", - "back_button_description": "Retour", - "save_button": "Enregistrer", - "expand_button_description": "Développer", - "enable_feature": "Activer la fonctionnalité", - "enabled": "Activé", - "disabled": "Désactivé" - } - }, - "manage_repos": { - "title": "Gérer les dépôts {type}", - "add_repo_button": "Ajouter un dépôt", - "add_repo_dialog_title": "Ajouter l'URL du dépôt", - "repo_url_label": "URL du dépôt", - "repo_added_successfully": "Dépôt ajouté avec succès !", - "add_repo_failed": "Échec de l'ajout du dépôt : {message}", - "add_button": "Ajouter", - "no_repos_added": "Aucun dépôt ajouté", - "remove_button": "Supprimer" } }, "rules": { - "toasts": { - "enabled": "{ruleName} activé", - "disabled": "{ruleName} désactivé" - }, "modes": { "blacklist": "Mode liste noire", "whitelist": "Mode liste blanche" @@ -553,130 +228,92 @@ "properties": { "auto_download": { "name": "Téléchargement automatique", - "description": "Télécharge automatiquement les Snaps lors de leur visualisation", + "description": "Télécharger automatiquement les Snaps lors de leur visionnage", "options": { "blacklist": "Exclure du téléchargement automatique", "whitelist": "Téléchargement automatique" } }, "stealth": { - "name": "Mode furtif", - "description": "Empêche quiconque de savoir que vous avez ouvert leurs Snaps/Discussions et conversations", + "name": "Mode incognito", + "description": "Empêche quiconque de savoir que vous avez ouvert ses Snaps/Chats", "options": { - "blacklist": "Exclure du mode furtif", - "whitelist": "Mode furtif" + "blacklist": "Exclure du mode incognito", + "whitelist": "Mode incognito" } }, "auto_save": { - "name": "Enregistrement automatique", - "description": "Enregistre les messages de discussion lors de leur visualisation", + "name": "Sauvegarde automatique", + "description": "Enregistre les messages lors de leur visionnage", "options": { - "blacklist": "Exclure de l'enregistrement automatique", - "whitelist": "Enregistrement automatique" - } - }, - "unsaveable_messages": { - "name": "Messages non enregistrables", - "description": "Empêche les messages d'être enregistrés dans la discussion par d'autres personnes", - "options": { - "blacklist": "Exclure des messages non enregistrables", - "whitelist": "Messages non enregistrables" - } - }, - "auto_open_snaps": { - "name": "Ouvrir automatiquement les Snaps", - "description": "Ouvre automatiquement les Snaps lors de leur réception", - "options": { - "blacklist": "Exclure de l'ouverture automatique des Snaps", - "whitelist": "Ouvrir automatiquement les Snaps" + "blacklist": "Exclure de la sauvegarde automatique", + "whitelist": "Sauvegarde automatique" } }, "hide_friend_feed": { - "name": "Masquer du fil d'amis" + "name": "Masquer du flux d'amis" }, "e2e_encryption": { - "name": "Utiliser le chiffrement E2E" + "name": "Utiliser le chiffrement de bout en bout" }, "pin_conversation": { "name": "Épingler la conversation" }, + "unsaveable_messages": { + "name": "Messages non enregistrables", + "options": { + "blacklist": "Exclure des Messages non enregistrables", + "whitelist": "Messages non enregistrables" + }, + "description": "Empêche les messages d'être enregistrés dans le chat par d'autres personnes" + }, + "auto_open_snaps": { + "name": "Auto-ouverture des Snaps", + "description": "Ouvre automatiquement les Snaps dès leur réception", + "options": { + "blacklist": "Exclure de l'ouverture automatique des Snaps", + "whitelist": "Ouverture automatique des Snaps" + } + }, "exclude_message_logger": { "name": "Exclure du journal des messages" } - } - }, - "actions": { - "clean_snapchat_cache": { - "name": "Nettoyer le cache de Snapchat", - "description": "Nettoie le cache de Snapchat" }, - "manage_friend_list": { - "name": "Gérer la liste d'amis", - "description": "Importer/exporter votre liste d'amis lors de la sauvegarde" - }, - "export_chat_messages": { - "name": "Exporter les messages de discussion", - "description": "Exporte les messages de conversation dans un fichier JSON/HTML/TXT" - }, - "export_memories": { - "name": "Exporter les souvenirs", - "description": "Exporte les souvenirs dans un fichier ZIP" - }, - "bulk_messaging_action": { - "name": "Action de messagerie en masse", - "description": "Effectue des opérations telles que la suppression d'amis ou la suppression massive de conversations" - }, - "regen_mappings": { - "name": "Régénérer les mappages", - "description": "Régénérer manuellement les mappages" - }, - "change_language": { - "name": "Changer de langue", - "description": "Changer la langue de PurrfectSnap" - }, - "file_imports": { - "name": "Importations de fichiers", - "description": "Importer des fichiers à utiliser dans Snapchat" - }, - "friend_tracker": { - "name": "Suivi d'amis", - "description": "Suivre vos amis sur Snapchat" - }, - "logger_history": { - "name": "Historique du journal", - "description": "Afficher l'historique des messages enregistrés" + "toasts": { + "enabled": "{ruleName} activé", + "disabled": "{ruleName} désactivé" } }, "features": { "notices": { "unstable": "⚠️ Instable", - "ban_risk": "⚠️ Cette fonctionnalité peut entraîner des bannissements", - "internal_behavior": "⚠️ Cela peut perturber le comportement interne de Snapchat" + "ban_risk": "⚠️ Cette fonctionnalité pourrait causer des bannissements", + "internal_behavior": "⚠️ Cela peut casser le comportement interne de Snapchat" }, "properties": { "downloader": { "name": "Téléchargeur", - "description": "Télécharger des médias Snapchat", + "description": "Télécharger médias de Snapchat", "properties": { "save_folder": { "name": "Dossier d'enregistrement", "description": "Sélectionnez le répertoire dans lequel tous les médias doivent être téléchargés" }, "auto_download_sources": { - "name": "Sources de téléchargement automatique", - "description": "Sélectionnez les sources à partir desquelles télécharger automatiquement" + "name": "Sources de téléchargements automatiques", + "description": "Sélectionner les sources pour lesquelles les téléchargements seront automatiques" }, "prevent_self_auto_download": { - "name": "Empêcher le téléchargement automatique de soi-même", - "description": "Empêche le téléchargement automatique de vos propres Snaps" + "name": "Empêcher l'automatisation du téléchargement", + "description": "Empêcher vos propres Snaps d'êtres automatiquement téléchargement" }, "path_format": { - "name": "Format du chemin", - "description": "Spécifiez le format du chemin du fichier" + "name": "Format du chemin d'accès", + "description": "Spécifier le format de l'emplacement de fichier" }, "allow_duplicate": { "name": "Autoriser les doublons", - "description": "Permet de télécharger plusieurs fois les mêmes médias" + "description": "Permet au même média d'être téléchargé plusieurs fois" }, "merge_overlays": { "name": "Fusionner les superpositions", @@ -688,290 +325,236 @@ }, "force_voice_note_format": { "name": "Forcer le format de la note vocale", - "description": "Force l'enregistrement des notes vocales dans un format spécifié" - }, - "auto_download_voice_notes": { - "name": "Télécharger automatiquement les notes vocales", - "description": "Télécharge automatiquement les notes vocales lors de leur lecture" + "description": "Forcer l'enregistrement des notes vocales dans un format spécifié" }, "download_profile_pictures": { "name": "Télécharger les photos de profil", - "description": "Vous permet de télécharger les photos de profil depuis la page de profil" - }, - "opera_download_button": { - "name": "Bouton de téléchargement Opera", - "description": "Ajoute un bouton de téléchargement dans le coin supérieur droit lors de la visualisation d'un Snap.\nUn appui long sur les boutons forcera le téléchargement" - }, - "download_context_menu": { - "name": "Menu contextuel de téléchargement", - "description": "Vous permet de télécharger/prévisualiser des messages d'une conversation ou d'une histoire à l'aide du menu contextuel.\nUn appui long sur les boutons forcera le téléchargement" + "description": "Vous permet de télécharger les photos du profil depuis la page de profil" }, "ffmpeg_options": { "name": "Options FFmpeg", - "description": "Spécifiez des options FFmpeg supplémentaires", + "description": "Spécifier des options supplémentaires pour FFmpeg", "properties": { "threads": { - "name": "Sujets", - "description": "Le nombre de threads à utiliser" + "name": "Fil de discussions", + "description": "Le nombre de fils de discussions à utiliser" }, "preset": { - "name": "Préréglage", - "description": "Définissez la vitesse de la conversion" + "name": "Préréglages", + "description": "Définir la vitesse de conversion" }, "constant_rate_factor": { - "name": "Facteur de débit constant", - "description": "Définissez le facteur de débit constant pour l'encodeur vidéo\nDe 0 à 51 pour libx264" + "name": "Facteur de taux constant", + "description": "Définir le facteur de débit constant pour l'encodeur vidéo\nde 0 à 51 pour libx264" }, "video_bitrate": { "name": "Débit vidéo", - "description": "Définissez le débit vidéo (kbps)" + "description": "Définir le débit vidéo (kbps)" }, "audio_bitrate": { "name": "Débit audio", - "description": "Définissez le débit audio (kbps)" + "description": "Définir le débit audio (kbps)" }, "custom_video_codec": { "name": "Codec vidéo personnalisé", - "description": "Définissez un codec vidéo personnalisé (par exemple, libx264)" + "description": "Définir un Codec Vidéo personnalisé tel que (libx264)" }, "custom_audio_codec": { "name": "Codec audio personnalisé", - "description": "Définissez un codec audio personnalisé (par exemple, AAC)" + "description": "Définir un Codec Audio personnalisé tel que (AAC)" } } }, "logging": { "name": "Journalisation", - "description": "Affiche des toasts lors du téléchargement de médias" + "description": "Afficher une bulle de notification lorsque un média est en cours de téléchargement" }, "custom_path_format": { - "name": "Format de chemin personnalisé", - "description": "Spécifiez un format de chemin personnalisé pour les médias téléchargés\n\nVariables disponibles :\n - %username%\n - %source%\n - %hash%\n - %date_time%" + "description": "Spécifier un format de chemin personnalisé pour les médias téléchargés\n\nVariables disponibles :\n - %username%\n - %source%\n - %hash%\n - %date_time%", + "name": "Format de chemin personnalisé" + }, + "opera_download_button": { + "description": "Ajoute un bouton de téléchargement dans le coin en haut à droite lors de la visualisation d'un Snap.\nUne longue pression sur ce bouton forcera le téléchargement", + "name": "Bouton de téléchargement Opera" + }, + "download_context_menu": { + "name": "Menu de téléchargement contextuel", + "description": "Vous permet de télécharger/voir les messages a partir d'une conversation ou d'une story a partir du menu contextuel.\nUne pression longue sur ce bouton forcera le téléchargement" + }, + "auto_download_voice_notes": { + "name": "Téléchargement automatique des messages vocaux", + "description": "Télécharge automatiquement les messages vocaux lors de leur lecture" } } }, "user_interface": { "name": "Interface utilisateur", - "description": "Modifier l'apparence de Snapchat", + "description": "Changer l'apparence de Snapchat", "properties": { "enable_app_appearance": { - "name": "Activer les paramètres d'apparence de l'application", - "description": "Active le paramètre d'apparence de l'application masqué\nPeut ne pas être requis sur les versions plus récentes de Snapchat" + "name": "Activer les paramètres d'apparence de l'appli", + "description": "Active le paramètre d’apparence caché de l’application\nPeut ne pas être nécessaire sur les nouvelles versions de Snapchat" }, "friend_feed_message_preview": { - "name": "Aperçu des messages du fil d'amis", - "description": "Affiche un aperçu des derniers messages dans le fil d'amis", + "name": "Aperçu du message du flux d'amis", + "description": "Affiche un aperçu des derniers messages du flux d'ami", "properties": { "amount": { "name": "Quantité", - "description": "La quantité de messages à prévisualiser" + "description": "Le nombre de messages à prévisualiser" } } }, - "snap_preview": { - "name": "Aperçu du Snap", - "description": "Affiche un petit aperçu à côté des Snaps non vus dans la discussion" - }, "bootstrap_override": { - "name": "Remplacement de Bootstrap", - "description": "Remplace les paramètres de bootstrap de l'interface utilisateur", + "name": "Remplacement de l'interface d'utilisateur", + "description": "Contourne les paramètres de démarrage de l'interface utilisateur", "properties": { "app_appearance": { - "name": "Apparence de l'application", - "description": "Définit une apparence d'application persistante" + "name": "Apparance de l'application", + "description": "Définit une apparence persistante de l'application" }, "home_tab": { "name": "Onglet d'accueil", - "description": "Remplace l'onglet de démarrage lors de l'ouverture de Snapchat" + "description": "Remplacement de l'onglet à l'ouverture" + }, + "simple_snapchat": { + "description": "Permet une version simplifiée de Snapchat", + "name": "Snapchat simple" } } }, - "force_amoled_theme": { - "name": "Mode sombre Amoled", - "description": "Utilise un fond noir véritable pour le thème sombre" - }, "map_friend_nametags": { - "name": "Plaques d'identification d'amis de la carte améliorées", - "description": "Améliore les plaques d'identification des amis sur la Snapmap" - }, - "prevent_message_list_auto_scroll": { - "name": "Empêcher le défilement automatique de la liste des messages", - "description": "Empêche la liste des messages de défiler vers le bas lors de l'envoi/la réception d'un message" + "name": "Améliorations des nametags d'amis sur la Carte Snap", + "description": "Améliore les nametags des amis sur la Carte Snap" }, "streak_expiration_info": { - "name": "Afficher les informations d'expiration de la série", - "description": "Affiche un minuteur d'expiration de la série à côté du compteur de séries" - }, - "hide_friend_feed_entry": { - "name": "Masquer l'entrée du fil d'amis", - "description": "Masque un ami spécifique du fil d'amis\nUtilisez l'onglet social pour gérer cette fonctionnalité" + "name": "Infos sur l'expiration des flammes", + "description": "Affiche un compteur d'expiration de flamme à côté du compteur de flamme" }, "hide_streak_restore": { - "name": "Masquer la restauration de la série", - "description": "Masque le bouton Restaurer dans le fil d'amis" - }, - "hide_quick_add_suggestions": { - "name": "Masquer les suggestions d'ajout rapide", - "description": "Supprime les suggestions d'amis d'ajout rapide" - }, - "hide_story_suggestions": { - "name": "Masquer les suggestions d'histoires", - "description": "Supprime les suggestions de la page Histoires" + "name": "Masque la restauration de Snapflamme", + "description": "Masque le bouton de restauration" }, "hide_ui_components": { - "name": "Masquer les composants de l'interface utilisateur", - "description": "Sélectionnez les composants de l'interface utilisateur à masquer" - }, - "opera_media_quick_info": { - "name": "Informations rapides sur les médias Opera", - "description": "Affiche des informations utiles sur les médias, telles que la date de création, dans le menu contextuel du visualiseur Opera" - }, - "old_bitmoji_selfie": { - "name": "Ancien selfie Bitmoji", - "description": "Restaure les selfies Bitmoji des anciennes versions de Snapchat" + "name": "Masque les composants de l'interface utilisateur", + "description": "Sélectionner quels éléments de l'interface est à masqué" }, "disable_spotlight": { - "name": "Désactiver Spotlight", + "name": "Désactive la section Spotlight", "description": "Désactive la page Spotlight" }, "friend_feed_menu_buttons": { - "name": "Boutons du menu du fil d'amis", - "description": "Sélectionnez les boutons à afficher dans le menu du fil d'amis" - }, - "auto_close_friend_feed_menu": { - "name": "Fermer automatiquement le menu du fil d'amis", - "description": "Ferme automatiquement le menu du fil d'amis après avoir appuyé sur un bouton de paramètre" - }, - "vertical_story_viewer": { - "name": "Visualiseur d'histoires vertical", - "description": "Active le visualiseur d'histoires vertical pour toutes les histoires" + "name": "Boutons dans le chat d'amis", + "description": "Sélectionner les boutons à afficher dans la barre de menu du fil d'amis" }, "enable_friend_feed_menu_bar": { - "name": "Barre de menu du fil d'amis", - "description": "Active la nouvelle barre de menu du fil d'amis" + "description": "Active la nouvelle barre de menu de flux d'amis", + "name": "Barre du menu du fil d'amis" }, - "message_indicators": { - "name": "Indicateurs de message", - "description": "Ajoute des icônes d'indicateurs spécifiques aux messages\nRemarque : Les indicateurs peuvent ne pas être précis à 100 %" + "opera_media_quick_info": { + "description": "Affiche des informations utiles sur les médias, telles que la date de création, dans le menu contextuel de la visionneuse d'Opera", + "name": "Informations rapides des médias Opera" }, - "stealth_mode_indicator": { - "name": "Indicateur de mode furtif", - "description": "Ajoute un emoji 👻 à côté des conversations en mode furtif" + "vertical_story_viewer": { + "name": "Visionneuse verticale de story", + "description": "Active la visualisation verticale pour toutes les Stories" + }, + "old_bitmoji_selfie": { + "name": "Ancien Selfie Bitmoji", + "description": "Restaurer les selfies Bitmoji des anciennes versions de Snapchat" + }, + "prevent_message_list_auto_scroll": { + "name": "Empêcher le défilement automatique de la liste des messages", + "description": "Empêche le défilement de la liste des messages vers le bas lors de l'envoi ou de la réception d'un message" }, "edit_text_override": { - "name": "Remplacement de la modification de texte", - "description": "Remplace le comportement du champ de texte" + "name": "Modification de l'éditeur de texte", + "description": "Remplace le comportement des champs de texte" }, - "prevent_forced_keyboard": { - "name": "Empêcher le clavier forcé", - "description": "Empêche Snapchat d'afficher automatiquement le clavier lorsque vous ouvrez une conversation" + "snap_preview": { + "name": "Aperçu des Snaps", + "description": "Affiche un petit aperçu à côté des Snaps non vus dans le chat" }, - "settings_menu": { - "name": "Menu des paramètres", - "description": "Modifie la façon dont vous ouvrez le menu PurrfectSnap", - "options": { - "default": "Par défaut", - "legacy": "Hérité" - } + "hide_friend_feed_entry": { + "description": "Masque un ami spécifique du fil des amis\nUtilisez l'onglet social pour gérer cette fonctionnalité", + "name": "Masquer l'entrée dans le fil d'amis" + }, + "hide_story_suggestions": { + "name": "Cacher les suggestions de story", + "description": "Supprimer les suggestions de la section des stories" + }, + "stealth_mode_indicator": { + "name": "Indicateur de Mode Furtif", + "description": "Ajoute un emoji 👻 à côté des conversations en mode furtif" + }, + "message_indicators": { + "name": "Indicateur de messages", + "description": "Ajoute des icônes d'indicateurs spécifiques aux messages\nRemarque : les indicateurs peuvent ne pas être à 100% précis" + }, + "auto_close_friend_feed_menu": { + "name": "Menu de fermeture automatique du fil d'amis", + "description": "Ferme automatiquement le menu liste d'amis après avoir appuyé sur un bouton de réglage" + }, + "custom_theme": { + "description": "Personnalisez les couleurs de Snapchat\nRemarque : si vous choisissez un thème sombre (comme Amoled), vous devrez peut-être activer le mode sombre dans les paramètres de Snapchat pour de meilleurs résultats", + "name": "Thème personnalisé" + }, + "hide_quick_add_suggestions": { + "name": "Masquer les suggestions d'ajout rapide", + "description": "Supprime les suggestions d'ajout rapide d'amis" } } }, "messaging": { "name": "Messagerie", - "description": "Modifier la façon dont vous interagissez avec vos amis", + "description": "Changez la façon dont vous interagissez avec vos amis", "properties": { - "bypass_screenshot_detection": { - "name": "Contourner la détection de capture d'écran", - "description": "Empêche Snapchat de détecter lorsque vous prenez une capture d'écran" - }, "anonymous_story_viewing": { - "name": "Visualisation anonyme des histoires", - "description": "Empêche quiconque de savoir que vous avez vu son histoire" - }, - "prevent_story_rewatch_indicator": { - "name": "Empêcher l'indicateur de re-visionnage de l'histoire", - "description": "Empêche quiconque de savoir que vous avez revu son histoire" - }, - "hide_peek_a_peek": { - "name": "Masquer Peek-a-Peek", - "description": "Empêche l'envoi d'une notification lorsque vous balayez à moitié dans une discussion" + "name": "Anonymiser le visionnage des stories", + "description": "Empêcher n'importe qui de savoir que vous avez vu leur story" }, "hide_bitmoji_presence": { - "name": "Masquer la présence de Bitmoji", - "description": "Empêche votre Bitmoji d'apparaître pendant que vous êtes dans la discussion" + "name": "Cacher le Bitmoji dans la conversation", + "description": "Empêche votre Bitmoji d'apparaître dans le chat" }, "hide_typing_notifications": { - "name": "Masquer les notifications de saisie", - "description": "Empêche quiconque de savoir que vous êtes en train de taper un message" + "name": "Masquer la notification \"En train d'écrire\"", + "description": "Empêcher n'importe qui de savoir que vous avez lu leurs messages" }, "unlimited_snap_view_time": { - "name": "Temps de visualisation de Snap illimité", + "name": "Temps de visionnage des Snaps illimités", "description": "Supprime la limite de temps pour la visualisation des Snaps" }, - "auto_mark_as_read": { - "name": "Marquer automatiquement comme lu", - "description": "Marque automatiquement les messages/snaps comme lus même lorsque le mode furtif est activé" - }, - "mark_snap_as_seen_button": { - "name": "Bouton Marquer le Snap comme vu", - "description": "Ajoute un bouton pour marquer un Snap comme vu lors de sa visualisation.\nCela fonctionnera même lorsque le mode furtif est activé" - }, - "skip_when_marking_as_seen": { - "name": "Ignorer lors du marquage comme vu", - "description": "Passe automatiquement au Snap suivant lors du marquage d'un Snap comme vu.\nÀ utiliser en combinaison avec le bouton Marquer le Snap comme vu" - }, - "loop_media_playback": { - "name": "Lecture en boucle des médias", - "description": "Lit en boucle les médias lors de la visualisation des Snaps/Histoires" - }, "disable_replay_in_ff": { "name": "Désactiver la relecture dans le FF", - "description": "Désactive la possibilité de rejouer avec un appui long depuis le fil d'amis" - }, - "half_swipe_notifier": { - "name": "Notificateur de balayage à moitié", - "description": "Vous avertit lorsque quelqu'un balaie à moitié dans une conversation", - "properties": { - "min_duration": { - "name": "Durée minimale", - "description": "La durée minimale du balayage à moitié (en secondes)" - }, - "max_duration": { - "name": "Durée maximale", - "description": "La durée maximale du balayage à moitié (en secondes)" - } - } - }, - "call_start_confirmation": { - "name": "Confirmation du début de l'appel", - "description": "Affiche une boîte de dialogue de confirmation lors du démarrage d'un appel" - }, - "unlimited_conversation_pinning": { - "name": "Épinglage de conversation illimité", - "description": "Vous permet d'épingler un nombre illimité de conversations localement" - }, - "disable_snap_mode_restrictions": { - "name": "Désactiver les restrictions du mode Snap", - "description": "Vous permet de visualiser les Snaps autodestructeurs sans restrictions" + "description": "Désactive la possibilité de rejouer avec un appui long du fil des amis" }, "prevent_message_sending": { - "name": "Empêcher l'envoi de messages", - "description": "Empêche l'envoi de certains types de messages" - }, - "friend_mutation_notifier": { - "name": "Notificateur de mutation d'amis", - "description": "Vous avertit lorsque quelque chose change dans le profil d'un ami" + "name": "Empêcher l'envoi de message", + "description": "Empêche l'envoi de certains types de message" }, "better_notifications": { - "name": "Meilleures notifications", - "description": "Ajoute plus d'informations dans les notifications reçues", + "name": "Notifications améliorées", + "description": "Ajouter plus d'informations dans les notifications reçues", "properties": { + "reply_button": { + "description": "Ajoute un bouton de réponse à la notification", + "name": "Bouton Répondre" + }, + "download_button": { + "name": "Bouton de téléchargement", + "description": "Vous permet de télécharger des médias à partir de la notification" + }, + "mark_as_read_and_save_in_chat": { + "name": "Marquer comme lu et enregistrer dans le chat", + "description": "Ajoute une marque comme lu et enregistre le bouton de discussion à la notification" + }, "group_notifications": { "name": "Notifications de groupe", "description": "Regrouper les notifications en une seule" }, "chat_preview": { - "name": "Aperçu de la discussion", + "name": "Aperçu du chat", "description": "Affiche un aperçu des messages reçus dans la notification" }, "media_preview": { @@ -979,302 +562,344 @@ "description": "Affiche un aperçu des types de médias sélectionnés dans la notification" }, "media_caption": { - "name": "Légende des médias", - "description": "Affiche la légende jointe des médias dans la notification" + "name": "Légende du média", + "description": "Affiche la légende jointe du média dans la notification" }, "stacked_media_messages": { "name": "Messages multimédias empilés", - "description": "Combine plusieurs messages multimédias en une seule notification textuelle lorsqu'ils ne peuvent pas être prévisualisés. À utiliser en combinaison avec l'aperçu de la discussion" + "description": "Combine plusieurs messages multimédias en une seule notification texte lorsqu'ils ne peuvent pas être prévisualisés. Utiliser en combinaison avec Aperçu du Chat" }, "friend_add_source": { - "name": "Source d'ajout d'amis", + "name": "Source d'ajout d'ami", "description": "Affiche la source d'une demande d'ami dans la notification" }, - "reply_button": { - "name": "Bouton Répondre", - "description": "Ajoute un bouton de réponse à la notification" - }, - "smart_replies": { - "name": "Réponses intelligentes", - "description": "Ajoute des réponses suggérées aux notifications (Android 10+). À utiliser en combinaison avec le bouton Répondre" - }, - "download_button": { - "name": "Bouton de téléchargement", - "description": "Vous permet de télécharger des médias depuis la notification" - }, "mark_as_read_button": { "name": "Bouton Marquer comme lu", - "description": "Vous permet de marquer un message comme lu depuis la notification" + "description": "Vous permet de marquer un message comme lu à partir de la notification" }, - "mark_as_read_and_save_in_chat": { - "name": "Marquer comme lu et enregistrer dans la discussion", - "description": "Ajoute un bouton marquer comme lu et enregistrer dans la discussion à la notification" + "smart_replies": { + "description": "Ajoute des réponses suggérées aux notifications (Android 10+). À utiliser en combinaison avec le bouton Répondre", + "name": "Réponses intelligentes" } } }, "notification_blacklist": { "name": "Liste noire des notifications", - "description": "Sélectionnez les notifications qui doivent être bloquées" + "description": "Sélectionnez les notifications qui devraient être bloquées" }, "message_logger": { - "name": "Journal des messages", - "description": "Empêche la suppression des messages", + "name": "Journalisation des messages", + "description": "Empêcher l'effacement des messages", "properties": { + "message_filter": { + "name": "Filtre de message", + "description": "Sélectionner les messages qui doivent être enregistrés (vide pour l'ensemble des messages)" + }, + "auto_purge": { + "description": "Supprime automatiquement les messages mis en cache qui sont plus anciens que la durée spécifiée", + "name": "Purge automatique" + }, "keep_my_own_messages": { "name": "Conserver mes propres messages", "description": "Empêche la suppression de vos propres messages" }, - "auto_purge": { - "name": "Purge automatique", - "description": "Supprime automatiquement les messages mis en cache qui sont plus anciens que la durée spécifiée" - }, - "message_filter": { - "name": "Filtre de messages", - "description": "Sélectionnez les messages qui doivent être enregistrés (vide pour tous les messages)" - }, "deleted_message_color": { - "name": "Couleur du message supprimé", - "description": "Définit la couleur des messages supprimés" + "description": "Définit la couleur des messages supprimés", + "name": "Couleur du message supprimé" } } }, "auto_save_messages_in_conversations": { - "name": "Enregistrer automatiquement les messages", - "description": "Enregistre automatiquement chaque message dans les conversations" + "name": "Enregistrement automatique des messages", + "description": "Enregistre automatiquement tous les messages des conversations" }, "gallery_media_send_override": { - "name": "Remplacement de l'envoi de médias de la galerie", - "description": "Falsifie la source des médias lors de l'envoi depuis la galerie" + "name": "Remplacement de l'envoi des médias de la galerie", + "description": "Falsifie la source du média lors de l'envoi depuis la Galerie" + }, + "loop_media_playback": { + "name": "Lecture en boucle des médias", + "description": "Lecture des médias en boucle lors de la visualisation des Snaps / Stories" + }, + "call_start_confirmation": { + "name": "Confirmation de début d'appel", + "description": "Affiche une fenêtre de confirmation lors du lancement d'un appel" + }, + "half_swipe_notifier": { + "properties": { + "min_duration": { + "name": "Durée minimale", + "description": "Durée minimale du balayage (en secondes)" + }, + "max_duration": { + "description": "Durée maximale du balayage (en secondes)", + "name": "Durée maximale" + } + }, + "name": "Notifications des entrouverts", + "description": "Vous avertit lorsque quelqu'un entrouvre une conversation" + }, + "bypass_screenshot_detection": { + "description": "Empêche Snapchat de détecter les captures d'écran", + "name": "Contourner la détection de capture d'écran" + }, + "prevent_story_rewatch_indicator": { + "name": "Empêcher l'indicateur de relecture des stories", + "description": "Empêche quiconque de savoir que vous avez revu leur Story" + }, + "hide_peek_a_peek": { + "description": "Empêche l'envoi d'une notification lorsque vous entre ouvrez une conversation", + "name": "Cacher les ouvertures partielles des conversations" }, "strip_media_metadata": { - "name": "Supprimer les métadonnées des médias", - "description": "Supprime les métadonnées des médias avant de les envoyer en tant que message" + "description": "Supprime les métadonnées des médias avant de les envoyer sous forme de message", + "name": "Enlever les métadonnées des médias" }, "bypass_message_retention_policy": { "name": "Contourner la politique de conservation des messages", - "description": "Empêche la suppression des messages après leur visualisation" + "description": "Empêche la disparition des messages après les avoir consultés" }, "bypass_message_action_restrictions": { - "name": "Contourner les restrictions d'action sur les messages", - "description": "Vous permet de réagir à un snap sans l'avoir ouvert ou d'enregistrer un message non enregistrable" + "name": "Contourner les restrictions d'action des messages", + "description": "Vous permet de réagir à un snap sans l'avoir ouvert ou de sauvegarder un message non sauvegardable" }, "remove_groups_locked_status": { - "name": "Supprimer l'état de verrouillage des groupes", - "description": "Vous permet de visualiser les informations du groupe après avoir été expulsé" + "name": "Supprimer le statut verrouillé des groupes", + "description": "Vous permet de consulter les informations du groupe après avoir été expulsé" }, - "double_tap_chat_action": { - "name": "Action de discussion par double appui", - "description": "Effectue une action personnalisée lorsque vous appuyez deux fois sur un message dans la discussion" + "auto_mark_as_read": { + "name": "Marquer automatiquement comme lu", + "description": "Marque automatiquement les messages/Snaps comme lus même lorsque le mode Stealth est activé" + }, + "friend_mutation_notifier": { + "name": "Notificateur de mutation d'ami", + "description": "Vous avertit lorsque quelque chose change dans le profil d'un ami" + }, + "unlimited_conversation_pinning": { + "description": "Permet d'épingler localement un nombre illimité de conversations", + "name": "Épinglage illimité des conversations" + }, + "mark_snap_as_seen_button": { + "name": "Bouton Marquer Snap comme vu", + "description": "Ajoute un bouton pour marquer un Snap comme vu lors de sa visualisation.\nCela fonctionnera même lorsque le mode furtif est activé" + }, + "skip_when_marking_as_seen": { + "name": "Ignorer lors du marquage comme vu", + "description": "Passe automatiquement au Snap suivant lors du marquage d'un Snap comme vu.\nÀ utiliser en combinaison avec le Bouton Marquer Snap comme vu" }, "double_tap_chat_action_custom_emoji": { - "name": "Réaction d'emoji personnalisée de l'action de discussion par double appui", - "description": "Définit une réaction d'emoji personnalisée pour l'action de discussion par double appui" + "name": "Action de chat en appuyant deux fois Réaction Emoji personnalisée", + "description": "Définit une réaction emoji personnalisée pour l'action de chat en double-cliquant" + }, + "double_tap_chat_action": { + "name": "Action de chat en appuyant deux fois", + "description": "Effectue une action personnalisée en appuyant deux fois sur un message dans le chat" } } }, "global": { - "name": "Mondial", + "name": "Global", "description": "Modifier les paramètres globaux de Snapchat", "properties": { - "better_location": { - "name": "Meilleur emplacement", - "description": "Améliore l'emplacement de Snapchat", - "properties": { - "spoof_location": { - "name": "Falsifier l'emplacement", - "description": "Falsifie votre emplacement à un emplacement spécifié" - }, - "coordinates": { - "name": "Coordonnées", - "description": "Définissez les coordonnées de l'emplacement falsifié" - }, - "walk_radius": { - "name": "Rayon de marche", - "description": "Se promener au hasard dans ce rayon (pieds)" - }, - "always_update_location": { - "name": "Toujours mettre à jour l'emplacement", - "description": "Forcer Snapchat à mettre à jour l'emplacement même si aucune donnée GPS n'est reçue" - }, - "suspend_location_updates": { - "name": "Suspendre les mises à jour de l'emplacement", - "description": "Empêche la mise à jour de votre emplacement" - }, - "spoof_battery_level": { - "name": "Falsifier le niveau de la batterie", - "description": "Falsifie le niveau de la batterie de votre appareil sur la carte\nLa valeur doit être comprise entre 0 et 100" - }, - "spoof_headphones": { - "name": "Falsifier les écouteurs", - "description": "Falsifie l'état d'écoute de la musique sur la carte" - }, - "show_battery_level": { - "name": "Afficher le niveau de la batterie", - "description": "Affiche le niveau de la batterie de vos amis sur la carte" - } - } - }, "snapchat_plus": { - "name": "SnapchatPlus", - "description": "Active les fonctionnalités de Snapchat Plus\nCertaines fonctionnalités côté serveur peuvent ne pas fonctionner" - }, - "media_upload_quality": { - "name": "Qualité de téléversement des médias", - "description": "Remplace la qualité de téléversement des médias", - "properties": { - "force_video_upload_source_quality": { - "name": "Forcer la qualité de la source de téléversement vidéo", - "description": "Force Snapchat à utiliser la qualité de la source lors du téléversement de vidéos\nVeuillez noter que cela peut ne pas supprimer les métadonnées des médias" - }, - "disable_image_compression": { - "name": "Désactiver la compression d'image", - "description": "Désactive la compression d'image lors du téléversement de médias" - }, - "custom_image_upload_format": { - "name": "Format de téléversement d'image personnalisé", - "description": "Définit un format de téléversement d'image personnalisé\nSélectionnez un format sans perte (comme PNG) pour la meilleure qualité" - } - } - }, - "disable_confirmation_dialogs": { - "name": "Désactiver les boîtes de dialogue de confirmation", - "description": "Confirme automatiquement les actions sélectionnées" + "name": "Snapchat Plus", + "description": "Activer les fonctionnalités de Snapchat Plus\nCertaines fonctionnalités côté serveur peuvent ne pas fonctionner" }, "auto_updater": { "name": "Mise à jour automatique", - "description": "Vérifie automatiquement les nouvelles mises à jour" + "description": "Vérifier automatiquement les mises à jour" }, "disable_metrics": { "name": "Désactiver les métriques", - "description": "Bloque l'envoi de données analytiques spécifiques à Snapchat" - }, - "disable_story_sections": { - "name": "Désactiver les sections d'histoires", - "description": "Supprime les sections de la page Histoires\nPeut nécessiter une actualisation pour fonctionner correctement" + "description": "Bloque l'envoi de données analytiques spécifiques vers Snapchat" }, "block_ads": { "name": "Bloquer les publicités", "description": "Empêche l'affichage des publicités" }, - "disable_custom_tabs": { - "name": "Désactiver les onglets personnalisés", - "description": "Ouvre les liens dans les applications prises en charge plutôt que dans le navigateur Web" + "bypass_video_length_restriction": { + "name": "Contourner la restriction de longueur vidéo", + "description": "Unique : envoie une seule vidéo\n Split : diviser les vidéos après le montage" }, - "disable_permission_requests": { - "name": "Désactiver les demandes d'autorisation", - "description": "Empêche Snapchat de demander des autorisations spécifiques" + "disable_google_play_dialogs": { + "name": "Désactiver les avertissements des services Google Play", + "description": "Empêcher les services Google Play d'afficher des boites de dialogues" }, - "disable_memories_snap_feed": { - "name": "Désactiver le fil de Snaps des souvenirs", - "description": "Empêche Snapchat d'afficher les souvenirs récents lorsque vous balayez vers le haut dans l'appareil photo" + "disable_snap_splitting": { + "name": "Désactiver le fractionnement des Snaps", + "description": "Empêche les Snaps d'être divisés en plusieurs parties\nLes images que vous envoyez seront transformées en vidéos" + }, + "disable_confirmation_dialogs": { + "name": "Désactiver les fenêtres de confirmation", + "description": "Confirme automatiquement les actions sélectionnées" }, "spotlight_comments_username": { "name": "Nom d'utilisateur des commentaires Spotlight", "description": "Affiche le nom d'utilisateur de l'auteur dans les commentaires Spotlight" }, - "bypass_video_length_restriction": { - "name": "Contourner les restrictions de longueur de vidéo", - "description": "Unique : envoie une seule vidéo\nDivisé : divise les vidéos après modification" + "disable_story_sections": { + "name": "Désactiver les sections de story", + "description": "Supprime les sections de la page des stories\nUne actualisation peut être nécessaire pour fonctionner correctement" + }, + "disable_memories_snap_feed": { + "name": "Désactive le Fil Souvenirs Snap", + "description": "Empêche Snapchat d'afficher les souvenirs récents lorsque vous faites glisser vers le haut dans l'appareil photo" }, "default_video_playback_rate": { - "name": "Vitesse de lecture vidéo par défaut", + "name": "Taux de lecture vidéo par défaut", "description": "Définit la vitesse par défaut pour la lecture des vidéos\nLa valeur doit être comprise entre 0,1 et 4,0" }, - "video_playback_rate_slider": { - "name": "Curseur de vitesse de lecture vidéo", - "description": "Ajoute un curseur dans le menu contextuel d'Opera pour modifier la vitesse de lecture vidéo\nRemarque : Les modifications ne s'appliquent qu'aux vidéos suivantes" + "disable_permission_requests": { + "name": "Désactiver la demande d'autorisation", + "description": "Empêche Snapchat de demander des autorisations spécifiques" }, - "disable_google_play_dialogs": { - "name": "Désactiver les boîtes de dialogue des services Google Play", - "description": "Empêcher l'affichage des boîtes de dialogue de disponibilité des services Google Play" + "better_location": { + "name": "Meilleure localisation", + "properties": { + "coordinates": { + "name": "Coordonnées", + "description": "Définissez les coordonnées de l'emplacement simulé" + }, + "always_update_location": { + "name": "Toujours actualiser la localisation", + "description": "Forcer Snapchat à mettre à jour la position même si aucune donnée GPS n'est reçue" + }, + "spoof_location": { + "description": "Simule votre emplacement à un endroit spécifié", + "name": "Fausser la localisation" + }, + "suspend_location_updates": { + "name": "Suspendre les mises à jour de localisation", + "description": "Empêche la mise à jour de votre position" + }, + "spoof_battery_level": { + "description": "Usure le niveau de la batterie de votre appareil sur la carte\n La valeur doit être comprise entre 0 et 100", + "name": "Usurper le niveau de batterie" + }, + "spoof_headphones": { + "description": "Usurpe le statut d'écoute de musique sur la carte", + "name": "Usurper les écouteurs" + }, + "walk_radius": { + "name": "Rayon de marche", + "description": "Déplacer de manière aléatoire à l'intérieur de ce rayon (en pieds)" + }, + "show_battery_level": { + "description": "Affiche le niveau de batterie de vos amis sur la carte", + "name": "Afficher le niveau de la batterie" + } + }, + "description": "Améliore la localisation sur Snapchat" }, "default_volume_controls": { - "name": "Commandes de volume par défaut", - "description": "Force Snapchat à utiliser les commandes de volume du système" + "description": "Force Snapchat à utiliser les commandes de volume du système", + "name": "Contrôles de volume par défaut" }, - "disable_telecom_framework": { - "name": "Désactiver le framework de télécommunication", - "description": "Empêche Snapchat d'utiliser le framework de télécommunication Android\nCela vous permet d'écouter de la musique pendant un appel" + "video_playback_rate_slider": { + "name": "Curseur de taux de lecture vidéo", + "description": "Ajoute un curseur dans le menu contextuel de l'opéra pour modifier la vitesse de lecture vidéo\nRemarque: Les modifications ne s'appliquent qu'aux vidéos suivantes" }, "hide_active_music": { - "name": "Masquer la musique active", - "description": "Empêche Snapchat de savoir que vous écoutez de la musique\nCela vous permettra de prendre des snaps à l'aide des boutons de contrôle du volume tout en écoutant de la musique" + "description": "Empêche Snapchat de savoir que vous écoutez de la musique\nCela vous permettra de prendre des snaps en utilisant les boutons de volume de contrôle tout en écoutant de la musique", + "name": "Cache la musique active" }, - "disable_snap_splitting": { - "name": "Désactiver la division des Snaps", - "description": "Empêche la division des Snaps en plusieurs parties\nLes photos que vous envoyez se transformeront en vidéos" + "disable_custom_tabs": { + "name": "Désactiver les onglets personnalisés", + "description": "Ouvre les liens dans les applications prises en charge plutôt que dans le navigateur Web" + }, + "media_upload_quality": { + "properties": { + "force_video_upload_source_quality": { + "name": "Forcer la qualité source de l'importation vidéo", + "description": "Force Snapchat à utiliser la qualité source lors de l'importation de vidéos\nVeuillez noter que cela ne supprimera peut-être pas les métadonnées du média." + }, + "disable_image_compression": { + "name": "Désactiver la compression d'image", + "description": "Désactive la compression d'image lors de l'importation de médias" + }, + "custom_image_upload_format": { + "name": "Format d'importation d'image personnalisé", + "description": "Définit un format d'importation d'image personnalisé\nSélectionnez un format sans perte (comme PNG) pour la meilleure qualité" + } + }, + "name": "Qualité d'importation des médias", + "description": "Remplace la qualité d'importation multimédia" + }, + "disable_telecom_framework": { + "name": "Désactiver le cadre de télécommunications", + "description": "Empêche Snapchat d'utiliser le framework Android Telecom\nCela vous permet d'écouter de la musique pendant un appel" } } }, "rules": { "name": "Règles", - "description": "Gérer les fonctionnalités automatiques pour des personnes individuelles" + "description": "Gérer les fonctionnalités automatiques pour les personnes individuelles" }, "camera": { - "name": "Appareil photo", - "description": "Ajustez les bons paramètres pour le snap parfait", + "name": "Caméra", + "description": "Ajuster les bons réglages pour le Snap parfait", "properties": { - "disable_cameras": { - "name": "Désactiver les appareils photo", - "description": "Empêche Snapchat d'utiliser les appareils photo sélectionnés" - }, - "black_photos": { - "name": "Photos noires", - "description": "Remplace les photos capturées par un fond noir\nLes vidéos ne sont pas affectées" - }, "immersive_camera_preview": { - "name": "Aperçu immersif", - "description": "Empêche Snapchat de recadrer l'aperçu de l'appareil photo\nCela peut provoquer un scintillement de l'appareil photo sur certains appareils" - }, - "override_front_resolution": { - "name": "Remplacer la résolution avant", - "description": "Remplace la résolution de l'appareil photo pour l'appareil photo avant" - }, - "override_back_resolution": { - "name": "Remplacer la résolution arrière", - "description": "Remplace la résolution de l'appareil photo pour l'appareil photo arrière" - }, - "custom_resolution": { - "name": "Résolution personnalisée", - "description": "Définit une résolution d'appareil photo personnalisée, largeur x hauteur (par exemple, 1920x1080).\nLa résolution personnalisée doit être prise en charge par votre appareil" - }, - "front_custom_frame_rate": { - "name": "Fréquence d'images personnalisée avant", - "description": "Remplace la fréquence d'images de l'appareil photo avant" - }, - "back_custom_frame_rate": { - "name": "Fréquence d'images personnalisée arrière", - "description": "Remplace la fréquence d'images de l'appareil photo arrière" + "name": "Aperçu de la caméra immersif", + "description": "Empêche Snapchat de recadrer l'aperçu de la caméra\nCela peut faire clignoter la caméra sur certains appareils" }, "force_camera_source_encoding": { - "name": "Forcer l'encodage de la source de l'appareil photo", - "description": "Force l'encodage de la source de l'appareil photo" + "name": "Forcer l'encodage source de la caméra", + "description": "Forcer l'encodage source de la caméra" }, - "startup_default_camera": { - "name": "Appareil photo par défaut au démarrage", - "description": "Définit l'appareil photo par défaut lors de l'ouverture de Snapchat" + "black_photos": { + "description": "Remplace les photos capturées par un arrière-plan noir\nLes vidéos ne sont pas affectées", + "name": "Photos noires" }, "hevc_recording": { "name": "Enregistrement HEVC", "description": "Utilise le codec HEVC (H.265) pour l'enregistrement vidéo" + }, + "back_custom_frame_rate": { + "name": "Fréquence d'images personnalisée à l'arrière", + "description": "Remplace la fréquence d'images de la caméra arrière" + }, + "override_front_resolution": { + "description": "Remplace la résolution de la caméra frontale", + "name": "Changer résolution frontale" + }, + "override_back_resolution": { + "description": "Remplace la résolution de la caméra arrière", + "name": "Changer résolution arrière" + }, + "custom_resolution": { + "name": "Résolution personnalisée", + "description": "Définit une résolution de caméra personnalisée, largeur x hauteur (par exemple 1920x1080).\nLa résolution personnalisée doit être prise en charge par votre appareil" + }, + "disable_cameras": { + "name": "Désactiver les caméras", + "description": "Empêche Snapchat d'utiliser les caméras sélectionnées" + }, + "front_custom_frame_rate": { + "name": "Fréquence d'images personnalisée à l'avant", + "description": "Remplace la fréquence d'images de la caméra frontale" + }, + "startup_default_camera": { + "name": "Caméra par défaut de démarrage", + "description": "Définit l'appareil photo par défaut lors de l'ouverture de Snapchat" } } }, "streaks_reminder": { - "name": "Rappel de séries", - "description": "Vous avertit périodiquement de vos séries", + "name": "Rappels des Flammes", + "description": "Vous informe périodiquement concernant vos flammes", "properties": { "interval": { - "name": "Intervalle", + "name": "Fréquence", "description": "L'intervalle entre chaque rappel (heures)" }, "remaining_hours": { "name": "Temps restant", - "description": "Le temps restant avant l'affichage de la notification (heures)" + "description": "Le temps restant avant que la notification soit affichée (heures)" }, "group_notifications": { "name": "Notifications de groupe", - "description": "Regrouper les notifications en une seule" + "description": "Grouper les notifications en une seule" } } }, @@ -1284,221 +909,219 @@ "properties": { "native_hooks": { "name": "Hooks natifs", - "description": "Fonctionnalités non sécurisées qui se connectent au code natif de Snapchat", "properties": { + "disable_bitmoji": { + "name": "Désactiver le Bitmoji", + "description": "Désactive le Bitmoji sur le profil d'amis" + }, "composer_hooks": { - "name": "Hooks du compositeur", - "description": "Injecte du code dans le framework d'interface utilisateur multiplateforme du compositeur", + "name": "Hooks Composer", + "description": "Injecte du code dans le framework d'interface utilisateur multiplateforme de Composer (uniquement arm64)", "properties": { - "show_first_created_username": { - "name": "Afficher le premier nom d'utilisateur créé", - "description": "Affiche le premier nom d'utilisateur créé à côté du nom d'utilisateur actuel sur la page de profil" - }, "bypass_camera_roll_limit": { - "name": "Contourner la limite de la pellicule", - "description": "Augmente la quantité maximale de médias que vous pouvez envoyer depuis la pellicule" - }, - "custom_self_destruct_snap_delay": { - "name": "Délai de Snap autodestructeur personnalisé", - "description": "Donne plus d'options pour le minuteur d'autodestruction lors de l'envoi d'un Snap" + "name": "Dépassement de la limite de la pellicule de l'appareil photo", + "description": "Augmente le nombre maximal de médias que vous pouvez envoyer depuis la pellicule de l'appareil photo" }, "composer_console": { - "name": "Console du compositeur", - "description": "Vous permet d'exécuter du code JavaScript dans le compositeur (arm64 uniquement)" + "name": "Console de Composer", + "description": "Permet d'exécuter du code JavaScript dans Composer" }, "composer_logs": { - "name": "Journaux du compositeur", - "description": "Redirige les journaux de la console du compositeur vers PurrfectSnap" + "name": "Journaux de Composer", + "description": "Redirige les journaux de console de Composer vers SnapEnhance" + }, + "show_first_created_username": { + "description": "Affiche le premier nom d'utilisateur créé à côté du nom d'utilisateur actuel dans la page de profil", + "name": "Afficher le premier nom d'utilisateur créé" } } }, - "disable_bitmoji": { - "name": "Désactiver Bitmoji", - "description": "Désactive le Bitmoji du profil des amis" - }, "custom_emoji_font": { - "name": "Police d'emoji personnalisée", - "description": "Vous permet d'utiliser une police d'emoji personnalisée. Ne fonctionne qu'avec les polices .ttf" + "name": "Police Emoji personnalisée", + "description": "Vous permet d'utiliser une police emoji personnalisée. Fonctionne uniquement avec les polices .ttf" }, "custom_shared_library": { "name": "Bibliothèque partagée personnalisée", "description": "Charge une bibliothèque partagée personnalisée dans Snapchat. Cette fonctionnalité est uniquement à des fins de test" } - } + }, + "description": "Fonctionnalités non fiables qui se greffent au code natif de Snapchat" }, "spoof": { - "name": "Falsifier", + "name": "Falsification", "description": "Falsifier diverses informations vous concernant", "properties": { - "play_store_installer_package_name": { - "name": "Nom du package d'installation du Play Store", - "description": "Remplace le nom du package d'installation par com.android.vending" + "remove_mock_location_flag": { + "name": "Supprimer le flag de Mock Location", + "description": "Empêche Snapchat de détecter les localisations Mock" }, "remove_vpn_transport_flag": { - "name": "Supprimer l'indicateur de transport VPN", - "description": "Empêche Snapchat de détecter les VPN" + "description": "Empêche Snapchat de détecter les VPN", + "name": "Supprimer le flag VPN Transport" }, - "remove_mock_location_flag": { - "name": "Supprimer l'indicateur d'emplacement fictif", - "description": "Empêche Snapchat de détecter l'emplacement fictif" - } - } - }, - "convert_message_locally": { - "name": "Convertir le message localement", - "description": "Convertit les snaps en médias externes de discussion localement. Cela apparaît dans le menu contextuel de téléchargement de la discussion" - }, - "media_file_picker": { - "name": "Sélecteur de fichiers multimédias", - "description": "Vous permet de choisir n'importe quel fichier vidéo/audio de la galerie" - }, - "story_logger": { - "name": "Journal des histoires", - "description": "Fournit un historique des histoires d'amis" - }, - "call_recorder": { - "name": "Enregistreur d'appels", - "description": "Enregistre automatiquement les appels audio" - }, - "account_switcher": { - "name": "Sélecteur de compte", - "description": "Vous permet de basculer entre les comptes sans vous déconnecter\nAppuyez longuement sur l'icône de recherche à côté de votre profil Bitmoji pour ouvrir le menu\nRemarque : Cette fonctionnalité est expérimentale et changera probablement à l'avenir", - "properties": { - "auto_backup_current_account": { - "name": "Sauvegarde automatique du compte actuel", - "description": "Sauvegarde automatiquement le compte actuel lors de la déconnexion ou du changement de compte" - } - } - }, - "better_transcript": { - "name": "Meilleure transcription", - "description": "Améliore la transcription des notes vocales", - "properties": { - "force_transcription": { - "name": "Forcer la transcription des notes vocales", - "description": "Permet de transcrire toutes les notes vocales" - }, - "preferred_transcription_lang": { - "name": "Langue de transcription préférée", - "description": "La langue préférée pour la transcription des notes vocales (par exemple, EN, ES, FR)" - }, - "notification_transcript": { - "name": "Transcription des notifications", - "description": "Transcrire les notes vocales dans les notifications\nCette fonctionnalité nécessite que la fonction d'aperçu de la discussion soit activée dans les meilleures notifications" - } - } - }, - "voice_note_auto_play": { - "name": "Lecture automatique des notes vocales", - "description": "Lit automatiquement la note vocale suivante une fois la note actuelle terminée" - }, - "friend_notes": { - "name": "Notes d'amis", - "description": "Vous permet d'ajouter des notes aux profils de vos amis" - }, - "cof_experiments": { - "name": "Expériences COF", - "description": "Active les fonctionnalités Snapchat non publiées/bêta" - }, - "context_menu_fix": { - "name": "Correction du menu contextuel", - "description": "Tenter de réparer le menu du fil d'amis car lorsque l'appareil est hors ligne, il ne peut pas être affiché correctement" - }, - "app_lock": { - "name": "Verrouillage de l'application", - "description": "Empêche l'accès à Snapchat sans mot de passe", - "properties": { - "lock_on_resume": { - "name": "Verrouiller à la reprise", - "description": "Verrouille l'application lorsqu'elle est rouverte" + "play_store_installer_package_name": { + "description": "Remplace le nom du package d'installation par com.android.vending", + "name": "Nom du package de l'installateur Play Store" } } }, "infinite_story_boost": { - "name": "Boost d'histoire infini", - "description": "Contourner le délai de la limite de boost d'histoire" - }, - "meo_passcode_bypass": { - "name": "Contournement du mot de passe de Mes yeux seulement", - "description": "Contourner le mot de passe de Mes yeux seulement\nCela ne fonctionnera que si le mot de passe a été saisi correctement auparavant" + "name": "Boost de story infini", + "description": "Contournez le délai de Boost de Story" }, "no_friend_score_delay": { - "name": "Pas de délai de score d'ami", - "description": "Supprime le délai lors de l'affichage du score d'un ami" - }, - "best_friend_pinning": { - "name": "Épinglage du meilleur ami", - "description": "Vous permet d'épingler un ami comme votre meilleur ami numéro un. Remarque : Vous seul pouvez voir votre meilleur ami épinglé" + "name": "Pas de délai du score d'amis", + "description": "Supprime le délai lors de la visualisation d'un score d'amis" }, "e2ee": { - "name": "Chiffrement de bout en bout", - "description": "Chiffre vos messages avec AES à l'aide d'une clé secrète partagée\nAssurez-vous de conserver votre clé en lieu sûr !", + "name": "Chiffrement de bout-en-bout", + "description": "Chiffre vos messages avec AES à l'aide d'une clé secrète\nAssurez-vous de sauvegarder votre clé quelque part en sécurité !", "properties": { "encrypted_message_indicator": { "name": "Indicateur de message chiffré", - "description": "Ajoute un emoji 🔒 à côté des messages chiffrés" + "description": "Ajoute un émoji 🔒 à côté des messages chiffrés" }, "force_message_encryption": { "name": "Forcer le chiffrement des messages", - "description": "Empêche l'envoi de messages chiffrés à des personnes qui n'ont pas activé le chiffrement de bout en bout uniquement lorsque plusieurs conversations sont sélectionnées" + "description": "Empêche l'envoi de messages chiffrés aux personnes qui n'ont pas de chiffrement de bout en bout activé uniquement lorsque plusieurs conversations sont sélectionnées" } } }, "add_friend_source_spoof": { - "name": "Falsifier la source d'ajout d'amis", - "description": "Falsifie la source d'une demande d'ami" + "description": "Falsifie la source d'une demande d'ami", + "name": "Changer la source des demandes d'amis" }, "hidden_snapchat_plus_features": { - "name": "Fonctionnalités Snapchat Plus masquées", - "description": "Active les fonctionnalités Snapchat Plus non publiées/bêta\nPeut ne pas fonctionner sur les anciennes versions de Snapchat" + "name": "Fonctionnalités Snapchat Plus cachées", + "description": "Active les fonctionnalités non publiées/beta de Snapchat Plus\nPeut ne pas fonctionner sur les anciennes versions de Snapchat" }, - "custom_streaks_expiration_format": { - "name": "Format d'expiration des séries personnalisé", - "description": "Personnalise le format d'expiration des séries\n\nVariables disponibles :\n - %c : Nombre de séries\n - %e : Emoji de sablier\n - %d : Jours\n - %h : Heures\n - %m : Minutes\n - %s : Secondes\n - %w : Temps restant" + "meo_passcode_bypass": { + "description": "Contourner le code d'accès My Eyes Only\nCela ne fonctionnera que si le code d'accès a été saisi correctement auparavant", + "name": "Contournement du code d'accès de My Eyes Only" }, "prevent_forced_logout": { "name": "Empêcher la déconnexion forcée", "description": "Empêche Snapchat de vous déconnecter lorsque vous vous connectez sur un autre appareil" }, + "convert_message_locally": { + "description": "Convertit localement les Snaps en médias externes dans le chat. Ceci apparaît dans le menu contextuel de téléchargement du chat", + "name": "Convertir le message localement" + }, + "story_logger": { + "description": "Fournit un historique des Stories d'amis", + "name": "Journal des Stories" + }, + "media_file_picker": { + "name": "Sélecteur de fichiers multimédias", + "description": "Vous permet de choisir n'importe quel fichier vidéo/audio dans la galerie" + }, + "call_recorder": { + "name": "Enregistreur d'appel", + "description": "Enregistre automatiquement les appels audio" + }, + "account_switcher": { + "name": "Changeur de compte", + "description": "Vous permet de passer d'un compte à un autre sans vous déconnecter\nAppuyez longuement sur l'icône de recherche à côté de votre profil Bitmoji pour ouvrir le menu\nRemarque : cette fonctionnalité est expérimentale et risque de changer à l'avenir", + "properties": { + "auto_backup_current_account": { + "name": "Compte courant de sauvegarde automatique", + "description": "Sauvegarde automatiquement le compte actuel lors de la déconnexion ou du changement de compte" + } + } + }, + "edit_message": { + "name": "Modifier les messages", + "description": "Vous permet de modifier les messages dans les conversations" + }, + "app_lock": { + "properties": { + "lock_on_resume": { + "description": "Verrouille l'application lors de sa réouverture", + "name": "Verrouiller à la reprise" + } + }, + "name": "Verrou d'application", + "description": "Empêche l'accès à Snapchat sans mot de passe" + }, + "custom_streaks_expiration_format": { + "name": "Format personnalisé d'expiration des flammes", + "description": "Personnalise le format d'expiration des flammes\n\nVariables disponibles :\n- %c : Nombre de flammes\n- %e : Emoji sablier\n- %d : Jours\n- %h : Heures\n- %m : Minutes\n- %s : Secondes\n- %w : Temps restant" + }, + "best_friend_pinning": { + "name": "Épinglage du meilleur ami", + "description": "Permet d'épingler un ami comme votre meilleur ami numéro un. Remarque : vous êtes le seul à pouvoir voir votre meilleur ami épinglé" + }, + "cof_experiments": { + "name": "Expériences COF", + "description": "Active les fonctionnalités Snapchat inédites/bêta" + }, + "context_menu_fix": { + "name": "Correction du menu contextuel", + "description": "Essayez de réparer le menu Liste d'amie, car lorsque l'appareil est hors ligne, il ne peut pas être affiché correctement" + }, + "better_transcript": { + "properties": { + "force_transcription": { + "description": "Permet de transcrire toutes les notes vocales", + "name": "Forcer la transcription des notes vocales" + }, + "enhanced_transcript": { + "name": "Transcription améliorée", + "description": "Améliore la transcription des notes vocales à l'aide de DeepL.\nAvant d'utiliser cette fonctionnalité, assurez-vous d'avoir lu leur politique de confidentialité." + }, + "preferred_transcription_lang": { + "name": "Langue de transcription préférée", + "description": "La langue préférée pour la transcription des notes vocales (par exemple EN, ES, FR)" + }, + "enhanced_transcript_in_notifications": { + "name": "Transcription améliorée dans les notifications", + "description": "Transcrit les notes vocales dans les notifications à l'aide de DeepL. Cela nécessite que la fonctionnalité Aperçu du chat soit activée dans Meilleur Notifications" + } + }, + "name": "Meilleure transcription", + "description": "Améliore la transcription des notes vocales" + }, + "voice_note_auto_play": { + "name": "Lecture automatique des notes vocales", + "description": "Joue automatiquement la note vocale suivante une fois la note actuelle terminée" + }, + "friend_notes": { + "description": "Vous permet d'ajouter des notes aux profils d'amis", + "name": "Notes d'ami" + }, "snapscore_changes": { - "name": "Modifications du Snapscore", - "description": "Suit les modifications du Snapscore des amis\nN'utilisez cette fonctionnalité que sur les versions plus récentes de Snapchat" + "name": "Modifications de Snapscore", + "description": "Suivi des changements dans le Snapscore des amis\nUtilisez cette fonctionnalité uniquement dans les versions plus récentes de Snapchat" } } }, "scripting": { - "name": "Script", - "description": "Exécuter des scripts personnalisés pour étendre PurrfectSnap", + "name": "Scripting", + "description": "Exécuter des scripts personnalisés pour étendre SnapEnhance", "properties": { "developer_mode": { - "name": "Mode développeur", + "name": "Mode Développeur", "description": "Affiche les informations de débogage sur l'interface utilisateur de Snapchat" }, "module_folder": { - "name": "Dossier du module", + "name": "Dossier des modules", "description": "Le dossier où se trouvent les scripts" }, - "auto_reload": { - "name": "Rechargement automatique", - "description": "Recharge automatiquement les scripts lorsqu'ils changent" - }, "integrated_ui": { "name": "Interface utilisateur intégrée", "description": "Permet aux scripts d'ajouter des composants d'interface utilisateur personnalisés à Snapchat" }, "disable_log_anonymization": { - "name": "Désactiver l'anonymisation des journaux", - "description": "Désactive l'anonymisation des journaux" + "description": "Désactive l'anonymisation des journaux", + "name": "Désactiver l'anonymisation des journaux" }, - "disable_optimization": { - "name": "Désactiver l'optimisation", - "description": "Désactive l'optimisation des scripts. Cela peut entraîner des problèmes de performances." + "auto_reload": { + "description": "Recharge automatiquement les scripts lorsqu'ils sont modifiés", + "name": "Rechargement automatique" } } }, "friend_tracker": { - "name": "Suivi d'amis", - "description": "Enregistre l'activité des amis sur Snapchat", "properties": { "record_messaging_events": { "name": "Enregistrer les événements de messagerie", @@ -1506,44 +1129,46 @@ }, "allow_running_in_background": { "name": "Autoriser l'exécution en arrière-plan", - "description": "Permet au suivi de s'exécuter en arrière-plan. Remarque : Cela videra considérablement votre batterie" + "description": "Permet au traqueur de fonctionner en arrière-plan. Remarque : cette fonction entraînera une consommation importante de la batterie" }, "auto_purge": { "name": "Purge automatique", "description": "Supprime automatiquement les événements mis en cache qui sont plus anciens que la durée spécifiée" } - } + }, + "name": "Traqueur d'amis", + "description": "Enregistre l'activité d'un ami sur Snapchat" } }, "options": { "app_appearance": { - "always_light": "Toujours clair", - "always_dark": "Toujours sombre" + "always_light": "Toujours Clair", + "always_dark": "Toujours Sombre" }, "friend_feed_menu_buttons": { "auto_download": "⬇️ Téléchargement automatique", - "auto_save": "💬 Enregistrer automatiquement les messages", + "auto_save": "💬 Enregistrement automatique des messages", + "stealth": "👻 Mode incognito", + "conversation_info": "👤 Infos de la Conversation", + "e2e_encryption": "🔒 Utiliser le chiffrement de bout en bout", + "mark_stories_as_seen_locally": "👀 Marquer localement les Stories comme vues", + "mark_snaps_as_seen": "👀 Marquer les snaps comme vu", "unsaveable_messages": "⬇️ Messages non enregistrables", - "auto_open_snaps": "📸 Ouvrir automatiquement les Snaps", - "stealth": "👻 Mode furtif", - "mark_snaps_as_seen": "👀 Marquer les Snaps comme vus", - "mark_stories_as_seen_locally": "👀 Marquer les histoires comme vues localement", - "conversation_info": "🧑‍🤝‍🧑 Informations sur la conversation", - "e2e_encryption": "🔒 Utiliser le chiffrement E2E" + "auto_open_snaps": "📷 Ouverture automatique des Snaps" }, "path_format": { - "create_author_folder": "Créer un dossier pour chaque auteur", - "create_source_folder": "Créer un dossier pour chaque type de source de média", - "append_hash": "Ajouter un hachage unique au nom du fichier", + "create_author_folder": "Créer un dossier pour chaque utilisateur", + "create_source_folder": "Créer un dossier pour chaque type de média", + "append_hash": "Ajouter une empreinte unique au nom du fichier", "append_source": "Ajouter la source du média au nom du fichier", "append_username": "Ajouter le nom d'utilisateur au nom du fichier", - "append_date_time": "Ajouter la date et l'heure au nom du fichier" + "append_date_time": "Ajouter la date ainsi que l'heure au nom du fichier" }, "auto_download_sources": { - "friend_snaps": "Snaps d'amis", - "friend_stories": "Histoires d'amis", - "public_stories": "Histoires publiques", - "spotlight": "Mettre en lumière" + "friend_snaps": "Snaps des amis", + "friend_stories": "Stories des amis", + "public_stories": "Stories publiques", + "spotlight": "Spotlight" }, "logging": { "started": "Démarré", @@ -1553,470 +1178,543 @@ }, "notifications": { "chat_screenshot": "Capture d'écran", - "chat_screen_record": "Enregistrement d'écran", - "snap_replay": "Relecture du Snap", - "camera_roll_save": "Enregistrer dans la pellicule", + "chat_screen_record": "Enregistrement vidéo de l'écran", + "snap_replay": "Revisionnage du Snap", + "camera_roll_save": "Sauvegarde de la pellicule", "chat": "Discussion", - "chat_reply": "Réponse à la discussion", - "snap": "Instantané", - "typing": "En train d'écrire", - "stories": "Histoires", - "speaking": "En train de parler", - "chat_reaction": "Réaction DM", - "group_chat_reaction": "Réaction de groupe", + "chat_reply": "Répondre", + "snap": "Snap", + "typing": "Saisie en cours", + "stories": "Stories", + "chat_reaction": "Réaction du MP", + "group_chat_reaction": "Réaction du groupe", "initiate_audio": "Appel audio entrant", "abandon_audio": "Appel audio manqué", "initiate_video": "Appel vidéo entrant", "abandon_video": "Appel vidéo manqué", - "map_live_location": "Emplacement en direct sur la carte" + "speaking": "En train de parler" }, "gallery_media_send_override": { - "always_ask": "Toujours demander", - "ORIGINAL": "Média original", - "NOTE": "Note audio", - "SNAP": "Instantané", + "ORIGINAL": "Media Originale", + "NOTE": "Vocal", + "SNAP": "Snap", + "always_ask": "Demandez toujours", "SAVEABLE_SNAP": "Snap enregistrable" }, + "auto_reload": { + "snapchat_only": "Snapchat uniquement", + "all": "Tous (Snapchat + SnapEnhance)" + }, "strip_media_metadata": { - "hide_caption_text": "Masquer le texte de la légende", - "hide_snap_filters": "Masquer les filtres Snap", - "hide_extras": "Masquer les extras (par exemple, les mentions)", - "remove_audio_note_duration": "Supprimer la durée de la note audio", - "remove_audio_note_transcript_capability": "Supprimer la capacité de transcription de la note audio" + "remove_audio_note_duration": "Supprimer la durée des vocaux", + "remove_audio_note_transcript_capability": "Supprimer la capacité de transcription des vocaux", + "hide_extras": "Cacher les autres informations (ex : les mentions)", + "hide_caption_text": "Cacher le texte des légendes", + "hide_snap_filters": "Cacher les filtres des Snaps" }, - "hide_ui_components": { - "hide_profile_call_buttons": "Supprimer les boutons d'appel du profil", - "hide_chat_call_buttons": "Supprimer les boutons d'appel de la discussion", - "hide_live_location_share_button": "Supprimer le bouton de partage de l'emplacement en direct", - "hide_stickers_button": "Supprimer le bouton des autocollants", - "hide_voice_record_button": "Supprimer le bouton d'enregistrement vocal", - "hide_unread_chat_hint": "Supprimer l'indice de discussion non lue", - "hide_post_to_story_buttons": "Supprimer les boutons de publication dans l'histoire avant d'envoyer un Snap", - "hide_billboard_prompt": "Supprimer l'invite du panneau d'affichage dans le fil d'amis", - "hide_snapchat_plus_gift_reminders": "Supprimer les rappels de cadeaux Snapchat Plus dans les conversations", - "hide_map_reactions": "Supprimer les réactions de la carte" + "bypass_video_length_restriction": { + "single": "Un seul média", + "split": "Division des médias" }, - "hide_story_suggestions": { - "hide_suggested_friend_stories": "Masquer les histoires d'amis suggérées", - "hide_my_stories": "Masquer mes histoires" + "auto_purge": { + "1_day": "1 jour", + "1_week": "1 semaine", + "1_month": "1 mois", + "2_weeks": "2 semaines", + "never": "Jamais", + "1_hour": "1 heure", + "3_hours": "3 heures", + "6_months": "6 mois", + "3_days": "3 jours", + "6_hours": "6 heures", + "3_months": "3 mois", + "12_hours": "12 heures" }, "home_tab": { "map": "Carte", - "chat": "Discussion", - "camera": "Appareil photo", - "discover": "Découvrir", - "spotlight": "Mettre en lumière" + "discover": "Découverte", + "spotlight": "Spotlight", + "camera": "Caméra", + "chat": "Chat" }, "add_friend_source_spoof": { - "added_by_username": "Par nom d'utilisateur", - "added_by_mention": "Par mention", - "added_by_group_chat": "Par discussion de groupe", - "added_by_qr_code": "Par code QR", "added_by_community": "Par communauté", + "added_by_mention": "Par mention", + "added_by_group_chat": "Par groupe de discussion", + "added_by_username": "Par nom d'utilisateur", + "added_by_qr_code": "Par QR Code", "added_by_quick_add": "Par ajout rapide (risque élevé d'être banni)" }, - "bypass_video_length_restriction": { - "single": "Média unique", - "split": "Média divisé" + "disable_confirmation_dialogs": { + "hide_conversation": "Cacher la conversation", + "clear_conversation": "Effacer la conversation du fil d'amis", + "remove_friend": "Supprimer l'ami", + "hide_friend": "Cacher l'ami", + "ignore_friend": "Ignorer l'ami", + "block_friend": "Bloquer l'ami", + "erase_message": "Effacer le message" + }, + "hide_ui_components": { + "hide_voice_record_button": "Supprimer le bouton d'enregistrement vocal", + "hide_unread_chat_hint": "Supprime l'indice de Chat non lu", + "hide_stickers_button": "Supprime le bouton des Stickers", + "hide_chat_call_buttons": "Supprimer les boutons d'appel dans le chat", + "hide_live_location_share_button": "Supprimer le bouton de partage de la localisation en direct", + "hide_profile_call_buttons": "Supprimer les boutons d'appel sur le profil", + "hide_post_to_story_buttons": "Supprimez les boutons Publier dans votre Story avant d'envoyer un Snap", + "hide_billboard_prompt": "Supprimer la fenêtre publicitaire dans le fil des amis", + "hide_snapchat_plus_gift_reminders": "Supprimer les rappels de cadeaux de Snapchat Plus dans les conversations", + "hide_map_reactions": "Supprimer les réactions de la carte" + }, + "edit_text_override": { + "bypass_text_input_limit": "Contourner la limite de saisie de texte", + "multi_line_chat_input": "Saisie multi-lignes" }, "old_bitmoji_selfie": { "2d": "Bitmoji 2D", "3d": "Bitmoji 3D" }, - "disable_confirmation_dialogs": { - "erase_message": "Effacer le message", - "remove_friend": "Supprimer un ami", - "block_friend": "Bloquer un ami", - "ignore_friend": "Ignorer un ami", - "hide_friend": "Masquer un ami", - "hide_conversation": "Masquer la conversation", - "clear_conversation": "Effacer la conversation du fil d'amis" - }, - "auto_reload": { - "snapchat_only": "Snapchat uniquement", - "all": "Tous (Snapchat + PurrfectSnap)" - }, - "edit_text_override": { - "multi_line_chat_input": "Saisie de discussion multiligne", - "bypass_text_input_limit": "Contourner la limite de saisie de texte" - }, - "auto_purge": { - "never": "Jamais", - "1_hour": "1 heure", - "3_hours": "3 heures", - "6_hours": "6 heures", - "12_hours": "12 heures", - "1_day": "1 jour", - "3_days": "3 jours", - "1_week": "1 semaine", - "2_weeks": "2 semaines", - "1_month": "1 mois", - "3_months": "3 mois", - "6_months": "6 mois" - }, "disable_story_sections": { + "discover": "Découverte", "friends": "Amis", - "suggested_stories": "Histoires suggérées", - "following": "Abonnements", - "discover": "Découvrir" + "following": "Suivis", + "suggested_stories": "Storys suggérées" + }, + "hide_story_suggestions": { + "hide_suggested_friend_stories": "Cacher les stories d'amis suggérées", + "hide_my_stories": "Cacher Ma Story" }, "disable_cameras": { - "front": "Appareil photo avant", - "back": "Appareil photo arrière" + "front": "Caméra Frontale", + "back": "Caméra arrière" }, "disable_permission_requests": { "notifications": "Notifications", - "read_media_images": "Lire les images des médias", - "read_media_video": "Lire la vidéo des médias", - "camera": "Appareil photo", - "microphone": "Microphone", + "microphone": "microphone", "location": "Emplacement", + "phone_calls": "Appels téléphoniques", + "read_media_images": "Lire des images médiatiques", + "read_media_video": "Lire la vidéo multimédia", + "camera": "Caméra", "read_contacts": "Lire les contacts", - "nearby_devices": "Appareils à proximité", - "phone_calls": "Appels téléphoniques" + "nearby_devices": "Appareils à proximité" }, "message_indicators": { - "encryption_indicator": "Ajoute une icône 🔒 à côté des messages qui vous ont été envoyés uniquement à vous", - "platform_indicator": "Ajoute l'icône de la plateforme à partir de laquelle un média a été envoyé (par exemple, Android, iOS, Web)", - "location_indicator": "Ajoute une icône 📍 aux snaps lorsqu'ils ont été envoyés avec l'emplacement activé", + "encryption_indicator": "Ajoute une icône 🔒 à côté des messages qui vous ont été envoyés uniquement", + "location_indicator": "Ajoute une icône 📍 aux clichés lorsqu'ils ont été envoyés avec la localisation activée", "ovf_editor_indicator": "Indique si un snap a été envoyé à l'aide de l'éditeur OVF", - "director_mode_indicator": "Ajoute une icône 🎬 aux snaps lorsqu'ils ont été envoyés en mode réalisateur, qui peut être utilisé pour envoyer des images de la galerie en tant que snaps" + "director_mode_indicator": "Ajoute une icône ✏️ aux clichés lorsqu'ils ont été envoyés en mode Directeur, qui peut être utilisée pour envoyer des images de la galerie sous forme de clichés", + "platform_indicator": "Ajoute l'icône de la plateforme à partir de laquelle un média a été envoyé (par exemple Android, iOS, Web)" }, "auto_mark_as_read": { "conversation_read": "Marquer la conversation comme lue lors de l'envoi d'un message", - "snap_reply": "Marquer les snaps comme lus lors de la réponse", - "save_snap_in_chat": "Marquer les snaps comme lus lors de leur enregistrement dans la discussion en mode furtif" + "snap_reply": "Marque les Snaps comme lus lorsqu'on y répond" }, "friend_mutation_notifier": { - "remove_friend": "Avertir lorsque quelqu'un vous supprime de ses amis", - "birthday_changes": "Avertir lorsque quelqu'un change sa date d'anniversaire", - "bitmoji_selfie_changes": "Avertir lorsque quelqu'un change son selfie Bitmoji", - "bitmoji_avatar_changes": "Avertir lorsque quelqu'un change son avatar Bitmoji", - "bitmoji_background_changes": "Avertir lorsque quelqu'un change son arrière-plan Bitmoji", - "bitmoji_scene_changes": "Avertir lorsque quelqu'un change sa scène Bitmoji" + "remove_friend": "Vous averti lorsque quelqu'un vous supprime en tant qu'ami", + "birthday_changes": "Vous averti lorsque quelqu'un change son anniversaire", + "bitmoji_selfie_changes": "Vous averti lorsque quelqu'un modifie son selfie Bitmoji", + "bitmoji_avatar_changes": "Vous averti lorsque quelqu'un change son avatar Bitmoji", + "bitmoji_background_changes": "Vous averti lorsque quelqu'un modifie son arrière-plan Bitmoji", + "bitmoji_scene_changes": "Vous averti lorsque quelqu'un change sa scène Bitmoji" + }, + "custom_theme": { + "amoled_dark_mode": "Mode sombre Amoled", + "custom": "Thèmes personnalisés (utilisez les actions rapides pour gérer les thèmes)", + "material_you_light": "Material You Light (Android 12+)", + "material_you_dark": "Materiel You Light (Android 12+)" }, "snapchat_plus": { "not_subscribed": "Non abonné", "basic": "Basique", "ad_free": "Sans publicité" }, + "simple_snapchat": { + "always_enabled": "Toujours activé", + "always_disabled": "Toujours désactivé" + }, "double_tap_chat_action": { - "like_message": "Aimer le message", + "like_message": "Aime le message", + "mark_as_read": "Marquer comme lu", "copy_text": "Copier le texte dans le presse-papiers", "delete_message": "Supprimer le message", - "mark_as_read": "Marquer comme lu", - "custom_emoji_reaction": "Réaction d'emoji personnalisée" + "custom_emoji_reaction": "Réaction Emoji personnalisée" }, "startup_default_camera": { - "front": "Appareil photo avant", - "back": "Appareil photo arrière" + "front": "Caméra frontale", + "back": "Caméra arrière" } } }, "friend_menu_option": { - "mark_snaps_as_seen": "Marquer les Snaps comme vus", - "mark_stories_as_seen_locally": "Marquer les histoires comme vues localement", "preview": "Aperçu", "stealth_mode": "Mode furtif", - "auto_download_blacklist": "Liste noire de téléchargement automatique", - "anti_auto_save": "Anti-enregistrement automatique" - }, - "content_type": { - "CHAT": "Discussion", - "SNAP": "Instantané", - "EXTERNAL_MEDIA": "Média externe", - "NOTE": "Note audio", - "STICKER": "Autocollant", - "SHARE": "Partager", - "STATUS": "Statut", - "LOCATION": "Emplacement", - "STATUS_SAVE_TO_CAMERA_ROLL": "Enregistré dans la pellicule", - "STATUS_CONVERSATION_CAPTURE_SCREENSHOT": "Capture d'écran", - "STATUS_CONVERSATION_CAPTURE_RECORD": "Enregistrement d'écran", - "STATUS_CALL_MISSED_VIDEO": "Appel vidéo manqué", - "STATUS_CALL_MISSED_AUDIO": "Appel audio manqué", - "LIVE_LOCATION_SHARE": "Partager l'emplacement en direct", - "CREATIVE_TOOL_ITEM": "Élément d'outil créatif", - "FAMILY_CENTER_INVITE": "Invitation au centre familial", - "FAMILY_CENTER_ACCEPT": "Accepter le centre familial", - "FAMILY_CENTER_LEAVE": "Quitter le centre familial", - "STATUS_PLUS_GIFT": "Cadeau Status Plus", - "TINY_SNAP": "Petit Snap", - "STATUS_COUNTDOWN": "Compte à rebours", - "MAP_REACTION": "Réaction de la carte" - }, - "media_download_source": { - "none": "Aucun", - "pending": "En attente", - "chat_media": "Média de discussion", - "story": "Histoire", - "public_story": "Histoire publique", - "spotlight": "Mettre en lumière", - "profile_picture": "Photo de profil", - "story_logger": "Journal des histoires", - "message_logger": "Journal des messages", - "merged": "Fusionné", - "voice_call": "Appel vocal" + "auto_download_blacklist": "Liste noire des téléchargements automatiques", + "anti_auto_save": "Empêcher l'enregistrement automatique", + "mark_snaps_as_seen": "Marquer les Snaps comme vu", + "mark_stories_as_seen_locally": "Marquer localement les Stories comme vues" }, "chat_action_menu": { "preview_button": "Aperçu", "download_button": "Télécharger", "delete_logged_message_button": "Supprimer le message enregistré", - "show_chat_edit_history": "Afficher l'historique des modifications de la discussion", - "convert_message": "Convertir le message" + "convert_message": "Convertir le message", + "edit_message": "Modifier le message", + "show_chat_edit_history": "Afficher l'historique des modifications du chat" }, "opera_context_menu": { - "download": "Télécharger le média", - "sent_at": "Envoyé le {date}", - "created_at": "Créé le {date}", + "download": "Télécharger les médias", + "media_duration": "Durée du média : {duration} ms", + "show_debug_info": "Afficher les informations de débogage", "expires_at": "Expire le {date}", - "media_size": "Taille du média : {size}", - "media_duration": "Durée du média : {duration} ms", - "show_debug_info": "Afficher les informations de débogage" + "created_at": "Créé le {date}", + "sent_at": "Envoyé le {date}", + "media_size": "Taille du média : {size}" }, "modal_option": { - "profile_info": "Informations sur le profil", + "profile_info": "Informations du profil", "close": "Fermer" }, "gallery_media_send_override": { "multiple_media_toast": "Vous ne pouvez envoyer qu'un seul média à la fois" }, - "mark_as_seen": { - "no_unseen_snaps_toast": "Aucun Snap non vu trouvé !", - "seen_toast": "Marqué comme vu !", - "unseen_toast": "Marqué comme non vu !", - "already_seen_toast": "Déjà marqué comme vu !", - "already_unseen_toast": "Déjà marqué comme non vu !" - }, "conversation_preview": { - "streak_expiration": "expire dans {day} jours {hour} heures {minute} minutes", - "total_messages": "Total des messages envoyés/reçus : {count}", + "streak_expiration": "expire dans {day} jour(s) {hour} heure(s) {minute} minute(s)", + "total_messages": "Total des messages envoyés/reçus : {count}", "title": "Aperçu", "unknown_user": "Utilisateur inconnu", - "no_messages": "Aucun message trouvé !" + "no_messages": "Aucun message trouvé !" }, "profile_info": { - "title": "Informations sur le profil", - "first_created_username": "Premier nom d'utilisateur créé", - "mutable_username": "Nom d'utilisateur modifiable", + "title": "Informations du profil", "display_name": "Nom d'affichage", "added_date": "Date d'ajout", - "birthday": "Anniversaire : {day} {month}", - "hidden_birthday": "Anniversaire : Masqué", - "friendship": "Amitié", - "add_source": "Ajouter une source", - "snapchat_plus": "SnapchatPlus", + "birthday": "Anniversaire : {day} {month}", "snapchat_plus_state": { "subscribed": "Abonné", "not_subscribed": "Non abonné" - } - }, - "friendship_link_type": { - "mutual": "Mutuel", - "outgoing": "Sortant", - "blocked": "Bloqué", - "deleted": "Supprimé", - "following": "Abonnement", - "suggested": "Suggéré", - "incoming": "Entrant", - "incoming_follower": "Abonné entrant" - }, - "bulk_messaging_action": { - "choose_action_title": "Choisir une action", - "progress_status": "Traitement de {index} sur {total}", - "selection_dialog_continue_button": "Continuer", - "confirmation_dialog": { - "title": "Êtes-vous sûr ?", - "message": "Cela affectera tous les amis sélectionnés. Cette action ne peut pas être annulée." }, - "actions": { - "remove_friends": "Supprimer des amis", - "clear_conversations": "Effacer les conversations" - } + "friendship": "Amitié", + "hidden_birthday": "Anniversaire : Caché", + "snapchat_plus": "Snapchat Plus", + "add_source": "Source d'ajout", + "first_created_username": "Premier nom d'utilisateur créé", + "mutable_username": "Nom d'utilisateur modifiable" }, "chat_export": { - "exporter_dialog": { - "select_conversations_title": "Sélectionner les conversations", - "text_field_selection": "{amount} sélectionnés", - "text_field_selection_all": "Tous", - "export_file_format_title": "Exporter le format de fichier", - "message_type_filter_title": "Filtrer les messages par type", - "amount_of_messages_title": "Nombre de messages (laisser vide pour tous)", - "download_medias_title": "Télécharger les médias" - }, "dialog_negative_button": "Annuler", "dialog_positive_button": "Exporter", "exported_to": "Exporté vers {path}", - "exporting_chats": "Exportation des discussions...", + "exporting_chats": "Exportation des chats...", "processing_chats": "Traitement de {amount} conversations...", - "export_fail": "Échec de l'exportation de la conversation {conversation}", - "writing_output": "Écriture de la sortie...", - "finished": "Terminé ! Vous pouvez maintenant fermer cette boîte de dialogue.", - "no_messages_found": "Aucun message trouvé !", - "exporting_message": "Exportation de {conversation}..." + "export_fail": "Échec de l'export de la conversation {conversation}", + "writing_output": "Écriture...", + "finished": "Terminé ! Vous pouvez maintenant fermer cette fenêtre.", + "no_messages_found": "Aucun message trouvé !", + "exporting_message": "Exportation de {conversation}...", + "exporter_dialog": { + "text_field_selection_all": "Tout", + "export_file_format_title": "Format du fichier exporté", + "download_medias_title": "Télécharger les médias", + "amount_of_messages_title": "Nombre de messages (laissez vide pour tous les messages)", + "message_type_filter_title": "Filtrer les messages par type", + "text_field_selection": "{amount} sélectionné(s)", + "select_conversations_title": "Sélectionner les conversations" + } }, "button": { - "ok": "D'ACCORD", + "ok": "Ok", "positive": "Oui", "negative": "Non", "cancel": "Annuler", "open": "Ouvrir", "download": "Télécharger", - "send": "Envoyer", - "restore_original": "Restaurer l'original", - "convert_external_media": "Convertir un média externe", - "save": "Enregistrer" - }, - "tracker_events": { - "conversation_enter": "Entrée dans la conversation", - "conversation_exit": "Sortie de la conversation", - "started_typing": "A commencé à écrire", - "stopped_typing": "A arrêté d'écrire", - "started_speaking": "A commencé à parler", - "stopped_speaking": "A arrêté de parler", - "started_peeking": "A commencé à jeter un coup d'œil", - "stopped_peeking": "A arrêté de jeter un coup d'œil", - "message_read": "Message lu", - "message_deleted": "Message supprimé", - "message_saved": "Message enregistré", - "message_unsaved": "Message non enregistré", - "message_edited": "Message modifié", - "message_reaction_add": "Ajouter une réaction au message", - "message_reaction_remove": "Supprimer la réaction du message", - "snap_opened": "Snap ouvert", - "snap_replayed": "Snap rejoué", - "snap_replayed_twice": "Snap rejoué deux fois", - "snap_screenshot": "Capture d'écran du Snap", - "snap_screen_record": "Enregistrement d'écran du Snap" - }, - "tracker_actions": { - "log": "Journal", - "in_app_notification": "Notification dans l'application", - "push_notification": "Notification push", - "custom": "Personnalisé" - }, - "better_notifications": { - "button": { - "reply": "Répondre", - "download": "Télécharger", - "mark_as_read": "Marquer comme lu" - } + "send": "Envoyer" }, "profile_picture_downloader": { - "button": "Télécharger la photo de profil", + "button": "Télécharger les photos de profil", "title": "Téléchargeur de photos de profil", "avatar_option": "Avatar", "background_option": "Arrière-plan" }, - "call_start_confirmation": { - "dialog_title": "Démarrer l'appel", - "dialog_message": "Êtes-vous sûr de vouloir démarrer un appel ?" - }, - "half_swipe_notifier": { - "notification_channel_name": "Balayage à moitié", - "notification_content_dm": "{friend} vient de balayer à moitié dans votre discussion pendant {duration} secondes", - "notification_content_group": "{friend} vient de balayer à moitié dans {group} pendant {duration} secondes" - }, "download_processor": { "attachment_type": { - "snap": "Instantané", + "snap": "Snap", "sticker": "Autocollant", - "gif": "GIF", "external_media": "Média externe", "note": "Note", - "original_story": "Histoire originale" + "original_story": "Storie originale", + "gif": "GIF" }, - "select_attachments_title": "Sélectionner les pièces jointes", + "select_attachments_title": "Sélectionnez les pièces jointes", "download_started_toast": "Téléchargement démarré", - "unsupported_content_type_toast": "Type de contenu non pris en charge !", + "unsupported_content_type_toast": "Type de contenu non supporté !", "failed_no_longer_available_toast": "Média plus disponible", - "no_attachments_toast": "Aucune pièce jointe trouvée !", - "already_queued_toast": "Média déjà dans la file d'attente !", - "already_downloaded_toast": "Média déjà téléchargé !", - "content_saved_toast": "Enregistré !", - "download_toast": "Téléchargement de {path}...", + "no_attachments_toast": "Aucune pièce jointe trouvée !", + "already_queued_toast": "Média déjà en file d'attente !", + "already_downloaded_toast": "Média déjà téléchargé !", + "download_toast": "Téléchargement {path}...", "processing_toast": "Traitement de {path}...", "failed_generic_toast": "Échec du téléchargement", - "failed_to_create_preview_toast": "Échec de la création de l'aperçu", + "failed_to_create_preview_toast": "Échec de création de l'aperçu", "failed_processing_toast": "Échec du traitement {error}", "failed_gallery_toast": "Échec de l'enregistrement dans la galerie {error}", - "dash_no_chapter": "Aucun chapitre trouvé", "dash_dialog": { - "title": "Télécharger le média dash", "download_all": "Tout télécharger", + "title": "Télécharger le média Dash", "segment_text": "Segment {from} - {to}" - } + }, + "dash_no_chapter": "Aucun chapitre trouvé", + "content_saved_toast": "Sauvegarder!" }, "streaks_reminder": { - "notification_title": "Séries", - "notification_text": "Vous perdrez votre série avec {friend} dans {hoursLeft} heures" + "notification_title": "Rappels des flammes", + "notification_text": "Vous perdrez vos flammes avec {friend} dans {hoursLeft} heure(s)" }, - "biometric_auth": { - "unlock_button": "Déverrouiller", - "title": "Déverrouiller Snapchat", - "subtitle": "Veuillez vous authentifier pour déverrouiller Snapchat" + "content_type": { + "FAMILY_CENTER_INVITE": "Invitation Family Center", + "STATUS_CONVERSATION_CAPTURE_RECORD": "Enregistrement d'écran", + "STATUS_CALL_MISSED_VIDEO": "Appel vidéo manqué", + "CREATIVE_TOOL_ITEM": "Item de Creative Tool", + "STICKER": "Autocollant", + "TINY_SNAP": "Mini Snap", + "STATUS_SAVE_TO_CAMERA_ROLL": "Sauvegardé dans la galerie", + "EXTERNAL_MEDIA": "Média externe", + "SNAP": "Snap", + "LOCATION": "Localisation", + "CHAT": "Message Textuel", + "STATUS_PLUS_GIFT": "Cadeau Snapchat Plus", + "STATUS_COUNTDOWN": "Compte à rebours", + "LIVE_LOCATION_SHARE": "Partage d'emplacement en direct", + "STATUS": "Statut", + "STATUS_CONVERSATION_CAPTURE_SCREENSHOT": "Capture d'écran", + "FAMILY_CENTER_ACCEPT": "Acceptation Family Center", + "FAMILY_CENTER_LEAVE": "A quitté Family Center", + "STATUS_CALL_MISSED_AUDIO": "Appel audio manqué", + "NOTE": "Vocal", + "MAP_REACTION": "Réaction de la carte", + "SHARE": "Partager" + }, + "media_download_source": { + "public_story": "Story Publique", + "spotlight": "Spotlight", + "pending": "En cours", + "merged": "Fusionné", + "story_logger": "Journal des stories", + "none": "Aucun", + "profile_picture": "Photo de profil", + "story": "Story", + "chat_media": "Média de Chat", + "voice_call": "Appel vocal", + "message_logger": "Enregistreur de messages" + }, + "material3_strings": { + "date_input_invalid_not_allowed": "Date invalide", + "date_range_input_invalid_range_input": "Plage de dates non valide", + "date_range_picker_scroll_to_previous_month": "Mois précédent", + "date_picker_switch_to_input_mode": "Entrée", + "date_range_picker_day_in_range": "Séléctionné", + "date_input_invalid_for_pattern": "Date invalide", + "date_picker_today_description": "Aujourd'hui", + "date_picker_switch_to_calendar_mode": "Calendrier", + "date_range_picker_start_headline": "Depuis", + "date_range_picker_end_headline": "Jusqu'à", + "date_range_picker_scroll_to_next_month": "Mois suivant", + "date_range_picker_title": "Sélectionner une plage de dates", + "date_input_invalid_year_range": "Année invalide" + }, + "better_notifications": { + "button": { + "download": "Télécharger", + "reply": "Répondre", + "mark_as_read": "Marquer comme lu" + } + }, + "half_swipe_notifier": { + "notification_content_group": "{friend} a entrouvert dans {group} pendant {duration} seconde(s)", + "notification_channel_name": "Entrouverts", + "notification_content_dm": "{friend} a entrouvert votre discussion pendant {duration} seconde(s)" + }, + "friendship_link_type": { + "mutual": "Mutuel", + "deleted": "Supprimé", + "following": "Suivi", + "incoming_follower": "Follower entrant", + "incoming": "Entrant", + "blocked": "Bloqué", + "suggested": "Suggéré", + "outgoing": "Sortant" + }, + "call_start_confirmation": { + "dialog_message": "Êtes-vous sûr de vouloir lancer un appel ?", + "dialog_title": "Démarrer un appel" + }, + "bulk_messaging_action": { + "choose_action_title": "Choisir une action", + "progress_status": "Traitement de {index} sur {total}", + "actions": { + "clear_conversations": "Nettoyer des conversations", + "remove_friends": "Supprimer des amis" + }, + "selection_dialog_continue_button": "Continuer", + "confirmation_dialog": { + "message": "Cette action affectera tous les amis sélectionnés. Cette action ne peut pas être annulée.", + "title": "Êtes-vous sûr ?" + } + }, + "actions": { + "clean_snapchat_cache": { + "name": "Nettoyer le cache Snapchat", + "description": "Nettoie le cache de Snapchat" + }, + "manage_friend_list": { + "name": "Gérer la liste d'amis", + "description": "Importez/exportez votre liste d'amis lors de la sauvegarde" + }, + "export_chat_messages": { + "name": "Exporter les messages de discussion", + "description": "Exporte les messages de conversation dans un fichier JSON/HTML/TXT" + }, + "export_memories": { + "name": "Exporter des souvenirs", + "description": "Exporter les souvenirs dans un fichier ZIP" + }, + "bulk_messaging_action": { + "description": "Effectue des opérations telles que la suppression d'amis ou la suppression en masse de conversations", + "name": "Action de messagerie en masse" + }, + "change_language": { + "name": "Changer la langue", + "description": "Changer la langue de SnapEnhance" + }, + "regen_mappings": { + "name": "Régénérer les mappages", + "description": "Régénérer manuellement les mappages" + }, + "file_imports": { + "name": "Imports de fichiers", + "description": "Importer des fichiers pour les utiliser dans Snapchat" + }, + "logger_history": { + "description": "Consulter l'historique des messages enregistrés", + "name": "Historique du logger" + }, + "friend_tracker": { + "name": "Traqueur d'amis", + "description": "Traquer vos amis sur Snapchat" + }, + "security_features": { + "name": "Fonctions de sécurité", + "description": "Modifier les préférences des fonctionnalités de sécurité" + }, + "theming": { + "name": "Thèmes", + "description": "Personnalisez l'apparence de Snapchat" + } + }, + "mark_as_seen": { + "no_unseen_snaps_toast": "Aucun Snap invisible trouvé !", + "seen_toast": "Marqué comme vu !", + "already_seen_toast": "Déjà marqué comme vu !", + "unseen_toast": "Marqué comme vu !", + "already_unseen_toast": "Déjà marqué comme invisible !" }, "end_to_end_encryption": { "toolbox": { - "no_shared_key": "Vous n'avez pas encore de secret partagé avec cet ami. Cliquez ci-dessous pour en créer un nouveau.", - "shared_key_fingerprint": "Votre empreinte digitale est :\n\n{fingerprint}\n\nAssurez-vous qu'elle correspond à l'empreinte digitale de votre ami !", + "no_shared_key": "Vous n'avez pas encore de secret partagé avec cet ami. Cliquez ci-dessous pour en lancer un nouveau.", + "shared_key_fingerprint": "Votre fingerprint est :\n\n{fingerprint}\n\nAssurez-vous de vérifier si cela correspond à la fingerprint de votre ami !", "initiate_exchange_button": "Lancer l'échange de clés" }, "confirmation_dialogs": { + "confirmation_1": "AVERTISSEMENT : Cela écrasera votre clé existante. Vous perdrez l'accès à tous les messages chiffrés de cet ami. Êtes-vous sûr de vouloir continuer ?", "title": "Chiffrement de bout en bout", - "confirmation_1": "AVERTISSEMENT : Cela écrasera votre clé existante. Vous perdrez l'accès à tous les messages chiffrés de cet ami. Êtes-vous sûr de vouloir continuer ?", - "confirmation_2": "Êtes-vous VRAIMENT sûr de vouloir continuer ? C'est votre dernière chance de vous rétracter." + "confirmation_2": "Êtes-vous VRAIMENT sûr de vouloir continuer ? C'est votre dernière chance de faire marche arrière." }, - "unencrypted_conversation_send_failure_toast": "Vous ne pouvez pas envoyer de contenu chiffré à des conversations à la fois chiffrées et non chiffrées !", - "native_hooks_send_failure_toast": "Échec de l'envoi ! Veuillez activer les hooks natifs dans les paramètres.", - "no_participants_to_encrypt_toast": "Vous n'avez aucun ami dans cette conversation avec qui chiffrer les messages !", - "encryption_failed_toast": "Échec du chiffrement du message ! Consultez logcat pour plus de détails.", - "accept_public_key_success_toast": "Clé publique acceptée avec succès !", - "accept_secret_key_success_toast": "Terminé ! Vous pouvez maintenant envoyer et recevoir des messages chiffrés avec cet ami.", + "unencrypted_conversation_send_failure_toast": "Vous ne pouvez pas envoyer de contenu chiffré à des conversations chiffrées et non chiffrées !", + "accept_public_key_success_toast": "Clé publique acceptée avec succès !", + "native_hooks_send_failure_toast": "Échec de l'envoi ! Veuillez activer les Hooks Natifs dans les paramètres.", + "accept_secret_key_success_toast": "Terminé ! Vous pouvez désormais envoyer et recevoir des messages chiffrés avec cet ami.", "accept_public_key_failure_toast": "Échec de l'acceptation de la clé publique", + "accept_secret_button": "Accepter la clé publique", + "no_participants_to_encrypt_toast": "Vous n'avez aucun ami dans cette conversation avec qui chiffrer les messages !", "accept_secret_key_failure_toast": "Échec de l'acceptation de la clé secrète", - "accept_secret_button": "Accepter le secret", + "encryption_failed_toast": "Échec de chiffrement du message ! Veuillez vérifier le logcat pour plus de détails.", "accept_public_key_button": "Accepter la clé publique", "outgoing_pk_message": "Demande d'échange de clés", "outgoing_secret_message": "Réponse d'échange de clés", "incoming_pk_message": "Vous venez de recevoir une demande de clé publique. Cliquez ci-dessous pour l'accepter.", "incoming_secret_message": "Votre ami vient d'accepter votre clé publique. Cliquez ci-dessous pour accepter le secret." }, + "scopes": { + "friend": "Ami", + "group": "Groupe" + }, + "biometric_auth": { + "title": "Débloquer Snapchat", + "subtitle": "Veuillez vous authentifier pour déverrouiller Snapchat", + "unlock_button": "Déverrouiller" + }, "auto_open_snaps": { - "title": "Ouvrir automatiquement les Snaps", - "notification_content": "{count} Snaps ouverts" + "notification_content": "{count} Snaps ouverts", + "title": "Auto-ouverture des Snaps" }, "friend_mutation_observer": { - "notification_channel_name": "Observateur de mutation d'amis", - "friend_removed": "{username} vous a supprimé de ses amis", - "birthday_removed": "{username} a supprimé sa date d'anniversaire ({birthday})", - "birthday_added": "{username} a ajouté sa date d'anniversaire ({birthday})", - "birthday_changed": "{username} a changé sa date d'anniversaire de {oldBirthday} à {newBirthday}", - "bitmoji_selfie_changed": "{username} a changé son selfie Bitmoji", + "notification_channel_name": "Observateur de mutation des amis", + "birthday_changed": "{username} a changé son anniversaire de {oldBirthday} à {newBirthday}", + "bitmoji_selfie_changed": "{username} a modifié son selfie Bitmoji", "bitmoji_avatar_changed": "{username} a changé son avatar Bitmoji", "bitmoji_background_changed": "{username} a changé son arrière-plan Bitmoji", + "friend_removed": "{username} vous a supprimé de sa liste d'amis", + "birthday_removed": "{username} a supprimé son anniversaire ({birthday})", + "birthday_added": "{username} a ajouté son anniversaire ({birthday})", "bitmoji_scene_changed": "{username} a changé sa scène Bitmoji" }, - "material3_strings": { - "date_range_picker_start_headline": "De", - "date_range_picker_end_headline": "À", - "date_range_picker_title": "Sélectionner une plage de dates", - "date_picker_switch_to_calendar_mode": "Calendrier", - "date_picker_switch_to_input_mode": "Saisie", - "date_range_picker_scroll_to_previous_month": "Mois précédent", - "date_range_picker_scroll_to_next_month": "Mois suivant", - "date_picker_today_description": "Aujourd'hui", - "date_range_picker_day_in_range": "Sélectionné", - "date_input_invalid_for_pattern": "Date non valide", - "date_input_invalid_year_range": "Année non valide", - "date_input_invalid_not_allowed": "Date non valide", - "date_range_input_invalid_range_input": "Plage de dates non valide" + "theming_attributes": { + "listBackgroundDrawable": "Liste de conversations", + "sigColorChatConversationsLine": "Couleur de la ligne de conversation", + "actionSheetBackgroundDrawable": "Couleur d’arrière-plan du menu d’action", + "actionSheetRoundedBackgroundDrawable": "Couleur d'arrière-plan ronde du menu d'action", + "sigColorIconPrimary": "Couleur d'arrière-plan ronde du menu d'action", + "sigExceptionColorCameraGridLines": "Couleur du quadrillage de la caméra", + "rangeFillColor": "Couleur de remplissage de plage", + "pstsIndicatorColor": "Couleur de l’indicateur PSTS", + "pstsTabBackground": "Arrière-plan de l'onglet PSTS", + "pstsDividerColor": "Couleur du séparateur PSTS", + "statusBarBackground": "Couleur d'arrière-plan de la barre d'état", + "strokeColor": "Couleur du trait", + "storyReplayViewRingColor": "Voir la rediffusion de l'histoire Couleur de la bague", + "sigColorButtonPrimary": "Couleur du bouton principal", + "sigColorBaseAppYellow": "Couleur jaune de l'application de base", + "sigColorBackgroundSurfaceTranslucent": "Couleur de la surface de fond translucide", + "sigColorStoryRingFriendsFeedStoryRing": "Bague d'histoire Flux d'amis Couleur de la bague d'histoire", + "sigColorStoryRingDiscoverTabThumbnailStoryRing": "Story Ring Onglet Découverte Vignette Story Ring Couleur", + "sigColorTextPrimary": "Couleur du texte principal", + "sigColorChatChat": "Couleur du texte du flux d'amis principal", + "sigColorBackgroundSurface": "Couleur de la surface d'arrière-plan", + "sigColorChatPendingSending": "Couleur du texte du fil d’ami secondaire", + "sigColorChatSnapWithSound": "Snaps avec la couleur du texte sonore", + "sigColorChatSnapWithoutSound": "Snaps sans couleur de texte sonore", + "actionSheetDescriptionTextColor": "Action Menu Description Couleur du texte", + "sigColorBackgroundMain": "Couleur de l'arrière plan", + "recipientPillBackgroundDrawable": "Fond de pilule du destinataire", + "boxBackgroundColor": "Couleur d'arrière-plan de la boîte", + "editTextColor": "Modifier la couleur du texte", + "chipBackgroundColor": "Couleur d'arrière-plan de la puce", + "listDivider": "Couleur du séparateur de liste", + "sigColorIconSecondary": "Couleur de l’icône secondaire", + "recipientInputStyle": "Style de saisie du destinataire", + "itemShapeFillColor": "Couleur de remplissage de la forme de l'élément", + "ringColor": "Couleur de la bague", + "ringStartColor": "Couleur de début de sonnerie", + "sigColorLayoutPlaceholder": "Couleur de l'espace réservé à la mise en page", + "scButtonColor": "Couleur du bouton Snapchat", + "tabTextColor": "Couleur du texte de l'onglet", + "statusBarForeground": "Couleur de premier plan de la barre d'état" }, "send_override_dialog": { - "title": "Envoyer le média en tant que {type}", - "duration": "Durée : {duration}", - "saveable_snap_hint": "Rendre le Snap enregistrable dans la discussion", + "title": "Envoyer des médias en tant que {type}", + "saveable_snap_hint": "Rendre Snap enregistrable dans le chat", + "duration": "Durée : {duration}", "unlimited_duration": "Illimité" - }, - "invalid_input_toast": "Saisie non valide ! Assurez-vous d'avoir saisi une valeur valide." -} \ No newline at end of file + } +} diff --git a/common/src/main/assets/lang/gsw.json b/common/src/main/assets/lang/gsw.json new file mode 100644 index 00000000..6dbafff3 --- /dev/null +++ b/common/src/main/assets/lang/gsw.json @@ -0,0 +1,441 @@ +{ + "features": { + "properties": { + "user_interface": { + "properties": { + "opera_media_quick_info": { + "description": "Zeigt nützlechi Informatione zu Medie wi Erschtelligsdatum im Opernbetrachter-Kontextmenü" + }, + "friend_feed_message_preview": { + "description": "Zeigt e Vorschou vo de letschte Nachrichte im Friend Feed" + } + } + }, + "messaging": { + "properties": { + "bypass_message_action_restrictions": { + "description": "Ermöglichts nechs ufne Snap z reagiere ohni ne göffnet zha, oder e nid speicherbari Nachricht z speichere" + }, + "auto_mark_as_read": { + "description": "Markiert automatisch Nachrichte/Snaps aus gläse, o we dr Steauth-Modus aktiviert isch" + } + } + }, + "global": { + "properties": { + "media_upload_quality": { + "properties": { + "force_video_upload_source_quality": { + "description": "Zwingt Snapchat, d Quellqualität bim Hochlade vo Videos z verwände\nBitte beachte, dass debi kei Metadate us Medie dörfe entfernt wärde." + } + } + }, + "disable_custom_tabs": { + "description": "Öffnet Links i unterstützte Awändige statt im Webrowser" + }, + "hide_active_music": { + "description": "Verhinderet, dass Snapchat merkt, dassd Musig losisch\nDas ermöglichts dir, Schnappschüss mit Lutstärcheregler-Taschte z'näh, während du Musig lose" + }, + "video_playback_rate_slider": { + "description": "Fügt e Schieberegler im Opera-Kontextmenü hinzue zum d Video-Wiedergabegschwindigkeit z ändere\nHiwiis: Änderige gälte nume für nachfolgende Videos" + } + } + }, + "experimental": { + "properties": { + "best_friend_pinning": { + "description": "Ermöglicht's Nech, e Fründ aus dine beschte Fründ Nummere eins anzheften. Hiwiis: Nume chasch din agheftete besti Fründ gseh." + }, + "e2ee": { + "properties": { + "force_message_encryption": { + "description": "Verhinderet ds Sände verschlüsselter Nachrichte a Persone wo d E2E Verschlüsselig nid aktiviert isch, nume we mehreri Ungerhautige usgwählt si" + } + }, + "description": "Verschlüsslet dini Nachrichte mit AES unger Verwändig vomene freigegebene gheime Schlüssel\nAchte druf, dass din Schlüssel amene sichere Ort ufbewahre!" + }, + "native_hooks": { + "properties": { + "composer_hooks": { + "properties": { + "show_first_created_username": { + "description": "Zeigt dr erschtellti Benutzername näbem aktuelle Benutzername ir Profilsiite a" + } + } + } + } + }, + "convert_message_locally": { + "description": "Konvertiert Snaps um externi Medie lokal z'chatte. Das wird im Kontextmenü zum Abelade vom Chat azeigt." + }, + "account_switcher": { + "description": "Ermöglichts ne zwüsche kontene z wechsle ohni sech abzmelde\nLang drücke uf ds Suchsymbol näb dim Bitmoji Profil zum ds Menü z öffne\nHiwiis: Die Funktion isch experimentell und wird sech wahrschinlech ir Zuekunft ändere." + }, + "custom_streaks_expiration_format": { + "description": "Passet ds Streaks Ablouf-Format a\n\nVerfüegbari Variable:\n – %c: Azahl der Streife\n – %e: Sanduhr-Emoji\n – %d: Tage\n – %h: Stunde\n – %m: Protokoll\n – %s: Sekunde\n – %w: Verbleibendi Zyt" + }, + "meo_passcode_bypass": { + "description": "Umghig vom My Eyes Only Passcode\nDas funktioniert nume we dr Passcode vor" + } + } + }, + "downloader": { + "properties": { + "opera_download_button": { + "description": "Fügt bim Betrachte vomene Snap e Download-Button obe rächts hinzue.\nLanges Drück uf Taschte wird ds Abelade erzwinge" + }, + "save_folder": { + "description": "Wähle s Verzeichnis wo alli Medie selled abeglade werde", + "name": "Speicherverzeichnis" + }, + "download_context_menu": { + "description": "Ermöglicht ds abeelade/Vorluege vo Nachrichte usere Ungerhautig oder ere Gschicht über ds Kontextmenü.\nLanges Drück uf Taschte wird ds Abelade erzwinge" + }, + "custom_path_format": { + "description": "Setzt e benutzzerdefinierti Kamerauflösig, Breiti x Höchi (z.B. 1920x1080).\nDi benutzzerdefinierti Uflösig mues unterstützt werde Geef e aapascht padformat op voor downloade media\n\nBeschikbari variable:\n – %username%\n – %source%\n – %hash%\n - %date_time% vo dim Gerät" + }, + "auto_download_sources": { + "description": "Wähl d'Quellä, vo dene automatisch abäzladä isch", + "name": "Quellä automatisch abäladä" + }, + "prevent_self_auto_download": { + "name": "Selbscht-Auto-Download verhinderä", + "description": "Verhinderät, dass dini eigenä Snaps automatisch abägladä wirdet" + }, + "allow_duplicate": { + "description": "Ermöglichts, dass diäselben Medien mehrmals abägladä wirdet", + "name": "Druplikat erlaubä" + }, + "merge_overlays": { + "name": "Overlays zsämmäfüährä", + "description": "Kombiniert dä Text und d'Mediä vo einem Snap i ei Datei" + }, + "path_format": { + "name": "Pfadformat", + "description": "Gibs Dateiformat a" + } + }, + "name": "Downloader", + "description": "Snapchat Mediä abäladä" + }, + "camera": { + "properties": { + "black_photos": { + "description": "Ersetzt ufgnommi Fötteli mit schwarzem Hintergrund\nVideos sy nid betroffe" + }, + "custom_resolution": { + "description": "Setzt e benutzzerdefinierti Kamerauflösig, Breiti x Höchi (z.B. 1920x1080).\nDi benutzzerdefinierti Uflösig mues vo dim Grät unterstützt werde" + } + } + }, + "streaks_reminder": { + "properties": { + "remaining_hours": { + "description": "Di verblybendi Zyt bis zur Azeig vor Benachrichtigung (Stund)" + } + } + } + }, + "options": { + "message_indicators": { + "director_mode_indicator": "Fügt es ✏️-Symbol zu Snaps hinzue, we si im Diräctor-Modus gsändet worde si, mit em Galerie-Bilder aus Snaps chöi gsändet wärde", + "encryption_indicator": "Fügt es 🔒-Symbol näb Nachrichte derzue, wo nume ah du gsesch worde si", + "platform_indicator": "Fügt ds Plattform-Symbol hinzue wo es Medium gsendet worde isch (z.B. Android, iOS, Web)", + "location_indicator": "Fügt es 📍-Symbol zu Snaps hinzue, we si mit aktiviertem Speicherort gsendet worde si" + } + }, + "notices": { + "unstable": "⚠ Instabil", + "ban_risk": "⚠ Dieses Feature chan zu Bans führä", + "internal_behavior": "⚠ Das chan s internä Verhaltä vo Snapchat störä" + } + }, + "biometric_auth": { + "title": "Snapchat entsperre", + "subtitle": "Bitte authentifiziere zum d Snapchat entsperre", + "unlock_button": "Entsperre" + }, + "end_to_end_encryption": { + "confirmation_dialogs": { + "title": "Ende-zu-End-Verschlüsselig", + "confirmation_1": "WARNIG: Durch wird dis vorhandene Schlüssel überschribe. Si verliere dr Zuegriff uf alli verschlüsslete Nachrichte vo däm Fründ. Bisch sicher, dass du witermache wotsch?", + "confirmation_2": "Bisch WÜRKLI sicher dass du witermache wotsch? Das isch dini letschti Chance es Rückzieher z mache." + }, + "native_hooks_send_failure_toast": "Versände fehlgschlage! Bitte aktiviered Sie nativi Hooks i de Ihstellige.", + "no_participants_to_encrypt_toast": "Du hesch kei Fründe i dere Unterhaltig wod Nachrichte chasch verschlüssle!", + "accept_public_key_success_toast": "Public Key erfolgrich akzeptiert!", + "accept_public_key_failure_toast": "Öffentliche Schlüssel het nid chönne akzeptiert wärde", + "accept_secret_button": "Akzeptiere gheim", + "toolbox": { + "initiate_exchange_button": "Schlüsseluusstuusch initiiere", + "no_shared_key": "Du hesch no kes Gheimnis mit däm Fründ teilt. Klick dunne um es neus z initiiere.", + "shared_key_fingerprint": "Dir Fingerabdruck isch:\n\n{fingerprint}\n\nÜberprüef, öb är mit em Fingerabdruck vo dim Fründ überiistimmt!" + }, + "incoming_pk_message": "Du hesch grad e Public-Key-Afrag übercho. Klick unde zum sie akzeptiere.", + "incoming_secret_message": "Din Fründ het grad dine öffentliche Schlüssel akzeptiert. Klick unde zums Gheimnis akzeptiere.", + "unencrypted_conversation_send_failure_toast": "Chasch ke verschlüsslete Inhaut sowou a verschlüssleti Inhaut, aus o a unverschlüssleti Ungerhautige schicke!", + "encryption_failed_toast": "D Verschlüsselig vo de Nachricht isch fählgschlage! Überprüefe Si logcat für wyteri Details.", + "accept_secret_key_success_toast": "Fertig! Dir chöi jetz verschlüssleti Nachrichte mit däm Fründ schicke und empfange.", + "accept_secret_key_failure_toast": "Dä gheimi Schlüssel isch nid akzeptiert worde" + }, + "friend_mutation_observer": { + "bitmoji_background_changed": "{username} het de Bitmoji hintergrund gänderet", + "bitmoji_scene_changed": "{username} het ihri Bitmoji szene gänderet" + }, + "material3_strings": { + "date_range_picker_end_headline": "Zu", + "date_picker_switch_to_input_mode": "Iihgab", + "date_range_picker_start_headline": "Vo", + "date_range_picker_title": "Datumsbereich uswähle", + "date_picker_switch_to_calendar_mode": "Kalender" + }, + "setup": { + "dialogs": { + "select_language": "Sprach uswähle", + "save_folder": "SnapEnhance benötigt Speicherberächtigunge zum Abelade und Speichere vo Medie vo Snapchat.\nBitte wähl de Ort us wo d Medie sölled abeglade werde.", + "select_save_folder_button": "Ordner uswähle" + }, + "mappings": { + "dialog": "S generiere vo mappings chan es wiili duure ...", + "generate_failure_no_snapchat": "SnapEnhance hät Snapchat nöd chöne erkenne, bitte versueched Sie Snapchat neu z installiere.", + "generate_failure": "Bim Versuech mappings generiere isch en fehler ufträtte, bitte versueched Sies erneut." + }, + "permissions": { + "dialog": "Zum wiitermache müend Sie folgendi Aforderige erfülle:", + "notification_access": "Benachrichtigung Zugang", + "battery_optimization": "Batterieoptimierig", + "display_over_other_apps": "Ahzeig über anderi Apps", + "request_button": "Anfrage" + } + }, + "manager": { + "sections": { + "home_logs": { + "no_logs_hint": "Kei Protokoll verfüegbar", + "saving_logs_toast": "Logs speichere, das chan es wiili duure ...", + "clear_logs_button": "Protokoll lösche", + "export_logs_button": "Logs exportiere", + "saved_logs_success_toast": "Protokoll erfolgriich gspicheret", + "saved_logs_failure_toast": "Speichere vo Protokoll fählgschlage" + }, + "tasks": { + "remove_selected_tasks_confirm": "{count}-Ufgabe entferne?", + "no_tasks": "Kei Ufgabe", + "merge_files_toast": "Zämeführe vo {count}-Dateien", + "remove_selected_tasks_title": "Sind Sie sicher, dass Sie usegwählti Ufgabe lösche wönd?", + "remove_all_tasks_title": "Sind Sie sicher, dass Sie alli Ufgabe möchted lösche?", + "delete_files_option": "Au Dateiä löschä", + "remove_all_tasks_confirm": "Alli Ufgabe lösche?" + }, + "features": { + "disabled": "Deaktiviert", + "export_option": "Exportierä", + "import_option": "Iifuhr", + "reset_option": "Zrücksetze", + "config_export_success_toast": "Istelligä erfolgrich exportiert", + "config_import_success_toast": "Istelligä erfolgrich importiert", + "config_import_failure_toast": "Istelligä chönd nid importiert werdä {error}", + "saved_config_snackbar": "Konfiguration gspeicheret" + }, + "manage_scope": { + "streaks_expiration_text_expired": "Abglaufe", + "reminder_button": "Erinnerig istelle", + "delete_scope_confirm_dialog_title": "Sind Sie sicher, dass Sie {scope} lösche wönd?", + "logged_stories_button": "g'loggdi Stories azeige", + "e2ee_title": "Änd-zu-Änd-Verschlüsselig", + "rules_title": "Reglä", + "participants_text": "{count}-Teilnehmer", + "not_found": "Nöd gfunde", + "streaks_title": "Flämmli", + "streaks_length_text": "Längi: {length}", + "streaks_expiration_text": "Lauft ab i {eta}" + }, + "logged_stories": { + "story_failed_to_load": "Fehler bim Lade", + "no_stories": "Kei Stories gfunde", + "save_from_cache_button": "Vom Zwischäspiecher speicherä" + }, + "messaging_preview": { + "save_selection_option": "Uswahl speichere", + "bridge_connection_failed": "Verbindig zu Snapchat über de Bruggä-Dienst fehlgschlage", + "bridge_init_failed": "Initialisierig vo de Messaging-Brugg fehlgschlage", + "message_fetch_failed": "Fehler bim Abruefe vo Nachrichte", + "no_message_hint": "Kei Nachricht", + "mark_all_as_seen_option": "Alli Snaps als gseh merkierä", + "save_all_option": "Alli speichere", + "unsave_selection_option": "Uswahl rückgängig mache", + "unsave_all_option": "Uswahl rückgängig mache", + "mark_selection_as_seen_option": "Usgwähltä Snap als g'seh markierä", + "delete_selection_option": "Uswahl lösche", + "delete_all_option": "Alli lösche" + }, + "home": { + "update_title": "SnapEnhance Update", + "update_content": "Version {version} isch verfüegbar!", + "update_button": "Abelade" + }, + "home_settings": { + "actions_title": "Massnahme", + "message_logger_title": "Nachrichtelogger", + "debug_title": "Debugge", + "success_toast": "Fertig!", + "message_logger_summary": "{messageCount} Nachrichtä\n{storyCount} Stories", + "export_button": "Exportierä", + "clear_button": "Löschä", + "view_logger_history_button": "Logger-Verlauf azeige" + }, + "social": { + "friends_tab": "Fründe", + "groups_tab": "Gruppe", + "empty_hint": "(leer)", + "streaks_expiration_short": "{hours} Stündli" + }, + "logger_history": { + "unknown_sender": "Unbekannte Absender", + "download_attachment_failed_toast": "De Ahang het nöd chöne abeglade werde", + "list_friend_format": "Fründ {Name}", + "list_group_format": "Gruppe {Name}", + "no_more_messages": "Kei Meldige meh", + "reverse_order_checkbox": "Umgekehrti Reihefolg", + "empty_message": "Lääri Chat-Nachricht", + "chat_attachment": "Ahang {index}", + "message_parse_failed": "Fehler bim Parse vo de Nachricht" + } + }, + "routes": { + "tasks": "Aufgaben", + "features": "Merkmal", + "home": "Heimat", + "home_settings": "Settigs", + "home_logs": "Logs", + "logger_history": "Logger-Verlauf", + "logged_stories": "Protokollierti Stories", + "friend_tracker": "Friend erkenni", + "edit_rule": "Edit Rulewe", + "social": "Soziales", + "manage_scope": "Rahme verwalte", + "messaging_preview": "Vorschau", + "scripts": "Skripte" + }, + "dialogs": { + "add_friend": { + "title": "Fründ oder Gruppe hinzuefüege", + "search_hint": "Düresueche", + "fetch_error": "Fehler bim Abruefe vo Date", + "category_groups": "Gruppe", + "category_friends": "Fründe" + }, + "scripting_warning": { + "title": "Warnig", + "content": "SnapEnhance enthaltet es Skripting-Tool, wo d Usfüerig vo benutzzerdefiniertem Code uf dim Grät ermöglicht. Si si vorsichtig u installiere Si nume Modul us bekannt, zuverlässige Quelle. Nid autorisierti oder nid verifizierti Modul chöi Sicherheitsrisike für dis System darstelle." + }, + "reset_config": { + "content": "Bisch sicher, dass du d Konfiguration wotsch zruggsetze?", + "success_toast": "Config erfolgrich zrüggsetze", + "title": "Konfiguration zrüggsetze" + }, + "messaging_action": { + "title": "Zu verarbeitende Inhaltstype uswähle", + "select_all_button": "Aui uswähle" + } + } + }, + "scopes": { + "friend": "Freund", + "group": "Gruppe" + }, + "rules": { + "properties": { + "stealth": { + "description": "Verhinderet, dass öpper erfahre das sini Snaps/Chats und Unterhaltige göffnet hesch", + "name": "Stealth-Modus", + "options": { + "blacklist": "Us em Schtealth-Modus usschlüsse", + "whitelist": "Stealth-Modus" + } + }, + "auto_save": { + "description": "Speicheret Chat-Nachrichte bim Betrachte", + "options": { + "blacklist": "Vom Auto speichere usschlüsse", + "whitelist": "Outo spichere" + }, + "name": "Outo spichere" + }, + "auto_download": { + "name": "Automatisches Abewähli", + "description": "Snaps outomatisch abelade we si azeigt wärde", + "options": { + "blacklist": "Vom Auto-Download usschlüsse", + "whitelist": "Automatisches Abewähli" + } + }, + "unsaveable_messages": { + "options": { + "whitelist": "Nid speicherbari Nachrichte", + "blacklist": "Vo nid speicherbare Nachrichte usschlüsse" + }, + "name": "Nid speicherbari Nachrichte", + "description": "Verhinderet, dass Nachrichte vo anderne Persone im Chat gspicheret wärde" + }, + "auto_open_snaps": { + "description": "Öffnet automatisch snaps we si empfange wärde", + "options": { + "blacklist": "Vum Auto Open Snaps usschlüsse", + "whitelist": "Automatischs Öffne vo Schnappschüss" + }, + "name": "Automatischs Öffne vo Schnappschüss" + }, + "hide_friend_feed": { + "name": "Usblende vo Fründ-Feed" + }, + "e2e_encryption": { + "name": "E2E-Verschlüsselig verwände" + }, + "pin_conversation": { + "name": "Konversation anpinnen" + } + }, + "toasts": { + "enabled": "{ruleName} aktiviert", + "disabled": "{ruleName} deaktiviert" + }, + "modes": { + "blacklist": "Blacklist-Modus", + "whitelist": "Wisslischte-Modus" + } + }, + "actions": { + "bulk_messaging_action": { + "description": "Füehrt Vorgäng wi ds Lösche vo Fründe oder ds Masselösche vo Ungerhautige us", + "name": "Massä Nachrichtä Aktion" + }, + "clean_snapchat_cache": { + "name": "Snapchat-Cache bereinige", + "description": "Reinigt der Snapchat-Cache" + }, + "export_memories": { + "name": "Speicher exportiere", + "description": "Exportiert d'Memories in än ZIP-Datei" + }, + "manage_friend_list": { + "name": "Fründesliste verwalte", + "description": "Importiere/Exportiere dini Fründeslischte bim Backup" + }, + "export_chat_messages": { + "name": "Chat-Nachrichte exportiere", + "description": "Exportiert Konversationsnachrichte i ne JSON/HTML/TXT-Datei" + }, + "regen_mappings": { + "name": "Ernüer d'Mappings", + "description": "Ernüer d'Mappings manuell" + }, + "change_language": { + "name": "Sproch änderä", + "description": "Ändert d'Sproch vo SnapEnhance" + } + }, + "streaks_reminder": { + "notification_text": "Du verliersch dy streak mit {friend} in {hoursLeft} Stunde" + } +} diff --git a/common/src/main/assets/lang/gu_IN.json b/common/src/main/assets/lang/gu_IN.json index d3544a51..4373c10c 100644 --- a/common/src/main/assets/lang/gu_IN.json +++ b/common/src/main/assets/lang/gu_IN.json @@ -1,2022 +1,16 @@ { "setup": { "dialogs": { - "select_language": "ભાષા પસંદ કરો", - "save_folder": "PurrfectSnap ને Snapchat માંથી મીડિયા ડાઉનલોડ કરવા અને સાચવવા માટે સ્ટોરેજ પરવાનગીની જરૂર છે.\nકૃપા કરીને તે સ્થાન પસંદ કરો જ્યાં મીડિયા ડાઉનલોડ થવું જોઈએ.", + "save_folder": "SnapEnhance ને Snapchat માંથી મીડિયા ડાઉનલોડ કરવા અને સાચવવા માટે સ્ટોરેજ પરવાનગીની જરૂર છે. કૃપા કરીને તે સ્થાન પસંદ કરો જ્યાં મીડિયા ડાઉનલોડ કરવું જોઈએ.", "select_save_folder_button": "ફોલ્ડર પસંદ કરો" }, "mappings": { - "dialog": "મેપિંગ જનરેટ કરી રહ્યું છે, આમાં થોડો સમય લાગી શકે છે...", - "generate_failure_no_snapchat": "PurrfectSnap Snapchat શોધી શક્યું નથી, કૃપા કરીને Snapchat ફરીથી ઇન્સ્ટોલ કરવાનો પ્રયાસ કરો.", - "generate_failure": "મેપિંગ જનરેટ કરવાનો પ્રયાસ કરતી વખતે એક ભૂલ આવી, કૃપા કરીને ફરી પ્રયાસ કરો." + "generate_failure": "મેપિંગ જનરેટ કરવાનો પ્રયાસ કરતી વખતે એક ભૂલ આવી, કૃપા કરીને ફરી પ્રયાસ કરો.", + "generate_failure_no_snapchat": "SnapEnhance Snapchat શોધવામાં અસમર્થ હતું, કૃપા કરીને Snapchat પુનઃસ્થાપિત કરવાનો પ્રયાસ કરો.", + "dialog": "Snapchat સંસ્કરણોની વિશાળ શ્રેણીને ગતિશીલ રીતે સમર્થન આપવા માટે, SnapEnhance યોગ્ય રીતે કાર્ય કરવા માટે મેપિંગ જરૂરી છે, આમાં 5 સેકન્ડથી વધુ સમય લાગવો જોઈએ નહીં." }, "permissions": { - "dialog": "આગળ વધવા માટે તમારે નીચેની આવશ્યકતાઓને પૂર્ણ કરવાની જરૂર છે:", - "notification_access": "સૂચના ઍક્સેસ", - "battery_optimization": "બેટરી ઓપ્ટિમાઇઝેશન", - "display_over_other_apps": "અન્ય એપ્લિકેશનો પર પ્રદર્શિત કરો", - "request_button": "વિનંતી" + "dialog": "ચાલુ રાખવા માટે તમારે નીચેની આવશ્યકતાઓને ફિટ કરવાની જરૂર છે:" } - }, - "scopes": { - "friend": "મિત્ર", - "group": "જૂથ" - }, - "manager": { - "routes": { - "tasks": "કાર્યો", - "features": "સુવિધાઓ", - "manage_rule_feature": "નિયમ સુવિધાનું સંચાલન કરો", - "home": "ઘર", - "home_settings": "સેટિંગ્સ", - "home_logs": "લોગ્સ", - "logger_history": "લોગર ઇતિહાસ", - "logged_stories": "લોગ કરેલી વાર્તાઓ", - "friend_tracker": "મિત્ર ટ્રેકર", - "edit_rule": "નિયમ સંપાદિત કરો", - "file_imports": "ફાઇલ આયાત", - "manage_repos": "ભંડારોનું સંચાલન કરો", - "social": "સામાજિક", - "manage_scope": "અવકાશનું સંચાલન કરો", - "messaging_preview": "પૂર્વાવલોકન", - "scripts": "સ્ક્રિપ્ટો", - "better_location": "વધુ સારી જગ્યા" - }, - "sections": { - "home": { - "version_title": "v{versionName} · Eternal દ્વારા ફોર્ક કરેલ", - "update_title": "PurrfectSnap અપડેટ", - "update_content": "સંસ્કરણ {version} ઉપલબ્ધ છે!", - "update_button": "ડાઉનલોડ કરો", - "debug_build_summary_title": "તમે PurrfectSnap નું ડિબગ બિલ્ડ ચલાવી રહ્યા છો", - "debug_build_summary_content": "સંસ્કરણ {versionName} ({versionCode})", - "debug_build_summary_date": "બિલ્ડ તારીખ: {date} ({days} દિવસો પહેલા)", - "quick_actions_title": "ઝડપી ક્રિયાઓ", - "download_icon_description": "ડાઉનલોડ કરો", - "completed_icon_description": "પૂર્ણ", - "failed_icon_description": "નિષ્ફળ", - "manage_quick_actions_description": "ઝડપી ક્રિયાઓનું સંચાલન કરો", - "quick_actions_icon_description": "ઝડપી ક્રિયાઓ", - "add_quick_action_description": "ઝડપી ક્રિયા ઉમેરો" - }, - "home_logs": { - "no_logs_hint": "કોઈ લોગ ઉપલબ્ધ નથી", - "clear_logs_button": "લોગ સાફ કરો", - "export_logs_button": "લોગ નિકાસ કરો", - "saving_logs_toast": "લોગ સાચવી રહ્યું છે, આમાં થોડો સમય લાગી શકે છે...", - "saved_logs_success_toast": "લોગ સફળતાપૂર્વક સાચવવામાં આવ્યા છે", - "saved_logs_failure_toast": "લોગ સાચવવામાં નિષ્ફળ" - }, - "home_settings": { - "actions_title": "ક્રિયાઓ", - "message_logger_title": "સંદેશ લોગર", - "debug_title": "ડિબગ", - "success_toast": "થઈ ગયું!", - "message_logger_summary": "{messageCount} સંદેશાઓ\n{storyCount} વાર્તાઓ", - "export_button": "નિકાસ કરો", - "clear_button": "સાફ કરો", - "view_logger_history_button": "લોગર ઇતિહાસ જુઓ", - "updates_title": "અપડેટ્સ", - "auto_update_check": "અપડેટ્સ માટે આપમેળે તપાસો", - "update_check_frequency": "અપડેટ તપાસવાની આવર્તન", - "update_check_frequency_daily": "દૈનિક", - "update_check_frequency_weekly": "સાપ્તાહિક", - "update_check_frequency_monthly": "માસિક", - "theme_icon_description": "થીમ", - "app_theme_title": "એપ્લિકેશન થીમ", - "theme_mode_system": "સિસ્ટમ", - "theme_mode_light": "પ્રકાશ", - "theme_mode_dark": "અંધારું", - "ui_settings_title": "UI સેટિંગ્સ", - "haptic_feedback_label": "હેપ્ટિક પ્રતિસાદ", - "test_mode_label": "પરીક્ષણ મોડ (ફક્ત ડિબગિંગ માટે)", - "disable_feature_loading_label": "સુવિધા લોડિંગ અક્ષમ કરો", - "disable_auto_mapper_label": "ઓટો મેપર અક્ષમ કરો", - "disable_bypass_indicator_label": "બાયપાસ સ્થિતિ સૂચક અક્ષમ કરો", - "update_notification_channel_name": "PurrfectSnap અપડેટ્સ", - "update_notification_channel_description": "PurrfectSnap અપડેટ્સ માટે સૂચનાઓ", - "update_notification_title": "PurrfectSnap અપડેટ ઉપલબ્ધ", - "update_notification_text": "સંસ્કરણ %s હવે ઉપલબ્ધ છે.", - "export_database_failed_toast": "ડેટાબેઝ નિકાસ કરવામાં નિષ્ફળ! {message}", - "clear_messages_failed_toast": "સંદેશાઓ સાફ કરવામાં નિષ્ફળ! {message}", - "clear_file_failed_toast": "ફાઇલ સાફ કરવામાં નિષ્ફળ! {message}", - "debug_file_config": "રૂપરેખાંકન", - "debug_file_mappings": "મેપિંગ્સ", - "debug_file_message_logger": "સંદેશ લોગર", - "debug_file_pinned_best_friend": "પિન કરેલ શ્રેષ્ઠ મિત્ર", - "debug_file_native_sig_cache": "મૂળ સહી કેશ" - }, - "tasks": { - "no_tasks": "કોઈ કાર્યો નથી", - "merge_button": "ભેળવો", - "failed_to_open_file": "ફાઇલ ખોલવામાં નિષ્ફળ", - "merge_files_toast": "{count} ફાઇલો ભેળવી રહી છે", - "remove_selected_tasks_title": "શું તમે ખાતરી કરો છો કે તમે પસંદ કરેલા કાર્યોને દૂર કરવા માંગો છો?", - "remove_all_tasks_title": "શું તમે ખાતરી કરો છો કે તમે બધા કાર્યોને દૂર કરવા માંગો છો?", - "delete_files_option": "ફાઇલો પણ કાઢી નાખો", - "remove_selected_tasks_confirm": "{count} કાર્યો દૂર કરો?", - "remove_all_tasks_confirm": "બધા કાર્યો દૂર કરો?", - "clear_tasks_description": "કાર્યો સાફ કરો", - "file_not_found_icon_description": "ફાઇલ મળી નથી", - "image_icon_description": "છબી", - "video_icon_description": "વિડિઓ", - "audio_icon_description": "ઓડિયો", - "file_icon_description": "ફાઇલ", - "download_icon_description": "ડાઉનલોડ કરો", - "chat_action_icon_description": "ચેટ ક્રિયા", - "cancel_icon_description": "રદ કરો", - "success_icon_description": "સફળતા", - "failure_icon_description": "નિષ્ફળતા", - "cancelled_icon_description": "રદ કરેલ", - "task_status_failure": "નિષ્ફળતા", - "task_status_cancelled": "રદ કરેલ" - }, - "features": { - "disabled": "અક્ષમ", - "export_option": "નિકાસ કરો", - "import_option": "આયાત કરો", - "reset_option": "રીસેટ કરો", - "config_export_success_toast": "રૂપરેખાંકન સફળતાપૂર્વક નિકાસ કરવામાં આવ્યું", - "config_import_success_toast": "રૂપરેખાંકન સફળતાપૂર્વક આયાત કરવામાં આવ્યું", - "config_import_failure_toast": "રૂપરેખાંકન આયાત કરવામાં નિષ્ફળ {error}", - "config_export_failure_toast": "રૂપરેખાંકન નિકાસ કરવામાં નિષ્ફળ {error}", - "saved_config_snackbar": "રૂપરેખાંકન સાચવવામાં આવ્યું", - "older_required": "આ સુવિધાને યોગ્ય રીતે કામ કરવા માટે Snapchat v{version} અથવા જૂનીની જરૂર છે", - "newer_required": "આ સુવિધાને યોગ્ય રીતે કામ કરવા માટે Snapchat v{version} અથવા નવીની જરૂર છે", - "search_button": "શોધો" - }, - "manage_rule_feature": { - "disable_state_option": "અક્ષમ", - "disable_state_subtext": "કોઈ મિત્રો/જૂથોને અસર થશે નહીં", - "whitelist_state_option": "સિવાય કોઈ નહીં ...", - "whitelist_state_subtext": "ફક્ત {count} મિત્રો/જૂથો આ નિયમથી પ્રભાવિત થશે", - "whitelist_state_button": "મંજૂર મિત્રો/જૂથો પસંદ કરો", - "blacklist_state_option": "સિવાય દરેક ...", - "blacklist_state_subtext": "સિવાય દરેક {count} મિત્રો/જૂથો આ નિયમથી પ્રભાવિત થશે", - "blacklist_state_button": "બાકાત મિત્રો/જૂથો પસંદ કરો", - "clear_list_button": "મિત્રો/જૂથોની સૂચિ સાફ કરો", - "dialog_clear_confirmation_text": "શું તમે ખાતરી કરો છો કે તમે સૂચિ સાફ કરવા માંગો છો?" - }, - "social": { - "friends_tab": "મિત્રો", - "groups_tab": "જૂથો", - "empty_hint": "(ખાલી)", - "streaks_expiration_short": "{hours}ક" - }, - "manage_scope": { - "logged_stories_button": "લોગ કરેલી વાર્તાઓ બતાવો", - "e2ee_title": "એન્ડ-ટુ-એન્ડ એન્ક્રિપ્શન", - "rules_title": "નિયમો", - "participants_text": "{count} સહભાગીઓ", - "not_found": "મળ્યું નથી", - "streaks_title": "સ્ટ્રીક્સ", - "streaks_length_text": "લંબાઈ: {length}", - "streaks_expiration_text": "{eta} માં સમાપ્ત થાય છે", - "streaks_expiration_text_expired": "સમાપ્ત", - "reminder_button": "રીમાઇન્ડર સેટ કરો", - "delete_scope_confirm_dialog_title": "શું તમે ખાતરી કરો છો કે તમે {scope} કાઢી નાખવા માંગો છો?", - "notes_placeholder": "નોંધ ઉમેરવા માટે ક્લિક કરો", - "invalid_key_size_32_bytes": "અમાન્ય કી કદ (32 બાઇટ્સ હોવું આવશ્યક છે)", - "successfully_imported_key": "કી સફળતાપૂર્વક આયાત કરવામાં આવી", - "failed_to_import_key": "કી આયાત કરવામાં નિષ્ફળ: {message}", - "export_base64_button": "બેઝ64 નિકાસ કરો", - "import_base64_button": "બેઝ64 આયાત કરો" - }, - "logged_stories": { - "story_failed_to_load": "લોડ કરવામાં નિષ્ફળ", - "no_stories": "કોઈ વાર્તાઓ મળી નથી", - "save_from_cache_button": "કેશમાંથી સાચવો", - "downloaded_to_path": "{path} પર ડાઉનલોડ થયું", - "download_failed": "ડાઉનલોડ નિષ્ફળ: {message}", - "posted_at": "{date} ના રોજ પોસ્ટ કર્યું", - "created_at": "{date} ના રોજ બનાવ્યું", - "failed_to_open_file": "ફાઇલ ખોલવામાં નિષ્ફળ. વધુ માહિતી માટે લોગ તપાસો", - "failed_to_get_file": "ફાઇલ મેળવવામાં નિષ્ફળ" - }, - "messaging_preview": { - "processed_messages_toast": "{count} સંદેશા પર પ્રક્રિયા કરવામાં આવી", - "processed_messages_text": "{count} સંદેશા પર પ્રક્રિયા કરવામાં આવી", - "close_button_description": "બંધ કરો", - "bridge_connection_failed": "બ્રિજ સાથે કનેક્ટ કરવામાં નિષ્ફળ. ખાતરી કરો કે Snapchat પૃષ્ઠભૂમિમાં ચાલી રહ્યું છે", - "bridge_init_failed": "મેસેજિંગ બ્રિજ શરૂ કરવામાં નિષ્ફળ. ખાતરી કરો કે Snapchat પૃષ્ઠભૂમિમાં ચાલી રહ્યું છે", - "message_fetch_failed": "સંદેશા મેળવવામાં નિષ્ફળ", - "no_message_hint": "કોઈ સંદેશ નથી", - "save_selection_option": "પસંદગી સાચવો", - "save_all_option": "બધા સાચવો", - "unsave_selection_option": "પસંદગી અસાચવો", - "unsave_all_option": "બધા અસાચવો", - "mark_selection_as_seen_option": "પસંદ કરેલ સ્નેપને જોયેલ તરીકે ચિહ્નિત કરો", - "mark_all_as_seen_option": "બધા સ્નેપને જોયેલ તરીકે ચિહ્નિત કરો", - "delete_selection_option": "પસંદગી કાઢી નાખો", - "delete_all_option": "બધા કાઢી નાખો" - }, - "logger_history": { - "download_started_toast": "ડાઉનલોડ શરૂ થયું!", - "download_success_toast": "{path} પર ડાઉનલોડ થયું", - "download_failed_toast": "{message} ડાઉનલોડ કરવામાં નિષ્ફળ", - "edited_at_text": "{message} ({date} ના રોજ સંપાદિત)", - "download_button": "ડાઉનલોડ કરો", - "select_conversation_placeholder": "વાર્તાલાપ પસંદ કરો", - "close_button_description": "બંધ કરો", - "search_button_description": "શોધો", - "list_friend_format": "મિત્ર {name}", - "list_group_format": "જૂથ {name}", - "no_more_messages": "વધુ સંદેશા નથી", - "reverse_order_checkbox": "ઉલટો ક્રમ", - "chat_attachment": "જોડાણ {index}", - "empty_message": "ખાલી ચેટ સંદેશ", - "message_parse_failed": "સંદેશ પાર્સ કરવામાં નિષ્ફળ", - "unknown_sender": "અજ્ઞાત પ્રેષક", - "download_attachment_failed_toast": "જોડાણ ડાઉનલોડ કરવામાં નિષ્ફળ", - "log_header_format": "{username} ({type}) - {date}" - }, - "file_imports": { - "import_file_button": "ફાઇલ આયાત કરો", - "file_not_found": "ફાઇલ મળી નથી", - "file_import_failed": "ફાઇલ આયાત કરવામાં નિષ્ફળ: {error}", - "file_imported": "ફાઇલ સફળતાપૂર્વક આયાત કરવામાં આવી", - "file_delete_failed": "ફાઇલ કાઢી નાખવામાં નિષ્ફળ", - "no_files_hint": "અહીં તમે Snapchat માં ઉપયોગ માટે ફાઇલો આયાત કરી શકો છો. ફાઇલ આયાત કરવા માટે નીચેનું બટન દબાવો." - }, - "better_location": { - "spoofed_coordinates_title": "અક્ષાંશ {latitude}, રેખાંશ {longitude}", - "save_coordinates_dialog_title": "કોઓર્ડિનેટ્સ સાચવો", - "saved_name_dialog_hint": "સાચવેલું નામ", - "latitude_dialog_hint": "અક્ષાંશ", - "longitude_dialog_hint": "રેખાંશ", - "save_dialog_button": "સાચવો", - "choose_location_button": "સ્થાન પસંદ કરો", - "teleport_to_friend_button": "મિત્ર પાસે ટેલિપોર્ટ કરો", - "spoof_location_toggle": "સ્થાન સ્પૂફ કરો", - "suspend_location_updates": "સ્થાન અપડેટ્સ સ્થગિત કરો", - "saved_coordinates_title": "સાચવેલા કોઓર્ડિનેટ્સ", - "no_saved_coordinates_hint": "કોઈ સાચવેલા કોઓર્ડિનેટ્સ નથી", - "delete_dialog_title": "સાચવેલ કોઓર્ડિનેટ કાઢી નાખો", - "delete_dialog_message": "શું તમે ખાતરી કરો છો કે તમે આ સાચવેલ કોઓર્ડિનેટ કાઢી નાખવા માંગો છો?", - "teleport_to_friend_title": "મિત્ર પાસે ટેલિપોર્ટ કરો", - "search_bar": "શોધો", - "no_friends_map": "નકશા પર કોઈ મિત્રો નથી", - "no_friends_found": "કોઈ મિત્રો મળ્યા નથી", - "edit_location_button_description": "સ્થાન સંપાદિત કરો", - "add_icon_description": "ઉમેરો", - "edit_icon_description": "સંપાદિત કરો", - "delete_icon_description": "કાઢી નાખો" - } - }, - "dialogs": { - "add_friend": { - "title": "મિત્ર અથવા જૂથ ઉમેરો", - "search_hint": "શોધો", - "fetch_error": "ડેટા મેળવવામાં નિષ્ફળ", - "category_groups": "જૂથો", - "category_friends": "મિત્રો", - "participants_text": "{count} સહભાગીઓ", - "search_icon_description": "શોધો" - }, - "scripting_warning": { - "title": "ચેતવણી", - "content": "PurrfectSnap માં સ્ક્રિપ્ટીંગ ટૂલ શામેલ છે, જે તમારા ઉપકરણ પર વપરાશકર્તા-વ્યાખ્યાયિત કોડ ચલાવવાની મંજૂરી આપે છે. અત્યંત સાવધાની રાખો અને ફક્ત જાણીતા, વિશ્વસનીય સ્ત્રોતોમાંથી મોડ્યુલો ઇન્સ્ટોલ કરો. અનધિકૃત અથવા ચકાસાયેલ ન હોય તેવા મોડ્યુલો તમારા સિસ્ટમ માટે સુરક્ષા જોખમો ઉભા કરી શકે છે." - }, - "reset_config": { - "title": "રૂપરેખાંકન રીસેટ કરો", - "content": "શું તમે ખાતરી કરો છો કે તમે રૂપરેખાંકન રીસેટ કરવા માંગો છો?", - "success_toast": "રૂપરેખાંકન સફળતાપૂર્વક રીસેટ કરવામાં આવ્યું" - }, - "export_config": { - "title": "સંવેદનશીલ ડેટા નિકાસ કરો?", - "content": "શું તમે સંવેદનશીલ ડેટા સાથે રૂપરેખાંકન નિકાસ કરવા માંગો છો? (જેમ કે સ્થાન કોઓર્ડિનેટ્સ, વગેરે)" - }, - "messaging_action": { - "title": "પ્રક્રિયા કરવા માટે સામગ્રી પ્રકારો પસંદ કરો", - "select_all_button": "બધા પસંદ કરો" - }, - "file_imports": { - "no_files_settings_hint": "કોઈ ફાઇલો મળી નથી. ખાતરી કરો કે તમે ફાઇલ આયાત વિભાગમાં જરૂરી ફાઇલો આયાત કરી છે", - "settings_select_file_hint": "આયાત કરેલી ફાઇલ પસંદ કરો" - }, - "quick_actions_dialog": { - "title": "ઝડપી ક્રિયાઓ સંપાદિત કરો", - "subtitle": "તમારી ઝડપી ક્રિયાઓ પસંદ કરો અને કદ આપો." - } - }, - "friend_tracker": { - "rules_tab": "નિયમો", - "logs_tab": "લોગ્સ", - "export_dialog_title": "નિકાસ કરો", - "bulk_export_button": "જથ્થાબંધ નિકાસ", - "individual_export_button": "વ્યક્તિગત નિકાસ", - "invalid_import_type_dialog_title": "અમાન્ય આયાત પ્રકાર", - "invalid_import_type_dialog_text": "પસંદ કરેલી ફાઇલ આ આયાત પ્રકાર સાથે સુસંગત નથી. કૃપા કરીને સાચો આયાત પ્રકાર પસંદ કરો.", - "import_dialog_title": "આયાત કરો", - "bulk_import_button": "જથ્થાબંધ આયાત", - "individual_import_button": "વ્યક્તિગત આયાત", - "import_button_description": "આયાત કરો", - "export_button_description": "નિકાસ કરો", - "export_button": "નિકાસ કરો", - "delete_button_description": "કાઢી નાખો", - "delete_button": "કાઢી નાખો", - "catalog_button_description": "કેટલોગ", - "catalog_button": "કેટલોગ", - "add_rule_button_description": "નિયમ ઉમેરો", - "add_rule_button": "નિયમ ઉમેરો", - "no_rules_found": "કોઈ નિયમો મળ્યા નથી", - "empty_rule_name": "(ખાલી)", - "events_suffix": "ઘટનાઓ", - "scopes_suffix": "અવકાશ", - "select_rule_to_export_title": "નિકાસ કરવા માટે નિયમ પસંદ કરો", - "deleted_logs_toast": "{count} લોગ કાઢી નાખવામાં આવ્યા", - "delete_logs_dialog_title": "લોગ કાઢી નાખવા છે?", - "deleting_logs_dialog_text": "{count} લોગ કાઢી રહ્યા છીએ...", - "delete_logs_dialog_confirm_text": "આ વર્તમાન ફિલ્ટર અને શોધ ક્વેરીના આધારે લોગ કાઢી નાખશે. આ ક્રિયા પૂર્વવત્ કરી શકાતી નથી.", - "exported_logs_toast": "લોગ નિકાસ કરવામાં આવ્યા!", - "export_logs_failed_toast": "લોગ નિકાસ કરવામાં નિષ્ફળ. વધુ વિગતો માટે લોગકેટ તપાસો.", - "export_logs_dialog_title": "લોગ નિકાસ કરવા છે?", - "exporting_logs_dialog_text": "લોગ નિકાસ કરી રહ્યું છે...", - "export_logs_dialog_confirm_text": "આ વર્તમાન ફિલ્ટર અને શોધ ક્વેરીના આધારે લોગ નિકાસ કરશે.", - "export_as_button": "{type} તરીકે નિકાસ કરો", - "filters_title": "ફિલ્ટર્સ", - "search_by_label": "દ્વારા શોધો", - "newest_first_label": "નવા પહેલા", - "since_label": "થી", - "until_label": "સુધી", - "pick_a_date_button": "તારીખ પસંદ કરો", - "search_placeholder": "શોધો", - "filter_button_description": "ફિલ્ટર", - "clear_button_description": "સાફ કરો", - "no_logs_found": "કોઈ લોગ મળ્યા નથી", - "log_event_format": "{conversation} માં {event}", - "condition_only_inside_conversation": "ફક્ત જ્યારે હું વાર્તાલાપમાં હોઉં", - "condition_only_outside_conversation": "ફક્ત જ્યારે હું વાર્તાલાપની બહાર હોઉં", - "condition_only_when_app_active": "ફક્ત જ્યારે Snapchat સક્રિય હોય", - "condition_only_when_app_inactive": "ફક્ત જ્યારે Snapchat નિષ્ક્રિય હોય", - "condition_no_push_notification_when_app_active": "Snapchat સક્રિય હોય ત્યારે કોઈ પુશ સૂચના નહીં", - "add_event_dialog_title": "ઘટના ઉમેરો", - "event_type_label": "ઘટનાનો પ્રકાર", - "triggers_title": "ટ્રિગર્સ", - "conditions_title": "શરતો", - "add_button": "ઉમેરો", - "default_rule_name": "કસ્ટમ નિયમ", - "discard_changes_dialog_title": "ફેરફારો કાઢી નાખવા છે?", - "discard_changes_dialog_text": "તમારી પાસે સાચવેલા ન હોય તેવા ફેરફારો છે. શું તમે ખાતરી કરો છો કે તમે તેમને કાઢી નાખવા માંગો છો?", - "discard_button": "કાઢી નાખો", - "cannot_save_rule_dialog_title": "નિયમ સાચવી શકાતો નથી", - "cannot_save_rule_dialog_text": "સાચવવા માટે નિયમમાં ઓછામાં ઓછી એક ઘટના હોવી આવશ્યક છે.", - "duplicate_rule_name_dialog_title": "ડુપ્લિકેટ નિયમ નામ", - "duplicate_rule_name_dialog_text": "આ નામનો નિયમ પહેલેથી જ અસ્તિત્વમાં છે. કૃપા કરીને બીજું નામ પસંદ કરો.", - "delete_rule_dialog_title": "નિયમ કાઢી નાખો", - "delete_rule_dialog_text": "શું તમે ખાતરી કરો છો કે તમે આ નિયમ કાઢી નાખવા માંગો છો?", - "new_rule_title": "નવો નિયમ", - "edit_rule_title": "નિયમ સંપાદિત કરો", - "back_button_description": "પાછા", - "save_button_description": "સાચવો", - "general_section_title": "સામાન્ય", - "rule_name_label": "નિયમનું નામ", - "author_name_label": "લેખકનું નામ", - "scope_section_title": "અવકાશ", - "scope_all": "બધા", - "scope_whitelist": "વ્હાઇટલિસ્ટ", - "scope_blacklist": "બ્લેકલિસ્ટ", - "select_friends_groups_button": "મિત્રો/જૂથો પસંદ કરો ({count})", - "events_section_title": "ઘટનાઓ", - "add_event_button": "ઘટના ઉમેરો", - "no_events_text": "કોઈ ઘટનાઓ નથી" - }, - "friend_tracker_catalog": { - "download_failed": "ડાઉનલોડ નિષ્ફળ: {code}", - "error": "ભૂલ: {message}", - "no_repos_added": "કોઈ ભંડારો ઉમેરવામાં આવ્યા નથી.", - "no_rules_available": "કોઈપણ ભંડારમાંથી કોઈ નિયમો ઉપલબ્ધ નથી.", - "by_author": "{author} દ્વારા", - "imported_button": "આયાત કરેલ", - "import_button": "આયાત કરો", - "title": "મિત્ર ટ્રેકર કેટલોગ", - "manage_repos_description": "ભંડારોનું સંચાલન કરો" - }, - "friend_tracker_export": { - "title": "નિયમો નિકાસ કરો", - "back_button_description": "પાછા", - "exported_toast": "મિત્ર ટ્રેકર નિયમો નિકાસ કરવામાં આવ્યા!", - "export_failed_toast": "નિયમો નિકાસ કરવામાં નિષ્ફળ: {message}", - "save_button": "સાચવો", - "expand_button_description": "વિસ્તૃત કરો" - }, - "friend_tracker_import": { - "title": "નિયમો આયાત કરો", - "back_button_description": "પાછા", - "imported_toast": "મિત્ર ટ્રેકર નિયમો આયાત કરવામાં આવ્યા!", - "import_failed_toast": "નિયમો આયાત કરવામાં નિષ્ફળ: {message}", - "confirm_button": "પુષ્ટિ કરો", - "expand_button_description": "વિસ્તૃત કરો" - }, - "friend_tracker_repos": { - "invalid_repo_title": "અમાન્ય ભંડાર", - "add_repo_button": "ભંડાર ઉમેરો", - "add_repo_dialog_title": "ભંડાર URL ઉમેરો", - "repo_url_label": "ભંડાર URL", - "repo_added_toast": "ભંડાર સફળતાપૂર્વક ઉમેરવામાં આવ્યો!", - "invalid_repo_error": "આ એક માન્ય મિત્ર ટ્રેકર ભંડાર હોય તેવું લાગતું નથી.", - "add_repo_failed_toast": "ભંડાર ઉમેરવામાં નિષ્ફળ: {message}", - "add_button": "ઉમેરો", - "no_repos_added": "કોઈ ભંડારો ઉમેરવામાં આવ્યા નથી", - "remove_button": "દૂર કરો", - "remove_repo_dialog_title": "ભંડાર દૂર કરો", - "remove_repo_dialog_text": "શું તમે ખાતરી કરો છો કે તમે આ ભંડાર દૂર કરવા માંગો છો?" - }, - "navigation": { - "tracker_tab_label": "ટ્રેકર", - "customize_bottom_bar_title": "નીચેની પટ્ટીને કસ્ટમાઇઝ કરો", - "customize_bottom_bar_subtitle": "ટેબ્સને ફરીથી ગોઠવો, ઉમેરો અથવા દૂર કરો. મહત્તમ પાંચ.", - "shown_tabs_title": "બતાવેલ ટેબ્સ", - "no_tabs_selected_text": "કોઈ ટેબ પસંદ નથી", - "available_tabs_title": "ઉપલબ્ધ ટેબ્સ", - "reset_button": "રીસેટ કરો", - "done_button": "થઈ ગયું" - }, - "scripting": { - "script_already_installed": "સ્ક્રિપ્ટ પહેલેથી જ ઇન્સ્ટોલ કરેલી છે!", - "downloading_script": "સ્ક્રિપ્ટ ડાઉનલોડ કરી રહ્યું છે...", - "script_downloaded": "{name} સ્ક્રિપ્ટ ડાઉનલોડ થઈ!", - "download_script_failed": "સ્ક્રિપ્ટ ડાઉનલોડ કરવામાં નિષ્ફળ. વધુ વિગતો માટે લોગ તપાસો", - "import_script_from_url_title": "URL માંથી સ્ક્રિપ્ટ આયાત કરો", - "import_script_warning": "ચેતવણી: આયાત કરેલી સ્ક્રિપ્ટો તમારા ઉપકરણ માટે હાનિકારક હોઈ શકે છે. ફક્ત વિશ્વસનીય સ્ત્રોતોમાંથી સ્ક્રિપ્ટો આયાત કરો.", - "enter_url_label": "અહીં URL દાખલ કરો:", - "script_imported": "{name} સ્ક્રિપ્ટ આયાત થઈ!", - "import_failed": "સ્ક્રિપ્ટ આયાત કરવામાં નિષ્ફળ. {message}. વધુ વિગતો માટે લોગ તપાસો", - "import_button": "આયાત કરો", - "update_module_button": "મોડ્યુલ અપડેટ કરો", - "updating_script": "{name} સ્ક્રિપ્ટ અપડેટ કરી રહ્યું છે...", - "module_not_found": "મોડ્યુલ મળ્યું નથી", - "updated_script": "{name} ને સંસ્કરણ {version} પર અપડેટ કર્યું", - "update_module_failed": "મોડ્યુલ અપડેટ કરવામાં નિષ્ફળ. વધુ વિગતો માટે લોગ તપાસો", - "edit_module_button": "મોડ્યુલ સંપાદિત કરો", - "open_module_failed": "મોડ્યુલ ફાઇલ ખોલવામાં નિષ્ફળ. વધુ વિગતો માટે લોગ તપાસો", - "clear_module_data_button": "મોડ્યુલ ડેટા સાફ કરો", - "module_data_cleared": "મોડ્યુલ ડેટા સાફ થયો!", - "clear_module_data_failed": "મોડ્યુલ ડેટા સાફ કરવામાં નિષ્ફળ. વધુ વિગતો માટે લોગ તપાસો", - "delete_module_button": "મોડ્યુલ કાઢી નાખો", - "deleted_script": "{name} સ્ક્રિપ્ટ કાઢી નાખવામાં આવી!", - "delete_module_failed": "મોડ્યુલ કાઢી નાખવામાં નિષ્ફળ. વધુ વિગતો માટે લોગ તપાસો", - "actions_title": "ક્રિયાઓ", - "no_description": "કોઈ વર્ણન નથી", - "update_available": "અપડેટ ઉપલબ્ધ: {version}", - "actions_button": "ક્રિયાઓ", - "loaded_script": "{name} સ્ક્રિપ્ટ લોડ થઈ", - "unloaded_script": "{name} સ્ક્રિપ્ટ અનલોડ થઈ", - "enable_script_failed": "સ્ક્રિપ્ટ સક્ષમ કરવામાં નિષ્ફળ. વધુ વિગતો માટે લોગ તપાસો", - "disable_script_failed": "સ્ક્રિપ્ટ અક્ષમ કરવામાં નિષ્ફળ. વધુ વિગતો માટે લોગ તપાસો", - "select_scripts_folder_toast": "કૃપા કરીને તમારો સ્ક્રિપ્ટ ફોલ્ડર પસંદ કરો!", - "manage_repos_button": "ભંડારોનું સંચાલન કરો", - "import_from_url_button": "URL માંથી આયાત કરો", - "open_scripts_folder_button": "સ્ક્રિપ્ટ ફોલ્ડર ખોલો", - "no_settings_for_module": "આ મોડ્યુલમાં કોઈ સેટિંગ્સ નથી", - "installed_scripts_tab": "ઇન્સ્ટોલ કરેલી સ્ક્રિપ્ટો", - "catalog_tab": "કેટલોગ", - "no_scripts_folder_selected_title": "કોઈ સ્ક્રિપ્ટ ફોલ્ડર પસંદ નથી", - "select_folder_button": "ફોલ્ડર પસંદ કરો", - "no_scripts_found_title": "કોઈ સ્ક્રિપ્ટો મળી નથી.", - "use_catalog_to_add_scripts": "સ્ક્રિપ્ટો ઉમેરવા માટે કેટલોગ ટેબનો ઉપયોગ કરો!", - "ok_button_timeout": "ઓકે ({timeout})", - "documentation_button": "દસ્તાવેજીકરણ", - "catalog": { - "script_already_installed": "સ્ક્રિપ્ટ પહેલેથી જ ઇન્સ્ટોલ કરેલી છે!", - "download_failed": "ડાઉનલોડ નિષ્ફળ: {code}", - "script_downloaded": "સ્ક્રિપ્ટ ડાઉનલોડ થઈ!", - "could_not_create_file": "ફાઇલ બનાવી શકાઈ નથી.", - "no_scripts_folder_selected": "કોઈ સ્ક્રિપ્ટ ફોલ્ડર પસંદ નથી.", - "error": "ભૂલ: {message}", - "no_repos_added": "કોઈ ભંડારો ઉમેરવામાં આવ્યા નથી.", - "repo_list_info": "અહીં તમે ભંડારોની સૂચિ શોધી શકો છો: ", - "link_text": "લિંક", - "no_scripts_available": "કોઈપણ ભંડારમાંથી કોઈ સ્ક્રિપ્ટો ઉપલબ્ધ નથી.", - "by_author": "{author} દ્વારા", - "version": "સંસ્કરણ: {version}", - "installed_button": "ઇન્સ્ટોલ કરેલ", - "download_button": "ડાઉનલોડ કરો" - }, - "repos": { - "invalid_repo_title": "અમાન્ય ભંડાર", - "add_repo_button": "ભંડાર ઉમેરો", - "add_repo_dialog_title": "ભંડાર URL ઉમેરો", - "repo_url_label": "ભંડાર URL", - "repo_added_toast": "ભંડાર સફળતાપૂર્વક ઉમેરવામાં આવ્યો!", - "invalid_repo_error": "આ એક માન્ય સ્ક્રિપ્ટ ભંડાર હોય તેવું લાગતું નથી.", - "add_repo_failed_toast": "ભંડાર ઉમેરવામાં નિષ્ફળ: {message}", - "add_button": "ઉમેરો", - "no_repos_added": "કોઈ ભંડારો ઉમેરવામાં આવ્યા નથી", - "remove_button": "દૂર કરો", - "remove_repo_dialog_title": "ભંડાર દૂર કરો", - "remove_repo_dialog_text": "શું તમે ખાતરી કરો છો કે તમે આ ભંડાર દૂર કરવા માંગો છો?" - } - }, - "features": { - "config_import": { - "title": "આયાતની પુષ્ટિ કરો", - "back_button_description": "પાછા", - "config_imported_toast": "રૂપરેખાંકન આયાત થયું!", - "confirm_button": "પુષ્ટિ કરો", - "expand_button_description": "વિસ્તૃત કરો", - "enable_feature": "સુવિધા સક્ષમ કરો", - "enabled": "સક્ષમ", - "disabled": "અક્ષમ" - }, - "config_export": { - "title": "નિકાસ સારાંશ", - "back_button_description": "પાછા", - "save_button": "સાચવો", - "expand_button_description": "વિસ્તૃત કરો", - "enable_feature": "સુવિધા સક્ષમ કરો", - "enabled": "સક્ષમ", - "disabled": "અક્ષમ" - } - }, - "manage_repos": { - "title": "{type} રિપોઝીટરીઝ મેનેજ કરો", - "add_repo_button": "ભંડાર ઉમેરો", - "add_repo_dialog_title": "ભંડાર URL ઉમેરો", - "repo_url_label": "ભંડાર URL", - "repo_added_successfully": "ભંડાર સફળતાપૂર્વક ઉમેરવામાં આવ્યો!", - "add_repo_failed": "ભંડાર ઉમેરવામાં નિષ્ફળ: {message}", - "add_button": "ઉમેરો", - "no_repos_added": "કોઈ ભંડારો ઉમેરવામાં આવ્યા નથી", - "remove_button": "દૂર કરો" - } - }, - "rules": { - "toasts": { - "enabled": "{ruleName} સક્ષમ", - "disabled": "{ruleName} અક્ષમ" - }, - "modes": { - "blacklist": "બ્લેકલિસ્ટ મોડ", - "whitelist": "વ્હાઇટલિસ્ટ મોડ" - }, - "properties": { - "auto_download": { - "name": "ઓટો ડાઉનલોડ", - "description": "જોતી વખતે સ્નેપ આપમેળે ડાઉનલોડ કરો", - "options": { - "blacklist": "ઓટો ડાઉનલોડમાંથી બાકાત રાખો", - "whitelist": "ઓટો ડાઉનલોડ" - } - }, - "stealth": { - "name": "સ્ટીલ્થ મોડ", - "description": "કોઈને પણ જાણ થતી અટકાવે છે કે તમે તેમના સ્નેપ/ચેટ્સ અને વાર્તાલાપ ખોલ્યા છે", - "options": { - "blacklist": "સ્ટીલ્થ મોડમાંથી બાકાત રાખો", - "whitelist": "સ્ટીલ્થ મોડ" - } - }, - "auto_save": { - "name": "ઓટો સેવ", - "description": "જોતી વખતે ચેટ સંદેશા સાચવે છે", - "options": { - "blacklist": "ઓટો સેવમાંથી બાકાત રાખો", - "whitelist": "ઓટો સેવ" - } - }, - "unsaveable_messages": { - "name": "અસાચવી શકાય તેવા સંદેશા", - "description": "અન્ય લોકો દ્વારા ચેટમાં સંદેશા સાચવવાથી અટકાવે છે", - "options": { - "blacklist": "અસાચવી શકાય તેવા સંદેશાઓમાંથી બાકાત રાખો", - "whitelist": "અસાચવી શકાય તેવા સંદેશા" - } - }, - "auto_open_snaps": { - "name": "ઓટો ઓપન સ્નેપ્સ", - "description": "પ્રાપ્ત કરતી વખતે સ્નેપ આપમેળે ખોલે છે", - "options": { - "blacklist": "ઓટો ઓપન સ્નેપ્સમાંથી બાકાત રાખો", - "whitelist": "ઓટો ઓપન સ્નેપ્સ" - } - }, - "hide_friend_feed": { - "name": "મિત્ર ફીડમાંથી છુપાવો" - }, - "e2e_encryption": { - "name": "E2E એન્ક્રિપ્શનનો ઉપયોગ કરો" - }, - "pin_conversation": { - "name": "વાર્તાલાપ પિન કરો" - }, - "exclude_message_logger": { - "name": "સંદેશ લોગરમાંથી બાકાત રાખો" - } - } - }, - "actions": { - "clean_snapchat_cache": { - "name": "Snapchat કેશ સાફ કરો", - "description": "Snapchat કેશ સાફ કરે છે" - }, - "manage_friend_list": { - "name": "મિત્ર સૂચિનું સંચાલન કરો", - "description": "બેકઅપ લેતી વખતે તમારી મિત્ર સૂચિ આયાત/નિકાસ કરો" - }, - "export_chat_messages": { - "name": "ચેટ સંદેશા નિકાસ કરો", - "description": "વાર્તાલાપ સંદેશાને JSON/HTML/TXT ફાઇલમાં નિકાસ કરે છે" - }, - "export_memories": { - "name": "યાદો નિકાસ કરો", - "description": "યાદોને ZIP ફાઇલમાં નિકાસ કરે છે" - }, - "bulk_messaging_action": { - "name": "જથ્થાબંધ મેસેજિંગ ક્રિયા", - "description": "મિત્રોને કાઢી નાખવા અથવા વાર્તાલાપને મોટા પાયે કાઢી નાખવા જેવી કામગીરી કરે છે" - }, - "regen_mappings": { - "name": "મેપિંગ્સ ફરીથી જનરેટ કરો", - "description": "મેપિંગ્સ જાતે ફરીથી જનરેટ કરો" - }, - "change_language": { - "name": "ભાષા બદલો", - "description": "PurrfectSnap ની ભાષા બદલો" - }, - "file_imports": { - "name": "ફાઇલ આયાત", - "description": "Snapchat માં ઉપયોગ માટે ફાઇલો આયાત કરો" - }, - "friend_tracker": { - "name": "મિત્ર ટ્રેકર", - "description": "Snapchat પર તમારા મિત્રોને ટ્રેક કરો" - }, - "logger_history": { - "name": "લોગર ઇતિહાસ", - "description": "લોગ કરેલા સંદેશાઓનો ઇતિહાસ જુઓ" - } - }, - "features": { - "notices": { - "unstable": "⚠️ અસ્થિર", - "ban_risk": "⚠️ આ સુવિધા પ્રતિબંધનું કારણ બની શકે છે", - "internal_behavior": "⚠️ આ Snapchat ના આંતરિક વર્તનને તોડી શકે છે" - }, - "properties": { - "downloader": { - "name": "ડાઉનલોડર", - "description": "Snapchat મીડિયા ડાઉનલોડ કરો", - "properties": { - "save_folder": { - "name": "ફોલ્ડર સાચવો", - "description": "બધા મીડિયા ડાઉનલોડ કરવા માટે ડિરેક્ટરી પસંદ કરો" - }, - "auto_download_sources": { - "name": "ઓટો ડાઉનલોડ સ્ત્રોતો", - "description": "આપમેળે ડાઉનલોડ કરવા માટે સ્ત્રોતો પસંદ કરો" - }, - "prevent_self_auto_download": { - "name": "સ્વયં ઓટો ડાઉનલોડ અટકાવો", - "description": "તમારા પોતાના સ્નેપને આપમેળે ડાઉનલોડ થતા અટકાવે છે" - }, - "path_format": { - "name": "પાથ ફોર્મેટ", - "description": "ફાઇલ પાથ ફોર્મેટનો ઉલ્લેખ કરો" - }, - "allow_duplicate": { - "name": "ડુપ્લિકેટને મંજૂરી આપો", - "description": "એક જ મીડિયાને ઘણી વખત ડાઉનલોડ કરવાની મંજૂરી આપે છે" - }, - "merge_overlays": { - "name": "ઓવરલે ભેળવો", - "description": "સ્નેપના ટેક્સ્ટ અને મીડિયાને એક જ ફાઇલમાં જોડે છે" - }, - "force_image_format": { - "name": "છબી ફોર્મેટ દબાણ કરો", - "description": "છબીઓને નિર્દિષ્ટ ફોર્મેટમાં સાચવવા માટે દબાણ કરે છે" - }, - "force_voice_note_format": { - "name": "વોઇસ નોટ ફોર્મેટ દબાણ કરો", - "description": "વોઇસ નોટ્સને નિર્દિષ્ટ ફોર્મેટમાં સાચવવા માટે દબાણ કરે છે" - }, - "auto_download_voice_notes": { - "name": "ઓટો ડાઉનલોડ વોઇસ નોટ્સ", - "description": "વોઇસ નોટ્સ વગાડતી વખતે આપમેળે ડાઉનલોડ કરે છે" - }, - "download_profile_pictures": { - "name": "પ્રોફાઇલ ચિત્રો ડાઉનલોડ કરો", - "description": "તમને પ્રોફાઇલ પૃષ્ઠ પરથી પ્રોફાઇલ ચિત્રો ડાઉનલોડ કરવાની મંજૂરી આપે છે" - }, - "opera_download_button": { - "name": "ઓપેરા ડાઉનલોડ બટન", - "description": "સ્નેપ જોતી વખતે ઉપરના જમણા ખૂણામાં ડાઉનલોડ બટન ઉમેરે છે.\nબટનો પર લાંબા સમય સુધી દબાવવાથી ડાઉનલોડ દબાણ થશે" - }, - "download_context_menu": { - "name": "ડાઉનલોડ સંદર્ભ મેનૂ", - "description": "તમને સંદર્ભ મેનૂનો ઉપયોગ કરીને વાર્તાલાપ અથવા વાર્તામાંથી સંદેશાઓ ડાઉનલોડ/પૂર્વાવલોકન કરવાની મંજૂરી આપે છે.\nબટનો પર લાંબા સમય સુધી દબાવવાથી ડાઉનલોડ દબાણ થશે" - }, - "ffmpeg_options": { - "name": "FFmpeg વિકલ્પો", - "description": "વધારાના FFmpeg વિકલ્પોનો ઉલ્લેખ કરો", - "properties": { - "threads": { - "name": "થ્રેડો", - "description": "ઉપયોગ કરવા માટેના થ્રેડોની સંખ્યા" - }, - "preset": { - "name": "પ્રીસેટ", - "description": "રૂપાંતરણની ગતિ સેટ કરો" - }, - "constant_rate_factor": { - "name": "સતત દર પરિબળ", - "description": "વિડિઓ એન્કોડર માટે સતત દર પરિબળ સેટ કરો\nlibx264 માટે 0 થી 51 સુધી" - }, - "video_bitrate": { - "name": "વિડિઓ બિટરેટ", - "description": "વિડિઓ બિટરેટ સેટ કરો (kbps)" - }, - "audio_bitrate": { - "name": "ઓડિયો બિટરેટ", - "description": "ઓડિયો બિટરેટ સેટ કરો (kbps)" - }, - "custom_video_codec": { - "name": "કસ્ટમ વિડિઓ કોડેક", - "description": "કસ્ટમ વિડિઓ કોડેક સેટ કરો (દા.ત. libx264)" - }, - "custom_audio_codec": { - "name": "કસ્ટમ ઓડિયો કોડેક", - "description": "કસ્ટમ ઓડિયો કોડેક સેટ કરો (દા.ત. AAC)" - } - } - }, - "logging": { - "name": "લોગિંગ", - "description": "મીડિયા ડાઉનલોડ કરતી વખતે ટોસ્ટ બતાવે છે" - }, - "custom_path_format": { - "name": "કસ્ટમ પાથ ફોર્મેટ", - "description": "ડાઉનલોડ કરેલા મીડિયા માટે કસ્ટમ પાથ ફોર્મેટનો ઉલ્લેખ કરો\n\nઉપલબ્ધ ચલો:\n - %username%\n - %source%\n - %hash%\n - %date_time%" - } - } - }, - "user_interface": { - "name": "વપરાશકર્તા ઈન્ટરફેસ", - "description": "Snapchat નો દેખાવ અને અનુભવ બદલો", - "properties": { - "enable_app_appearance": { - "name": "એપ્લિકેશન દેખાવ સેટિંગ્સ સક્ષમ કરો", - "description": "છુપાયેલ એપ્લિકેશન દેખાવ સેટિંગને સક્ષમ કરે છે\nનવા Snapchat સંસ્કરણો પર જરૂરી ન હોઈ શકે" - }, - "friend_feed_message_preview": { - "name": "મિત્ર ફીડ સંદેશ પૂર્વાવલોકન", - "description": "મિત્ર ફીડમાં છેલ્લા સંદેશાઓનું પૂર્વાવલોકન બતાવે છે", - "properties": { - "amount": { - "name": "રકમ", - "description": "પૂર્વાવલોકન કરવા માટેના સંદેશાઓની રકમ" - } - } - }, - "snap_preview": { - "name": "સ્નેપ પૂર્વાવલોકન", - "description": "ચેટમાં ન જોયેલા સ્નેપની બાજુમાં એક નાનું પૂર્વાવલોકન પ્રદર્શિત કરે છે" - }, - "bootstrap_override": { - "name": "બુટસ્ટ્રેપ ઓવરરાઇડ", - "description": "વપરાશકર્તા ઈન્ટરફેસ બુટસ્ટ્રેપ સેટિંગ્સને ઓવરરાઇડ કરે છે", - "properties": { - "app_appearance": { - "name": "એપ્લિકેશન દેખાવ", - "description": "એક સતત એપ્લિકેશન દેખાવ સેટ કરે છે" - }, - "home_tab": { - "name": "હોમ ટેબ", - "description": "Snapchat ખોલતી વખતે સ્ટાર્ટઅપ ટેબને ઓવરરાઇડ કરે છે" - } - } - }, - "force_amoled_theme": { - "name": "અમોલેડ ડાર્ક મોડ", - "description": "ડાર્ક થીમ માટે સાચા કાળા પૃષ્ઠભૂમિનો ઉપયોગ કરે છે" - }, - "map_friend_nametags": { - "name": "ઉન્નત મિત્ર નકશા નામટેગ્સ", - "description": "સ્નેપમેપ પર મિત્રોના નામટેગ્સને સુધારે છે" - }, - "prevent_message_list_auto_scroll": { - "name": "સંદેશ સૂચિ ઓટો સ્ક્રોલ અટકાવો", - "description": "સંદેશ મોકલતી/પ્રાપ્ત કરતી વખતે સંદેશ સૂચિને તળિયે સ્ક્રોલ થતી અટકાવે છે" - }, - "streak_expiration_info": { - "name": "સ્ટ્રીક સમાપ્તિ માહિતી બતાવો", - "description": "સ્ટ્રીક્સ કાઉન્ટરની બાજુમાં સ્ટ્રીક સમાપ્તિ ટાઇમર બતાવે છે" - }, - "hide_friend_feed_entry": { - "name": "મિત્ર ફીડ એન્ટ્રી છુપાવો", - "description": "મિત્ર ફીડમાંથી ચોક્કસ મિત્રને છુપાવે છે\nઆ સુવિધાનું સંચાલન કરવા માટે સામાજિક ટેબનો ઉપયોગ કરો" - }, - "hide_streak_restore": { - "name": "સ્ટ્રીક પુનઃસ્થાપિત છુપાવો", - "description": "મિત્ર ફીડમાં પુનઃસ્થાપિત બટનને છુપાવે છે" - }, - "hide_quick_add_suggestions": { - "name": "ઝડપી ઉમેરો સૂચનો છુપાવો", - "description": "ઝડપી ઉમેરો મિત્ર સૂચનોને દૂર કરે છે" - }, - "hide_story_suggestions": { - "name": "વાર્તા સૂચનો છુપાવો", - "description": "વાર્તાઓ પૃષ્ઠમાંથી સૂચનોને દૂર કરે છે" - }, - "hide_ui_components": { - "name": "UI ઘટકો છુપાવો", - "description": "કયા UI ઘટકોને છુપાવવા તે પસંદ કરો" - }, - "opera_media_quick_info": { - "name": "ઓપેરા મીડિયા ઝડપી માહિતી", - "description": "ઓપેરા વ્યૂઅર સંદર્ભ મેનૂમાં મીડિયાની ઉપયોગી માહિતી જેમ કે બનાવટની તારીખ બતાવે છે" - }, - "old_bitmoji_selfie": { - "name": "જૂનું બિટમોજી સેલ્ફી", - "description": "જૂના Snapchat સંસ્કરણોમાંથી બિટમોજી સેલ્ફી પાછા લાવે છે" - }, - "disable_spotlight": { - "name": "સ્પોટલાઇટ અક્ષમ કરો", - "description": "સ્પોટલાઇટ પૃષ્ઠને અક્ષમ કરે છે" - }, - "friend_feed_menu_buttons": { - "name": "મિત્ર ફીડ મેનુ બટનો", - "description": "મિત્ર ફીડ મેનુમાં કયા બટનો બતાવવા તે પસંદ કરો" - }, - "auto_close_friend_feed_menu": { - "name": "મિત્ર ફીડ મેનુ આપમેળે બંધ કરો", - "description": "સેટિંગ બટન દબાવ્યા પછી મિત્ર ફીડ મેનુ આપમેળે બંધ કરે છે" - }, - "vertical_story_viewer": { - "name": "વર્ટિકલ સ્ટોરી વ્યૂઅર", - "description": "બધી વાર્તાઓ માટે વર્ટિકલ સ્ટોરી વ્યૂઅરને સક્ષમ કરે છે" - }, - "enable_friend_feed_menu_bar": { - "name": "મિત્ર ફીડ મેનુ બાર", - "description": "નવા મિત્ર ફીડ મેનુ બારને સક્ષમ કરે છે" - }, - "message_indicators": { - "name": "સંદેશ સૂચકો", - "description": "સંદેશાઓમાં વિશિષ્ટ સૂચક ચિહ્નો ઉમેરે છે\nનોંધ: સૂચકો 100% સચોટ ન હોઈ શકે" - }, - "stealth_mode_indicator": { - "name": "સ્ટીલ્થ મોડ સૂચક", - "description": "સ્ટીલ્થ મોડમાં વાર્તાલાપની બાજુમાં 👻 ઇમોજી ઉમેરે છે" - }, - "edit_text_override": { - "name": "ટેક્સ્ટ સંપાદન ઓવરરાઇડ", - "description": "ટેક્સ્ટ ફીલ્ડ વર્તનને ઓવરરાઇડ કરે છે" - }, - "prevent_forced_keyboard": { - "name": "દબાણયુક્ત કીબોર્ડ અટકાવો", - "description": "તમે વાર્તાલાપ ખોલો ત્યારે Snapchat ને આપમેળે કીબોર્ડ પોપ અપ થતું અટકાવે છે" - }, - "settings_menu": { - "name": "સેટિંગ્સ મેનુ", - "description": "તમે PurrfectSnap મેનુ ખોલવાની રીતને બદલે છે", - "options": { - "default": "ડિફોલ્ટ", - "legacy": "વારસો" - } - } - } - }, - "messaging": { - "name": "મેસેજિંગ", - "description": "તમે મિત્રો સાથે કેવી રીતે ક્રિયાપ્રતિક્રિયા કરો છો તે બદલો", - "properties": { - "bypass_screenshot_detection": { - "name": "સ્ક્રીનશોટ શોધને બાયપાસ કરો", - "description": "તમે સ્ક્રીનશોટ લો ત્યારે Snapchat ને શોધવાથી અટકાવે છે" - }, - "anonymous_story_viewing": { - "name": "અનામી વાર્તા જોવી", - "description": "કોઈને પણ જાણ થતી અટકાવે છે કે તમે તેમની વાર્તા જોઈ છે" - }, - "prevent_story_rewatch_indicator": { - "name": "વાર્તા ફરીથી જોવાનું સૂચક અટકાવો", - "description": "કોઈને પણ જાણ થતી અટકાવે છે કે તમે તેમની વાર્તા ફરીથી જોઈ છે" - }, - "hide_peek_a_peek": { - "name": "પીક-એ-પીક છુપાવો", - "description": "તમે ચેટમાં અડધો સ્વાઇપ કરો ત્યારે સૂચના મોકલવાથી અટકાવે છે" - }, - "hide_bitmoji_presence": { - "name": "બિટમોજી હાજરી છુપાવો", - "description": "ચેટમાં હોય ત્યારે તમારા બિટમોજીને પોપ અપ થતા અટકાવે છે" - }, - "hide_typing_notifications": { - "name": "ટાઇપિંગ સૂચનાઓ છુપાવો", - "description": "કોઈને પણ જાણ થતી અટકાવે છે કે તમે સંદેશ ટાઇપ કરી રહ્યા છો" - }, - "unlimited_snap_view_time": { - "name": "અમર્યાદિત સ્નેપ જોવાનો સમય", - "description": "સ્નેપ જોવા માટે સમય મર્યાદા દૂર કરે છે" - }, - "auto_mark_as_read": { - "name": "આપમેળે વાંચેલ તરીકે ચિહ્નિત કરો", - "description": "સ્ટીલ્થ મોડ સક્ષમ હોય ત્યારે પણ સંદેશાઓ/સ્નેપને આપમેળે વાંચેલ તરીકે ચિહ્નિત કરે છે" - }, - "mark_snap_as_seen_button": { - "name": "સ્નેપને જોયેલ તરીકે ચિહ્નિત કરો બટન", - "description": "સ્નેપ જોતી વખતે તેને જોયેલ તરીકે ચિહ્નિત કરવા માટે એક બટન ઉમેરે છે.\nઆ સ્ટીલ્થ મોડ સક્ષમ હોય ત્યારે પણ કામ કરશે" - }, - "skip_when_marking_as_seen": { - "name": "જોયેલ તરીકે ચિહ્નિત કરતી વખતે અવગણો", - "description": "સ્નેપને જોયેલ તરીકે ચિહ્નિત કરતી વખતે આપમેળે આગલા સ્નેપ પર અવગણે છે.\nસ્નેપને જોયેલ તરીકે ચિહ્નિત કરો બટન સાથે સંયોજનમાં ઉપયોગ કરો" - }, - "loop_media_playback": { - "name": "લૂપ મીડિયા પ્લેબેક", - "description": "સ્નેપ/વાર્તાઓ જોતી વખતે મીડિયા પ્લેબેકને લૂપ કરે છે" - }, - "disable_replay_in_ff": { - "name": "FF માં રિપ્લે અક્ષમ કરો", - "description": "મિત્ર ફીડમાંથી લાંબા સમય સુધી દબાવીને રિપ્લે કરવાની ક્ષમતાને અક્ષમ કરે છે" - }, - "half_swipe_notifier": { - "name": "અડધો સ્વાઇપ સૂચક", - "description": "જ્યારે કોઈ વાર્તાલાપમાં અડધો સ્વાઇપ કરે ત્યારે તમને સૂચિત કરે છે", - "properties": { - "min_duration": { - "name": "ન્યૂનતમ અવધિ", - "description": "અડધા સ્વાઇપની ન્યૂનતમ અવધિ (સેકંડમાં)" - }, - "max_duration": { - "name": "મહત્તમ અવધિ", - "description": "અડધા સ્વાઇપની મહત્તમ અવધિ (સેકંડમાં)" - } - } - }, - "call_start_confirmation": { - "name": "કોલ પ્રારંભ પુષ્ટિ", - "description": "કોલ શરૂ કરતી વખતે પુષ્ટિ સંવાદ બતાવે છે" - }, - "unlimited_conversation_pinning": { - "name": "અમર્યાદિત વાર્તાલાપ પિનિંગ", - "description": "તમને સ્થાનિક રીતે અમર્યાદિત સંખ્યામાં વાર્તાલાપ પિન કરવાની મંજૂરી આપે છે" - }, - "disable_snap_mode_restrictions": { - "name": "સ્નેપ મોડ પ્રતિબંધો અક્ષમ કરો", - "description": "તમને પ્રતિબંધો વિના સ્વ-વિનાશક સ્નેપ જોવાની મંજૂરી આપે છે" - }, - "prevent_message_sending": { - "name": "સંદેશ મોકલવાનું અટકાવો", - "description": "ચોક્કસ પ્રકારના સંદેશા મોકલવાનું અટકાવે છે" - }, - "friend_mutation_notifier": { - "name": "મિત્ર મ્યુટેશન સૂચક", - "description": "જ્યારે મિત્રના પ્રોફાઇલમાં કંઈક બદલાય ત્યારે તમને સૂચિત કરે છે" - }, - "better_notifications": { - "name": "વધુ સારી સૂચનાઓ", - "description": "પ્રાપ્ત સૂચનાઓમાં વધુ માહિતી ઉમેરે છે", - "properties": { - "group_notifications": { - "name": "જૂથ સૂચનાઓ", - "description": "જૂથ સૂચનાઓને એકમાં જૂથબદ્ધ કરો" - }, - "chat_preview": { - "name": "ચેટ પૂર્વાવલોકન", - "description": "સૂચનામાં પ્રાપ્ત સંદેશાઓનું પૂર્વાવલોકન બતાવે છે" - }, - "media_preview": { - "name": "મીડિયા પૂર્વાવલોકન", - "description": "સૂચનામાં પસંદ કરેલા મીડિયા પ્રકારોનું પૂર્વાવલોકન બતાવે છે" - }, - "media_caption": { - "name": "મીડિયા કેપ્શન", - "description": "સૂચનામાં મીડિયાના જોડાયેલા કેપ્શનને બતાવે છે" - }, - "stacked_media_messages": { - "name": "સ્ટેક્ડ મીડિયા સંદેશા", - "description": "જ્યારે તેઓ પૂર્વાવલોકન કરી શકાતા નથી ત્યારે બહુવિધ મીડિયા સંદેશાઓને એક ટેક્સ્ટ સૂચનામાં જોડે છે. ચેટ પૂર્વાવલોકન સાથે સંયોજનમાં ઉપયોગ કરો" - }, - "friend_add_source": { - "name": "મિત્ર ઉમેરો સ્ત્રોત", - "description": "સૂચનામાં મિત્ર વિનંતીનો સ્ત્રોત બતાવે છે" - }, - "reply_button": { - "name": "જવાબ બટન", - "description": "સૂચનામાં જવાબ બટન ઉમેરે છે" - }, - "smart_replies": { - "name": "સ્માર્ટ જવાબો", - "description": "સૂચનાઓમાં સૂચવેલા જવાબો ઉમેરે છે (Android 10+). જવાબ બટન સાથે સંયોજનમાં ઉપયોગ કરો" - }, - "download_button": { - "name": "ડાઉનલોડ બટન", - "description": "તમને સૂચનામાંથી મીડિયા ડાઉનલોડ કરવાની મંજૂરી આપે છે" - }, - "mark_as_read_button": { - "name": "વાંચેલ તરીકે ચિહ્નિત કરો બટન", - "description": "તમને સૂચનામાંથી સંદેશને વાંચેલ તરીકે ચિહ્નિત કરવાની મંજૂરી આપે છે" - }, - "mark_as_read_and_save_in_chat": { - "name": "વાંચેલ તરીકે ચિહ્નિત કરો અને ચેટમાં સાચવો", - "description": "સૂચનામાં વાંચેલ તરીકે ચિહ્નિત કરો અને ચેટમાં સાચવો બટન ઉમેરે છે" - } - } - }, - "notification_blacklist": { - "name": "સૂચના બ્લેકલિસ્ટ", - "description": "કઈ સૂચનાઓ અવરોધિત થવી જોઈએ તે પસંદ કરો" - }, - "message_logger": { - "name": "સંદેશ લોગર", - "description": "સંદેશાને કાઢી નાખવાથી અટકાવે છે", - "properties": { - "keep_my_own_messages": { - "name": "મારા પોતાના સંદેશા રાખો", - "description": "તમારા પોતાના સંદેશાને કાઢી નાખવાથી અટકાવે છે" - }, - "auto_purge": { - "name": "ઓટો પર્જ", - "description": "નિર્દિષ્ટ સમય કરતાં જૂના કેશ્ડ સંદેશાને આપમેળે કાઢી નાખે છે" - }, - "message_filter": { - "name": "સંદેશ ફિલ્ટર", - "description": "કયા સંદેશા લોગ થવા જોઈએ તે પસંદ કરો (બધા સંદેશા માટે ખાલી)" - }, - "deleted_message_color": { - "name": "કાઢી નાખેલ સંદેશનો રંગ", - "description": "કાઢી નાખેલા સંદેશાઓનો રંગ સેટ કરે છે" - } - } - }, - "auto_save_messages_in_conversations": { - "name": "વાર્તાલાપમાં સંદેશા આપમેળે સાચવો", - "description": "વાર્તાલાપમાં દરેક સંદેશને આપમેળે સાચવે છે" - }, - "gallery_media_send_override": { - "name": "ગેલેરી મીડિયા મોકલો ઓવરરાઇડ", - "description": "ગેલેરીમાંથી મોકલતી વખતે મીડિયા સ્ત્રોતને સ્પૂફ કરે છે" - }, - "strip_media_metadata": { - "name": "મીડિયા મેટાડેટા સ્ટ્રીપ કરો", - "description": "સંદેશ તરીકે મોકલતા પહેલા મીડિયાના મેટાડેટાને દૂર કરે છે" - }, - "bypass_message_retention_policy": { - "name": "સંદેશ રીટેન્શન નીતિને બાયપાસ કરો", - "description": "સંદેશા જોયા પછી તેને કાઢી નાખવાથી અટકાવે છે" - }, - "bypass_message_action_restrictions": { - "name": "સંદેશ ક્રિયા પ્રતિબંધોને બાયપાસ કરો", - "description": "તમને સ્નેપ ખોલ્યા વિના તેના પર પ્રતિક્રિયા આપવા અથવા અસાચવી શકાય તેવા સંદેશને સાચવવાની મંજૂરી આપે છે" - }, - "remove_groups_locked_status": { - "name": "જૂથોની લોક કરેલી સ્થિતિ દૂર કરો", - "description": "તમને બહાર કાઢ્યા પછી જૂથ માહિતી જોવાની મંજૂરી આપે છે" - }, - "double_tap_chat_action": { - "name": "ડબલ ટેપ ચેટ ક્રિયા", - "description": "ચેટમાં સંદેશ પર ડબલ ટેપ કરતી વખતે કસ્ટમ ક્રિયા કરે છે" - }, - "double_tap_chat_action_custom_emoji": { - "name": "ડબલ ટેપ ચેટ ક્રિયા કસ્ટમ ઇમોજી પ્રતિક્રિયા", - "description": "ડબલ ટેપ ચેટ ક્રિયા માટે કસ્ટમ ઇમોજી પ્રતિક્રિયા સેટ કરે છે" - } - } - }, - "global": { - "name": "વૈશ્વિક", - "description": "વૈશ્વિક Snapchat સેટિંગ્સને ટ્વિક કરો", - "properties": { - "better_location": { - "name": "વધુ સારી જગ્યા", - "description": "Snapchat સ્થાનને વધારે છે", - "properties": { - "spoof_location": { - "name": "સ્થાન સ્પૂફ કરો", - "description": "તમારા સ્થાનને નિર્દિષ્ટ સ્થાન પર સ્પૂફ કરે છે" - }, - "coordinates": { - "name": "કોઓર્ડિનેટ્સ", - "description": "સ્પૂફ કરેલા સ્થાનના કોઓર્ડિનેટ્સ સેટ કરો" - }, - "walk_radius": { - "name": "ચાલવાની ત્રિજ્યા", - "description": "આ ત્રિજ્યામાં રેન્ડમલી ચાલો (ફૂટ)" - }, - "always_update_location": { - "name": "હંમેશા સ્થાન અપડેટ કરો", - "description": "કોઈ GPS ડેટા પ્રાપ્ત ન થાય ત્યારે પણ Snapchat ને સ્થાન અપડેટ કરવા દબાણ કરો" - }, - "suspend_location_updates": { - "name": "સ્થાન અપડેટ્સ સ્થગિત કરો", - "description": "તમારા સ્થાનને અપડેટ થતું અટકાવે છે" - }, - "spoof_battery_level": { - "name": "બેટરી સ્તર સ્પૂફ કરો", - "description": "નકશા પર તમારા ઉપકરણના બેટરી સ્તરને સ્પૂફ કરે છે\nમૂલ્ય 0 અને 100 ની વચ્ચે હોવું આવશ્યક છે" - }, - "spoof_headphones": { - "name": "હેડફોન સ્પૂફ કરો", - "description": "નકશા પર સંગીત સાંભળવાની સ્થિતિને સ્પૂફ કરે છે" - }, - "show_battery_level": { - "name": "બેટરી સ્તર બતાવો", - "description": "નકશા પર તમારા મિત્રોના બેટરી સ્તરને બતાવે છે" - } - } - }, - "snapchat_plus": { - "name": "સ્નેપચેટ વત્તા", - "description": "Snapchat Plus સુવિધાઓને સક્ષમ કરે છે\nકેટલીક સર્વર-સાઇડ સુવિધાઓ કામ ન કરી શકે" - }, - "media_upload_quality": { - "name": "મીડિયા અપલોડ ગુણવત્તા", - "description": "મીડિયા અપલોડ ગુણવત્તાને ઓવરરાઇડ કરે છે", - "properties": { - "force_video_upload_source_quality": { - "name": "વિડિઓ અપલોડ સ્ત્રોત ગુણવત્તા દબાણ કરો", - "description": "વિડિઓ અપલોડ કરતી વખતે સ્ત્રોત ગુણવત્તાનો ઉપયોગ કરવા Snapchat ને દબાણ કરે છે\nકૃપા કરીને નોંધો કે આ મીડિયામાંથી મેટાડેટાને દૂર ન કરી શકે" - }, - "disable_image_compression": { - "name": "છબી સંકોચન અક્ષમ કરો", - "description": "મીડિયા અપલોડ કરતી વખતે છબી સંકોચનને અક્ષમ કરે છે" - }, - "custom_image_upload_format": { - "name": "કસ્ટમ છબી અપલોડ ફોર્મેટ", - "description": "કસ્ટમ છબી અપલોડ ફોર્મેટ સેટ કરે છે\nશ્રેષ્ઠ ગુણવત્તા માટે લોસલેસ ફોર્મેટ (જેમ કે PNG) પસંદ કરો" - } - } - }, - "disable_confirmation_dialogs": { - "name": "પુષ્ટિ સંવાદો અક્ષમ કરો", - "description": "પસંદ કરેલી ક્રિયાઓને આપમેળે પુષ્ટિ કરે છે" - }, - "auto_updater": { - "name": "ઓટો અપડેટર", - "description": "નવા અપડેટ્સ માટે આપમેળે તપાસે છે" - }, - "disable_metrics": { - "name": "મેટ્રિક્સ અક્ષમ કરો", - "description": "Snapchat પર વિશિષ્ટ એનાલિટિક્સ ડેટા મોકલવાનું અવરોધે છે" - }, - "disable_story_sections": { - "name": "વાર્તા વિભાગો અક્ષમ કરો", - "description": "વાર્તાઓ પૃષ્ઠમાંથી વિભાગોને દૂર કરે છે\nયોગ્ય રીતે કામ કરવા માટે રિફ્રેશની જરૂર પડી શકે છે" - }, - "block_ads": { - "name": "જાહેરાતો અવરોધિત કરો", - "description": "જાહેરાતોને પ્રદર્શિત થતી અટકાવે છે" - }, - "disable_custom_tabs": { - "name": "કસ્ટમ ટેબ્સ અક્ષમ કરો", - "description": "વેબ બ્રાઉઝરને બદલે સમર્થિત એપ્લિકેશનોમાં લિંક્સ ખોલે છે" - }, - "disable_permission_requests": { - "name": "પરવાનગી વિનંતીઓ અક્ષમ કરો", - "description": "Snapchat ને વિશિષ્ટ પરવાનગીઓ માટે પૂછવાથી અટકાવે છે" - }, - "disable_memories_snap_feed": { - "name": "યાદો સ્નેપ ફીડ અક્ષમ કરો", - "description": "તમે કેમેરામાં ઉપર સ્વાઇપ કરો ત્યારે Snapchat ને તાજેતરની યાદો બતાવવાથી અટકાવે છે" - }, - "spotlight_comments_username": { - "name": "સ્પોટલાઇટ ટિપ્પણીઓ વપરાશકર્તાનામ", - "description": "સ્પોટલાઇટ ટિપ્પણીઓમાં લેખકનું વપરાશકર્તાનામ બતાવે છે" - }, - "bypass_video_length_restriction": { - "name": "વિડિઓ લંબાઈ પ્રતિબંધને બાયપાસ કરો", - "description": "એકલ: એક જ વિડિઓ મોકલે છે\nવિભાજીત: સંપાદન પછી વિડિઓઝને વિભાજીત કરો" - }, - "default_video_playback_rate": { - "name": "ડિફોલ્ટ વિડિઓ પ્લેબેક દર", - "description": "વિડિઓઝના પ્લેબેક માટે ડિફોલ્ટ ગતિ સેટ કરે છે\nમૂલ્ય 0.1 અને 4.0 ની વચ્ચે હોવું આવશ્યક છે" - }, - "video_playback_rate_slider": { - "name": "વિડિઓ પ્લેબેક દર સ્લાઇડર", - "description": "વિડિઓ પ્લેબેક દર બદલવા માટે ઓપેરા સંદર્ભ મેનૂમાં સ્લાઇડર ઉમેરે છે\nનોંધ: ફેરફારો ફક્ત પછીના વિડિઓઝ પર લાગુ થાય છે" - }, - "disable_google_play_dialogs": { - "name": "Google Play સેવાઓ સંવાદો અક્ષમ કરો", - "description": "Google Play સેવાઓ ઉપલબ્ધતા સંવાદોને બતાવવાથી અટકાવો" - }, - "default_volume_controls": { - "name": "ડિફોલ્ટ વોલ્યુમ નિયંત્રણો", - "description": "Snapchat ને સિસ્ટમ વોલ્યુમ નિયંત્રણોનો ઉપયોગ કરવા દબાણ કરે છે" - }, - "disable_telecom_framework": { - "name": "ટેલિકોમ ફ્રેમવર્ક અક્ષમ કરો", - "description": "Snapchat ને Android ટેલિકોમ ફ્રેમવર્કનો ઉપયોગ કરતા અટકાવે છે\nઆ તમને કોલ પર હોય ત્યારે સંગીત સાંભળવાની મંજૂરી આપે છે" - }, - "hide_active_music": { - "name": "સક્રિય સંગીત છુપાવો", - "description": "Snapchat ને જાણ થતી અટકાવે છે કે તમે સંગીત સાંભળી રહ્યા છો\nઆ તમને સંગીત સાંભળતી વખતે નિયંત્રણ વોલ્યુમ બટનોનો ઉપયોગ કરીને સ્નેપ લેવાની મંજૂરી આપશે" - }, - "disable_snap_splitting": { - "name": "સ્નેપ વિભાજન અક્ષમ કરો", - "description": "સ્નેપને બહુવિધ ભાગોમાં વિભાજીત થતા અટકાવે છે\nતમે મોકલો છો તે ચિત્રો વિડિઓઝમાં ફેરવાઈ જશે" - } - } - }, - "rules": { - "name": "નિયમો", - "description": "વ્યક્તિગત લોકો માટે સ્વચાલિત સુવિધાઓનું સંચાલન કરો" - }, - "camera": { - "name": "કેમેરા", - "description": "સંપૂર્ણ સ્નેપ માટે યોગ્ય સેટિંગ્સને સમાયોજિત કરો", - "properties": { - "disable_cameras": { - "name": "કેમેરા અક્ષમ કરો", - "description": "Snapchat ને પસંદ કરેલા કેમેરાનો ઉપયોગ કરતા અટકાવે છે" - }, - "black_photos": { - "name": "કાળા ફોટા", - "description": "કેપ્ચર કરેલા ફોટાને કાળા પૃષ્ઠભૂમિથી બદલે છે\nવિડિઓઝને અસર થતી નથી" - }, - "immersive_camera_preview": { - "name": "ઇમર્સિવ પૂર્વાવલોકન", - "description": "Snapchat ને કેમેરા પૂર્વાવલોકનને કાપવાથી અટકાવે છે\nઆ કેટલાક ઉપકરણો પર કેમેરાને ફ્લિકર કરી શકે છે" - }, - "override_front_resolution": { - "name": "આગળના રિઝોલ્યુશનને ઓવરરાઇડ કરો", - "description": "આગળના કેમેરા માટે કેમેરા રિઝોલ્યુશનને ઓવરરાઇડ કરે છે" - }, - "override_back_resolution": { - "name": "પાછળના રિઝોલ્યુશનને ઓવરરાઇડ કરો", - "description": "પાછળના કેમેરા માટે કેમેરા રિઝોલ્યુશનને ઓવરરાઇડ કરે છે" - }, - "custom_resolution": { - "name": "કસ્ટમ રિઝોલ્યુશન", - "description": "કસ્ટમ કેમેરા રિઝોલ્યુશન સેટ કરે છે, પહોળાઈ x ઊંચાઈ (દા.ત. 1920x1080).\nકસ્ટમ રિઝોલ્યુશન તમારા ઉપકરણ દ્વારા સમર્થિત હોવું આવશ્યક છે" - }, - "front_custom_frame_rate": { - "name": "આગળનો કસ્ટમ ફ્રેમ દર", - "description": "આગળના કેમેરાના ફ્રેમ દરને ઓવરરાઇડ કરે છે" - }, - "back_custom_frame_rate": { - "name": "પાછળનો કસ્ટમ ફ્રેમ દર", - "description": "પાછળના કેમેરાના ફ્રેમ દરને ઓવરરાઇડ કરે છે" - }, - "force_camera_source_encoding": { - "name": "કેમેરા સ્ત્રોત એન્કોડિંગ દબાણ કરો", - "description": "કેમેરા સ્ત્રોત એન્કોડિંગને દબાણ કરે છે" - }, - "startup_default_camera": { - "name": "સ્ટાર્ટઅપ ડિફોલ્ટ કેમેરા", - "description": "Snapchat ખોલતી વખતે ડિફોલ્ટ કેમેરા સેટ કરે છે" - }, - "hevc_recording": { - "name": "HEVC રેકોર્ડિંગ", - "description": "વિડિઓ રેકોર્ડિંગ માટે HEVC (H.265) કોડેકનો ઉપયોગ કરે છે" - } - } - }, - "streaks_reminder": { - "name": "સ્ટ્રીક્સ રીમાઇન્ડર", - "description": "તમને સમયાંતરે તમારી સ્ટ્રીક્સ વિશે સૂચિત કરે છે", - "properties": { - "interval": { - "name": "અંતરાલ", - "description": "દરેક રીમાઇન્ડર વચ્ચેનો અંતરાલ (કલાકો)" - }, - "remaining_hours": { - "name": "બાકીનો સમય", - "description": "સૂચના બતાવવામાં આવે તે પહેલાં બાકી રહેલો સમય (કલાકો)" - }, - "group_notifications": { - "name": "જૂથ સૂચનાઓ", - "description": "જૂથ સૂચનાઓને એકમાં જૂથબદ્ધ કરો" - } - } - }, - "experimental": { - "name": "પ્રાયોગિક", - "description": "પ્રાયોગિક સુવિધાઓ", - "properties": { - "native_hooks": { - "name": "મૂળ હુક્સ", - "description": "અસુરક્ષિત સુવિધાઓ જે Snapchat ના મૂળ કોડમાં હૂક કરે છે", - "properties": { - "composer_hooks": { - "name": "કમ્પોઝર હુક્સ", - "description": "કમ્પોઝર ક્રોસ-પ્લેટફોર્મ UI ફ્રેમવર્કમાં કોડ ઇન્જેક્ટ કરે છે", - "properties": { - "show_first_created_username": { - "name": "પ્રથમ બનાવેલ વપરાશકર્તાનામ બતાવો", - "description": "પ્રોફાઇલ પૃષ્ઠ પર વર્તમાન વપરાશકર્તાનામની બાજુમાં પ્રથમ બનાવેલ વપરાશકર્તાનામ બતાવે છે" - }, - "bypass_camera_roll_limit": { - "name": "કેમેરા રોલ મર્યાદાને બાયપાસ કરો", - "description": "તમે કેમેરા રોલમાંથી મોકલી શકો તે મીડિયાની મહત્તમ રકમ વધારે છે" - }, - "custom_self_destruct_snap_delay": { - "name": "કસ્ટમ સ્વ-વિનાશ સ્નેપ વિલંબ", - "description": "સ્નેપ મોકલતી વખતે સ્વ-વિનાશ ટાઇમર માટે વધુ વિકલ્પો આપે છે" - }, - "composer_console": { - "name": "કમ્પોઝર કોન્સોલ", - "description": "તમને કમ્પોઝરમાં JavaScript કોડ ચલાવવાની મંજૂરી આપે છે (ફક્ત arm64)" - }, - "composer_logs": { - "name": "કમ્પોઝર લોગ્સ", - "description": "કમ્પોઝરના કોન્સોલ લોગ્સને PurrfectSnap પર રીડાયરેક્ટ કરે છે" - } - } - }, - "disable_bitmoji": { - "name": "બિટમોજી અક્ષમ કરો", - "description": "મિત્રો પ્રોફાઇલ બિટમોજીને અક્ષમ કરે છે" - }, - "custom_emoji_font": { - "name": "કસ્ટમ ઇમોજી ફોન્ટ", - "description": "તમને કસ્ટમ ઇમોજી ફોન્ટનો ઉપયોગ કરવાની મંજૂરી આપે છે. ફક્ત .ttf ફોન્ટ્સ સાથે કામ કરે છે" - }, - "custom_shared_library": { - "name": "કસ્ટમ શેર્ડ લાઇબ્રેરી", - "description": "Snapchat માં કસ્ટમ શેર્ડ લાઇબ્રેરી લોડ કરે છે. આ સુવિધા ફક્ત પરીક્ષણ હેતુઓ માટે છે" - } - } - }, - "spoof": { - "name": "સ્પૂફ", - "description": "તમારા વિશેની વિવિધ માહિતીને સ્પૂફ કરો", - "properties": { - "play_store_installer_package_name": { - "name": "પ્લે સ્ટોર ઇન્સ્ટોલર પેકેજ નામ", - "description": "ઇન્સ્ટોલર પેકેજ નામને com.android.vending પર ઓવરરાઇડ કરે છે" - }, - "remove_vpn_transport_flag": { - "name": "VPN ટ્રાન્સપોર્ટ ફ્લેગ દૂર કરો", - "description": "Snapchat ને VPN શોધવાથી અટકાવે છે" - }, - "remove_mock_location_flag": { - "name": "મૉક સ્થાન ફ્લેગ દૂર કરો", - "description": "Snapchat ને મૉક સ્થાન શોધવાથી અટકાવે છે" - } - } - }, - "convert_message_locally": { - "name": "સંદેશને સ્થાનિક રીતે રૂપાંતરિત કરો", - "description": "સ્નેપને સ્થાનિક રીતે ચેટ બાહ્ય મીડિયામાં રૂપાંતરિત કરે છે. આ ચેટ ડાઉનલોડ સંદર્ભ મેનૂમાં દેખાય છે" - }, - "media_file_picker": { - "name": "મીડિયા ફાઇલ પીકર", - "description": "તમને ગેલેરીમાંથી કોઈપણ વિડિઓ/ઓડિયો ફાઇલ પસંદ કરવાની મંજૂરી આપે છે" - }, - "story_logger": { - "name": "વાર્તા લોગર", - "description": "મિત્રોની વાર્તાઓનો ઇતિહાસ પ્રદાન કરે છે" - }, - "call_recorder": { - "name": "કોલ રેકોર્ડર", - "description": "ઓડિયો કોલ્સ આપમેળે રેકોર્ડ કરે છે" - }, - "account_switcher": { - "name": "એકાઉન્ટ સ્વિચર", - "description": "તમને લોગ આઉટ કર્યા વિના એકાઉન્ટ્સ વચ્ચે સ્વિચ કરવાની મંજૂરી આપે છે\nમેનુ ખોલવા માટે તમારા બિટમોજી પ્રોફાઇલની બાજુમાં શોધ આઇકોન પર લાંબા સમય સુધી દબાવો\nનોંધ: આ સુવિધા પ્રાયોગિક છે અને ભવિષ્યમાં બદલાવાની શક્યતા છે", - "properties": { - "auto_backup_current_account": { - "name": "વર્તમાન એકાઉન્ટનો ઓટો બેકઅપ", - "description": "લોગ આઉટ કરતી વખતે અથવા એકાઉન્ટ્સ સ્વિચ કરતી વખતે વર્તમાન એકાઉન્ટનો આપમેળે બેકઅપ લે છે" - } - } - }, - "better_transcript": { - "name": "વધુ સારી ટ્રાન્સક્રિપ્ટ", - "description": "વોઇસ નોટ ટ્રાન્સક્રિપ્ટને સુધારે છે", - "properties": { - "force_transcription": { - "name": "વોઇસ નોટ ટ્રાન્સક્રિપ્શન દબાણ કરો", - "description": "બધી વોઇસ નોટ્સને ટ્રાન્સક્રાઇબ કરવાની મંજૂરી આપે છે" - }, - "preferred_transcription_lang": { - "name": "પસંદગીની ટ્રાન્સક્રિપ્શન ભાષા", - "description": "વોઇસ નોટ ટ્રાન્સક્રિપ્ટ માટે પસંદગીની ભાષા (દા.ત. EN, ES, FR)" - }, - "notification_transcript": { - "name": "સૂચના ટ્રાન્સક્રિપ્ટ", - "description": "સૂચનાઓમાં વોઇસ નોટ્સને ટ્રાન્સક્રાઇબ કરે છે\nઆ સુવિધાને વધુ સારી સૂચનાઓમાં ચેટ પૂર્વાવલોકન સુવિધા સક્ષમ કરવાની જરૂર છે" - } - } - }, - "voice_note_auto_play": { - "name": "વોઇસ નોટ ઓટો પ્લે", - "description": "વર્તમાન વોઇસ નોટ સમાપ્ત થયા પછી આગલી વોઇસ નોટ આપમેળે વગાડે છે" - }, - "friend_notes": { - "name": "મિત્ર નોંધો", - "description": "તમને મિત્રોના પ્રોફાઇલમાં નોંધો ઉમેરવાની મંજૂરી આપે છે" - }, - "cof_experiments": { - "name": "COF પ્રયોગો", - "description": "પ્રકાશિત ન થયેલ/બીટા Snapchat સુવિધાઓને સક્ષમ કરે છે" - }, - "context_menu_fix": { - "name": "સંદર્ભ મેનુ ફિક્સ", - "description": "મિત્ર ફીડ મેનુને સમારકામ કરવાનો પ્રયાસ કરો કારણ કે જ્યારે ઉપકરણ ઓફલાઇન હોય ત્યારે તે યોગ્ય રીતે પ્રદર્શિત થઈ શકતું નથી" - }, - "app_lock": { - "name": "એપ્લિકેશન લોક", - "description": "પાસકોડ વિના Snapchat માં પ્રવેશ અટકાવે છે", - "properties": { - "lock_on_resume": { - "name": "ફરી શરૂ કરવા પર લોક કરો", - "description": "જ્યારે એપ્લિકેશન ફરીથી ખોલવામાં આવે ત્યારે તેને લોક કરે છે" - } - } - }, - "infinite_story_boost": { - "name": "અનંત વાર્તા બુસ્ટ", - "description": "વાર્તા બુસ્ટ મર્યાદા વિલંબને બાયપાસ કરો" - }, - "meo_passcode_bypass": { - "name": "મારી આંખો ફક્ત પાસકોડ બાયપાસ", - "description": "મારી આંખો ફક્ત પાસકોડને બાયપાસ કરો\nઆ ફક્ત ત્યારે જ કામ કરશે જો પાસકોડ પહેલા યોગ્ય રીતે દાખલ કરવામાં આવ્યો હોય" - }, - "no_friend_score_delay": { - "name": "કોઈ મિત્ર સ્કોર વિલંબ નથી", - "description": "મિત્રોનો સ્કોર જોતી વખતે વિલંબ દૂર કરે છે" - }, - "best_friend_pinning": { - "name": "શ્રેષ્ઠ મિત્ર પિનિંગ", - "description": "તમને તમારા નંબર વન શ્રેષ્ઠ મિત્ર તરીકે મિત્રને પિન કરવાની મંજૂરી આપે છે. નોંધ: ફક્ત તમે જ તમારા પિન કરેલા શ્રેષ્ઠ મિત્રને જોઈ શકો છો" - }, - "e2ee": { - "name": "એન્ડ-ટુ-એન્ડ એન્ક્રિપ્શન", - "description": "તમારા સંદેશાઓને વહેંચાયેલ ગુપ્ત કીનો ઉપયોગ કરીને AES સાથે એન્ક્રિપ્ટ કરે છે\nતમારી કી ક્યાંક સુરક્ષિત સાચવવાની ખાતરી કરો!", - "properties": { - "encrypted_message_indicator": { - "name": "એન્ક્રિપ્ટેડ સંદેશ સૂચક", - "description": "એન્ક્રિપ્ટેડ સંદેશાઓની બાજુમાં 🔒 ઇમોજી ઉમેરે છે" - }, - "force_message_encryption": { - "name": "સંદેશ એન્ક્રિપ્શન દબાણ કરો", - "description": "ફક્ત જ્યારે બહુવિધ વાર્તાલાપ પસંદ કરવામાં આવે ત્યારે E2E એન્ક્રિપ્શન સક્ષમ ન હોય તેવા લોકોને એન્ક્રિપ્ટેડ સંદેશા મોકલવાનું અટકાવે છે" - } - } - }, - "add_friend_source_spoof": { - "name": "મિત્ર ઉમેરો સ્ત્રોત સ્પૂફ", - "description": "મિત્ર વિનંતીના સ્ત્રોતને સ્પૂફ કરે છે" - }, - "hidden_snapchat_plus_features": { - "name": "છુપાયેલ Snapchat Plus સુવિધાઓ", - "description": "પ્રકાશિત ન થયેલ/બીટા Snapchat Plus સુવિધાઓને સક્ષમ કરે છે\nજૂના Snapchat સંસ્કરણો પર કામ ન કરી શકે" - }, - "custom_streaks_expiration_format": { - "name": "કસ્ટમ સ્ટ્રીક્સ સમાપ્તિ ફોર્મેટ", - "description": "સ્ટ્રીક્સ સમાપ્તિ ફોર્મેટને કસ્ટમાઇઝ કરે છે\n\nઉપલબ્ધ ચલો:\n - %c: સ્ટ્રીક્સ ગણતરી\n - %e: કલાકગ્લાસ ઇમોજી\n - %d: દિવસો\n - %h: કલાકો\n - %m: મિનિટો\n - %s: સેકંડ\n - %w: બાકીનો સમય" - }, - "prevent_forced_logout": { - "name": "દબાણયુક્ત લોગઆઉટ અટકાવો", - "description": "તમે બીજા ઉપકરણ પર લોગિન કરો ત્યારે Snapchat ને તમને લોગ આઉટ કરતા અટકાવે છે" - }, - "snapscore_changes": { - "name": "સ્નેપસ્કોર ફેરફારો", - "description": "મિત્રોના સ્નેપસ્કોરમાં ફેરફારોને ટ્રેક કરે છે\nઆ સુવિધાનો ઉપયોગ ફક્ત Snapchat ના નવા સંસ્કરણોમાં કરો" - } - } - }, - "scripting": { - "name": "સ્ક્રિપ્ટીંગ", - "description": "PurrfectSnap ને વિસ્તારવા માટે કસ્ટમ સ્ક્રિપ્ટો ચલાવો", - "properties": { - "developer_mode": { - "name": "વિકાસકર્તા મોડ", - "description": "Snapchat ના UI પર ડિબગ માહિતી બતાવે છે" - }, - "module_folder": { - "name": "મોડ્યુલ ફોલ્ડર", - "description": "જ્યાં સ્ક્રિપ્ટો સ્થિત છે તે ફોલ્ડર" - }, - "auto_reload": { - "name": "ઓટો રીલોડ", - "description": "જ્યારે તેઓ બદલાય ત્યારે સ્ક્રિપ્ટોને આપમેળે રીલોડ કરે છે" - }, - "integrated_ui": { - "name": "સંકલિત UI", - "description": "સ્ક્રિપ્ટોને Snapchat માં કસ્ટમ UI ઘટકો ઉમેરવાની મંજૂરી આપે છે" - }, - "disable_log_anonymization": { - "name": "લોગ અનામીકરણ અક્ષમ કરો", - "description": "લોગના અનામીકરણને અક્ષમ કરે છે" - }, - "disable_optimization": { - "name": "ઓપ્ટિમાઇઝેશન અક્ષમ કરો", - "description": "સ્ક્રિપ્ટોના ઓપ્ટિમાઇઝેશનને અક્ષમ કરે છે. આ પ્રદર્શન સમસ્યાઓનું કારણ બની શકે છે." - } - } - }, - "friend_tracker": { - "name": "મિત્ર ટ્રેકર", - "description": "Snapchat પર મિત્રની પ્રવૃત્તિ રેકોર્ડ કરે છે", - "properties": { - "record_messaging_events": { - "name": "મેસેજિંગ ઘટનાઓ રેકોર્ડ કરો", - "description": "સ્નેપ ખોલવા, સંદેશ વાંચવા જેવી મેસેજિંગ ઘટનાઓ રેકોર્ડ કરે છે." - }, - "allow_running_in_background": { - "name": "પૃષ્ઠભૂમિમાં ચાલવાની મંજૂરી આપો", - "description": "ટ્રેકરને પૃષ્ઠભૂમિમાં ચાલવાની મંજૂરી આપે છે. નોંધ: આ તમારી બેટરીને નોંધપાત્ર રીતે ડ્રેઇન કરશે" - }, - "auto_purge": { - "name": "ઓટો પર્જ", - "description": "નિર્દિષ્ટ સમય કરતાં જૂની કેશ્ડ ઘટનાઓને આપમેળે કાઢી નાખે છે" - } - } - } - }, - "options": { - "app_appearance": { - "always_light": "હંમેશા પ્રકાશ", - "always_dark": "હંમેશા અંધારું" - }, - "friend_feed_menu_buttons": { - "auto_download": "⬇️ ઓટો ડાઉનલોડ", - "auto_save": "💬 ઓટો સેવ સંદેશા", - "unsaveable_messages": "⬇️ અસાચવી શકાય તેવા સંદેશા", - "auto_open_snaps": "📸 ઓટો ઓપન સ્નેપ્સ", - "stealth": "👻 સ્ટીલ્થ મોડ", - "mark_snaps_as_seen": "👀 સ્નેપને જોયેલ તરીકે ચિહ્નિત કરો", - "mark_stories_as_seen_locally": "👀 વાર્તાઓને સ્થાનિક રીતે જોયેલ તરીકે ચિહ્નિત કરો", - "conversation_info": "🧑‍🤝‍🧑 વાર્તાલાપ માહિતી", - "e2e_encryption": "🔒 E2E એન્ક્રિપ્શનનો ઉપયોગ કરો" - }, - "path_format": { - "create_author_folder": "દરેક લેખક માટે ફોલ્ડર બનાવો", - "create_source_folder": "દરેક મીડિયા સ્ત્રોત પ્રકાર માટે ફોલ્ડર બનાવો", - "append_hash": "ફાઇલનામમાં એક અનન્ય હેશ ઉમેરો", - "append_source": "ફાઇલનામમાં મીડિયા સ્ત્રોત ઉમેરો", - "append_username": "ફાઇલનામમાં વપરાશકર્તાનામ ઉમેરો", - "append_date_time": "ફાઇલનામમાં તારીખ અને સમય ઉમેરો" - }, - "auto_download_sources": { - "friend_snaps": "મિત્ર સ્નેપ્સ", - "friend_stories": "મિત્ર વાર્તાઓ", - "public_stories": "જાહેર વાર્તાઓ", - "spotlight": "સ્પોટલાઇટ" - }, - "logging": { - "started": "શરૂ થયું", - "success": "સફળતા", - "progress": "પ્રગતિ", - "failure": "નિષ્ફળતા" - }, - "notifications": { - "chat_screenshot": "સ્ક્રીનશોટ", - "chat_screen_record": "સ્ક્રીન રેકોર્ડ", - "snap_replay": "સ્નેપ રિપ્લે", - "camera_roll_save": "કેમેરા રોલમાં સાચવો", - "chat": "ચેટ", - "chat_reply": "ચેટ જવાબ", - "snap": "સ્નેપ", - "typing": "ટાઇપિંગ", - "stories": "વાર્તાઓ", - "speaking": "બોલવું", - "chat_reaction": "DM પ્રતિક્રિયા", - "group_chat_reaction": "જૂથ પ્રતિક્રિયા", - "initiate_audio": "ઇનકમિંગ ઓડિયો કોલ", - "abandon_audio": "મિસ્ડ ઓડિયો કોલ", - "initiate_video": "ઇનકમિંગ વિડિઓ કોલ", - "abandon_video": "મિસ્ડ વિડિઓ કોલ", - "map_live_location": "નકશો લાઇવ સ્થાન" - }, - "gallery_media_send_override": { - "always_ask": "હંમેશા પૂછો", - "ORIGINAL": "મૂળ મીડિયા", - "NOTE": "ઓડિયો નોટ", - "SNAP": "સ્નેપ", - "SAVEABLE_SNAP": "સાચવી શકાય તેવું સ્નેપ" - }, - "strip_media_metadata": { - "hide_caption_text": "કેપ્શન ટેક્સ્ટ છુપાવો", - "hide_snap_filters": "સ્નેપ ફિલ્ટર્સ છુપાવો", - "hide_extras": "વધારાની વસ્તુઓ છુપાવો (દા.ત. ઉલ્લેખો)", - "remove_audio_note_duration": "ઓડિયો નોટ અવધિ દૂર કરો", - "remove_audio_note_transcript_capability": "ઓડિયો નોટ ટ્રાન્સક્રિપ્ટ ક્ષમતા દૂર કરો" - }, - "hide_ui_components": { - "hide_profile_call_buttons": "પ્રોફાઇલ કોલ બટનો દૂર કરો", - "hide_chat_call_buttons": "ચેટ કોલ બટનો દૂર કરો", - "hide_live_location_share_button": "લાઇવ સ્થાન શેર બટન દૂર કરો", - "hide_stickers_button": "સ્ટીકરો બટન દૂર કરો", - "hide_voice_record_button": "વોઇસ રેકોર્ડ બટન દૂર કરો", - "hide_unread_chat_hint": "ન વાંચેલ ચેટ સંકેત દૂર કરો", - "hide_post_to_story_buttons": "સ્નેપ મોકલતા પહેલા વાર્તા પર પોસ્ટ બટનો દૂર કરો", - "hide_billboard_prompt": "મિત્રો ફીડમાં બિલબોર્ડ પ્રોમ્પ્ટ દૂર કરો", - "hide_snapchat_plus_gift_reminders": "વાર્તાલાપમાં Snapchat Plus ભેટ રીમાઇન્ડર્સ દૂર કરો", - "hide_map_reactions": "નકશા પ્રતિક્રિયાઓ દૂર કરો" - }, - "hide_story_suggestions": { - "hide_suggested_friend_stories": "સૂચવેલ મિત્ર વાર્તાઓ છુપાવો", - "hide_my_stories": "મારી વાર્તાઓ છુપાવો" - }, - "home_tab": { - "map": "નકશો", - "chat": "ચેટ", - "camera": "કેમેરા", - "discover": "શોધો", - "spotlight": "સ્પોટલાઇટ" - }, - "add_friend_source_spoof": { - "added_by_username": "વપરાશકર્તાનામ દ્વારા", - "added_by_mention": "ઉલ્લેખ દ્વારા", - "added_by_group_chat": "જૂથ ચેટ દ્વારા", - "added_by_qr_code": "QR કોડ દ્વારા", - "added_by_community": "સમુદાય દ્વારા", - "added_by_quick_add": "ઝડપી ઉમેરો દ્વારા (પ્રતિબંધિત થવાનું ઉચ્ચ જોખમ)" - }, - "bypass_video_length_restriction": { - "single": "એકલ મીડિયા", - "split": "વિભાજીત મીડિયા" - }, - "old_bitmoji_selfie": { - "2d": "2D બિટમોજી", - "3d": "3D બિટમોજી" - }, - "disable_confirmation_dialogs": { - "erase_message": "સંદેશ ભૂંસી નાખો", - "remove_friend": "મિત્રને દૂર કરો", - "block_friend": "મિત્રને અવરોધિત કરો", - "ignore_friend": "મિત્રને અવગણો", - "hide_friend": "મિત્રને છુપાવો", - "hide_conversation": "વાર્તાલાપ છુપાવો", - "clear_conversation": "મિત્ર ફીડમાંથી વાર્તાલાપ સાફ કરો" - }, - "auto_reload": { - "snapchat_only": "ફક્ત Snapchat", - "all": "બધા (Snapchat + PurrfectSnap)" - }, - "edit_text_override": { - "multi_line_chat_input": "મલ્ટી લાઇન ચેટ ઇનપુટ", - "bypass_text_input_limit": "ટેક્સ્ટ ઇનપુટ મર્યાદાને બાયપાસ કરો" - }, - "auto_purge": { - "never": "ક્યારેય નહીં", - "1_hour": "1 કલાક", - "3_hours": "3 કલાક", - "6_hours": "6 કલાક", - "12_hours": "12 કલાક", - "1_day": "1 દિવસ", - "3_days": "3 દિવસ", - "1_week": "1 અઠવાડિયું", - "2_weeks": "2 અઠવાડિયા", - "1_month": "1 મહિનો", - "3_months": "3 મહિના", - "6_months": "6 મહિના" - }, - "disable_story_sections": { - "friends": "મિત્રો", - "suggested_stories": "સૂચવેલ વાર્તાઓ", - "following": "અનુસરી રહ્યા છે", - "discover": "શોધો" - }, - "disable_cameras": { - "front": "આગળનો કેમેરો", - "back": "પાછળનો કેમેરો" - }, - "disable_permission_requests": { - "notifications": "સૂચનાઓ", - "read_media_images": "મીડિયા છબીઓ વાંચો", - "read_media_video": "મીડિયા વિડિઓ વાંચો", - "camera": "કેમેરો", - "microphone": "માઇક્રોફોન", - "location": "સ્થાન", - "read_contacts": "સંપર્કો વાંચો", - "nearby_devices": "નજીકના ઉપકરણો", - "phone_calls": "ફોન કોલ્સ" - }, - "message_indicators": { - "encryption_indicator": "ફક્ત તમને મોકલવામાં આવેલા સંદેશાઓની બાજુમાં 🔒 ચિહ્ન ઉમેરે છે", - "platform_indicator": "જે પ્લેટફોર્મ પરથી મીડિયા મોકલવામાં આવ્યું હતું તેનું પ્લેટફોર્મ ચિહ્ન ઉમેરે છે (દા.ત. Android, iOS, Web)", - "location_indicator": "જ્યારે સ્થાન સક્ષમ કરીને મોકલવામાં આવે ત્યારે સ્નેપમાં 📍 ચિહ્ન ઉમેરે છે", - "ovf_editor_indicator": "જો OVF સંપાદકનો ઉપયોગ કરીને સ્નેપ મોકલવામાં આવ્યો હોય તો સૂચવે છે", - "director_mode_indicator": "જ્યારે ડિરેક્ટર મોડનો ઉપયોગ કરીને મોકલવામાં આવે ત્યારે સ્નેપમાં 🎬 ચિહ્ન ઉમેરે છે, જેનો ઉપયોગ ગેલેરી છબીઓને સ્નેપ તરીકે મોકલવા માટે થઈ શકે છે" - }, - "auto_mark_as_read": { - "conversation_read": "સંદેશ મોકલતી વખતે વાર્તાલાપને વાંચેલ તરીકે ચિહ્નિત કરો", - "snap_reply": "સ્નેપનો જવાબ આપતી વખતે તેને વાંચેલ તરીકે ચિહ્નિત કરો", - "save_snap_in_chat": "સ્ટીલ્થ મોડમાં હોય ત્યારે ચેટમાં સ્નેપ સાચવતી વખતે તેને વાંચેલ તરીકે ચિહ્નિત કરો" - }, - "friend_mutation_notifier": { - "remove_friend": "જ્યારે કોઈ તમને મિત્ર તરીકે દૂર કરે ત્યારે સૂચિત કરો", - "birthday_changes": "જ્યારે કોઈ તેમનો જન્મદિવસ બદલે ત્યારે સૂચિત કરો", - "bitmoji_selfie_changes": "જ્યારે કોઈ તેમનું બિટમોજી સેલ્ફી બદલે ત્યારે સૂચિત કરો", - "bitmoji_avatar_changes": "જ્યારે કોઈ તેમનું બિટમોજી અવતાર બદલે ત્યારે સૂચિત કરો", - "bitmoji_background_changes": "જ્યારે કોઈ તેમનું બિટમોજી પૃષ્ઠભૂમિ બદલે ત્યારે સૂચિત કરો", - "bitmoji_scene_changes": "જ્યારે કોઈ તેમની બિટમોજી દ્રશ્ય બદલે ત્યારે સૂચિત કરો" - }, - "snapchat_plus": { - "not_subscribed": "સબ્સ્ક્રાઇબ નથી", - "basic": "મૂળભૂત", - "ad_free": "જાહેરાત મુક્ત" - }, - "double_tap_chat_action": { - "like_message": "સંદેશ પસંદ કરો", - "copy_text": "ક્લિપબોર્ડ પર ટેક્સ્ટ કૉપિ કરો", - "delete_message": "સંદેશ કાઢી નાખો", - "mark_as_read": "વાંચેલ તરીકે ચિહ્નિત કરો", - "custom_emoji_reaction": "કસ્ટમ ઇમોજી પ્રતિક્રિયા" - }, - "startup_default_camera": { - "front": "આગળનો કેમેરો", - "back": "પાછળનો કેમેરો" - } - } - }, - "friend_menu_option": { - "mark_snaps_as_seen": "સ્નેપને જોયેલ તરીકે ચિહ્નિત કરો", - "mark_stories_as_seen_locally": "વાર્તાઓને સ્થાનિક રીતે જોયેલ તરીકે ચિહ્નિત કરો", - "preview": "પૂર્વાવલોકન", - "stealth_mode": "સ્ટીલ્થ મોડ", - "auto_download_blacklist": "ઓટો ડાઉનલોડ બ્લેકલિસ્ટ", - "anti_auto_save": "એન્ટી ઓટો સેવ" - }, - "content_type": { - "CHAT": "ચેટ", - "SNAP": "સ્નેપ", - "EXTERNAL_MEDIA": "બાહ્ય મીડિયા", - "NOTE": "ઓડિયો નોટ", - "STICKER": "સ્ટીકર", - "SHARE": "શેર કરો", - "STATUS": "સ્થિતિ", - "LOCATION": "સ્થાન", - "STATUS_SAVE_TO_CAMERA_ROLL": "કેમેરા રોલમાં સાચવવામાં આવ્યું", - "STATUS_CONVERSATION_CAPTURE_SCREENSHOT": "સ્ક્રીનશોટ", - "STATUS_CONVERSATION_CAPTURE_RECORD": "સ્ક્રીન રેકોર્ડ", - "STATUS_CALL_MISSED_VIDEO": "મિસ્ડ વિડિઓ કોલ", - "STATUS_CALL_MISSED_AUDIO": "મિસ્ડ ઓડિયો કોલ", - "LIVE_LOCATION_SHARE": "લાઇવ સ્થાન શેર કરો", - "CREATIVE_TOOL_ITEM": "સર્જનાત્મક સાધન આઇટમ", - "FAMILY_CENTER_INVITE": "કૌટુંબિક કેન્દ્ર આમંત્રણ", - "FAMILY_CENTER_ACCEPT": "કૌટુંબિક કેન્દ્ર સ્વીકારો", - "FAMILY_CENTER_LEAVE": "કૌટુંબિક કેન્દ્ર છોડો", - "STATUS_PLUS_GIFT": "સ્થિતિ પ્લસ ભેટ", - "TINY_SNAP": "નાનો સ્નેપ", - "STATUS_COUNTDOWN": "કાઉન્ટડાઉન", - "MAP_REACTION": "નકશા પ્રતિક્રિયા" - }, - "media_download_source": { - "none": "કોઈ નહીં", - "pending": "બાકી", - "chat_media": "ચેટ મીડિયા", - "story": "વાર્તા", - "public_story": "જાહેર વાર્તા", - "spotlight": "સ્પોટલાઇટ", - "profile_picture": "પ્રોફાઇલ ચિત્ર", - "story_logger": "વાર્તા લોગર", - "message_logger": "સંદેશ લોગર", - "merged": "ભેળવેલ", - "voice_call": "વોઇસ કોલ" - }, - "chat_action_menu": { - "preview_button": "પૂર્વાવલોકન", - "download_button": "ડાઉનલોડ કરો", - "delete_logged_message_button": "લોગ કરેલ સંદેશ કાઢી નાખો", - "show_chat_edit_history": "ચેટ સંપાદન ઇતિહાસ બતાવો", - "convert_message": "સંદેશ રૂપાંતરિત કરો" - }, - "opera_context_menu": { - "download": "મીડિયા ડાઉનલોડ કરો", - "sent_at": "{date} ના રોજ મોકલવામાં આવ્યું", - "created_at": "{date} ના રોજ બનાવવામાં આવ્યું", - "expires_at": "{date} ના રોજ સમાપ્ત થાય છે", - "media_size": "મીડિયાનું કદ: {size}", - "media_duration": "મીડિયા અવધિ: {duration} ms", - "show_debug_info": "ડિબગ માહિતી બતાવો" - }, - "modal_option": { - "profile_info": "પ્રોફાઇલ માહિતી", - "close": "બંધ કરો" - }, - "gallery_media_send_override": { - "multiple_media_toast": "તમે એક સમયે ફક્ત એક જ મીડિયા મોકલી શકો છો" - }, - "mark_as_seen": { - "no_unseen_snaps_toast": "કોઈ ન જોયેલા સ્નેપ મળ્યા નથી!", - "seen_toast": "જોયેલ તરીકે ચિહ્નિત!", - "unseen_toast": "ન જોયેલ તરીકે ચિહ્નિત!", - "already_seen_toast": "પહેલેથી જ જોયેલ તરીકે ચિહ્નિત!", - "already_unseen_toast": "પહેલેથી જ ન જોયેલ તરીકે ચિહ્નિત!" - }, - "conversation_preview": { - "streak_expiration": "{day} દિવસ {hour} કલાક {minute} મિનિટમાં સમાપ્ત થાય છે", - "total_messages": "કુલ મોકલેલા/પ્રાપ્ત સંદેશા: {count}", - "title": "પૂર્વાવલોકન", - "unknown_user": "અજ્ઞાત વપરાશકર્તા", - "no_messages": "કોઈ સંદેશા મળ્યા નથી!" - }, - "profile_info": { - "title": "પ્રોફાઇલ માહિતી", - "first_created_username": "પ્રથમ બનાવેલ વપરાશકર્તાનામ", - "mutable_username": "પરિવર્તનશીલ વપરાશકર્તાનામ", - "display_name": "પ્રદર્શન નામ", - "added_date": "ઉમેરવાની તારીખ", - "birthday": "જન્મદિવસ : {day} {month}", - "hidden_birthday": "જન્મદિવસ : છુપાયેલ", - "friendship": "મિત્રતા", - "add_source": "સ્ત્રોત ઉમેરો", - "snapchat_plus": "સ્નેપચેટ વત્તા", - "snapchat_plus_state": { - "subscribed": "સબ્સ્ક્રાઇબ કરેલ", - "not_subscribed": "સબ્સ્ક્રાઇબ નથી" - } - }, - "friendship_link_type": { - "mutual": "પારસ્પરિક", - "outgoing": "આઉટગોઇંગ", - "blocked": "અવરોધિત", - "deleted": "કાઢી નાખેલ", - "following": "અનુસરી રહ્યા છે", - "suggested": "સૂચવેલ", - "incoming": "ઇનકમિંગ", - "incoming_follower": "ઇનકમિંગ અનુયાયી" - }, - "bulk_messaging_action": { - "choose_action_title": "ક્રિયા પસંદ કરો", - "progress_status": "{total} માંથી {index} પર પ્રક્રિયા કરી રહ્યું છે", - "selection_dialog_continue_button": "ચાલુ રાખો", - "confirmation_dialog": { - "title": "શું તમે ખાતરી કરો છો?", - "message": "આ બધા પસંદ કરેલા મિત્રોને અસર કરશે. આ ક્રિયા પૂર્વવત્ કરી શકાતી નથી." - }, - "actions": { - "remove_friends": "મિત્રોને દૂર કરો", - "clear_conversations": "વાર્તાલાપ સાફ કરો" - } - }, - "chat_export": { - "exporter_dialog": { - "select_conversations_title": "વાર્તાલાપ પસંદ કરો", - "text_field_selection": "{amount} પસંદ કરેલ", - "text_field_selection_all": "બધા", - "export_file_format_title": "ફાઇલ ફોર્મેટ નિકાસ કરો", - "message_type_filter_title": "પ્રકાર દ્વારા સંદેશા ફિલ્ટર કરો", - "amount_of_messages_title": "સંદેશાઓની સંખ્યા (બધા માટે ખાલી છોડી દો)", - "download_medias_title": "મીડિયા ડાઉનલોડ કરો" - }, - "dialog_negative_button": "રદ કરો", - "dialog_positive_button": "નિકાસ કરો", - "exported_to": "{path} પર નિકાસ કરવામાં આવ્યું", - "exporting_chats": "ચેટ્સ નિકાસ કરી રહ્યું છે...", - "processing_chats": "{amount} વાર્તાલાપ પર પ્રક્રિયા કરી રહ્યું છે...", - "export_fail": "વાર્તાલાપ {conversation} નિકાસ કરવામાં નિષ્ફળ", - "writing_output": "આઉટપુટ લખી રહ્યું છે...", - "finished": "થઈ ગયું! તમે હવે આ સંવાદ બંધ કરી શકો છો.", - "no_messages_found": "કોઈ સંદેશા મળ્યા નથી!", - "exporting_message": "{conversation} નિકાસ કરી રહ્યું છે..." - }, - "button": { - "ok": "ઓકે", - "positive": "હા", - "negative": "ના", - "cancel": "રદ કરો", - "open": "ખોલો", - "download": "ડાઉનલોડ કરો", - "send": "મોકલો", - "restore_original": "મૂળ પુનઃસ્થાપિત કરો", - "convert_external_media": "બાહ્ય મીડિયા રૂપાંતરિત કરો", - "save": "સાચવો" - }, - "tracker_events": { - "conversation_enter": "વાર્તાલાપમાં પ્રવેશ કરો", - "conversation_exit": "વાર્તાલાપમાંથી બહાર નીકળો", - "started_typing": "ટાઇપ કરવાનું શરૂ કર્યું", - "stopped_typing": "ટાઇપ કરવાનું બંધ કર્યું", - "started_speaking": "બોલવાનું શરૂ કર્યું", - "stopped_speaking": "બોલવાનું બંધ કર્યું", - "started_peeking": "ડોકિયું કરવાનું શરૂ કર્યું", - "stopped_peeking": "ડોકિયું કરવાનું બંધ કર્યું", - "message_read": "સંદેશ વાંચ્યો", - "message_deleted": "સંદેશ કાઢી નાખ્યો", - "message_saved": "સંદેશ સાચવ્યો", - "message_unsaved": "સંદેશ અસાચવ્યો", - "message_edited": "સંદેશ સંપાદિત કર્યો", - "message_reaction_add": "સંદેશ પ્રતિક્રિયા ઉમેરો", - "message_reaction_remove": "સંદેશ પ્રતિક્રિયા દૂર કરો", - "snap_opened": "સ્નેપ ખોલ્યો", - "snap_replayed": "સ્નેપ ફરીથી ચલાવ્યો", - "snap_replayed_twice": "સ્નેપ બે વાર ફરીથી ચલાવ્યો", - "snap_screenshot": "સ્નેપ સ્ક્રીનશોટ", - "snap_screen_record": "સ્નેપ સ્ક્રીન રેકોર્ડ" - }, - "tracker_actions": { - "log": "લોગ", - "in_app_notification": "એપ્લિકેશનમાં સૂચના", - "push_notification": "પુશ સૂચના", - "custom": "કસ્ટમ" - }, - "better_notifications": { - "button": { - "reply": "જવાબ આપો", - "download": "ડાઉનલોડ કરો", - "mark_as_read": "વાંચેલ તરીકે ચિહ્નિત કરો" - } - }, - "profile_picture_downloader": { - "button": "પ્રોફાઇલ ચિત્ર ડાઉનલોડ કરો", - "title": "પ્રોફાઇલ ચિત્ર ડાઉનલોડર", - "avatar_option": "અવતાર", - "background_option": "પૃષ્ઠભૂમિ" - }, - "call_start_confirmation": { - "dialog_title": "કોલ શરૂ કરો", - "dialog_message": "શું તમે ખાતરી કરો છો કે તમે કોલ શરૂ કરવા માંગો છો?" - }, - "half_swipe_notifier": { - "notification_channel_name": "અડધો સ્વાઇપ", - "notification_content_dm": "{friend} એ હમણાં જ તમારા ચેટમાં {duration} સેકંડ માટે અડધો સ્વાઇપ કર્યો", - "notification_content_group": "{friend} એ હમણાં જ {group} માં {duration} સેકંડ માટે અડધો સ્વાઇપ કર્યો" - }, - "download_processor": { - "attachment_type": { - "snap": "સ્નેપ", - "sticker": "સ્ટીકર", - "gif": "જાદુઈ", - "external_media": "બાહ્ય મીડિયા", - "note": "નોંધ", - "original_story": "મૂળ વાર્તા" - }, - "select_attachments_title": "જોડાણો પસંદ કરો", - "download_started_toast": "ડાઉનલોડ શરૂ થયું", - "unsupported_content_type_toast": "અસમર્થિત સામગ્રી પ્રકાર!", - "failed_no_longer_available_toast": "મીડિયા હવે ઉપલબ્ધ નથી", - "no_attachments_toast": "કોઈ જોડાણો મળ્યા નથી!", - "already_queued_toast": "મીડિયા પહેલેથી જ કતારમાં છે!", - "already_downloaded_toast": "મીડિયા પહેલેથી જ ડાઉનલોડ થયેલ છે!", - "content_saved_toast": "સાચવવામાં આવ્યું!", - "download_toast": "{path} ડાઉનલોડ કરી રહ્યું છે...", - "processing_toast": "{path} પર પ્રક્રિયા કરી રહ્યું છે...", - "failed_generic_toast": "ડાઉનલોડ કરવામાં નિષ્ફળ", - "failed_to_create_preview_toast": "પૂર્વાવલોકન બનાવવામાં નિષ્ફળ", - "failed_processing_toast": "પ્રક્રિયા નિષ્ફળ {error}", - "failed_gallery_toast": "ગેલેરીમાં સાચવવામાં નિષ્ફળ {error}", - "dash_no_chapter": "કોઈ પ્રકરણ મળ્યું નથી", - "dash_dialog": { - "title": "ડેશ મીડિયા ડાઉનલોડ કરો", - "download_all": "બધા ડાઉનલોડ કરો", - "segment_text": "સેગમેન્ટ {from} - {to}" - } - }, - "streaks_reminder": { - "notification_title": "સ્ટ્રીક્સ", - "notification_text": "તમે {hoursLeft} કલાકમાં {friend} સાથે તમારી સ્ટ્રીક ગુમાવશો" - }, - "biometric_auth": { - "unlock_button": "અનલોક કરો", - "title": "Snapchat અનલોક કરો", - "subtitle": "કૃપા કરીને Snapchat અનલોક કરવા માટે પ્રમાણિત કરો" - }, - "end_to_end_encryption": { - "toolbox": { - "no_shared_key": "તમારી પાસે હજી સુધી આ મિત્ર સાથે કોઈ વહેંચાયેલ ગુપ્ત કી નથી. નવું શરૂ કરવા માટે નીચે ક્લિક કરો.", - "shared_key_fingerprint": "તમારી ફિંગરપ્રિન્ટ છે:\n\n{fingerprint}\n\nખાતરી કરો કે તે તમારા મિત્રની ફિંગરપ્રિન્ટ સાથે મેળ ખાય છે!", - "initiate_exchange_button": "કી વિનિમય શરૂ કરો" - }, - "confirmation_dialogs": { - "title": "એન્ડ-ટુ-એન્ડ એન્ક્રિપ્શન", - "confirmation_1": "ચેતવણી: આ તમારી હાલની કીને ઓવરરાઇટ કરશે. તમે આ મિત્ર પાસેથી બધા એન્ક્રિપ્ટેડ સંદેશાઓની ઍક્સેસ ગુમાવશો. શું તમે ખાતરી કરો છો કે તમે ચાલુ રાખવા માંગો છો?", - "confirmation_2": "શું તમે ખરેખર ખાતરી કરો છો કે તમે ચાલુ રાખવા માંગો છો? આ પાછા હટવાની તમારી છેલ્લી તક છે." - }, - "unencrypted_conversation_send_failure_toast": "તમે એન્ક્રિપ્ટેડ અને અનએન્ક્રિપ્ટેડ બંને વાર્તાલાપમાં એન્ક્રિપ્ટેડ સામગ્રી મોકલી શકતા નથી!", - "native_hooks_send_failure_toast": "મોકલવામાં નિષ્ફળ! કૃપા કરીને સેટિંગ્સમાં મૂળ હુક્સ સક્ષમ કરો.", - "no_participants_to_encrypt_toast": "આ વાર્તાલાપમાં તમારી પાસે સંદેશા એન્ક્રિપ્ટ કરવા માટે કોઈ મિત્રો નથી!", - "encryption_failed_toast": "સંદેશ એન્ક્રિપ્ટ કરવામાં નિષ્ફળ! વધુ વિગતો માટે લોગકેટ તપાસો.", - "accept_public_key_success_toast": "જાહેર કી સફળતાપૂર્વક સ્વીકારવામાં આવી!", - "accept_secret_key_success_toast": "થઈ ગયું! તમે હવે આ મિત્ર સાથે એન્ક્રિપ્ટેડ સંદેશા મોકલી અને પ્રાપ્ત કરી શકો છો.", - "accept_public_key_failure_toast": "જાહેર કી સ્વીકારવામાં નિષ્ફળ", - "accept_secret_key_failure_toast": "ગુપ્ત કી સ્વીકારવામાં નિષ્ફળ", - "accept_secret_button": "ગુપ્ત સ્વીકારો", - "accept_public_key_button": "જાહેર કી સ્વીકારો", - "outgoing_pk_message": "કી વિનિમય વિનંતી", - "outgoing_secret_message": "કી વિનિમય પ્રતિસાદ", - "incoming_pk_message": "તમને હમણાં જ એક જાહેર કી વિનંતી મળી છે. તેને સ્વીકારવા માટે નીચે ક્લિક કરો.", - "incoming_secret_message": "તમારા મિત્રએ હમણાં જ તમારી જાહેર કી સ્વીકારી છે. ગુપ્ત સ્વીકારવા માટે નીચે ક્લિક કરો." - }, - "auto_open_snaps": { - "title": "ઓટો ઓપન સ્નેપ્સ", - "notification_content": "{count} સ્નેપ ખોલ્યા" - }, - "friend_mutation_observer": { - "notification_channel_name": "મિત્ર મ્યુટેશન ઓબ્ઝર્વર", - "friend_removed": "{username} એ તમને મિત્ર તરીકે દૂર કર્યા છે", - "birthday_removed": "{username} એ તેમનો જન્મદિવસ દૂર કર્યો છે ({birthday})", - "birthday_added": "{username} એ તેમનો જન્મદિવસ ઉમેર્યો છે ({birthday})", - "birthday_changed": "{username} એ તેમનો જન્મદિવસ {oldBirthday} થી {newBirthday} માં બદલ્યો છે", - "bitmoji_selfie_changed": "{username} એ તેમનું બિટમોજી સેલ્ફી બદલ્યું છે", - "bitmoji_avatar_changed": "{username} એ તેમનું બિટમોજી અવતાર બદલ્યું છે", - "bitmoji_background_changed": "{username} એ તેમની બિટમોજી પૃષ્ઠભૂમિ બદલી છે", - "bitmoji_scene_changed": "{username} એ તેમની બિટમોજી દ્રશ્ય બદલ્યું છે" - }, - "material3_strings": { - "date_range_picker_start_headline": "થી", - "date_range_picker_end_headline": "સુધી", - "date_range_picker_title": "તારીખ શ્રેણી પસંદ કરો", - "date_picker_switch_to_calendar_mode": "કેલેન્ડર", - "date_picker_switch_to_input_mode": "ઇનપુટ", - "date_range_picker_scroll_to_previous_month": "પહેલાનો મહિનો", - "date_range_picker_scroll_to_next_month": "આવતો મહિનો", - "date_picker_today_description": "આજે", - "date_range_picker_day_in_range": "પસંદ કરેલ", - "date_input_invalid_for_pattern": "અમાન્ય તારીખ", - "date_input_invalid_year_range": "અમાન્ય વર્ષ", - "date_input_invalid_not_allowed": "અમાન્ય તારીખ", - "date_range_input_invalid_range_input": "અમાન્ય તારીખ શ્રેણી" - }, - "send_override_dialog": { - "title": "{type} તરીકે મીડિયા મોકલો", - "duration": "અવધિ: {duration}", - "saveable_snap_hint": "ચેટમાં સ્નેપને સાચવી શકાય તેવું બનાવો", - "unlimited_duration": "અમર્યાદિત" - }, - "invalid_input_toast": "અમાન્ય ઇનપુટ! ખાતરી કરો કે તમે માન્ય મૂલ્ય દાખલ કર્યું છે." -} \ No newline at end of file + } +} diff --git a/common/src/main/assets/lang/gwi.json b/common/src/main/assets/lang/gwi.json new file mode 100644 index 00000000..9af7d9b8 --- /dev/null +++ b/common/src/main/assets/lang/gwi.json @@ -0,0 +1,1389 @@ +{ + "media_download_source": { + "none": "Keine", + "pending": "Ausstehend", + "chat_media": "Chat-Medium", + "story": "Story", + "public_story": "Öffentliche Story", + "spotlight": "Spotlight", + "profile_picture": "Profilbild", + "story_logger": "Story Logger", + "message_logger": "Nachrichtenprotokollierung", + "merged": "Zusammengeführt", + "voice_call": "Sprachanruf" + }, + "mark_as_seen": { + "already_unseen_toast": "Schon als ungelesen markiert!", + "no_unseen_snaps_toast": "Es wurden keine ungesehenen Snaps gefunden!", + "seen_toast": "Markiert als gesehen!", + "unseen_toast": "Markiert als ungesehen!", + "already_seen_toast": "Bereits markiert als gesehen!" + }, + "conversation_preview": { + "streak_expiration": "läuft in {day} Tagen, {hour} Stunden, {minute} Minuten ab", + "total_messages": "Insgesamt gesendete/empfangene Nachrichten: {count}", + "title": "Vorschau", + "unknown_user": "Unbekannter Benutzer" + }, + "chat_export": { + "processing_chats": "{amount} Konversationen werden verarbeitet...", + "exporter_dialog": { + "select_conversations_title": "Konversationen auswählen", + "text_field_selection": "{amount} ausgewählt", + "text_field_selection_all": "Alle", + "export_file_format_title": "Dateiformat für den Export", + "message_type_filter_title": "Nachrichten nach Typ filtern", + "amount_of_messages_title": "Anzahl der Nachrichten (für alle leer lassen)", + "download_medias_title": "Medien herunterladen" + }, + "dialog_negative_button": "Abbrechen", + "dialog_positive_button": "Exportieren", + "exported_to": "Exportiert zu {path}", + "exporting_chats": "Chats exportieren...", + "export_fail": "Konversation {conversation} konnte nicht exportiert werden", + "writing_output": "Ausgabe schreiben...", + "finished": "Fertig! Du kannst diesen Dialog jetzt schließen.", + "no_messages_found": "Keine Nachrichten gefunden!", + "exporting_message": "{conversation} wird exportiert..." + }, + "button": { + "ok": "OK", + "open": "Öffnen", + "download": "Download", + "positive": "Ja", + "negative": "Nein", + "cancel": "Abbrechen" + }, + "download_processor": { + "dash_dialog": { + "segment_text": "Segment {from} - {to}", + "title": "Dash-Medium herunterladen", + "download_all": "Alle herunterladen" + }, + "attachment_type": { + "snap": "Snap", + "sticker": "Sticker", + "gif": "GIF", + "external_media": "Externe Medien", + "note": "Notiz", + "original_story": "Originale Story" + }, + "select_attachments_title": "Anhänge auswählen", + "download_started_toast": "Download gestartet", + "unsupported_content_type_toast": "Nicht unterstützter Content-Typ!", + "failed_no_longer_available_toast": "Datei ist nicht mehr verfügbar", + "no_attachments_toast": "Keine Anhänge gefunden!", + "already_queued_toast": "Datei wird bereits bearbeitet!", + "already_downloaded_toast": "Datei wurde bereits heruntergeladen!", + "download_toast": "{path} wird heruntergeladen...", + "processing_toast": "Verarbeite {path}...", + "failed_generic_toast": "Download fehlgeschlagen", + "failed_to_create_preview_toast": "Fehler beim Erstellen der Vorschau", + "failed_processing_toast": "Fehler beim Verarbeiten {error}", + "failed_gallery_toast": "Speichern in der Galerie fehlgeschlagen {error}", + "dash_no_chapter": "Kein Abschnitt gefunden" + }, + "auto_open_snaps": { + "title": "Auto-Öffnen von Snaps", + "notification_content": "{count} Snaps geöffnet" + }, + "friend_mutation_observer": { + "birthday_changed": "{username} hat sein/ ihr Geburtsdatum von {oldBirthday} auf {newBirthday} geändert", + "notification_channel_name": "Freund-Mutationsbeobachter", + "friend_removed": "{username} hat dich als Freund:in entfernt", + "birthday_removed": "{username} hat sein/ ihr Geburtsdatum ({birthday}) entfernt", + "birthday_added": "{username} hat sein/ ihr Geburtsdatum ({birthday}) hinzugefügt", + "bitmoji_selfie_changed": "{username} hat sein/ ihr Bitmoji-Selfie geändert", + "bitmoji_avatar_changed": "{username} hat sein/ ihr Bitmoji-Avatar geändert", + "bitmoji_background_changed": "{username} hat den Hintergrund seines/ ihres Bitmojis geändert", + "bitmoji_scene_changed": "{username} hat seine/ ihre Bitmoji-Szene geändert" + }, + "material3_strings": { + "date_input_invalid_year_range": "Invalides Jahr", + "date_input_invalid_not_allowed": "Invalides Datum", + "date_range_input_invalid_range_input": "Ungültiger Zeitraum", + "date_picker_switch_to_calendar_mode": "Kalender", + "date_picker_switch_to_input_mode": "Eingabe", + "date_range_picker_start_headline": "Von", + "date_range_picker_end_headline": "Bis", + "date_range_picker_title": "Wähle einen Zeitraum", + "date_range_picker_scroll_to_previous_month": "Vorheriger Monat", + "date_range_picker_scroll_to_next_month": "Nächster Monat", + "date_picker_today_description": "Heute", + "date_range_picker_day_in_range": "Gewählt", + "date_input_invalid_for_pattern": "Invalides Datum" + }, + "setup": { + "dialogs": { + "select_language": "Sprache auswählen", + "save_folder": "SnapEnhance benötigt Zugriff auf den Gerätespeicher, um Medien von Snapchat herunterzuladen und zu sichern.\nBitte wähle einen Ziel-Ordner für die Downloads aus.", + "select_save_folder_button": "Ordner wählen" + }, + "mappings": { + "dialog": "Mappings werden generiert, dies könnte ein bisschen dauern ...", + "generate_failure_no_snapchat": "SnapEnhance konnte Snapchat nicht finden, bitte versuchen Sie Snapchat neu zu installieren.", + "generate_failure": "Beim Generieren der Zuordnungen ist ein Fehler aufgetreten. Bitte versuchen Sie es erneut." + }, + "permissions": { + "dialog": "Um fortfahren zu können, müssen Sie diese Anforderungen erfüllen:", + "notification_access": "Zugriff auf Benachrichtigungen", + "battery_optimization": "Batterieoptimierung", + "display_over_other_apps": "Über anderen Apps einblenden", + "request_button": "Anfordern" + } + }, + "scopes": { + "group": "Gruppe", + "friend": "Freund:in" + }, + "manager": { + "routes": { + "tasks": "Aufgaben", + "home_settings": "Einstellungen", + "messaging_preview": "Vorschau", + "scripts": "Skripte", + "features": "Funktionen", + "home": "Startseite", + "home_logs": "Logs", + "logger_history": "Logs Verlauf", + "logged_stories": "Geloggte Storys", + "friend_tracker": "Freundtracker:in", + "edit_rule": "Regel bearbeiten", + "social": "Sozial", + "manage_scope": "Verwalte Scope" + }, + "sections": { + "home": { + "update_title": "SnapEnhance Update", + "update_button": "Herunterladen", + "update_content": "Version {version} ist verfügbar!" + }, + "social": { + "empty_hint": "(leer)", + "friends_tab": "Freunde", + "groups_tab": "Gruppen", + "streaks_expiration_short": "{hours}h" + }, + "home_settings": { + "success_toast": "Erledigt!", + "actions_title": "Aktionen", + "message_logger_title": "Nachrichtenaufzeichner", + "debug_title": "Debuggen", + "message_logger_summary": "{messageCount} Nachrichten\n{storyCount} Stories", + "export_button": "Exportieren", + "clear_button": "Löschen", + "view_logger_history_button": "Historie des Nachrichtenaufzeichners ansehen" + }, + "home_logs": { + "no_logs_hint": "Keine Protokolle verfügbar", + "clear_logs_button": "Protokolle löschen", + "export_logs_button": "Protokolle exportieren", + "saving_logs_toast": "Speichern von Protokollen, das kann eine Weile dauern ...", + "saved_logs_success_toast": "Protokolle erfolgreich gespeichert", + "saved_logs_failure_toast": "Speichern von Protokollen fehlgeschlagen" + }, + "tasks": { + "no_tasks": "Keine Aufgaben", + "merge_files_toast": "Zusammenführen von {count} Dateien", + "remove_selected_tasks_title": "Sind Sie sicher, dass Sie die ausgewählten Aufgaben entfernen möchten?", + "remove_all_tasks_title": "Sind Sie sicher, dass Sie alle Aufgaben entfernen möchten?", + "delete_files_option": "Auch Dateien löschen", + "remove_selected_tasks_confirm": "{count} Aufgaben entfernen?", + "remove_all_tasks_confirm": "Alle Aufgaben entfernen?" + }, + "features": { + "disabled": "Deaktiviert", + "export_option": "Exportieren", + "import_option": "Importieren", + "reset_option": "Zurücksetzen", + "config_export_success_toast": "Einstellungen erfolgreich exportiert", + "config_import_success_toast": "Einstellungen erfolgreich importiert", + "config_import_failure_toast": "Einstellungen konnten nicht importiert werden. {error}", + "saved_config_snackbar": "Einstellungen gespeichert" + }, + "manage_scope": { + "logged_stories_button": "Aufgezeichnete Stories anschauen", + "e2ee_title": "Ende-zu-Ende Verschlüsselung", + "rules_title": "Regeln", + "participants_text": "{count} Teilnehmer", + "not_found": "Nicht gefunden", + "streaks_title": "Streaks", + "streaks_length_text": "Länge: {length}", + "streaks_expiration_text": "Läuft ab in {eta}", + "streaks_expiration_text_expired": "Abgelaufen", + "reminder_button": "Erinnerung erstellen", + "delete_scope_confirm_dialog_title": "Sind Sie sicher, dass Sie ein {scope} löschen wollen?" + }, + "logged_stories": { + "story_failed_to_load": "Laden fehlgeschlagen", + "no_stories": "Keine Stories gefunden", + "save_from_cache_button": "Aus Zwischenspeicher speichern" + }, + "messaging_preview": { + "bridge_connection_failed": "Verbindung zu Snapchat über den Brückendienst fehlgeschlagen", + "bridge_init_failed": "Initialisierung der Nachrichtenbrücke fehlgeschlagen", + "message_fetch_failed": "Fehler beim Abrufen der Nachrichten", + "no_message_hint": "Keine Nachricht", + "save_selection_option": "Auswahl speichern", + "save_all_option": "Alles speichern", + "unsave_selection_option": "Auswahl nicht mehr speichern", + "unsave_all_option": "Alles nicht mehr speichern", + "mark_selection_as_seen_option": "Ausgewählten Snap als gesehen markieren", + "mark_all_as_seen_option": "Alle Snaps als gesehen markieren", + "delete_selection_option": "Auswahl löschen", + "delete_all_option": "Alles löschen" + }, + "logger_history": { + "list_friend_format": "Freund {name}", + "list_group_format": "Gruppe {name}", + "no_more_messages": "Keine weiteren Nachrichten", + "reverse_order_checkbox": "Umgekehrte Reihenfolge", + "chat_attachment": "Anhang {index}", + "empty_message": "Leere Chatnachricht", + "message_parse_failed": "Nachricht konnte nicht verarbeitet werden", + "unknown_sender": "Unbekannter Absender", + "download_attachment_failed_toast": "Fehler beim Herunterladen des Anhangs" + } + }, + "dialogs": { + "scripting_warning": { + "title": "Warnung", + "content": "SnapEnhance enthält ein Skripting-Tool, das die Ausführung von benutzerdefinierten Code auf Ihrem Gerät ermöglicht. Seien Sie äußerst vorsichtig und installieren Sie nur Module aus bekannten, zuverlässigen Quellen. Unautorisierte oder ungeprüfte Module können Sicherheitsrisiken für Ihr System darstellen." + }, + "add_friend": { + "category_groups": "Gruppen", + "title": "Freund oder Gruppe hinzufügen", + "search_hint": "Suchen", + "fetch_error": "Fehler beim Abrufen der Daten", + "category_friends": "Freunde" + }, + "reset_config": { + "title": "Einstellungen zurücksetzen", + "content": "Bist Du sicher, dass Du die Einstellungen zurücksetzen möchtest?", + "success_toast": "Einstellungen erfolgreich zurückgesetzt" + }, + "messaging_action": { + "title": "Wählen Sie die zu verarbeitenden Inhaltstypen um fortzufahren", + "select_all_button": "Alle auswählen" + } + } + }, + "rules": { + "modes": { + "blacklist": "Blacklist Modus", + "whitelist": "Whitlist Modus" + }, + "properties": { + "stealth": { + "options": { + "blacklist": "Vom Heimlichen Modus ausschließen", + "whitelist": "Heimlicher Modus" + }, + "name": "Heimlicher Modus", + "description": "Verhindert, dass jemand weiß, dass du seine Snaps/Chats oder Konversationen geöffnet hast" + }, + "auto_save": { + "name": "Automatisches speichern", + "description": "Speichert Chat-Nachrichten beim Ansehen", + "options": { + "blacklist": "Vom automatischen Speichern ausschließen", + "whitelist": "Automatisch speichern" + } + }, + "auto_download": { + "name": "Auto-Download", + "description": "Snaps beim Ansehen automatisch herunterladen", + "options": { + "blacklist": "Vom Auto-Download ausschließen", + "whitelist": "Auto-Download" + } + }, + "unsaveable_messages": { + "name": "Nicht speicherbare Nachrichten", + "description": "Verhindert, dass Nachrichten im Chat von anderen Personen gespeichert werden können", + "options": { + "blacklist": "Von nicht speicherbaren Nachrichten ausschließen", + "whitelist": "Nicht speicherbare Nachrichten" + } + }, + "auto_open_snaps": { + "name": "Automatisches Öffnen von Snaps", + "description": "Öffnet Snaps automatisch beim Empfang", + "options": { + "blacklist": "Von der automatischen Snap-Öffnung ausschließen", + "whitelist": "Auto-Öffnen von Snaps" + } + }, + "hide_friend_feed": { + "name": "Vom Freundes-Feed ausblenden" + }, + "e2e_encryption": { + "name": "E2E-Verschlüsselung verwenden" + }, + "pin_conversation": { + "name": "Unterhaltung anheften" + } + }, + "toasts": { + "enabled": "{ruleName} aktiviert", + "disabled": "{ruleName} deaktiviert" + } + }, + "actions": { + "bulk_messaging_action": { + "name": "Massen Nachrichten Aktion", + "description": "Führt Operationen wie das Löschen von Freunden oder amassenlöschung von Konversationen durch" + }, + "clean_snapchat_cache": { + "name": "Leere den Snapchat Cache", + "description": "Leert den Snapchat Cache" + }, + "manage_friend_list": { + "name": "Freundesliste verwalten", + "description": "Im-/ex- portiere deine Freundesliste beim Backup" + }, + "export_chat_messages": { + "name": "Exportiere die Chatnachrichten", + "description": "Exportiert Chat-Nachrichten in eine JSON/HTML/TXT Datei" + }, + "export_memories": { + "name": "Exportiere die Memories", + "description": "Exportiere die Memories in eine ZIP-Datei" + }, + "regen_mappings": { + "name": "Erneuere die Mappings", + "description": "Erneuere die Mappings manuell" + }, + "change_language": { + "name": "Sprache ändern", + "description": "Ändere die Sprache von SnapEnhance" + } + }, + "features": { + "properties": { + "downloader": { + "properties": { + "auto_download_sources": { + "name": "Quellen automatisch herunterladen", + "description": "Wähle die Quellen, von denen automatisch herunterzuladen ist" + }, + "force_voice_note_format": { + "name": "Sprachnotiz Format erzwingen", + "description": "Erzwingt das Speichern von Sprachnotizen in einem bestimmten Format" + }, + "logging": { + "description": "Zeigt Toasts, wenn Medien heruntergeladen werden", + "name": "Logging" + }, + "save_folder": { + "name": "Speicherverzeichnis", + "description": "Wähle das Verzeichnis, in das alle Medien heruntergeladen werden sollen" + }, + "prevent_self_auto_download": { + "name": "Selbst-Auto-Download verhindern", + "description": "Verhindert, dass eigene Snaps automatisch heruntergeladen werden" + }, + "path_format": { + "name": "Pfadformat", + "description": "Gib das Dateiformat an" + }, + "allow_duplicate": { + "name": "Duplikate erlauben", + "description": "Ermöglicht es, dass dieselben Medien mehrmals heruntergeladen werden" + }, + "merge_overlays": { + "name": "Overlays zusammenführen", + "description": "Kombiniert den Text und die Medien eines Snaps in eine Datei" + }, + "force_image_format": { + "name": "Bildformat erzwingen", + "description": "Erzwingt das Speichern von Bildern in einem bestimmten Format" + }, + "download_profile_pictures": { + "name": "Profilbilder herunterladen", + "description": "Ermöglicht das Herunterladen von Profilbildern von einer Profilseite" + }, + "opera_download_button": { + "name": "Schwebender Download Button", + "description": "Fügt einen Download-Button in der oberen rechten Ecke hinzu, wenn ein Snap angezeigt wird.\nGedrückt halten um einen Download zu starten" + }, + "download_context_menu": { + "name": "Download Kontext Menü", + "description": "Ermöglicht es, Nachrichten oder eine Story herunterzuladen/vorher anzuschauen mithilfe des Kontext Menüs.\nLanges Drücken des Knopfes erzwingt den Download" + }, + "ffmpeg_options": { + "name": "FFmpeg-Optionen", + "description": "Zusätzliche FFmpeg-Optionen angeben", + "properties": { + "threads": { + "name": "Threads", + "description": "Die Anzahl Threads, welche zu gebrauchen ist" + }, + "preset": { + "name": "Voreinstellungen", + "description": "Geschwindigkeit der Konvertierung festlegen" + }, + "constant_rate_factor": { + "name": "Konstanter Rate-Faktor", + "description": "Setze den Constant Rate Factor für den Video-Encoder\nvon 0 bis 51 für libx264" + }, + "video_bitrate": { + "name": "Videobitrate", + "description": "Video-Bitrate (kbps) festlegen" + }, + "audio_bitrate": { + "name": "Audiobitrate", + "description": "Audio-Bitrate (kbps) festlegen" + }, + "custom_video_codec": { + "name": "Benutzerdefinierter Video-Codec", + "description": "Wähle einen benutzerdefinierten Video-Codec (z.B. libx264)" + }, + "custom_audio_codec": { + "name": "Benutzerdefinierter Audio-Codec", + "description": "Wähle einen benutzerdefinierten Audio-Codec (z.B. AAC)" + } + } + }, + "custom_path_format": { + "name": "Benutzerdefiniertes Pfadformat", + "description": "Legen Sie ein benutzerdefiniertes Pfadformat für heruntergeladene Medien fest\n\nVerfügbare Variablen:\n - %username%\n - %source%\n - %hash%\n - %date_time%" + } + }, + "name": "Downloader", + "description": "Snapchat Medien herunterladen" + }, + "user_interface": { + "name": "Benutzeroberfläche", + "properties": { + "friend_feed_message_preview": { + "name": "Freund Feed Nachrichten Vorschau", + "description": "Zeigt eine Vorschau der letzten Nachrichten im Freundes-Feed", + "properties": { + "amount": { + "name": "Anzahl", + "description": "Die Anzahl der Nachrichten, die in der Vorschau angezeigt werden" + } + } + }, + "enable_app_appearance": { + "name": "Aktiviert die App Darstellungseinstellungen", + "description": "Aktiviert die versteckte App-Erscheinungsbild Einstellung,\nbei neueren Snapchat-Versionen möglicherweise nicht erforderlich" + }, + "snap_preview": { + "name": "Snap-Vorschau", + "description": "Zeigt eine kleine Vorschau neben ungesehenen Snaps im Chat an" + }, + "bootstrap_override": { + "name": "Bootstrap Überschreibung", + "description": "Bootstrap-Einstellungen der Benutzeroberfläche überschreiben", + "properties": { + "app_appearance": { + "name": "App-Erscheinungsbild", + "description": "Legt eine dauerhafte App-Darstellung fest" + }, + "home_tab": { + "name": "Home Registerkarte", + "description": "Überschreibt den Start-Tab beim Öffnen von Snapchat" + } + } + }, + "map_friend_nametags": { + "name": "Verbesserte Karten-Namensschilder von Freunden", + "description": "Verbessert die Namensschilder von Freunden auf der Snapmap" + }, + "prevent_message_list_auto_scroll": { + "name": "Automatisches Scrollen der Nachrichtenliste verhindern", + "description": "Verhindert, dass die Nachrichtenliste beim Senden/Empfangen einer Nachricht nach unten scrollt" + }, + "streak_expiration_info": { + "name": "Informationen zum Flammen-Ablauf anzeigen", + "description": "Zeigt einen Flammen-Ablauf-Timer neben dem Flammen-Zähler" + }, + "hide_friend_feed_entry": { + "name": "Freund Feed Eintrag ausblenden", + "description": "Versteckt einen bestimmten Freund aus dem Freundes-Feed,\nBenutze den sozialen Tab um diese Funktion zu verwalten" + }, + "hide_streak_restore": { + "name": "Flammen-Wiederherstellung verstecken", + "description": "Versteckt den Wiederherstellen-Button im Freundesfeed" + }, + "hide_story_suggestions": { + "name": "Story Vorschläge ausblenden", + "description": "Entfernt Empfehlungen von der Story‐Seite" + }, + "hide_ui_components": { + "name": "UI-Komponenten ausblenden", + "description": "Wähle aus welche UI-Elemente ausgeblendet werden sollen" + }, + "opera_media_quick_info": { + "name": "Medien Schnellinfo", + "description": "Zeigt nützliche Informationen zu Medien wie das Erstellungsdatum im Kontextmenü der Snap-Ansicht an" + }, + "old_bitmoji_selfie": { + "name": "Altes Bitmoji-Selfie", + "description": "Bringt die Bitmoji-Selfies aus früheren Snapchat-Versionen zurück" + }, + "disable_spotlight": { + "name": "Spotlight deaktivieren", + "description": "Deaktiviert die Spotlight Seite" + }, + "friend_feed_menu_buttons": { + "name": "Schaltflächen für das Freunde-Feed Menü", + "description": "Wähle aus welche Schaltflächen in der Freunde Feed Menüleiste angezeigt werden sollen" + }, + "vertical_story_viewer": { + "name": "Vertikale Story Ansicht", + "description": "Aktiviert die vertikale Story Ansicht für alle Storys" + }, + "enable_friend_feed_menu_bar": { + "name": "Freunde Feed Menüleiste", + "description": "Aktiviert die neue Freunde Feed Menüleiste" + }, + "message_indicators": { + "name": "Nachrichtenindikatoren", + "description": "Fügt Nachrichten spezifische Anzeigesymbole hinzu\nHinweis: Die Symbole sind möglicherweise nicht 100 % genau" + }, + "stealth_mode_indicator": { + "name": "Diebstahl Modus Indikator", + "description": "Fügt den Konversationen im Stealth-Modus ein 👻-Emoji hinzu" + }, + "edit_text_override": { + "name": "Textfeld-Verhalten überschreiben", + "description": "Überschreibt das Verhalten von Textfeldern" + } + }, + "description": "Ändere das Aussehen von Snapchat" + }, + "messaging": { + "properties": { + "auto_mark_as_read": { + "name": "Automatisch als gelesen markieren", + "description": "Markiert Nachrichten bzw. Snaps automatisch als gelesen wenn der Stealth Mode aktiviert ist" + }, + "message_logger": { + "name": "Nachrichten Logger", + "description": "Verhindert, dass Nachrichten gelöscht werden", + "properties": { + "keep_my_own_messages": { + "name": "Eigene Nachrichten behalten", + "description": "Verhindert, dass Ihre eigenen Nachrichten gelöscht werden" + }, + "auto_purge": { + "name": "Automatische Bereinigung", + "description": "Löscht automatisch zwischengespeicherte Nachrichten, die älter als die angegebene Zeit sind" + }, + "message_filter": { + "name": "Nachrichtenfilter", + "description": "Wählen Sie aus, welche Nachrichten behalten werden sollen (leer für alle Nachrichten)" + } + } + }, + "bypass_screenshot_detection": { + "name": "Umgehen der Screenshot-Erkennung", + "description": "Verhindert, dass Snapchat erkennt, wenn du einen Screenshot machst" + }, + "anonymous_story_viewing": { + "name": "Anonyme Story Ansicht", + "description": "Verhindert, dass jemand erfährt, dass du seine Story gesehen hast" + }, + "prevent_story_rewatch_indicator": { + "name": "Wiederholungs-Indikator bei Stories verhindern", + "description": "Verhindert, dass andere wissen, dass Sie ihre Story noch einmal angeschaut haben" + }, + "hide_peek_a_peek": { + "name": "Vorschau Benachrichtigung verhindern", + "description": "Verhindert, dass eine Benachrichtigung gesendet wird, wenn Sie halb in einen Chat swipen" + }, + "hide_bitmoji_presence": { + "name": "Bitmoji Präsenz verstecken", + "description": "Verhindert, dass dein Bitmoji im Chat auftaucht" + }, + "hide_typing_notifications": { + "name": "Tippen-Benachrichtigungen verbergen", + "description": "Verhindert, dass jemand erfährt, dass du eine Nachricht tippst" + }, + "unlimited_snap_view_time": { + "name": "Unbegrenzte Zeit zum Ansehen von Snaps", + "description": "Entfernt das Zeitlimit für die Anzeige von Snaps" + }, + "loop_media_playback": { + "name": "Medien Wiedergabe Wiederholen", + "description": "Wiederholt Snaps & Stories beim ansehen in einer Schleife" + }, + "disable_replay_in_ff": { + "name": "Replay in FF deaktivieren", + "description": "Deaktiviert die Möglichkeit, mit einem langen Drücken vom Freundes-Feed zu wiederholen" + }, + "half_swipe_notifier": { + "name": "Über Half-Swipes informieren", + "description": "Benachrichtigt Sie, wenn jemand halb in ihren Chat swiped", + "properties": { + "min_duration": { + "name": "Mindestdauer", + "description": "Die Mindestdauer der halben Swipes (in Sekunden)" + }, + "max_duration": { + "name": "Maximale Dauer", + "description": "Die maximale Dauer des halben Swipes (in Sekunden)" + } + } + }, + "call_start_confirmation": { + "name": "Bestätigung des Starts eines Anrufs", + "description": "Zeigt einen Bestätigungsdialog beim Starten eines Anrufs an" + }, + "unlimited_conversation_pinning": { + "name": "Unlimitiertes Anpinnen von Konversationen", + "description": "Erlaubt dir eine unlimitierte Anzahl von Konversationen lokal anzupinnen" + }, + "prevent_message_sending": { + "name": "Nachrichtenversand verhindern", + "description": "Verhindert das Versenden bestimmter Nachrichten" + }, + "friend_mutation_notifier": { + "name": "Freund-Mutationsbenachrichtigung", + "description": "Benachrichtigt Sie, wenn sich etwas im Profil eines Freundes ändert" + }, + "better_notifications": { + "name": "Bessere Benachrichtigungen", + "description": "Zeige weitere Informationen in Benachrichtigungen an" + }, + "notification_blacklist": { + "name": "Benachrichtigungs Blacklist", + "description": "Wählen Sie Benachrichtigungen aus, die blockiert werden sollen" + }, + "auto_save_messages_in_conversations": { + "name": "Automatisches Speichern von Nachrichten", + "description": "Speichert automatisch jede Nachricht in Unterhaltungen" + }, + "gallery_media_send_override": { + "name": "Galerie-Medien senden Überschreiben", + "description": "Fälscht die Medienquelle, wenn etwas von der Galerie gesendet wird" + }, + "strip_media_metadata": { + "name": "Medien-Metadaten entfernen", + "description": "Entfernt Metadaten von Medien vor dem Versand als Nachricht" + }, + "bypass_message_retention_policy": { + "name": "Umgehung der Richtlinie zur Aufbewahrung von Nachrichten", + "description": "Verhindert, dass Nachrichten nach dem Anzeigen gelöscht werden" + }, + "bypass_message_action_restrictions": { + "name": "Umgehung von Nachrichtenaktionsbeschränkungen", + "description": "Ermöglicht es Ihnen, auf einen Snap zu reagieren, ohne ihn geöffnet zu haben, oder eine nicht speicherbare Nachricht zu speichern" + }, + "remove_groups_locked_status": { + "name": "Entfernen des Gruppen-Sperrstatus", + "description": "Ermöglicht es Ihnen, nach dem Rauswurf Gruppeninformationen anzuzeigen" + } + }, + "name": "Mitteilungen", + "description": "Ändern wie mit Freunden interagiert wird" + }, + "global": { + "properties": { + "media_upload_quality": { + "properties": { + "force_video_upload_source_quality": { + "name": "Erzwingen Sie die Qualität der Video-Upload-Quelle", + "description": "Erzwing Snapchat die Quellenqualität zu nutzen, wenn Videos hochgelden werden\nBitte merkte, dass dies eventuell die Metadaten von Medien nicht entfernt" + }, + "disable_image_compression": { + "name": "Deaktiviert Bildkompression", + "description": "Deaktiviert Bildkompression, wenn Medien hochgeladen werden" + }, + "custom_image_upload_format": { + "name": "Benutzerdefiniertes Bild-Upload-Format", + "description": "Setzt ein benutzerdefiniertes Bildhochladformat\nWähle ein verlustfreies Format (wie PNG) für die beste Qualität" + } + }, + "name": "Qualität", + "description": "Überschreibt die Medienuploadqualität" + }, + "disable_snap_splitting": { + "name": "Snap-Aufteilung deaktivieren", + "description": "Verhindert, dass Snaps in mehrere Teile aufgeteilt werden\nBilder werden in Videos umgewandelt" + }, + "better_location": { + "name": "Besserer Ort", + "description": "Erweitert den Snapchat-Ort", + "properties": { + "spoof_location": { + "name": "Täusche den Ort", + "description": "Täuscht Ihren Standort auf einen bestimmten Ort vor" + }, + "coordinates": { + "name": "Koordinaten", + "description": "Wähle die Koordinaten des getäuschten Standorts" + }, + "walk_radius": { + "name": "Radius", + "description": "Laufe zufälligerweise in diesem Radium (ft) herum" + }, + "always_update_location": { + "name": "Aktualisiere den Ort immer", + "description": "Zwingt Snapchat dazu, die den Standort zu aktualisieren, auch wenn es kein GPS Signal erhält" + }, + "suspend_location_updates": { + "name": "Stoppe die Aktualisierung des Standortes", + "description": "Fügt in den Karteneinstellungen eine Schaltfläche hinzu, um Standortaktualisierungen auszusetzen" + }, + "spoof_battery_level": { + "name": "­Täusche den Akkustand vor", + "description": "Verfälscht den Akkustand Ihres Geräts auf der Karte\nDer Wert muss zwischen 0 und 100 liegen" + }, + "spoof_headphones": { + "name": "Simuliere Kopfhörer", + "description": "Verfälscht den Status des Musikhörens auf der Karte" + } + } + }, + "snapchat_plus": { + "name": "Snapchat Plus", + "description": "Aktiviert Snapchat Plus Funktionen\nEinige serverseitige Funktionen funktionieren möglicherweise nicht" + }, + "disable_confirmation_dialogs": { + "name": "Bestätigungsdialoge deaktivieren", + "description": "Bestätigt automatisch ausgewählte Aktionen" + }, + "auto_updater": { + "name": "Auto Updater", + "description": "Automatisch auf Updates prüfen" + }, + "disable_metrics": { + "name": "Metriken deaktivieren", + "description": "Verhindert das Senden von analytischen Daten an Snapchat" + }, + "disable_story_sections": { + "name": "Story Sektion deaktivieren", + "description": "Entfernt Sektionen von der Story-Seite\nErfordert möglicherweise eine Aktualisierung, um richtig zu funktionieren" + }, + "block_ads": { + "name": "Werbung blockieren", + "description": "Verhindert die Anzeige von Werbung" + }, + "disable_custom_tabs": { + "name": "Deaktivieren Sie benutzerdefinierte Registerkarten", + "description": "Öffnet Links in unterstützen Applikationen, anstatt dem Webbrowser" + }, + "disable_permission_requests": { + "name": "Berechtigungsanfragen deaktivieren", + "description": "Verhindert, dass Snapchat nach bestimmten Berechtigungen fragt" + }, + "disable_memories_snap_feed": { + "name": "Memories Snap Feed deaktivieren", + "description": "Verhindert, dass Snapchat aktuelle Erinnerungen anzeigt, wenn Sie in der Kamera nach oben wischen" + }, + "spotlight_comments_username": { + "name": "Spotlight Kommentare Benutzername", + "description": "Zeigt den Benutzernamen des Autors in Spotlight-Kommentaren an" + }, + "bypass_video_length_restriction": { + "name": "Umgeht Videolängenbeschränkungen", + "description": "Einzel: sendet ein einzelnes Video\nSplitt: Videos nach Bearbeitung aufteilen" + }, + "default_video_playback_rate": { + "name": "Standardmäßige Videowiedergaberate", + "description": "Legt die Standardgeschwindigkeit für die Wiedergabe von Videos fest\n\tDer Wert muss zwischen 0,1 und 4,0 liegen" + }, + "video_playback_rate_slider": { + "name": "Schieberegler für die Videowiedergaberate", + "description": "Fügt einen Schieberegler im Opera-Kontextmenü hinzu, um die Videowiedergabegeschwindigkeit zu ändern\nHinweis: Änderungen gelten nur für nachfolgende Videos" + }, + "disable_google_play_dialogs": { + "name": "Google Play-Service Dialog deaktivieren", + "description": "Verfügbarkeitsdialog für Google Play Services nicht anzeigen" + }, + "default_volume_controls": { + "name": "Standard Lautstärkekontrolle", + "description": "Zwinge Snapchat die Systemlautstärke zu nutzen" + }, + "hide_active_music": { + "name": "Aktive Musik ausblenden", + "description": "Verhindert, dass Snapchat erkennt, dass Sie Musik hören.\nSo können Sie mithilfe der Lautstärketasten Snaps aufnehmen, während Sie Musik hören" + } + }, + "name": "Global", + "description": "Globale Snapchat-Einstellungen anpassen" + }, + "rules": { + "name": "Regeln", + "description": "Automatische Funktionen für einzelne Personen verwalten" + }, + "camera": { + "properties": { + "immersive_camera_preview": { + "name": "Immersive Vorschau", + "description": "Verhindert das Beschneiden der Kameravorschau\nDas kann dazu führen, dass die Kamera auf einigen Geräten flickert" + }, + "front_custom_frame_rate": { + "name": "Benutzerdefinierte Frame-Rate Selfie-Kamera", + "description": "Überschreibt die Frame-Rate der Selfie-Kamera" + }, + "disable_cameras": { + "name": "Kameras deaktivieren", + "description": "Verhindert, dass Snapchat die gewählten Kameras nutzt" + }, + "black_photos": { + "name": "Schwarze Fotos", + "description": "Ersetzt die aufgenommenen Fotos durch einen schwarzen Hintergrund\nVideos sind davon nicht betroffen" + }, + "override_front_resolution": { + "name": "Überschreiben der Frontauflösung", + "description": "Überschreibt die Kameraauflösung für die Selfie-Kamera" + }, + "override_back_resolution": { + "name": "Hauptkamera Auflösung überschreiben", + "description": "Überschreibt die Kameraauflösung der Hauptkamera" + }, + "custom_resolution": { + "name": "Benutzerdefinierte Auflösung", + "description": "Legt eine benutzerdefinierte Kameraauflösung (Breite x Höhe) fest (z. B. 1920x1080).\nDie benutzerdefinierte Auflösung muss von Ihrem Gerät unterstützt werden" + }, + "back_custom_frame_rate": { + "name": "Benutzerdefinierte Frame-Rate Haupt-Kamera", + "description": "Überschreibt die Frame-Rate der Haupt-Kamera" + }, + "force_camera_source_encoding": { + "name": "Kodierung der Kameraquelle erzwingen", + "description": "Erzwingt die Kodierung der Kameraquelle" + }, + "hevc_recording": { + "name": "HEVC Aufnahme", + "description": "Verwendet HEVC (H.265) Codec für die Videoaufzeichnung" + } + }, + "name": "Kamera", + "description": "Pass die richtigen Einstellungen für den perfekten Snap an" + }, + "streaks_reminder": { + "properties": { + "group_notifications": { + "name": "Gruppierte Benachrichtigungen", + "description": "Benachrichtigungen in eine einzelne gruppieren" + }, + "interval": { + "name": "Intervall", + "description": "Das Intervall zwischen jeder Erinnerung (Stunden)" + }, + "remaining_hours": { + "name": "Verbleibende Zeit", + "description": "Die verbleibende Zeit, bevor die Benachrichtigung angezeigt wird (in Stunden)" + } + }, + "name": "Flammen-Erinnerung", + "description": "Benachrichtigt dich regelmäßig über deine Flammen" + }, + "experimental": { + "properties": { + "account_switcher": { + "description": "Ermöglicht es Ihnen, zwischen Konten zu wechseln, ohne sich auszuloggen\nHalten Sie lange auf das Suchsymbol neben Ihrem Bitmoji-Profil, um das Menü zu öffnen\nHinweis: Diese Funktion ist experimentell und wird wahrscheinlich in Zukunft geändert", + "name": "­Accountwechsler", + "properties": { + "auto_backup_current_account": { + "name": "Automatisches Backup des aktuellen Accounts", + "description": "Automatisch wird das aktuelle Konto gesichert, wenn Sie sich ausloggen oder zwischen Konten wechseln" + } + } + }, + "no_friend_score_delay": { + "name": "Keine Friend Score Verzögerung", + "description": "Entfernt die Verzögerung beim Betrachten einer Friends Score" + }, + "best_friend_pinning": { + "name": "Bester Freund Pinning", + "description": "Erlaubt einen Freund als besten Freund Nummer 1 anzupinnen. Notiz: Nur du kannst deinen gepinnten besten Freund sehen" + }, + "hidden_snapchat_plus_features": { + "description": "Aktiviert unveröffentlichte/beta Snapchat Plus Funktionen\nKönnte auf älteren Snapchat-Versionen nicht funktionieren", + "name": "Verborgene Snapchat Plus-Funktionen" + }, + "native_hooks": { + "name": "Native Hooks", + "description": "Unsichere Funktionen, welche sich in Snapchats nativen Code einhängen", + "properties": { + "composer_hooks": { + "name": "Composer Haken", + "description": "Injiziert Code in das Composer UI-Framework (nur arm64)", + "properties": { + "show_first_created_username": { + "name": "Zeige erstgewählten Benutzernamen", + "description": "Zeige den erstgewählten Benutzernamen neben dem jetzigen Benutzernamen in der Profileseite" + }, + "bypass_camera_roll_limit": { + "name": "Umgeht das Kamerarollenlimit", + "description": "Erhöht die maximale Anzahl von Medien, die Sie aus der Kamerarolle senden können" + }, + "composer_console": { + "name": "Composer-Konsole", + "description": "Ermöglicht das Ausführen von JavaScript-Code in Composer (nur arm64)" + }, + "composer_logs": { + "name": "Composer-Protokolle", + "description": "Leitet Konsolenprotokolle von Composer zu SnapEnhance um" + } + } + }, + "disable_bitmoji": { + "name": "Bitmojis deaktivieren", + "description": "Deaktiviert das Bitmoji des Freund:innenprofil" + } + } + }, + "spoof": { + "name": "Simulieren", + "description": "Verschiedene Informationen über dich vortäuschen", + "properties": { + "play_store_installer_package_name": { + "name": "Goolge Play Installationsname des Paketes", + "description": "Überschreibt den Namen des Installationspakets auf com.android.vending_machine" + }, + "remove_vpn_transport_flag": { + "name": "VPN-Transport-Flagge entfernen", + "description": "Hindert Snapchat daran, VPNs zu erkennen" + }, + "remove_mock_location_flag": { + "name": "Kennzeichnung für den gefälschten Standort entfernen", + "description": "Verhindert, dass Snapchat gefälschte Standorte erkennt" + } + } + }, + "convert_message_locally": { + "name": "Nachricht lokal umwandeln", + "description": "Konvertiert Snaps lokal in externe Chat-Medien. Dies erscheint im Kontextmenü für den Chat-Download" + }, + "media_file_picker": { + "name": "Mediendatei-Auswahl", + "description": "Ermöglicht es beliebige Video und Audio Dateien von der Gallerie auszuwählen" + }, + "story_logger": { + "name": "Geschichtenprotokollierer", + "description": "Liefert eine Historie der Stories von Freund:innen" + }, + "call_recorder": { + "name": "Anrufaufzeichner", + "description": "Zeichnet automatisch Audioanrufe auf" + }, + "edit_message": { + "name": "Nachrichten bearbeiten", + "description": "Ermöglicht es Nachrichten in Konversationen zu bearbeiten" + }, + "app_lock": { + "name": "App-Sperre", + "description": "Verhindert den Zugriff auf Snapchat ohne einen passcode", + "properties": { + "lock_on_resume": { + "name": "Sperren beim fortsetzen", + "description": "Sperrt die App wenn sie wieder geöffnet wird" + } + } + }, + "infinite_story_boost": { + "name": "Unendlicher Story Boost", + "description": "Story Boost Limit Verzögerung umgehen" + }, + "meo_passcode_bypass": { + "name": "Passwortumgehung für privaten Bereich", + "description": "Umgeht das Passwort für den privaten Bereich\nFunktioniert nur, wenn das korrekte Passwort schon einmal eingegeben wurde" + }, + "e2ee": { + "name": "Ende-zu-Ende-Verschlüsselung", + "description": "Verschlüsselt deine Nachrichten mit AES unter Verwendung eines freigegebenen geheimen Schlüssels\nAchte darauf, dass du deinen Schlüssel an einem sicheren Ort aufbewahrst!", + "properties": { + "encrypted_message_indicator": { + "name": "Anzeige für verschlüsselte Nachrichten", + "description": "Fügt einen 🔒 Emoji neben verschlüsselten Nachrichten hinzu" + }, + "force_message_encryption": { + "name": "Nachrichtenverschlüsselung erzwingen", + "description": "Verhindert das Senden von verschlüsselten Nachrichten an Personen, die keine E2E-Verschlüsselung aktiviert haben, wenn mehrere Unterhaltungen ausgewählt sind" + } + } + }, + "add_friend_source_spoof": { + "name": "Freundesquellen-Änderung hinzufügen", + "description": "Verfälscht die Quelle einer Freundschaftsanfrage" + }, + "custom_streaks_expiration_format": { + "name": "Benutzerdefiniertes Ablaufdatum für Serien", + "description": "Passt das Ablaufdatumformat für Serien an\n\nVerfügbare Variablen:\n- %c: Anzahl der Serien\n- %e: Sanduhr-Emoji\n- %d: Tage\n- %h: Stunden\n- %m: Minuten\n- %s: Sekunden\n- %w: Verbleibende Zeit" + }, + "prevent_forced_logout": { + "name": "Erzwungenen Logout verhindern", + "description": "Verhindert, dass Snapchat dich abmeldet, wenn du dich auf einem anderen Gerät anmeldest" + } + }, + "name": "Experimentell", + "description": "Experimentelle Funktionen" + }, + "scripting": { + "name": "Scripting", + "description": "Benutzerdefinierte Skripte ausführen, um SnapEnhance zu erweitern", + "properties": { + "developer_mode": { + "name": "Entwickler:innenmodus", + "description": "Zeigt Debug-Informationen auf Snapchat's UI" + }, + "module_folder": { + "name": "Modulordner", + "description": "Der Ordner, in dem sich die Skripte befinden" + }, + "auto_reload": { + "name": "Automatisches Neuladen", + "description": "Automatisches Neuladen von Skripten, wenn diese sich ändern" + }, + "integrated_ui": { + "name": "Integrierte Benutzeroberfläche", + "description": "Erlaubt Skripten, benutzerdefinierte UI-Komponenten zu Snapchat hinzuzufügen" + }, + "disable_log_anonymization": { + "name": "Log-Anonymisierung deaktivieren", + "description": "Deaktiviert die Anonymisierung von Logs" + } + } + }, + "friend_tracker": { + "name": "Freundestracker", + "description": "Die Aktivität der Freunde aufzeichnen", + "properties": { + "record_messaging_events": { + "name": "Nachrichtenevents aufzeichnen", + "description": "Zeichnet Nachrichtenereignisse wie das Öffnen eines Snaps, das Lesen einer Nachricht usw. auf." + }, + "allow_running_in_background": { + "name": "Hintergrundnutzung erlauben", + "description": "Ermöglicht die Ausführung des Trackers im Hintergrund. Hinweis: Dadurch wird Ihr Akku erheblich entladen" + } + } + } + }, + "options": { + "friend_feed_menu_buttons": { + "auto_download": "⬇️ Auto-Download", + "auto_save": "💬 Auto-Nachricht-Speichern", + "unsaveable_messages": "⬇️ Nicht speicherbare Nachrichten", + "auto_open_snaps": "📷 Automatisches Öffnen von Snaps", + "stealth": "👻 Heimlicher Modus", + "mark_snaps_as_seen": "👀 Snaps als gesehen markieren", + "mark_stories_as_seen_locally": "👀 Stories als lokal gesehen markieren", + "conversation_info": "👤 Gesprächsinformationen", + "e2e_encryption": "🔒 E2E-Verschlüsselung verwenden" + }, + "path_format": { + "append_source": "Füge die Medienquelle zum Dateinamen hinzu", + "append_username": "Füge den Benutzernamen zum Dateinamen hinzu", + "append_date_time": "Füge Datum und Uhrzeit zum Dateinamen hinzu", + "create_author_folder": "Erzeuge ein Verzeichnis für jeden Benutzer", + "create_source_folder": "Ordner für jeden Medienquellentyp erstellen", + "append_hash": "Fügt jedem Dateinamen einen einzigartigen Hash hinzu" + }, + "auto_download_sources": { + "friend_snaps": "Freund-Snaps", + "friend_stories": "Freund-Stories", + "public_stories": "Öffentliche Stories", + "spotlight": "Spotlight" + }, + "auto_purge": { + "1_hour": "1 Stunde", + "3_hours": "3 Stunden", + "6_hours": "6 Stunden", + "12_hours": "12 Stunden", + "1_day": "1 Tag", + "3_days": "3 Tage", + "never": "Nie", + "1_week": "1 Woche", + "2_weeks": "2 Wochen", + "1_month": "1 Monat", + "3_months": "3 Monate", + "6_months": "6 Monate" + }, + "app_appearance": { + "always_light": "Immer hell", + "always_dark": "Immer dunkel" + }, + "logging": { + "started": "Gestartet", + "success": "Erfolgreich", + "progress": "Fortschritt", + "failure": "Fehler" + }, + "notifications": { + "chat_screenshot": "Screenshot", + "chat_screen_record": "Bildschirmaufnahme", + "typing": "Schreiben", + "snap_replay": "Snap Wiederholung", + "camera_roll_save": "In Aufnahmen gespeichert", + "chat": "Chat", + "chat_reply": "Chat Antwort", + "snap": "Snap", + "stories": "Stories", + "speaking": "Sprache", + "chat_reaction": "DM-Reaktion", + "group_chat_reaction": "Gruppenreaktion", + "initiate_audio": "Eingehender Audioanruf", + "abandon_audio": "Verpasster Audioanruf", + "initiate_video": "Eingehender Videoanruf", + "abandon_video": "Verpasster Videoanruf" + }, + "gallery_media_send_override": { + "always_ask": "Immer Fragen", + "ORIGINAL": "Original", + "NOTE": "Audio-Notiz", + "SNAP": "Snap" + }, + "strip_media_metadata": { + "hide_caption_text": "Bildunterschriftstext ausblenden", + "hide_snap_filters": "Snap Filter ausblenden", + "hide_extras": "Extras ausblenden (z. B. Erwähnungen)", + "remove_audio_note_duration": "Dauer der Sprachnachricht entfernen", + "remove_audio_note_transcript_capability": "Sprachnachricht-Transkriptionsfunktion entfernen" + }, + "hide_ui_components": { + "hide_profile_call_buttons": "Entferne Anruf Tasten", + "hide_chat_call_buttons": "Entferne Anruf Tasten im Chat", + "hide_live_location_share_button": "Schaltfläche Live-Standortfreigabe entfernen", + "hide_stickers_button": "Entferne Stickers Taste", + "hide_voice_record_button": "Knopf für Sprachaufzeichnung entfernen", + "hide_unread_chat_hint": "Hinweis auf ungelesene Chats entfernen" + }, + "hide_story_suggestions": { + "hide_suggested_friend_stories": "Empfohlene Stories von Freunden ausblenden", + "hide_my_stories": "Meine Stories verbergen" + }, + "home_tab": { + "map": "Karte", + "chat": "Chat", + "camera": "Kamera", + "discover": "Entdecken", + "spotlight": "Spotlight" + }, + "add_friend_source_spoof": { + "added_by_username": "Nach Benutzername", + "added_by_mention": "Durch Erwähnung", + "added_by_group_chat": "Per Gruppenchat", + "added_by_qr_code": "Per QR-Code", + "added_by_community": "Per Community" + }, + "bypass_video_length_restriction": { + "single": "Einzelnes Medium", + "split": "Medien aufteilen" + }, + "old_bitmoji_selfie": { + "2d": "2D Bitmoji", + "3d": "3D Bitmoji" + }, + "disable_confirmation_dialogs": { + "erase_message": "Nachricht löschen", + "remove_friend": "Freund entfernen", + "block_friend": "Freund blockieren", + "ignore_friend": "Freund ignorieren", + "hide_friend": "Freund ausblenden", + "hide_conversation": "Konversation ausblenden", + "clear_conversation": "Konversation aus dem Freundes-Feed löschen" + }, + "auto_reload": { + "snapchat_only": "Nur Snapchat", + "all": "Alles (Snapchat + SnapEnhance)" + }, + "edit_text_override": { + "multi_line_chat_input": "Mehrzeiliges Chat-Eingabefeld", + "bypass_text_input_limit": "Umgehen des Limits für die Texteingabe" + }, + "disable_story_sections": { + "friends": "Freunde", + "following": "Folge Ich", + "discover": "Entdecken" + }, + "disable_cameras": { + "front": "Selfie Kamera", + "back": "Hauptkamera" + }, + "disable_permission_requests": { + "notifications": "Benachrichtigungen", + "read_media_images": "Medienbilder lesen", + "read_media_video": "Medienvideos lesen", + "camera": "Kamera", + "microphone": "Mikrofon", + "location": "Standort", + "read_contacts": "Kontakte lesen", + "nearby_devices": "In der Nähe befindliche Geräte", + "phone_calls": "Telefonanrufe" + }, + "message_indicators": { + "encryption_indicator": "Fügt neben Nachrichten, die nur an Sie gesendet wurden, ein 🔒-Symbol hinzu", + "platform_indicator": "Fügt das Plattformsymbol hinzu, von der aus ein Medium gesendet wurde (z. B. Android, iOS, Web)", + "location_indicator": "Fügt Snaps ein 📍-Symbol hinzu, wenn sie mit aktivierter Standortfunktion gesendet wurden", + "ovf_editor_indicator": "Kennzeichnet, ob ein Snap mit dem OVF-Editor gesendet wurde", + "director_mode_indicator": "Fügt Snaps ein ✏️-Symbol hinzu, wenn sie mit dem Director-Modus gesendet wurden, der verwendet werden kann, um Galeriebilder als Snaps zu senden" + }, + "auto_mark_as_read": { + "conversation_read": "Markiert Konversation als gelesen sobald eine Narchicht gesendet wird", + "snap_reply": "Markiert Snaps als gelesen sobald auf sie geantwortet wird" + }, + "friend_mutation_notifier": { + "remove_friend": "Benachrichtige, wenn dich jemand als Freund entfernt", + "birthday_changes": "Benachrichtige, wenn jemand sein Geburtsdatum ändert", + "bitmoji_selfie_changes": "Benachrichtigen, wenn jemand sein Bitmoji-Selfie ändert", + "bitmoji_avatar_changes": "Benachrichtige, wenn jemand sein Bitmoji-Avatar ändert", + "bitmoji_background_changes": "Benachrichtige, wenn jemand den Hintergrund seines Bitmoji ändert", + "bitmoji_scene_changes": "Benachrichtige, wenn jemand seine Bitmoji-Szene ändert" + } + }, + "notices": { + "unstable": "⚠ Instabil", + "ban_risk": "⚠ Dieses Feature kann zu Bans führen", + "internal_behavior": "⚠ Dies kann das interne Verhalten von Snapchat stören" + } + }, + "friend_menu_option": { + "mark_snaps_as_seen": "Snaps als gesehen markieren", + "mark_stories_as_seen_locally": "Stories als lokal gesehen markieren", + "preview": "Vorschau", + "stealth_mode": "Inkognitomodus", + "auto_download_blacklist": "Blacklist für automatische Downloads", + "anti_auto_save": "Anti-Auto-Speichern" + }, + "content_type": { + "CHAT": "Chat", + "SNAP": "Snap", + "EXTERNAL_MEDIA": "Externe Medien", + "NOTE": "Sprachnachricht", + "STICKER": "Sticker", + "STATUS": "Status", + "LOCATION": "Standort", + "STATUS_SAVE_TO_CAMERA_ROLL": "In Camera Roll gespeichert", + "STATUS_CONVERSATION_CAPTURE_SCREENSHOT": "Screenshot", + "STATUS_CONVERSATION_CAPTURE_RECORD": "Bildschirmaufnahme", + "STATUS_CALL_MISSED_VIDEO": "Verpasster Videoanruf", + "STATUS_CALL_MISSED_AUDIO": "Verpasster Sprachanruf", + "LIVE_LOCATION_SHARE": "Live-Standort teilen", + "CREATIVE_TOOL_ITEM": "Kreativ-Werkzeug Element", + "FAMILY_CENTER_INVITE": "Family Center einladen", + "FAMILY_CENTER_ACCEPT": "Family Center akzeptieren", + "FAMILY_CENTER_LEAVE": "Family Center verlassen", + "STATUS_PLUS_GIFT": "Status Plus Geschenk", + "TINY_SNAP": "Winziger Snap", + "STATUS_COUNTDOWN": "Countdown", + "MAP_REACTION": "Kartenreaktion" + }, + "chat_action_menu": { + "preview_button": "Vorschau", + "download_button": "Download", + "delete_logged_message_button": "Gespeicherte Nachrichten löschen", + "convert_message": "Nachricht konvertieren", + "edit_message": "Nachricht bearbeiten" + }, + "opera_context_menu": { + "download": "Medien herunterladen", + "sent_at": "Gesendet am {date}", + "created_at": "Erstellt am {date}", + "expires_at": "Läuft am {date} ab", + "media_size": "Mediengröße: {size}", + "media_duration": "Mediendauer: {duration} ms", + "show_debug_info": "Debug-Informationen anzeigen" + }, + "modal_option": { + "profile_info": "Profil Info", + "close": "Schließen" + }, + "gallery_media_send_override": { + "multiple_media_toast": "Du kannst nur eine Datei auf einmal senden" + }, + "profile_info": { + "title": "Profil Info", + "first_created_username": "Erster Benutzername", + "mutable_username": "Änderbarer Benutzername", + "display_name": "Anzeigename", + "added_date": "Datum hinzugefügt", + "birthday": "Geburtstag: {month} {day}", + "hidden_birthday": "Geburtstag : Versteckt", + "friendship": "Freundschaft", + "add_source": "Quelle hinzufügen", + "snapchat_plus": "Snapchat Plus", + "snapchat_plus_state": { + "subscribed": "Abonniert", + "not_subscribed": "Nicht abonniert" + } + }, + "friendship_link_type": { + "mutual": "Gegenseitig", + "outgoing": "Ausgehend", + "blocked": "Blockiert", + "deleted": "Gelöscht", + "following": "Folge Ich", + "suggested": "Empfohlen", + "incoming": "Eingehend", + "incoming_follower": "Eingehender Follower" + }, + "bulk_messaging_action": { + "choose_action_title": "Wähle eine Aktion", + "progress_status": "Verarbeite {index} von {total}", + "selection_dialog_continue_button": "Weiter", + "confirmation_dialog": { + "title": "Sind Sie sicher?", + "message": "Das betrifft alle ausgewählten Freunde. Diese Aktion kann nicht rückgängig gemacht werden." + }, + "actions": { + "remove_friends": "Freunde entfernen", + "clear_conversations": "Lösche Konversationen" + } + }, + "better_notifications": { + "button": { + "reply": "Antwort", + "download": "Herunterladen", + "mark_as_read": "Als gelesen markieren" + } + }, + "profile_picture_downloader": { + "button": "Profilbilder herunterladen", + "title": "Profilbild-Downloader", + "avatar_option": "Avatar", + "background_option": "Hintergrund" + }, + "call_start_confirmation": { + "dialog_title": "Anruf starten", + "dialog_message": "Sind Sie sicher, dass Sie einen Anruf starten wollen?" + }, + "half_swipe_notifier": { + "notification_content_group": "{friend} hat gerade halb in {group} für {duration} Sekunden geswiped", + "notification_channel_name": "Halb-Swipe", + "notification_content_dm": "{friend} hat gerade für {duration} Sekunden halb in deinen Chat geswiped" + }, + "streaks_reminder": { + "notification_title": "Flammen", + "notification_text": "Du wirst deine Flammen mit {friend} in {hoursLeft} Stunden verlieren" + }, + "biometric_auth": { + "unlock_button": "Entsperren", + "title": "Entsperre Snapchat", + "subtitle": "Bitte authentifizieren Sie sich um Snapchat zu entsperren" + }, + "end_to_end_encryption": { + "toolbox": { + "no_shared_key": "Sie haben noch kein gemeinsames Geheimnis mit diesem Freund. Klicken Sie unten, um ein neues zu erstellen.", + "shared_key_fingerprint": "Dein Fingerabdruck ist:\n\n{fingerprint}\n\nSieh nach, ob er mit dem Fingerabdruck deines Freundes übereinstimmt!", + "initiate_exchange_button": "Schlüsselaustausch einleiten" + }, + "confirmation_dialogs": { + "title": "Ende-zu-Ende Verschlüsselung", + "confirmation_1": "WARNUNG: Dadurch wird Ihr vorhandener Schlüssel überschrieben. Sie werden den Zugang zu allen verschlüsselten Nachrichten dieses Freundes verlieren. Sind Sie sicher, dass Sie fortfahren möchten?", + "confirmation_2": "Sind Sie WIRKLICH sicher, dass Sie weitermachen wollen? Dies ist Ihre letzte Chance, einen Rückzieher zu machen." + }, + "unencrypted_conversation_send_failure_toast": "Sie können keine verschlüsselten Inhalte zu verschlüsselten und unverschlüsselten Gesprächen gleichzeitig senden!", + "native_hooks_send_failure_toast": "Senden fehlgeschlagen! Bitte aktivieren Sie die nativen Hooks in den Einstellungen.", + "no_participants_to_encrypt_toast": "Sie haben in diesem Gespräch keine Freunde, mit denen Sie Nachrichten verschlüsseln können!", + "encryption_failed_toast": "Nachricht konnte nicht verschlüsselt werden! Prüfen Sie logcat für weitere Details.", + "accept_public_key_success_toast": "Öffentlicher Schlüssel erfolgreich akzeptiert!", + "accept_secret_key_success_toast": "Geschafft! Sie können nun verschlüsselte Nachrichten an diesen Freund senden und empfangen.", + "accept_public_key_failure_toast": "Akzeptieren des öffentlichen Schlüssels fehlgeschlagen", + "accept_secret_key_failure_toast": "Akzeptieren des geheimen Schlüssels fehlgeschlagen", + "accept_secret_button": "Geheimnis akzeptieren", + "accept_public_key_button": "Öffentlichen Schlüssel akzeptieren", + "outgoing_pk_message": "Schlüsselaustausch-Anfrage", + "outgoing_secret_message": "Schlüsselaustausch-Antwort", + "incoming_pk_message": "Sie haben gerade eine Anfrage für einen öffentlichen Schlüssel erhalten. Klicken Sie unten, um sie anzunehmen.", + "incoming_secret_message": "Ihr Freund hat gerade Ihren öffentlichen Schlüssel akzeptiert. Klicken Sie unten, um das Passwort zu akzeptieren." + } +} diff --git a/common/src/main/assets/lang/hi_IN.json b/common/src/main/assets/lang/hi_IN.json index 3c0fd262..5136e4ef 100644 --- a/common/src/main/assets/lang/hi_IN.json +++ b/common/src/main/assets/lang/hi_IN.json @@ -2,617 +2,279 @@ "setup": { "dialogs": { "select_language": "भाषा चुनें", - "save_folder": "PurrfectSnap को Snapchat से मीडिया डाउनलोड करने और सहेजने के लिए संग्रहण अनुमतियों की आवश्यकता है।\nकृपया वह स्थान चुनें जहाँ मीडिया डाउनलोड किया जाना चाहिए।", - "select_save_folder_button": "फ़ोल्डर चुनें" + "select_save_folder_button": "फोल्डर चुनें", + "save_folder": "SnapEnhance को स्नैपचैट से मीडिया को डाउनलोड करने और सेव करने के लिए स्टोरेज अनुमति की आवश्यकता होती है।\n कृपया वह स्थान चुनें जहां से मीडिया डाउनलोड किया जाना चाहिए।" }, "mappings": { - "dialog": "मैपिंग बना रहा है, इसमें कुछ समय लग सकता है...", - "generate_failure_no_snapchat": "PurrfectSnap Snapchat का पता नहीं लगा सका, कृपया Snapchat को फिर से स्थापित करने का प्रयास करें।", - "generate_failure": "मैपिंग बनाने का प्रयास करते समय एक त्रुटि हुई, कृपया पुनः प्रयास करें।" + "generate_failure_no_snapchat": "स्नैपएन्हांस के द्वारा स्नैपचैट को डिटेक्ट नहीं किया गया, कृपया स्नैपचैट दुबारा इंस्टॉल करें।", + "generate_failure": "मैपिंग बनाते समय एक त्रुटि पाई गई है, कृपया दुबारा कोसिस करें।", + "dialog": "स्नैपचैट संस्करणों की एक विस्तृत श्रृंखला को गतिशील रूप से समर्थन देने के लिए, SnapEnhance के ठीक से काम करने के लिए मैपिंग आवश्यक है, इसमें 5 सेकंड से अधिक समय नहीं लगना चाहिए।" }, "permissions": { - "dialog": "जारी रखने के लिए आपको निम्नलिखित आवश्यकताओं को पूरा करना होगा:", - "notification_access": "अधिसूचना पहुंच", - "battery_optimization": "बैटरी अनुकूलन", - "display_over_other_apps": "अन्य ऐप्स पर प्रदर्शित करें", + "dialog": "आगे बढ़ने के लिए आपको निम्नलिखित मांगो को पूरा करना पड़ेगा।:", + "notification_access": "नोटिफिकेशन अनुमति", + "battery_optimization": "बैटरी ऑप्टिमाइजेशन", + "display_over_other_apps": "दूसरे ऐप्लिकेशन के ऊपर दिखाए जाने का ऐक्सेस", "request_button": "अनुरोध" } }, - "scopes": { - "friend": "मित्र", - "group": "समूह" - }, "manager": { "routes": { - "tasks": "कार्य", - "features": "विशेषताएँ", - "manage_rule_feature": "नियम सुविधा प्रबंधित करें", - "home": "घर", + "features": "फीचर्स", + "home": "होम", "home_settings": "सेटिंग्स", - "home_logs": "लॉग", - "logger_history": "लॉगर इतिहास", - "logged_stories": "लॉग की गई कहानियाँ", - "friend_tracker": "मित्र ट्रैकर", - "edit_rule": "नियम संपादित करें", - "file_imports": "फ़ाइल आयात", - "manage_repos": "भंडार प्रबंधित करें", "social": "सामाजिक", - "manage_scope": "दायरा प्रबंधित करें", - "messaging_preview": "पूर्वावलोकन", "scripts": "स्क्रिप्ट", - "better_location": "बेहतर स्थान" + "home_logs": "लॉग्स", + "tasks": "कार्य", + "manage_scope": "दायरा प्रबंधित करें", + "messaging_preview": "पूर्व दर्शन", + "logger_history": "प्रचालेखन इतिहास", + "logged_stories": "प्रचालेखित कि गई स्टोरी" }, "sections": { - "home": { - "version_title": "v{versionName} · Eternal द्वारा फोर्क किया गया", - "update_title": "PurrfectSnap अपडेट", - "update_content": "संस्करण {version} उपलब्ध है!", - "update_button": "डाउनलोड करें", - "debug_build_summary_title": "आप PurrfectSnap का एक डिबग बिल्ड चला रहे हैं", - "debug_build_summary_content": "संस्करण {versionName} ({versionCode})", - "debug_build_summary_date": "बिल्ड तिथि: {date} ({days} दिन पहले)", - "quick_actions_title": "त्वरित क्रियाएँ", - "download_icon_description": "डाउनलोड करें", - "completed_icon_description": "पूर्ण", - "failed_icon_description": "विफल", - "manage_quick_actions_description": "त्वरित क्रियाएँ प्रबंधित करें", - "quick_actions_icon_description": "त्वरित क्रियाएँ", - "add_quick_action_description": "त्वरित क्रिया जोड़ें" + "features": { + "disabled": "निष्क्रिय", + "export_option": "निर्यात", + "import_option": "आयात", + "reset_option": "फिर से सब पहले जैसा करे", + "config_import_success_toast": "फाइल सफलतापूर्वक लग चुकी है", + "config_import_failure_toast": "फाइल असफल हुई आने मे (Import failed)", + "saved_config_snackbar": "फाइल सेव हो चुकी है", + "config_export_success_toast": "विन्यास सफलतापूर्वक निर्यात किया गया" }, - "home_logs": { - "no_logs_hint": "कोई लॉग उपलब्ध नहीं है", - "clear_logs_button": "लॉग साफ़ करें", - "export_logs_button": "लॉग निर्यात करें", - "saving_logs_toast": "लॉग सहेज रहा है, इसमें कुछ समय लग सकता है...", - "saved_logs_success_toast": "लॉग सफलतापूर्वक सहेजे गए", - "saved_logs_failure_toast": "लॉग सहेजने में विफल" - }, - "home_settings": { - "actions_title": "क्रियाएँ", - "message_logger_title": "संदेश लकड़हारा", - "debug_title": "डीबग", - "success_toast": "हो गया!", - "message_logger_summary": "{messageCount} संदेश\n{storyCount} कहानियाँ", - "export_button": "निर्यात करें", - "clear_button": "साफ़ करें", - "view_logger_history_button": "लॉगर इतिहास देखें", - "updates_title": "अपडेट", - "auto_update_check": "अपडेट के लिए स्वतः जांचें", - "update_check_frequency": "अपडेट जांच आवृत्ति", - "update_check_frequency_daily": "दैनिक", - "update_check_frequency_weekly": "साप्ताहिक", - "update_check_frequency_monthly": "मासिक", - "theme_icon_description": "थीम", - "app_theme_title": "ऐप थीम", - "theme_mode_system": "सिस्टम", - "theme_mode_light": "प्रकाश", - "theme_mode_dark": "अंधेरा", - "ui_settings_title": "UI सेटिंग्स", - "haptic_feedback_label": "हैप्टिक फीडबैक", - "test_mode_label": "परीक्षण मोड (केवल डिबगिंग के लिए)", - "disable_feature_loading_label": "सुविधा लोडिंग अक्षम करें", - "disable_auto_mapper_label": "ऑटो मैपर अक्षम करें", - "disable_bypass_indicator_label": "बाईपास स्थिति संकेतक अक्षम करें", - "update_notification_channel_name": "PurrfectSnap अपडेट", - "update_notification_channel_description": "PurrfectSnap अपडेट के लिए सूचनाएं", - "update_notification_title": "PurrfectSnap अपडेट उपलब्ध है", - "update_notification_text": "संस्करण %s अब उपलब्ध है।", - "export_database_failed_toast": "डेटाबेस निर्यात करने में विफल! {message}", - "clear_messages_failed_toast": "संदेशों को साफ़ करने में विफल! {message}", - "clear_file_failed_toast": "फ़ाइल साफ़ करने में विफल! {message}", - "debug_file_config": "विन्यास", - "debug_file_mappings": "मैपिंग", - "debug_file_message_logger": "संदेश लकड़हारा", - "debug_file_pinned_best_friend": "पिन किया हुआ सबसे अच्छा दोस्त", - "debug_file_native_sig_cache": "मूल हस्ताक्षर कैश" + "social": { + "streaks_expiration_short": "{hours}h", + "friends_tab": "दोस्त", + "groups_tab": "समूह" }, "tasks": { "no_tasks": "कोई कार्य नहीं", - "merge_button": "मिलाना", - "failed_to_open_file": "फ़ाइल खोलने में विफल", - "merge_files_toast": "{count} फ़ाइलों को मिला रहा है", - "remove_selected_tasks_title": "क्या आप वाकई चयनित कार्यों को हटाना चाहते हैं?", - "remove_all_tasks_title": "क्या आप वाकई सभी कार्यों को हटाना चाहते हैं?", - "delete_files_option": "फ़ाइलें भी हटाएं", - "remove_selected_tasks_confirm": "{count} कार्यों को हटाएं?", - "remove_all_tasks_confirm": "सभी कार्यों को हटाएं?", - "clear_tasks_description": "कार्य साफ़ करें", - "file_not_found_icon_description": "फ़ाइल नहीं मिली", - "image_icon_description": "छवि", - "video_icon_description": "वीडियो", - "audio_icon_description": "ऑडियो", - "file_icon_description": "फ़ाइल", - "download_icon_description": "डाउनलोड करें", - "chat_action_icon_description": "चैट क्रिया", - "cancel_icon_description": "रद्द करें", - "success_icon_description": "सफलता", - "failure_icon_description": "विफलता", - "cancelled_icon_description": "रद्द", - "task_status_failure": "विफलता", - "task_status_cancelled": "रद्द" + "merge_files_toast": "{संख्या} फाईल जुड़ रही है", + "delete_files_option": "files भी हटाएं", + "remove_selected_tasks_confirm": "{संख्या} कार्य हटाएं?", + "remove_all_tasks_confirm": "सभी कार्य हटाएं?", + "remove_all_tasks_title": "क्या आप सभी कार्यों को हटाने के लिए सहमत हैं?", + "remove_selected_tasks_title": "क्या आप चिह्नित किए हुए कार्यों को हटाने के लिए सहमत है?" }, - "features": { - "disabled": "अक्षम", - "export_option": "निर्यात करें", - "import_option": "आयात करें", - "reset_option": "रीसेट करें", - "config_export_success_toast": "कॉन्फ़िगरेशन सफलतापूर्वक निर्यात किया गया", - "config_import_success_toast": "कॉन्फ़िगरेशन सफलतापूर्वक आयात किया गया", - "config_import_failure_toast": "कॉन्फ़िगरेशन आयात करने में विफल {error}", - "config_export_failure_toast": "कॉन्फ़िगरेशन निर्यात करने में विफल {error}", - "saved_config_snackbar": "कॉन्फ़िगरेशन सहेजा गया", - "older_required": "इस सुविधा को ठीक से काम करने के लिए Snapchat v{version} या पुराने की आवश्यकता है", - "newer_required": "इस सुविधा को ठीक से काम करने के लिए Snapchat v{version} या नए की आवश्यकता है", - "search_button": "खोज" + "home": { + "update_content": "वर्जन {वर्जन} उपलब्ध है!", + "update_title": "SnapEnhance अपडेट", + "update_button": "डाऊनलोड" }, - "manage_rule_feature": { - "disable_state_option": "अक्षम", - "disable_state_subtext": "कोई मित्र/समूह प्रभावित नहीं होंगे", - "whitelist_state_option": "सिवाय कोई नहीं ...", - "whitelist_state_subtext": "केवल {count} मित्र/समूह इस नियम से प्रभावित होंगे", - "whitelist_state_button": "अनुमत मित्र/समूह चुनें", - "blacklist_state_option": "सिवाय हर कोई ...", - "blacklist_state_subtext": "सिवाय हर कोई {count} मित्र/समूह इस नियम से प्रभावित होंगे", - "blacklist_state_button": "बहिष्कृत मित्र/समूह चुनें", - "clear_list_button": "मित्र/समूह सूची साफ़ करें", - "dialog_clear_confirmation_text": "क्या आप वाकई सूची साफ़ करना चाहते हैं?" + "home_logs": { + "no_logs_hint": "logs उपलब्ध नहीं", + "clear_logs_button": "logs साफ करें", + "export_logs_button": "logs निर्यात करें", + "saving_logs_toast": "logs सेव हो रहे हैं, इसमें थोड़ा सा ही समय लगेगा..।", + "saved_logs_success_toast": "विवरण सफलतापूर्वक सेव हो चुके हैं", + "saved_logs_failure_toast": "logs सेव होने में असफल" }, - "social": { - "friends_tab": "मित्र", - "groups_tab": "समूह", - "empty_hint": "(खाली)", - "streaks_expiration_short": "{hours}घ" - }, - "manage_scope": { - "logged_stories_button": "लॉग की गई कहानियाँ दिखाएँ", - "e2ee_title": "एंड-टू-एंड एन्क्रिप्शन", - "rules_title": "नियम", - "participants_text": "{count} प्रतिभागी", - "not_found": "नहीं मिला", - "streaks_title": "स्ट्रीक्स", - "streaks_length_text": "लंबाई: {length}", - "streaks_expiration_text": "{eta} में समाप्त होता है", - "streaks_expiration_text_expired": "समाप्त", - "reminder_button": "रिमाइंडर सेट करें", - "delete_scope_confirm_dialog_title": "क्या आप वाकई एक {scope} हटाना चाहते हैं?", - "notes_placeholder": "एक नोट जोड़ने के लिए क्लिक करें", - "invalid_key_size_32_bytes": "अमान्य कुंजी आकार (32 बाइट्स होना चाहिए)", - "successfully_imported_key": "कुंजी सफलतापूर्वक आयात की गई", - "failed_to_import_key": "कुंजी आयात करने में विफल: {message}", - "export_base64_button": "बेस64 निर्यात करें", - "import_base64_button": "बेस64 आयात करें" - }, - "logged_stories": { - "story_failed_to_load": "लोड करने में विफल", - "no_stories": "कोई कहानी नहीं मिली", - "save_from_cache_button": "कैश से सहेजें", - "downloaded_to_path": "{path} पर डाउनलोड किया गया", - "download_failed": "डाउनलोड विफल: {message}", - "posted_at": "{date} को पोस्ट किया गया", - "created_at": "{date} को बनाया गया", - "failed_to_open_file": "फ़ाइल खोलने में विफल। अधिक जानकारी के लिए लॉग देखें", - "failed_to_get_file": "फ़ाइल प्राप्त करने में विफल" + "home_settings": { + "actions_title": "प्रत्क्रिया", + "message_logger_summary": "{मैसेज संख्या} मैसेज\n{स्टोरी संख्या} स्टोरीज", + "view_logger_history_button": "logger हिस्ट्री देखे", + "export_button": "निर्यात करें", + "clear_button": "साफ करें", + "message_logger_title": "मेसेज को डिलीट होने से बचाएं", + "debug_title": "दोष मुक्त", + "success_toast": "हो चुका!" }, "messaging_preview": { - "processed_messages_toast": "{count} संदेशों पर कार्रवाई की गई", - "processed_messages_text": "{count} संदेशों पर कार्रवाई की गई", - "close_button_description": "बंद करें", - "bridge_connection_failed": "ब्रिज से कनेक्ट करने में विफल। सुनिश्चित करें कि Snapchat पृष्ठभूमि में चल रहा है", - "bridge_init_failed": "संदेश भेजने वाले ब्रिज को शुरू करने में विफल। सुनिश्चित करें कि Snapchat पृष्ठभूमि में चल रहा है", - "message_fetch_failed": "संदेश प्राप्त करने में विफल", - "no_message_hint": "कोई संदेश नहीं", + "mark_selection_as_seen_option": "चुने हुए स्नेप को पढा हुआ करे", + "mark_all_as_seen_option": "सभी स्नेप को पढा हुआ करे", + "delete_all_option": "सभी डिलीट करे", + "bridge_connection_failed": "ब्रिज सर्विस के माध्यम से स्नैपचैट से कनेक्ट करने में विफल", + "bridge_init_failed": "मैसेजिंग ब्रिज आरंभ करने में विफल", + "no_message_hint": "कोई मैसेज नही", + "save_all_option": "सभी सेव करें", + "unsave_all_option": "सभी सेव हटाए", + "delete_selection_option": "चुने हुए डिलिट करें", + "message_fetch_failed": "संदेश लाने में विफल", "save_selection_option": "चयन सहेजें", - "save_all_option": "सभी सहेजें", - "unsave_selection_option": "चयन को न सहेजें", - "unsave_all_option": "सभी को न सहेजें", - "mark_selection_as_seen_option": "चयनित स्नैप को देखे गए के रूप में चिह्नित करें", - "mark_all_as_seen_option": "सभी स्नैप को देखे गए के रूप में चिह्नित करें", - "delete_selection_option": "चयन हटाएं", - "delete_all_option": "सभी हटाएं" + "unsave_selection_option": "चयन सहेजें नहीं" + }, + "manage_scope": { + "rules_title": "नियम", + "logged_stories_button": "लॉग की गई कहानियाँ दिखाएँ", + "e2ee_title": "एंड-टू-एंड एन्क्रिप्शन", + "participants_text": "{गिनती} प्रतिभागी", + "not_found": "नहीं मिला", + "streaks_title": "धारियाँ", + "streaks_length_text": "लंबाई: {लंबाई}", + "streaks_expiration_text": "{eta} में समाप्त होगा", + "streaks_expiration_text_expired": "खत्म हो चुका", + "reminder_button": "अनुस्मारक सेट करें", + "delete_scope_confirm_dialog_title": "क्या आप वाकई एक {स्कोप} हटाना चाहते हैं?" + }, + "logged_stories": { + "story_failed_to_load": "लोड करने में असफल", + "no_stories": "कोर्ई स्टोरी नही", + "save_from_cache_button": "कैश से बचाएं" }, "logger_history": { - "download_started_toast": "डाउनलोड शुरू हो गया!", - "download_success_toast": "{path} पर डाउनलोड किया गया", - "download_failed_toast": "{message} डाउनलोड करने में विफल", - "edited_at_text": "{message} ({date} को संपादित)", - "download_button": "डाउनलोड करें", - "select_conversation_placeholder": "एक वार्तालाप चुनें", - "close_button_description": "बंद करें", - "search_button_description": "खोज", - "list_friend_format": "मित्र {name}", - "list_group_format": "समूह {name}", - "no_more_messages": "कोई और संदेश नहीं", - "reverse_order_checkbox": "उलटा क्रम", - "chat_attachment": "अनुलग्नक {index}", - "empty_message": "खाली चैट संदेश", + "list_friend_format": "दोस्त {नाम}", + "list_group_format": "समुह {नाम}", + "no_more_messages": "कोई मैसेज नही", "message_parse_failed": "संदेश को पार्स करने में विफल", - "unknown_sender": "अज्ञात प्रेषक", - "download_attachment_failed_toast": "अनुलग्नक डाउनलोड करने में विफल", - "log_header_format": "{username} ({type}) - {date}" - }, - "file_imports": { - "import_file_button": "फ़ाइल आयात करें", - "file_not_found": "फ़ाइल नहीं मिली", - "file_import_failed": "फ़ाइल आयात करने में विफल: {error}", - "file_imported": "फ़ाइल सफलतापूर्वक आयात की गई", - "file_delete_failed": "फ़ाइल हटाने में विफल", - "no_files_hint": "यहां आप Snapchat में उपयोग के लिए फ़ाइलें आयात कर सकते हैं। फ़ाइल आयात करने के लिए नीचे दिए गए बटन को दबाएं।" - }, - "better_location": { - "spoofed_coordinates_title": "अक्षांश {latitude}, देशांतर {longitude}", - "save_coordinates_dialog_title": "निर्देशांक सहेजें", - "saved_name_dialog_hint": "सहेजा गया नाम", - "latitude_dialog_hint": "अक्षांश", - "longitude_dialog_hint": "देशांतर", - "save_dialog_button": "सहेजें", - "choose_location_button": "स्थान चुनें", - "teleport_to_friend_button": "मित्र के पास टेलीपोर्ट करें", - "spoof_location_toggle": "स्थान स्पूफ करें", - "suspend_location_updates": "स्थान अपडेट निलंबित करें", - "saved_coordinates_title": "सहेजे गए निर्देशांक", - "no_saved_coordinates_hint": "कोई सहेजे गए निर्देशांक नहीं", - "delete_dialog_title": "सहेजा गया निर्देशांक हटाएं", - "delete_dialog_message": "क्या आप वाकई इस सहेजे गए निर्देशांक को हटाना चाहते हैं?", - "teleport_to_friend_title": "मित्र के पास टेलीपोर्ट करें", - "search_bar": "खोज", - "no_friends_map": "नक्शे पर कोई मित्र नहीं", - "no_friends_found": "कोई मित्र नहीं मिला", - "edit_location_button_description": "स्थान संपादित करें", - "add_icon_description": "जोड़ें", - "edit_icon_description": "संपादित करें", - "delete_icon_description": "हटाएं" + "unknown_sender": "अज्ञात व्यक्ति", + "reverse_order_checkbox": "उल्टे क्रम", + "chat_attachment": "अनुलग्नक {सूचकांक}", + "empty_message": "खाली चैट संदेश", + "download_attachment_failed_toast": "अनुलग्नक डाउनलोड करने में विफल" } }, "dialogs": { "add_friend": { "title": "मित्र या समूह जोड़ें", - "search_hint": "खोज", - "fetch_error": "डेटा प्राप्त करने में विफल", "category_groups": "समूह", - "category_friends": "मित्र", - "participants_text": "{count} प्रतिभागी", - "search_icon_description": "खोज" + "fetch_error": "डेटा लाने में विफल", + "category_friends": "दोस्त", + "search_hint": "खोज" }, "scripting_warning": { "title": "चेतावनी", - "content": "PurrfectSnap में एक स्क्रिप्टिंग टूल शामिल है, जो आपके डिवाइस पर उपयोगकर्ता-परिभाषित कोड निष्पादित करने की अनुमति देता है। अत्यधिक सावधानी बरतें और केवल ज्ञात, विश्वसनीय स्रोतों से मॉड्यूल स्थापित करें। अनधिकृत या असत्यापित मॉड्यूल आपके सिस्टम के लिए सुरक्षा जोखिम पैदा कर सकते हैं।" + "content": "SnapEnhance में एक स्क्रिप्टिंग टूल शामिल है, जो आपके डिवाइस पर उपयोगकर्ता द्वारा परिभाषित कोड के निष्पादन की अनुमति देता है। अत्यधिक सावधानी बरतें और केवल ज्ञात, विश्वसनीय स्रोतों से ही मॉड्यूल स्थापित करें। अनधिकृत या असत्यापित मॉड्यूल आपके सिस्टम के लिए सुरक्षा जोखिम पैदा कर सकते हैं।" + }, + "messaging_action": { + "select_all_button": "सभी सिलेक्ट करे", + "title": "संसाधित करने के लिए सामग्री प्रकार चुनें" }, "reset_config": { "title": "कॉन्फ़िगरेशन रीसेट करें", - "content": "क्या आप वाकई कॉन्फ़िगरेशन रीसेट करना चाहते हैं?", - "success_toast": "कॉन्फ़िगरेशन सफलतापूर्वक रीसेट किया गया" - }, - "export_config": { - "title": "संवेदनशील डेटा निर्यात करें?", - "content": "क्या आप संवेदनशील डेटा के साथ कॉन्फ़िगरेशन निर्यात करना चाहते हैं? (जैसे स्थान निर्देशांक, आदि)" - }, - "messaging_action": { - "title": "संसाधित करने के लिए सामग्री प्रकार चुनें", - "select_all_button": "सभी चुनें" - }, - "file_imports": { - "no_files_settings_hint": "कोई फ़ाइल नहीं मिली। सुनिश्चित करें कि आपने फ़ाइल आयात अनुभाग में आवश्यक फ़ाइलें आयात की हैं", - "settings_select_file_hint": "एक आयातित फ़ाइल चुनें" - }, - "quick_actions_dialog": { - "title": "त्वरित क्रियाएँ संपादित करें", - "subtitle": "अपनी त्वरित क्रियाएँ चुनें और उनका आकार बदलें।" + "content": "क्या आप वाकई कॉन्फिग को रीसेट करना चाहते हैं?", + "success_toast": "कॉन्फ़िगरेशन सफलतापूर्वक रीसेट हो गया" } - }, - "friend_tracker": { - "rules_tab": "नियम", - "logs_tab": "लॉग", - "export_dialog_title": "निर्यात करें", - "bulk_export_button": "थोक निर्यात", - "individual_export_button": "व्यक्तिगत निर्यात", - "invalid_import_type_dialog_title": "अमान्य आयात प्रकार", - "invalid_import_type_dialog_text": "चयनित फ़ाइल इस आयात प्रकार के साथ संगत नहीं है। कृपया सही आयात प्रकार चुनें।", - "import_dialog_title": "आयात करें", - "bulk_import_button": "थोक आयात", - "individual_import_button": "व्यक्तिगत आयात", - "import_button_description": "आयात करें", - "export_button_description": "निर्यात करें", - "export_button": "निर्यात करें", - "delete_button_description": "हटाएं", - "delete_button": "हटाएं", - "catalog_button_description": "कैटलॉग", - "catalog_button": "कैटलॉग", - "add_rule_button_description": "नियम जोड़ें", - "add_rule_button": "नियम जोड़ें", - "no_rules_found": "कोई नियम नहीं मिला", - "empty_rule_name": "(खाली)", - "events_suffix": "घटनाएँ", - "scopes_suffix": "दायरे", - "select_rule_to_export_title": "निर्यात करने के लिए नियम चुनें", - "deleted_logs_toast": "{count} लॉग हटा दिए गए", - "delete_logs_dialog_title": "लॉग हटाएं?", - "deleting_logs_dialog_text": "{count} लॉग हटा रहा है...", - "delete_logs_dialog_confirm_text": "यह वर्तमान फ़िल्टर और खोज क्वेरी के आधार पर लॉग हटा देगा। इस क्रिया को पूर्ववत नहीं किया जा सकता है।", - "exported_logs_toast": "लॉग निर्यात किए गए!", - "export_logs_failed_toast": "लॉग निर्यात करने में विफल। अधिक विवरण के लिए लॉगकैट देखें।", - "export_logs_dialog_title": "लॉग निर्यात करें?", - "exporting_logs_dialog_text": "लॉग निर्यात कर रहा है...", - "export_logs_dialog_confirm_text": "यह वर्तमान फ़िल्टर और खोज क्वेरी के आधार पर लॉग निर्यात करेगा।", - "export_as_button": "{type} के रूप में निर्यात करें", - "filters_title": "फ़िल्टर", - "search_by_label": "द्वारा खोजें", - "newest_first_label": "नवीनतम पहले", - "since_label": "से", - "until_label": "तक", - "pick_a_date_button": "एक तारीख चुनें", - "search_placeholder": "खोज", - "filter_button_description": "फ़िल्टर", - "clear_button_description": "साफ़ करें", - "no_logs_found": "कोई लॉग नहीं मिला", - "log_event_format": "{conversation} में {event}", - "condition_only_inside_conversation": "केवल जब मैं बातचीत में हूँ", - "condition_only_outside_conversation": "केवल जब मैं बातचीत के बाहर हूँ", - "condition_only_when_app_active": "केवल जब Snapchat सक्रिय हो", - "condition_only_when_app_inactive": "केवल जब Snapchat निष्क्रिय हो", - "condition_no_push_notification_when_app_active": "Snapchat सक्रिय होने पर कोई पुश सूचना नहीं", - "add_event_dialog_title": "घटना जोड़ें", - "event_type_label": "घटना का प्रकार", - "triggers_title": "ट्रिगर्स", - "conditions_title": "शर्तें", - "add_button": "जोड़ें", - "default_rule_name": "कस्टम नियम", - "discard_changes_dialog_title": "परिवर्तन त्यागें?", - "discard_changes_dialog_text": "आपके पास सहेजे नहीं गए परिवर्तन हैं। क्या आप वाकई उन्हें त्यागना चाहते हैं?", - "discard_button": "त्यागें", - "cannot_save_rule_dialog_title": "नियम सहेजा नहीं जा सकता", - "cannot_save_rule_dialog_text": "सहेजने के लिए एक नियम में कम से कम एक घटना होनी चाहिए।", - "duplicate_rule_name_dialog_title": "डुप्लिकेट नियम नाम", - "duplicate_rule_name_dialog_text": "इस नाम का एक नियम पहले से मौजूद है। कृपया एक अलग नाम चुनें।", - "delete_rule_dialog_title": "नियम हटाएं", - "delete_rule_dialog_text": "क्या आप वाकई इस नियम को हटाना चाहते हैं?", - "new_rule_title": "नया नियम", - "edit_rule_title": "नियम संपादित करें", - "back_button_description": "वापस", - "save_button_description": "सहेजें", - "general_section_title": "सामान्य", - "rule_name_label": "नियम का नाम", - "author_name_label": "लेखक का नाम", - "scope_section_title": "दायरा", - "scope_all": "सभी", - "scope_whitelist": "श्वेतसूची", - "scope_blacklist": "कालीसूची", - "select_friends_groups_button": "मित्र/समूह चुनें ({count})", - "events_section_title": "घटनाएँ", - "add_event_button": "घटना जोड़ें", - "no_events_text": "कोई घटना नहीं" - }, - "friend_tracker_catalog": { - "download_failed": "डाउनलोड विफल: {code}", - "error": "त्रुटि: {message}", - "no_repos_added": "कोई भंडार नहीं जोड़ा गया।", - "no_rules_available": "किसी भी भंडार से कोई नियम उपलब्ध नहीं है।", - "by_author": "{author} द्वारा", - "imported_button": "आयातित", - "import_button": "आयात करें", - "title": "मित्र ट्रैकर कैटलॉग", - "manage_repos_description": "भंडार प्रबंधित करें" - }, - "friend_tracker_export": { - "title": "नियम निर्यात करें", - "back_button_description": "वापस", - "exported_toast": "मित्र ट्रैकर नियम निर्यात किए गए!", - "export_failed_toast": "नियम निर्यात करने में विफल: {message}", - "save_button": "सहेजें", - "expand_button_description": "विस्तृत करें" - }, - "friend_tracker_import": { - "title": "नियम आयात करें", - "back_button_description": "वापस", - "imported_toast": "मित्र ट्रैकर नियम आयात किए गए!", - "import_failed_toast": "नियम आयात करने में विफल: {message}", - "confirm_button": "पुष्टि करें", - "expand_button_description": "विस्तृत करें" - }, - "friend_tracker_repos": { - "invalid_repo_title": "अमान्य भंडार", - "add_repo_button": "भंडार जोड़ें", - "add_repo_dialog_title": "भंडार URL जोड़ें", - "repo_url_label": "भंडार URL", - "repo_added_toast": "भंडार सफलतापूर्वक जोड़ा गया!", - "invalid_repo_error": "यह एक मान्य मित्र ट्रैकर भंडार प्रतीत नहीं होता है।", - "add_repo_failed_toast": "भंडार जोड़ने में विफल: {message}", - "add_button": "जोड़ें", - "no_repos_added": "कोई भंडार नहीं जोड़ा गया", - "remove_button": "हटाएं", - "remove_repo_dialog_title": "भंडार हटाएं", - "remove_repo_dialog_text": "क्या आप वाकई इस भंडार को हटाना चाहते हैं?" - }, - "navigation": { - "tracker_tab_label": "ट्रैकर", - "customize_bottom_bar_title": "नीचे की पट्टी को अनुकूलित करें", - "customize_bottom_bar_subtitle": "टैब को फिर से व्यवस्थित करें, जोड़ें या हटाएं। अधिकतम पांच।", - "shown_tabs_title": "दिखाए गए टैब", - "no_tabs_selected_text": "कोई टैब चयनित नहीं है", - "available_tabs_title": "उपलब्ध टैब", - "reset_button": "रीसेट करें", - "done_button": "हो गया" - }, - "scripting": { - "script_already_installed": "स्क्रिप्ट पहले से ही स्थापित है!", - "downloading_script": "स्क्रिप्ट डाउनलोड हो रही है...", - "script_downloaded": "{name} स्क्रिप्ट डाउनलोड हो गई!", - "download_script_failed": "स्क्रिप्ट डाउनलोड करने में विफल। अधिक विवरण के लिए लॉग देखें", - "import_script_from_url_title": "URL से स्क्रिप्ट आयात करें", - "import_script_warning": "चेतावनी: आयातित स्क्रिप्ट आपके डिवाइस के लिए हानिकारक हो सकती हैं। केवल विश्वसनीय स्रोतों से स्क्रिप्ट आयात करें।", - "enter_url_label": "यहां URL दर्ज करें:", - "script_imported": "{name} स्क्रिप्ट आयात हो गई!", - "import_failed": "स्क्रिप्ट आयात करने में विफल। {message}. अधिक विवरण के लिए लॉग देखें", - "import_button": "आयात करें", - "update_module_button": "मॉड्यूल अपडेट करें", - "updating_script": "{name} स्क्रिप्ट अपडेट हो रही है...", - "module_not_found": "मॉड्यूल नहीं मिला", - "updated_script": "{name} को संस्करण {version} में अपडेट किया गया", - "update_module_failed": "मॉड्यूल अपडेट करने में विफल। अधिक विवरण के लिए लॉग देखें", - "edit_module_button": "मॉड्यूल संपादित करें", - "open_module_failed": "मॉड्यूल फ़ाइल खोलने में विफल। अधिक विवरण के लिए लॉग देखें", - "clear_module_data_button": "मॉड्यूल डेटा साफ़ करें", - "module_data_cleared": "मॉड्यूल डेटा साफ़ हो गया!", - "clear_module_data_failed": "मॉड्यूल डेटा साफ़ करने में विफल। अधिक विवरण के लिए लॉग देखें", - "delete_module_button": "मॉड्यूल हटाएं", - "deleted_script": "{name} स्क्रिप्ट हटाई गई!", - "delete_module_failed": "मॉड्यूल हटाने में विफल। अधिक विवरण के लिए लॉग देखें", - "actions_title": "क्रियाएँ", - "no_description": "कोई विवरण नहीं", - "update_available": "अपडेट उपलब्ध: {version}", - "actions_button": "क्रियाएँ", - "loaded_script": "{name} स्क्रिप्ट लोड हो गई", - "unloaded_script": "{name} स्क्रिप्ट अनलोड हो गई", - "enable_script_failed": "स्क्रिप्ट सक्षम करने में विफल। अधिक विवरण के लिए लॉग देखें", - "disable_script_failed": "स्क्रिप्ट अक्षम करने में विफल। अधिक विवरण के लिए लॉग देखें", - "select_scripts_folder_toast": "कृपया अपना स्क्रिप्ट फ़ोल्डर चुनें!", - "manage_repos_button": "भंडार प्रबंधित करें", - "import_from_url_button": "URL से आयात करें", - "open_scripts_folder_button": "स्क्रिप्ट फ़ोल्डर खोलें", - "no_settings_for_module": "इस मॉड्यूल में कोई सेटिंग नहीं है", - "installed_scripts_tab": "स्थापित स्क्रिप्ट", - "catalog_tab": "कैटलॉग", - "no_scripts_folder_selected_title": "कोई स्क्रिप्ट फ़ोल्डर चयनित नहीं है", - "select_folder_button": "फ़ोल्डर चुनें", - "no_scripts_found_title": "कोई स्क्रिप्ट नहीं मिली।", - "use_catalog_to_add_scripts": "स्क्रिप्ट जोड़ने के लिए कैटलॉग टैब का उपयोग करें!", - "ok_button_timeout": "ठीक है ({timeout})", - "documentation_button": "दस्तावेज़ीकरण", - "catalog": { - "script_already_installed": "स्क्रिप्ट पहले से ही स्थापित है!", - "download_failed": "डाउनलोड विफल: {code}", - "script_downloaded": "स्क्रिप्ट डाउनलोड हो गई!", - "could_not_create_file": "फ़ाइल नहीं बना सका।", - "no_scripts_folder_selected": "कोई स्क्रिप्ट फ़ोल्डर चयनित नहीं है।", - "error": "त्रुटि: {message}", - "no_repos_added": "कोई भंडार नहीं जोड़ा गया।", - "repo_list_info": "यहां आप भंडारों की एक सूची पा सकते हैं: ", - "link_text": "लिंक", - "no_scripts_available": "किसी भी भंडार से कोई स्क्रिप्ट उपलब्ध नहीं है।", - "by_author": "{author} द्वारा", - "version": "संस्करण: {version}", - "installed_button": "स्थापित", - "download_button": "डाउनલોડ કરો" - }, - "repos": { - "invalid_repo_title": "अमान्य भंडार", - "add_repo_button": "भंडार जोड़ें", - "add_repo_dialog_title": "भंडार URL जोड़ें", - "repo_url_label": "भंडार URL", - "repo_added_toast": "भंडार सफलतापूर्वक जोड़ा गया!", - "invalid_repo_error": "यह एक मान्य स्क्रिप्ट भंडार प्रतीत नहीं होता है।", - "add_repo_failed_toast": "भंडार जोड़ने में विफल: {message}", - "add_button": "जोड़ें", - "no_repos_added": "कोई भंडार नहीं जोड़ा गया", - "remove_button": "हटाएं", - "remove_repo_dialog_title": "भंडार हटाएं", - "remove_repo_dialog_text": "क्या आप वाकई इस भंडार को हटाना चाहते हैं?" - } - }, - "features": { - "config_import": { - "title": "आयात की पुष्टि करें", - "back_button_description": "वापस", - "config_imported_toast": "कॉन्फ़िगरेशन आयात किया गया!", - "confirm_button": "पुष्टि करें", - "expand_button_description": "विस्तृत करें", - "enable_feature": "सुविधा सक्षम करें", - "enabled": "सक्षम", - "disabled": "अक्षम" - }, - "config_export": { - "title": "निर्यात सारांश", - "back_button_description": "वापस", - "save_button": "सहेजें", - "expand_button_description": "विस्तृत करें", - "enable_feature": "सुविधा सक्षम करें", - "enabled": "सक्षम", - "disabled": "अक्षम" - } - }, - "manage_repos": { - "title": "{type} रिपॉजिटरी प्रबंधित करें", - "add_repo_button": "भंडार जोड़ें", - "add_repo_dialog_title": "भंडार URL जोड़ें", - "repo_url_label": "भंडार URL", - "repo_added_successfully": "भंडार सफलतापूर्वक जोड़ा गया!", - "add_repo_failed": "भंडार जोड़ने में विफल: {message}", - "add_button": "जोड़ें", - "no_repos_added": "कोई भंडार नहीं जोड़ा गया", - "remove_button": "हटाएं" } }, + "friend_menu_option": { + "preview": "पूर्वावलोकन", + "stealth_mode": "छिपे हुए मोड", + "auto_download_blacklist": "ऑटो डाउनलोड ब्लैकलिस्ट", + "anti_auto_save": "ऑटो सेव के खिलाफ" + }, + "chat_action_menu": { + "preview_button": "पूर्वावलोकन", + "download_button": "डाउनलोड करें", + "delete_logged_message_button": "लॉग किए गए संदेश को हटाएं" + }, + "opera_context_menu": { + "download": "मीडिया डाउनलोड करें" + }, + "modal_option": { + "profile_info": "प्रोफ़ाइल जानकारी", + "close": "बंद करें" + }, + "gallery_media_send_override": { + "multiple_media_toast": "एक बार में बस 1 मीडिया भेज सकते है" + }, + "conversation_preview": { + "streak_expiration": "{day} दिन {hour} घंटे {minute} मिनट में समाप्त होता है", + "total_messages": "कुल मिल के भेजे/मिले मेसेजेस: {count}", + "title": "पूर्वावलोकन", + "unknown_user": "अज्ञात उपयोगकर्ता" + }, + "profile_info": { + "title": "प्रोफ़ाइल जानकारी", + "display_name": "प्रदर्शित नाम", + "added_date": "जोड़ने की तारीख", + "birthday": "जन्मदिन: {month} {day}" + }, + "chat_export": { + "dialog_negative_button": "रद्द करें", + "dialog_positive_button": "निर्यात करें", + "exported_to": "{path} में निर्यात किया गया", + "exporting_chats": "बातचीत निर्यात कर रहा है...", + "processing_chats": "{amount} बातचीतों का प्रसंस्करण कर रहा है...", + "export_fail": "बातचीत {conversation} को निर्यात करने में विफल रहा", + "writing_output": "आउटपुट लिख रहा है...", + "finished": "तैयार हो गया! अब आप इस संवाद बॉक्स को बंद कर सकते हैं।", + "no_messages_found": "कोई संदेश नहीं मिले!", + "exporting_message": "{conversation} को निर्यात कर रहा है..." + }, + "button": { + "ok": "ठीक है", + "positive": "हाँ", + "negative": "नहीं", + "cancel": "रद्द करें", + "open": "खोलें" + }, + "download_processor": { + "download_started_toast": "डाउनलोड शुरू", + "unsupported_content_type_toast": "असमर्थित फ़ाइल प्रकार!", + "failed_no_longer_available_toast": "यह मीडिया अब उपलब्ध नहीं है", + "already_queued_toast": "मीडिया पहले से कतार में है!", + "already_downloaded_toast": "मीडिया पहले से डाउनलोड हो चुका है!", + "download_toast": "डोनलोडिंग टू {path}...", + "processing_toast": "प्रोसेसिंग {path}...", + "failed_generic_toast": "डाउनलोड करने में असफल", + "failed_to_create_preview_toast": "प्रीव्यू करने में असफल" + }, + "scopes": { + "friend": "दोस्त", + "group": "समुह" + }, "rules": { - "toasts": { - "enabled": "{ruleName} सक्षम", - "disabled": "{ruleName} अक्षम" - }, "modes": { - "blacklist": "ब्लैकलिस्ट मोड", - "whitelist": "व्हाइटलिस्ट मोड" + "blacklist": "इन्हे छोड़ कर", + "whitelist": "सिर्फ इन्हे" }, "properties": { "auto_download": { - "name": "ऑटो डाउनलोड", - "description": "स्नैप देखते समय उन्हें स्वचालित रूप से डाउनलोड करें", + "description": "देखते समय अपने आप डाउनलोड करे", + "name": "अपने आप डाउनलोड करे", "options": { - "blacklist": "ऑटो डाउनलोड से बाहर रखें", - "whitelist": "ऑटो डाउनलोड" + "blacklist": "अपने आप डाउनलोड होने से इन्हे हटाएँ", + "whitelist": "स्वतः डाउनलोड" } }, "stealth": { - "name": "स्टील्थ मोड", + "name": "चुपके मोड", "description": "किसी को भी यह जानने से रोकता है कि आपने उनके स्नैप/चैट और वार्तालाप खोले हैं", "options": { - "blacklist": "स्टील्थ मोड से बाहर रखें", - "whitelist": "स्टील्थ मोड" - } - }, - "auto_save": { - "name": "ऑटो सेव", - "description": "चैट संदेश देखते समय उन्हें सहेजता है", - "options": { - "blacklist": "ऑटो सेव से बाहर रखें", - "whitelist": "ऑटो सेव" + "blacklist": "चुपके मोड से बाहर रखें", + "whitelist": "चुपके मोड" } }, "unsaveable_messages": { - "name": "न सहेजने योग्य संदेश", - "description": "अन्य लोगों द्वारा चैट में संदेशों को सहेजे जाने से रोकता है", "options": { - "blacklist": "न सहेजने योग्य संदेशों से बाहर रखें", - "whitelist": "न सहेजने योग्य संदेश" - } + "whitelist": "सहेजे न जा सकने वाले संदेश", + "blacklist": "सहेजे न जा सकने वाले संदेशों को बाहर निकालें" + }, + "name": "सहेजे न जा सकने वाले संदेश", + "description": "संदेशों को अन्य लोगों द्वारा चैट में सहेजे जाने से रोकता है" }, - "auto_open_snaps": { - "name": "ऑटो ओपन स्नैप्स", - "description": "प्राप्त करते समय स्नैप स्वचालित रूप से खोलता है", + "auto_save": { + "name": "स्वतः सहेजें", "options": { - "blacklist": "ऑटो ओपन स्नैप्स से बाहर रखें", - "whitelist": "ऑटो ओपन स्नैप्स" - } - }, - "hide_friend_feed": { - "name": "मित्र फ़ीड से छिपाएँ" - }, - "e2e_encryption": { - "name": "E2E एन्क्रिप्शन का उपयोग करें" + "blacklist": "ऑटो सेव से बाहर निकालें", + "whitelist": "स्वतः सहेजें" + }, + "description": "चैट संदेशों को देखने पर उन्हें सहेजता है" }, "pin_conversation": { "name": "वार्तालाप पिन करें" }, - "exclude_message_logger": { - "name": "संदेश लकड़हारा से बाहर रखें" + "e2e_encryption": { + "name": "E2E एन्क्रिप्शन का उपयोग करें" + }, + "hide_friend_feed": { + "name": "मित्र फ़ीड से छिपाएँ" } + }, + "toasts": { + "enabled": "{नियम नाम} सक्षम किया गया", + "disabled": "{नियम का नाम} अक्षम किया गया" } }, "actions": { "clean_snapchat_cache": { - "name": "Snapchat कैश साफ़ करें", - "description": "Snapchat कैश साफ़ करता है" + "name": "स्नैपचैट कैश साफ़ करें", + "description": "स्नैपचैट कैश को साफ़ करता है" }, "manage_friend_list": { - "name": "मित्र सूची प्रबंधित करें", - "description": "बैकअप लेते समय अपनी मित्र सूची आयात/निर्यात करें" + "description": "बैकअप लेते समय अपनी मित्र सूची आयात/निर्यात करें", + "name": "मित्र सूची प्रबंधित करें" }, "export_chat_messages": { "name": "चैट संदेश निर्यात करें", @@ -620,1403 +282,133 @@ }, "export_memories": { "name": "यादें निर्यात करें", - "description": "यादों को ZIP फ़ाइल में निर्यात करता है" + "description": "स्मृतियों को एक ज़िप फ़ाइल में निर्यात करता है" }, "bulk_messaging_action": { "name": "थोक संदेश क्रिया", "description": "मित्रों को हटाने या वार्तालापों को बड़े पैमाने पर हटाने जैसे ऑपरेशन करता है" }, "regen_mappings": { - "name": "मैपिंग फिर से बनाएँ", - "description": "मैपिंग मैन्युअल रूप से फिर से बनाएँ" + "name": "मैपिंग पुन: उत्पन्न करें", + "description": "मैपिंग को मैन्युअल रूप से पुन: उत्पन्न करें" }, "change_language": { "name": "भाषा बदलें", - "description": "PurrfectSnap की भाषा बदलें" - }, - "file_imports": { - "name": "फ़ाइल आयात", - "description": "Snapchat में उपयोग के लिए फ़ाइलें आयात करें" - }, - "friend_tracker": { - "name": "मित्र ट्रैकर", - "description": "Snapchat पर अपने दोस्तों को ट्रैक करें" - }, - "logger_history": { - "name": "लॉगर इतिहास", - "description": "लॉग किए गए संदेशों का इतिहास देखें" + "description": "SnapEnhance की भाषा बदलें" } }, "features": { - "notices": { - "unstable": "⚠️ अस्थिर", - "ban_risk": "⚠️ यह सुविधा प्रतिबंध का कारण बन सकती है", - "internal_behavior": "⚠️ यह Snapchat के आंतरिक व्यवहार को तोड़ सकता है" - }, "properties": { "downloader": { - "name": "डाउनलोडर", - "description": "Snapchat मीडिया डाउनलोड करें", "properties": { - "save_folder": { - "name": "फ़ोल्डर सहेजें", - "description": "सभी मीडिया डाउनलोड करने के लिए निर्देशिका चुनें" + "opera_download_button": { + "name": "ओपेरा डाउनलोड बटन", + "description": "स्नैप देखते समय शीर्ष दाएं कोने पर एक डाउनलोड बटन जोड़ता है।\nबटनों को देर तक दबाने से डाउनलोड बाध्य हो जाएगा" + }, + "ffmpeg_options": { + "description": "अतिरिक्त FFmpeg विकल्प निर्दिष्ट करें", + "properties": { + "custom_video_codec": { + "description": "एक कस्टम वीडियो कोडेक सेट करें (उदा. libx264)", + "name": "कस्टम वीडियो कोडेक" + }, + "threads": { + "name": "धागे", + "description": "उपयोग किये जाने वाले धागों की मात्रा" + }, + "constant_rate_factor": { + "description": "वीडियो एन्कोडर के लिए स्थिर दर कारक सेट करें\nlibx264 के लिए 0 से 51 तक", + "name": "स्थिर दर कारक" + }, + "video_bitrate": { + "name": "वीडियो बिटरेट", + "description": "वीडियो बिटरेट (kbps) सेट करें" + }, + "preset": { + "name": "प्रीसेट", + "description": "रूपांतरण की गति निर्धारित करें" + }, + "custom_audio_codec": { + "name": "कस्टम ऑडियो कोडेक", + "description": "एक कस्टम ऑडियो कोडेक सेट करें (उदा. AAC)" + }, + "audio_bitrate": { + "name": "ऑडियो बिटरेट", + "description": "ऑडियो बिटरेट (kbps) सेट करें" + } + }, + "name": "एफएफएमपीईजी विकल्प" }, "auto_download_sources": { - "name": "ऑटो डाउनलोड स्रोत", - "description": "स्वचालित रूप से डाउनलोड करने के लिए स्रोत चुनें" + "description": "स्वचालित रूप से डाउनलोड करने के लिए स्रोतों का चयन करें", + "name": "ऑटो डाउनलोड स्रोत" }, - "prevent_self_auto_download": { - "name": "स्वयं ऑटो डाउनलोड रोकें", - "description": "आपके अपने स्नैप को स्वचालित रूप से डाउनलोड होने से रोकता है" + "save_folder": { + "name": "फ़ोल्डर सहेजें", + "description": "उस निर्देशिका का चयन करें जिसमें सभी मीडिया को डाउनलोड किया जाना चाहिए" }, "path_format": { "name": "पथ प्रारूप", "description": "फ़ाइल पथ प्रारूप निर्दिष्ट करें" }, "allow_duplicate": { - "name": "डुप्लिकेट की अनुमति दें", - "description": "एक ही मीडिया को कई बार डाउनलोड करने की अनुमति देता है" - }, - "merge_overlays": { - "name": "ओवरले मर्ज करें", - "description": "एक स्नैप के टेक्स्ट और मीडिया को एक ही फ़ाइल में जोड़ता है" + "description": "एक ही मीडिया को कई बार डाउनलोड करने की अनुमति देता है", + "name": "डुप्लिकेट की अनुमति दें" }, "force_image_format": { - "name": "छवि प्रारूप बल दें", + "name": "बलपूर्वक छवि प्रारूप", "description": "छवियों को एक निर्दिष्ट प्रारूप में सहेजने के लिए बाध्य करता है" }, "force_voice_note_format": { - "name": "वॉयस नोट प्रारूप बल दें", + "name": "वॉयस नोट प्रारूप को बाध्य करें", "description": "वॉयस नोट्स को एक निर्दिष्ट प्रारूप में सहेजने के लिए बाध्य करता है" }, - "auto_download_voice_notes": { - "name": "ऑटो डाउनलोड वॉयस नोट्स", - "description": "वॉयस नोट्स चलाते समय उन्हें स्वचालित रूप से डाउनलोड करता है" - }, "download_profile_pictures": { "name": "प्रोफ़ाइल चित्र डाउनलोड करें", "description": "आपको प्रोफ़ाइल पृष्ठ से प्रोफ़ाइल चित्र डाउनलोड करने की अनुमति देता है" }, - "opera_download_button": { - "name": "ओपेरा डाउनलोड बटन", - "description": "एक स्नैप देखते समय ऊपरी दाएं कोने में एक डाउनलोड बटन जोड़ता है।\nबटनों पर लंबे समय तक दबाने से डाउनलोड बाध्य होगा" - }, - "download_context_menu": { - "name": "डाउनलोड संदर्भ मेनू", - "description": "आपको संदर्भ मेनू का उपयोग करके किसी वार्तालाप या कहानी से संदेशों को डाउनलोड/पूर्वावलोकन करने की अनुमति देता है।\nबटनों पर लंबे समय तक दबाने से डाउनलोड बाध्य होगा" - }, - "ffmpeg_options": { - "name": "FFmpeg विकल्प", - "description": "अतिरिक्त FFmpeg विकल्प निर्दिष्ट करें", - "properties": { - "threads": { - "name": "थ्रेड्स", - "description": "उपयोग करने के लिए थ्रेड्स की संख्या" - }, - "preset": { - "name": "प्रीसेट", - "description": "रूपांतरण की गति सेट करें" - }, - "constant_rate_factor": { - "name": "स्थिर दर कारक", - "description": "वीडियो एनकोडर के लिए स्थिर दर कारक सेट करें\nlibx264 के लिए 0 से 51 तक" - }, - "video_bitrate": { - "name": "वीडियो बिटरेट", - "description": "वीडियो बिटरेट सेट करें (kbps)" - }, - "audio_bitrate": { - "name": "ऑडियो बिटरेट", - "description": "ऑडियो बिटरेट सेट करें (kbps)" - }, - "custom_video_codec": { - "name": "कस्टम वीडियो कोडेक", - "description": "एक कस्टम वीडियो कोडेक सेट करें (जैसे libx264)" - }, - "custom_audio_codec": { - "name": "कस्टम ऑडियो कोडेक", - "description": "एक कस्टम ऑडियो कोडेक सेट करें (जैसे AAC)" - } - } - }, "logging": { - "name": "लॉगिंग", - "description": "मीडिया डाउनलोड करते समय टोस्ट दिखाता है" + "description": "जब मीडिया डाउनलोड हो रहा हो तो टोस्ट दिखाता है", + "name": "लॉगिंग" }, "custom_path_format": { - "name": "कस्टम पथ प्रारूप", - "description": "डाउनलोड किए गए मीडिया के लिए एक कस्टम पथ प्रारूप निर्दिष्ट करें\n\nउपलब्ध चर:\n - %username%\n - %source%\n - %hash%\n - %date_time%" + "description": "डाउनलोड किए गए मीडिया के लिए एक कस्टम पथ प्रारूप निर्दिष्ट करें\n\nउपलब्ध चर:\n - %उपयोगकर्ता नाम%\n - %स्रोत%\n - %हैश%\n - %दिनांक समय%", + "name": "कस्टम पथ प्रारूप" + }, + "download_context_menu": { + "description": "आपको संदर्भ मेनू का उपयोग करके किसी वार्तालाप या कहानी से संदेशों को डाउनलोड/पूर्वावलोकन करने की अनुमति देता है।\nबटनों को देर तक दबाने से डाउनलोड बाध्य हो जाएगा", + "name": "संदर्भ मेनू डाउनलोड करें" + }, + "prevent_self_auto_download": { + "name": "सेल्फ ऑटो डाउनलोड को रोकें", + "description": "आपके स्वयं के स्नैप्स को स्वचालित रूप से डाउनलोड होने से रोकता है" + }, + "merge_overlays": { + "description": "स्नैप के टेक्स्ट और मीडिया को एक फ़ाइल में संयोजित करता है", + "name": "ओवरले मर्ज करें" } - } + }, + "description": "स्नैपचैट मीडिया डाउनलोड करें", + "name": "डाउनलोडर" }, "user_interface": { - "name": "यूजर इंटरफेस", - "description": "Snapchat का रंग-रूप बदलें", + "name": "प्रयोक्ता इंटरफ़ेस", "properties": { - "enable_app_appearance": { - "name": "ऐप उपस्थिति सेटिंग्स सक्षम करें", - "description": "छिपी हुई ऐप उपस्थिति सेटिंग को सक्षम करता है\nनए Snapchat संस्करणों पर आवश्यक नहीं हो सकता है" - }, - "friend_feed_message_preview": { - "name": "मित्र फ़ीड संदेश पूर्वावलोकन", - "description": "मित्र फ़ीड में अंतिम संदेशों का पूर्वावलोकन दिखाता है", - "properties": { - "amount": { - "name": "राशि", - "description": "पूर्वावलोकन किए जाने वाले संदेशों की राशि" - } - } - }, - "snap_preview": { - "name": "स्नैप पूर्वावलोकन", - "description": "चैट में न देखे गए स्नैप के बगल में एक छोटा पूर्वावलोकन प्रदर्शित करता है" - }, "bootstrap_override": { - "name": "बूटस्ट्रैप ओवरराइड", - "description": "यूजर इंटरफेस बूटस्ट्रैप सेटिंग्स को ओवरराइड करता है", "properties": { - "app_appearance": { - "name": "ऐप उपस्थिति", - "description": "एक स्थायी ऐप उपस्थिति सेट करता है" - }, "home_tab": { - "name": "होम टैब", - "description": "Snapchat खोलते समय स्टार्टअप टैब को ओवरराइड करता है" + "name": "होम टैब" } } - }, - "force_amoled_theme": { - "name": "एमोलेड डार्क मोड", - "description": "डार्क थीम के लिए एक सच्चे काले पृष्ठभूमि का उपयोग करता है" - }, - "map_friend_nametags": { - "name": "उन्नत मित्र मानचित्र नामटैग", - "description": "स्नैपमैप पर दोस्तों के नामटैग में सुधार करता है" - }, - "prevent_message_list_auto_scroll": { - "name": "संदेश सूची ऑटो स्क्रॉल रोकें", - "description": "संदेश भेजते/प्राप्त करते समय संदेश सूची को नीचे स्क्रॉल होने से रोकता है" - }, - "streak_expiration_info": { - "name": "स्ट्रीक समाप्ति जानकारी दिखाएं", - "description": "स्ट्रीक्स काउंटर के बगल में एक स्ट्रीक समाप्ति टाइमर दिखाता है" - }, - "hide_friend_feed_entry": { - "name": "मित्र फ़ीड प्रविष्टि छिपाएँ", - "description": "मित्र फ़ीड से एक विशिष्ट मित्र को छिपाता है\nइस सुविधा को प्रबंधित करने के लिए सामाजिक टैब का उपयोग करें" - }, - "hide_streak_restore": { - "name": "स्ट्रीक पुनर्स्थापना छिपाएँ", - "description": "मित्र फ़ीड में पुनर्स्थापना बटन छिपाता है" - }, - "hide_quick_add_suggestions": { - "name": "त्वरित जोड़ सुझाव छिपाएँ", - "description": "त्वरित जोड़ मित्र सुझावों को हटाता है" - }, - "hide_story_suggestions": { - "name": "कहानी सुझाव छिपाएँ", - "description": "कहानियों पृष्ठ से सुझावों को हटाता है" - }, - "hide_ui_components": { - "name": "UI घटक छिपाएँ", - "description": "कौन से UI घटकों को छिपाना है चुनें" - }, - "opera_media_quick_info": { - "name": "ओपेरा मीडिया त्वरित जानकारी", - "description": "ओपेरा व्यूअर संदर्भ मेनू में मीडिया की उपयोगी जानकारी जैसे निर्माण तिथि दिखाता है" - }, - "old_bitmoji_selfie": { - "name": "पुराना बिटमोजी सेल्फी", - "description": "पुराने Snapchat संस्करणों से बिटमोजी सेल्फी वापस लाता है" - }, - "disable_spotlight": { - "name": "स्पॉटलाइट अक्षम करें", - "description": "स्पॉटलाइट पृष्ठ को अक्षम करता है" - }, - "friend_feed_menu_buttons": { - "name": "मित्र फ़ीड मेनू बटन", - "description": "मित्र फ़ीड मेनू में कौन से बटन दिखाने हैं चुनें" - }, - "auto_close_friend_feed_menu": { - "name": "मित्र फ़ीड मेनू स्वतः बंद करें", - "description": "एक सेटिंग बटन दबाने के बाद मित्र फ़ीड मेनू को स्वचालित रूप से बंद कर देता है" - }, - "vertical_story_viewer": { - "name": "ऊर्ध्वाधर कहानी व्यूअर", - "description": "सभी कहानियों के लिए ऊर्ध्वाधर कहानी व्यूअर को सक्षम करता है" - }, - "enable_friend_feed_menu_bar": { - "name": "मित्र फ़ीड मेनू बार", - "description": "नए मित्र फ़ीड मेनू बार को सक्षम करता है" - }, - "message_indicators": { - "name": "संदेश संकेतक", - "description": "संदेशों में विशिष्ट संकेतक आइकन जोड़ता है\nनोट: संकेतक 100% सटीक नहीं हो सकते हैं" - }, - "stealth_mode_indicator": { - "name": "स्टील्थ मोड संकेतक", - "description": "स्टील्थ मोड में वार्तालापों के बगल में एक 👻 इमोजी जोड़ता है" - }, - "edit_text_override": { - "name": "टेक्स्ट संपादन ओवरराइड", - "description": "टेक्स्ट फ़ील्ड व्यवहार को ओवरराइड करता है" - }, - "prevent_forced_keyboard": { - "name": "जबरन कीबोर्ड रोकें", - "description": "जब आप कोई वार्तालाप खोलते हैं तो Snapchat को स्वचालित रूप से कीबोर्ड पॉप अप करने से रोकता है" - }, - "settings_menu": { - "name": "सेटिंग्स मेनू", - "description": "आप PurrfectSnap मेनू खोलने का तरीका बदलता है", - "options": { - "default": "डिफ़ॉल्ट", - "legacy": "विरासत" - } } - } - }, - "messaging": { - "name": "संदेश सेवा", - "description": "आप दोस्तों के साथ कैसे बातचीत करते हैं बदलें", - "properties": { - "bypass_screenshot_detection": { - "name": "स्क्रीनशॉट पहचान को बायपास करें", - "description": "जब आप स्क्रीनशॉट लेते हैं तो Snapchat को पहचानने से रोकता है" - }, - "anonymous_story_viewing": { - "name": "अनाम कहानी देखना", - "description": "किसी को भी यह जानने से रोकता है कि आपने उनकी कहानी देखी है" - }, - "prevent_story_rewatch_indicator": { - "name": "कहानी फिर से देखने का संकेतक रोकें", - "description": "किसी को भी यह जानने से रोकता है कि आपने उनकी कहानी फिर से देखी है" - }, - "hide_peek_a_peek": { - "name": "पीक-ए-पीक छिपाएँ", - "description": "जब आप किसी चैट में आधा स्वाइप करते हैं तो अधिसूचना भेजे जाने से रोकता है" - }, - "hide_bitmoji_presence": { - "name": "बिटमोजी उपस्थिति छिपाएँ", - "description": "चैट में रहते हुए आपके बिटमोजी को पॉप अप होने से रोकता है" - }, - "hide_typing_notifications": { - "name": "टाइपिंग सूचनाएं छिपाएँ", - "description": "किसी को भी यह जानने से रोकता है कि आप एक संदेश टाइप कर रहे हैं" - }, - "unlimited_snap_view_time": { - "name": "असीमित स्नैप देखने का समय", - "description": "स्नैप देखने के लिए समय सीमा हटाता है" - }, - "auto_mark_as_read": { - "name": "स्वचालित रूप से पढ़े गए के रूप में चिह्नित करें", - "description": "स्टील्थ मोड सक्षम होने पर भी संदेशों/स्नैप को स्वचालित रूप से पढ़े गए के रूप में चिह्नित करता है" - }, - "mark_snap_as_seen_button": { - "name": "स्नैप को देखे गए के रूप में चिह्नित करें बटन", - "description": "एक स्नैप देखते समय उसे देखे गए के रूप में चिह्नित करने के लिए एक बटन जोड़ता है।\nयह स्टील्थ मोड सक्षम होने पर भी काम करेगा" - }, - "skip_when_marking_as_seen": { - "name": "देखे गए के रूप में चिह्नित करते समय छोड़ें", - "description": "एक स्नैप को देखे गए के रूप में चिह्नित करते समय स्वचालित रूप से अगले स्नैप पर छोड़ देता है।\nस्नैप को देखे गए के रूप में चिह्नित करें बटन के साथ संयोजन में उपयोग करें" - }, - "loop_media_playback": { - "name": "लूप मीडिया प्लेबैक", - "description": "स्नैप/कहानियों को देखते समय मीडिया प्लेबैक को लूप करता है" - }, - "disable_replay_in_ff": { - "name": "FF में रीप्ले अक्षम करें", - "description": "मित्र फ़ीड से लंबे समय तक दबाकर रीप्ले करने की क्षमता को अक्षम करता है" - }, - "half_swipe_notifier": { - "name": "आधा स्वाइप सूचक", - "description": "जब कोई किसी वार्तालाप में आधा स्वाइप करता है तो आपको सूचित करता है", - "properties": { - "min_duration": { - "name": "न्यूनतम अवधि", - "description": "आधे स्वाइप की न्यूनतम अवधि (सेकंड में)" - }, - "max_duration": { - "name": "अधिकतम अवधि", - "description": "आधे स्वाइप की अधिकतम अवधि (सेकंड में)" - } - } - }, - "call_start_confirmation": { - "name": "कॉल प्रारंभ पुष्टि", - "description": "कॉल शुरू करते समय एक पुष्टि संवाद दिखाता है" - }, - "unlimited_conversation_pinning": { - "name": "असीमित वार्तालाप पिनिंग", - "description": "आपको स्थानीय रूप से असीमित संख्या में वार्तालापों को पिन करने की अनुमति देता है" - }, - "disable_snap_mode_restrictions": { - "name": "स्नैप मोड प्रतिबंध अक्षम करें", - "description": "आपको प्रतिबंधों के बिना स्व-विनाशकारी स्नैप देखने की अनुमति देता है" - }, - "prevent_message_sending": { - "name": "संदेश भेजना रोकें", - "description": "कुछ प्रकार के संदेशों को भेजने से रोकता है" - }, - "friend_mutation_notifier": { - "name": "मित्र उत्परिवर्तन सूचक", - "description": "जब किसी मित्र के प्रोफ़ाइल में कुछ बदलता है तो आपको सूचित करता है" - }, - "better_notifications": { - "name": "बेहतर सूचनाएं", - "description": "प्राप्त सूचनाओं में अधिक जानकारी जोड़ता है", - "properties": { - "group_notifications": { - "name": "समूह सूचनाएं", - "description": "समूह सूचनाओं को एक में समूहित करें" - }, - "chat_preview": { - "name": "चैट पूर्वावलोकन", - "description": "अधिसूचना में प्राप्त संदेशों का पूर्वावलोकन दिखाता है" - }, - "media_preview": { - "name": "मीडिया पूर्वावलोकन", - "description": "अधिसूचना में चयनित मीडिया प्रकारों का पूर्वावलोकन दिखाता है" - }, - "media_caption": { - "name": "मीडिया कैप्शन", - "description": "अधिसूचना में मीडिया के संलग्न कैप्शन को दिखाता है" - }, - "stacked_media_messages": { - "name": "स्टैक्ड मीडिया संदेश", - "description": "जब वे पूर्वावलोकन नहीं किए जा सकते हैं तो कई मीडिया संदेशों को एक टेक्स्ट अधिसूचना में जोड़ता है। चैट पूर्वावलोकन के साथ संयोजन में उपयोग करें" - }, - "friend_add_source": { - "name": "मित्र जोड़ें स्रोत", - "description": "अधिसूचना में एक मित्र अनुरोध का स्रोत दिखाता है" - }, - "reply_button": { - "name": "उत्तर बटन", - "description": "अधिसूचना में एक उत्तर बटन जोड़ता है" - }, - "smart_replies": { - "name": "स्मार्ट उत्तर", - "description": "सूचनाओं में सुझाए गए उत्तर जोड़ता है (Android 10+)। उत्तर बटन के साथ संयोजन में उपयोग करें" - }, - "download_button": { - "name": "डाउनलोड बटन", - "description": "आपको अधिसूचना से मीडिया डाउनलोड करने की अनुमति देता है" - }, - "mark_as_read_button": { - "name": "पढ़े गए के रूप में चिह्नित करें बटन", - "description": "आपको अधिसूचना से किसी संदेश को पढ़े गए के रूप में चिह्नित करने की अनुमति देता है" - }, - "mark_as_read_and_save_in_chat": { - "name": "पढ़े गए के रूप में चिह्नित करें और चैट में सहेजें", - "description": "अधिसूचना में पढ़े गए के रूप में चिह्नित करें और चैट में सहेजें बटन जोड़ता है" - } - } - }, - "notification_blacklist": { - "name": "अधिसूचना ब्लैकलिस्ट", - "description": "कौन सी सूचनाएं अवरुद्ध होनी चाहिए चुनें" - }, - "message_logger": { - "name": "संदेश लकड़हारा", - "description": "संदेशों को हटाए जाने से रोकता है", - "properties": { - "keep_my_own_messages": { - "name": "मेरे अपने संदेश रखें", - "description": "आपके अपने संदेशों को हटाए जाने से रोकता है" - }, - "auto_purge": { - "name": "ऑटो पर्ज", - "description": "निर्दिष्ट समय से पुराने कैश्ड संदेशों को स्वचालित रूप से हटा देता है" - }, - "message_filter": { - "name": "संदेश फ़िल्टर", - "description": "कौन से संदेश लॉग किए जाने चाहिए चुनें (सभी संदेशों के लिए खाली)" - }, - "deleted_message_color": { - "name": "हटाए गए संदेश का रंग", - "description": "हटाए गए संदेशों का रंग सेट करता है" - } - } - }, - "auto_save_messages_in_conversations": { - "name": "वार्तालापों में संदेशों को स्वतः सहेजें", - "description": "वार्तालापों में प्रत्येक संदेश को स्वचालित रूप से सहेजता है" - }, - "gallery_media_send_override": { - "name": "गैलरी मीडिया भेजें ओवरराइड", - "description": "गैलरी से भेजते समय मीडिया स्रोत को स्पूफ करता है" - }, - "strip_media_metadata": { - "name": "मीडिया मेटाडेटा स्ट्रिप करें", - "description": "एक संदेश के रूप में भेजने से पहले मीडिया के मेटाडेटा को हटा देता है" - }, - "bypass_message_retention_policy": { - "name": "संदेश प्रतिधारण नीति को बायपास करें", - "description": "संदेशों को देखने के बाद उन्हें हटाए जाने से रोकता है" - }, - "bypass_message_action_restrictions": { - "name": "संदेश कार्रवाई प्रतिबंधों को बायपास करें", - "description": "आपको इसे खोले बिना किसी स्नैप पर प्रतिक्रिया करने या एक न सहेजने योग्य संदेश को सहेजने की अनुमति देता है" - }, - "remove_groups_locked_status": { - "name": "समूहों की लॉक की गई स्थिति हटाएं", - "description": "आपको बाहर निकाले जाने के बाद समूह जानकारी देखने की अनुमति देता है" - }, - "double_tap_chat_action": { - "name": "डबल टैप चैट क्रिया", - "description": "चैट में किसी संदेश पर डबल टैप करते समय एक कस्टम क्रिया करता है" - }, - "double_tap_chat_action_custom_emoji": { - "name": "डबल टैप चैट क्रिया कस्टम इमोजी प्रतिक्रिया", - "description": "डबल टैप चैट क्रिया के लिए एक कस्टम इमोजी प्रतिक्रिया सेट करता है" - } - } - }, - "global": { - "name": "वैश्विक", - "description": "वैश्विक Snapchat सेटिंग्स को ट्वीक करें", - "properties": { - "better_location": { - "name": "बेहतर स्थान", - "description": "Snapchat स्थान को बढ़ाता है", - "properties": { - "spoof_location": { - "name": "स्थान स्पूफ करें", - "description": "आपके स्थान को एक निर्दिष्ट स्थान पर स्पूफ करता है" - }, - "coordinates": { - "name": "निर्देशांक", - "description": "स्पूफ किए गए स्थान के निर्देशांक सेट करें" - }, - "walk_radius": { - "name": "चलने की त्रिज्या", - "description": "इस त्रिज्या के भीतर बेतरतीब ढंग से चलें (फीट)" - }, - "always_update_location": { - "name": "हमेशा स्थान अपडेट करें", - "description": "कोई GPS डेटा प्राप्त न होने पर भी Snapchat को स्थान अपडेट करने के लिए बाध्य करें" - }, - "suspend_location_updates": { - "name": "स्थान अपडेट निलंबित करें", - "description": "आपके स्थान को अपडेट होने से रोकता है" - }, - "spoof_battery_level": { - "name": "बैटरी स्तर स्पूफ करें", - "description": "नक्शे पर आपके डिवाइस के बैटरी स्तर को स्पूफ करता है\nमान 0 और 100 के बीच होना चाहिए" - }, - "spoof_headphones": { - "name": "हेडफोन स्पूफ करें", - "description": "नक्शे पर संगीत सुनने की स्थिति को स्पूफ करता है" - }, - "show_battery_level": { - "name": "बैटरी स्तर दिखाएं", - "description": "नक्शे पर आपके दोस्तों के बैटरी स्तर को दिखाता है" - } - } - }, - "snapchat_plus": { - "name": "स्नैपचैट प्लस", - "description": "Snapchat Plus सुविधाओं को सक्षम करता है\nकुछ सर्वर-साइड सुविधाएँ काम नहीं कर सकती हैं" - }, - "media_upload_quality": { - "name": "मीडिया अपलोड गुणवत्ता", - "description": "मीडिया अपलोड गुणवत्ता को ओवरराइड करता है", - "properties": { - "force_video_upload_source_quality": { - "name": "वीडियो अपलोड स्रोत गुणवत्ता बल दें", - "description": "वीडियो अपलोड करते समय स्रोत गुणवत्ता का उपयोग करने के लिए Snapchat को बाध्य करता है\nकृपया ध्यान दें कि यह मीडिया से मेटाडेटा को नहीं हटा सकता है" - }, - "disable_image_compression": { - "name": "छवि संपीड़न अक्षम करें", - "description": "मीडिया अपलोड करते समय छवि संपीड़न को अक्षम करता है" - }, - "custom_image_upload_format": { - "name": "कस्टम छवि अपलोड प्रारूप", - "description": "एक कस्टम छवि अपलोड प्रारूप सेट करता है\nसर्वोत्तम गुणवत्ता के लिए एक दोषरहित प्रारूप (जैसे PNG) चुनें" - } - } - }, - "disable_confirmation_dialogs": { - "name": "पुष्टि संवाद अक्षम करें", - "description": "चयनित क्रियाओं की स्वचालित रूप से पुष्टि करता है" - }, - "auto_updater": { - "name": "ऑटो अपडेटर", - "description": "नए अपडेट के लिए स्वचालित रूप से जाँच करता है" - }, - "disable_metrics": { - "name": "मेट्रिक्स अक्षम करें", - "description": "Snapchat को विशिष्ट विश्लेषणात्मक डेटा भेजने से रोकता है" - }, - "disable_story_sections": { - "name": "कहानी अनुभाग अक्षम करें", - "description": "कहानियों पृष्ठ से अनुभागों को हटाता है\nठीक से काम करने के लिए एक ताज़ा करने की आवश्यकता हो सकती है" - }, - "block_ads": { - "name": "विज्ञापन अवरुद्ध करें", - "description": "विज्ञापनों को प्रदर्शित होने से रोकता है" - }, - "disable_custom_tabs": { - "name": "कस्टम टैब अक्षम करें", - "description": "वेब ब्राउज़र के बजाय समर्थित अनुप्रयोगों में लिंक खोलता है" - }, - "disable_permission_requests": { - "name": "अनुमति अनुरोध अक्षम करें", - "description": "Snapchat को विशिष्ट अनुमतियों के लिए पूछने से रोकता है" - }, - "disable_memories_snap_feed": { - "name": "यादें स्नैप फ़ीड अक्षम करें", - "description": "जब आप कैमरे में ऊपर स्वाइप करते हैं तो Snapchat को हाल की यादें दिखाने से रोकता है" - }, - "spotlight_comments_username": { - "name": "स्पॉटलाइट टिप्पणियाँ उपयोगकर्ता नाम", - "description": "स्पॉटलाइट टिप्पणियों में लेखक का उपयोगकर्ता नाम दिखाता है" - }, - "bypass_video_length_restriction": { - "name": "वीडियो लंबाई प्रतिबंध को बायपास करें", - "description": "एकल: एक ही वीडियो भेजता है\nविभाजित: संपादन के बाद वीडियो विभाजित करें" - }, - "default_video_playback_rate": { - "name": "डिफ़ॉल्ट वीडियो प्लेबैक दर", - "description": "वीडियो के प्लेबैक के लिए डिफ़ॉल्ट गति सेट करता है\nमान 0.1 और 4.0 के बीच होना चाहिए" - }, - "video_playback_rate_slider": { - "name": "वीडियो प्लेबैक दर स्लाइडर", - "description": "वीडियो प्लेबैक दर बदलने के लिए ओपेरा संदर्भ मेनू में एक स्लाइडर जोड़ता है\nनोट: परिवर्तन केवल बाद के वीडियो पर लागू होते हैं" - }, - "disable_google_play_dialogs": { - "name": "Google Play सेवाएं संवाद अक्षम करें", - "description": "Google Play सेवाएं उपलब्धता संवादों को दिखाए जाने से रोकें" - }, - "default_volume_controls": { - "name": "डिफ़ॉल्ट वॉल्यूम नियंत्रण", - "description": "Snapchat को सिस्टम वॉल्यूम नियंत्रणों का उपयोग करने के लिए बाध्य करता है" - }, - "disable_telecom_framework": { - "name": "टेलीकॉम फ्रेमवर्क अक्षम करें", - "description": "Snapchat को Android टेलीकॉम फ्रेमवर्क का उपयोग करने से रोकता है\nयह आपको कॉल पर रहते हुए संगीत सुनने की अनुमति देता है" - }, - "hide_active_music": { - "name": "सक्रिय संगीत छिपाएँ", - "description": "Snapchat को यह जानने से रोकता है कि आप संगीत सुन रहे हैं\nयह आपको संगीत सुनते समय नियंत्रण वॉल्यूम बटनों का उपयोग करके स्नैप लेने की अनुमति देगा" - }, - "disable_snap_splitting": { - "name": "स्नैप विभाजन अक्षम करें", - "description": "स्नैप को कई भागों में विभाजित होने से रोकता है\nआपके द्वारा भेजे गए चित्र वीडियो में बदल जाएंगे" - } - } - }, - "rules": { - "name": "नियम", - "description": "व्यक्तिगत लोगों के लिए स्वचालित सुविधाओं का प्रबंधन करें" - }, - "camera": { - "name": "कैमरा", - "description": "सही स्नैप के लिए सही सेटिंग्स समायोजित करें", - "properties": { - "disable_cameras": { - "name": "कैमरे अक्षम करें", - "description": "Snapchat को चयनित कैमरों का उपयोग करने से रोकता है" - }, - "black_photos": { - "name": "काले फोटो", - "description": "कैप्चर किए गए फोटो को एक काले पृष्ठभूमि से बदल देता है\nवीडियो प्रभावित नहीं होते हैं" - }, - "immersive_camera_preview": { - "name": "इमर्सिव पूर्वावलोकन", - "description": "Snapchat को कैमरा पूर्वावलोकन को क्रॉप करने से रोकता है\nयह कुछ उपकरणों पर कैमरे को झिलमिलाहट का कारण बन सकता है" - }, - "override_front_resolution": { - "name": "फ्रंट रिज़ॉल्यूशन ओवरराइड करें", - "description": "फ्रंट कैमरे के लिए कैमरा रिज़ॉल्यूशन को ओवरराइड करता है" - }, - "override_back_resolution": { - "name": "बैक रिज़ॉल्यूशन ओवरराइड करें", - "description": "बैक कैमरे के लिए कैमरा रिज़ॉल्यूशन को ओवरराइड करता है" - }, - "custom_resolution": { - "name": "कस्टम रिज़ॉल्यूशन", - "description": "एक कस्टम कैमरा रिज़ॉल्यूशन सेट करता है, चौड़ाई x ऊँचाई (जैसे 1920x1080)।\nकस्टम रिज़ॉल्यूशन आपके डिवाइस द्वारा समर्थित होना चाहिए" - }, - "front_custom_frame_rate": { - "name": "फ्रंट कस्टम फ्रेम दर", - "description": "फ्रंट कैमरा फ्रेम दर को ओवरराइड करता है" - }, - "back_custom_frame_rate": { - "name": "बैक कस्टम फ्रेम दर", - "description": "बैक कैमरा फ्रेम दर को ओवरराइड करता है" - }, - "force_camera_source_encoding": { - "name": "कैमरा स्रोत एन्कोडिंग बल दें", - "description": "कैमरा स्रोत एन्कोडिंग को बाध्य करता है" - }, - "startup_default_camera": { - "name": "स्टार्टअप डिफ़ॉल्ट कैमरा", - "description": "Snapchat खोलते समय डिफ़ॉल्ट कैमरा सेट करता है" - }, - "hevc_recording": { - "name": "HEVC रिकॉर्डिंग", - "description": "वीडियो रिकॉर्डिंग के लिए HEVC (H.265) कोडेक का उपयोग करता है" - } - } - }, - "streaks_reminder": { - "name": "स्ट्रीक्स अनुस्मारक", - "description": "समय-समय पर आपको अपनी स्ट्रीक्स के बारे में सूचित करता है", - "properties": { - "interval": { - "name": "अंतराल", - "description": "प्रत्येक अनुस्मारक के बीच का अंतराल (घंटे)" - }, - "remaining_hours": { - "name": "शेष समय", - "description": "अधिसूचना दिखाए जाने से पहले शेष समय की मात्रा (घंटे)" - }, - "group_notifications": { - "name": "समूह सूचनाएं", - "description": "समूह सूचनाओं को एक में समूहित करें" - } - } - }, - "experimental": { - "name": "प्रायोगिक", - "description": "प्रायोगिक सुविधाएँ", - "properties": { - "native_hooks": { - "name": "मूल हुक", - "description": "असुरक्षित सुविधाएँ जो Snapchat के मूल कोड में हुक करती हैं", - "properties": { - "composer_hooks": { - "name": "संगीतकार हुक", - "description": "संगीतकार क्रॉस-प्लेटफ़ॉर्म UI फ्रेमवर्क में कोड इंजेक्ट करता है", - "properties": { - "show_first_created_username": { - "name": "पहला बनाया गया उपयोगकर्ता नाम दिखाएं", - "description": "प्रोफ़ाइल पृष्ठ पर वर्तमान उपयोगकर्ता नाम के बगल में पहला बनाया गया उपयोगकर्ता नाम दिखाता है" - }, - "bypass_camera_roll_limit": { - "name": "कैमरा रोल सीमा को बायपास करें", - "description": "आप कैमरा रोल से भेज सकते हैं मीडिया की अधिकतम मात्रा बढ़ाता है" - }, - "custom_self_destruct_snap_delay": { - "name": "कस्टम स्व-विनाश स्नैप विलंब", - "description": "एक स्नैप भेजते समय स्व-विनाश टाइमर के लिए अधिक विकल्प देता है" - }, - "composer_console": { - "name": "संगीतकार कंसोल", - "description": "आपको संगीतकार में जावास्क्रिप्ट कोड निष्पादित करने की अनुमति देता है (केवल arm64)" - }, - "composer_logs": { - "name": "संगीतकार लॉग", - "description": "संगीतकार के कंसोल लॉग को PurrfectSnap पर पुनर्निर्देशित करता है" - } - } - }, - "disable_bitmoji": { - "name": "बिटमोजी अक्षम करें", - "description": "मित्र प्रोफ़ाइल बिटमोजी को अक्षम करता है" - }, - "custom_emoji_font": { - "name": "कस्टम इमोजी फ़ॉन्ट", - "description": "आपको एक कस्टम इमोजी फ़ॉन्ट का उपयोग करने की अनुमति देता है। केवल .ttf फ़ॉन्ट के साथ काम करता है" - }, - "custom_shared_library": { - "name": "कस्टम साझा पुस्तकालय", - "description": "Snapchat में एक कस्टम साझा पुस्तकालय लोड करता है। यह सुविधा केवल परीक्षण उद्देश्यों के लिए है" - } - } - }, - "spoof": { - "name": "स्पूफ", - "description": "आपके बारे में विभिन्न जानकारी को स्पूफ करें", - "properties": { - "play_store_installer_package_name": { - "name": "प्ले स्टोर इंस्टॉलर पैकेज नाम", - "description": "इंस्टॉलर पैकेज नाम को com.android.vending पर ओवरराइड करता है" - }, - "remove_vpn_transport_flag": { - "name": "वीपीएन परिवहन ध्वज हटाएं", - "description": "Snapchat को वीपीएन का पता लगाने से रोकता है" - }, - "remove_mock_location_flag": { - "name": "मॉक स्थान ध्वज हटाएं", - "description": "Snapchat को मॉक स्थान का पता लगाने से रोकता है" - } - } - }, - "convert_message_locally": { - "name": "संदेश को स्थानीय रूप से रूपांतरित करें", - "description": "स्नैप को स्थानीय रूप से चैट बाहरी मीडिया में रूपांतरित करता है। यह चैट डाउनलोड संदर्भ मेनू में दिखाई देता है" - }, - "media_file_picker": { - "name": "मीडिया फ़ाइल पिकर", - "description": "आपको गैलरी से कोई भी वीडियो/ऑडियो फ़ाइल चुनने की अनुमति देता है" - }, - "story_logger": { - "name": "कहानी लकड़हारा", - "description": "दोस्तों की कहानियों का इतिहास प्रदान करता है" - }, - "call_recorder": { - "name": "कॉल रिकॉर्डर", - "description": "ऑडियो कॉल स्वचालित रूप से रिकॉर्ड करता है" - }, - "account_switcher": { - "name": "खाता स्विचर", - "description": "आपको लॉग आउट किए बिना खातों के बीच स्विच करने की अनुमति देता है\nमेनू खोलने के लिए अपने बिटमोजी प्रोफ़ाइल के बगल में खोज आइकन पर लंबे समय तक दबाएं\nनोट: यह सुविधा प्रायोगिक है और भविष्य में बदलने की संभावना है", - "properties": { - "auto_backup_current_account": { - "name": "वर्तमान खाते का ऑटो बैकअप", - "description": "लॉग आउट करते समय या खातों को स्विच करते समय वर्तमान खाते का स्वचालित रूप से बैकअप लेता है" - } - } - }, - "better_transcript": { - "name": "बेहतर प्रतिलेख", - "description": "वॉयस नोट प्रतिलेख में सुधार करता है", - "properties": { - "force_transcription": { - "name": "वॉयस नोट ट्रांसक्रिप्शन बल दें", - "description": "सभी वॉयस नोट्स को ट्रांसक्राइब करने की अनुमति देता है" - }, - "preferred_transcription_lang": { - "name": "पसंदीदा ट्रांसक्रिप्शन भाषा", - "description": "वॉयस नोट प्रतिलेख के लिए पसंदीदा भाषा (जैसे EN, ES, FR)" - }, - "notification_transcript": { - "name": "अधिसूचना प्रतिलेख", - "description": "सूचनाओं में वॉयस नोट्स को ट्रांसक्राइब करता है\nइस सुविधा के लिए बेहतर सूचनाओं में चैट पूर्वावलोकन सुविधा को सक्षम करने की आवश्यकता है" - } - } - }, - "voice_note_auto_play": { - "name": "वॉयस नोट ऑटो प्ले", - "description": "वर्तमान वॉयस नोट समाप्त होने के बाद अगला वॉयस नोट स्वचालित रूप से चलाता है" - }, - "friend_notes": { - "name": "मित्र नोट्स", - "description": "आपको दोस्तों के प्रोफ़ाइल में नोट्स जोड़ने की अनुमति देता है" - }, - "cof_experiments": { - "name": "सीओएफ प्रयोग", - "description": "अप्रकाशित/बीटा Snapchat सुविधाओं को सक्षम करता है" - }, - "context_menu_fix": { - "name": "संदर्भ मेनू फिक्स", - "description": "मित्र फ़ीड मेनू की मरम्मत करने का प्रयास करें क्योंकि जब डिवाइस ऑफ़लाइन होता है तो इसे सही ढंग से प्रदर्शित नहीं किया जा सकता है" - }, - "app_lock": { - "name": "ऐप लॉक", - "description": "पासकोड के बिना Snapchat तक पहुंच को रोकता है", - "properties": { - "lock_on_resume": { - "name": "फिर से शुरू करने पर लॉक करें", - "description": "जब ऐप फिर से खोला जाता है तो उसे लॉक कर देता है" - } - } - }, - "infinite_story_boost": { - "name": "अनंत कहानी बूस्ट", - "description": "कहानी बूस्ट सीमा विलंब को बायपास करें" - }, - "meo_passcode_bypass": { - "name": "माई आइज़ ओनली पासकोड बायपास", - "description": "माई आइज़ ओनली पासकोड को बायपास करें\nयह केवल तभी काम करेगा जब पासकोड पहले सही ढंग से दर्ज किया गया हो" - }, - "no_friend_score_delay": { - "name": "कोई मित्र स्कोर विलंब नहीं", - "description": "एक मित्र स्कोर देखते समय विलंब को हटाता है" - }, - "best_friend_pinning": { - "name": "सबसे अच्छा दोस्त पिनिंग", - "description": "आपको अपने नंबर एक सबसे अच्छे दोस्त के रूप में एक दोस्त को पिन करने की अनुमति देता है। नोट: केवल आप ही अपने पिन किए गए सबसे अच्छे दोस्त को देख सकते हैं" - }, - "e2ee": { - "name": "एंड-टू-एंड एन्क्रिप्शन", - "description": "आपके संदेशों को एक साझा गुप्त कुंजी का उपयोग करके एईएस के साथ एन्क्रिप्ट करता है\nअपनी कुंजी को कहीं सुरक्षित सहेजना सुनिश्चित करें!", - "properties": { - "encrypted_message_indicator": { - "name": "एन्क्रिप्टेड संदेश संकेतक", - "description": "एन्क्रिप्टेड संदेशों के बगल में एक 🔒 इमोजी जोड़ता है" - }, - "force_message_encryption": { - "name": "संदेश एन्क्रिप्शन बल दें", - "description": "केवल जब कई वार्तालाप चुने जाते हैं तो E2E एन्क्रिप्शन सक्षम नहीं करने वाले लोगों को एन्क्रिप्टेड संदेश भेजने से रोकता है" - } - } - }, - "add_friend_source_spoof": { - "name": "मित्र स्रोत स्पूफ जोड़ें", - "description": "एक मित्र अनुरोध के स्रोत को स्पूफ करता है" - }, - "hidden_snapchat_plus_features": { - "name": "छिपी हुई Snapchat प्लस सुविधाएँ", - "description": "अप्रकाशित/बीटा Snapchat प्लस सुविधाओं को सक्षम करता है\nपुराने Snapchat संस्करणों पर काम नहीं कर सकता है" - }, - "custom_streaks_expiration_format": { - "name": "कस्टम स्ट्रीक्स समाप्ति प्रारूप", - "description": "स्ट्रीक्स समाप्ति प्रारूप को अनुकूलित करता है\n\nउपलब्ध चर:\n - %c: स्ट्रीक्स गणना\n - %e: घंटाघर इमोजी\n - %d: दिन\n - %h: घंटे\n - %m: मिनट\n - %s: सेकंड\n - %w: शेष समय" - }, - "prevent_forced_logout": { - "name": "जबरन लॉगआउट रोकें", - "description": "जब आप किसी अन्य डिवाइस पर लॉग इन करते हैं तो Snapchat को आपको लॉग आउट करने से रोकता है" - }, - "snapscore_changes": { - "name": "स्नैपस्कोर परिवर्तन", - "description": "दोस्तों के स्नैपस्कोर में बदलावों को ट्रैक करता है\nइस सुविधा का उपयोग केवल Snapchat के नए संस्करणों में करें" - } - } - }, - "scripting": { - "name": "स्क्रिप्टिंग", - "description": "PurrfectSnap का विस्तार करने के लिए कस्टम स्क्रिप्ट चलाएँ", - "properties": { - "developer_mode": { - "name": "डेवलपर मोड", - "description": "Snapchat के UI पर डिबग जानकारी दिखाता है" - }, - "module_folder": { - "name": "मॉड्यूल फ़ोल्डर", - "description": "वह फ़ोल्डर जहाँ स्क्रिप्ट स्थित हैं" - }, - "auto_reload": { - "name": "ऑटो रीलोड", - "description": "जब वे बदलते हैं तो स्क्रिप्ट को स्वचालित रूप से रीलोड करता है" - }, - "integrated_ui": { - "name": "एकीकृत यूआई", - "description": "स्क्रिप्ट को Snapchat में कस्टम UI घटक जोड़ने की अनुमति देता है" - }, - "disable_log_anonymization": { - "name": "लॉग अनामकरण अक्षम करें", - "description": "लॉग के अनामकरण को अक्षम करता है" - }, - "disable_optimization": { - "name": "अनुकूलन अक्षम करें", - "description": "स्क्रिप्ट के अनुकूलन को अक्षम करता है। यह प्रदर्शन समस्याओं का कारण बन सकता है।" - } - } - }, - "friend_tracker": { - "name": "मित्र ट्रैकर", - "description": "Snapchat पर मित्र की गतिविधि रिकॉर्ड करता है", - "properties": { - "record_messaging_events": { - "name": "संदेश सेवा ईवेंट रिकॉर्ड करें", - "description": "संदेश सेवा ईवेंट जैसे स्नैप खोलना, संदेश पढ़ना आदि रिकॉर्ड करता है।" - }, - "allow_running_in_background": { - "name": "पृष्ठभूमि में चलने की अनुमति दें", - "description": "ट्रैकर को पृष्ठभूमि में चलने की अनुमति देता है। नोट: यह आपकी बैटरी को काफी हद तक खत्म कर देगा" - }, - "auto_purge": { - "name": "ऑटो पर्ज", - "description": "निर्दिष्ट समय से पुराने कैश्ड ईवेंट को स्वचालित रूप से हटा देता है" - } - } + }, + "description": "स्नैपचैट का स्वरूप और अनुभव बदलें" } }, - "options": { - "app_appearance": { - "always_light": "हमेशा प्रकाश", - "always_dark": "हमेशा अंधेरा" - }, - "friend_feed_menu_buttons": { - "auto_download": "⬇️ ऑटो डाउनलोड", - "auto_save": "💬 ऑटो सेव संदेश", - "unsaveable_messages": "⬇️ न सहेजने योग्य संदेश", - "auto_open_snaps": "📸 ऑटो ओपन स्नैप्स", - "stealth": "👻 स्टील्थ मोड", - "mark_snaps_as_seen": "👀 स्नैप को देखे गए के रूप में चिह्नित करें", - "mark_stories_as_seen_locally": "👀 कहानियों को स्थानीय रूप से देखे गए के रूप में चिह्नित करें", - "conversation_info": "🧑‍🤝‍🧑 वार्तालाप जानकारी", - "e2e_encryption": "🔒 E2E एन्क्रिप्शन का उपयोग करें" - }, - "path_format": { - "create_author_folder": "प्रत्येक लेखक के लिए फ़ोल्डर बनाएँ", - "create_source_folder": "प्रत्येक मीडिया स्रोत प्रकार के लिए फ़ोल्डर बनाएँ", - "append_hash": "फ़ाइल नाम में एक अद्वितीय हैश जोड़ें", - "append_source": "फ़ाइल नाम में मीडिया स्रोत जोड़ें", - "append_username": "फ़ाइल नाम में उपयोगकर्ता नाम जोड़ें", - "append_date_time": "फ़ाइल नाम में दिनांक और समय जोड़ें" - }, - "auto_download_sources": { - "friend_snaps": "मित्र स्नैप्स", - "friend_stories": "मित्र कहानियाँ", - "public_stories": "सार्वजनिक कहानियाँ", - "spotlight": "स्पॉटलाइट" - }, - "logging": { - "started": "शुरू हुआ", - "success": "सफलता", - "progress": "प्रगति", - "failure": "विफलता" - }, - "notifications": { - "chat_screenshot": "स्क्रीनशॉट", - "chat_screen_record": "स्क्रीन रिकॉर्ड", - "snap_replay": "स्नैप रीप्ले", - "camera_roll_save": "कैमरा रोल में सहेजें", - "chat": "चैट", - "chat_reply": "चैट उत्तर", - "snap": "स्नैप", - "typing": "टाइपिंग", - "stories": "कहानियाँ", - "speaking": "बोलना", - "chat_reaction": "डीएम प्रतिक्रिया", - "group_chat_reaction": "समूह प्रतिक्रिया", - "initiate_audio": "आने वाली ऑडियो कॉल", - "abandon_audio": "मिस्ड ऑडियो कॉल", - "initiate_video": "आने वाली वीडियो कॉल", - "abandon_video": "मिस्ड वीडियो कॉल", - "map_live_location": "मानचित्र लाइव स्थान" - }, - "gallery_media_send_override": { - "always_ask": "हमेशा पूछें", - "ORIGINAL": "मूल मीडिया", - "NOTE": "ऑडियो नोट", - "SNAP": "स्नैप", - "SAVEABLE_SNAP": "सहेजने योग्य स्नैप" - }, - "strip_media_metadata": { - "hide_caption_text": "कैप्शन टेक्स्ट छिपाएँ", - "hide_snap_filters": "स्नैप फ़िल्टर छिपाएँ", - "hide_extras": "अतिरिक्त छिपाएँ (जैसे उल्लेख)", - "remove_audio_note_duration": "ऑडियो नोट अवधि हटाएं", - "remove_audio_note_transcript_capability": "ऑडियो नोट प्रतिलेख क्षमता हटाएं" - }, - "hide_ui_components": { - "hide_profile_call_buttons": "प्रोफ़ाइल कॉल बटन हटाएं", - "hide_chat_call_buttons": "चैट कॉल बटन हटाएं", - "hide_live_location_share_button": "लाइव स्थान साझा करें बटन हटाएं", - "hide_stickers_button": "स्टिकर बटन हटाएं", - "hide_voice_record_button": "वॉयस रिकॉर्ड बटन हटाएं", - "hide_unread_chat_hint": "न पढ़े गए चैट संकेत हटाएं", - "hide_post_to_story_buttons": "एक स्नैप भेजने से पहले कहानी पर पोस्ट बटन हटाएं", - "hide_billboard_prompt": "मित्र फ़ीड में बिलबोर्ड प्रॉम्प्ट हटाएं", - "hide_snapchat_plus_gift_reminders": "वार्तालापों में Snapchat प्लस उपहार अनुस्मारक हटाएं", - "hide_map_reactions": "मानचित्र प्रतिक्रियाएं हटाएं" - }, - "hide_story_suggestions": { - "hide_suggested_friend_stories": "सुझाए गए मित्र कहानियों को छिपाएँ", - "hide_my_stories": "मेरी कहानियाँ छिपाएँ" - }, - "home_tab": { - "map": "मानचित्र", - "chat": "चैट", - "camera": "कैमरा", - "discover": "खोजें", - "spotlight": "स्पॉटलाइट" - }, - "add_friend_source_spoof": { - "added_by_username": "उपयोगकर्ता नाम द्वारा", - "added_by_mention": "उल्लेख द्वारा", - "added_by_group_chat": "समूह चैट द्वारा", - "added_by_qr_code": "क्यूआर कोड द्वारा", - "added_by_community": "समुदाय द्वारा", - "added_by_quick_add": "त्वरित जोड़ द्वारा (प्रतिबंधित होने का उच्च जोखिम)" - }, - "bypass_video_length_restriction": { - "single": "एकल मीडिया", - "split": "विभाजित मीडिया" - }, - "old_bitmoji_selfie": { - "2d": "2डी बिटमोजी", - "3d": "3डी बिटमोजी" - }, - "disable_confirmation_dialogs": { - "erase_message": "संदेश मिटाएँ", - "remove_friend": "मित्र को हटाएं", - "block_friend": "मित्र को अवरुद्ध करें", - "ignore_friend": "मित्र को अनदेखा करें", - "hide_friend": "मित्र को छिपाएँ", - "hide_conversation": "वार्तालाप छिपाएँ", - "clear_conversation": "मित्र फ़ीड से वार्तालाप साफ़ करें" - }, - "auto_reload": { - "snapchat_only": "केवल Snapchat", - "all": "सभी (Snapchat + PurrfectSnap)" - }, - "edit_text_override": { - "multi_line_chat_input": "मल्टी लाइन चैट इनपुट", - "bypass_text_input_limit": "टेक्स्ट इनपुट सीमा को बायपास करें" - }, - "auto_purge": { - "never": "कभी नहीँ", - "1_hour": "1 घंटा", - "3_hours": "3 घंटे", - "6_hours": "6 घंटे", - "12_hours": "12 घंटे", - "1_day": "1 दिन", - "3_days": "3 दिन", - "1_week": "1 सप्ताह", - "2_weeks": "2 सप्ताह", - "1_month": "1 महीना", - "3_months": "3 महीने", - "6_months": "6 महीने" - }, - "disable_story_sections": { - "friends": "मित्र", - "suggested_stories": "सुझाए गए कहानियाँ", - "following": "अनुसरण कर रहे हैं", - "discover": "खोजें" - }, - "disable_cameras": { - "front": "सामने का कैमरा", - "back": "पिछला कैमरा" - }, - "disable_permission_requests": { - "notifications": "सूचनाएं", - "read_media_images": "मीडिया छवियां पढ़ें", - "read_media_video": "मीडिया वीडियो पढ़ें", - "camera": "कैमरा", - "microphone": "माइक्रोफोन", - "location": "स्थान", - "read_contacts": "संपर्क पढ़ें", - "nearby_devices": "आस-पास के उपकरण", - "phone_calls": "फोन कॉल" - }, - "message_indicators": { - "encryption_indicator": "केवल आपको भेजे गए संदेशों के बगल में एक 🔒 आइकन जोड़ता है", - "platform_indicator": "जिस प्लेटफ़ॉर्म से एक मीडिया भेजा गया था उसका प्लेटफ़ॉर्म आइकन जोड़ता है (जैसे Android, iOS, Web)", - "location_indicator": "जब वे स्थान सक्षम के साथ भेजे गए हों तो स्नैप में एक 📍 आइकन जोड़ता है", - "ovf_editor_indicator": "इंगित करता है कि OVF संपादक का उपयोग करके एक स्नैप भेजा गया है या नहीं", - "director_mode_indicator": "जब वे निदेशक मोड का उपयोग करके भेजे गए हों तो स्नैप में एक 🎬 आइकन जोड़ता है, जिसका उपयोग गैलरी छवियों को स्नैप के रूप में भेजने के लिए किया जा सकता है" - }, - "auto_mark_as_read": { - "conversation_read": "एक संदेश भेजते समय वार्तालाप को पढ़े गए के रूप में चिह्नित करें", - "snap_reply": "स्नैप का उत्तर देते समय उन्हें पढ़े गए के रूप में चिह्नित करें", - "save_snap_in_chat": "स्टील्थ मोड में रहते हुए चैट में स्नैप सहेजते समय उन्हें पढ़े गए के रूप में चिह्नित करें" - }, - "friend_mutation_notifier": { - "remove_friend": "जब कोई आपको मित्र के रूप में हटाता है तो सूचित करें", - "birthday_changes": "जब कोई अपना जन्मदिन बदलता है तो सूचित करें", - "bitmoji_selfie_changes": "जब कोई अपना बिटमोजी सेल्फी बदलता है तो सूचित करें", - "bitmoji_avatar_changes": "जब कोई अपना बिटमोजी अवतार बदलता है तो सूचित करें", - "bitmoji_background_changes": "जब कोई अपनी बिटमोजी पृष्ठभूमि बदलता है तो सूचित करें", - "bitmoji_scene_changes": "जब कोई अपनी बिटमोजी दृश्य बदलता है तो सूचित करें" - }, - "snapchat_plus": { - "not_subscribed": "सब्सक्राइब नहीं किया है", - "basic": "बुनियादी", - "ad_free": "विज्ञापन मुक्त" - }, - "double_tap_chat_action": { - "like_message": "संदेश पसंद करें", - "copy_text": "क्लिपबोर्ड पर टेक्स्ट कॉपी करें", - "delete_message": "संदेश हटाएं", - "mark_as_read": "पढ़े गए के रूप में चिह्नित करें", - "custom_emoji_reaction": "कस्टम इमोजी प्रतिक्रिया" - }, - "startup_default_camera": { - "front": "सामने का कैमरा", - "back": "पिछला कैमरा" - } + "notices": { + "internal_behavior": "⚠ इससे स्नैपचैट का आंतरिक व्यवहार ख़राब हो सकता है", + "unstable": "⚠अस्थिर", + "ban_risk": "⚠इस सुविधा पर प्रतिबंध लग सकता है" } - }, - "friend_menu_option": { - "mark_snaps_as_seen": "स्नैप को देखे गए के रूप में चिह्नित करें", - "mark_stories_as_seen_locally": "कहानियों को स्थानीय रूप से देखे गए के रूप में चिह्नित करें", - "preview": "पूर्वावलोकन", - "stealth_mode": "स्टील्थ मोड", - "auto_download_blacklist": "ऑटो डाउनलोड ब्लैकलिस्ट", - "anti_auto_save": "एंटी ऑटो सेव" - }, - "content_type": { - "CHAT": "चैट", - "SNAP": "स्नैप", - "EXTERNAL_MEDIA": "बाहरी मीडिया", - "NOTE": "ऑडियो नोट", - "STICKER": "स्टिकर", - "SHARE": "शेयर करें", - "STATUS": "स्थिति", - "LOCATION": "स्थान", - "STATUS_SAVE_TO_CAMERA_ROLL": "कैमरा रोल में सहेजा गया", - "STATUS_CONVERSATION_CAPTURE_SCREENSHOT": "स्क्रीनशॉट", - "STATUS_CONVERSATION_CAPTURE_RECORD": "स्क्रीन रिकॉर्ड", - "STATUS_CALL_MISSED_VIDEO": "मिस्ड वीडियो कॉल", - "STATUS_CALL_MISSED_AUDIO": "मिस्ड ऑडियो कॉल", - "LIVE_LOCATION_SHARE": "लाइव स्थान साझा करें", - "CREATIVE_TOOL_ITEM": "रचनात्मक उपकरण आइटम", - "FAMILY_CENTER_INVITE": "परिवार केंद्र आमंत्रण", - "FAMILY_CENTER_ACCEPT": "परिवार केंद्र स्वीकार करें", - "FAMILY_CENTER_LEAVE": "परिवार केंद्र छोड़ें", - "STATUS_PLUS_GIFT": "स्थिति प्लस उपहार", - "TINY_SNAP": "छोटा स्नैप", - "STATUS_COUNTDOWN": "उल्टी गिनती", - "MAP_REACTION": "मानचित्र प्रतिक्रिया" - }, - "media_download_source": { - "none": "कोई नहीं", - "pending": "लंबित", - "chat_media": "चैट मीडिया", - "story": "कहानी", - "public_story": "सार्वजनिक कहानी", - "spotlight": "स्पॉटलाइट", - "profile_picture": "प्रोफ़ाइल चित्र", - "story_logger": "कहानी लकड़हारा", - "message_logger": "संदेश लकड़हारा", - "merged": "मर्ज किया गया", - "voice_call": "वॉयस कॉल" - }, - "chat_action_menu": { - "preview_button": "पूर्वावलोकन", - "download_button": "डाउनलोड करें", - "delete_logged_message_button": "लॉग किया गया संदेश हटाएं", - "show_chat_edit_history": "चैट संपादन इतिहास दिखाएं", - "convert_message": "संदेश रूपांतरित करें" - }, - "opera_context_menu": { - "download": "मीडिया डाउनलोड करें", - "sent_at": "{date} को भेजा गया", - "created_at": "{date} को बनाया गया", - "expires_at": "{date} को समाप्त होता है", - "media_size": "मीडिया का आकार: {size}", - "media_duration": "मीडिया अवधि: {duration} ms", - "show_debug_info": "डिबग जानकारी दिखाएं" - }, - "modal_option": { - "profile_info": "प्रोफ़ाइल जानकारी", - "close": "बंद करें" - }, - "gallery_media_send_override": { - "multiple_media_toast": "आप एक समय में केवल एक ही मीडिया भेज सकते हैं" - }, - "mark_as_seen": { - "no_unseen_snaps_toast": "कोई न देखे गए स्नैप नहीं मिले!", - "seen_toast": "देखे गए के रूप में चिह्नित!", - "unseen_toast": "न देखे गए के रूप में चिह्नित!", - "already_seen_toast": "पहले से ही देखे गए के रूप में चिह्नित!", - "already_unseen_toast": "पहले से ही न देखे गए के रूप में चिह्नित!" - }, - "conversation_preview": { - "streak_expiration": "{day} दिन {hour} घंटे {minute} मिनट में समाप्त होता है", - "total_messages": "कुल भेजे गए/प्राप्त संदेश: {count}", - "title": "पूर्वावलोकन", - "unknown_user": "अज्ञात उपयोगकर्ता", - "no_messages": "कोई संदेश नहीं मिला!" - }, - "profile_info": { - "title": "प्रोफ़ाइल जानकारी", - "first_created_username": "पहला बनाया गया उपयोगकर्ता नाम", - "mutable_username": "परिवर्तनशील उपयोगकर्ता नाम", - "display_name": "प्रदर्शन नाम", - "added_date": "जोड़ने की तारीख", - "birthday": "जन्मदिन : {day} {month}", - "hidden_birthday": "जन्मदिन : छिपा हुआ", - "friendship": "मित्रता", - "add_source": "स्रोत जोड़ें", - "snapchat_plus": "स्नैपचैट प्लस", - "snapchat_plus_state": { - "subscribed": "सब्सक्राइब किया है", - "not_subscribed": "सब्सक्राइब नहीं किया है" - } - }, - "friendship_link_type": { - "mutual": "पारस्परिक", - "outgoing": "जावक", - "blocked": "अवरुद्ध", - "deleted": "हटा दिया", - "following": "अनुसरण कर रहे हैं", - "suggested": "सुझाया गया", - "incoming": "आने वाली", - "incoming_follower": "आने वाला अनुयायी" - }, - "bulk_messaging_action": { - "choose_action_title": "एक क्रिया चुनें", - "progress_status": "{total} में से {index} पर संसाधित हो रहा है", - "selection_dialog_continue_button": "जारी रखें", - "confirmation_dialog": { - "title": "क्या आप सुनिश्चित हैं?", - "message": "यह सभी चयनित मित्रों को प्रभावित करेगा। इस क्रिया को पूर्ववत नहीं किया जा सकता है।" - }, - "actions": { - "remove_friends": "मित्रों को हटाएं", - "clear_conversations": "वार्तालाप साफ़ करें" - } - }, - "chat_export": { - "exporter_dialog": { - "select_conversations_title": "वार्तालाप चुनें", - "text_field_selection": "{amount} चयनित", - "text_field_selection_all": "सभी", - "export_file_format_title": "फ़ाइल प्रारूप निर्यात करें", - "message_type_filter_title": "प्रकार के अनुसार संदेशों को फ़िल्टर करें", - "amount_of_messages_title": "संदेशों की संख्या (सभी के लिए खाली छोड़ दें)", - "download_medias_title": "मीडिया डाउनलोड करें" - }, - "dialog_negative_button": "रद्द करें", - "dialog_positive_button": "निर्यात करें", - "exported_to": "{path} पर निर्यात किया गया", - "exporting_chats": "चैट निर्यात कर रहा है...", - "processing_chats": "{amount} वार्तालापों पर संसाधित हो रहा है...", - "export_fail": "वार्तालाप {conversation} निर्यात करने में विफल", - "writing_output": "आउटपुट लिख रहा है...", - "finished": "हो गया! अब आप इस संवाद को बंद कर सकते हैं।", - "no_messages_found": "कोई संदेश नहीं मिला!", - "exporting_message": "{conversation} निर्यात कर रहा है..." - }, - "button": { - "ok": "ठीक है", - "positive": "हाँ", - "negative": "नहीं", - "cancel": "रद्द करें", - "open": "खोलें", - "download": "डाउनलोड करें", - "send": "भेजें", - "restore_original": "मूल पुनर्स्थापित करें", - "convert_external_media": "बाहरी मीडिया रूपांतरित करें", - "save": "सहेजें" - }, - "tracker_events": { - "conversation_enter": "वार्तालाप में प्रवेश करें", - "conversation_exit": "वार्तालाप से बाहर निकलें", - "started_typing": "टाइप करना शुरू किया", - "stopped_typing": "टाइप करना बंद कर दिया", - "started_speaking": "बोलना शुरू किया", - "stopped_speaking": "बोलना बंद कर दिया", - "started_peeking": "झाँकना शुरू किया", - "stopped_peeking": "झाँकना बंद कर दिया", - "message_read": "संदेश पढ़ा", - "message_deleted": "संदेश हटाया गया", - "message_saved": "संदेश सहेजा गया", - "message_unsaved": "संदेश नहीं सहेजा गया", - "message_edited": "संदेश संपादित किया गया", - "message_reaction_add": "संदेश प्रतिक्रिया जोड़ें", - "message_reaction_remove": "संदेश प्रतिक्रिया हटाएं", - "snap_opened": "स्नैप खोला गया", - "snap_replayed": "स्नैप फिर से चलाया गया", - "snap_replayed_twice": "स्नैप दो बार फिर से चलाया गया", - "snap_screenshot": "स्नैप स्क्रीनशॉट", - "snap_screen_record": "स्नैप स्क्रीन रिकॉर्ड" - }, - "tracker_actions": { - "log": "लॉग", - "in_app_notification": "इन-ऐप अधिसूचना", - "push_notification": "पुश अधिसूचना", - "custom": "कस्टम" - }, - "better_notifications": { - "button": { - "reply": "उत्तर दें", - "download": "डाउनलोड करें", - "mark_as_read": "पढ़े गए के रूप में चिह्नित करें" - } - }, - "profile_picture_downloader": { - "button": "प्रोफ़ाइल चित्र डाउनलोड करें", - "title": "प्रोफ़ाइल चित्र डाउनलोडर", - "avatar_option": "अवतार", - "background_option": "पृष्ठभूमि" - }, - "call_start_confirmation": { - "dialog_title": "कॉल शुरू करें", - "dialog_message": "क्या आप सुनिश्चित हैं कि आप कॉल शुरू करना चाहते हैं?" - }, - "half_swipe_notifier": { - "notification_channel_name": "आधा स्वाइप", - "notification_content_dm": "{friend} ने अभी आपके चैट में {duration} सेकंड के लिए आधा स्वाइप किया", - "notification_content_group": "{friend} ने अभी {group} में {duration} सेकंड के लिए आधा स्वाइप किया" - }, - "download_processor": { - "attachment_type": { - "snap": "स्नैप", - "sticker": "स्टिकर", - "gif": "जीआईएफ", - "external_media": "बाहरी मीडिया", - "note": "नोट", - "original_story": "मूल कहानी" - }, - "select_attachments_title": "अनुलग्नक चुनें", - "download_started_toast": "डाउनलोड शुरू हुआ", - "unsupported_content_type_toast": "असमर्थित सामग्री प्रकार!", - "failed_no_longer_available_toast": "मीडिया अब उपलब्ध नहीं है", - "no_attachments_toast": "कोई अनुलग्नक नहीं मिला!", - "already_queued_toast": "मीडिया पहले से ही कतार में है!", - "already_downloaded_toast": "मीडिया पहले से ही डाउनलोड है!", - "content_saved_toast": "सहेजा गया!", - "download_toast": "{path} डाउनलोड हो रहा है...", - "processing_toast": "{path} संसाधित हो रहा है...", - "failed_generic_toast": "डाउनलोड करने में विफल", - "failed_to_create_preview_toast": "पूर्वावलोकन बनाने में विफल", - "failed_processing_toast": "संसाधन विफल {error}", - "failed_gallery_toast": "गैलरी में सहेजने में विफल {error}", - "dash_no_chapter": "कोई अध्याय नहीं मिला", - "dash_dialog": { - "title": "डैश मीडिया डाउनलोड करें", - "download_all": "सभी डाउनलोड करें", - "segment_text": "खंड {from} - {to}" - } - }, - "streaks_reminder": { - "notification_title": "स्ट्रीक्स", - "notification_text": "आप {hoursLeft} घंटों में {friend} के साथ अपनी स्ट्रीक खो देंगे" - }, - "biometric_auth": { - "unlock_button": "अनलॉक करें", - "title": "Snapchat अनलॉक करें", - "subtitle": "कृपया Snapchat अनलॉक करने के लिए प्रमाणित करें" - }, - "end_to_end_encryption": { - "toolbox": { - "no_shared_key": "आपके पास अभी तक इस मित्र के साथ कोई साझा रहस्य नहीं है। नया शुरू करने के लिए नीचे क्लिक करें।", - "shared_key_fingerprint": "आपकी फिंगरप्रिंट है:\n\n{fingerprint}\n\nसुनिश्चित करें कि यह आपके मित्र की फिंगरप्रिंट से मेल खाता है!", - "initiate_exchange_button": "कुंजी विनिमय शुरू करें" - }, - "confirmation_dialogs": { - "title": "एंड-टू-एंड एन्क्रिप्शन", - "confirmation_1": "चेतावनी: यह आपकी मौजूदा कुंजी को ओवरराइट कर देगा। आप इस मित्र से सभी एन्क्रिप्टेड संदेशों तक पहुंच खो देंगे। क्या आप सुनिश्चित हैं कि आप जारी रखना चाहते हैं?", - "confirmation_2": "क्या आप वास्तव में सुनिश्चित हैं कि आप जारी रखना चाहते हैं? यह पीछे हटने का आपका आखिरी मौका है।" - }, - "unencrypted_conversation_send_failure_toast": "आप एन्क्रिप्टेड और अनएन्क्रिप्टेड दोनों वार्तालापों में एन्क्रिप्टेड सामग्री नहीं भेज सकते हैं!", - "native_hooks_send_failure_toast": "भेजने में विफल! कृपया सेटिंग्स में मूल हुक सक्षम करें।", - "no_participants_to_encrypt_toast": "इस वार्तालाप में आपके पास संदेशों को एन्क्रिप्ट करने के लिए कोई मित्र नहीं है!", - "encryption_failed_toast": "संदेश एन्क्रिप्ट करने में विफल! अधिक विवरण के लिए लॉगकैट देखें।", - "accept_public_key_success_toast": "सार्वजनिक कुंजी सफलतापूर्वक स्वीकार कर ली गई!", - "accept_secret_key_success_toast": "हो गया! अब आप इस मित्र के साथ एन्क्रिप्टेड संदेश भेज और प्राप्त कर सकते हैं।", - "accept_public_key_failure_toast": "सार्वजनिक कुंजी स्वीकार करने में विफल", - "accept_secret_key_failure_toast": "गुप्त कुंजी स्वीकार करने में विफल", - "accept_secret_button": "गुप्त स्वीकार करें", - "accept_public_key_button": "सार्वजनिक कुंजी स्वीकार करें", - "outgoing_pk_message": "कुंजी विनिमय अनुरोध", - "outgoing_secret_message": "कुंजी विनिमय प्रतिक्रिया", - "incoming_pk_message": "आपको अभी एक सार्वजनिक कुंजी अनुरोध प्राप्त हुआ है। इसे स्वीकार करने के लिए नीचे क्लिक करें।", - "incoming_secret_message": "आपके मित्र ने अभी आपकी सार्वजनिक कुंजी स्वीकार कर ली है। रहस्य स्वीकार करने के लिए नीचे क्लिक करें।" - }, - "auto_open_snaps": { - "title": "ऑटो ओपन स्नैप्स", - "notification_content": "{count} स्नैप खोले गए" - }, - "friend_mutation_observer": { - "notification_channel_name": "मित्र उत्परिवर्तन प्रेक्षक", - "friend_removed": "{username} ने आपको एक मित्र के रूप में हटा दिया है", - "birthday_removed": "{username} ने अपना जन्मदिन हटा दिया है ({birthday})", - "birthday_added": "{username} ने अपना जन्मदिन जोड़ा है ({birthday})", - "birthday_changed": "{username} ने अपना जन्मदिन {oldBirthday} से {newBirthday} में बदल दिया है", - "bitmoji_selfie_changed": "{username} ने अपना बिटमोजी सेल्फी बदल दिया है", - "bitmoji_avatar_changed": "{username} ने अपना बिटमोजी अवतार बदल दिया है", - "bitmoji_background_changed": "{username} ने अपनी बिटमोजी पृष्ठभूमि बदल दी है", - "bitmoji_scene_changed": "{username} ने अपनी बिटमोजी दृश्य बदल दिया है" - }, - "material3_strings": { - "date_range_picker_start_headline": "से", - "date_range_picker_end_headline": "तक", - "date_range_picker_title": "दिनांक सीमा चुनें", - "date_picker_switch_to_calendar_mode": "कैलेंडर", - "date_picker_switch_to_input_mode": "इनपुट", - "date_range_picker_scroll_to_previous_month": "पिछला महीना", - "date_range_picker_scroll_to_next_month": "अगला महीना", - "date_picker_today_description": "आज", - "date_range_picker_day_in_range": "चयनित", - "date_input_invalid_for_pattern": "अमान्य दिनांक", - "date_input_invalid_year_range": "अमान्य वर्ष", - "date_input_invalid_not_allowed": "अमान्य दिनांक", - "date_range_input_invalid_range_input": "अमान्य दिनांक सीमा" - }, - "send_override_dialog": { - "title": "{type} के रूप में मीडिया भेजें", - "duration": "अवधि: {duration}", - "saveable_snap_hint": "चैट में स्नैप को सहेजने योग्य बनाएं", - "unlimited_duration": "असीमित" - }, - "invalid_input_toast": "अमान्य इनपुट! सुनिश्चित करें कि आपने एक मान्य मान दर्ज किया है।" -} \ No newline at end of file + } +} diff --git a/common/src/main/assets/lang/hr_HR.json b/common/src/main/assets/lang/hr_HR.json new file mode 100644 index 00000000..1b43a6a5 --- /dev/null +++ b/common/src/main/assets/lang/hr_HR.json @@ -0,0 +1,71 @@ +{ + "setup": { + "dialogs": { + "select_save_folder_button": "Odaberite mapu", + "select_language": "Odaberite jezik", + "save_folder": "SnapEnhance-u je potrebno omogućiti pristup datotekama kako bi mogao skidati i spremati medije sa Snapchat-a.\nMolimo odaberite lokaciju gdje želite da se mediji spremaju." + }, + "mappings": { + "dialog": "Generiranje mapiranja, ovo može potrajati..", + "generate_failure_no_snapchat": "SnapEnhance nije uspio detektirati Snapchat, probajte ga ponovo instalirati.", + "generate_failure": "Greška prilikom generiranja \"mappings\"-a, molimo pokušajte ponovo." + }, + "permissions": { + "notification_access": "Pristup notifikacijama", + "battery_optimization": "Optimizacija baterije", + "display_over_other_apps": "Prikaz preko drugih aplikacija", + "request_button": "Zahtjev", + "dialog": "Kako bih nastavili morate ispunjavati sljedeće uvjete:" + } + }, + "scopes": { + "friend": "Prijatelj", + "group": "Grupa" + }, + "manager": { + "routes": { + "tasks": "Zadaci", + "features": "Značajke", + "home": "Početna", + "home_logs": "Logovi", + "logger_history": "Povijest loggera", + "social": "Social", + "messaging_preview": "Pretpregled", + "scripts": "Skripte", + "home_settings": "Postavke", + "logged_stories": "Zabilježene priče", + "manage_scope": "Upravljanje opsegom" + }, + "sections": { + "home": { + "update_title": "SnapEnhance nadogradnja", + "update_content": "Verzija {version} je dostupna!", + "update_button": "Preuzimanje" + }, + "home_logs": { + "export_logs_button": "Izvezi logove", + "saved_logs_failure_toast": "Logovi neuspješno spremljeni", + "no_logs_hint": "Nema dostupnih logova", + "clear_logs_button": "Očisti logove", + "saving_logs_toast": "Spremanje logova, ovo može potrajati...", + "saved_logs_success_toast": "Logovi uspješno spremljeni" + }, + "home_settings": { + "actions_title": "Akcije", + "message_logger_title": "Logger poruka", + "debug_title": "Debug", + "clear_button": "Očisti", + "view_logger_history_button": "Pregledaj povijest loggera", + "success_toast": "Gotovo!", + "message_logger_summary": "{messageCount} poruka\n{storyCount} stories", + "export_button": "Izvoz" + }, + "tasks": { + "no_tasks": "Nema zadataka", + "merge_files_toast": "Spajanje {count} datoteka", + "remove_selected_tasks_title": "Jeste li sigurni da želite ukloniti odabrane zadatke?", + "remove_all_tasks_title": "Jeste li sigurni da ste uklonili sve zadatke?" + } + } + } +} diff --git a/common/src/main/assets/lang/hu_HU.json b/common/src/main/assets/lang/hu_HU.json new file mode 100644 index 00000000..546bffe8 --- /dev/null +++ b/common/src/main/assets/lang/hu_HU.json @@ -0,0 +1,1517 @@ +{ + "setup": { + "dialogs": { + "select_language": "Nyelv kiválasztása", + "save_folder": "A SnapEnhance-nek tárhelyhozzáférésre van szüksége média mentéséhez és letöltéséhez. \nKérem válassza ki a média mentési helyét.", + "select_save_folder_button": "Mappa kiválasztása" + }, + "mappings": { + "dialog": "Hozzárendelések generálása, ez eltarthat egy darabig ...", + "generate_failure_no_snapchat": "A SnapEnhance nem találja a Snapchatet, próbálja meg újra telepíteni a Snapchatet.", + "generate_failure": "Hiba történt a beállítások mentése során, kérjük próbálja meg újra." + }, + "permissions": { + "dialog": "A folytatáshoz a következőkre van szükség:", + "notification_access": "Értesítési hozzáférés", + "battery_optimization": "Akkumulátor optimalizálás", + "display_over_other_apps": "Megjelenítés a többi alkalmazás fölött", + "request_button": "Kérelem" + } + }, + "manager": { + "routes": { + "features": "Funkciók", + "home": "Kezdőlap", + "home_settings": "Beállítások", + "home_logs": "Naplófájlok", + "social": "Közösség", + "scripts": "Szkriptek", + "tasks": "Feladatok", + "logger_history": "Naplózó előzménye", + "logged_stories": "Naplózott sztorik", + "manage_scope": "Terület kezelése", + "messaging_preview": "Előnézet", + "edit_rule": "Szabály szerkesztése", + "friend_tracker": "Barát figyelő", + "better_location": "Jobb helyzet", + "file_imports": "Fájl importálások" + }, + "sections": { + "features": { + "disabled": "Kikapcsolva", + "import_option": "Importálás", + "reset_option": "Visszaállítás", + "config_export_success_toast": "Beállításfájl sikeresen exportálva", + "config_import_success_toast": "Beállításfájl sikeresen importálva", + "config_import_failure_toast": "Beállításfájl importálása sikertelen {error}", + "saved_config_snackbar": "Beállításfájl elmentve", + "export_option": "Exportálás", + "config_export_failure_toast": "Nem sikerült a configot exportálni {error}" + }, + "social": { + "streaks_expiration_short": "{hours} óra", + "groups_tab": "Csoportok", + "empty_hint": "(üres)", + "friends_tab": "Barátok" + }, + "tasks": { + "no_tasks": "Nincsenek feladatok", + "merge_files_toast": "{count} fájl egybevonása", + "remove_selected_tasks_title": "Biztosan törölni szeretnéd a kiválasztott feladatokat?", + "remove_all_tasks_title": "Biztosan törölni szeretnéd az összes feladatot?", + "delete_files_option": "Törölje a fájlokat is", + "remove_selected_tasks_confirm": "{count} feladat eltávolítása?", + "remove_all_tasks_confirm": "Minden feladat eltávolítása?", + "failed_to_open_file": "Fájl megnyitása sikertelen" + }, + "home": { + "update_title": "SnapEnhance frissítés", + "update_content": "A(z) {version} már elérhető!", + "update_button": "Letöltés", + "version_title": "v{versionName} · eternal által", + "debug_build_summary_content": "Verzió {versionName} ({versionCode})", + "debug_build_summary_date": "Buildelés dátuma: {date} ({days} napja)", + "quick_actions_title": "Gyors műveletek", + "debug_build_summary_title": "Egy debug verziót használsz a SnapEnhance-ből" + }, + "home_settings": { + "view_logger_history_button": "Naplóelőzmények megtekintése", + "actions_title": "Műveletek", + "message_logger_title": "Üzenet naplózó", + "debug_title": "Hibakeresés", + "success_toast": "Kész!", + "message_logger_summary": "{messageCount} üzenet(ek)\n{storyCount} történet(ek)", + "export_button": "Exportálás", + "clear_button": "Töröl" + }, + "home_logs": { + "no_logs_hint": "Nincsenek elérhető naplófájlok", + "clear_logs_button": "Naplófájlok törlése", + "export_logs_button": "Naplófájlok exportálása", + "saving_logs_toast": "Naplófájlok mentése, eltarthat egy ideig...", + "saved_logs_success_toast": "Naplófájlok sikeresen elmentve", + "saved_logs_failure_toast": "Naplófájlok mentése sikertelen" + }, + "manage_scope": { + "logged_stories_button": "Mutassa a naplózott történeteket", + "e2ee_title": "Végpontok közötti titkosítás", + "rules_title": "Szabályok", + "participants_text": "{count} résztvevő(k)", + "not_found": "Nincs találat", + "streaks_title": "Sorozatok", + "streaks_length_text": "Hossz: {length}", + "streaks_expiration_text": "Lejár {eta} időn belül", + "streaks_expiration_text_expired": "Lejárt", + "reminder_button": "Emlékeztető beállítása", + "delete_scope_confirm_dialog_title": "Biztosan törölni szeretnéd a {scope}-ot?" + }, + "logged_stories": { + "story_failed_to_load": "Sikertelen betöltés", + "no_stories": "Nincsenek történetek", + "save_from_cache_button": "Mnetés gyorsítótárból" + }, + "messaging_preview": { + "bridge_connection_failed": "Nem sikerült a hídhoz csatlakozni. Ellenőrizd, hogy a Snapchat fut-e a háttérben", + "bridge_init_failed": "Nem sikerült a híd szolgáltatás létrehozása. Ellenőrizd, higy a Snapchat fut-e a háttérben", + "message_fetch_failed": "Nem sikerült az üzenetek lekérése", + "no_message_hint": "Nincs(enek) üzenet(ek)", + "save_selection_option": "Kiválasztás mentése", + "save_all_option": "Mind mentése", + "unsave_selection_option": "Mégse mentse a kiválasztottakat", + "unsave_all_option": "Egyiket se mentse", + "mark_selection_as_seen_option": "Kijelölt snap megjelölése \"láttam\"-ként", + "mark_all_as_seen_option": "Minden snap megjelölése \"láttam\"-ként", + "delete_selection_option": "Kiválasztottak törlése", + "delete_all_option": "Mind törlése" + }, + "logger_history": { + "list_friend_format": "Barát: {name}", + "list_group_format": "Csoport: {name}", + "no_more_messages": "Nincs több üzenet", + "reverse_order_checkbox": "Sorrend megfordítása", + "chat_attachment": "Csatolmány {index}", + "empty_message": "Chat üzeneteinek törlése", + "message_parse_failed": "Nem sikerült az üzenetet értelmezni", + "unknown_sender": "Ismeretlen küldő", + "download_attachment_failed_toast": "Nem sikerült a csatolmányt letölteni" + }, + "file_imports": { + "file_imported": "A fájl sikeresen importálva", + "file_delete_failed": "Nem sikerült törölni a fájlt", + "file_import_failed": "Nem sikerült a fájlt importálni: {error}", + "no_files_hint": "Itt tudsz fájlokat importálni, hogy a Snapchatben használd. Nyomd meg a gombot egy fájl importálásához.", + "import_file_button": "Fájl importálása", + "file_not_found": "Fájl nem található" + }, + "better_location": { + "spoofed_coordinates_title": "Szé {latitude}, Hsz {longitude}", + "save_coordinates_dialog_title": "Kordináták mentése", + "saved_name_dialog_hint": "Elmentett név", + "longitude_dialog_hint": "Hosszúság", + "save_dialog_button": "Mentés", + "teleport_to_friend_button": "Teleportálás egy baráthoz", + "saved_coordinates_title": "Elmentett kordináták", + "no_saved_coordinates_hint": "Nincs mentett kordináta", + "delete_dialog_message": "Biztos, hogy törölni szeretnéd ezt az elmentett kordinátát?", + "teleport_to_friend_title": "Teleportálás egy baráthoz", + "no_friends_map": "Nincsen a térképen barátod", + "no_friends_found": "Nincsenek barátaid", + "latitude_dialog_hint": "Szélesség", + "choose_location_button": "Válassz egy helyet", + "spoof_location_toggle": "Helyzet hamisítása", + "delete_dialog_title": "Mentett kordináta törlése", + "search_bar": "Keresés", + "suspend_location_updates": "Helyadatok küldésének letiltása" + } + }, + "dialogs": { + "add_friend": { + "title": "Barát vagy csoport hozzáadása", + "search_hint": "Keresés", + "fetch_error": "Sikertelen adatlekérdezés", + "category_groups": "Csoportok", + "category_friends": "Barátok" + }, + "scripting_warning": { + "content": "A SnapEnhance egy script-író eszközt, amely lehetővé teszi a felhasználó által meghatározott kódok végrehajtását az eszközön. Használja fokozott óvatossággal és csak megbízható forrásból származó modulokat telepítsen. A nem engedélyezett vagy nem ellenőrzött modulok biztonsági kockázatokat jelenthetnek a rendszerének.", + "title": "Figyelmeztetés" + }, + "reset_config": { + "content": "Biztosan vissza akarod állítani a beállításfájlt?", + "title": "Beállításfájl visszaállítása", + "success_toast": "Beállításfájl sikeresen visszaállítva" + }, + "messaging_action": { + "title": "Válassza ki a feldolgozni kívánt tartalomtípusokat", + "select_all_button": "Összes keresése" + }, + "file_imports": { + "no_files_settings_hint": "Nincsenek fájlok. Ellenőrizd, hogy minden szükséges fájl benne van-e a Fájl importálás részben", + "settings_select_file_hint": "Válassz egy importált fájlt" + }, + "export_config": { + "title": "Exportálod az érzékeny adatokat?", + "content": "Szeretnéd exportálni a beállításaidat az érzékeny adataiddal együtt? (Mint a helyzeted kordinátái, stb.)" + } + } + }, + "rules": { + "modes": { + "blacklist": "Feketelista mód", + "whitelist": "Whitelist mód" + }, + "properties": { + "auto_download": { + "name": "Automatikus letöltés", + "description": "Automatikusan letölti a Snap-eket a megtekintésükkor", + "options": { + "blacklist": "Automatikus letöltésből való kizárás", + "whitelist": "Automatikus Letöltés" + } + }, + "stealth": { + "name": "Rejtőzködő üzemmód", + "description": "Megakadályozza, hogy bárki megtudja, hogy megnyitotta a Snap-eket/Chat-eket és beszélgetéseket", + "options": { + "blacklist": "Kizárás a rejtőzködő üzemmódból", + "whitelist": "Rejtőzködő üzemmód" + } + }, + "auto_save": { + "name": "Automatikus mentés", + "description": "Elmenti a Chat Üzeneteket megtekintéskor", + "options": { + "blacklist": "Automatikus mentésből kizárás", + "whitelist": "Automatikus mentés" + } + }, + "hide_friend_feed": { + "name": "Elrejtés a barát hírfolyamáról" + }, + "e2e_encryption": { + "name": "Végpontok közötti titkosítás használata" + }, + "pin_conversation": { + "name": "Beszélgetés kitűzése" + }, + "unsaveable_messages": { + "name": "Nem menthető üzenetek", + "options": { + "whitelist": "Nem menthető üzenetek", + "blacklist": "Kizárás a nem menthető üzenetekből" + }, + "description": "Megakadályozza, hogy az üzeneteket elmenthessék mások a chatben" + }, + "auto_open_snaps": { + "name": "Automatikus Snap-ek", + "description": "Automatikusan megnyitja a Snap-eket, amikor megkapja azokat", + "options": { + "blacklist": "A kihagyás az automatikus snap-ekből", + "whitelist": "Automatikus snap-ek megnyitása" + } + } + }, + "toasts": { + "enabled": "{ruleName} engedélyezve", + "disabled": "{ruleName} letiltva" + } + }, + "features": { + "notices": { + "unstable": "⚠ Instabil", + "ban_risk": "⚠ Ez a funkció tiltást eredményezhet", + "internal_behavior": "⚠ Ez a funkció hibát okozhat a Snapchat működésében" + }, + "properties": { + "downloader": { + "name": "Letöltő", + "description": "Snapchat média letöltése", + "properties": { + "save_folder": { + "name": "Letöltések mappa", + "description": "Válaszd ki a könyvtárat ahová a letöltött médiát szeretnéd menteni" + }, + "auto_download_sources": { + "name": "Automatikus letöltési források", + "description": "Válaszd ki a forrásokat ahonnan automatikusan leszeretnél tölteni" + }, + "prevent_self_auto_download": { + "name": "Sajátmagam automatikus letöltésének megakadályozása", + "description": "Megakadályozza hogy a saját Snap-jeid automatikusan le legyenek töltve" + }, + "path_format": { + "name": "Elérési útvonal formátuma", + "description": "A fájl elérési útvonal formátumának megadása" + }, + "allow_duplicate": { + "name": "Ismétlődések engedélyezése", + "description": "Engedélyezi a médiák többszöri letöltését" + }, + "force_image_format": { + "name": "Képformátum kényszerítése", + "description": "Kényszeríti a képeket hogy egy megadott formátumba legyenek mentve" + }, + "force_voice_note_format": { + "name": "Hangüzenet formátumának kényszerítése", + "description": "Kényszeríti a hangüzeneteket hogy egy megadott formátumba legyenek mentve" + }, + "download_profile_pictures": { + "name": "Profilképek letöltése", + "description": "Lehetővé teszi hogy letölts profilképeket a profil oldaláról" + }, + "ffmpeg_options": { + "name": "FFmpeg beállítások", + "description": "További FFmpeg beállítások meghatározása", + "properties": { + "preset": { + "name": "Sablon", + "description": "Beszélgetés gyorsaságának állítása" + }, + "video_bitrate": { + "name": "Videó bitrátája", + "description": "A videó bitrátájának állítása (kbps)" + }, + "audio_bitrate": { + "name": "Hang bitrátája", + "description": "A hang bitrátájának állítása (kbps)" + }, + "custom_video_codec": { + "name": "Egyéni videó codec", + "description": "Egyéni videó codec beállítása (pl.: libx264)" + }, + "custom_audio_codec": { + "name": "Egyéni audió codec", + "description": "Egyéni audió codec beállítása (pl.: AAC)" + }, + "threads": { + "name": "Szálak", + "description": "A felhasznált szálak mennyisége" + }, + "constant_rate_factor": { + "name": "Állandó ráta tényező", + "description": "Állandó sebességtényező beállítása a videokódolóhoz\n0 és 51 között libx264 esetén" + } + } + }, + "logging": { + "name": "Naplózás", + "description": "Üzenet megjelenítése média letöltésekor" + }, + "opera_download_button": { + "description": "Hozzáad egy letöltés gombot a jobb felső sarokban, amikor egy Snapet nézel.\nA gombok hosszú megnyomása kikényszeríti a letöltést", + "name": "Letöltés Operával Gomb" + }, + "merge_overlays": { + "description": "Egyesíti egy Snap szövegét és médiáját egy fájlba", + "name": "Overlay-ek összefűzése" + }, + "custom_path_format": { + "name": "Egyéni elérési útvonal formátum", + "description": "Egyéni elérési útvonal-formátum megadása a letöltött média számára\n\nElérhető változók:\n - %username%\n - %source%\n - %hash%\n - %date_time%" + }, + "download_context_menu": { + "name": "Letöltés kontextusmenü", + "description": "Lehetővé teszi az üzenetek letöltését/előnézetét egy beszélgetésből vagy egy történetből a kontextusmenü segítségével.\nA gombok hosszú megnyomása kikényszeríti a letöltést" + } + } + }, + "user_interface": { + "name": "Felhasználói felület", + "properties": { + "enable_app_appearance": { + "name": "Az alkalmazás megjelenési beállításainak engedélyezése", + "description": "Engedélyezi a rejtett Megjelenés beállítást az alkalmazásban\nLehet, hogy az újabb Snapchat verziókban nincs szükség rá" + }, + "friend_feed_message_preview": { + "name": "Barát hírfolyam üzenet előnézet", + "description": "Megmutatja az előnézetét az utolsó üzeneteknek a barát hírfolyamban", + "properties": { + "amount": { + "name": "Mennyiség", + "description": "Az előnézetben megjelenítendő üzenetek mennyisége" + } + } + }, + "bootstrap_override": { + "properties": { + "app_appearance": { + "name": "App Megjelenése", + "description": "Állandó alkalmazásmegjelenítés beállítása" + }, + "home_tab": { + "name": "Kezdőlap fül", + "description": "Felülírja a megjelenő ablakot a Snapchat indulásakor" + } + }, + "description": "Felülírja a kezelőfelület Bootstrap beállításait", + "name": "Bootstrap felülírása" + }, + "streak_expiration_info": { + "name": "Mutassa a streak lejárati adatait", + "description": "A Streak számláló mellett megjelenik a Streak lejárati időzítője" + }, + "hide_friend_feed_entry": { + "name": "Barát hírfolyam elrejtése", + "description": "Elrejt egy kiválasztott barátot a barát hírfolyamról\nHasználd a közösségi lapot ahhoz hogy kezeld ezt a funkciót" + }, + "hide_streak_restore": { + "name": "Sorozat pontszám elrejtése", + "description": "Elrejti a visszaállítás gombot a barát hírfolyamról" + }, + "hide_ui_components": { + "name": "Felhasználói felület elemeinek elrejtése", + "description": "Válaszd ki hogy a felhasználói felület mely részeit szeretnéd elrejteni" + }, + "disable_spotlight": { + "name": "Spotlight letiltása", + "description": "Letiltja a Spotlight oldalt" + }, + "friend_feed_menu_buttons": { + "name": "Barát hírfolyam menü gombok", + "description": "Annak kiválasztása hogy mely gombok jelennek meg a barát hírfolyam menüsorban" + }, + "enable_friend_feed_menu_bar": { + "name": "Barát hírfolyam menüsor", + "description": "Engedélyezi az új barát hírfolyam menüsort" + }, + "prevent_message_list_auto_scroll": { + "name": "Megakadályozza az üzenet lista automatikus görgetését", + "description": "Megakadályozza, hogy az üzenetlista üzenetek küldésekor/fogadásakor a lista aljára gördüljön" + }, + "snap_preview": { + "name": "Snap előnézet", + "description": "Megjelenít egy kis előnézetet a nem látott pillanatok mellett a csevegésben" + }, + "map_friend_nametags": { + "name": "Továbbfejlesztett baráti térkép névtáblák", + "description": "Javítja a barátok névtábláit a Snapmap-en" + }, + "stealth_mode_indicator": { + "description": "Hozzáad egy 👻 emojit a rejtett módban lévő beszélgetések mellé", + "name": "Rejtőzködő üzemmód jelzője" + }, + "edit_text_override": { + "name": "Szöveg szerkesztése felülírása", + "description": "Felülírja a szövegmező viselkedését" + }, + "opera_media_quick_info": { + "name": "Opera Media gyors információ", + "description": "Megjeleníti a média hasznos információit, például a létrehozás dátumát az Opera Viewer kontextusmenüjében" + }, + "vertical_story_viewer": { + "description": "Engedélyezi a függőleges történetnézegetőt az összes történethez", + "name": "Függőleges történetnéző" + }, + "old_bitmoji_selfie": { + "description": "Visszahozza a Bitmoji szelfiket a régebbi Snapchat verziókból", + "name": "Régi Bitmoji szelfi" + }, + "hide_story_suggestions": { + "name": "Történet javaslatok elrejtése", + "description": "Eltávolítja a javaslatokat a Történetek oldalról" + }, + "message_indicators": { + "name": "Üzenetjelzők", + "description": "Speciális jelzőikonok hozzáadása az üzenetekhez\nMegjegyzés: a mutatók nem biztos, hogy 100%-ban pontosak" + } + }, + "description": "Módosítsd a Snapchat kinézetét" + }, + "messaging": { + "name": "Üzenetküldés", + "properties": { + "anonymous_story_viewing": { + "name": "Anonim Story nézés", + "description": "Megakadályozza, hogy bárki megtudja, hogy láttad a történetüket" + }, + "hide_bitmoji_presence": { + "name": "Bitmojik elrejtése", + "description": "Megakadályozza a Bitmoji-d megjelenítését, miközben a Chat meg van nyitva" + }, + "hide_typing_notifications": { + "name": "Gépelési értesítések elrejtése", + "description": "Megakadályozza, hogy bárki megtudja, hogy éppen üzenetet írsz" + }, + "unlimited_snap_view_time": { + "name": "Korlátlan Snap Megtekintési Idő", + "description": "Eltávolítja a Snap-ek megtekintési időkorlátját" + }, + "disable_replay_in_ff": { + "description": "Letiltja a lehetőséget hogy újrajátsz a barát hírfolyamból hosszú nyomással", + "name": "A visszajátszás kikapcsolása FF-ben" + }, + "better_notifications": { + "name": "Jobb Értesítések", + "description": "Több információt mutat az értesítésekben", + "properties": { + "group_notifications": { + "description": "Egy értesítésbe csoportosítja az értesítéseket", + "name": "Csoportosított értesítés" + }, + "chat_preview": { + "name": "Beszélgetés előnézet", + "description": "Megjeleníti a kapott üzenetek előnézetét az értesítésben" + }, + "media_preview": { + "description": "Megjeleníti a kapott média típusok előnézetét az értesítésben", + "name": "Média előnézet" + }, + "stacked_media_messages": { + "name": "Csoportosított média üzenetek", + "description": "Több médiaüzenet egyetlen szöveges értesítésben történő egyesítése, ha azok nem tekinthetők meg előnézetben. A Beszélgetés előnézet funkcióval együtt használható" + }, + "friend_add_source": { + "name": "Barát hozzáadásának forrása", + "description": "Megjeleníti a barát kérelem forrását az értesítésben" + }, + "media_caption": { + "name": "Média felirat", + "description": "Megjeleníti a csatolt feliratokat a média értesítésben" + }, + "reply_button": { + "name": "Válasz gomb", + "description": "Hozzáad egy válasz gombot az értesítéshez" + }, + "download_button": { + "name": "Letöltés gomb", + "description": "Engedi, hogy letöltse a médiát az értesítésből" + }, + "mark_as_read_button": { + "name": "Megjelölés olvasottként gomb", + "description": "Engedi, hogy megjelöld az üzenetet olvasottként az értesítésből" + }, + "mark_as_read_and_save_in_chat": { + "name": "Megjelölés olvasottként és mentés", + "description": "Megjelöli olvasottként és elmenti a beszélgetésben az értesítésből" + }, + "smart_replies": { + "name": "Okos válaszok", + "description": "Hozzáad ajánlott válaszokat az értesítéshez (Android 10+). Használd a válasz gombbal együtt" + } + } + }, + "notification_blacklist": { + "name": "Értesítési Tiltólista", + "description": "Jelöld ki azokat az értesítéseket, amelyeket tiltani szeretnél" + }, + "message_logger": { + "name": "Üzenetnapló", + "description": "Megakadályozza az üzenetek törlését", + "properties": { + "message_filter": { + "name": "Üzenet szűrő", + "description": "Jelöld ki, hogy mely üzenetek kerüljenek naplózásra (üres az összes üzenet esetén)" + }, + "keep_my_own_messages": { + "description": "Megakadályozza a saját üzenetek törlését", + "name": "Saját üzeneteim megtartása" + }, + "auto_purge": { + "name": "Automatikus tisztítás", + "description": "Automatikusan törli a megadott időnél régebbi gyorsítótárazott üzeneteket" + } + } + }, + "auto_save_messages_in_conversations": { + "name": "Üzenetek automatikus mentése", + "description": "Automatikusan elment minden üzenetet a beszélgetésekben" + }, + "gallery_media_send_override": { + "name": "Galéria Média küldés felülbírálása", + "description": "Meghamisítja a média forrását amikor a gallériából küldöd" + }, + "prevent_story_rewatch_indicator": { + "name": "Megakadályozza a történet újranézésének jelzését", + "description": "Megakadályozza, hogy bárki megtudja, hogy újra megnézted a történetüket" + }, + "bypass_screenshot_detection": { + "name": "Képernyőkép-érzékelés megkerülése", + "description": "Megakadályozza, hogy a Snapchat érzékelje, ha képernyőképet készítesz" + }, + "hide_peek_a_peek": { + "name": "Peek-a-Peek elrejtése", + "description": "Megakadályozza az értesítés elküldését, amikor félig belelapozol egy csevegésbe" + }, + "loop_media_playback": { + "name": "Média lejátszás hurokban", + "description": "Média lejátszási hurok a Snaps / Stories megtekintésekor" + }, + "strip_media_metadata": { + "name": "Média metaadatok eltávolítása", + "description": "A média metaadatainak eltávolítása üzenetként való elküldés előtt" + }, + "call_start_confirmation": { + "name": "Hívásindítás megerősítése", + "description": "Megerősítő párbeszédpanel megjelenítése hívás indításakor" + }, + "prevent_message_sending": { + "name": "Üzenetküldés megakadályozása", + "description": "Megakadályozza bizonyos típusú üzenetek küldését" + }, + "half_swipe_notifier": { + "name": "Fél húzás értesítő", + "description": "Értesít, ha valaki félig belecsapódik egy beszélgetésbe", + "properties": { + "min_duration": { + "name": "Minimális időtartam", + "description": "A fél áthúzás minimális időtartama (másodpercben)" + }, + "max_duration": { + "name": "Maximális időtartam", + "description": "A félbehúzás maximális időtartama (másodpercben)" + } + } + }, + "bypass_message_retention_policy": { + "description": "Megakadályozza az üzenetek törlését azok megtekintése után", + "name": "Üzenetmegőrzési irányelvek megkerülése" + }, + "bypass_message_action_restrictions": { + "name": "Üzenetműveleti korlátozások megkerülése", + "description": "Lehetővé teszi, hogy reagálj egy snapre anélkül, hogy megnyitottad volna, vagy hogy elmentsd a menthetetlen üzenetet" + }, + "remove_groups_locked_status": { + "name": "Csoportok zárolt státuszának eltávolítása", + "description": "Lehetővé teszi a csoportinformációk megtekintését, miután kirúgták" + }, + "auto_mark_as_read": { + "name": "Automatikus megjelölés olvasottnak", + "description": "Automatikusan megjelöli az üzeneteket/snap-eket olvasottként, még akkor is, ha a Láthatatlanság mód be van kapcsolva" + }, + "friend_mutation_notifier": { + "name": "Barát Módosítás Értesítő", + "description": "Értesít, amikor valami változik egy barát profiljában" + }, + "unlimited_conversation_pinning": { + "description": "Engedélyezi, hogy végtelen mennyiségű beszélgetést kitűzz helyileg", + "name": "Korlátlan beszélgetés kitűzés" + } + }, + "description": "Változtasd meg a barátaiddal való kapcsolattartásodat" + }, + "global": { + "name": "Globális", + "properties": { + "snapchat_plus": { + "name": "Snapchat Plusz", + "description": "Engedélyezi a Snapchat Plusz funkciókat\nNéhány szerver oldali funkció lehetséges hogy nem működik" + }, + "auto_updater": { + "name": "Automatikus frissítő", + "description": "Automatikusan keres új frissítéseket" + }, + "disable_metrics": { + "name": "Mérések letiltása", + "description": "Blokkolja az elemző adatküldést a Snapchat számára" + }, + "block_ads": { + "name": "Hirdetések Blokkolása", + "description": "Megakadályozza a reklámok megjelenítését" + }, + "bypass_video_length_restriction": { + "name": "Videóhossz-korlátozás megkerülése", + "description": "Egyetlen: egyetlen videó küldése\nOsztás: a videók szétválasztása szerkesztés után" + }, + "disable_google_play_dialogs": { + "name": "A Google Play Szolgáltatások Párbeszédablakainak Letiltása", + "description": "Megakadályozza a Google Play Szolgáltatások elérhetőségére vonatkozó párbeszédablakok megjelenítését" + }, + "disable_snap_splitting": { + "name": "Snap szétválasztás kikapcsolása", + "description": "Megakadályozza a Snap-ek több részre történő szétválasztását\nA képek amiket küldesz videók lesznek" + }, + "disable_confirmation_dialogs": { + "name": "Megerősítő ablakok letiltása", + "description": "Automatikusan megerősíti a kiválasztott műveleteket" + }, + "spotlight_comments_username": { + "description": "Megjeleníti a szerző felhasználónevét a Spotlight hozzászólásokban", + "name": "Spotlight hozzászólások felhasználónév" + }, + "better_location": { + "description": "Javítja a Snapchaten a helyzeted", + "name": "Jobb helyzet", + "properties": { + "spoof_location": { + "name": "Helyzet hamisítása", + "description": "Átírja a tartózkodási helyedet egy megadott helyhez" + }, + "coordinates": { + "name": "Koordináták", + "description": "Az átírt hely koordinátáinak beállítása" + }, + "always_update_location": { + "name": "Mindig frissítse a helyet", + "description": "Kényszerítsd a Snapchatet a helyfrissítésre akkor is, ha nem érkezik GPS-adat" + }, + "suspend_location_updates": { + "name": "Helyszínfrissítések felfüggesztése", + "description": "Megakadályozza, hogy a térkép frissítéseket kapjon tőled" + }, + "spoof_battery_level": { + "name": "Akkumulátor szint átírása", + "description": "Átírja a készülék akkumulátorának szintjét a térképen\nAz értéknek 0 és 100 között kell lennie" + }, + "spoof_headphones": { + "name": "Hamisított fejhallgató", + "description": "Hazudik a zenehallgatás státuszáról a térképen" + }, + "walk_radius": { + "description": "Random ezen a területen belül fogsz sétálni (láb/ft)", + "name": "Séta körzet" + } + } + }, + "disable_story_sections": { + "description": "Eltávolítja a szakaszokat a Sztorik oldalról\nA megfelelő működéshez frissítésre lehet szükség", + "name": "Sztori részek letiltása" + }, + "disable_permission_requests": { + "name": "Engedélykérelmek letiltása", + "description": "Megakadályozza, hogy a Snapchat bizonyos engedélyeket kérjen" + }, + "disable_memories_snap_feed": { + "name": "Emlékek Snap Feed letiltása", + "description": "Megakadályozza, hogy a Snapchat megjelenítse a legutóbbi emlékeket, amikor a kamerában felfelé húzza a lapot" + }, + "default_volume_controls": { + "name": "Alapértelmezett hangerőszabályozók", + "description": "Kényszeríti a Snapchatet a rendszer hangerőszabályzóinak használatára" + }, + "default_video_playback_rate": { + "name": "Alapértelmezett videó lejátszási sebesség", + "description": "A videók lejátszásának alapértelmezett sebességének beállítása\nAz értéknek 0,1 és 4,0 között kell lennie" + }, + "video_playback_rate_slider": { + "name": "Videó lejátszási sebesség csúszka", + "description": "Hozzáad egy csúszkát az opera kontextus menüjébe a videó lejátszási sebesség megváltoztatásához\nMegjegyzés: A módosítások csak a következő videókra vonatkoznak" + }, + "hide_active_music": { + "name": "Aktív zene elrejtése", + "description": "Megakadályozza, hogy a Snapchat megtudja, hogy éppen zenét hallgatsz\nEz lehetővé teszi, hogy zenehallgatás közben is készíthess pillanatképeket a vezérlő hangerőgombok segítségével" + }, + "media_upload_quality": { + "properties": { + "disable_image_compression": { + "description": "Letiltja a kép tömörítést, amikor feltöltesz egy fájlt", + "name": "Kép tömörítés letiltása" + }, + "force_video_upload_source_quality": { + "name": "Eredeti videóminőség feltöltésének kényszerítése", + "description": "A Snapchatet kényszeríti, hogy a forrással megegyező minőségben töltse fel\nTartsd észben, hogy ezzel az opcióval nem törlődnek a metaadatok a fájból" + }, + "custom_image_upload_format": { + "name": "Egyedi kép feltöltési formátum", + "description": "Egyedi kép kiterjesztést használ feltöltéshez\nVálassz egy veszteségmentes formátumot (pl PNG) a legjobb minőségért" + } + }, + "description": "Felülírja a média feltöltés minőségét", + "name": "Feltöltési minőség" + }, + "disable_custom_tabs": { + "name": "Egyedi lapok letiltása", + "description": "A linkeket inkább az appokban nyitja meg, mint a böngészőben" + }, + "disable_telecom_framework": { + "name": "Telecom Framework letiltása", + "description": "Megakadályozza, hogy a Snapchat használja az Android Telecom framework-öt\nEz lehetővé teszi, hogy hívás közben zenét hallgass" + } + }, + "description": "Globális Snapchat beállítások módosítása" + }, + "rules": { + "name": "Szabályok", + "description": "Automatikus funkciók kezelése egyes személyek számára" + }, + "camera": { + "name": "Kamera", + "properties": { + "black_photos": { + "name": "Fekete fotók", + "description": "A rögzített fényképek fekete háttérrel való helyettesítése\nA videókat nem érinti" + }, + "hevc_recording": { + "description": "HEVC (H.265) kodeket használ videofelvételhez", + "name": "HEVC felvétel" + }, + "force_camera_source_encoding": { + "description": "Kényszeríti a kamera forráskódolását", + "name": "Kamera forráskódolás kikényszerítése" + }, + "disable_cameras": { + "name": "Kamera letiltása", + "description": "Megakadályozza, hogy a Snapchat használja a kiválasztott kamerákat" + }, + "override_front_resolution": { + "description": "Felülbírálja az előlapi kamera felbontását", + "name": "Előlapi felbontás felülbírálása" + }, + "front_custom_frame_rate": { + "name": "Egyéni előlapi képkocka sebesség", + "description": "Felülírja az előlapi kamera képkocka sebességét" + }, + "custom_resolution": { + "name": "Egyéni felbontás", + "description": "Egyéni kamera felbontás beállítása, szélesség x magasság (pl. 1920x1080).\nAz egyéni felbontásnak támogatottnak kell lennie az eszközön" + }, + "override_back_resolution": { + "name": "Hátlapi felbontás felülbírálása", + "description": "Felülírja a kamera felbontását a hátlapi kamera esetében" + }, + "back_custom_frame_rate": { + "name": "Egyéni hátlapi képkocka sebesség", + "description": "Felülírja az hátlapi kamera képkocka sebességét" + }, + "immersive_camera_preview": { + "name": "Magával ragadó előnézet", + "description": "Megakadályozza, hogy a Snapchat levágja a kamera előnézetét\nEz egyes készülékeken a kamera villogását okozhatja" + } + }, + "description": "Igazítsd a megfelelő beállításokat a tökéletes felvételhez" + }, + "streaks_reminder": { + "properties": { + "remaining_hours": { + "name": "Hátralévő idő", + "description": "Az értesítés megjelenítéséig hátralévő idő (órákban)" + }, + "group_notifications": { + "name": "Csoportos értesítések", + "description": "Értesítések csoportosítása egyetlen értesítésbe" + }, + "interval": { + "name": "Intervallum", + "description": "Az egyes emlékeztetők közötti időköz (órákban)" + } + }, + "description": "Rendszeresen értesít a sorozataidról", + "name": "Sorozat emlékeztető" + }, + "experimental": { + "name": "Kísérleti", + "description": "Kísérleti funkciók", + "properties": { + "native_hooks": { + "properties": { + "disable_bitmoji": { + "name": "Bitmoji kikapcsolása", + "description": "Barátok Bitmoji-jának kikapcsolása" + }, + "composer_hooks": { + "properties": { + "bypass_camera_roll_limit": { + "name": "Kameragörgő korlát kikerülése", + "description": "Növeli a kameragörgőről küldhető média maximális mennyiségét" + }, + "composer_console": { + "description": "Lehetővé teszi JavaScript kód végrehajtását a Composerben (csak arm64)", + "name": "Összetevő Konzol" + }, + "composer_logs": { + "name": "Összetevő Naplók", + "description": "A Composer konzolnaplóit átirányítja a SnapEnhance felé" + }, + "show_first_created_username": { + "name": "Első felhasználónév megjelenítése", + "description": "Megjeleníti, hogy milyen felhasználónévvel regisztrált a profilján" + } + }, + "name": "Összetevő Horgok", + "description": "Kód befecskendezése a Composer keresztplatformú UI keretrendszerbe" + }, + "custom_emoji_font": { + "name": "Egyedi emoji betűtípus", + "description": "Engedélyezi az egyedi emoji betűtípust. Csak .ttf fájlokkal működik" + } + }, + "name": "Natív hookok", + "description": "Nem biztonságos funkciók, amelyek a Snapchat natív kódjához kapcsolódnak" + }, + "spoof": { + "name": "Hamisítás", + "description": "Meghamisít számos információt rólad", + "properties": { + "play_store_installer_package_name": { + "description": "Felülírja a telepítőcsomag nevét com.android.vending-re", + "name": "Play áruház telepítő csomag neve" + }, + "remove_mock_location_flag": { + "description": "Megakadályozza, hogy a Snapchat felismerje a Mock helyét", + "name": "Távolítsa el a Mock Location Flag-et" + }, + "remove_vpn_transport_flag": { + "name": "VPN szállítási zászló eltávolítása", + "description": "Megakadályozza, hogy a Snapchat felismerje a VPN-eket" + } + } + }, + "infinite_story_boost": { + "name": "Végtelen történet Boost", + "description": "Történet Boost limit megkerülése" + }, + "e2ee": { + "name": "Végpontok közötti titkosítás", + "description": "Titkosítja az üzeneteidet AES-el egy megosztott titkos kulcsot használva\nBizonyosodj meg róla hogy lementsd a kulcsodat egy biztonságos helyre!", + "properties": { + "encrypted_message_indicator": { + "name": "Titkosított Üzenet Jelző", + "description": "Hozzáad egy 🔒 emoji-t a titkosított üzenetek mellé" + }, + "force_message_encryption": { + "name": "Üzenet titkosítás kényszerítése", + "description": "Csak akkor akadályozza meg a titkosított üzenetek küldését olyan személyeknek, akiknek nincs engedélyezve az E2E titkosítás, ha több beszélgetés van kiválasztva" + } + } + }, + "hidden_snapchat_plus_features": { + "name": "Engedélyezi a rejtett Snapchat Plusz funkciókat", + "description": "Engedélyezi a még nem megjelent/béta Snapchat Plusz funkciókat\nRégebbi Snapchat verziókon lehetséges hogy nem működik" + }, + "convert_message_locally": { + "name": "Üzenet helyi átalakítása", + "description": "Átalakítja a snapeket külső média helyi csevegésre. Ez a chat letöltés kontextusmenüjében jelenik meg" + }, + "meo_passcode_bypass": { + "description": "A My Eyes Only jelszó megkerülése\nEz csak akkor működik, ha a jelszót korábban helyesen adtad meg", + "name": "My Eyes Only jelszó megkerülése" + }, + "no_friend_score_delay": { + "name": "Nincs Friend Score késleltetés", + "description": "Eltávolítja a késleltetést a Friends Score megtekintésekor" + }, + "call_recorder": { + "name": "Hívásrögzítő", + "description": "Automatikusan rögzíti a hanghívásokat" + }, + "edit_message": { + "description": "Lehetővé teszi az üzenetek szerkesztését a beszélgetésekben", + "name": "Üzenetek szerkesztése" + }, + "media_file_picker": { + "name": "Média fájlválasztó", + "description": "Lehetővé teszi, hogy bármelyik videó/hangfájlt kiválaszd a galériából" + }, + "story_logger": { + "description": "A barátok sztorijainak története", + "name": "Sztori naplózó" + }, + "account_switcher": { + "name": "Fiókváltó", + "properties": { + "auto_backup_current_account": { + "name": "Automatikus mentés jelenlegi fióknál", + "description": "Automatikusan biztonsági mentést készít az aktuális fiókról kijelentkezéskor vagy fiókváltáskor" + } + }, + "description": "Lehetővé teszi a fiókok közötti váltást kijelentkezés nélkül\nA menü megnyitásához nyomd meg hosszan a keresés ikonját a Bitmoji profilod mellett\nMegjegyzés: ez a funkció kísérleti jellegű, és a jövőben valószínűleg változni fog" + }, + "add_friend_source_spoof": { + "name": "Barát forrás hozzáaadásának átírásának", + "description": "Meghamisítja a Barátkérés forrását" + }, + "prevent_forced_logout": { + "name": "Kényszerített kijelentkezés megakadályozása", + "description": "Megakadályozza, hogy a Snapchat kijelentkezzen, amikor egy másik eszközön jelentkezel be" + }, + "app_lock": { + "name": "App Zár", + "description": "Megakadályozza a Snapchat hozzáférését jelszó nélkül", + "properties": { + "lock_on_resume": { + "name": "Zár a folytatásnál", + "description": "Az alkalmazás zárolása annak újbóli megnyitásakor" + } + } + }, + "custom_streaks_expiration_format": { + "name": "Egyedi sorozat lejárati formátum", + "description": "Egyedi sorozat lejárati formátum\n\nElérhető változók:\n- %c: Sorozatok Száma\n- %e: Homokóra Emoji\n- %d: Napok\n- %h: Órák\n- %m: Perc\n- %s: Másodperc\n- %w: Hátralévő Idő" + }, + "best_friend_pinning": { + "name": "Legjobb barát kitűzés", + "description": "Engedi, hogy megjelöld legeslegjobb barátodként. Fontos: Csak te látod" + }, + "cof_experiments": { + "name": "COF kísérletek", + "description": "Engedélyezi a kiadatlan/béta Snapchat funkciókat" + }, + "context_menu_fix": { + "name": "Kontextus menü javítás", + "description": "Próbálja megjavítani a Friend Feed menüt, mivel ha a készülék offline állapotban van, nem jelenik meg megfelelően" + } + } + }, + "scripting": { + "properties": { + "developer_mode": { + "name": "Fejlesztői mód", + "description": "Megjeleníti a hibakeresési információkat a Snapchat felhasználói felületén" + }, + "integrated_ui": { + "name": "Integrált UI", + "description": "Lehetővé teszi, hogy a szkriptek egyéni UI komponenseket adjanak a Snapchathez" + }, + "module_folder": { + "name": "Modul mappa", + "description": "A mappa, ahol a szkriptek találhatók" + }, + "auto_reload": { + "name": "Automatikus újratöltés", + "description": "Automatikusan újratölti a szkripteket, amikor azok megváltoznak" + }, + "disable_log_anonymization": { + "name": "Napló anonimizálás kikapcsolása", + "description": "Letiltja a naplók anonimizálását" + } + }, + "description": "Egyéni szkriptek futtatása a SnapEnhance bővítéséhez", + "name": "Szkriptelés" + }, + "friend_tracker": { + "name": "Barát figyelő", + "properties": { + "allow_running_in_background": { + "name": "Futás a háttérben engedélyezése", + "description": "Engedi, hogy a követő fusson a háttérben. Megjegyzés: Ez jelentősen meríti az akkumulátorodat" + }, + "record_messaging_events": { + "description": "Feljegyzi az üzenet eventeket, mint snapchat megnyitása, üzenet elolvasása, stb.", + "name": "Figyeli az üzenet eventeket" + }, + "auto_purge": { + "name": "Automatikus tisztítás", + "description": "Automatikusan törli a gyorsítótárazott eseményeket és régebbi egy adott időnél" + } + }, + "description": "Figyeli a barátaid tevékenységét Snapchaten" + } + }, + "options": { + "app_appearance": { + "always_light": "Mindig világos", + "always_dark": "Mindig sötét" + }, + "friend_feed_menu_buttons": { + "auto_download": "⬇️ Automatikus letöltés", + "auto_save": "💬 Üzenetek automatikus mentése", + "stealth": "👻 Lopakodó üzemmód", + "conversation_info": "👤 Beszélgetés információk", + "e2e_encryption": "🔒 Végpontok közötti titkosítás használata", + "unsaveable_messages": "⬇️ Nem menthető üzenetek", + "mark_snaps_as_seen": "👀 Snapek megjelölése látottként", + "mark_stories_as_seen_locally": "👀 Snapek megjelölése látottként helyileg", + "auto_open_snaps": "📷 Automatikus Snaps Megnyitás" + }, + "auto_download_sources": { + "friend_snaps": "Barát Snap-ek", + "friend_stories": "Barát történetek", + "public_stories": "Nyilvános történetek", + "spotlight": "Spotlight" + }, + "logging": { + "started": "Elkezdődött", + "success": "Siker", + "progress": "Előrehaladás", + "failure": "Sikertelen" + }, + "notifications": { + "chat_screenshot": "Képernyőkép", + "chat_screen_record": "Képernyőfelvétel", + "snap_replay": "Snap újrajátszás", + "chat": "Chat", + "chat_reply": "Chat Válasz", + "snap": "Snap", + "typing": "Gépel", + "stories": "Történetek", + "initiate_audio": "Bejövő hívás", + "abandon_audio": "Nem fogadott hívás", + "initiate_video": "Bejövő videóhívás", + "abandon_video": "Nem fogadott videóhívás", + "chat_reaction": "DM reakció", + "group_chat_reaction": "Csoportos reakció", + "camera_roll_save": "Kamera tekercs mentése", + "speaking": "Beszél" + }, + "gallery_media_send_override": { + "ORIGINAL": "Eredeti", + "SNAP": "Snap", + "NOTE": "Hangüzenet", + "always_ask": "Mindig kérdezze meg" + }, + "hide_ui_components": { + "hide_chat_call_buttons": "Hívás gombok eltávolítása", + "hide_voice_record_button": "Hangfelvétel gomb eltávolítása", + "hide_profile_call_buttons": "Profil hívógombok eltávolítása", + "hide_unread_chat_hint": "Olvasatlan csevegési utalás eltávolítása", + "hide_stickers_button": "Matricák gomb eltávolítása", + "hide_live_location_share_button": "Élő helymegosztó gomb eltávolítása", + "hide_post_to_story_buttons": "A Snap elküldése előtti Post to Story gombok eltávolítása" + }, + "home_tab": { + "map": "Térkép", + "chat": "Chat", + "camera": "Kamera", + "discover": "Felfedezés", + "spotlight": "Spotlight" + }, + "disable_story_sections": { + "friends": "Barátok", + "following": "Követve", + "discover": "Felfedezés" + }, + "edit_text_override": { + "bypass_text_input_limit": "Szövegbeviteli korlát megkerülése", + "multi_line_chat_input": "Többsoros csevegés bemenet" + }, + "old_bitmoji_selfie": { + "2d": "2D bitmoji", + "3d": "3D bitmoji" + }, + "disable_confirmation_dialogs": { + "remove_friend": "Barát eltávolítása", + "block_friend": "Barát letiltása", + "ignore_friend": "Barát ignorálása", + "clear_conversation": "Beszélgetés törlése a Friend Feedből", + "hide_friend": "Barát elrejtése", + "hide_conversation": "Beszélgetés elrejtése", + "erase_message": "Üzenet Törlése" + }, + "auto_purge": { + "1_month": "1 hónap", + "3_months": "3 hónap", + "6_months": "6 hónap", + "3_hours": "3 óra", + "6_hours": "6 óra", + "12_hours": "12 óra", + "1_day": "1 nap", + "3_days": "3 nap", + "1_week": "1 hét", + "2_weeks": "2 hét", + "never": "Soha", + "1_hour": "1 óra" + }, + "bypass_video_length_restriction": { + "split": "Szétválasztott média", + "single": "Egyetlen média" + }, + "disable_permission_requests": { + "read_contacts": "Névjegyek elolvasása", + "camera": "Kamera", + "notifications": "Értesítések", + "read_media_images": "Médiaképek olvasása", + "nearby_devices": "Közeli eszközök", + "phone_calls": "Telefonhívások", + "read_media_video": "Média videó olvasása", + "microphone": "Mikrofon", + "location": "Helymeghatározás" + }, + "message_indicators": { + "encryption_indicator": "Hozzáad egy 🔒 ikont a csak neked küldött üzenetek mellé", + "director_mode_indicator": "Hozzáad egy ✏️ ikont a snaphez, ha azokat rendezői módban küldték el, amivel galériaképeket lehet snapeket elküldeni", + "platform_indicator": "Hozzáadja a platform ikonját, amelyről a médiát küldték (pl. Android, iOS, Web)", + "location_indicator": "Hozzáad egy 📍 ikont a snapekhez, ha a helymeghatározással lett elküldve", + "ovf_editor_indicator": "Jelzi, ha egy snapet küldtek az OVF szerkesztő segítségével" + }, + "hide_story_suggestions": { + "hide_my_stories": "Sztorijaim elrejtése", + "hide_suggested_friend_stories": "Javasolt barát sztorik elrejtése" + }, + "strip_media_metadata": { + "remove_audio_note_duration": "Hangüzenet időtartamának eltávolítása", + "remove_audio_note_transcript_capability": "Hangüzenet átírási képesség eltávolítása", + "hide_extras": "Extrák elrejtése (pl. említések)", + "hide_caption_text": "Képaláírás elrejtése", + "hide_snap_filters": "Snap szűrők elrejtése" + }, + "auto_reload": { + "snapchat_only": "Csak Snapchat", + "all": "Összes (Snapchat + SnapEnhance)" + }, + "disable_cameras": { + "front": "Előlapi kamera", + "back": "Hátlapi kamera" + }, + "path_format": { + "create_author_folder": "Mappa létrehozása minden szerző számára", + "create_source_folder": "Mappa létrehozása minden médiaforrás típushoz", + "append_hash": "Egyedi hash hozzáadása a fájlnévhez", + "append_source": "Adja hozzá a médiaforrást a fájlnévhez", + "append_username": "Adja hozzá a felhasználónevet a fájl nevéhez", + "append_date_time": "Adja hozzá a dátumot és az időt a fájl nevéhez" + }, + "add_friend_source_spoof": { + "added_by_community": "Közösség szerint", + "added_by_username": "Felhasználónév szerint", + "added_by_mention": "Említés szerint", + "added_by_group_chat": "Csoportos chat szerint", + "added_by_qr_code": "QR kód szerint", + "added_by_quick_add": "Gyors hozzáadásból (nagy esélye a kitiltásnak)" + }, + "auto_mark_as_read": { + "conversation_read": "Az üzenet küldésekor jelölje a beszélgetést olvasottként", + "snap_reply": "Azokat a Snap-eket jelölje olvasottnak, amelyekre válaszol" + }, + "friend_mutation_notifier": { + "birthday_changes": "Értesítés, ha valaki megváltoztatja a születésnapját", + "bitmoji_avatar_changes": "Értesítés, ha valaki megváltoztatja a Bitmoji avatarát", + "bitmoji_scene_changes": "Értesítés, ha valaki megváltoztatja a Bitmoji jelenetét", + "remove_friend": "Értesítés, ha valaki eltávolít téged barátként", + "bitmoji_selfie_changes": "Értesítés, ha valaki megváltoztatja a Bitmoji önarcképét", + "bitmoji_background_changes": "Értesítés, ha valaki megváltoztatja a Bitmoji háttérképét" + } + } + }, + "friend_menu_option": { + "preview": "Előnézet", + "stealth_mode": "Lopakodó Üzemmód", + "auto_download_blacklist": "Automatikus Letöltési Kivételek", + "anti_auto_save": "Automatikus Mentés Megakadályozása", + "mark_stories_as_seen_locally": "Megjelöli a látott sztorikat helyileg", + "mark_snaps_as_seen": "Snapek megjelölése látottként" + }, + "chat_action_menu": { + "preview_button": "Előnézet", + "download_button": "Letöltés", + "delete_logged_message_button": "Naplózott üzenet törlése", + "convert_message": "Üzenet átalakítása", + "edit_message": "Üzenet szerkesztése", + "show_chat_edit_history": "Chat szerkesztési előzmények megjelenítése" + }, + "opera_context_menu": { + "download": "Média letöltése", + "sent_at": "Elküldve {date}", + "created_at": "Létrehozva {date}", + "expires_at": "Lejár {date}", + "media_size": "Média mérete: {size}", + "media_duration": "Média hossza: {duration} mp", + "show_debug_info": "Hibakeresési infók megjelenítése" + }, + "modal_option": { + "profile_info": "Profil Infó", + "close": "Bezár" + }, + "gallery_media_send_override": { + "multiple_media_toast": "Egyszerre csak egy médiát küldhet" + }, + "conversation_preview": { + "streak_expiration": "Lejár {day} nap {hour} óra {minute} perc múlva", + "total_messages": "Összes kapott/küldött üzenetek: {count}", + "title": "Előnézet", + "unknown_user": "Ismeretlen felhasználó", + "no_messages": "Nincsenek üzenetek!" + }, + "profile_info": { + "title": "Profil Infó", + "mutable_username": "Némítható felhasználónév", + "display_name": "Megjelenített név", + "added_date": "Hozzáadás dátuma", + "birthday": "Születésnap : {month} {day}", + "friendship": "Barátság", + "add_source": "Forrás hozzáadása", + "snapchat_plus": "Snapchat Plusz", + "snapchat_plus_state": { + "subscribed": "Feliratkozva", + "not_subscribed": "Nincs feliratkozás" + }, + "hidden_birthday": "Születésnap : Rejtett", + "first_created_username": "Először létrehozott felhasználónév" + }, + "chat_export": { + "dialog_negative_button": "Mégsem", + "dialog_positive_button": "Exportálás", + "exported_to": "Exportálva ide {path}", + "exporting_chats": "Üzenetek exportálása...", + "processing_chats": "{amount} beszélgetések feldolgozása...", + "export_fail": "Nem sikerült exportálni a beszélgetést {conversation}", + "writing_output": "Kimenet írása...", + "finished": "Kész! Most már ezt bezárhatod.", + "no_messages_found": "Nincsenek üzenetek!", + "exporting_message": "Expotálás {conversation}...", + "exporter_dialog": { + "message_type_filter_title": "Üzenetek szűrése típus szerint", + "select_conversations_title": "Beszélgetések kiválasztása", + "text_field_selection": "{amount} kiválasztva", + "text_field_selection_all": "Összes", + "export_file_format_title": "Exportálási fájlformátum", + "download_medias_title": "Médiák letöltése", + "amount_of_messages_title": "Üzenetek száma (hagyd üresen az összesért)" + } + }, + "button": { + "ok": "OK", + "positive": "Igen", + "negative": "Nem", + "cancel": "Mégsem", + "open": "Megnyitás", + "download": "Letöltés" + }, + "profile_picture_downloader": { + "button": "Profilkép letöltése", + "title": "Profilkép letöltő", + "avatar_option": "Avatár", + "background_option": "Háttér" + }, + "download_processor": { + "attachment_type": { + "snap": "Snap", + "sticker": "Matrica", + "external_media": "Külső média", + "note": "Megjegyzés", + "original_story": "Eredeti történet", + "gif": "GIF" + }, + "select_attachments_title": "Válaszd ki a csatolmányokat", + "download_started_toast": "A letöltés megkezdődött", + "unsupported_content_type_toast": "A tartalom típusa nem támogatott!", + "failed_no_longer_available_toast": "A média már nem érhető el", + "no_attachments_toast": "Nem találhatóak csatolmányok!", + "already_queued_toast": "A média már várólistán van!", + "already_downloaded_toast": "Ez már le lett töltve!", + "download_toast": "Letöltés {path}...", + "processing_toast": "Feldolgozás {path}...", + "failed_generic_toast": "Letöltés sikertelen", + "failed_to_create_preview_toast": "Előnézet létrehozása sikertelen", + "failed_processing_toast": "Nem sikerült feldolgozni {error}", + "failed_gallery_toast": "Nem sikerült lementeni a galériába {error}", + "dash_dialog": { + "download_all": "Összes letötlése", + "segment_text": "Szegmens {from} - {to}", + "title": "Dash média letöltése" + }, + "dash_no_chapter": "Nincsenek fejezetek" + }, + "streaks_reminder": { + "notification_title": "Sorozatok", + "notification_text": "El fogod veszíteni a sorozatodat {friend}-el/al {hoursLeft} múlva" + }, + "material3_strings": { + "date_input_invalid_not_allowed": "Helytelen dátum", + "date_range_input_invalid_range_input": "Helytelen dátum intervallum", + "date_range_picker_day_in_range": "Kiválasztott", + "date_input_invalid_for_pattern": "Helytelen dátum", + "date_picker_today_description": "Ma", + "date_input_invalid_year_range": "Helytelen év", + "date_range_picker_start_headline": "Tőle", + "date_range_picker_title": "Dátumtartomány kiválasztása", + "date_picker_switch_to_calendar_mode": "Naptár", + "date_range_picker_end_headline": "Neki", + "date_picker_switch_to_input_mode": "Bemenet", + "date_range_picker_scroll_to_next_month": "Következő hónap", + "date_range_picker_scroll_to_previous_month": "Előző hónap" + }, + "media_download_source": { + "chat_media": "Beszélgetés média", + "merged": "Egyesített", + "story_logger": "Sztori naplózó", + "none": "Nincs", + "story": "Sztory", + "pending": "Függőben", + "spotlight": "Reflektorfény", + "message_logger": "Üzenetnaplózó", + "voice_call": "Hanghívás", + "profile_picture": "Profilkép", + "public_story": "Nyilvános sztori" + }, + "actions": { + "clean_snapchat_cache": { + "name": "Snapchat gyorsítótárának törlése", + "description": "Kitörli a Snapchat gyorsítótárját" + }, + "manage_friend_list": { + "name": "Barátlista kezelése", + "description": "Barátaid listájának importálása/exportálása biztonsági mentéskor" + }, + "export_chat_messages": { + "description": "Beszélgetési üzenetek exportálása JSON/HTML/TXT fájlba", + "name": "Chat üzenetek exportálása" + }, + "bulk_messaging_action": { + "description": "Olyan műveleteket végez, mint a barátok törlése vagy a beszélgetések tömeges törlése", + "name": "Tömeges üzenetküldési művelet" + }, + "regen_mappings": { + "name": "Leképezések újragenerálása", + "description": "Manuálisan regenerálja a leképezéseket" + }, + "change_language": { + "name": "Nyelv módosítása", + "description": "A SnapEnhance nyelvének módosítása" + }, + "export_memories": { + "name": "Emlékek exportálása", + "description": "Emlékek exportálása ZIP fájlba" + }, + "file_imports": { + "name": "Fájl importálások", + "description": "Importálj fájlokat, hogy a Snapchatben használd őket" + }, + "friend_tracker": { + "description": "Figyeld a barátaidat Snapchaten", + "name": "Barát figyelő" + }, + "logger_history": { + "name": "Naplózó előzmények", + "description": "Nézd meg az előményeket a naplózott üzenetekről" + } + }, + "content_type": { + "STICKER": "Matrica", + "STATUS_COUNTDOWN": "Visszaszámlálás", + "TINY_SNAP": "Apró Snap", + "STATUS_CONVERSATION_CAPTURE_RECORD": "Képernyőfelvétel", + "LOCATION": "Helyszín", + "NOTE": "Hangüzenet", + "CHAT": "Csevegés", + "SNAP": "Snap", + "STATUS": "Állapot", + "STATUS_CALL_MISSED_VIDEO": "Nem fogadott videóhívás", + "FAMILY_CENTER_ACCEPT": "Családi központ elfogadás", + "STATUS_PLUS_GIFT": "Status Plus ajándék", + "MAP_REACTION": "Térkép reakció", + "EXTERNAL_MEDIA": "Külső média", + "STATUS_CONVERSATION_CAPTURE_SCREENSHOT": "Képernyőkép", + "STATUS_CALL_MISSED_AUDIO": "Nem fogadott hanghívás", + "CREATIVE_TOOL_ITEM": "Kreatív eszköz elem", + "FAMILY_CENTER_INVITE": "Családi központ meghívó", + "FAMILY_CENTER_LEAVE": "Családi központ elhagyás", + "STATUS_SAVE_TO_CAMERA_ROLL": "Mentve a képeid közé", + "LIVE_LOCATION_SHARE": "Élő helymegosztás", + "SHARE": "Megosztás" + }, + "better_notifications": { + "button": { + "download": "Letöltés", + "mark_as_read": "Megjelölés olvasottként", + "reply": "Válasz" + } + }, + "half_swipe_notifier": { + "notification_content_group": "{friend} épp most ugrott be félig a {group}, {duration} másodpercre", + "notification_channel_name": "Fél húzás", + "notification_content_dm": "{friend} épp most ugrott be félig a chatedbe {duration} másodpercre" + }, + "mark_as_seen": { + "no_unseen_snaps_toast": "Nem találtunk nem látott Snapeket!", + "seen_toast": "Megjelölve látottként!", + "unseen_toast": "Megjelölve nem látottként!", + "already_seen_toast": "Már meg lett jelölve látottként!", + "already_unseen_toast": "Már meg lett jelölve nem látottként!" + }, + "friendship_link_type": { + "mutual": "Kölcsönös", + "outgoing": "Kimenő", + "deleted": "Törölve", + "blocked": "Letiltva", + "suggested": "Javasolt", + "incoming": "Bejövő", + "incoming_follower": "Bejövő követő", + "following": "Követve" + }, + "bulk_messaging_action": { + "selection_dialog_continue_button": "Folytatás", + "progress_status": "{index} feldolgozása {total}-ból", + "confirmation_dialog": { + "message": "Ez az összes kiválasztott barátod érinti. Ezt a műveletet nem lehet visszacsinálni.", + "title": "Biztos vagy benne?" + }, + "choose_action_title": "Művelet kiválasztása", + "actions": { + "remove_friends": "Barátok eltávolítása", + "clear_conversations": "Világos beszélgetések" + } + }, + "call_start_confirmation": { + "dialog_title": "Hívás indítása", + "dialog_message": "Biztos, hogy hívást akarsz indítani?" + }, + "scopes": { + "friend": "Barát", + "group": "Csoport" + }, + "end_to_end_encryption": { + "toolbox": { + "shared_key_fingerprint": "Az ujjlenyomatod:\n\n{fingerprint}\n\nEllenőrizd, hogy egyezik-e a barátod ujjlenyomatával!", + "no_shared_key": "Ezzel a barátoddal még nincs közös titkotok. Kattints az alábbi gombra, hogy új titok létrehozását kezdeményezd.", + "initiate_exchange_button": "Kulcscsere kezdeményezése" + }, + "confirmation_dialogs": { + "confirmation_1": "FIGYELMEZTETÉS: Ez felülírja a meglévő kulcsot. Elveszted a hozzáférést az összes titkosított üzenethez ezzel a barátoddal. Biztos, hogy folytatni akarod?", + "confirmation_2": "TÉNYLEG biztos vagy benne, hogy folytatni akarod? Ez az utolsó esélyed, hogy visszalépj.", + "title": "Végpontok közti titkosítás" + }, + "unencrypted_conversation_send_failure_toast": "Nem küldhetsz titkosított tartalmat titkosított és titkosítatlan beszélgetésekbe egyaránt!", + "accept_public_key_failure_toast": "Nem sikerült elfogadni a publikus kulcsot", + "accept_secret_key_failure_toast": "Nem sikerült elfogadni a titkos kulcsot", + "accept_public_key_button": "Publikus kulcs elfogadása", + "outgoing_pk_message": "Kulcs cserélési kérelem", + "incoming_pk_message": "Kaptál egy publikus kulcs kérelmet. Kattints lejjeb az elfogadáshot.", + "native_hooks_send_failure_toast": "Nem sikerült elküldeni! Kérlek, engedélyezd a Natív hookok használatát a beállításokban.", + "no_participants_to_encrypt_toast": "Nincsenek barátaid ebben a beszélgetésben, akikkel üzeneteket titkosíthatnál!", + "encryption_failed_toast": "Nem sikerült titkosítani az üzenetet! További részletekért nézd meg a logcat-et.", + "accept_public_key_success_toast": "Publikus kulcs elfogadva!", + "accept_secret_key_success_toast": "Siker! Most már küldhetsz és fogadhatsz titkosított üzeneteket ezzel a barátoddal.", + "accept_secret_button": "Titok elfogadása", + "outgoing_secret_message": "Kulcs cserélésre a válasz", + "incoming_secret_message": "A barátod elfogadta a publikus kulcsot. Kattints lejjebb az elfogadáshoz." + }, + "friend_mutation_observer": { + "bitmoji_avatar_changed": "{username} megváltoztatta a Bitmoji avatarát", + "friend_removed": "{username} eltávolított téged barátként", + "birthday_changed": "{username} megváltoztatta a születésnapját: {oldBirthday} -ról {newBirthday} -re", + "bitmoji_scene_changed": "{username} megváltoztatta a Bitmoji-jelenetét", + "notification_channel_name": "Barát Mutáció Megfigyelő", + "birthday_removed": "{username} eltávolította a születésnapját ({birthday})", + "birthday_added": "{username} hozzáadta a születésnapját ({birthday})", + "bitmoji_selfie_changed": "{username} megváltoztatta a Bitmoji önarcképét", + "bitmoji_background_changed": "{username} megváltoztatta a Bitmoji háttérképét" + }, + "biometric_auth": { + "unlock_button": "Feloldás", + "title": "Snapchat feloldása", + "subtitle": "Kérlek, azonosítsd magad a Snapchat feloldásához" + }, + "auto_open_snaps": { + "title": "Automatikus Snaps Megnyitás", + "notification_content": "{count} Snaps megnyitva" + } +} diff --git a/common/src/main/assets/lang/id.json b/common/src/main/assets/lang/id.json index 97432cb2..b8c54cb0 100644 --- a/common/src/main/assets/lang/id.json +++ b/common/src/main/assets/lang/id.json @@ -1,2022 +1,269 @@ { "setup": { "dialogs": { - "select_language": "Pilih Bahasa", - "save_folder": "PurrfectSnap memerlukan izin Penyimpanan untuk mengunduh dan Menyimpan Media dari Snapchat.\nSilakan pilih lokasi tempat media harus diunduh.", - "select_save_folder_button": "Pilih Folder" + "select_language": "Pilih bahasa", + "save_folder": "SnapEnhance memerlukan izin Penyimpanan untuk mengunduh dan Menyimpan Media dari Snapchat.\nSilakan pilih lokasi di mana media harus diunduh.", + "select_save_folder_button": "Pilih folder" }, "mappings": { - "dialog": "Membuat Pemetaan, ini mungkin memakan waktu...", - "generate_failure_no_snapchat": "PurrfectSnap tidak dapat mendeteksi Snapchat, silakan coba instal ulang Snapchat.", + "dialog": "Menghasilkan pemetaan, ini mungkin memakan waktu beberapa saat ...", + "generate_failure_no_snapchat": "SnapEnhance tidak dapat mendeteksi Snapchat, coba instal ulang Snapchat.", "generate_failure": "Terjadi kesalahan saat mencoba membuat pemetaan, silakan coba lagi." }, "permissions": { "dialog": "Untuk melanjutkan, Anda harus memenuhi persyaratan berikut:", "notification_access": "Akses Notifikasi", "battery_optimization": "Optimasi Baterai", - "display_over_other_apps": "Tampilkan di Atas Aplikasi Lain", - "request_button": "Minta" + "display_over_other_apps": "Tampilkan Di Atas Aplikasi Lain", + "request_button": "Meminta" + } + }, + "manager": { + "routes": { + "features": "Fitur", + "home": "Rumah", + "home_settings": "Pengaturan", + "home_logs": "Log", + "social": "Sosial", + "scripts": "Skrip", + "tasks": "Tugas", + "manage_rule_feature": "Kelola fitur aturan", + "manage_scope": "Kelola ruang lingkup", + "file_imports": "Impor file", + "messaging_preview": "Pratinjau", + "better_location": "Lokasi yang lebih baik", + "friend_tracker": "Pelacak teman", + "edit_rule": "Edit aturan", + "logger_history": "Riwayat logger", + "logged_stories": "Cerita yang dicatat", + "theming": "Tema", + "edit_theme": "Edit Tema", + "manage_repos": "Kelola repositori" + }, + "sections": { + "features": { + "disabled": "Lepas", + "export_option": "Ekspor", + "import_option": "Impor", + "reset_option": "Ulang awal" + }, + "better_location": { + "search_bar": "Cari", + "latitude_dialog_hint": "Lintang", + "save_dialog_button": "Simpan" + }, + "home_settings": { + "actions_title": "Aksi", + "debug_title": "Debugg", + "success_toast": "Selesai!", + "export_button": "Ekspor", + "clear_button": "Bersihkan" + }, + "manage_scope": { + "streaks_expiration_text_expired": "Kadaluarsa", + "rules_title": "Aturan" + }, + "home": { + "update_button": "Unduhan" + }, + "social": { + "empty_hint": "(kosong)", + "friends_tab": "Teman²", + "groups_tab": "Grup²" + } + }, + "dialogs": { + "add_friend": { + "category_groups": "Grup", + "category_friends": "Teman-teman", + "search_hint": "Pencarian" + }, + "scripting_warning": { + "title": "Bahaya" + } + } + }, + "features": { + "properties": { + "downloader": { + "properties": { + "ffmpeg_options": { + "properties": { + "threads": { + "name": "Utas" + } + } + } + }, + "name": "Download" + }, + "camera": { + "name": "Kamera" + }, + "rules": { + "name": "Garis" + }, + "scripting": { + "name": "Skrip" + }, + "experimental": { + "properties": { + "spoof": { + "name": "Tipuan" + } + } + }, + "global": { + "properties": { + "better_location": { + "properties": { + "coordinates": { + "name": "Kordinat" + } + } + } + } + } + }, + "options": { + "logging": { + "started": "Dimulai", + "success": "Berhasil", + "progress": "Proses", + "failure": "Kegagalan" + }, + "auto_download_sources": { + "spotlight": "Menyoroti" + }, + "notifications": { + "chat": "Obrolan", + "snap": "snap", + "stories": "Cerita", + "typing": "Mengetik", + "chat_screenshot": "Tangkapan Layar", + "speaking": "Berbicara" + }, + "home_tab": { + "map": "Map", + "chat": "Obrolan", + "spotlight": "Menyoroti", + "camera": "Kamera", + "discover": "Tampilan" + }, + "gallery_media_send_override": { + "SNAP": "snap" + }, + "disable_story_sections": { + "following": "Mengikuti", + "friends": "Teman²", + "discover": "Tampilan" + }, + "disable_permission_requests": { + "location": "Lokasi", + "camera": "Kamera", + "microphone": "Mikropon", + "notifications": "Notifikasi" + }, + "auto_purge": { + "never": "Tidak Pernah" + } } }, "scopes": { "friend": "Teman", "group": "Grup" }, - "manager": { - "routes": { - "tasks": "Tugas", - "features": "Fitur", - "manage_rule_feature": "Kelola Fitur Aturan", - "home": "Beranda", - "home_settings": "Pengaturan", - "home_logs": "Log", - "logger_history": "Riwayat Logger", - "logged_stories": "Cerita yang Dicatat", - "friend_tracker": "Pelacak Teman", - "edit_rule": "Edit Aturan", - "file_imports": "Impor File", - "manage_repos": "Kelola Repositori", - "social": "Sosial", - "manage_scope": "Kelola Cakupan", - "messaging_preview": "Pratinjau", - "scripts": "Skrip", - "better_location": "Lokasi Lebih Baik" - }, - "sections": { - "home": { - "version_title": "v{versionName} · di-fork oleh Eternal", - "update_title": "Pembaruan PurrfectSnap", - "update_content": "Versi {version} tersedia!", - "update_button": "Unduh", - "debug_build_summary_title": "Anda menjalankan build debug dari PurrfectSnap", - "debug_build_summary_content": "Versi {versionName} ({versionCode})", - "debug_build_summary_date": "Tanggal build: {date} ({days} hari yang lalu)", - "quick_actions_title": "Tindakan Cepat", - "download_icon_description": "Unduh", - "completed_icon_description": "Selesai", - "failed_icon_description": "Gagal", - "manage_quick_actions_description": "Kelola Tindakan Cepat", - "quick_actions_icon_description": "Tindakan Cepat", - "add_quick_action_description": "Tambah Tindakan Cepat" - }, - "home_logs": { - "no_logs_hint": "Tidak ada log yang tersedia", - "clear_logs_button": "Hapus Log", - "export_logs_button": "Ekspor Log", - "saving_logs_toast": "Menyimpan log, ini mungkin memakan waktu...", - "saved_logs_success_toast": "Log berhasil disimpan", - "saved_logs_failure_toast": "Gagal menyimpan log" - }, - "home_settings": { - "actions_title": "Tindakan", - "message_logger_title": "Pencatat Pesan", - "debug_title": "Men-debug", - "success_toast": "Selesai!", - "message_logger_summary": "{messageCount} pesan\n{storyCount} cerita", - "export_button": "Ekspor", - "clear_button": "Hapus", - "view_logger_history_button": "Lihat Riwayat Logger", - "updates_title": "Pembaruan", - "auto_update_check": "Periksa pembaruan secara otomatis", - "update_check_frequency": "Frekuensi pemeriksaan pembaruan", - "update_check_frequency_daily": "Harian", - "update_check_frequency_weekly": "Mingguan", - "update_check_frequency_monthly": "Bulanan", - "theme_icon_description": "Tema", - "app_theme_title": "Tema Aplikasi", - "theme_mode_system": "Sistem", - "theme_mode_light": "Terang", - "theme_mode_dark": "Gelap", - "ui_settings_title": "Pengaturan UI", - "haptic_feedback_label": "Umpan Balik Haptik", - "test_mode_label": "Mode Uji (HANYA UNTUK DEBUGGING)", - "disable_feature_loading_label": "Nonaktifkan Pemuatan Fitur", - "disable_auto_mapper_label": "Nonaktifkan Pemeta Otomatis", - "disable_bypass_indicator_label": "Nonaktifkan Indikator Status Bypass", - "update_notification_channel_name": "Pembaruan PurrfectSnap", - "update_notification_channel_description": "Notifikasi untuk pembaruan PurrfectSnap", - "update_notification_title": "Pembaruan PurrfectSnap Tersedia", - "update_notification_text": "Versi %s sekarang tersedia.", - "export_database_failed_toast": "Gagal mengekspor database! {message}", - "clear_messages_failed_toast": "Gagal menghapus pesan! {message}", - "clear_file_failed_toast": "Gagal menghapus file! {message}", - "debug_file_config": "Konfigurasi", - "debug_file_mappings": "Pemetaan", - "debug_file_message_logger": "Pencatat Pesan", - "debug_file_pinned_best_friend": "Sahabat Terbaik yang Disematkan", - "debug_file_native_sig_cache": "Cache Tanda Tangan Asli" - }, - "tasks": { - "no_tasks": "Tidak ada tugas", - "merge_button": "Gabungkan", - "failed_to_open_file": "Gagal membuka file", - "merge_files_toast": "Menggabungkan {count} file", - "remove_selected_tasks_title": "Apakah Anda yakin ingin menghapus tugas yang dipilih?", - "remove_all_tasks_title": "Apakah Anda yakin ingin menghapus semua tugas?", - "delete_files_option": "Hapus juga file", - "remove_selected_tasks_confirm": "Hapus {count} tugas?", - "remove_all_tasks_confirm": "Hapus semua tugas?", - "clear_tasks_description": "Hapus tugas", - "file_not_found_icon_description": "File tidak ditemukan", - "image_icon_description": "Gambar", - "video_icon_description": "Video", - "audio_icon_description": "Audio", - "file_icon_description": "Mengajukan", - "download_icon_description": "Unduh", - "chat_action_icon_description": "Tindakan Obrolan", - "cancel_icon_description": "Batal", - "success_icon_description": "Berhasil", - "failure_icon_description": "Gagal", - "cancelled_icon_description": "Dibatalkan", - "task_status_failure": "Gagal", - "task_status_cancelled": "Dibatalkan" - }, - "features": { - "disabled": "Dinonaktifkan", - "export_option": "Ekspor", - "import_option": "Impor", - "reset_option": "Setel Ulang", - "config_export_success_toast": "Konfigurasi berhasil diekspor", - "config_import_success_toast": "Konfigurasi berhasil diimpor", - "config_import_failure_toast": "Gagal mengimpor konfigurasi {error}", - "config_export_failure_toast": "Gagal mengekspor konfigurasi {error}", - "saved_config_snackbar": "Konfigurasi disimpan", - "older_required": "Fitur ini memerlukan Snapchat v{version} atau lebih lama untuk berfungsi dengan benar", - "newer_required": "Fitur ini memerlukan Snapchat v{version} atau lebih baru untuk berfungsi dengan benar", - "search_button": "Cari" - }, - "manage_rule_feature": { - "disable_state_option": "Dinonaktifkan", - "disable_state_subtext": "Tidak ada teman/grup yang akan terpengaruh", - "whitelist_state_option": "Tidak ada kecuali...", - "whitelist_state_subtext": "Hanya {count} teman/grup yang akan terpengaruh oleh aturan ini", - "whitelist_state_button": "Pilih teman/grup yang diizinkan", - "blacklist_state_option": "Semua orang kecuali...", - "blacklist_state_subtext": "Semua orang kecuali {count} teman/grup akan terpengaruh oleh aturan ini", - "blacklist_state_button": "Pilih teman/grup yang dikecualikan", - "clear_list_button": "Hapus daftar teman/grup", - "dialog_clear_confirmation_text": "Apakah Anda yakin ingin menghapus daftar ini?" - }, - "social": { - "friends_tab": "Teman", - "groups_tab": "Grup", - "empty_hint": "(kosong)", - "streaks_expiration_short": "{hours}j" - }, - "manage_scope": { - "logged_stories_button": "Tampilkan Cerita yang Dicatat", - "e2ee_title": "Enkripsi End-to-End", - "rules_title": "Aturan", - "participants_text": "{count} peserta", - "not_found": "Tidak ditemukan", - "streaks_title": "Streak", - "streaks_length_text": "Panjang: {length}", - "streaks_expiration_text": "Kedaluwarsa dalam {eta}", - "streaks_expiration_text_expired": "Kedaluwarsa", - "reminder_button": "Setel Pengingat", - "delete_scope_confirm_dialog_title": "Apakah Anda yakin ingin menghapus {scope}?", - "notes_placeholder": "Klik untuk menambahkan catatan", - "invalid_key_size_32_bytes": "Ukuran kunci tidak valid (harus 32 byte)", - "successfully_imported_key": "Kunci berhasil diimpor", - "failed_to_import_key": "Gagal mengimpor kunci: {message}", - "export_base64_button": "Ekspor Base64", - "import_base64_button": "Impor Base64" - }, - "logged_stories": { - "story_failed_to_load": "Gagal memuat", - "no_stories": "Tidak ada cerita yang ditemukan", - "save_from_cache_button": "Simpan dari Cache", - "downloaded_to_path": "Diunduh ke {path}", - "download_failed": "Gagal mengunduh: {message}", - "posted_at": "Diposting pada {date}", - "created_at": "Dibuat pada {date}", - "failed_to_open_file": "Gagal membuka file. Periksa log untuk info lebih lanjut", - "failed_to_get_file": "Gagal mendapatkan file" - }, - "messaging_preview": { - "processed_messages_toast": "Memproses {count} pesan", - "processed_messages_text": "Memproses {count} pesan", - "close_button_description": "Tutup", - "bridge_connection_failed": "Gagal terhubung ke jembatan. Pastikan Snapchat berjalan di latar belakang", - "bridge_init_failed": "Gagal menginisialisasi jembatan pesan. Pastikan Snapchat berjalan di latar belakang", - "message_fetch_failed": "Gagal mengambil pesan", - "no_message_hint": "Tidak ada pesan", - "save_selection_option": "Simpan Pilihan", - "save_all_option": "Simpan Semua", - "unsave_selection_option": "Batalkan Penyimpanan Pilihan", - "unsave_all_option": "Batalkan Penyimpanan Semua", - "mark_selection_as_seen_option": "Tandai Snap yang dipilih sebagai telah dilihat", - "mark_all_as_seen_option": "Tandai semua Snap sebagai telah dilihat", - "delete_selection_option": "Hapus Pilihan", - "delete_all_option": "Hapus Semua" - }, - "logger_history": { - "download_started_toast": "Pengunduhan dimulai!", - "download_success_toast": "Diunduh ke {path}", - "download_failed_toast": "Gagal mengunduh {message}", - "edited_at_text": "{message} (diedit pada {date})", - "download_button": "Unduh", - "select_conversation_placeholder": "Pilih percakapan", - "close_button_description": "Tutup", - "search_button_description": "Cari", - "list_friend_format": "Teman {name}", - "list_group_format": "Grup {name}", - "no_more_messages": "Tidak ada pesan lagi", - "reverse_order_checkbox": "Urutan Terbalik", - "chat_attachment": "Lampiran {index}", - "empty_message": "Pesan Obrolan Kosong", - "message_parse_failed": "Gagal mengurai pesan", - "unknown_sender": "Pengirim Tidak Dikenal", - "download_attachment_failed_toast": "Gagal mengunduh lampiran", - "log_header_format": "{username} ({type}) - {date}" - }, - "file_imports": { - "import_file_button": "Impor File", - "file_not_found": "File tidak ditemukan", - "file_import_failed": "Gagal mengimpor file: {error}", - "file_imported": "File berhasil diimpor", - "file_delete_failed": "Gagal menghapus file", - "no_files_hint": "Di sini Anda dapat mengimpor file untuk digunakan di Snapchat. Tekan tombol di bawah untuk mengimpor file." - }, - "better_location": { - "spoofed_coordinates_title": "Lintang {latitude}, Panjang {longitude}", - "save_coordinates_dialog_title": "Simpan Koordinat", - "saved_name_dialog_hint": "Nama yang Disimpan", - "latitude_dialog_hint": "Lintang", - "longitude_dialog_hint": "Bujur", - "save_dialog_button": "Simpan", - "choose_location_button": "Pilih Lokasi", - "teleport_to_friend_button": "Teleportasi ke Teman", - "spoof_location_toggle": "Lokasi Palsu", - "suspend_location_updates": "Tangguhkan Pembaruan Lokasi", - "saved_coordinates_title": "Koordinat yang Disimpan", - "no_saved_coordinates_hint": "Tidak ada koordinat yang disimpan", - "delete_dialog_title": "Hapus Koordinat yang Disimpan", - "delete_dialog_message": "Apakah Anda yakin ingin menghapus koordinat yang disimpan ini?", - "teleport_to_friend_title": "Teleportasi ke Teman", - "search_bar": "Cari", - "no_friends_map": "Tidak ada teman di peta", - "no_friends_found": "Tidak ada teman yang ditemukan", - "edit_location_button_description": "Edit Lokasi", - "add_icon_description": "Tambah", - "edit_icon_description": "Sunting", - "delete_icon_description": "Hapus" - } - }, - "dialogs": { - "add_friend": { - "title": "Tambah Teman atau Grup", - "search_hint": "Cari", - "fetch_error": "Gagal mengambil data", - "category_groups": "Grup", - "category_friends": "Teman", - "participants_text": "{count} peserta", - "search_icon_description": "Cari" - }, - "scripting_warning": { - "title": "Peringatan", - "content": "PurrfectSnap menyertakan alat skrip, yang memungkinkan eksekusi kode yang ditentukan pengguna di perangkat Anda. Gunakan sangat hati-hati dan hanya instal modul dari sumber yang dikenal dan andal. Modul yang tidak sah atau tidak terverifikasi dapat menimbulkan risiko keamanan bagi sistem Anda." - }, - "reset_config": { - "title": "Setel Ulang Konfigurasi", - "content": "Apakah Anda yakin ingin menyetel ulang konfigurasi?", - "success_toast": "Konfigurasi berhasil disetel ulang" - }, - "export_config": { - "title": "Ekspor Data Sensitif?", - "content": "Apakah Anda ingin mengekspor konfigurasi dengan data sensitif? (Seperti koordinat lokasi, dll.)" - }, - "messaging_action": { - "title": "Pilih jenis konten untuk diproses", - "select_all_button": "Pilih Semua" - }, - "file_imports": { - "no_files_settings_hint": "Tidak ada file yang ditemukan. Pastikan Anda telah mengimpor file yang diperlukan di bagian Impor File", - "settings_select_file_hint": "Pilih file yang diimpor" - }, - "quick_actions_dialog": { - "title": "Edit Tindakan Cepat", - "subtitle": "Pilih dan ukur tindakan cepat Anda." - } - }, - "friend_tracker": { - "rules_tab": "Aturan", - "logs_tab": "Log", - "export_dialog_title": "Ekspor", - "bulk_export_button": "Ekspor Massal", - "individual_export_button": "Ekspor Individu", - "invalid_import_type_dialog_title": "Jenis Impor Tidak Valid", - "invalid_import_type_dialog_text": "File yang dipilih tidak kompatibel dengan jenis impor ini. Silakan pilih jenis impor yang benar.", - "import_dialog_title": "Impor", - "bulk_import_button": "Impor Massal", - "individual_import_button": "Impor Individu", - "import_button_description": "Impor", - "export_button_description": "Ekspor", - "export_button": "Ekspor", - "delete_button_description": "Hapus", - "delete_button": "Hapus", - "catalog_button_description": "Katalog", - "catalog_button": "Katalog", - "add_rule_button_description": "Tambah Aturan", - "add_rule_button": "Tambah Aturan", - "no_rules_found": "Tidak ada aturan yang ditemukan", - "empty_rule_name": "(kosong)", - "events_suffix": "peristiwa", - "scopes_suffix": "cakupan", - "select_rule_to_export_title": "Pilih Aturan untuk Diekspor", - "deleted_logs_toast": "Menghapus {count} log", - "delete_logs_dialog_title": "Hapus log?", - "deleting_logs_dialog_text": "Menghapus {count} log...", - "delete_logs_dialog_confirm_text": "Ini akan menghapus log berdasarkan filter saat ini dan kueri pencarian. Tindakan ini tidak dapat dibatalkan.", - "exported_logs_toast": "Log diekspor!", - "export_logs_failed_toast": "Gagal mengekspor log. Periksa logcat untuk detail lebih lanjut.", - "export_logs_dialog_title": "Ekspor log?", - "exporting_logs_dialog_text": "Mengekspor log...", - "export_logs_dialog_confirm_text": "Ini akan mengekspor log berdasarkan filter saat ini dan kueri pencarian.", - "export_as_button": "Ekspor sebagai {type}", - "filters_title": "Filter", - "search_by_label": "Cari berdasarkan", - "newest_first_label": "Terbaru dulu", - "since_label": "Sejak", - "until_label": "Hingga", - "pick_a_date_button": "Pilih tanggal", - "search_placeholder": "Cari", - "filter_button_description": "Menyaring", - "clear_button_description": "Hapus", - "no_logs_found": "Tidak ada log yang ditemukan", - "log_event_format": "{event} di {conversation}", - "condition_only_inside_conversation": "Hanya saat saya di dalam percakapan", - "condition_only_outside_conversation": "Hanya saat saya di luar percakapan", - "condition_only_when_app_active": "Hanya saat Snapchat aktif", - "condition_only_when_app_inactive": "Hanya saat Snapchat tidak aktif", - "condition_no_push_notification_when_app_active": "Tidak ada notifikasi push saat Snapchat aktif", - "add_event_dialog_title": "Tambah Peristiwa", - "event_type_label": "Jenis peristiwa", - "triggers_title": "Pemicu", - "conditions_title": "Kondisi", - "add_button": "Tambah", - "default_rule_name": "Aturan Kustom", - "discard_changes_dialog_title": "Buang Perubahan?", - "discard_changes_dialog_text": "Anda memiliki perubahan yang belum disimpan. Apakah Anda yakin ingin membuangnya?", - "discard_button": "Buang", - "cannot_save_rule_dialog_title": "Tidak Dapat Menyimpan Aturan", - "cannot_save_rule_dialog_text": "Sebuah aturan harus memiliki setidaknya satu peristiwa untuk disimpan.", - "duplicate_rule_name_dialog_title": "Nama Aturan Duplikat", - "duplicate_rule_name_dialog_text": "Aturan dengan nama ini sudah ada. Silakan pilih nama lain.", - "delete_rule_dialog_title": "Hapus Aturan", - "delete_rule_dialog_text": "Apakah Anda yakin ingin menghapus aturan ini?", - "new_rule_title": "Aturan Baru", - "edit_rule_title": "Edit Aturan", - "back_button_description": "Kembali", - "save_button_description": "Simpan", - "general_section_title": "Umum", - "rule_name_label": "Nama Aturan", - "author_name_label": "Nama Penulis", - "scope_section_title": "Cakupan", - "scope_all": "Semua", - "scope_whitelist": "Daftar Putih", - "scope_blacklist": "Daftar Hitam", - "select_friends_groups_button": "Pilih Teman/Grup ({count})", - "events_section_title": "Peristiwa", - "add_event_button": "Tambah Peristiwa", - "no_events_text": "Tidak ada peristiwa" - }, - "friend_tracker_catalog": { - "download_failed": "Gagal mengunduh: {code}", - "error": "Kesalahan: {message}", - "no_repos_added": "Tidak ada repositori yang ditambahkan.", - "no_rules_available": "Tidak ada aturan yang tersedia dari repositori mana pun.", - "by_author": "oleh {author}", - "imported_button": "Diimpor", - "import_button": "Impor", - "title": "Katalog Pelacak Teman", - "manage_repos_description": "Kelola Repositori" - }, - "friend_tracker_export": { - "title": "Ekspor Aturan", - "back_button_description": "Kembali", - "exported_toast": "Aturan Pelacak Teman Diekspor!", - "export_failed_toast": "Gagal mengekspor aturan: {message}", - "save_button": "Simpan", - "expand_button_description": "Perluas" - }, - "friend_tracker_import": { - "title": "Impor Aturan", - "back_button_description": "Kembali", - "imported_toast": "Aturan Pelacak Teman Diimpor!", - "import_failed_toast": "Gagal mengimpor aturan: {message}", - "confirm_button": "Konfirmasi", - "expand_button_description": "Perluas" - }, - "friend_tracker_repos": { - "invalid_repo_title": "Repositori Tidak Valid", - "add_repo_button": "Tambah Repositori", - "add_repo_dialog_title": "Tambah URL Repositori", - "repo_url_label": "URL Repositori", - "repo_added_toast": "Repositori berhasil ditambahkan!", - "invalid_repo_error": "Ini tampaknya bukan repositori Pelacak Teman yang valid.", - "add_repo_failed_toast": "Gagal menambahkan repositori: {message}", - "add_button": "Tambah", - "no_repos_added": "Tidak ada repositori yang ditambahkan", - "remove_button": "Hapus", - "remove_repo_dialog_title": "Hapus Repositori", - "remove_repo_dialog_text": "Apakah Anda yakin ingin menghapus repositori ini?" - }, - "navigation": { - "tracker_tab_label": "Pelacak", - "customize_bottom_bar_title": "Sesuaikan Bilah Bawah", - "customize_bottom_bar_subtitle": "Urutkan ulang, tambah, atau hapus tab. Maksimal lima.", - "shown_tabs_title": "Tab yang Ditampilkan", - "no_tabs_selected_text": "Tidak ada tab yang dipilih", - "available_tabs_title": "Tab yang Tersedia", - "reset_button": "Setel Ulang", - "done_button": "Selesai" - }, - "scripting": { - "script_already_installed": "Skrip sudah diinstal!", - "downloading_script": "Mengunduh skrip...", - "script_downloaded": "Skrip {name} diunduh!", - "download_script_failed": "Gagal mengunduh skrip. Periksa log untuk detail lebih lanjut", - "import_script_from_url_title": "Impor Skrip dari URL", - "import_script_warning": "Peringatan: Skrip yang diimpor dapat berbahaya bagi perangkat Anda. Hanya impor skrip dari sumber tepercaya.", - "enter_url_label": "Masukkan URL di sini:", - "script_imported": "Skrip {name} diimpor!", - "import_failed": "Gagal mengimpor skrip. {message}. Periksa log untuk detail lebih lanjut", - "import_button": "Impor", - "update_module_button": "Perbarui Modul", - "updating_script": "Memperbarui skrip {name}...", - "module_not_found": "Modul tidak ditemukan", - "updated_script": "Memperbarui {name} ke versi {version}", - "update_module_failed": "Gagal memperbarui modul. Periksa log untuk detail lebih lanjut", - "edit_module_button": "Edit Modul", - "open_module_failed": "Gagal membuka file modul. Periksa log untuk detail lebih lanjut", - "clear_module_data_button": "Hapus Data Modul", - "module_data_cleared": "Data modul dihapus!", - "clear_module_data_failed": "Gagal menghapus data modul. Periksa log untuk detail lebih lanjut", - "delete_module_button": "Hapus Modul", - "deleted_script": "Menghapus skrip {name}!", - "delete_module_failed": "Gagal menghapus modul. Periksa log untuk detail lebih lanjut", - "actions_title": "Tindakan", - "no_description": "Tidak ada deskripsi", - "update_available": "Pembaruan tersedia: {version}", - "actions_button": "Tindakan", - "loaded_script": "Skrip {name} dimuat", - "unloaded_script": "Skrip {name} dibongkar", - "enable_script_failed": "Gagal mengaktifkan skrip. Periksa log untuk detail lebih lanjut", - "disable_script_failed": "Gagal menonaktifkan skrip. Periksa log untuk detail lebih lanjut", - "select_scripts_folder_toast": "Silakan pilih folder skrip Anda!", - "manage_repos_button": "Kelola Repositori", - "import_from_url_button": "Impor dari URL", - "open_scripts_folder_button": "Buka Folder Skrip", - "no_settings_for_module": "Modul ini tidak memiliki pengaturan apa pun", - "installed_scripts_tab": "Skrip yang Diinstal", - "catalog_tab": "Katalog", - "no_scripts_folder_selected_title": "Tidak ada folder skrip yang dipilih", - "select_folder_button": "Pilih folder", - "no_scripts_found_title": "Tidak ada skrip yang ditemukan.", - "use_catalog_to_add_scripts": "Gunakan tab katalog untuk menambahkan skrip!", - "ok_button_timeout": "Oke ({timeout})", - "documentation_button": "Dokumentasi", - "catalog": { - "script_already_installed": "Skrip sudah diinstal!", - "download_failed": "Gagal mengunduh: {code}", - "script_downloaded": "Skrip diunduh!", - "could_not_create_file": "Tidak dapat membuat file.", - "no_scripts_folder_selected": "Tidak ada folder skrip yang dipilih.", - "error": "Kesalahan: {message}", - "no_repos_added": "Tidak ada repositori yang ditambahkan.", - "repo_list_info": "Di sini Anda dapat menemukan daftar repositori: ", - "link_text": "Tautan", - "no_scripts_available": "Tidak ada skrip yang tersedia dari repositori mana pun.", - "by_author": "oleh {author}", - "version": "Versi: {version}", - "installed_button": "Diinstal", - "download_button": "Unduh" - }, - "repos": { - "invalid_repo_title": "Repositori Tidak Valid", - "add_repo_button": "Tambah Repositori", - "add_repo_dialog_title": "Tambah URL Repositori", - "repo_url_label": "URL Repositori", - "repo_added_toast": "Repositori berhasil ditambahkan!", - "invalid_repo_error": "Ini tampaknya bukan repositori Skrip yang valid.", - "add_repo_failed_toast": "Gagal menambahkan repositori: {message}", - "add_button": "Tambah", - "no_repos_added": "Tidak ada repositori yang ditambahkan", - "remove_button": "Hapus", - "remove_repo_dialog_title": "Hapus Repositori", - "remove_repo_dialog_text": "Apakah Anda yakin ingin menghapus repositori ini?" - } - }, - "features": { - "config_import": { - "title": "Konfirmasi Impor", - "back_button_description": "Kembali", - "config_imported_toast": "Konfigurasi Diimpor!", - "confirm_button": "Konfirmasi", - "expand_button_description": "Perluas", - "enable_feature": "Aktifkan Fitur", - "enabled": "Diaktifkan", - "disabled": "Dinonaktifkan" - }, - "config_export": { - "title": "Ringkasan Ekspor", - "back_button_description": "Kembali", - "save_button": "Simpan", - "expand_button_description": "Perluas", - "enable_feature": "Aktifkan Fitur", - "enabled": "Diaktifkan", - "disabled": "Dinonaktifkan" - } - }, - "manage_repos": { - "title": "Kelola Repositori {type}", - "add_repo_button": "Tambah Repositori", - "add_repo_dialog_title": "Tambah URL Repositori", - "repo_url_label": "URL Repositori", - "repo_added_successfully": "Repositori berhasil ditambahkan!", - "add_repo_failed": "Gagal menambahkan repositori: {message}", - "add_button": "Tambah", - "no_repos_added": "Tidak ada repositori yang ditambahkan", - "remove_button": "Hapus" - } + "content_type": { + "SNAP": "Jepret", + "STATUS": "Cerita", + "LOCATION": "Lokasi", + "STATUS_COUNTDOWN": "Hitung mundur", + "CHAT": "Obrolan", + "STICKER": "Stiker", + "SHARE": "Bagikan", + "STATUS_CONVERSATION_CAPTURE_SCREENSHOT": "Tangkapan layar" }, - "rules": { - "toasts": { - "enabled": "{ruleName} diaktifkan", - "disabled": "{ruleName} dinonaktifkan" - }, - "modes": { - "blacklist": "Mode daftar hitam", - "whitelist": "Mode daftar putih" - }, - "properties": { - "auto_download": { - "name": "Unduh otomatis", - "description": "Unduh Snap secara otomatis saat melihatnya", - "options": { - "blacklist": "Kecualikan dari Unduh Otomatis", - "whitelist": "Unduh Otomatis" - } - }, - "stealth": { - "name": "Mode Siluman", - "description": "Mencegah siapa pun mengetahui bahwa Anda telah membuka Snap/Obrolan dan percakapan mereka", - "options": { - "blacklist": "Kecualikan dari Mode Siluman", - "whitelist": "Mode siluman" - } - }, - "auto_save": { - "name": "Simpan Otomatis", - "description": "Menyimpan Pesan Obrolan saat melihatnya", - "options": { - "blacklist": "Kecualikan dari Simpan Otomatis", - "whitelist": "Simpan otomatis" - } - }, - "unsaveable_messages": { - "name": "Pesan yang Tidak Dapat Disimpan", - "description": "Mencegah pesan disimpan dalam obrolan oleh orang lain", - "options": { - "blacklist": "Kecualikan dari Pesan yang Tidak Dapat Disimpan", - "whitelist": "Pesan yang Tidak Dapat Disimpan" - } - }, - "auto_open_snaps": { - "name": "Buka Snap Otomatis", - "description": "Membuka Snap secara otomatis saat menerimanya", - "options": { - "blacklist": "Kecualikan dari Buka Snap Otomatis", - "whitelist": "Buka Snap Otomatis" - } - }, - "hide_friend_feed": { - "name": "Sembunyikan dari Umpan Teman" - }, - "e2e_encryption": { - "name": "Gunakan Enkripsi E2E" - }, - "pin_conversation": { - "name": "Sematkan Percakapan" - }, - "exclude_message_logger": { - "name": "Kecualikan dari Pencatat Pesan" - } - } + "material3_strings": { + "date_range_picker_day_in_range": "Terpilih", + "date_range_picker_end_headline": "Untuk", + "date_picker_switch_to_calendar_mode": "Kalender", + "date_picker_switch_to_input_mode": "Masukan", + "date_picker_today_description": "Hari ini", + "date_range_picker_start_headline": "Dari" }, - "actions": { - "clean_snapchat_cache": { - "name": "Bersihkan Cache Snapchat", - "description": "Membersihkan Cache Snapchat" - }, - "manage_friend_list": { - "name": "Kelola Daftar Teman", - "description": "Impor/ekspor daftar teman Anda saat mencadangkan" - }, - "export_chat_messages": { - "name": "Ekspor Pesan Obrolan", - "description": "Mengekspor pesan percakapan ke file JSON/HTML/TXT" - }, - "export_memories": { - "name": "Ekspor Kenangan", - "description": "Mengekspor kenangan ke file ZIP" - }, - "bulk_messaging_action": { - "name": "Tindakan Pesan Massal", - "description": "Melakukan operasi seperti menghapus teman atau penghapusan massal percakapan" - }, - "regen_mappings": { - "name": "Buat Ulang Pemetaan", - "description": "Buat ulang pemetaan secara manual" - }, - "change_language": { - "name": "Ubah Bahasa", - "description": "Ubah bahasa PurrfectSnap" - }, - "file_imports": { - "name": "Impor File", - "description": "Impor file untuk digunakan di Snapchat" - }, - "friend_tracker": { - "name": "Pelacak Teman", - "description": "Lacak teman Anda di Snapchat" - }, - "logger_history": { - "name": "Riwayat Logger", - "description": "Lihat riwayat pesan yang dicatat" - } + "button": { + "positive": "Iya", + "open": "Buka", + "cancel": "Batal", + "download": "Unduhan", + "ok": "Oke", + "negative": "Tidak" }, - "features": { - "notices": { - "unstable": "⚠️ Tidak Stabil", - "ban_risk": "⚠️ Fitur ini dapat menyebabkan larangan", - "internal_behavior": "⚠️ Ini dapat merusak perilaku internal Snapchat" - }, - "properties": { - "downloader": { - "name": "Pengunduh", - "description": "Unduh Media Snapchat", - "properties": { - "save_folder": { - "name": "Simpan Folder", - "description": "Pilih direktori tempat semua media harus diunduh" - }, - "auto_download_sources": { - "name": "Sumber Unduh Otomatis", - "description": "Pilih sumber untuk diunduh secara otomatis" - }, - "prevent_self_auto_download": { - "name": "Cegah Unduh Otomatis Sendiri", - "description": "Mencegah Snap Anda sendiri diunduh secara otomatis" - }, - "path_format": { - "name": "Format Jalur", - "description": "Tentukan Format Jalur File" - }, - "allow_duplicate": { - "name": "Izinkan Duplikat", - "description": "Memungkinkan media yang sama diunduh beberapa kali" - }, - "merge_overlays": { - "name": "Gabungkan Hamparan", - "description": "Menggabungkan Teks dan media Snap menjadi satu file" - }, - "force_image_format": { - "name": "Paksa Format Gambar", - "description": "Memaksa gambar disimpan dalam Format yang ditentukan" - }, - "force_voice_note_format": { - "name": "Paksa Format Catatan Suara", - "description": "Memaksa Catatan Suara disimpan dalam Format yang ditentukan" - }, - "auto_download_voice_notes": { - "name": "Unduh Catatan Suara Otomatis", - "description": "Mengunduh catatan suara secara otomatis saat memutarnya" - }, - "download_profile_pictures": { - "name": "Unduh Gambar Profil", - "description": "Memungkinkan Anda mengunduh Gambar Profil dari halaman profil" - }, - "opera_download_button": { - "name": "Tombol Unduh Opera", - "description": "Menambahkan tombol unduh di sudut kanan atas saat melihat Snap.\nTekan lama pada tombol akan memaksa pengunduhan" - }, - "download_context_menu": { - "name": "Menu Konteks Unduh", - "description": "Memungkinkan Anda mengunduh/melihat pratinjau pesan dari percakapan atau cerita menggunakan menu konteks.\nTekan lama pada tombol akan memaksa pengunduhan" - }, - "ffmpeg_options": { - "name": "Opsi FFmpeg", - "description": "Tentukan opsi FFmpeg tambahan", - "properties": { - "threads": { - "name": "Utas", - "description": "Jumlah utas yang akan digunakan" - }, - "preset": { - "name": "Prasetel", - "description": "Atur kecepatan konversi" - }, - "constant_rate_factor": { - "name": "Faktor Laju Konstan", - "description": "Atur faktor laju konstan untuk enkoder video\nDari 0 hingga 51 untuk libx264" - }, - "video_bitrate": { - "name": "Bitrate Video", - "description": "Atur bitrate video (kbps)" - }, - "audio_bitrate": { - "name": "Bitrate Audio", - "description": "Atur bitrate audio (kbps)" - }, - "custom_video_codec": { - "name": "Codec Video Kustom", - "description": "Atur Codec Video kustom (misalnya libx264)" - }, - "custom_audio_codec": { - "name": "Codec Audio Kustom", - "description": "Atur Codec Audio kustom (misalnya AAC)" - } - } - }, - "logging": { - "name": "Pencatatan", - "description": "Menampilkan toast saat media sedang diunduh" - }, - "custom_path_format": { - "name": "Format Jalur Kustom", - "description": "Tentukan format jalur kustom untuk media yang diunduh\n\nVariabel yang tersedia:\n - %username%\n - %source%\n - %hash%\n - %date_time%" - } - } - }, - "user_interface": { - "name": "Antarmuka Pengguna", - "description": "Ubah tampilan dan nuansa Snapchat", - "properties": { - "enable_app_appearance": { - "name": "Aktifkan Pengaturan Tampilan Aplikasi", - "description": "Mengaktifkan Pengaturan Tampilan Aplikasi yang tersembunyi\nMungkin tidak diperlukan pada versi Snapchat yang lebih baru" - }, - "friend_feed_message_preview": { - "name": "Pratinjau Pesan Umpan Teman", - "description": "Menampilkan pratinjau pesan terakhir di Umpan Teman", - "properties": { - "amount": { - "name": "Jumlah", - "description": "Jumlah pesan yang akan dipratinjau" - } - } - }, - "snap_preview": { - "name": "Pratinjau Snap", - "description": "Menampilkan pratinjau kecil di sebelah Snap yang belum dilihat di obrolan" - }, - "bootstrap_override": { - "name": "Penggantian Bootstrap", - "description": "Mengganti pengaturan bootstrap antarmuka pengguna", - "properties": { - "app_appearance": { - "name": "Tampilan Aplikasi", - "description": "Mengatur Tampilan Aplikasi yang persisten" - }, - "home_tab": { - "name": "Tab Beranda", - "description": "Mengganti tab startup saat membuka Snapchat" - } - } - }, - "force_amoled_theme": { - "name": "Mode Gelap Amoled", - "description": "Menggunakan latar belakang hitam pekat untuk tema gelap" - }, - "map_friend_nametags": { - "name": "Tag Nama Teman Peta yang Ditingkatkan", - "description": "Meningkatkan Tag Nama teman di Snapmap" - }, - "prevent_message_list_auto_scroll": { - "name": "Cegah Gulir Otomatis Daftar Pesan", - "description": "Mencegah daftar pesan bergulir ke bawah saat mengirim/menerima pesan" - }, - "streak_expiration_info": { - "name": "Tampilkan Info Kedaluwarsa Streak", - "description": "Menampilkan penghitung waktu Kedaluwarsa Streak di sebelah penghitung Streak" - }, - "hide_friend_feed_entry": { - "name": "Sembunyikan Entri Umpan Teman", - "description": "Menyembunyikan teman tertentu dari Umpan Teman\nGunakan tab sosial untuk mengelola fitur ini" - }, - "hide_streak_restore": { - "name": "Sembunyikan Pemulihan Streak", - "description": "Menyembunyikan tombol Pulihkan di umpan teman" - }, - "hide_quick_add_suggestions": { - "name": "Sembunyikan Saran Tambah Cepat", - "description": "Menghapus saran teman tambah cepat" - }, - "hide_story_suggestions": { - "name": "Sembunyikan Saran Cerita", - "description": "Menghapus saran dari halaman Cerita" - }, - "hide_ui_components": { - "name": "Sembunyikan Komponen UI", - "description": "Pilih komponen UI mana yang akan disembunyikan" - }, - "opera_media_quick_info": { - "name": "Info Cepat Media Opera", - "description": "Menampilkan informasi berguna tentang media seperti tanggal pembuatan di menu konteks penampil opera" - }, - "old_bitmoji_selfie": { - "name": "Selfie Bitmoji Lama", - "description": "Mengembalikan selfie Bitmoji dari versi Snapchat yang lebih lama" - }, - "disable_spotlight": { - "name": "Nonaktifkan Spotlight", - "description": "Menonaktifkan halaman Spotlight" - }, - "friend_feed_menu_buttons": { - "name": "Tombol Menu Umpan Teman", - "description": "Pilih tombol mana yang akan ditampilkan di Menu Umpan Teman" - }, - "auto_close_friend_feed_menu": { - "name": "Tutup Otomatis Menu Umpan Teman", - "description": "Menutup Menu Umpan Teman secara otomatis setelah menekan tombol pengaturan" - }, - "vertical_story_viewer": { - "name": "Penampil Cerita Vertikal", - "description": "Mengaktifkan penampil cerita vertikal untuk semua cerita" - }, - "enable_friend_feed_menu_bar": { - "name": "Bilah Menu Umpan Teman", - "description": "Mengaktifkan Bilah Menu Umpan Teman yang baru" - }, - "message_indicators": { - "name": "Indikator Pesan", - "description": "Menambahkan ikon indikator spesifik ke pesan\nCatatan: Indikator mungkin tidak 100% akurat" - }, - "stealth_mode_indicator": { - "name": "Indikator Mode Siluman", - "description": "Menambahkan emoji 👻 di sebelah percakapan dalam mode siluman" - }, - "edit_text_override": { - "name": "Penggantian Edit Teks", - "description": "Mengganti perilaku bidang teks" - }, - "prevent_forced_keyboard": { - "name": "Cegah Keyboard Paksa", - "description": "Mencegah Snapchat memunculkan keyboard secara otomatis saat Anda membuka percakapan" - }, - "settings_menu": { - "name": "Menu Pengaturan", - "description": "Mengubah cara Anda membuka menu PurrfectSnap", - "options": { - "default": "Bawaan", - "legacy": "Lama" - } - } - } - }, - "messaging": { - "name": "Pesan", - "description": "Ubah cara Anda berinteraksi dengan teman", - "properties": { - "bypass_screenshot_detection": { - "name": "Lewati Deteksi Tangkapan Layar", - "description": "Mencegah Snapchat mendeteksi saat Anda mengambil tangkapan layar" - }, - "anonymous_story_viewing": { - "name": "Melihat Cerita Secara Anonim", - "description": "Mencegah siapa pun mengetahui bahwa Anda telah melihat cerita mereka" - }, - "prevent_story_rewatch_indicator": { - "name": "Cegah Indikator Tonton Ulang Cerita", - "description": "Mencegah siapa pun mengetahui bahwa Anda telah menonton ulang cerita mereka" - }, - "hide_peek_a_peek": { - "name": "Sembunyikan Mengintip", - "description": "Mencegah pemberitahuan dikirim saat Anda setengah menggeser ke dalam obrolan" - }, - "hide_bitmoji_presence": { - "name": "Sembunyikan Kehadiran Bitmoji", - "description": "Mencegah Bitmoji Anda muncul saat berada di Obrolan" - }, - "hide_typing_notifications": { - "name": "Sembunyikan Notifikasi Mengetik", - "description": "Mencegah siapa pun mengetahui bahwa Anda sedang mengetik pesan" - }, - "unlimited_snap_view_time": { - "name": "Waktu Lihat Snap Tidak Terbatas", - "description": "Menghapus Batas Waktu untuk melihat Snap" - }, - "auto_mark_as_read": { - "name": "Tandai Otomatis sebagai Telah Dibaca", - "description": "Secara otomatis menandai pesan/snap sebagai telah dibaca bahkan saat Mode Siluman diaktifkan" - }, - "mark_snap_as_seen_button": { - "name": "Tombol Tandai Snap sebagai Telah Dilihat", - "description": "Menambahkan tombol untuk menandai Snap sebagai telah dilihat saat melihatnya.\nIni akan berfungsi bahkan saat Mode Siluman diaktifkan" - }, - "skip_when_marking_as_seen": { - "name": "Lewati Saat Menandai sebagai Telah Dilihat", - "description": "Secara otomatis melompat ke Snap berikutnya saat menandai Snap sebagai telah dilihat.\nGunakan dalam kombinasi dengan Tombol Tandai Snap sebagai Telah Dilihat" - }, - "loop_media_playback": { - "name": "Putar Ulang Media", - "description": "Memutar ulang media saat melihat Snap/Cerita" - }, - "disable_replay_in_ff": { - "name": "Nonaktifkan Putar Ulang di FF", - "description": "Menonaktifkan kemampuan untuk memutar ulang dengan menekan lama dari Umpan Teman" - }, - "half_swipe_notifier": { - "name": "Pemberitahu Setengah Geser", - "description": "Memberi tahu Anda saat seseorang setengah menggeser ke dalam percakapan", - "properties": { - "min_duration": { - "name": "Durasi Minimum", - "description": "Durasi minimum setengah geser (dalam detik)" - }, - "max_duration": { - "name": "Durasi Maksimum", - "description": "Durasi maksimum setengah geser (dalam detik)" - } - } - }, - "call_start_confirmation": { - "name": "Konfirmasi Mulai Panggilan", - "description": "Menampilkan dialog konfirmasi saat memulai panggilan" - }, - "unlimited_conversation_pinning": { - "name": "Menyematkan Percakapan Tanpa Batas", - "description": "Memungkinkan Anda menyematkan jumlah percakapan tanpa batas secara lokal" - }, - "disable_snap_mode_restrictions": { - "name": "Nonaktifkan Pembatasan Mode Snap", - "description": "Memungkinkan Anda melihat Snap yang dapat merusak diri sendiri tanpa batasan" - }, - "prevent_message_sending": { - "name": "Cegah Pengiriman Pesan", - "description": "Mencegah pengiriman jenis pesan tertentu" - }, - "friend_mutation_notifier": { - "name": "Pemberitahu Mutasi Teman", - "description": "Memberi tahu Anda saat ada sesuatu yang berubah di profil teman" - }, - "better_notifications": { - "name": "Notifikasi Lebih Baik", - "description": "Menambahkan lebih banyak informasi dalam notifikasi yang diterima", - "properties": { - "group_notifications": { - "name": "Notifikasi Grup", - "description": "Kelompokkan notifikasi menjadi satu" - }, - "chat_preview": { - "name": "Pratinjau Obrolan", - "description": "Menampilkan pratinjau pesan yang diterima dalam notifikasi" - }, - "media_preview": { - "name": "Pratinjau Media", - "description": "Menampilkan pratinjau jenis media yang dipilih dalam notifikasi" - }, - "media_caption": { - "name": "Keterangan Media", - "description": "Menampilkan keterangan media yang terlampir dalam notifikasi" - }, - "stacked_media_messages": { - "name": "Pesan Media Bertumpuk", - "description": "Menggabungkan beberapa pesan media menjadi satu notifikasi teks saat tidak dapat dipratinjau. Gunakan dalam kombinasi dengan Pratinjau Obrolan" - }, - "friend_add_source": { - "name": "Sumber Tambah Teman", - "description": "Menampilkan sumber permintaan pertemanan dalam notifikasi" - }, - "reply_button": { - "name": "Tombol Balas", - "description": "Menambahkan tombol balas ke notifikasi" - }, - "smart_replies": { - "name": "Balasan Cerdas", - "description": "Menambahkan balasan yang disarankan ke notifikasi (Android 10+). Gunakan dalam kombinasi dengan Tombol Balas" - }, - "download_button": { - "name": "Tombol Unduh", - "description": "Memungkinkan Anda mengunduh media dari notifikasi" - }, - "mark_as_read_button": { - "name": "Tombol Tandai sebagai Telah Dibaca", - "description": "Memungkinkan Anda menandai pesan sebagai telah dibaca dari notifikasi" - }, - "mark_as_read_and_save_in_chat": { - "name": "Tandai sebagai Telah Dibaca dan Simpan di Obrolan", - "description": "Menambahkan tombol tandai sebagai telah dibaca dan simpan di obrolan ke notifikasi" - } - } - }, - "notification_blacklist": { - "name": "Daftar Hitam Notifikasi", - "description": "Pilih notifikasi mana yang harus diblokir" - }, - "message_logger": { - "name": "Pencatat Pesan", - "description": "Mencegah pesan dihapus", - "properties": { - "keep_my_own_messages": { - "name": "Simpan Pesan Saya Sendiri", - "description": "Mencegah pesan Anda sendiri dihapus" - }, - "auto_purge": { - "name": "Hapus Otomatis", - "description": "Secara otomatis menghapus pesan yang di-cache yang lebih lama dari jumlah waktu yang ditentukan" - }, - "message_filter": { - "name": "Filter Pesan", - "description": "Pilih pesan mana yang harus dicatat (kosong untuk semua pesan)" - }, - "deleted_message_color": { - "name": "Warna Pesan yang Dihapus", - "description": "Mengatur warna pesan yang dihapus" - } - } - }, - "auto_save_messages_in_conversations": { - "name": "Simpan Pesan Otomatis", - "description": "Secara otomatis menyimpan setiap pesan dalam percakapan" - }, - "gallery_media_send_override": { - "name": "Penggantian Pengiriman Media Galeri", - "description": "Memalsukan sumber media saat mengirim dari Galeri" - }, - "strip_media_metadata": { - "name": "Hapus Metadata Media", - "description": "Menghapus metadata media sebelum mengirim sebagai pesan" - }, - "bypass_message_retention_policy": { - "name": "Lewati Kebijakan Penyimpanan Pesan", - "description": "Mencegah pesan dihapus setelah melihatnya" - }, - "bypass_message_action_restrictions": { - "name": "Lewati Pembatasan Tindakan Pesan", - "description": "Memungkinkan Anda bereaksi terhadap snap tanpa membukanya atau menyimpan pesan yang tidak dapat disimpan" - }, - "remove_groups_locked_status": { - "name": "Hapus Status Terkunci Grup", - "description": "Memungkinkan Anda melihat informasi grup setelah dikeluarkan" - }, - "double_tap_chat_action": { - "name": "Tindakan Obrolan Ketuk Dua Kali", - "description": "Melakukan tindakan kustom saat mengetuk dua kali pesan dalam obrolan" - }, - "double_tap_chat_action_custom_emoji": { - "name": "Reaksi Emoji Kustom Tindakan Obrolan Ketuk Dua Kali", - "description": "Mengatur reaksi emoji kustom untuk tindakan obrolan ketuk dua kali" - } - } - }, - "global": { - "name": "Global", - "description": "Ubah Pengaturan Snapchat Global", - "properties": { - "better_location": { - "name": "Lokasi Lebih Baik", - "description": "Meningkatkan Lokasi Snapchat", - "properties": { - "spoof_location": { - "name": "Lokasi Palsu", - "description": "Memalsukan lokasi Anda ke lokasi yang ditentukan" - }, - "coordinates": { - "name": "Koordinat", - "description": "Atur koordinat lokasi palsu" - }, - "walk_radius": { - "name": "Radius Jalan", - "description": "Berjalan secara acak di dalam radius ini (kaki)" - }, - "always_update_location": { - "name": "Selalu Perbarui Lokasi", - "description": "Paksa Snapchat untuk memperbarui lokasi bahkan jika tidak ada data GPS yang diterima" - }, - "suspend_location_updates": { - "name": "Tangguhkan Pembaruan Lokasi", - "description": "Mencegah lokasi Anda diperbarui" - }, - "spoof_battery_level": { - "name": "Tingkat Baterai Palsu", - "description": "Memalsukan tingkat baterai perangkat Anda di peta\nNilai harus antara 0 dan 100" - }, - "spoof_headphones": { - "name": "Headphone Palsu", - "description": "Memalsukan status mendengarkan musik di peta" - }, - "show_battery_level": { - "name": "Tampilkan Tingkat Baterai", - "description": "Menampilkan tingkat baterai teman Anda di peta" - } - } - }, - "snapchat_plus": { - "name": "Snapchat Ditambah", - "description": "Mengaktifkan fitur Snapchat Plus\nBeberapa fitur Sisi Server mungkin tidak berfungsi" - }, - "media_upload_quality": { - "name": "Kualitas Unggahan Media", - "description": "Mengganti kualitas unggahan media", - "properties": { - "force_video_upload_source_quality": { - "name": "Paksa Kualitas Sumber Unggahan Video", - "description": "Memaksa Snapchat untuk menggunakan kualitas sumber saat mengunggah video\nHarap dicatat bahwa ini mungkin tidak menghapus metadata dari media" - }, - "disable_image_compression": { - "name": "Nonaktifkan Kompresi Gambar", - "description": "Menonaktifkan kompresi gambar saat mengunggah media" - }, - "custom_image_upload_format": { - "name": "Format Unggahan Gambar Kustom", - "description": "Mengatur format unggahan gambar kustom\nPilih format tanpa kehilangan (seperti PNG) untuk kualitas terbaik" - } - } - }, - "disable_confirmation_dialogs": { - "name": "Nonaktifkan Dialog Konfirmasi", - "description": "Secara otomatis mengonfirmasi tindakan yang dipilih" - }, - "auto_updater": { - "name": "Pembaruan Otomatis", - "description": "Secara otomatis memeriksa pembaruan baru" - }, - "disable_metrics": { - "name": "Nonaktifkan Metrik", - "description": "Memblokir pengiriman data analitik spesifik ke Snapchat" - }, - "disable_story_sections": { - "name": "Nonaktifkan Bagian Cerita", - "description": "Menghapus bagian dari halaman Cerita\nMungkin memerlukan penyegaran agar berfungsi dengan baik" - }, - "block_ads": { - "name": "Blokir Iklan", - "description": "Mencegah Iklan ditampilkan" - }, - "disable_custom_tabs": { - "name": "Nonaktifkan Tab Kustom", - "description": "Membuka tautan di aplikasi yang didukung alih-alih di Browser Web" - }, - "disable_permission_requests": { - "name": "Nonaktifkan Permintaan Izin", - "description": "Mencegah Snapchat meminta izin spesifik" - }, - "disable_memories_snap_feed": { - "name": "Nonaktifkan Umpan Snap Kenangan", - "description": "Mencegah Snapchat menampilkan kenangan terbaru saat Anda menggeser ke atas di kamera" - }, - "spotlight_comments_username": { - "name": "Nama Pengguna Komentar Spotlight", - "description": "Menampilkan nama pengguna penulis di komentar Spotlight" - }, - "bypass_video_length_restriction": { - "name": "Lewati Pembatasan Panjang Video", - "description": "Tunggal: mengirim satu video\nBagi: membagi video setelah mengedit" - }, - "default_video_playback_rate": { - "name": "Laju Putar Video Bawaan", - "description": "Mengatur kecepatan bawaan untuk pemutaran video\nNilai harus antara 0,1 dan 4,0" - }, - "video_playback_rate_slider": { - "name": "Penggeser Laju Putar Video", - "description": "Menambahkan penggeser di menu konteks opera untuk mengubah laju putar video\nCatatan: Perubahan hanya berlaku untuk video berikutnya" - }, - "disable_google_play_dialogs": { - "name": "Nonaktifkan Dialog Layanan Google Play", - "description": "Mencegah dialog ketersediaan Layanan Google Play ditampilkan" - }, - "default_volume_controls": { - "name": "Kontrol Volume Bawaan", - "description": "Memaksa Snapchat untuk menggunakan kontrol volume sistem" - }, - "disable_telecom_framework": { - "name": "Nonaktifkan Kerangka Kerja Telekomunikasi", - "description": "Mencegah Snapchat menggunakan kerangka kerja Telekomunikasi Android\nIni memungkinkan Anda mendengarkan musik saat melakukan panggilan" - }, - "hide_active_music": { - "name": "Sembunyikan Musik Aktif", - "description": "Mencegah Snapchat mengetahui bahwa Anda sedang mendengarkan musik\nIni akan memungkinkan Anda mengambil snap menggunakan tombol kontrol volume saat mendengarkan musik" - }, - "disable_snap_splitting": { - "name": "Nonaktifkan Pemisahan Snap", - "description": "Mencegah Snap dibagi menjadi beberapa bagian\nGambar yang Anda kirim akan berubah menjadi video" - } - } - }, - "rules": { - "name": "Aturan", - "description": "Kelola Fitur Otomatis untuk orang per orang" - }, - "camera": { - "name": "Kamera", - "description": "Sesuaikan pengaturan yang tepat untuk snap yang sempurna", - "properties": { - "disable_cameras": { - "name": "Nonaktifkan Kamera", - "description": "Mencegah Snapchat menggunakan kamera yang dipilih" - }, - "black_photos": { - "name": "Foto Hitam", - "description": "Mengganti foto yang diambil dengan latar belakang hitam\nVideo tidak terpengaruh" - }, - "immersive_camera_preview": { - "name": "Pratinjau Imersif", - "description": "Mencegah Snapchat Memotong pratinjau Kamera\nIni mungkin menyebabkan kamera berkedip pada beberapa perangkat" - }, - "override_front_resolution": { - "name": "Ganti Resolusi Depan", - "description": "Mengganti resolusi kamera untuk kamera depan" - }, - "override_back_resolution": { - "name": "Ganti Resolusi Belakang", - "description": "Mengganti resolusi kamera untuk kamera belakang" - }, - "custom_resolution": { - "name": "Resolusi Kustom", - "description": "Mengatur resolusi kamera kustom, lebar x tinggi (misalnya 1920x1080).\nResolusi kustom harus didukung oleh perangkat Anda" - }, - "front_custom_frame_rate": { - "name": "Laju Bingkai Kustom Depan", - "description": "Mengganti laju bingkai kamera depan" - }, - "back_custom_frame_rate": { - "name": "Laju Bingkai Kustom Belakang", - "description": "Mengganti laju bingkai kamera belakang" - }, - "force_camera_source_encoding": { - "name": "Paksa Pengodean Sumber Kamera", - "description": "Memaksa pengodean sumber kamera" - }, - "startup_default_camera": { - "name": "Kamera Bawaan Startup", - "description": "Mengatur kamera bawaan saat membuka Snapchat" - }, - "hevc_recording": { - "name": "Perekaman HEVC", - "description": "Menggunakan codec HEVC (H.265) untuk perekaman video" - } - } - }, - "streaks_reminder": { - "name": "Pengingat Streak", - "description": "Memberi tahu Anda secara berkala tentang Streak Anda", - "properties": { - "interval": { - "name": "Selang", - "description": "Interval antara setiap pengingat (jam)" - }, - "remaining_hours": { - "name": "Waktu Tersisa", - "description": "Jumlah waktu yang tersisa sebelum notifikasi ditampilkan (jam)" - }, - "group_notifications": { - "name": "Notifikasi Grup", - "description": "Kelompokkan notifikasi menjadi satu" - } - } - }, - "experimental": { - "name": "Eksperimental", - "description": "Fitur eksperimental", - "properties": { - "native_hooks": { - "name": "Hook Asli", - "description": "Fitur Tidak Aman yang terhubung ke kode asli Snapchat", - "properties": { - "composer_hooks": { - "name": "Hook Komposer", - "description": "Menyuntikkan kode ke dalam kerangka kerja UI lintas platform Komposer", - "properties": { - "show_first_created_username": { - "name": "Tampilkan Nama Pengguna yang Dibuat Pertama", - "description": "Menampilkan nama pengguna yang dibuat pertama di sebelah nama pengguna saat ini di halaman profil" - }, - "bypass_camera_roll_limit": { - "name": "Lewati Batas Rol Kamera", - "description": "Meningkatkan jumlah maksimum media yang dapat Anda kirim dari rol kamera" - }, - "custom_self_destruct_snap_delay": { - "name": "Tunda Snap Hancur Sendiri Kustom", - "description": "Memberikan lebih banyak opsi untuk penghitung waktu hancur sendiri saat mengirim Snap" - }, - "composer_console": { - "name": "Konsol Komposer", - "description": "Memungkinkan Anda menjalankan kode JavaScript di Komposer (hanya arm64)" - }, - "composer_logs": { - "name": "Log Komposer", - "description": "Mengarahkan log konsol Komposer ke PurrfectSnap" - } - } - }, - "disable_bitmoji": { - "name": "Nonaktifkan Bitmoji", - "description": "Menonaktifkan Bitmoji Profil Teman" - }, - "custom_emoji_font": { - "name": "Font Emoji Kustom", - "description": "Memungkinkan Anda menggunakan font emoji kustom. Hanya berfungsi dengan font .ttf" - }, - "custom_shared_library": { - "name": "Pustaka Bersama Kustom", - "description": "Memuat pustaka bersama kustom ke dalam Snapchat. Fitur ini hanya untuk tujuan pengujian" - } - } - }, - "spoof": { - "name": "Palsu", - "description": "Palsukan berbagai informasi tentang Anda", - "properties": { - "play_store_installer_package_name": { - "name": "Nama Paket Penginstal Play Store", - "description": "Mengganti nama paket penginstal menjadi com.android.vending" - }, - "remove_vpn_transport_flag": { - "name": "Hapus Bendera Transportasi VPN", - "description": "Mencegah Snapchat mendeteksi VPN" - }, - "remove_mock_location_flag": { - "name": "Hapus Bendera Lokasi Palsu", - "description": "Mencegah Snapchat mendeteksi Lokasi Palsu" - } - } - }, - "convert_message_locally": { - "name": "Konversi Pesan Secara Lokal", - "description": "Mengonversi snap menjadi media eksternal obrolan secara lokal. Ini muncul di menu konteks unduhan obrolan" - }, - "media_file_picker": { - "name": "Pemilih File Media", - "description": "Memungkinkan Anda memilih file video/audio apa pun dari galeri" - }, - "story_logger": { - "name": "Pencatat Cerita", - "description": "Menyediakan riwayat cerita teman" - }, - "call_recorder": { - "name": "Perekam Panggilan", - "description": "Merekam panggilan audio secara otomatis" - }, - "account_switcher": { - "name": "Pengalih Akun", - "description": "Memungkinkan Anda beralih antar akun tanpa keluar\nTekan lama pada ikon pencarian di sebelah profil Bitmoji Anda untuk membuka menu\nCatatan: Fitur ini bersifat eksperimental dan kemungkinan akan berubah di masa mendatang", - "properties": { - "auto_backup_current_account": { - "name": "Cadangkan Akun Saat Ini Secara Otomatis", - "description": "Secara otomatis mencadangkan akun saat ini saat keluar atau beralih akun" - } - } - }, - "better_transcript": { - "name": "Transkrip Lebih Baik", - "description": "Meningkatkan transkrip catatan suara", - "properties": { - "force_transcription": { - "name": "Paksa Transkripsi Catatan Suara", - "description": "Memungkinkan semua catatan suara ditranskripsi" - }, - "preferred_transcription_lang": { - "name": "Bahasa Transkripsi Pilihan", - "description": "Bahasa pilihan untuk transkrip catatan suara (misalnya EN, ES, FR)" - }, - "notification_transcript": { - "name": "Transkrip Notifikasi", - "description": "Mentranskripsi catatan suara dalam notifikasi\nFitur ini memerlukan fitur Pratinjau Obrolan untuk diaktifkan di Notifikasi Lebih Baik" - } - } - }, - "voice_note_auto_play": { - "name": "Putar Otomatis Catatan Suara", - "description": "Secara otomatis memutar catatan suara berikutnya setelah yang sekarang selesai" - }, - "friend_notes": { - "name": "Catatan Teman", - "description": "Memungkinkan Anda menambahkan catatan ke profil teman" - }, - "cof_experiments": { - "name": "Eksperimen COF", - "description": "Mengaktifkan fitur Snapchat yang belum dirilis/beta" - }, - "context_menu_fix": { - "name": "Perbaikan Menu Konteks", - "description": "Mencoba memperbaiki Menu Umpan Teman karena saat perangkat offline tidak dapat ditampilkan dengan benar" - }, - "app_lock": { - "name": "Kunci Aplikasi", - "description": "Mencegah akses ke Snapchat tanpa kode sandi", - "properties": { - "lock_on_resume": { - "name": "Kunci Saat Dilanjutkan", - "description": "Mengunci aplikasi saat dibuka kembali" - } - } - }, - "infinite_story_boost": { - "name": "Peningkatan Cerita Tak Terbatas", - "description": "Lewati penundaan Batas Peningkatan Cerita" - }, - "meo_passcode_bypass": { - "name": "Lewati Kode Sandi Hanya Mata Saya", - "description": "Lewati kode sandi Hanya Mata Saya\nIni hanya akan berfungsi jika kode sandi telah dimasukkan dengan benar sebelumnya" - }, - "no_friend_score_delay": { - "name": "Tidak Ada Penundaan Skor Teman", - "description": "Menghapus penundaan saat melihat Skor Teman" - }, - "best_friend_pinning": { - "name": "Menyematkan Sahabat Terbaik", - "description": "Memungkinkan Anda menyematkan teman sebagai sahabat terbaik nomor satu Anda. Catatan: Hanya Anda yang dapat melihat sahabat terbaik yang Anda sematkan" - }, - "e2ee": { - "name": "Enkripsi End-To-End", - "description": "Mengenkripsi pesan Anda dengan AES menggunakan kunci rahasia bersama\nPastikan untuk menyimpan kunci Anda di tempat yang aman!", - "properties": { - "encrypted_message_indicator": { - "name": "Indikator Pesan Terenkripsi", - "description": "Menambahkan emoji 🔒 di sebelah pesan terenkripsi" - }, - "force_message_encryption": { - "name": "Paksa Enkripsi Pesan", - "description": "Mencegah pengiriman pesan terenkripsi kepada orang yang tidak mengaktifkan Enkripsi E2E hanya saat beberapa percakapan dipilih" - } - } - }, - "add_friend_source_spoof": { - "name": "Palsu Sumber Tambah Teman", - "description": "Memalsukan sumber Permintaan Pertemanan" - }, - "hidden_snapchat_plus_features": { - "name": "Fitur Snapchat Plus Tersembunyi", - "description": "Mengaktifkan fitur Snapchat Plus yang belum dirilis/beta\nMungkin tidak berfungsi pada versi Snapchat yang lebih lama" - }, - "custom_streaks_expiration_format": { - "name": "Format Kedaluwarsa Streak Kustom", - "description": "Menyesuaikan format Kedaluwarsa Streak\n\nVariabel yang tersedia:\n - %c: Jumlah Streak\n - %e: Emoji Jam Pasir\n - %d: Hari\n - %h: Jam\n - %m: Menit\n - %s: Detik\n - %w: Waktu Tersisa" - }, - "prevent_forced_logout": { - "name": "Cegah Keluar Paksa", - "description": "Mencegah Snapchat mengeluarkan Anda saat Anda masuk di perangkat lain" - }, - "snapscore_changes": { - "name": "Perubahan Snapscore", - "description": "Melacak perubahan skor teman Snapscore\nGunakan fitur ini hanya di versi Snapchat yang lebih baru" - } - } - }, - "scripting": { - "name": "Skrip", - "description": "Jalankan skrip kustom untuk memperluas PurrfectSnap", - "properties": { - "developer_mode": { - "name": "Mode Pengembang", - "description": "Menampilkan info debug di UI Snapchat" - }, - "module_folder": { - "name": "Folder Modul", - "description": "Folder tempat skrip berada" - }, - "auto_reload": { - "name": "Muat Ulang Otomatis", - "description": "Secara otomatis memuat ulang skrip saat berubah" - }, - "integrated_ui": { - "name": "UI Terintegrasi", - "description": "Memungkinkan skrip untuk menambahkan komponen UI kustom ke Snapchat" - }, - "disable_log_anonymization": { - "name": "Nonaktifkan Anonimisasi Log", - "description": "Menonaktifkan anonimisasi log" - }, - "disable_optimization": { - "name": "Nonaktifkan Optimasi", - "description": "Menonaktifkan optimasi skrip. Ini dapat menyebabkan masalah kinerja." - } - } - }, - "friend_tracker": { - "name": "Pelacak Teman", - "description": "Mencatat aktivitas teman di Snapchat", - "properties": { - "record_messaging_events": { - "name": "Catat Peristiwa Pesan", - "description": "Mencatat peristiwa pesan seperti membuka snap, membaca pesan, dll." - }, - "allow_running_in_background": { - "name": "Izinkan Berjalan di Latar Belakang", - "description": "Memungkinkan pelacak berjalan di latar belakang. Catatan: Ini akan menguras baterai Anda secara signifikan" - }, - "auto_purge": { - "name": "Hapus Otomatis", - "description": "Secara otomatis menghapus peristiwa yang di-cache yang lebih lama dari jumlah waktu yang ditentukan" - } - } - } - }, - "options": { - "app_appearance": { - "always_light": "Selalu Terang", - "always_dark": "Selalu Gelap" - }, - "friend_feed_menu_buttons": { - "auto_download": "⬇️ Unduh Otomatis", - "auto_save": "💬 Simpan Pesan Otomatis", - "unsaveable_messages": "⬇️ Pesan yang Tidak Dapat Disimpan", - "auto_open_snaps": "📸 Buka Snap Otomatis", - "stealth": "👻 Mode Siluman", - "mark_snaps_as_seen": "👀 Tandai Snap sebagai telah dilihat", - "mark_stories_as_seen_locally": "👀 Tandai Cerita sebagai telah dilihat secara lokal", - "conversation_info": "🧑‍🤝‍🧑 Info Percakapan", - "e2e_encryption": "🔒 Gunakan Enkripsi E2E" - }, - "path_format": { - "create_author_folder": "Buat folder untuk setiap penulis", - "create_source_folder": "Buat folder untuk setiap jenis sumber media", - "append_hash": "Tambahkan hash unik ke nama file", - "append_source": "Tambahkan sumber media ke nama file", - "append_username": "Tambahkan nama pengguna ke nama file", - "append_date_time": "Tambahkan tanggal dan waktu ke nama file" - }, - "auto_download_sources": { - "friend_snaps": "Snap Teman", - "friend_stories": "Cerita Teman", - "public_stories": "Cerita Publik", - "spotlight": "Menyoroti" - }, - "logging": { - "started": "Dimulai", - "success": "Berhasil", - "progress": "Kemajuan", - "failure": "Gagal" - }, - "notifications": { - "chat_screenshot": "Tangkapan Layar", - "chat_screen_record": "Rekaman Layar", - "snap_replay": "Putar Ulang Snap", - "camera_roll_save": "Simpan ke Rol Kamera", - "chat": "Obrolan", - "chat_reply": "Balasan Obrolan", - "snap": "Patah", - "typing": "Mengetik", - "stories": "Cerita", - "speaking": "Berbicara", - "chat_reaction": "Reaksi DM", - "group_chat_reaction": "Reaksi Grup", - "initiate_audio": "Panggilan Audio Masuk", - "abandon_audio": "Panggilan Audio Tak Terjawab", - "initiate_video": "Panggilan Video Masuk", - "abandon_video": "Panggilan Video Tak Terjawab", - "map_live_location": "Lokasi Langsung Peta" - }, - "gallery_media_send_override": { - "always_ask": "Selalu Tanya", - "ORIGINAL": "Media Asli", - "NOTE": "Catatan Audio", - "SNAP": "Patah", - "SAVEABLE_SNAP": "Snap yang Dapat Disimpan" - }, - "strip_media_metadata": { - "hide_caption_text": "Sembunyikan Teks Keterangan", - "hide_snap_filters": "Sembunyikan Filter Snap", - "hide_extras": "Sembunyikan Ekstra (misalnya sebutan)", - "remove_audio_note_duration": "Hapus Durasi Catatan Audio", - "remove_audio_note_transcript_capability": "Hapus Kemampuan Transkrip Catatan Audio" - }, - "hide_ui_components": { - "hide_profile_call_buttons": "Hapus Tombol Panggilan Profil", - "hide_chat_call_buttons": "Hapus Tombol Panggilan Obrolan", - "hide_live_location_share_button": "Hapus Tombol Bagikan Lokasi Langsung", - "hide_stickers_button": "Hapus Tombol Stiker", - "hide_voice_record_button": "Hapus Tombol Rekam Suara", - "hide_unread_chat_hint": "Hapus Petunjuk Obrolan yang Belum Dibaca", - "hide_post_to_story_buttons": "Hapus tombol Posting ke Cerita sebelum mengirim Snap", - "hide_billboard_prompt": "Hapus Prompt Papan Iklan di Umpan Teman", - "hide_snapchat_plus_gift_reminders": "Hapus pengingat hadiah Snapchat Plus dalam percakapan", - "hide_map_reactions": "Hapus Reaksi Peta" - }, - "hide_story_suggestions": { - "hide_suggested_friend_stories": "Sembunyikan cerita teman yang disarankan", - "hide_my_stories": "Sembunyikan Cerita Saya" - }, - "home_tab": { - "map": "Peta", - "chat": "Obrolan", - "camera": "Kamera", - "discover": "Temukan", - "spotlight": "Menyoroti" - }, - "add_friend_source_spoof": { - "added_by_username": "Berdasarkan Nama Pengguna", - "added_by_mention": "Berdasarkan Sebutan", - "added_by_group_chat": "Berdasarkan Obrolan Grup", - "added_by_qr_code": "Berdasarkan Kode QR", - "added_by_community": "Berdasarkan Komunitas", - "added_by_quick_add": "Berdasarkan Tambah Cepat (risiko tinggi diblokir)" - }, - "bypass_video_length_restriction": { - "single": "Media tunggal", - "split": "Media terpisah" - }, - "old_bitmoji_selfie": { - "2d": "Bitmoji 2D", - "3d": "Bitmoji 3D" - }, - "disable_confirmation_dialogs": { - "erase_message": "Hapus Pesan", - "remove_friend": "Hapus Teman", - "block_friend": "Blokir Teman", - "ignore_friend": "Abaikan Teman", - "hide_friend": "Sembunyikan Teman", - "hide_conversation": "Sembunyikan Percakapan", - "clear_conversation": "Hapus Percakapan dari Umpan Teman" - }, - "auto_reload": { - "snapchat_only": "Hanya Snapchat", - "all": "Semua (Snapchat + PurrfectSnap)" - }, - "edit_text_override": { - "multi_line_chat_input": "Input Obrolan Multi Baris", - "bypass_text_input_limit": "Lewati Batas Input Teks" - }, - "auto_purge": { - "never": "Tidak Pernah", - "1_hour": "1 Jam", - "3_hours": "3 Jam", - "6_hours": "6 Jam", - "12_hours": "12 Jam", - "1_day": "1 Hari", - "3_days": "3 Hari", - "1_week": "1 Minggu", - "2_weeks": "2 Minggu", - "1_month": "1 Bulan", - "3_months": "3 Bulan", - "6_months": "6 Bulan" - }, - "disable_story_sections": { - "friends": "Teman", - "suggested_stories": "Cerita yang Disarankan", - "following": "Mengikuti", - "discover": "Temukan" - }, - "disable_cameras": { - "front": "Kamera Depan", - "back": "Kamera Belakang" - }, - "disable_permission_requests": { - "notifications": "Notifikasi", - "read_media_images": "Baca Gambar Media", - "read_media_video": "Baca Video Media", - "camera": "Kamera", - "microphone": "Mikrofon", - "location": "Lokasi", - "read_contacts": "Baca Kontak", - "nearby_devices": "Perangkat Terdekat", - "phone_calls": "Panggilan Telepon" - }, - "message_indicators": { - "encryption_indicator": "Menambahkan ikon 🔒 di sebelah pesan yang hanya dikirimkan kepada Anda", - "platform_indicator": "Menambahkan ikon platform tempat media dikirim (misalnya Android, iOS, Web)", - "location_indicator": "Menambahkan ikon 📍 ke snap saat dikirim dengan lokasi diaktifkan", - "ovf_editor_indicator": "Menunjukkan apakah snap telah dikirim menggunakan Editor OVF", - "director_mode_indicator": "Menambahkan ikon 🎬 ke snap saat dikirim menggunakan Mode Sutradara, yang dapat digunakan untuk mengirim gambar galeri sebagai snap" - }, - "auto_mark_as_read": { - "conversation_read": "Tandai percakapan sebagai telah dibaca saat mengirim pesan", - "snap_reply": "Tandai snap sebagai telah dibaca saat membalasnya", - "save_snap_in_chat": "Tandai snap sebagai telah dibaca saat menyimpannya dalam obrolan saat dalam Mode Siluman" - }, - "friend_mutation_notifier": { - "remove_friend": "Beri tahu saat seseorang menghapus Anda sebagai teman", - "birthday_changes": "Beri tahu saat seseorang mengubah hari ulang tahunnya", - "bitmoji_selfie_changes": "Beri tahu saat seseorang mengubah selfie Bitmoji-nya", - "bitmoji_avatar_changes": "Beri tahu saat seseorang mengubah avatar Bitmoji-nya", - "bitmoji_background_changes": "Beri tahu saat seseorang mengubah latar belakang Bitmoji-nya", - "bitmoji_scene_changes": "Beri tahu saat seseorang mengubah adegan Bitmoji-nya" - }, - "snapchat_plus": { - "not_subscribed": "Tidak Berlangganan", - "basic": "Dasar", - "ad_free": "Bebas Iklan" - }, - "double_tap_chat_action": { - "like_message": "Sukai Pesan", - "copy_text": "Salin Teks ke Papan Klip", - "delete_message": "Hapus Pesan", - "mark_as_read": "Tandai sebagai Telah Dibaca", - "custom_emoji_reaction": "Reaksi Emoji Kustom" - }, - "startup_default_camera": { - "front": "Kamera Depan", - "back": "Kamera Belakang" - } + "biometric_auth": { + "unlock_button": "Buka Kunci" + }, + "conversation_preview": { + "title": "Pratinjau" + }, + "download_processor": { + "attachment_type": { + "gif": "Gifs", + "sticker": "Stiker", + "note": "Catatan", + "snap": "Jepret" } }, "friend_menu_option": { - "mark_snaps_as_seen": "Tandai Snap sebagai telah dilihat", - "mark_stories_as_seen_locally": "Tandai Cerita sebagai telah dilihat secara lokal", - "preview": "Pratinjau", - "stealth_mode": "Mode Siluman", - "auto_download_blacklist": "Daftar Hitam Unduh Otomatis", - "anti_auto_save": "Anti Simpan Otomatis" + "preview": "Pratinjau" }, - "content_type": { - "CHAT": "Obrolan", - "SNAP": "Patah", - "EXTERNAL_MEDIA": "Media Eksternal", - "NOTE": "Catatan Audio", - "STICKER": "Stiker", - "SHARE": "Bagikan", - "STATUS": "Status", - "LOCATION": "Lokasi", - "STATUS_SAVE_TO_CAMERA_ROLL": "Disimpan ke Rol Kamera", - "STATUS_CONVERSATION_CAPTURE_SCREENSHOT": "Tangkapan Layar", - "STATUS_CONVERSATION_CAPTURE_RECORD": "Rekaman Layar", - "STATUS_CALL_MISSED_VIDEO": "Panggilan Video Tak Terjawab", - "STATUS_CALL_MISSED_AUDIO": "Panggilan Audio Tak Terjawab", - "LIVE_LOCATION_SHARE": "Bagikan Lokasi Langsung", - "CREATIVE_TOOL_ITEM": "Item Alat Kreatif", - "FAMILY_CENTER_INVITE": "Undangan Pusat Keluarga", - "FAMILY_CENTER_ACCEPT": "Terima Pusat Keluarga", - "FAMILY_CENTER_LEAVE": "Tinggalkan Pusat Keluarga", - "STATUS_PLUS_GIFT": "Hadiah Status Plus", - "TINY_SNAP": "Snap Kecil", - "STATUS_COUNTDOWN": "Hitung Mundur", - "MAP_REACTION": "Reaksi Peta" - }, - "media_download_source": { - "none": "Tidak Ada", - "pending": "Tertunda", - "chat_media": "Media Obrolan", - "story": "Cerita", - "public_story": "Cerita Publik", - "spotlight": "Menyoroti", - "profile_picture": "Gambar Profil", - "story_logger": "Pencatat Cerita", - "message_logger": "Pencatat Pesan", - "merged": "Digabungkan", - "voice_call": "Panggilan Suara" + "modal_option": { + "close": "Tutup" }, "chat_action_menu": { "preview_button": "Pratinjau", - "download_button": "Unduh", - "delete_logged_message_button": "Hapus Pesan yang Dicatat", - "show_chat_edit_history": "Tampilkan Riwayat Edit Obrolan", - "convert_message": "Konversi Pesan" + "download_button": "Unduhan" }, - "opera_context_menu": { - "download": "Unduh Media", - "sent_at": "Dikirim pada {date}", - "created_at": "Dibuat pada {date}", - "expires_at": "Kedaluwarsa pada {date}", - "media_size": "Ukuran media: {size}", - "media_duration": "Durasi media: {duration} ms", - "show_debug_info": "Tampilkan Info Debug" - }, - "modal_option": { - "profile_info": "Info Profil", - "close": "Tutup" - }, - "gallery_media_send_override": { - "multiple_media_toast": "Anda hanya dapat mengirim satu media sekaligus" - }, - "mark_as_seen": { - "no_unseen_snaps_toast": "Tidak ada Snap yang belum dilihat!", - "seen_toast": "Ditandai sebagai telah dilihat!", - "unseen_toast": "Ditandai sebagai belum dilihat!", - "already_seen_toast": "Sudah ditandai sebagai telah dilihat!", - "already_unseen_toast": "Sudah ditandai sebagai belum dilihat!" - }, - "conversation_preview": { - "streak_expiration": "kedaluwarsa dalam {day} hari {hour} jam {minute} menit", - "total_messages": "Total pesan terkirim/diterima: {count}", - "title": "Pratinjau", - "unknown_user": "Pengguna Tidak Dikenal", - "no_messages": "Tidak ada pesan yang ditemukan!" - }, - "profile_info": { - "title": "Info Profil", - "first_created_username": "Nama Pengguna yang Dibuat Pertama", - "mutable_username": "Nama Pengguna yang Dapat Diubah", - "display_name": "Nama Tampilan", - "added_date": "Tanggal Ditambahkan", - "birthday": "Ulang Tahun: {month} {day}", - "hidden_birthday": "Ulang Tahun: Tersembunyi", - "friendship": "Pertemanan", - "add_source": "Tambah Sumber", - "snapchat_plus": "Snapchat Ditambah", - "snapchat_plus_state": { - "subscribed": "Berlangganan", - "not_subscribed": "Tidak Berlangganan" - } + "media_download_source": { + "none": "Tidak ada", + "merged": "Digabung", + "pending": "Ditunda", + "story": "Cerita", + "spotlight": "Sorotan" }, "friendship_link_type": { - "mutual": "Saling", - "outgoing": "Keluar", "blocked": "Diblokir", - "deleted": "Dihapus", - "following": "Mengikuti", "suggested": "Disarankan", - "incoming": "Masuk", - "incoming_follower": "Pengikut Masuk" + "mutual": "Saling", + "deleted": "Dihapus", + "incoming": "Akan datang", + "following": "Mengikuti" }, - "bulk_messaging_action": { - "choose_action_title": "Pilih tindakan", - "progress_status": "Memproses {index} dari {total}", - "selection_dialog_continue_button": "Lanjutkan", - "confirmation_dialog": { - "title": "Apakah Anda yakin?", - "message": "Ini akan memengaruhi semua teman yang dipilih. Tindakan ini tidak dapat dibatalkan." - }, - "actions": { - "remove_friends": "Hapus Teman", - "clear_conversations": "Hapus Percakapan" + "better_notifications": { + "button": { + "download": "Unduhan", + "reply": "Balas" } }, "chat_export": { "exporter_dialog": { - "select_conversations_title": "Pilih Percakapan", - "text_field_selection": "{amount} dipilih", - "text_field_selection_all": "Semua", - "export_file_format_title": "Ekspor Format File", - "message_type_filter_title": "Filter Pesan berdasarkan Jenis", - "amount_of_messages_title": "Jumlah Pesan (kosongkan untuk semua)", - "download_medias_title": "Unduh Media" + "text_field_selection_all": "Semua" }, - "dialog_negative_button": "Batal", "dialog_positive_button": "Ekspor", - "exported_to": "Diekspor ke {path}", - "exporting_chats": "Mengekspor Obrolan...", - "processing_chats": "Memproses {amount} percakapan...", - "export_fail": "Gagal mengekspor percakapan {conversation}", - "writing_output": "Menulis output...", - "finished": "Selesai! Anda sekarang dapat menutup dialog ini.", - "no_messages_found": "Tidak ada pesan yang ditemukan!", - "exporting_message": "Mengekspor {conversation}..." + "dialog_negative_button": "Batal" }, - "button": { - "ok": "Oke", - "positive": "Ya", - "negative": "Tidak", - "cancel": "Batal", - "open": "Buka", - "download": "Unduh", - "send": "Kirim", - "restore_original": "Pulihkan Asli", - "convert_external_media": "Konversi Media Eksternal", - "save": "Simpan" - }, - "tracker_events": { - "conversation_enter": "Masuk Percakapan", - "conversation_exit": "Keluar Percakapan", - "started_typing": "Mulai Mengetik", - "stopped_typing": "Berhenti Mengetik", - "started_speaking": "Mulai Berbicara", - "stopped_speaking": "Berhenti Berbicara", - "started_peeking": "Mulai Mengintip", - "stopped_peeking": "Berhenti Mengintip", - "message_read": "Pesan Dibaca", - "message_deleted": "Pesan Dihapus", - "message_saved": "Pesan Disimpan", - "message_unsaved": "Pesan Tidak Disimpan", - "message_edited": "Pesan Diedit", - "message_reaction_add": "Tambah Reaksi Pesan", - "message_reaction_remove": "Hapus Reaksi Pesan", - "snap_opened": "Snap Dibuka", - "snap_replayed": "Snap Diputar Ulang", - "snap_replayed_twice": "Snap Diputar Ulang Dua Kali", - "snap_screenshot": "Tangkapan Layar Snap", - "snap_screen_record": "Rekaman Layar Snap" - }, - "tracker_actions": { - "log": "Catatan", - "in_app_notification": "Notifikasi Dalam Aplikasi", - "push_notification": "Notifikasi Push", - "custom": "Kustom" - }, - "better_notifications": { - "button": { - "reply": "Balas", - "download": "Unduh", - "mark_as_read": "Tandai sebagai Telah Dibaca" - } - }, - "profile_picture_downloader": { - "button": "Unduh Gambar Profil", - "title": "Pengunduh Gambar Profil", - "avatar_option": "Avatar", - "background_option": "Latar Belakang" - }, - "call_start_confirmation": { - "dialog_title": "Mulai Panggilan", - "dialog_message": "Apakah Anda yakin ingin memulai panggilan?" - }, - "half_swipe_notifier": { - "notification_channel_name": "Setengah Geser", - "notification_content_dm": "{friend} baru saja setengah menggeser ke dalam obrolan Anda selama {duration} detik", - "notification_content_group": "{friend} baru saja setengah menggeser ke dalam {group} selama {duration} detik" - }, - "download_processor": { - "attachment_type": { - "snap": "Patah", - "sticker": "Stiker", - "gif": "GIF", - "external_media": "Media Eksternal", - "note": "Catatan", - "original_story": "Cerita Asli" + "profile_info": { + "snapchat_plus_state": { + "subscribed": "Berlangganan" }, - "select_attachments_title": "Pilih lampiran", - "download_started_toast": "Pengunduhan dimulai", - "unsupported_content_type_toast": "Jenis konten tidak didukung!", - "failed_no_longer_available_toast": "Media tidak lagi tersedia", - "no_attachments_toast": "Tidak ada lampiran yang ditemukan!", - "already_queued_toast": "Media sudah dalam antrean!", - "already_downloaded_toast": "Media sudah diunduh!", - "content_saved_toast": "Disimpan!", - "download_toast": "Mengunduh {path}...", - "processing_toast": "Memproses {path}...", - "failed_generic_toast": "Gagal mengunduh", - "failed_to_create_preview_toast": "Gagal membuat pratinjau", - "failed_processing_toast": "Gagal memproses {error}", - "failed_gallery_toast": "Gagal menyimpan ke galeri {error}", - "dash_no_chapter": "Tidak ada bab yang ditemukan", - "dash_dialog": { - "title": "Unduh media dash", - "download_all": "Unduh Semua", - "segment_text": "Segmen {from} - {to}" - } + "friendship": "Persahabatan" + }, + "bulk_messaging_action": { + "selection_dialog_continue_button": "Lanjutkan" }, "streaks_reminder": { - "notification_title": "Streak", - "notification_text": "Anda akan kehilangan Streak Anda dengan {friend} dalam {hoursLeft} jam" + "notification_title": "Garis -garis" }, - "biometric_auth": { - "unlock_button": "Buka Kunci", - "title": "Buka Kunci Snapchat", - "subtitle": "Harap otentikasi untuk membuka kunci Snapchat" - }, - "end_to_end_encryption": { - "toolbox": { - "no_shared_key": "Anda belum memiliki rahasia bersama dengan teman ini. Klik di bawah untuk memulai yang baru.", - "shared_key_fingerprint": "Sidik jari Anda adalah:\n\n{fingerprint}\n\nPastikan itu cocok dengan sidik jari teman Anda!", - "initiate_exchange_button": "Mulai Pertukaran Kunci" - }, - "confirmation_dialogs": { - "title": "Enkripsi end-to-end", - "confirmation_1": "PERINGATAN: Ini akan menimpa kunci Anda yang ada. Anda akan kehilangan akses ke semua pesan terenkripsi dari teman ini. Apakah Anda yakin ingin melanjutkan?", - "confirmation_2": "Apakah Anda BENAR-BENAR yakin ingin melanjutkan? Ini adalah kesempatan terakhir Anda untuk mundur." - }, - "unencrypted_conversation_send_failure_toast": "Anda tidak dapat mengirim konten terenkripsi ke percakapan terenkripsi dan tidak terenkripsi!", - "native_hooks_send_failure_toast": "Gagal mengirim! Harap aktifkan Hook Asli di pengaturan.", - "no_participants_to_encrypt_toast": "Anda tidak memiliki teman dalam percakapan ini untuk mengenkripsi pesan!", - "encryption_failed_toast": "Gagal mengenkripsi pesan! Periksa logcat untuk detail lebih lanjut.", - "accept_public_key_success_toast": "Kunci publik berhasil diterima!", - "accept_secret_key_success_toast": "Selesai! Anda sekarang dapat mengirim dan menerima pesan terenkripsi dengan teman ini.", - "accept_public_key_failure_toast": "Gagal menerima kunci publik", - "accept_secret_key_failure_toast": "Gagal menerima kunci rahasia", - "accept_secret_button": "Terima Rahasia", - "accept_public_key_button": "Terima Kunci Publik", - "outgoing_pk_message": "Permintaan pertukaran kunci", - "outgoing_secret_message": "Respons pertukaran kunci", - "incoming_pk_message": "Anda baru saja menerima permintaan kunci publik. Klik di bawah untuk menerimanya.", - "incoming_secret_message": "Teman Anda baru saja menerima kunci publik Anda. Klik di bawah untuk menerima rahasia." - }, - "auto_open_snaps": { - "title": "Buka Snap Otomatis", - "notification_content": "{count} Snap dibuka" - }, - "friend_mutation_observer": { - "notification_channel_name": "Pengamat Mutasi Teman", - "friend_removed": "{username} telah menghapus Anda sebagai teman", - "birthday_removed": "{username} telah menghapus hari ulang tahunnya ({birthday})", - "birthday_added": "{username} telah menambahkan hari ulang tahunnya ({birthday})", - "birthday_changed": "{username} telah mengubah hari ulang tahunnya dari {oldBirthday} menjadi {newBirthday}", - "bitmoji_selfie_changed": "{username} telah mengubah selfie Bitmoji-nya", - "bitmoji_avatar_changed": "{username} telah mengubah avatar Bitmoji-nya", - "bitmoji_background_changed": "{username} telah mengubah latar belakang Bitmoji-nya", - "bitmoji_scene_changed": "{username} telah mengubah adegan Bitmoji-nya" - }, - "material3_strings": { - "date_range_picker_start_headline": "Dari", - "date_range_picker_end_headline": "Hingga", - "date_range_picker_title": "Pilih rentang tanggal", - "date_picker_switch_to_calendar_mode": "Kalender", - "date_picker_switch_to_input_mode": "Masukan", - "date_range_picker_scroll_to_previous_month": "Bulan sebelumnya", - "date_range_picker_scroll_to_next_month": "Bulan berikutnya", - "date_picker_today_description": "Hari ini", - "date_range_picker_day_in_range": "Dipilih", - "date_input_invalid_for_pattern": "Tanggal tidak valid", - "date_input_invalid_year_range": "Tahun tidak valid", - "date_input_invalid_not_allowed": "Tanggal tidak valid", - "date_range_input_invalid_range_input": "Rentang tanggal tidak valid" - }, - "send_override_dialog": { - "title": "Kirim media sebagai {type}", - "duration": "Durasi: {duration}", - "saveable_snap_hint": "Buat Snap dapat disimpan di obrolan", - "unlimited_duration": "Tidak terbatas" - }, - "invalid_input_toast": "Input tidak valid! Pastikan Anda memasukkan nilai yang valid." -} \ No newline at end of file + "profile_picture_downloader": { + "background_option": "Latar belakang" + } +} diff --git a/common/src/main/assets/lang/it_IT.json b/common/src/main/assets/lang/it_IT.json index 885afdbd..6c3f5ea2 100644 --- a/common/src/main/assets/lang/it_IT.json +++ b/common/src/main/assets/lang/it_IT.json @@ -1,2022 +1,139 @@ { - "setup": { - "dialogs": { - "select_language": "Seleziona Lingua", - "save_folder": "PurrfectSnap richiede i permessi di archiviazione per scaricare e salvare i media da Snapchat.\nScegli la posizione in cui scaricare i media.", - "select_save_folder_button": "Seleziona Cartella" - }, - "mappings": { - "dialog": "Generazione delle mappature, potrebbe richiedere del tempo...", - "generate_failure_no_snapchat": "PurrfectSnap non è riuscito a rilevare Snapchat, prova a reinstallare Snapchat.", - "generate_failure": "Si è verificato un errore durante la generazione delle mappature, riprova." - }, - "permissions": { - "dialog": "Per continuare devi soddisfare i seguenti requisiti:", - "notification_access": "Accesso alle Notifiche", - "battery_optimization": "Ottimizzazione della Batteria", - "display_over_other_apps": "Visualizzazione sopra altre app", - "request_button": "Richiesta" - } - }, - "scopes": { - "friend": "Amico", - "group": "Gruppo" - }, - "manager": { - "routes": { - "tasks": "Attività", - "features": "Funzionalità", - "manage_rule_feature": "Gestisci Funzionalità Regola", - "home": "Casa", - "home_settings": "Impostazioni", - "home_logs": "Log", - "logger_history": "Cronologia Logger", - "logged_stories": "Storie Registrate", - "friend_tracker": "Tracciatore di Amici", - "edit_rule": "Modifica Regola", - "file_imports": "Importazioni File", - "manage_repos": "Gestisci Repository", - "social": "Sociale", - "manage_scope": "Gestisci Ambito", - "messaging_preview": "Anteprima", - "scripts": "Script", - "better_location": "Posizione Migliore" - }, - "sections": { - "home": { - "version_title": "v{versionName} · forkato da Eternal", - "update_title": "Aggiornamento PurrfectSnap", - "update_content": "La versione {version} è disponibile!", - "update_button": "Scarica", - "debug_build_summary_title": "Stai eseguendo una build di debug di PurrfectSnap", - "debug_build_summary_content": "Versione {versionName} ({versionCode})", - "debug_build_summary_date": "Data build: {date} ({days} giorni fa)", - "quick_actions_title": "Azioni Rapide", - "download_icon_description": "Scarica", - "completed_icon_description": "Completato", - "failed_icon_description": "Fallito", - "manage_quick_actions_description": "Gestisci Azioni Rapide", - "quick_actions_icon_description": "Azioni Rapide", - "add_quick_action_description": "Aggiungi Azione Rapida" - }, - "home_logs": { - "no_logs_hint": "Nessun log disponibile", - "clear_logs_button": "Cancella Log", - "export_logs_button": "Esporta Log", - "saving_logs_toast": "Salvataggio dei log in corso, potrebbe richiedere del tempo...", - "saved_logs_success_toast": "Log salvati con successo", - "saved_logs_failure_toast": "Salvataggio dei log fallito" - }, - "home_settings": { - "actions_title": "Azioni", - "message_logger_title": "Logger Messaggi", - "debug_title": "Debug", - "success_toast": "Fatto!", - "message_logger_summary": "{messageCount} messaggi\n{storyCount} storie", - "export_button": "Esporta", - "clear_button": "Cancella", - "view_logger_history_button": "Visualizza Cronologia Logger", - "updates_title": "Aggiornamenti", - "auto_update_check": "Controlla aggiornamenti automaticamente", - "update_check_frequency": "Frequenza controllo aggiornamenti", - "update_check_frequency_daily": "Giornaliero", - "update_check_frequency_weekly": "Settimanale", - "update_check_frequency_monthly": "Mensile", - "theme_icon_description": "Tema", - "app_theme_title": "Tema App", - "theme_mode_system": "Sistema", - "theme_mode_light": "Chiaro", - "theme_mode_dark": "Scuro", - "ui_settings_title": "Impostazioni UI", - "haptic_feedback_label": "Feedback Aptico", - "test_mode_label": "Modalità Test (SOLO PER DEBUGGING)", - "disable_feature_loading_label": "Disabilita Caricamento Funzionalità", - "disable_auto_mapper_label": "Disabilita Auto Mapper", - "disable_bypass_indicator_label": "Disabilita Indicatore Stato Bypass", - "update_notification_channel_name": "Aggiornamenti PurrfectSnap", - "update_notification_channel_description": "Notifiche per gli aggiornamenti di PurrfectSnap", - "update_notification_title": "Aggiornamento PurrfectSnap Disponibile", - "update_notification_text": "La versione %s è ora disponibile.", - "export_database_failed_toast": "Esportazione del database fallita! {message}", - "clear_messages_failed_toast": "Cancellazione dei messaggi fallita! {message}", - "clear_file_failed_toast": "Cancellazione del file fallita! {message}", - "debug_file_config": "Configurazione", - "debug_file_mappings": "Mappature", - "debug_file_message_logger": "Logger Messaggi", - "debug_file_pinned_best_friend": "Migliore Amico Fissato", - "debug_file_native_sig_cache": "Cache Firme Native" - }, - "tasks": { - "no_tasks": "Nessuna attività", - "merge_button": "Unisci", - "failed_to_open_file": "Apertura del file fallita", - "merge_files_toast": "Unione di {count} file", - "remove_selected_tasks_title": "Sei sicuro di voler rimuovere le attività selezionate?", - "remove_all_tasks_title": "Sei sicuro di voler rimuovere tutte le attività?", - "delete_files_option": "Elimina anche i file", - "remove_selected_tasks_confirm": "Rimuovere {count} attività?", - "remove_all_tasks_confirm": "Rimuovere tutte le attività?", - "clear_tasks_description": "Cancella attività", - "file_not_found_icon_description": "File non trovato", - "image_icon_description": "Immagine", - "video_icon_description": "Video", - "audio_icon_description": "Audio", - "file_icon_description": "File", - "download_icon_description": "Scarica", - "chat_action_icon_description": "Azione Chat", - "cancel_icon_description": "Annulla", - "success_icon_description": "Successo", - "failure_icon_description": "Fallimento", - "cancelled_icon_description": "Annullato", - "task_status_failure": "Fallimento", - "task_status_cancelled": "Annullato" - }, - "features": { - "disabled": "Disabilitato", - "export_option": "Esporta", - "import_option": "Importa", - "reset_option": "Ripristina", - "config_export_success_toast": "Configurazione esportata con successo", - "config_import_success_toast": "Configurazione importata con successo", - "config_import_failure_toast": "Importazione della configurazione fallita {error}", - "config_export_failure_toast": "Esportazione della configurazione fallita {error}", - "saved_config_snackbar": "Configurazione salvata", - "older_required": "Questa funzionalità richiede Snapchat v{version} o precedente per funzionare correttamente", - "newer_required": "Questa funzionalità richiede Snapchat v{version} o successiva per funzionare correttamente", - "search_button": "Cerca" - }, - "manage_rule_feature": { - "disable_state_option": "Disabilitato", - "disable_state_subtext": "Nessun amico/gruppo sarà interessato", - "whitelist_state_option": "Nessuno tranne...", - "whitelist_state_subtext": "Solo {count} amici/gruppi saranno interessati da questa regola", - "whitelist_state_button": "Seleziona amici/gruppi permessi", - "blacklist_state_option": "Tutti tranne...", - "blacklist_state_subtext": "Tutti tranne {count} amici/gruppi saranno interessati da questa regola", - "blacklist_state_button": "Seleziona amici/gruppi esclusi", - "clear_list_button": "Cancella lista amici/gruppi", - "dialog_clear_confirmation_text": "Sei sicuro di voler cancellare la lista?" - }, - "social": { - "friends_tab": "Amici", - "groups_tab": "Gruppi", - "empty_hint": "(vuoto)", - "streaks_expiration_short": "{hours}h" - }, - "manage_scope": { - "logged_stories_button": "Mostra Storie Registrate", - "e2ee_title": "Crittografia End-to-End", - "rules_title": "Regole", - "participants_text": "{count} partecipanti", - "not_found": "Non trovato", - "streaks_title": "Streak", - "streaks_length_text": "Lunghezza: {length}", - "streaks_expiration_text": "Scade tra {eta}", - "streaks_expiration_text_expired": "Scaduto", - "reminder_button": "Imposta Promemoria", - "delete_scope_confirm_dialog_title": "Sei sicuro di voler eliminare un {scope}?", - "notes_placeholder": "Clicca per aggiungere una nota", - "invalid_key_size_32_bytes": "Dimensione chiave non valida (deve essere di 32 byte)", - "successfully_imported_key": "Chiave importata con successo", - "failed_to_import_key": "Importazione della chiave fallita: {message}", - "export_base64_button": "Esporta Base64", - "import_base64_button": "Importa Base64" - }, - "logged_stories": { - "story_failed_to_load": "Caricamento fallito", - "no_stories": "Nessuna storia trovata", - "save_from_cache_button": "Salva dalla Cache", - "downloaded_to_path": "Scaricato in {path}", - "download_failed": "Download fallito: {message}", - "posted_at": "Pubblicato il {date}", - "created_at": "Creato il {date}", - "failed_to_open_file": "Apertura del file fallita. Controlla i log per maggiori informazioni", - "failed_to_get_file": "Ottenimento del file fallito" - }, - "messaging_preview": { - "processed_messages_toast": "Elaborati {count} messaggi", - "processed_messages_text": "Elaborati {count} messaggi", - "close_button_description": "Chiudi", - "bridge_connection_failed": "Connessione al bridge fallita. Assicurati che Snapchat sia in esecuzione in background", - "bridge_init_failed": "Inizializzazione del bridge di messaggistica fallita. Assicurati che Snapchat sia in esecuzione in background", - "message_fetch_failed": "Recupero dei messaggi fallito", - "no_message_hint": "Nessun messaggio", - "save_selection_option": "Salva Selezione", - "save_all_option": "Salva Tutto", - "unsave_selection_option": "Annulla Salvataggio Selezione", - "unsave_all_option": "Annulla Salvataggio Tutto", - "mark_selection_as_seen_option": "Segna Snap selezionato come visto", - "mark_all_as_seen_option": "Segna tutti gli Snap come visti", - "delete_selection_option": "Elimina Selezione", - "delete_all_option": "Elimina Tutto" - }, - "logger_history": { - "download_started_toast": "Download avviato!", - "download_success_toast": "Scaricato in {path}", - "download_failed_toast": "Download di {message} fallito", - "edited_at_text": "{message} (modificato il {date})", - "download_button": "Scarica", - "select_conversation_placeholder": "Seleziona una conversazione", - "close_button_description": "Chiudi", - "search_button_description": "Cerca", - "list_friend_format": "Amico {name}", - "list_group_format": "Gruppo {name}", - "no_more_messages": "Nessun altro messaggio", - "reverse_order_checkbox": "Ordine Inverso", - "chat_attachment": "Allegato {index}", - "empty_message": "Messaggio Chat Vuoto", - "message_parse_failed": "Analisi del messaggio fallita", - "unknown_sender": "Mittente Sconosciuto", - "download_attachment_failed_toast": "Download dell'allegato fallito", - "log_header_format": "{username} ({type}) - {date}" - }, - "file_imports": { - "import_file_button": "Importa File", - "file_not_found": "File non trovato", - "file_import_failed": "Importazione del file fallita: {error}", - "file_imported": "File importato con successo", - "file_delete_failed": "Eliminazione del file fallita", - "no_files_hint": "Qui puoi importare file da utilizzare in Snapchat. Premi il pulsante qui sotto per importare un file." - }, - "better_location": { - "spoofed_coordinates_title": "Lat {latitude}, Lng {longitude}", - "save_coordinates_dialog_title": "Salva Coordinate", - "saved_name_dialog_hint": "Nome Salvato", - "latitude_dialog_hint": "Latitudine", - "longitude_dialog_hint": "Longitudine", - "save_dialog_button": "Salva", - "choose_location_button": "Scegli Posizione", - "teleport_to_friend_button": "Teletrasportati da un Amico", - "spoof_location_toggle": "Posizione Falsa", - "suspend_location_updates": "Sospendi Aggiornamenti Posizione", - "saved_coordinates_title": "Coordinate Salvate", - "no_saved_coordinates_hint": "Nessuna coordinata salvata", - "delete_dialog_title": "Elimina Coordinata Salvata", - "delete_dialog_message": "Sei sicuro di voler eliminare questa coordinata salvata?", - "teleport_to_friend_title": "Teletrasportati da un Amico", - "search_bar": "Cerca", - "no_friends_map": "Nessun amico sulla mappa", - "no_friends_found": "Nessun amico trovato", - "edit_location_button_description": "Modifica Posizione", - "add_icon_description": "Aggiungi", - "edit_icon_description": "Modifica", - "delete_icon_description": "Elimina" - } - }, - "dialogs": { - "add_friend": { - "title": "Aggiungi Amico o Gruppo", - "search_hint": "Cerca", - "fetch_error": "Recupero dei dati fallito", - "category_groups": "Gruppi", - "category_friends": "Amici", - "participants_text": "{count} partecipanti", - "search_icon_description": "Cerca" - }, - "scripting_warning": { - "title": "Avviso", - "content": "PurrfectSnap include uno strumento di scripting, che consente l'esecuzione di codice definito dall'utente sul tuo dispositivo. Usa estrema cautela e installa solo moduli da fonti note e affidabili. Moduli non autorizzati o non verificati possono comportare rischi per la sicurezza del tuo sistema." - }, - "reset_config": { - "title": "Ripristina Configurazione", - "content": "Sei sicuro di voler ripristinare la configurazione?", - "success_toast": "Configurazione ripristinata con successo" - }, - "export_config": { - "title": "Esportare Dati Sensibili?", - "content": "Vuoi esportare la configurazione con dati sensibili? (Come coordinate di posizione, ecc.)" - }, - "messaging_action": { - "title": "Scegli i tipi di contenuto da elaborare", - "select_all_button": "Seleziona Tutto" - }, - "file_imports": { - "no_files_settings_hint": "Nessun file trovato. Assicurati di aver importato i file richiesti nella sezione Importazioni File", - "settings_select_file_hint": "Seleziona un file importato" - }, - "quick_actions_dialog": { - "title": "Modifica Azioni Rapide", - "subtitle": "Seleziona e ridimensiona le tue azioni rapide." - } - }, - "friend_tracker": { - "rules_tab": "Regole", - "logs_tab": "Log", - "export_dialog_title": "Esporta", - "bulk_export_button": "Esportazione Massiva", - "individual_export_button": "Esportazione Individuale", - "invalid_import_type_dialog_title": "Tipo di Importazione Non Valido", - "invalid_import_type_dialog_text": "Il file selezionato non è compatibile con questo tipo di importazione. Seleziona il tipo di importazione corretto.", - "import_dialog_title": "Importa", - "bulk_import_button": "Importazione Massiva", - "individual_import_button": "Importazione Individuale", - "import_button_description": "Importa", - "export_button_description": "Esporta", - "export_button": "Esporta", - "delete_button_description": "Elimina", - "delete_button": "Elimina", - "catalog_button_description": "Catalogo", - "catalog_button": "Catalogo", - "add_rule_button_description": "Aggiungi Regola", - "add_rule_button": "Aggiungi Regola", - "no_rules_found": "Nessuna regola trovata", - "empty_rule_name": "(vuoto)", - "events_suffix": "eventi", - "scopes_suffix": "ambiti", - "select_rule_to_export_title": "Seleziona Regola da Esportare", - "deleted_logs_toast": "Eliminati {count} log", - "delete_logs_dialog_title": "Eliminare i log?", - "deleting_logs_dialog_text": "Eliminazione di {count} log...", - "delete_logs_dialog_confirm_text": "Questo eliminerà i log in base al filtro corrente e alla query di ricerca. Questa azione non può essere annullata.", - "exported_logs_toast": "Log esportati!", - "export_logs_failed_toast": "Esportazione dei log fallita. Controlla logcat per maggiori dettagli.", - "export_logs_dialog_title": "Esportare i log?", - "exporting_logs_dialog_text": "Esportazione dei log in corso...", - "export_logs_dialog_confirm_text": "Questo esporterà i log in base al filtro corrente e alla query di ricerca.", - "export_as_button": "Esporta come {type}", - "filters_title": "Filtri", - "search_by_label": "Cerca per", - "newest_first_label": "Più recenti prima", - "since_label": "Da", - "until_label": "A", - "pick_a_date_button": "Scegli una data", - "search_placeholder": "Cerca", - "filter_button_description": "Filtro", - "clear_button_description": "Cancella", - "no_logs_found": "Nessun log trovato", - "log_event_format": "{event} in {conversation}", - "condition_only_inside_conversation": "Solo quando sono in una conversazione", - "condition_only_outside_conversation": "Solo quando sono fuori da una conversazione", - "condition_only_when_app_active": "Solo quando Snapchat è attivo", - "condition_only_when_app_inactive": "Solo quando Snapchat è inattivo", - "condition_no_push_notification_when_app_active": "Nessuna notifica push quando Snapchat è attivo", - "add_event_dialog_title": "Aggiungi Evento", - "event_type_label": "Tipo di evento", - "triggers_title": "Attivatori", - "conditions_title": "Condizioni", - "add_button": "Aggiungi", - "default_rule_name": "Regola Personalizzata", - "discard_changes_dialog_title": "Annullare le Modifiche?", - "discard_changes_dialog_text": "Hai modifiche non salvate. Sei sicuro di volerle annullare?", - "discard_button": "Annulla", - "cannot_save_rule_dialog_title": "Impossibile Salvare la Regola", - "cannot_save_rule_dialog_text": "Una regola deve avere almeno un evento per essere salvata.", - "duplicate_rule_name_dialog_title": "Nome Regola Duplicato", - "duplicate_rule_name_dialog_text": "Esiste già una regola con questo nome. Scegli un nome diverso.", - "delete_rule_dialog_title": "Elimina Regola", - "delete_rule_dialog_text": "Sei sicuro di voler eliminare questa regola?", - "new_rule_title": "Nuova Regola", - "edit_rule_title": "Modifica Regola", - "back_button_description": "Indietro", - "save_button_description": "Salva", - "general_section_title": "Generale", - "rule_name_label": "Nome Regola", - "author_name_label": "Nome Autore", - "scope_section_title": "Ambito", - "scope_all": "Tutti", - "scope_whitelist": "Lista Bianca", - "scope_blacklist": "Lista Nera", - "select_friends_groups_button": "Seleziona Amici/Gruppi ({count})", - "events_section_title": "Eventi", - "add_event_button": "Aggiungi Evento", - "no_events_text": "Nessun evento" - }, - "friend_tracker_catalog": { - "download_failed": "Download fallito: {code}", - "error": "Errore: {message}", - "no_repos_added": "Nessun repository aggiunto.", - "no_rules_available": "Nessuna regola disponibile da alcun repository.", - "by_author": "di {author}", - "imported_button": "Importato", - "import_button": "Importa", - "title": "Catalogo Tracciatore di Amici", - "manage_repos_description": "Gestisci Repository" - }, - "friend_tracker_export": { - "title": "Esporta Regole", - "back_button_description": "Indietro", - "exported_toast": "Regole del Tracciatore di Amici Esportate!", - "export_failed_toast": "Esportazione delle regole fallita: {message}", - "save_button": "Salva", - "expand_button_description": "Espandi" - }, - "friend_tracker_import": { - "title": "Importa Regole", - "back_button_description": "Indietro", - "imported_toast": "Regole del Tracciatore di Amici Importate!", - "import_failed_toast": "Importazione delle regole fallita: {message}", - "confirm_button": "Conferma", - "expand_button_description": "Espandi" - }, - "friend_tracker_repos": { - "invalid_repo_title": "Repository Non Valido", - "add_repo_button": "Aggiungi Repository", - "add_repo_dialog_title": "Aggiungi URL Repository", - "repo_url_label": "URL Repository", - "repo_added_toast": "Repository aggiunto con successo!", - "invalid_repo_error": "Questo non sembra essere un repository valido per il Tracciatore di Amici.", - "add_repo_failed_toast": "Aggiunta del repository fallita: {message}", - "add_button": "Aggiungi", - "no_repos_added": "Nessun repository aggiunto", - "remove_button": "Rimuovi", - "remove_repo_dialog_title": "Rimuovi Repository", - "remove_repo_dialog_text": "Sei sicuro di voler rimuovere questo repository?" - }, - "navigation": { - "tracker_tab_label": "Tracciatore", - "customize_bottom_bar_title": "Personalizza Barra Inferiore", - "customize_bottom_bar_subtitle": "Riordina, aggiungi o rimuovi schede. Massimo cinque.", - "shown_tabs_title": "Schede Mostrate", - "no_tabs_selected_text": "Nessuna scheda selezionata", - "available_tabs_title": "Schede Disponibili", - "reset_button": "Ripristina", - "done_button": "Fatto" - }, - "scripting": { - "script_already_installed": "Script già installato!", - "downloading_script": "Download dello script in corso...", - "script_downloaded": "Script {name} scaricato!", - "download_script_failed": "Download dello script fallito. Controlla i log per maggiori dettagli", - "import_script_from_url_title": "Importa Script da URL", - "import_script_warning": "Avviso: Gli script importati possono essere dannosi per il tuo dispositivo. Importa solo script da fonti attendibili.", - "enter_url_label": "Inserisci l'URL qui:", - "script_imported": "Script {name} importato!", - "import_failed": "Importazione dello script fallita. {message}. Controlla i log per maggiori dettagli", - "import_button": "Importa", - "update_module_button": "Aggiorna Modulo", - "updating_script": "Aggiornamento dello script {name}...", - "module_not_found": "Modulo non trovato", - "updated_script": "Aggiornato {name} alla versione {version}", - "update_module_failed": "Aggiornamento del modulo fallito. Controlla i log per maggiori dettagli", - "edit_module_button": "Modifica Modulo", - "open_module_failed": "Apertura del file del modulo fallita. Controlla i log per maggiori dettagli", - "clear_module_data_button": "Cancella Dati Modulo", - "module_data_cleared": "Dati del modulo cancellati!", - "clear_module_data_failed": "Cancellazione dei dati del modulo fallita. Controlla i log per maggiori dettagli", - "delete_module_button": "Elimina Modulo", - "deleted_script": "Script {name} eliminato!", - "delete_module_failed": "Eliminazione del modulo fallita. Controlla i log per maggiori dettagli", - "actions_title": "Azioni", - "no_description": "Nessuna descrizione", - "update_available": "Aggiornamento disponibile: {version}", - "actions_button": "Azioni", - "loaded_script": "Script {name} caricato", - "unloaded_script": "Script {name} scaricato", - "enable_script_failed": "Abilitazione dello script fallita. Controlla i log per maggiori dettagli", - "disable_script_failed": "Disabilitazione dello script fallita. Controlla i log per maggiori dettagli", - "select_scripts_folder_toast": "Seleziona la tua cartella degli script!", - "manage_repos_button": "Gestisci Repository", - "import_from_url_button": "Importa da URL", - "open_scripts_folder_button": "Apri Cartella Script", - "no_settings_for_module": "Questo modulo non ha impostazioni", - "installed_scripts_tab": "Script Installati", - "catalog_tab": "Catalogo", - "no_scripts_folder_selected_title": "Nessuna cartella degli script selezionata", - "select_folder_button": "Seleziona cartella", - "no_scripts_found_title": "Nessun script trovato.", - "use_catalog_to_add_scripts": "Usa la scheda catalogo per aggiungere script!", - "ok_button_timeout": "OK ({timeout})", - "documentation_button": "Documentazione", - "catalog": { - "script_already_installed": "Script già installato!", - "download_failed": "Download fallito: {code}", - "script_downloaded": "Script scaricato!", - "could_not_create_file": "Impossibile creare il file.", - "no_scripts_folder_selected": "Nessuna cartella degli script selezionata.", - "error": "Errore: {message}", - "no_repos_added": "Nessun repository aggiunto.", - "repo_list_info": "Qui puoi trovare un elenco di repository: ", - "link_text": "Collegamento", - "no_scripts_available": "Nessun script disponibile da alcun repository.", - "by_author": "di {author}", - "version": "Versione: {version}", - "installed_button": "Installato", - "download_button": "Scarica" - }, - "repos": { - "invalid_repo_title": "Repository Non Valido", - "add_repo_button": "Aggiungi Repository", - "add_repo_dialog_title": "Aggiungi URL Repository", - "repo_url_label": "URL Repository", - "repo_added_toast": "Repository aggiunto con successo!", - "invalid_repo_error": "Questo non sembra essere un repository di Script valido.", - "add_repo_failed_toast": "Aggiunta del repository fallita: {message}", - "add_button": "Aggiungi", - "no_repos_added": "Nessun repository aggiunto", - "remove_button": "Rimuovi", - "remove_repo_dialog_title": "Rimuovi Repository", - "remove_repo_dialog_text": "Sei sicuro di voler rimuovere questo repository?" - } - }, - "features": { - "config_import": { - "title": "Conferma Importazione", - "back_button_description": "Indietro", - "config_imported_toast": "Configurazione Importata!", - "confirm_button": "Conferma", - "expand_button_description": "Espandi", - "enable_feature": "Abilita Funzionalità", - "enabled": "Abilitato", - "disabled": "Disabilitato" - }, - "config_export": { - "title": "Riepilogo Esportazione", - "back_button_description": "Indietro", - "save_button": "Salva", - "expand_button_description": "Espandi", - "enable_feature": "Abilita Funzionalità", - "enabled": "Abilitato", - "disabled": "Disabilitato" - } - }, - "manage_repos": { - "title": "Gestisci repository {type}", - "add_repo_button": "Aggiungi Repository", - "add_repo_dialog_title": "Aggiungi URL Repository", - "repo_url_label": "URL Repository", - "repo_added_successfully": "Repository aggiunto con successo!", - "add_repo_failed": "Aggiunta del repository fallita: {message}", - "add_button": "Aggiungi", - "no_repos_added": "Nessun repository aggiunto", - "remove_button": "Rimuovi" - } - }, - "rules": { - "toasts": { - "enabled": "{ruleName} abilitato", - "disabled": "{ruleName} disabilitato" - }, - "modes": { - "blacklist": "Modalità lista nera", - "whitelist": "Modalità lista bianca" - }, - "properties": { - "auto_download": { - "name": "Download automatico", - "description": "Scarica automaticamente gli Snap durante la visualizzazione", - "options": { - "blacklist": "Escludi dal Download Automatico", - "whitelist": "Download Automatico" - } - }, - "stealth": { - "name": "Modalità Invisibile", - "description": "Impedisce a chiunque di sapere che hai aperto i loro Snap/Chat e conversazioni", - "options": { - "blacklist": "Escludi dalla Modalità Invisibile", - "whitelist": "Modalità invisibile" - } - }, - "auto_save": { - "name": "Salvataggio Automatico", - "description": "Salva i Messaggi di Chat durante la visualizzazione", - "options": { - "blacklist": "Escludi dal Salvataggio Automatico", - "whitelist": "Salvataggio automatico" - } - }, - "unsaveable_messages": { - "name": "Messaggi non Salvabili", - "description": "Impedisce che i messaggi vengano salvati in chat da altre persone", - "options": { - "blacklist": "Escludi dai Messaggi non Salvabili", - "whitelist": "Messaggi non Salvabili" - } - }, - "auto_open_snaps": { - "name": "Apri Snap Automaticamente", - "description": "Apre automaticamente gli Snap quando li ricevi", - "options": { - "blacklist": "Escludi dall'Apertura Automatica degli Snap", - "whitelist": "Apri Snap Automaticamente" - } - }, - "hide_friend_feed": { - "name": "Nascondi dal Feed Amici" - }, - "e2e_encryption": { - "name": "Usa Crittografia E2E" - }, - "pin_conversation": { - "name": "Fissa Conversazione" - }, - "exclude_message_logger": { - "name": "Escludi dal Logger Messaggi" - } - } - }, - "actions": { - "clean_snapchat_cache": { - "name": "Pulisci Cache di Snapchat", - "description": "Pulisce la Cache di Snapchat" - }, - "manage_friend_list": { - "name": "Gestisci Lista Amici", - "description": "Importa/esporta la tua lista di amici durante il backup" - }, - "export_chat_messages": { - "name": "Esporta Messaggi Chat", - "description": "Esporta i messaggi di conversazione in un file JSON/HTML/TXT" - }, - "export_memories": { - "name": "Esporta Ricordi", - "description": "Esporta i ricordi in un file ZIP" - }, - "bulk_messaging_action": { - "name": "Azione di Messaggistica di Massa", - "description": "Esegue operazioni come l'eliminazione di amici o l'eliminazione di massa di conversazioni" - }, - "regen_mappings": { - "name": "Rigenera Mappature", - "description": "Rigenera manualmente le mappature" - }, - "change_language": { - "name": "Cambia Lingua", - "description": "Cambia la lingua di PurrfectSnap" - }, - "file_imports": { - "name": "Importazioni File", - "description": "Importa file da utilizzare in Snapchat" - }, - "friend_tracker": { - "name": "Tracciatore di Amici", - "description": "Traccia i tuoi amici su Snapchat" - }, - "logger_history": { - "name": "Cronologia Logger", - "description": "Visualizza la cronologia dei messaggi registrati" - } - }, - "features": { - "notices": { - "unstable": "⚠️ Instabile", - "ban_risk": "⚠️ Questa funzionalità potrebbe causare ban", - "internal_behavior": "⚠️ Questo potrebbe compromettere il comportamento interno di Snapchat" - }, - "properties": { - "downloader": { - "name": "Downloader", - "description": "Scarica Media di Snapchat", - "properties": { - "save_folder": { - "name": "Salva Cartella", - "description": "Seleziona la directory in cui scaricare tutti i media" - }, - "auto_download_sources": { - "name": "Fonti di Download Automatico", - "description": "Seleziona le fonti da cui scaricare automaticamente" - }, - "prevent_self_auto_download": { - "name": "Impedisci Download Automatico Personale", - "description": "Impedisce il download automatico dei tuoi Snap" - }, - "path_format": { - "name": "Formato Percorso", - "description": "Specifica il Formato del Percorso del File" - }, - "allow_duplicate": { - "name": "Consenti Duplicati", - "description": "Consente di scaricare più volte lo stesso media" - }, - "merge_overlays": { - "name": "Unisci Sovrapposizioni", - "description": "Combina il Testo e il media di uno Snap in un unico file" - }, - "force_image_format": { - "name": "Forza Formato Immagine", - "description": "Forza il salvataggio delle immagini in un Formato specificato" - }, - "force_voice_note_format": { - "name": "Forza Formato Nota Vocale", - "description": "Forza il salvataggio delle Note Vocali in un Formato specificato" - }, - "auto_download_voice_notes": { - "name": "Download Automatico Note Vocali", - "description": "Scarica automaticamente le note vocali durante la riproduzione" - }, - "download_profile_pictures": { - "name": "Scarica Immagini del Profilo", - "description": "Consente di scaricare le Immagini del Profilo dalla pagina del profilo" - }, - "opera_download_button": { - "name": "Pulsante Download Opera", - "description": "Aggiunge un pulsante di download nell'angolo in alto a destra durante la visualizzazione di uno Snap.\nUna pressione prolungata sui pulsanti forzerà il download" - }, - "download_context_menu": { - "name": "Menu Contestuale di Download", - "description": "Consente di scaricare/visualizzare in anteprima i messaggi da una conversazione o una storia utilizzando il menu contestuale.\nUna pressione prolungata sui pulsanti forzerà il download" - }, - "ffmpeg_options": { - "name": "Opzioni FFmpeg", - "description": "Specifica opzioni FFmpeg aggiuntive", - "properties": { - "threads": { - "name": "Thread", - "description": "Il numero di thread da utilizzare" - }, - "preset": { - "name": "Preimpostazione", - "description": "Imposta la velocità della conversione" - }, - "constant_rate_factor": { - "name": "Fattore di Tasso Costante", - "description": "Imposta il fattore di tasso costante per il codificatore video\nDa 0 a 51 per libx264" - }, - "video_bitrate": { - "name": "Bitrate Video", - "description": "Imposta il bitrate del video (kbps)" - }, - "audio_bitrate": { - "name": "Bitrate Audio", - "description": "Imposta il bitrate dell'audio (kbps)" - }, - "custom_video_codec": { - "name": "Codec Video Personalizzato", - "description": "Imposta un Codec Video personalizzato (es. libx264)" - }, - "custom_audio_codec": { - "name": "Codec Audio Personalizzato", - "description": "Imposta un Codec Audio personalizzato (es. AAC)" - } - } - }, - "logging": { - "name": "Registrazione", - "description": "Mostra toast durante il download dei media" - }, - "custom_path_format": { - "name": "Formato Percorso Personalizzato", - "description": "Specifica un formato di percorso personalizzato per i media scaricati\n\nVariabili disponibili:\n - %username%\n - %source%\n - %hash%\n - %date_time%" - } - } - }, - "user_interface": { - "name": "Interfaccia Utente", - "description": "Cambia l'aspetto e la sensazione di Snapchat", - "properties": { - "enable_app_appearance": { - "name": "Abilita Impostazioni Aspetto App", - "description": "Abilita l'impostazione nascosta Aspetto App\nPotrebbe non essere richiesto nelle versioni più recenti di Snapchat" - }, - "friend_feed_message_preview": { - "name": "Anteprima Messaggio Feed Amici", - "description": "Mostra un'anteprima degli ultimi messaggi nel Feed Amici", - "properties": { - "amount": { - "name": "Quantità", - "description": "La quantità di messaggi da visualizzare in anteprima" - } - } - }, - "snap_preview": { - "name": "Anteprima Snap", - "description": "Visualizza una piccola anteprima accanto agli Snap non visti in chat" - }, - "bootstrap_override": { - "name": "Sovrascrittura Bootstrap", - "description": "Sovrascrive le impostazioni di bootstrap dell'interfaccia utente", - "properties": { - "app_appearance": { - "name": "Aspetto App", - "description": "Imposta un Aspetto App persistente" - }, - "home_tab": { - "name": "Scheda Home", - "description": "Sovrascrive la scheda di avvio all'apertura di Snapchat" - } - } - }, - "force_amoled_theme": { - "name": "Modalità Scura Amoled", - "description": "Utilizza uno sfondo nero puro per il tema scuro" - }, - "map_friend_nametags": { - "name": "Etichette Nome Amici Mappa Migliorate", - "description": "Migliora le Etichette Nome degli amici su Snapmap" - }, - "prevent_message_list_auto_scroll": { - "name": "Impedisci Scorrimento Automatico Elenco Messaggi", - "description": "Impedisce all'elenco dei messaggi di scorrere verso il basso durante l'invio/ricezione di un messaggio" - }, - "streak_expiration_info": { - "name": "Mostra Info Scadenza Streak", - "description": "Mostra un timer di Scadenza Streak accanto al contatore delle Streak" - }, - "hide_friend_feed_entry": { - "name": "Nascondi Voce Feed Amici", - "description": "Nasconde un amico specifico dal Feed Amici\nUsa la scheda social per gestire questa funzionalità" - }, - "hide_streak_restore": { - "name": "Nascondi Ripristino Streak", - "description": "Nasconde il pulsante Ripristina nel feed amici" - }, - "hide_quick_add_suggestions": { - "name": "Nascondi Suggerimenti Aggiunta Rapida", - "description": "Rimuove i suggerimenti di amici per l'aggiunta rapida" - }, - "hide_story_suggestions": { - "name": "Nascondi Suggerimenti Storie", - "description": "Rimuove i suggerimenti dalla pagina Storie" - }, - "hide_ui_components": { - "name": "Nascondi Componenti UI", - "description": "Seleziona quali componenti UI nascondere" - }, - "opera_media_quick_info": { - "name": "Info Rapide Media Opera", - "description": "Mostra informazioni utili sui media come la data di creazione nel menu contestuale del visualizzatore opera" - }, - "old_bitmoji_selfie": { - "name": "Selfie Bitmoji Vecchio", - "description": "Ripristina i selfie Bitmoji dalle versioni più vecchie di Snapchat" - }, - "disable_spotlight": { - "name": "Disabilita Spotlight", - "description": "Disabilita la pagina Spotlight" - }, - "friend_feed_menu_buttons": { - "name": "Pulsanti Menu Feed Amici", - "description": "Seleziona quali pulsanti mostrare nel Menu Feed Amici" - }, - "auto_close_friend_feed_menu": { - "name": "Chiudi Automaticamente Menu Feed Amici", - "description": "Chiude automaticamente il Menu Feed Amici dopo aver premuto un pulsante di impostazione" - }, - "vertical_story_viewer": { - "name": "Visualizzatore Storie Verticale", - "description": "Abilita il visualizzatore di storie verticale per tutte le storie" - }, - "enable_friend_feed_menu_bar": { - "name": "Barra Menu Feed Amici", - "description": "Abilita la nuova Barra Menu Feed Amici" - }, - "message_indicators": { - "name": "Indicatori Messaggio", - "description": "Aggiunge icone di indicatori specifici ai messaggi\nNota: Gli indicatori potrebbero non essere precisi al 100%" - }, - "stealth_mode_indicator": { - "name": "Indicatore Modalità Invisibile", - "description": "Aggiunge un'emoji 👻 accanto alle conversazioni in modalità invisibile" - }, - "edit_text_override": { - "name": "Sovrascrittura Modifica Testo", - "description": "Sovrascrive il comportamento del campo di testo" - }, - "prevent_forced_keyboard": { - "name": "Impedisci Tastiera Forzata", - "description": "Impedisce a Snapchat di far apparire automaticamente la tastiera quando apri una conversazione" - }, - "settings_menu": { - "name": "Menu Impostazioni", - "description": "Modifica il modo in cui apri il menu di PurrfectSnap", - "options": { - "default": "Predefinito", - "legacy": "Eredità" - } - } - } - }, - "messaging": { - "name": "Messaggistica", - "description": "Cambia il modo in cui interagisci con gli amici", - "properties": { - "bypass_screenshot_detection": { - "name": "Bypassa Rilevamento Screenshot", - "description": "Impedisce a Snapchat di rilevare quando fai uno screenshot" - }, - "anonymous_story_viewing": { - "name": "Visualizzazione Anonima delle Storie", - "description": "Impedisce a chiunque di sapere che hai visto la loro storia" - }, - "prevent_story_rewatch_indicator": { - "name": "Impedisci Indicatore Riguarda Storia", - "description": "Impedisce a chiunque di sapere che hai riguardato la loro storia" - }, - "hide_peek_a_peek": { - "name": "Nascondi Sbircia", - "description": "Impedisce l'invio di notifiche quando fai uno swipe parziale in una chat" - }, - "hide_bitmoji_presence": { - "name": "Nascondi Presenza Bitmoji", - "description": "Impedisce al tuo Bitmoji di apparire durante una Chat" - }, - "hide_typing_notifications": { - "name": "Nascondi Notifiche di Digitazione", - "description": "Impedisce a chiunque di sapere che stai digitando un messaggio" - }, - "unlimited_snap_view_time": { - "name": "Tempo di Visualizzazione Snap Illimitato", - "description": "Rimuove il Limite di Tempo per la visualizzazione degli Snap" - }, - "auto_mark_as_read": { - "name": "Segna Automaticamente come Letto", - "description": "Segna automaticamente messaggi/snap come letti anche quando la Modalità Invisibile è abilitata" - }, - "mark_snap_as_seen_button": { - "name": "Pulsante Segna Snap come Visto", - "description": "Aggiunge un pulsante per segnare uno Snap come visto durante la visualizzazione.\nFunzionerà anche quando la Modalità Invisibile è abilitata" - }, - "skip_when_marking_as_seen": { - "name": "Salta quando si Segna come Visto", - "description": "Salta automaticamente allo Snap successivo quando si segna uno Snap come visto.\nUsa in combinazione con il Pulsante Segna Snap come Visto" - }, - "loop_media_playback": { - "name": "Riproduzione Media in Loop", - "description": "Riproduce i media in loop durante la visualizzazione di Snap/Storie" - }, - "disable_replay_in_ff": { - "name": "Disabilita Riproduzione in FF", - "description": "Disabilita la possibilità di riprodurre con una pressione prolungata dal Feed Amici" - }, - "half_swipe_notifier": { - "name": "Notificatore di Mezzo Swipe", - "description": "Ti notifica quando qualcuno fa un mezzo swipe in una conversazione", - "properties": { - "min_duration": { - "name": "Durata Minima", - "description": "La durata minima del mezzo swipe (in secondi)" - }, - "max_duration": { - "name": "Durata Massima", - "description": "La durata massima del mezzo swipe (in secondi)" - } - } - }, - "call_start_confirmation": { - "name": "Conferma Inizio Chiamata", - "description": "Mostra una finestra di dialogo di conferma all'avvio di una chiamata" - }, - "unlimited_conversation_pinning": { - "name": "Fissaggio Conversazioni Illimitato", - "description": "Consente di fissare un numero illimitato di conversazioni localmente" - }, - "disable_snap_mode_restrictions": { - "name": "Disabilita Restrizioni Modalità Snap", - "description": "Consente di visualizzare gli Snap autodistruttivi senza restrizioni" - }, - "prevent_message_sending": { - "name": "Impedisci Invio Messaggio", - "description": "Impedisce l'invio di determinati tipi di messaggi" - }, - "friend_mutation_notifier": { - "name": "Notificatore Mutazione Amico", - "description": "Ti notifica quando qualcosa cambia nel profilo di un amico" - }, - "better_notifications": { - "name": "Notifiche Migliori", - "description": "Aggiunge più informazioni alle notifiche ricevute", - "properties": { - "group_notifications": { - "name": "Notifiche di Gruppo", - "description": "Raggruppa le notifiche in una sola" - }, - "chat_preview": { - "name": "Anteprima Chat", - "description": "Mostra un'anteprima dei messaggi ricevuti nella notifica" - }, - "media_preview": { - "name": "Anteprima Media", - "description": "Mostra un'anteprima dei tipi di media selezionati nella notifica" - }, - "media_caption": { - "name": "Didascalia Media", - "description": "Mostra la didascalia allegata dei media nella notifica" - }, - "stacked_media_messages": { - "name": "Messaggi Media Impilati", - "description": "Combina più messaggi media in una notifica di testo quando non possono essere visualizzati in anteprima. Usa in combinazione con Anteprima Chat" - }, - "friend_add_source": { - "name": "Fonte Aggiunta Amico", - "description": "Mostra la fonte di una richiesta di amicizia nella notifica" - }, - "reply_button": { - "name": "Pulsante Rispondi", - "description": "Aggiunge un pulsante di risposta alla notifica" - }, - "smart_replies": { - "name": "Risposte Intelligenti", - "description": "Aggiunge risposte suggerite alle notifiche (Android 10+). Usa in combinazione con il Pulsante Rispondi" - }, - "download_button": { - "name": "Pulsante Download", - "description": "Consente di scaricare i media dalla notifica" - }, - "mark_as_read_button": { - "name": "Pulsante Segna come Letto", - "description": "Consente di segnare un messaggio come letto dalla notifica" - }, - "mark_as_read_and_save_in_chat": { - "name": "Segna come Letto e Salva in Chat", - "description": "Aggiunge un pulsante segna come letto e salva in chat alla notifica" - } - } - }, - "notification_blacklist": { - "name": "Lista Nera Notifiche", - "description": "Seleziona quali notifiche devono essere bloccate" - }, - "message_logger": { - "name": "Logger Messaggi", - "description": "Impedisce l'eliminazione dei messaggi", - "properties": { - "keep_my_own_messages": { - "name": "Conserva i Miei Messaggi", - "description": "Impedisce l'eliminazione dei tuoi messaggi" - }, - "auto_purge": { - "name": "Eliminazione Automatica", - "description": "Elimina automaticamente i messaggi memorizzati nella cache più vecchi della quantità di tempo specificata" - }, - "message_filter": { - "name": "Filtro Messaggi", - "description": "Seleziona quali messaggi devono essere registrati (vuoto per tutti i messaggi)" - }, - "deleted_message_color": { - "name": "Colore Messaggio Eliminato", - "description": "Imposta il colore dei messaggi eliminati" - } - } - }, - "auto_save_messages_in_conversations": { - "name": "Salva Messaggi Automaticamente", - "description": "Salva automaticamente ogni messaggio nelle conversazioni" - }, - "gallery_media_send_override": { - "name": "Sovrascrittura Invio Media Galleria", - "description": "Falsifica la fonte dei media durante l'invio dalla Galleria" - }, - "strip_media_metadata": { - "name": "Rimuovi Metadati Media", - "description": "Rimuove i metadati dei media prima di inviarli come messaggio" - }, - "bypass_message_retention_policy": { - "name": "Bypassa Politica di Conservazione Messaggi", - "description": "Impedisce l'eliminazione dei messaggi dopo averli visualizzati" - }, - "bypass_message_action_restrictions": { - "name": "Bypassa Restrizioni Azione Messaggio", - "description": "Consente di reagire a uno snap senza averlo aperto o di salvare un messaggio non salvabile" - }, - "remove_groups_locked_status": { - "name": "Rimuovi Stato Bloccato Gruppi", - "description": "Consente di visualizzare le informazioni del gruppo dopo essere stati espulsi" - }, - "double_tap_chat_action": { - "name": "Azione Chat Doppio Tocco", - "description": "Esegue un'azione personalizzata quando si tocca due volte un messaggio in chat" - }, - "double_tap_chat_action_custom_emoji": { - "name": "Reazione Emoji Personalizzata Azione Chat Doppio Tocco", - "description": "Imposta una reazione emoji personalizzata per l'azione di chat a doppio tocco" - } - } - }, - "global": { - "name": "Globale", - "description": "Modifica Impostazioni Globali di Snapchat", - "properties": { - "better_location": { - "name": "Posizione Migliore", - "description": "Migliora la Posizione di Snapchat", - "properties": { - "spoof_location": { - "name": "Posizione Falsa", - "description": "Falsifica la tua posizione in una specificata" - }, - "coordinates": { - "name": "Coordinate", - "description": "Imposta le coordinate della posizione falsificata" - }, - "walk_radius": { - "name": "Raggio di Camminata", - "description": "Cammina casualmente all'interno di questo raggio (piedi)" - }, - "always_update_location": { - "name": "Aggiorna Sempre la Posizione", - "description": "Forza Snapchat ad aggiornare la posizione anche se non vengono ricevuti dati GPS" - }, - "suspend_location_updates": { - "name": "Sospendi Aggiornamenti Posizione", - "description": "Impedisce l'aggiornamento della tua posizione" - }, - "spoof_battery_level": { - "name": "Livello Batteria Falso", - "description": "Falsifica il livello della batteria del tuo dispositivo sulla mappa\nIl valore deve essere compreso tra 0 e 100" - }, - "spoof_headphones": { - "name": "Cuffie False", - "description": "Falsifica lo stato di ascolto della musica sulla mappa" - }, - "show_battery_level": { - "name": "Mostra Livello Batteria", - "description": "Mostra il livello della batteria dei tuoi amici sulla mappa" - } - } - }, - "snapchat_plus": { - "name": "Snapchat Plus", - "description": "Abilita le funzionalità di Snapchat Plus\nAlcune funzionalità lato server potrebbero non funzionare" - }, - "media_upload_quality": { - "name": "Qualità Caricamento Media", - "description": "Sovrascrive la qualità di caricamento dei media", - "properties": { - "force_video_upload_source_quality": { - "name": "Forza Qualità Sorgente Caricamento Video", - "description": "Forza Snapchat a utilizzare la qualità sorgente durante il caricamento dei video\nNota che questo potrebbe non rimuovere i metadati dai media" - }, - "disable_image_compression": { - "name": "Disabilita Compressione Immagini", - "description": "Disabilita la compressione delle immagini durante il caricamento dei media" - }, - "custom_image_upload_format": { - "name": "Formato Caricamento Immagine Personalizzato", - "description": "Imposta un formato di caricamento immagine personalizzato\nSeleziona un formato senza perdita (come PNG) per la migliore qualità" - } - } - }, - "disable_confirmation_dialogs": { - "name": "Disabilita Finestre di Conferma", - "description": "Conferma automaticamente le azioni selezionate" - }, - "auto_updater": { - "name": "Aggiornamento Automatico", - "description": "Controlla automaticamente la presenza di nuovi aggiornamenti" - }, - "disable_metrics": { - "name": "Disabilita Metriche", - "description": "Blocca l'invio di dati analitici specifici a Snapchat" - }, - "disable_story_sections": { - "name": "Disabilita Sezioni Storie", - "description": "Rimuove le sezioni dalla pagina Storie\nPotrebbe essere necessario un aggiornamento per funzionare correttamente" - }, - "block_ads": { - "name": "Blocca Annunci", - "description": "Impedisce la visualizzazione di Annunci" - }, - "disable_custom_tabs": { - "name": "Disabilita Schede Personalizzate", - "description": "Apre i link nelle applicazioni supportate anziché nel Browser Web" - }, - "disable_permission_requests": { - "name": "Disabilita Richieste di Permesso", - "description": "Impedisce a Snapchat di chiedere permessi specifici" - }, - "disable_memories_snap_feed": { - "name": "Disabilita Feed Snap Ricordi", - "description": "Impedisce a Snapchat di mostrare i ricordi recenti quando scorri verso l'alto nella fotocamera" - }, - "spotlight_comments_username": { - "name": "Nome Utente Commenti Spotlight", - "description": "Mostra il nome utente dell'autore nei commenti di Spotlight" - }, - "bypass_video_length_restriction": { - "name": "Bypassa Restrizioni Lunghezza Video", - "description": "Singolo: invia un singolo video\nDiviso: divide i video dopo la modifica" - }, - "default_video_playback_rate": { - "name": "Velocità di Riproduzione Video Predefinita", - "description": "Imposta la velocità predefinita per la riproduzione dei video\nIl valore deve essere compreso tra 0.1 e 4.0" - }, - "video_playback_rate_slider": { - "name": "Cursore Velocità di Riproduzione Video", - "description": "Aggiunge un cursore nel menu contestuale di opera per modificare la velocità di riproduzione del video\nNota: Le modifiche si applicano solo ai video successivi" - }, - "disable_google_play_dialogs": { - "name": "Disabilita Finestre di Dialogo di Google Play Services", - "description": "Impedisce la visualizzazione delle finestre di dialogo sulla disponibilità di Google Play Services" - }, - "default_volume_controls": { - "name": "Controlli Volume Predefiniti", - "description": "Forza Snapchat a utilizzare i controlli del volume di sistema" - }, - "disable_telecom_framework": { - "name": "Disabilita Framework Telecom", - "description": "Impedisce a Snapchat di utilizzare il framework Telecom di Android\nQuesto ti consente di ascoltare la musica durante una chiamata" - }, - "hide_active_music": { - "name": "Nascondi Musica Attiva", - "description": "Impedisce a Snapchat di sapere che stai ascoltando musica\nQuesto ti consentirà di scattare snap utilizzando i pulsanti di controllo del volume mentre ascolti la musica" - }, - "disable_snap_splitting": { - "name": "Disabilita Divisione Snap", - "description": "Impedisce la divisione degli Snap in più parti\nLe immagini che invii si trasformeranno in video" - } - } - }, - "rules": { - "name": "Regole", - "description": "Gestisci Funzionalità Automatiche per singole persone" - }, - "camera": { - "name": "Fotocamera", - "description": "Regola le impostazioni giuste per lo snap perfetto", - "properties": { - "disable_cameras": { - "name": "Disabilita Fotocamere", - "description": "Impedisce a Snapchat di utilizzare le fotocamere selezionate" - }, - "black_photos": { - "name": "Foto Nere", - "description": "Sostituisce le foto scattate con uno sfondo nero\nI video non sono interessati" - }, - "immersive_camera_preview": { - "name": "Anteprima Immersiva", - "description": "Impedisce a Snapchat di ritagliare l'anteprima della fotocamera\nQuesto potrebbe causare lo sfarfallio della fotocamera su alcuni dispositivi" - }, - "override_front_resolution": { - "name": "Sovrascrivi Risoluzione Anteriore", - "description": "Sovrascrive la risoluzione della fotocamera per la fotocamera anteriore" - }, - "override_back_resolution": { - "name": "Sovrascrivi Risoluzione Posteriore", - "description": "Sovrascrive la risoluzione della fotocamera per la fotocamera posteriore" - }, - "custom_resolution": { - "name": "Risoluzione Personalizzata", - "description": "Imposta una risoluzione della fotocamera personalizzata, larghezza x altezza (es. 1920x1080).\nLa risoluzione personalizzata deve essere supportata dal tuo dispositivo" - }, - "front_custom_frame_rate": { - "name": "Frequenza Fotogrammi Personalizzata Anteriore", - "description": "Sovrascrive la frequenza dei fotogrammi della fotocamera anteriore" - }, - "back_custom_frame_rate": { - "name": "Frequenza Fotogrammi Personalizzata Posteriore", - "description": "Sovrascrive la frequenza dei fotogrammi della fotocamera posteriore" - }, - "force_camera_source_encoding": { - "name": "Forza Codifica Sorgente Fotocamera", - "description": "Forza la codifica della sorgente della fotocamera" - }, - "startup_default_camera": { - "name": "Fotocamera Predefinita all'Avvio", - "description": "Imposta la fotocamera predefinita all'apertura di Snapchat" - }, - "hevc_recording": { - "name": "Registrazione HEVC", - "description": "Utilizza il codec HEVC (H.265) per la registrazione video" - } - } - }, - "streaks_reminder": { - "name": "Promemoria Streak", - "description": "Ti notifica periodicamente riguardo alle tue Streak", - "properties": { - "interval": { - "name": "Intervallo", - "description": "L'intervallo tra ogni promemoria (ore)" - }, - "remaining_hours": { - "name": "Tempo Rimanente", - "description": "La quantità di tempo rimanente prima che venga mostrata la notifica (ore)" - }, - "group_notifications": { - "name": "Notifiche di Gruppo", - "description": "Raggruppa le notifiche in una sola" - } - } - }, - "experimental": { - "name": "Sperimentale", - "description": "Funzionalità sperimentali", - "properties": { - "native_hooks": { - "name": "Hook Nativi", - "description": "Funzionalità non sicure che si agganciano al codice nativo di Snapchat", - "properties": { - "composer_hooks": { - "name": "Hook del Compositore", - "description": "Inietta codice nel framework UI multipiattaforma del Compositore", - "properties": { - "show_first_created_username": { - "name": "Mostra Primo Nome Utente Creato", - "description": "Mostra il primo nome utente creato accanto al nome utente corrente nella pagina del profilo" - }, - "bypass_camera_roll_limit": { - "name": "Bypassa Limite Rullino Fotografico", - "description": "Aumenta la quantità massima di media che puoi inviare dal rullino fotografico" - }, - "custom_self_destruct_snap_delay": { - "name": "Ritardo Snap Autodistruttivo Personalizzato", - "description": "Offre più opzioni per il timer di autodistruzione durante l'invio di uno Snap" - }, - "composer_console": { - "name": "Console del Compositore", - "description": "Consente di eseguire codice JavaScript nel Compositore (solo arm64)" - }, - "composer_logs": { - "name": "Log del Compositore", - "description": "Reindirizza i log della console del Compositore a PurrfectSnap" - } - } - }, - "disable_bitmoji": { - "name": "Disabilita Bitmoji", - "description": "Disabilita il Bitmoji del Profilo Amici" - }, - "custom_emoji_font": { - "name": "Carattere Emoji Personalizzato", - "description": "Consente di utilizzare un carattere emoji personalizzato. Funziona solo con i caratteri .ttf" - }, - "custom_shared_library": { - "name": "Libreria Condivisa Personalizzata", - "description": "Carica una libreria condivisa personalizzata in Snapchat. Questa funzionalità è solo a scopo di test" - } - } - }, - "spoof": { - "name": "Falso", - "description": "Falsifica varie informazioni su di te", - "properties": { - "play_store_installer_package_name": { - "name": "Nome Pacchetto Installatore Play Store", - "description": "Sovrascrive il nome del pacchetto dell'installatore a com.android.vending" - }, - "remove_vpn_transport_flag": { - "name": "Rimuovi Flag Trasporto VPN", - "description": "Impedisce a Snapchat di rilevare le VPN" - }, - "remove_mock_location_flag": { - "name": "Rimuovi Flag Posizione Fittizia", - "description": "Impedisce a Snapchat di rilevare la Posizione Fittizia" - } - } - }, - "convert_message_locally": { - "name": "Converti Messaggio Localmente", - "description": "Converte gli snap in media esterni della chat localmente. Questo appare nel menu contestuale di download della chat" - }, - "media_file_picker": { - "name": "Selettore File Media", - "description": "Consente di scegliere qualsiasi file video/audio dalla galleria" - }, - "story_logger": { - "name": "Logger Storie", - "description": "Fornisce una cronologia delle storie degli amici" - }, - "call_recorder": { - "name": "Registratore Chiamate", - "description": "Registra automaticamente le chiamate audio" - }, - "account_switcher": { - "name": "Cambio Account", - "description": "Consente di passare da un account all'altro senza effettuare il logout\nPremi a lungo sull'icona di ricerca accanto al tuo profilo Bitmoji per aprire il menu\nNota: Questa funzionalità è sperimentale e probabilmente cambierà in futuro", - "properties": { - "auto_backup_current_account": { - "name": "Backup Automatico Account Corrente", - "description": "Esegue automaticamente il backup dell'account corrente durante il logout o il cambio di account" - } - } - }, - "better_transcript": { - "name": "Trascrizione Migliore", - "description": "Migliora la trascrizione delle note vocali", - "properties": { - "force_transcription": { - "name": "Forza Trascrizione Nota Vocale", - "description": "Consente di trascrivere tutte le note vocali" - }, - "preferred_transcription_lang": { - "name": "Lingua di Trascrizione Preferita", - "description": "La lingua preferita per la trascrizione delle note vocali (es. EN, ES, FR)" - }, - "notification_transcript": { - "name": "Trascrizione Notifica", - "description": "Trascrive le note vocali nelle notifiche\nQuesta funzionalità richiede che la funzione Anteprima Chat sia abilitata in Notifiche Migliori" - } - } - }, - "voice_note_auto_play": { - "name": "Riproduzione Automatica Nota Vocale", - "description": "Riproduce automaticamente la nota vocale successiva al termine di quella corrente" - }, - "friend_notes": { - "name": "Note Amico", - "description": "Consente di aggiungere note ai profili degli amici" - }, - "cof_experiments": { - "name": "Esperimenti COF", - "description": "Abilita funzionalità Snapchat non rilasciate/beta" - }, - "context_menu_fix": { - "name": "Correzione Menu Contestuale", - "description": "Tenta di riparare il Menu Feed Amici poiché quando il dispositivo è offline non può essere visualizzato correttamente" - }, - "app_lock": { - "name": "Blocco App", - "description": "Impedisce l'accesso a Snapchat senza un codice di accesso", - "properties": { - "lock_on_resume": { - "name": "Blocca alla Ripresa", - "description": "Blocca l'app quando viene riaperta" - } - } - }, - "infinite_story_boost": { - "name": "Potenziamento Storia Infinito", - "description": "Bypassa il ritardo del Limite di Potenziamento Storia" - }, - "meo_passcode_bypass": { - "name": "Bypass Codice di Accesso My Eyes Only", - "description": "Bypassa il codice di accesso di My Eyes Only\nFunzionerà solo se il codice di accesso è stato inserito correttamente in precedenza" - }, - "no_friend_score_delay": { - "name": "Nessun Ritardo Punteggio Amico", - "description": "Rimuove il ritardo durante la visualizzazione del Punteggio di un Amico" - }, - "best_friend_pinning": { - "name": "Fissaggio Migliore Amico", - "description": "Consente di fissare un amico come il tuo migliore amico numero uno. Nota: Solo tu puoi vedere il tuo migliore amico fissato" - }, - "e2ee": { - "name": "Crittografia End-To-End", - "description": "Cripta i tuoi messaggi con AES utilizzando una chiave segreta condivisa\nAssicurati di salvare la tua chiave in un posto sicuro!", - "properties": { - "encrypted_message_indicator": { - "name": "Indicatore Messaggio Criptato", - "description": "Aggiunge un'emoji 🔒 accanto ai messaggi criptati" - }, - "force_message_encryption": { - "name": "Forza Crittografia Messaggio", - "description": "Impedisce l'invio di messaggi criptati a persone che non hanno la Crittografia E2E abilitata solo quando sono selezionate più conversazioni" - } - } - }, - "add_friend_source_spoof": { - "name": "Falsifica Fonte Aggiunta Amico", - "description": "Falsifica la fonte di una Richiesta di Amicizia" - }, - "hidden_snapchat_plus_features": { - "name": "Funzionalità Nascoste di Snapchat Plus", - "description": "Abilita funzionalità Snapchat Plus non rilasciate/beta\nPotrebbe non funzionare sulle versioni più vecchie di Snapchat" - }, - "custom_streaks_expiration_format": { - "name": "Formato Scadenza Streak Personalizzato", - "description": "Personalizza il formato di Scadenza delle Streak\n\nVariabili disponibili:\n - %c: Conteggio Streak\n - %e: Emoji Clessidra\n - %d: Giorni\n - %h: Ore\n - %m: Minuti\n - %s: Secondi\n - %w: Tempo Rimanente" - }, - "prevent_forced_logout": { - "name": "Impedisci Logout Forzato", - "description": "Impedisce a Snapchat di disconnetterti quando accedi da un altro dispositivo" - }, - "snapscore_changes": { - "name": "Cambiamenti Snapscore", - "description": "Traccia i cambiamenti nello Snapscore degli amici\nUsa questa funzionalità solo nelle versioni più recenti di Snapchat" - } - } - }, - "scripting": { - "name": "Scrittura", - "description": "Esegui script personalizzati per estendere PurrfectSnap", - "properties": { - "developer_mode": { - "name": "Modalità Sviluppatore", - "description": "Mostra informazioni di debug sull'interfaccia utente di Snapchat" - }, - "module_folder": { - "name": "Cartella Modulo", - "description": "La cartella in cui si trovano gli script" - }, - "auto_reload": { - "name": "Ricarica Automatica", - "description": "Ricarica automaticamente gli script quando cambiano" - }, - "integrated_ui": { - "name": "UI Integrata", - "description": "Consente agli script di aggiungere componenti UI personalizzati a Snapchat" - }, - "disable_log_anonymization": { - "name": "Disabilita Anonimizzazione Log", - "description": "Disabilita l'anonimizzazione dei log" - }, - "disable_optimization": { - "name": "Disabilita Ottimizzazione", - "description": "Disabilita l'ottimizzazione degli script. Ciò potrebbe causare problemi di prestazioni." - } - } - }, - "friend_tracker": { - "name": "Tracciatore di Amici", - "description": "Registra l'attività degli amici su Snapchat", - "properties": { - "record_messaging_events": { - "name": "Registra Eventi di Messaggistica", - "description": "Registra eventi di messaggistica come l'apertura di uno snap, la lettura di un messaggio, ecc." - }, - "allow_running_in_background": { - "name": "Consenti Esecuzione in Background", - "description": "Consente al tracciatore di funzionare in background. Nota: Ciò consumerà notevolmente la batteria" - }, - "auto_purge": { - "name": "Eliminazione Automatica", - "description": "Elimina automaticamente gli eventi memorizzati nella cache più vecchi della quantità di tempo specificata" - } - } - } - }, - "options": { - "app_appearance": { - "always_light": "Sempre Chiaro", - "always_dark": "Sempre Scuro" - }, - "friend_feed_menu_buttons": { - "auto_download": "⬇️ Download Automatico", - "auto_save": "💬 Salva Messaggi Automaticamente", - "unsaveable_messages": "⬇️ Messaggi non Salvabili", - "auto_open_snaps": "📸 Apri Snap Automaticamente", - "stealth": "👻 Modalità Invisibile", - "mark_snaps_as_seen": "👀 Segna Snap come visti", - "mark_stories_as_seen_locally": "👀 Segna Storie come viste localmente", - "conversation_info": "🧑‍🤝‍🧑 Info Conversazione", - "e2e_encryption": "🔒 Usa Crittografia E2E" - }, - "path_format": { - "create_author_folder": "Crea cartella per ogni autore", - "create_source_folder": "Crea cartella per ogni tipo di fonte multimediale", - "append_hash": "Aggiungi un hash univoco al nome del file", - "append_source": "Aggiungi la fonte multimediale al nome del file", - "append_username": "Aggiungi il nome utente al nome del file", - "append_date_time": "Aggiungi la data e l'ora al nome del file" - }, - "auto_download_sources": { - "friend_snaps": "Snap Amici", - "friend_stories": "Storie Amici", - "public_stories": "Storie Pubbliche", - "spotlight": "Riflettore" - }, - "logging": { - "started": "Avviato", - "success": "Successo", - "progress": "Progresso", - "failure": "Fallimento" - }, - "notifications": { - "chat_screenshot": "Schermata", - "chat_screen_record": "Registrazione Schermo", - "snap_replay": "Riproduzione Snap", - "camera_roll_save": "Salva nel Rullino Fotografico", - "chat": "Chiacchierata", - "chat_reply": "Risposta Chat", - "snap": "Affrettato", - "typing": "Sta scrivendo", - "stories": "Storie", - "speaking": "Sta parlando", - "chat_reaction": "Reazione DM", - "group_chat_reaction": "Reazione di Gruppo", - "initiate_audio": "Chiamata Audio in Arrivo", - "abandon_audio": "Chiamata Audio Persa", - "initiate_video": "Videochiamata in Arrivo", - "abandon_video": "Videochiamata Persa", - "map_live_location": "Posizione Live Mappa" - }, - "gallery_media_send_override": { - "always_ask": "Chiedi Sempre", - "ORIGINAL": "Media Originale", - "NOTE": "Nota Audio", - "SNAP": "Affrettato", - "SAVEABLE_SNAP": "Snap Salvabile" - }, - "strip_media_metadata": { - "hide_caption_text": "Nascondi Testo Didascalia", - "hide_snap_filters": "Nascondi Filtri Snap", - "hide_extras": "Nascondi Extra (es. menzioni)", - "remove_audio_note_duration": "Rimuovi Durata Nota Audio", - "remove_audio_note_transcript_capability": "Rimuovi Capacità di Trascrizione Nota Audio" - }, - "hide_ui_components": { - "hide_profile_call_buttons": "Rimuovi Pulsanti Chiamata Profilo", - "hide_chat_call_buttons": "Rimuovi Pulsanti Chiamata Chat", - "hide_live_location_share_button": "Rimuovi Pulsante Condivisione Posizione Live", - "hide_stickers_button": "Rimuovi Pulsante Adesivi", - "hide_voice_record_button": "Rimuovi Pulsante Registrazione Vocale", - "hide_unread_chat_hint": "Rimuovi Suggerimento Chat non Letta", - "hide_post_to_story_buttons": "Rimuovi pulsanti Pubblica su Storia prima di inviare uno Snap", - "hide_billboard_prompt": "Rimuovi Prompt Cartellone nel Feed Amici", - "hide_snapchat_plus_gift_reminders": "Rimuovi promemoria regali Snapchat Plus nelle conversazioni", - "hide_map_reactions": "Rimuovi Reazioni Mappa" - }, - "hide_story_suggestions": { - "hide_suggested_friend_stories": "Nascondi storie di amici suggerite", - "hide_my_stories": "Nascondi le Mie Storie" - }, - "home_tab": { - "map": "Mappa", - "chat": "Chiacchierata", - "camera": "Fotocamera", - "discover": "Scopri", - "spotlight": "Riflettore" - }, - "add_friend_source_spoof": { - "added_by_username": "Per Nome Utente", - "added_by_mention": "Per Menzione", - "added_by_group_chat": "Per Chat di Gruppo", - "added_by_qr_code": "Per Codice QR", - "added_by_community": "Per Comunità", - "added_by_quick_add": "Per Aggiunta Rapida (alto rischio di ban)" - }, - "bypass_video_length_restriction": { - "single": "Media singolo", - "split": "Media diviso" - }, - "old_bitmoji_selfie": { - "2d": "Bitmoji 2D", - "3d": "Bitmoji 3D" - }, - "disable_confirmation_dialogs": { - "erase_message": "Cancella Messaggio", - "remove_friend": "Rimuovi Amico", - "block_friend": "Blocca Amico", - "ignore_friend": "Ignora Amico", - "hide_friend": "Nascondi Amico", - "hide_conversation": "Nascondi Conversazione", - "clear_conversation": "Cancella Conversazione dal Feed Amici" - }, - "auto_reload": { - "snapchat_only": "Solo Snapchat", - "all": "Tutti (Snapchat + PurrfectSnap)" - }, - "edit_text_override": { - "multi_line_chat_input": "Input Chat Multi Riga", - "bypass_text_input_limit": "Bypassa Limite Input Testo" - }, - "auto_purge": { - "never": "Mai", - "1_hour": "1 Ora", - "3_hours": "3 Ore", - "6_hours": "6 Ore", - "12_hours": "12 Ore", - "1_day": "1 Giorno", - "3_days": "3 Giorni", - "1_week": "1 Settimana", - "2_weeks": "2 Settimane", - "1_month": "1 Mese", - "3_months": "3 Mesi", - "6_months": "6 Mesi" - }, - "disable_story_sections": { - "friends": "Amici", - "suggested_stories": "Storie Suggerite", - "following": "Seguiti", - "discover": "Scopri" - }, - "disable_cameras": { - "front": "Fotocamera Anteriore", - "back": "Fotocamera Posteriore" - }, - "disable_permission_requests": { - "notifications": "Notifiche", - "read_media_images": "Leggi Immagini Media", - "read_media_video": "Leggi Video Media", - "camera": "Fotocamera", - "microphone": "Microfono", - "location": "Posizione", - "read_contacts": "Leggi Contatti", - "nearby_devices": "Dispositivi Vicini", - "phone_calls": "Chiamate Telefoniche" - }, - "message_indicators": { - "encryption_indicator": "Aggiunge un'icona 🔒 accanto ai messaggi che sono stati inviati solo a te", - "platform_indicator": "Aggiunge l'icona della piattaforma da cui è stato inviato un media (es. Android, iOS, Web)", - "location_indicator": "Aggiunge un'icona 📍 agli snap quando sono stati inviati con la posizione abilitata", - "ovf_editor_indicator": "Indica se uno snap è stato inviato utilizzando l'Editor OVF", - "director_mode_indicator": "Aggiunge un'icona 🎬 agli snap quando sono stati inviati utilizzando la Modalità Regista, che può essere utilizzata per inviare immagini della galleria come snap" - }, - "auto_mark_as_read": { - "conversation_read": "Segna la conversazione come letta durante l'invio di un messaggio", - "snap_reply": "Segna gli snap come letti quando rispondi", - "save_snap_in_chat": "Segna gli snap come letti quando li salvi in chat in Modalità Invisibile" - }, - "friend_mutation_notifier": { - "remove_friend": "Notifica quando qualcuno ti rimuove come amico", - "birthday_changes": "Notifica quando qualcuno cambia il suo compleanno", - "bitmoji_selfie_changes": "Notifica quando qualcuno cambia il suo selfie Bitmoji", - "bitmoji_avatar_changes": "Notifica quando qualcuno cambia il suo avatar Bitmoji", - "bitmoji_background_changes": "Notifica quando qualcuno cambia lo sfondo del suo Bitmoji", - "bitmoji_scene_changes": "Notifica quando qualcuno cambia la sua scena Bitmoji" - }, - "snapchat_plus": { - "not_subscribed": "Non Iscritto", - "basic": "Base", - "ad_free": "Senza Annunci" - }, - "double_tap_chat_action": { - "like_message": "Metti Mi Piace al Messaggio", - "copy_text": "Copia Testo negli Appunti", - "delete_message": "Elimina Messaggio", - "mark_as_read": "Segna come Letto", - "custom_emoji_reaction": "Reazione Emoji Personalizzata" - }, - "startup_default_camera": { - "front": "Fotocamera Anteriore", - "back": "Fotocamera Posteriore" - } - } - }, "friend_menu_option": { - "mark_snaps_as_seen": "Segna Snap come visti", - "mark_stories_as_seen_locally": "Segna Storie come viste localmente", "preview": "Anteprima", - "stealth_mode": "Modalità Invisibile", - "auto_download_blacklist": "Lista Nera Download Automatico", - "anti_auto_save": "Anti Salvataggio Automatico" - }, - "content_type": { - "CHAT": "Chiacchierata", - "SNAP": "Affrettato", - "EXTERNAL_MEDIA": "Media Esterno", - "NOTE": "Nota Audio", - "STICKER": "Adesivo", - "SHARE": "Condividi", - "STATUS": "Stato", - "LOCATION": "Posizione", - "STATUS_SAVE_TO_CAMERA_ROLL": "Salvato nel Rullino Fotografico", - "STATUS_CONVERSATION_CAPTURE_SCREENSHOT": "Schermata", - "STATUS_CONVERSATION_CAPTURE_RECORD": "Registrazione Schermo", - "STATUS_CALL_MISSED_VIDEO": "Videochiamata Persa", - "STATUS_CALL_MISSED_AUDIO": "Chiamata Audio Persa", - "LIVE_LOCATION_SHARE": "Condividi Posizione Live", - "CREATIVE_TOOL_ITEM": "Elemento Strumento Creativo", - "FAMILY_CENTER_INVITE": "Invito Centro Famiglia", - "FAMILY_CENTER_ACCEPT": "Accetta Centro Famiglia", - "FAMILY_CENTER_LEAVE": "Lascia Centro Famiglia", - "STATUS_PLUS_GIFT": "Regalo Status Plus", - "TINY_SNAP": "Snap Piccolo", - "STATUS_COUNTDOWN": "Conto alla Rovescia", - "MAP_REACTION": "Reazione Mappa" - }, - "media_download_source": { - "none": "Nessuno", - "pending": "In attesa", - "chat_media": "Media Chat", - "story": "Storia", - "public_story": "Storia Pubblica", - "spotlight": "Riflettore", - "profile_picture": "Immagine del Profilo", - "story_logger": "Logger Storie", - "message_logger": "Logger Messaggi", - "merged": "Unito", - "voice_call": "Chiamata Vocale" + "stealth_mode": "Modalità Stealth", + "auto_download_blacklist": "Scarica Automaticamente la Lista Nera", + "anti_auto_save": "Anti-Salvataggio Automatico" }, "chat_action_menu": { "preview_button": "Anteprima", "download_button": "Scarica", - "delete_logged_message_button": "Elimina Messaggio Registrato", - "show_chat_edit_history": "Mostra Cronologia Modifiche Chat", - "convert_message": "Converti Messaggio" + "delete_logged_message_button": "Elimina Messaggio Caricato" }, "opera_context_menu": { - "download": "Scarica Media", - "sent_at": "Inviato il {date}", - "created_at": "Creato il {date}", - "expires_at": "Scade il {date}", - "media_size": "Dimensione media: {size}", - "media_duration": "Durata media: {duration} ms", - "show_debug_info": "Mostra Info Debug" + "download": "Scarica Media" }, "modal_option": { "profile_info": "Info Profilo", "close": "Chiudi" }, "gallery_media_send_override": { - "multiple_media_toast": "Puoi inviare solo un media alla volta" - }, - "mark_as_seen": { - "no_unseen_snaps_toast": "Nessun Snap non visto trovato!", - "seen_toast": "Segnato come visto!", - "unseen_toast": "Segnato come non visto!", - "already_seen_toast": "Già segnato come visto!", - "already_unseen_toast": "Già segnato come non visto!" + "multiple_media_toast": "Puoi inviare soltanto un media per volta" }, "conversation_preview": { - "streak_expiration": "scade tra {day} giorni {hour} ore {minute} minuti", - "total_messages": "Totale messaggi inviati/ricevuti: {count}", + "streak_expiration": "scade tra {day} giorni, {hour} ore, {minute} minuti", + "total_messages": "Messaggi inviati/ricevuti totali: {count}", "title": "Anteprima", - "unknown_user": "Utente Sconosciuto", - "no_messages": "Nessun messaggio trovato!" + "unknown_user": "Utente Sconosciuto" }, "profile_info": { - "title": "Info Profilo", - "first_created_username": "Primo Nome Utente Creato", - "mutable_username": "Nome Utente Modificabile", + "title": "Info sul Profilo", "display_name": "Nome Visualizzato", - "added_date": "Data Aggiunta", - "birthday": "Compleanno: {month} {day}", - "hidden_birthday": "Compleanno: Nascosto", - "friendship": "Amicizia", - "add_source": "Aggiungi Fonte", - "snapchat_plus": "Snapchat Plus", - "snapchat_plus_state": { - "subscribed": "Iscritto", - "not_subscribed": "Non Iscritto" - } - }, - "friendship_link_type": { - "mutual": "Reciproco", - "outgoing": "In uscita", - "blocked": "Bloccato", - "deleted": "Eliminato", - "following": "Seguito", - "suggested": "Suggerito", - "incoming": "In arrivo", - "incoming_follower": "Seguace in Arrivo" - }, - "bulk_messaging_action": { - "choose_action_title": "Scegli un'azione", - "progress_status": "Elaborazione di {index} su {total}", - "selection_dialog_continue_button": "Continua", - "confirmation_dialog": { - "title": "Sei sicuro?", - "message": "Questo influenzerà tutti gli amici selezionati. Questa azione non può essere annullata." - }, - "actions": { - "remove_friends": "Rimuovi Amici", - "clear_conversations": "Cancella Conversazioni" - } + "added_date": "Data di Aggiunta", + "birthday": "Compleanno: {day} {month}" }, "chat_export": { - "exporter_dialog": { - "select_conversations_title": "Seleziona Conversazioni", - "text_field_selection": "{amount} selezionati", - "text_field_selection_all": "Tutti", - "export_file_format_title": "Esporta Formato File", - "message_type_filter_title": "Filtra Messaggi per Tipo", - "amount_of_messages_title": "Quantità di Messaggi (lascia vuoto per tutti)", - "download_medias_title": "Scarica Media" - }, "dialog_negative_button": "Annulla", "dialog_positive_button": "Esporta", - "exported_to": "Esportato in {path}", - "exporting_chats": "Esportazione delle Chat in corso...", - "processing_chats": "Elaborazione di {amount} conversazioni...", - "export_fail": "Esportazione della conversazione {conversation} fallita", - "writing_output": "Scrittura dell'output in corso...", - "finished": "Fatto! Ora puoi chiudere questa finestra di dialogo.", + "exported_to": "Esportato a {path}", + "exporting_chats": "Esportando le Chat...", + "processing_chats": "Elaborando {amount} conversazioni...", + "export_fail": "Impossibile esportare la conversazione {conversation}", + "writing_output": "Scrivendo il risultato...", + "finished": "Fatto! Ora puoi chiudere questa finestra.", "no_messages_found": "Nessun messaggio trovato!", - "exporting_message": "Esportazione di {conversation} in corso..." + "exporting_message": "Esportando {conversation}..." }, "button": { "ok": "OK", "positive": "Sì", - "negative": "NO", + "negative": "No", "cancel": "Annulla", - "open": "Apri", - "download": "Scarica", - "send": "Invia", - "restore_original": "Ripristina Originale", - "convert_external_media": "Converti Media Esterno", - "save": "Salva" - }, - "tracker_events": { - "conversation_enter": "Ingresso in Conversazione", - "conversation_exit": "Uscita dalla Conversazione", - "started_typing": "Ha iniziato a scrivere", - "stopped_typing": "Ha smesso di scrivere", - "started_speaking": "Ha iniziato a parlare", - "stopped_speaking": "Ha smesso di parlare", - "started_peeking": "Ha iniziato a sbirciare", - "stopped_peeking": "Ha smesso di sbirciare", - "message_read": "Messaggio Letto", - "message_deleted": "Messaggio Eliminato", - "message_saved": "Messaggio Salvato", - "message_unsaved": "Messaggio non Salvato", - "message_edited": "Messaggio Modificato", - "message_reaction_add": "Aggiungi Reazione al Messaggio", - "message_reaction_remove": "Rimuovi Reazione al Messaggio", - "snap_opened": "Snap Aperto", - "snap_replayed": "Snap Riproduzione", - "snap_replayed_twice": "Snap Riproduzione due volte", - "snap_screenshot": "Screenshot dello Snap", - "snap_screen_record": "Registrazione Schermo dello Snap" - }, - "tracker_actions": { - "log": "Tronco d'albero", - "in_app_notification": "Notifica In-App", - "push_notification": "Notifica Push", - "custom": "Personalizzato" - }, - "better_notifications": { - "button": { - "reply": "Rispondi", - "download": "Scarica", - "mark_as_read": "Segna come Letto" - } - }, - "profile_picture_downloader": { - "button": "Scarica Immagine del Profilo", - "title": "Downloader Immagini del Profilo", - "avatar_option": "Avatar", - "background_option": "Sfondo" - }, - "call_start_confirmation": { - "dialog_title": "Inizia Chiamata", - "dialog_message": "Sei sicuro di voler iniziare una chiamata?" - }, - "half_swipe_notifier": { - "notification_channel_name": "Mezzo Swipe", - "notification_content_dm": "{friend} ha appena fatto un mezzo swipe nella tua chat per {duration} secondi", - "notification_content_group": "{friend} ha appena fatto un mezzo swipe in {group} per {duration} secondi" + "open": "Apri" }, "download_processor": { - "attachment_type": { - "snap": "Affrettato", - "sticker": "Adesivo", - "gif": "GIF", - "external_media": "Media Esterno", - "note": "Nota", - "original_story": "Storia Originale" - }, - "select_attachments_title": "Seleziona allegati", "download_started_toast": "Download avviato", "unsupported_content_type_toast": "Tipo di contenuto non supportato!", "failed_no_longer_available_toast": "Media non più disponibile", - "no_attachments_toast": "Nessun allegato trovato!", "already_queued_toast": "Media già in coda!", "already_downloaded_toast": "Media già scaricato!", - "content_saved_toast": "Salvato!", - "download_toast": "Download di {path} in corso...", - "processing_toast": "Elaborazione di {path} in corso...", - "failed_generic_toast": "Download fallito", - "failed_to_create_preview_toast": "Creazione dell'anteprima fallita", - "failed_processing_toast": "Elaborazione fallita {error}", - "failed_gallery_toast": "Salvataggio nella galleria fallito {error}", - "dash_no_chapter": "Nessun capitolo trovato", - "dash_dialog": { - "title": "Scarica media dash", - "download_all": "Scarica Tutto", - "segment_text": "Segmento {from} - {to}" + "download_toast": "Scaricando {path}...", + "processing_toast": "Elaborando {path}...", + "failed_generic_toast": "Impossibile scaricare", + "failed_to_create_preview_toast": "Impossibile creare l'anteprima" + }, + "manager": { + "sections": { + "social": { + "streaks_expiration_short": "{hours}h" + }, + "tasks": { + "no_tasks": "Nessuna attività", + "failed_to_open_file": "Errore nell'apertura del file" + }, + "features": { + "disabled": "Disabilitato", + "export_option": "Esporta", + "import_option": "Importa", + "config_import_success_toast": "Configurazione importata con successo", + "saved_config_snackbar": "Configurazione salvata" + }, + "home_settings": { + "success_toast": "Fatto!", + "clear_button": "Pulisci", + "debug_title": "Debug", + "actions_title": "Azioni", + "export_button": "Esporta" + }, + "home": { + "update_button": "Scarica", + "quick_actions_title": "Azioni rapide", + "update_title": "Aggiorna SnapEnhance", + "update_content": "La versione {version} è disponibile!" + }, + "manage_rule_feature": { + "disable_state_option": "Disabilitato", + "whitelist_state_option": "Nessuno eccetto..." + } + }, + "routes": { + "tasks": "Attività", + "home_logs": "Log", + "home_settings": "Impostazioni", + "social": "Social", + "logged_stories": "Log registrati", + "messaging_preview": "Anteprima", + "features": "Caratteristiche", + "home": "Home", + "logger_history": "Cronologia Log", + "better_location": "Migliora la geolocalizzazione", + "file_imports": "Importa file", + "edit_rule": "Modifica regola", + "scripts": "Scripts", + "edit_theme": "Modifica Tema" } }, - "streaks_reminder": { - "notification_title": "Streak", - "notification_text": "Perderai la tua Streak con {friend} tra {hoursLeft} ore" - }, - "biometric_auth": { - "unlock_button": "Sblocca", - "title": "Sblocca Snapchat", - "subtitle": "Autenticati per sbloccare Snapchat" - }, - "end_to_end_encryption": { - "toolbox": { - "no_shared_key": "Non hai ancora una chiave segreta condivisa con questo amico. Clicca qui sotto per iniziarne una nuova.", - "shared_key_fingerprint": "La tua impronta digitale è:\n\n{fingerprint}\n\nAssicurati che corrisponda all'impronta digitale del tuo amico!", - "initiate_exchange_button": "Avvia Scambio Chiavi" + "setup": { + "mappings": { + "dialog": "Per funzionare dinamicamente con un'ampia gamma di versioni di Snapchat, la mappatura è necessaria per far funzionare correttamente SnapEnhance, questo non dovrebbe durare più di 5 secondi.", + "generate_failure_no_snapchat": "SnapEnhance non è in grado di rilevare Snapchat, per favore prova a reinstallare Snapchat.", + "generate_failure": "C'è stato un errore durante la generazione della mappatura, prova di nuovo." }, - "confirmation_dialogs": { - "title": "Crittografia end-to-end", - "confirmation_1": "AVVISO: Questo sovrascriverà la tua chiave esistente. Perderai l'accesso a tutti i messaggi crittografati da questo amico. Sei sicuro di voler continuare?", - "confirmation_2": "Sei VERAMENTE sicuro di voler continuare? Questa è la tua ultima possibilità di tirarti indietro." + "dialogs": { + "select_save_folder_button": "Seleziona cartella", + "select_language": "Seleziona la lingua", + "save_folder": "SnapEnhance richiede i permessi di archiviazione per scaricare e salvare i file da Snapchat.\nScegli una cartella dove salvare i file." }, - "unencrypted_conversation_send_failure_toast": "Non puoi inviare contenuti crittografati a conversazioni sia crittografate che non crittografate!", - "native_hooks_send_failure_toast": "Invio fallito! Abilita gli Hook Nativi nelle impostazioni.", - "no_participants_to_encrypt_toast": "Non hai amici in questa conversazione con cui crittografare i messaggi!", - "encryption_failed_toast": "Crittografia del messaggio fallita! Controlla logcat per maggiori dettagli.", - "accept_public_key_success_toast": "Chiave pubblica accettata con successo!", - "accept_secret_key_success_toast": "Fatto! Ora puoi inviare e ricevere messaggi crittografati con questo amico.", - "accept_public_key_failure_toast": "Accettazione della chiave pubblica fallita", - "accept_secret_key_failure_toast": "Accettazione della chiave segreta fallita", - "accept_secret_button": "Accetta Segreto", - "accept_public_key_button": "Accetta Chiave Pubblica", - "outgoing_pk_message": "Richiesta di scambio di chiavi", - "outgoing_secret_message": "Risposta allo scambio di chiavi", - "incoming_pk_message": "Hai appena ricevuto una richiesta di chiave pubblica. Clicca qui sotto per accettarla.", - "incoming_secret_message": "Il tuo amico ha appena accettato la tua chiave pubblica. Clicca qui sotto per accettare il segreto." + "permissions": { + "dialog": "Per continuare devi rispettare i seguenti requisiti:", + "notification_access": "Accesso alle notifiche", + "battery_optimization": "Ottimizzazione batteria", + "display_over_other_apps": "Mostra sopra altre app", + "request_button": "Richiedi" + } }, - "auto_open_snaps": { - "title": "Apri Snap Automaticamente", - "notification_content": "{count} Snap aperti" - }, - "friend_mutation_observer": { - "notification_channel_name": "Osservatore Mutazione Amico", - "friend_removed": "{username} ti ha rimosso come amico", - "birthday_removed": "{username} ha rimosso il suo compleanno ({birthday})", - "birthday_added": "{username} ha aggiunto il suo compleanno ({birthday})", - "birthday_changed": "{username} ha cambiato il suo compleanno da {oldBirthday} a {newBirthday}", - "bitmoji_selfie_changed": "{username} ha cambiato il suo selfie Bitmoji", - "bitmoji_avatar_changed": "{username} ha cambiato il suo avatar Bitmoji", - "bitmoji_background_changed": "{username} ha cambiato lo sfondo del suo Bitmoji", - "bitmoji_scene_changed": "{username} ha cambiato la sua scena Bitmoji" - }, - "material3_strings": { - "date_range_picker_start_headline": "Da", - "date_range_picker_end_headline": "A", - "date_range_picker_title": "Seleziona intervallo di date", - "date_picker_switch_to_calendar_mode": "Calendario", - "date_picker_switch_to_input_mode": "Ingresso", - "date_range_picker_scroll_to_previous_month": "Mese precedente", - "date_range_picker_scroll_to_next_month": "Mese successivo", - "date_picker_today_description": "Oggi", - "date_range_picker_day_in_range": "Selezionato", - "date_input_invalid_for_pattern": "Data non valida", - "date_input_invalid_year_range": "Anno non valido", - "date_input_invalid_not_allowed": "Data non valida", - "date_range_input_invalid_range_input": "Intervallo di date non valido" - }, - "send_override_dialog": { - "title": "Invia media come {type}", - "duration": "Durata: {duration}", - "saveable_snap_hint": "Rendi lo Snap salvabile nella chat", - "unlimited_duration": "Illimitato" - }, - "invalid_input_toast": "Input non valido! Assicurati di aver inserito un valore valido." -} \ No newline at end of file + "scopes": { + "friend": "Amico", + "group": "Gruppo" + } +} diff --git a/common/src/main/assets/lang/ja.json b/common/src/main/assets/lang/ja.json deleted file mode 100644 index b44c8a7c..00000000 --- a/common/src/main/assets/lang/ja.json +++ /dev/null @@ -1,2022 +0,0 @@ -{ - "setup": { - "dialogs": { - "select_language": "言語を選択", - "save_folder": "PurrfectSnapはSnapchatからメディアをダウンロードして保存するためにストレージ権限が必要です。\nメディアをダウンロードする場所を選択してください。", - "select_save_folder_button": "フォルダを選択" - }, - "mappings": { - "dialog": "マッピングを生成しています、これには時間がかかる場合があります...", - "generate_failure_no_snapchat": "PurrfectSnapはSnapchatを検出できませんでした、Snapchatを再インストールしてみてください。", - "generate_failure": "マッピングの生成中にエラーが発生しました、もう一度お試しください。" - }, - "permissions": { - "dialog": "続行するには、次の要件を満たす必要があります:", - "notification_access": "通知アクセス", - "battery_optimization": "バッテリー最適化", - "display_over_other_apps": "他のアプリの上に表示", - "request_button": "リクエスト" - } - }, - "scopes": { - "friend": "友達", - "group": "グループ" - }, - "manager": { - "routes": { - "tasks": "タスク", - "features": "機能", - "manage_rule_feature": "ルール機能を管理", - "home": "ホーム", - "home_settings": "設定", - "home_logs": "ログ", - "logger_history": "ロガー履歴", - "logged_stories": "ログに記録されたストーリー", - "friend_tracker": "友達トラッカー", - "edit_rule": "ルールを編集", - "file_imports": "ファイルのインポート", - "manage_repos": "リポジトリを管理", - "social": "ソーシャル", - "manage_scope": "スコープを管理", - "messaging_preview": "プレビュー", - "scripts": "スクリプト", - "better_location": "より良い場所" - }, - "sections": { - "home": { - "version_title": "v{versionName} · Eternalによってフォークされました", - "update_title": "PurrfectSnapアップデート", - "update_content": "バージョン{version}が利用可能です!", - "update_button": "ダウンロード", - "debug_build_summary_title": "PurrfectSnapのデバッグビルドを実行しています", - "debug_build_summary_content": "バージョン{versionName}({versionCode})", - "debug_build_summary_date": "ビルド日:{date}({days}日前)", - "quick_actions_title": "クイックアクション", - "download_icon_description": "ダウンロード", - "completed_icon_description": "完了", - "failed_icon_description": "失敗", - "manage_quick_actions_description": "クイックアクションを管理", - "quick_actions_icon_description": "クイックアクション", - "add_quick_action_description": "クイックアクションを追加" - }, - "home_logs": { - "no_logs_hint": "利用可能なログはありません", - "clear_logs_button": "ログをクリア", - "export_logs_button": "ログをエクスポート", - "saving_logs_toast": "ログを保存しています、これには時間がかかる場合があります...", - "saved_logs_success_toast": "ログが正常に保存されました", - "saved_logs_failure_toast": "ログの保存に失敗しました" - }, - "home_settings": { - "actions_title": "アクション", - "message_logger_title": "メッセージロガー", - "debug_title": "デバッグ", - "success_toast": "完了!", - "message_logger_summary": "{messageCount}メッセージ\n{storyCount}ストーリー", - "export_button": "エクスポート", - "clear_button": "クリア", - "view_logger_history_button": "ロガー履歴を表示", - "updates_title": "アップデート", - "auto_update_check": "アップデートを自動的に確認", - "update_check_frequency": "アップデート確認頻度", - "update_check_frequency_daily": "毎日", - "update_check_frequency_weekly": "毎週", - "update_check_frequency_monthly": "毎月", - "theme_icon_description": "テーマ", - "app_theme_title": "アプリのテーマ", - "theme_mode_system": "システム", - "theme_mode_light": "ライト", - "theme_mode_dark": "ダーク", - "ui_settings_title": "UI設定", - "haptic_feedback_label": "ハプティックフィードバック", - "test_mode_label": "テストモード(デバッグ専用)", - "disable_feature_loading_label": "機能の読み込みを無効にする", - "disable_auto_mapper_label": "自動マッパーを無効にする", - "disable_bypass_indicator_label": "バイパスステータスインジケーターを無効にする", - "update_notification_channel_name": "PurrfectSnapアップデート", - "update_notification_channel_description": "PurrfectSnapアップデートの通知", - "update_notification_title": "PurrfectSnapアップデートが利用可能です", - "update_notification_text": "バージョン%sが利用可能です。", - "export_database_failed_toast": "データベースのエクスポートに失敗しました! {message}", - "clear_messages_failed_toast": "メッセージのクリアに失敗しました! {message}", - "clear_file_failed_toast": "ファイルのクリアに失敗しました! {message}", - "debug_file_config": "構成", - "debug_file_mappings": "マッピング", - "debug_file_message_logger": "メッセージロガー", - "debug_file_pinned_best_friend": "ピン留めされた親友", - "debug_file_native_sig_cache": "ネイティブ署名キャッシュ" - }, - "tasks": { - "no_tasks": "タスクなし", - "merge_button": "マージ", - "failed_to_open_file": "ファイルのオープンに失敗しました", - "merge_files_toast": "{count}個のファイルをマージしています", - "remove_selected_tasks_title": "選択したタスクを削除してもよろしいですか?", - "remove_all_tasks_title": "すべてのタスクを削除してもよろしいですか?", - "delete_files_option": "ファイルも削除", - "remove_selected_tasks_confirm": "{count}個のタスクを削除しますか?", - "remove_all_tasks_confirm": "すべてのタスクを削除しますか?", - "clear_tasks_description": "タスクをクリア", - "file_not_found_icon_description": "ファイルが見つかりません", - "image_icon_description": "画像", - "video_icon_description": "ビデオ", - "audio_icon_description": "オーディオ", - "file_icon_description": "ファイル", - "download_icon_description": "ダウンロード", - "chat_action_icon_description": "チャットアクション", - "cancel_icon_description": "キャンセル", - "success_icon_description": "成功", - "failure_icon_description": "失敗", - "cancelled_icon_description": "キャンセル済み", - "task_status_failure": "失敗", - "task_status_cancelled": "キャンセル済み" - }, - "features": { - "disabled": "無効", - "export_option": "エクスポート", - "import_option": "インポート", - "reset_option": "リセット", - "config_export_success_toast": "構成が正常にエクスポートされました", - "config_import_success_toast": "構成が正常にインポートされました", - "config_import_failure_toast": "構成のインポートに失敗しました {error}", - "config_export_failure_toast": "構成のエクスポートに失敗しました {error}", - "saved_config_snackbar": "構成が保存されました", - "older_required": "この機能が正しく動作するには、Snapchat v{version}以前が必要です", - "newer_required": "この機能が正しく動作するには、Snapchat v{version}以降が必要です", - "search_button": "検索" - }, - "manage_rule_feature": { - "disable_state_option": "無効", - "disable_state_subtext": "友達/グループは影響を受けません", - "whitelist_state_option": "誰もいない、ただし...", - "whitelist_state_subtext": "このルールは{count}人の友達/グループにのみ影響します", - "whitelist_state_button": "許可された友達/グループを選択", - "blacklist_state_option": "全員、ただし...", - "blacklist_state_subtext": "このルールは{count}人の友達/グループを除く全員に影響します", - "blacklist_state_button": "除外された友達/グループを選択", - "clear_list_button": "友達/グループリストをクリア", - "dialog_clear_confirmation_text": "リストをクリアしてもよろしいですか?" - }, - "social": { - "friends_tab": "友達", - "groups_tab": "グループ", - "empty_hint": "(空)", - "streaks_expiration_short": "{hours}時間" - }, - "manage_scope": { - "logged_stories_button": "ログに記録されたストーリーを表示", - "e2ee_title": "エンドツーエンド暗号化", - "rules_title": "ルール", - "participants_text": "{count}人の参加者", - "not_found": "見つかりません", - "streaks_title": "連続記録", - "streaks_length_text": "長さ:{length}", - "streaks_expiration_text": "{eta}で期限切れ", - "streaks_expiration_text_expired": "期限切れ", - "reminder_button": "リマインダーを設定", - "delete_scope_confirm_dialog_title": "{scope}を削除してもよろしいですか?", - "notes_placeholder": "メモを追加するにはクリックしてください", - "invalid_key_size_32_bytes": "無効なキーサイズ(32バイトである必要があります)", - "successfully_imported_key": "キーが正常にインポートされました", - "failed_to_import_key": "キーのインポートに失敗しました:{message}", - "export_base64_button": "Base64をエクスポート", - "import_base64_button": "Base64をインポート" - }, - "logged_stories": { - "story_failed_to_load": "読み込みに失敗しました", - "no_stories": "ストーリーが見つかりません", - "save_from_cache_button": "キャッシュから保存", - "downloaded_to_path": "{path}にダウンロードしました", - "download_failed": "ダウンロードに失敗しました:{message}", - "posted_at": "{date}に投稿", - "created_at": "{date}に作成", - "failed_to_open_file": "ファイルのオープンに失敗しました。詳細はログを確認してください", - "failed_to_get_file": "ファイルの取得に失敗しました" - }, - "messaging_preview": { - "processed_messages_toast": "{count}件のメッセージを処理しました", - "processed_messages_text": "{count}件のメッセージを処理しました", - "close_button_description": "閉じる", - "bridge_connection_failed": "ブリッジへの接続に失敗しました。Snapchatがバックグラウンドで実行されていることを確認してください", - "bridge_init_failed": "メッセージングブリッジの初期化に失敗しました。Snapchatがバックグラウンドで実行されていることを確認してください", - "message_fetch_failed": "メッセージの取得に失敗しました", - "no_message_hint": "メッセージなし", - "save_selection_option": "選択を保存", - "save_all_option": "すべて保存", - "unsave_selection_option": "選択の保存を解除", - "unsave_all_option": "すべての保存を解除", - "mark_selection_as_seen_option": "選択したスナップを既読にする", - "mark_all_as_seen_option": "すべてのスナップを既読にする", - "delete_selection_option": "選択を削除", - "delete_all_option": "すべて削除" - }, - "logger_history": { - "download_started_toast": "ダウンロードを開始しました!", - "download_success_toast": "{path}にダウンロードしました", - "download_failed_toast": "{message}のダウンロードに失敗しました", - "edited_at_text": "{message}({date}に編集)", - "download_button": "ダウンロード", - "select_conversation_placeholder": "会話を選択", - "close_button_description": "閉じる", - "search_button_description": "検索", - "list_friend_format": "友達{name}", - "list_group_format": "グループ{name}", - "no_more_messages": "これ以上メッセージはありません", - "reverse_order_checkbox": "逆順", - "chat_attachment": "添付ファイル{index}", - "empty_message": "空のチャットメッセージ", - "message_parse_failed": "メッセージの解析に失敗しました", - "unknown_sender": "不明な送信者", - "download_attachment_failed_toast": "添付ファイルのダウンロードに失敗しました", - "log_header_format": "{username}({type}) - {date}" - }, - "file_imports": { - "import_file_button": "ファイルをインポート", - "file_not_found": "ファイルが見つかりません", - "file_import_failed": "ファイルのインポートに失敗しました:{error}", - "file_imported": "ファイルが正常にインポートされました", - "file_delete_failed": "ファイルの削除に失敗しました", - "no_files_hint": "ここでは、Snapchatで使用するファイルをインポートできます。下のボタンを押してファイルをインポートしてください。" - }, - "better_location": { - "spoofed_coordinates_title": "緯度{latitude}、経度{longitude}", - "save_coordinates_dialog_title": "座標を保存", - "saved_name_dialog_hint": "保存名", - "latitude_dialog_hint": "緯度", - "longitude_dialog_hint": "経度", - "save_dialog_button": "保存", - "choose_location_button": "場所を選択", - "teleport_to_friend_button": "友達にテレポート", - "spoof_location_toggle": "場所を偽装", - "suspend_location_updates": "場所の更新を一時停止", - "saved_coordinates_title": "保存された座標", - "no_saved_coordinates_hint": "保存された座標はありません", - "delete_dialog_title": "保存された座標を削除", - "delete_dialog_message": "この保存された座標を削除してもよろしいですか?", - "teleport_to_friend_title": "友達にテレポート", - "search_bar": "検索", - "no_friends_map": "地図に友達がいません", - "no_friends_found": "友達が見つかりません", - "edit_location_button_description": "場所を編集", - "add_icon_description": "追加", - "edit_icon_description": "編集", - "delete_icon_description": "削除" - } - }, - "dialogs": { - "add_friend": { - "title": "友達またはグループを追加", - "search_hint": "検索", - "fetch_error": "データの取得に失敗しました", - "category_groups": "グループ", - "category_friends": "友達", - "participants_text": "{count}人の参加者", - "search_icon_description": "検索" - }, - "scripting_warning": { - "title": "警告", - "content": "PurrfectSnapにはスクリプトツールが含まれており、デバイス上でユーザー定義のコードを実行できます。細心の注意を払い、既知の信頼できるソースからのみモジュールをインストールしてください。許可されていない、または検証されていないモジュールは、システムにセキュリティリスクをもたらす可能性があります。" - }, - "reset_config": { - "title": "構成をリセット", - "content": "構成をリセットしてもよろしいですか?", - "success_toast": "構成が正常にリセットされました" - }, - "export_config": { - "title": "機密データをエクスポートしますか?", - "content": "機密データ(位置座標など)を含む構成をエクスポートしますか?" - }, - "messaging_action": { - "title": "処理するコンテンツタイプを選択", - "select_all_button": "すべて選択" - }, - "file_imports": { - "no_files_settings_hint": "ファイルが見つかりません。ファイルのインポートセクションで必要なファイルをインポートしたことを確認してください", - "settings_select_file_hint": "インポートされたファイルを選択" - }, - "quick_actions_dialog": { - "title": "クイックアクションを編集", - "subtitle": "クイックアクションを選択してサイズを変更します。" - } - }, - "friend_tracker": { - "rules_tab": "ルール", - "logs_tab": "ログ", - "export_dialog_title": "エクスポート", - "bulk_export_button": "一括エクスポート", - "individual_export_button": "個別エクスポート", - "invalid_import_type_dialog_title": "無効なインポートタイプ", - "invalid_import_type_dialog_text": "選択したファイルはこのインポートタイプと互換性がありません。正しいインポートタイプを選択してください。", - "import_dialog_title": "インポート", - "bulk_import_button": "一括インポート", - "individual_import_button": "個別インポート", - "import_button_description": "インポート", - "export_button_description": "エクスポート", - "export_button": "エクスポート", - "delete_button_description": "削除", - "delete_button": "削除", - "catalog_button_description": "カタログ", - "catalog_button": "カタログ", - "add_rule_button_description": "ルールを追加", - "add_rule_button": "ルールを追加", - "no_rules_found": "ルールが見つかりません", - "empty_rule_name": "(空)", - "events_suffix": "イベント", - "scopes_suffix": "スコープ", - "select_rule_to_export_title": "エクスポートするルールを選択", - "deleted_logs_toast": "{count}件のログを削除しました", - "delete_logs_dialog_title": "ログを削除しますか?", - "deleting_logs_dialog_text": "{count}件のログを削除しています...", - "delete_logs_dialog_confirm_text": "これにより、現在のフィルターと検索クエリに基づいてログが削除されます。この操作は元に戻せません。", - "exported_logs_toast": "ログがエクスポートされました!", - "export_logs_failed_toast": "ログのエクスポートに失敗しました。詳細はlogcatを確認してください。", - "export_logs_dialog_title": "ログをエクスポートしますか?", - "exporting_logs_dialog_text": "ログをエクスポートしています...", - "export_logs_dialog_confirm_text": "これにより、現在のフィルターと検索クエリに基づいてログがエクスポートされます。", - "export_as_button": "{type}としてエクスポート", - "filters_title": "フィルター", - "search_by_label": "検索条件", - "newest_first_label": "新しい順", - "since_label": "以降", - "until_label": "まで", - "pick_a_date_button": "日付を選択", - "search_placeholder": "検索", - "filter_button_description": "フィルター", - "clear_button_description": "クリア", - "no_logs_found": "ログが見つかりません", - "log_event_format": "{conversation}で{event}", - "condition_only_inside_conversation": "会話中にのみ", - "condition_only_outside_conversation": "会話外にのみ", - "condition_only_when_app_active": "Snapchatがアクティブな場合にのみ", - "condition_only_when_app_inactive": "Snapchatが非アクティブな場合にのみ", - "condition_no_push_notification_when_app_active": "Snapchatがアクティブな場合は通知なし", - "add_event_dialog_title": "イベントを追加", - "event_type_label": "イベントタイプ", - "triggers_title": "トリガー", - "conditions_title": "条件", - "add_button": "追加", - "default_rule_name": "カスタムルール", - "discard_changes_dialog_title": "変更を破棄しますか?", - "discard_changes_dialog_text": "保存されていない変更があります。破棄してもよろしいですか?", - "discard_button": "破棄", - "cannot_save_rule_dialog_title": "ルールを保存できません", - "cannot_save_rule_dialog_text": "ルールを保存するには、少なくとも1つのイベントが必要です。", - "duplicate_rule_name_dialog_title": "重複したルール名", - "duplicate_rule_name_dialog_text": "この名前のルールは既に存在します。別の名前を選択してください。", - "delete_rule_dialog_title": "ルールを削除", - "delete_rule_dialog_text": "このルールを削除してもよろしいですか?", - "new_rule_title": "新しいルール", - "edit_rule_title": "ルールを編集", - "back_button_description": "戻る", - "save_button_description": "保存", - "general_section_title": "一般", - "rule_name_label": "ルール名", - "author_name_label": "作成者名", - "scope_section_title": "スコープ", - "scope_all": "すべて", - "scope_whitelist": "ホワイトリスト", - "scope_blacklist": "ブラックリスト", - "select_friends_groups_button": "友達/グループを選択({count})", - "events_section_title": "イベント", - "add_event_button": "イベントを追加", - "no_events_text": "イベントなし" - }, - "friend_tracker_catalog": { - "download_failed": "ダウンロードに失敗しました:{code}", - "error": "エラー:{message}", - "no_repos_added": "リポジトリが追加されていません。", - "no_rules_available": "どのリポジトリからもルールが利用できません。", - "by_author": "{author}作", - "imported_button": "インポート済み", - "import_button": "インポート", - "title": "友達トラッカーカタログ", - "manage_repos_description": "リポジトリを管理" - }, - "friend_tracker_export": { - "title": "ルールをエクスポート", - "back_button_description": "戻る", - "exported_toast": "友達トラッカーのルールがエクスポートされました!", - "export_failed_toast": "ルールのエクスポートに失敗しました:{message}", - "save_button": "保存", - "expand_button_description": "展開" - }, - "friend_tracker_import": { - "title": "ルールをインポート", - "back_button_description": "戻る", - "imported_toast": "友達トラッカーのルールがインポートされました!", - "import_failed_toast": "ルールのインポートに失敗しました:{message}", - "confirm_button": "確認", - "expand_button_description": "展開" - }, - "friend_tracker_repos": { - "invalid_repo_title": "無効なリポジトリ", - "add_repo_button": "リポジトリを追加", - "add_repo_dialog_title": "リポジトリURLを追加", - "repo_url_label": "リポジトリURL", - "repo_added_toast": "リポジトリが正常に追加されました!", - "invalid_repo_error": "これは有効な友達トラッカーリポジトリではないようです。", - "add_repo_failed_toast": "リポジトリの追加に失敗しました:{message}", - "add_button": "追加", - "no_repos_added": "リポジトリが追加されていません", - "remove_button": "削除", - "remove_repo_dialog_title": "リポジトリを削除", - "remove_repo_dialog_text": "このリポジトリを削除してもよろしいですか?" - }, - "navigation": { - "tracker_tab_label": "トラッカー", - "customize_bottom_bar_title": "下部バーをカスタマイズ", - "customize_bottom_bar_subtitle": "タブを並べ替え、追加、または削除します。最大5つ。", - "shown_tabs_title": "表示中のタブ", - "no_tabs_selected_text": "タブが選択されていません", - "available_tabs_title": "利用可能なタブ", - "reset_button": "リセット", - "done_button": "完了" - }, - "scripting": { - "script_already_installed": "スクリプトは既にインストールされています!", - "downloading_script": "スクリプトをダウンロード中...", - "script_downloaded": "スクリプト{name}がダウンロードされました!", - "download_script_failed": "スクリプトのダウンロードに失敗しました。詳細はログを確認してください", - "import_script_from_url_title": "URLからスクリプトをインポート", - "import_script_warning": "警告:インポートされたスクリプトはデバイスに有害な可能性があります。信頼できるソースからのみスクリプトをインポートしてください。", - "enter_url_label": "ここにURLを入力してください:", - "script_imported": "スクリプト{name}がインポートされました!", - "import_failed": "スクリプトのインポートに失敗しました。{message}。詳細はログを確認してください", - "import_button": "インポート", - "update_module_button": "モジュールを更新", - "updating_script": "スクリプト{name}を更新中...", - "module_not_found": "モジュールが見つかりません", - "updated_script": "{name}をバージョン{version}に更新しました", - "update_module_failed": "モジュールの更新に失敗しました。詳細はログを確認してください", - "edit_module_button": "モジュールを編集", - "open_module_failed": "モジュールファイルのオープンに失敗しました。詳細はログを確認してください", - "clear_module_data_button": "モジュールデータをクリア", - "module_data_cleared": "モジュールデータがクリアされました!", - "clear_module_data_failed": "モジュールデータのクリアに失敗しました。詳細はログを確認してください", - "delete_module_button": "モジュールを削除", - "deleted_script": "スクリプト{name}を削除しました!", - "delete_module_failed": "モジュールの削除に失敗しました。詳細はログを確認してください", - "actions_title": "アクション", - "no_description": "説明なし", - "update_available": "アップデートが利用可能です:{version}", - "actions_button": "アクション", - "loaded_script": "スクリプト{name}を読み込みました", - "unloaded_script": "スクリプト{name}をアンロードしました", - "enable_script_failed": "スクリプトの有効化に失敗しました。詳細はログを確認してください", - "disable_script_failed": "スクリプトの無効化に失敗しました。詳細はログを確認してください", - "select_scripts_folder_toast": "スクリプトフォルダを選択してください!", - "manage_repos_button": "リポジトリを管理", - "import_from_url_button": "URLからインポート", - "open_scripts_folder_button": "スクリプトフォルダを開く", - "no_settings_for_module": "このモジュールには設定がありません", - "installed_scripts_tab": "インストール済みスクリプト", - "catalog_tab": "カタログ", - "no_scripts_folder_selected_title": "スクリプトフォルダが選択されていません", - "select_folder_button": "フォルダを選択", - "no_scripts_found_title": "スクリプトが見つかりません。", - "use_catalog_to_add_scripts": "カタログタブを使用してスクリプトを追加してください!", - "ok_button_timeout": "OK({timeout})", - "documentation_button": "ドキュメント", - "catalog": { - "script_already_installed": "スクリプトは既にインストールされています!", - "download_failed": "ダウンロードに失敗しました:{code}", - "script_downloaded": "スクリプトがダウンロードされました!", - "could_not_create_file": "ファイルを作成できませんでした。", - "no_scripts_folder_selected": "スクリプトフォルダが選択されていません。", - "error": "エラー:{message}", - "no_repos_added": "リポジトリが追加されていません。", - "repo_list_info": "リポジトリのリストはこちら:", - "link_text": "リンク", - "no_scripts_available": "どのリポジトリからもスクリプトが利用できません。", - "by_author": "{author}作", - "version": "バージョン:{version}", - "installed_button": "インストール済み", - "download_button": "ダウンロード" - }, - "repos": { - "invalid_repo_title": "無効なリポジトリ", - "add_repo_button": "リポジトリを追加", - "add_repo_dialog_title": "リポジトリURLを追加", - "repo_url_label": "リポジトリURL", - "repo_added_toast": "リポジトリが正常に追加されました!", - "invalid_repo_error": "これは有効なスクリプトリポジトリではないようです。", - "add_repo_failed_toast": "リポジトリの追加に失敗しました:{message}", - "add_button": "追加", - "no_repos_added": "リポジトリが追加されていません", - "remove_button": "削除", - "remove_repo_dialog_title": "リポジトリを削除", - "remove_repo_dialog_text": "このリポジトリを削除してもよろしいですか?" - } - }, - "features": { - "config_import": { - "title": "インポートを確認", - "back_button_description": "戻る", - "config_imported_toast": "構成がインポートされました!", - "confirm_button": "確認", - "expand_button_description": "展開", - "enable_feature": "機能を有効にする", - "enabled": "有効", - "disabled": "無効" - }, - "config_export": { - "title": "エクスポートの概要", - "back_button_description": "戻る", - "save_button": "保存", - "expand_button_description": "展開", - "enable_feature": "機能を有効にする", - "enabled": "有効", - "disabled": "無効" - } - }, - "manage_repos": { - "title": "{type}リポジトリを管理", - "add_repo_button": "リポジトリを追加", - "add_repo_dialog_title": "リポジトリURLを追加", - "repo_url_label": "リポジトリURL", - "repo_added_successfully": "リポジトリが正常に追加されました!", - "add_repo_failed": "リポジトリの追加に失敗しました:{message}", - "add_button": "追加", - "no_repos_added": "リポジトリが追加されていません", - "remove_button": "削除" - } - }, - "rules": { - "toasts": { - "enabled": "{ruleName}が有効になりました", - "disabled": "{ruleName}が無効になりました" - }, - "modes": { - "blacklist": "ブラックリストモード", - "whitelist": "ホワイトリストモード" - }, - "properties": { - "auto_download": { - "name": "自動ダウンロード", - "description": "スナップ表示時に自動的にダウンロード", - "options": { - "blacklist": "自動ダウンロードから除外", - "whitelist": "自動ダウンロード" - } - }, - "stealth": { - "name": "ステルスモード", - "description": "他の人があなたがスナップ/チャットを開いたことを知られないようにします", - "options": { - "blacklist": "ステルスモードから除外", - "whitelist": "ステルスモード" - } - }, - "auto_save": { - "name": "自動保存", - "description": "チャットメッセージ表示時に保存", - "options": { - "blacklist": "自動保存から除外", - "whitelist": "自動保存" - } - }, - "unsaveable_messages": { - "name": "保存不可能なメッセージ", - "description": "他の人がチャットでメッセージを保存するのを防ぎます", - "options": { - "blacklist": "保存不可能なメッセージから除外", - "whitelist": "保存不可能なメッセージ" - } - }, - "auto_open_snaps": { - "name": "スナップを自動で開く", - "description": "受信時にスナップを自動的に開きます", - "options": { - "blacklist": "スナップの自動オープンから除外", - "whitelist": "スナップを自動で開く" - } - }, - "hide_friend_feed": { - "name": "友達フィードから隠す" - }, - "e2e_encryption": { - "name": "E2E暗号化を使用" - }, - "pin_conversation": { - "name": "会話をピン留め" - }, - "exclude_message_logger": { - "name": "メッセージロガーから除外" - } - } - }, - "actions": { - "clean_snapchat_cache": { - "name": "Snapchatキャッシュをクリーンアップ", - "description": "Snapchatキャッシュをクリーンアップします" - }, - "manage_friend_list": { - "name": "友達リストを管理", - "description": "バックアップ時に友達リストをインポート/エクスポート" - }, - "export_chat_messages": { - "name": "チャットメッセージをエクスポート", - "description": "会話メッセージをJSON/HTML/TXTファイルにエクスポートします" - }, - "export_memories": { - "name": "思い出をエクスポート", - "description": "思い出をZIPファイルにエクスポートします" - }, - "bulk_messaging_action": { - "name": "一括メッセージングアクション", - "description": "友達の削除や会話の一括削除などの操作を実行します" - }, - "regen_mappings": { - "name": "マッピングを再生成", - "description": "マッピングを手動で再生成します" - }, - "change_language": { - "name": "言語を変更", - "description": "PurrfectSnapの言語を変更します" - }, - "file_imports": { - "name": "ファイルのインポート", - "description": "Snapchatで使用するファイルをインポートします" - }, - "friend_tracker": { - "name": "友達トラッカー", - "description": "Snapchatで友達を追跡します" - }, - "logger_history": { - "name": "ロガー履歴", - "description": "ログに記録されたメッセージの履歴を表示します" - } - }, - "features": { - "notices": { - "unstable": "⚠️不安定", - "ban_risk": "⚠️この機能はBANの原因となる可能性があります", - "internal_behavior": "⚠️これはSnapchatの内部動作を破壊する可能性があります" - }, - "properties": { - "downloader": { - "name": "ダウンローダー", - "description": "Snapchatメディアをダウンロード", - "properties": { - "save_folder": { - "name": "保存フォルダ", - "description": "すべてのメディアをダウンロードするディレクトリを選択" - }, - "auto_download_sources": { - "name": "自動ダウンロードソース", - "description": "自動的にダウンロードするソースを選択" - }, - "prevent_self_auto_download": { - "name": "自己自動ダウンロードを防止", - "description": "自分のスナップが自動的にダウンロードされるのを防ぎます" - }, - "path_format": { - "name": "パス形式", - "description": "ファイルパス形式を指定" - }, - "allow_duplicate": { - "name": "重複を許可", - "description": "同じメディアを複数回ダウンロードできるようにします" - }, - "merge_overlays": { - "name": "オーバーレイをマージ", - "description": "スナップのテキストとメディアを単一のファイルに結合します" - }, - "force_image_format": { - "name": "画像形式を強制", - "description": "指定した形式で画像を保存するように強制します" - }, - "force_voice_note_format": { - "name": "ボイスノート形式を強制", - "description": "指定した形式でボイスノートを保存するように強制します" - }, - "auto_download_voice_notes": { - "name": "ボイスノートを自動ダウンロード", - "description": "再生時にボイスノートを自動的にダウンロードします" - }, - "download_profile_pictures": { - "name": "プロフィール写真をダウンロード", - "description": "プロフィールページからプロフィール写真をダウンロードできます" - }, - "opera_download_button": { - "name": "Operaダウンロードボタン", - "description": "スナップ表示時に右上にダウンロードボタンを追加します。\nボタンを長押しすると強制的にダウンロードされます" - }, - "download_context_menu": { - "name": "ダウンロードコンテキストメニュー", - "description": "コンテキストメニューを使用して、会話やストーリーからメッセージをダウンロード/プレビューできます。\nボタンを長押しすると強制的にダウンロードされます" - }, - "ffmpeg_options": { - "name": "FFmpegオプション", - "description": "追加のFFmpegオプションを指定", - "properties": { - "threads": { - "name": "スレッド", - "description": "使用するスレッド数" - }, - "preset": { - "name": "プリセット", - "description": "変換速度を設定" - }, - "constant_rate_factor": { - "name": "定率係数", - "description": "ビデオエンコーダーの定率係数を設定\nlibx264の場合は0から51まで" - }, - "video_bitrate": { - "name": "ビデオビットレート", - "description": "ビデオビットレートを設定(kbps)" - }, - "audio_bitrate": { - "name": "オーディオビットレート", - "description": "オーディオビットレートを設定(kbps)" - }, - "custom_video_codec": { - "name": "カスタムビデオコーデック", - "description": "カスタムビデオコーデックを設定(例:libx264)" - }, - "custom_audio_codec": { - "name": "カスタムオーディオコーデック", - "description": "カスタムオーディオコーデックを設定(例:AAC)" - } - } - }, - "logging": { - "name": "ロギング", - "description": "メディアダウンロード時にトーストを表示" - }, - "custom_path_format": { - "name": "カスタムパス形式", - "description": "ダウンロードしたメディアのカスタムパス形式を指定\n\n利用可能な変数:\n - %username%\n - %source%\n - %hash%\n - %date_time%" - } - } - }, - "user_interface": { - "name": "ユーザーインターフェース", - "description": "Snapchatのルックアンドフィールを変更", - "properties": { - "enable_app_appearance": { - "name": "アプリの外観設定を有効にする", - "description": "非表示のアプリの外観設定を有効にします\n新しいSnapchatバージョンでは不要な場合があります" - }, - "friend_feed_message_preview": { - "name": "友達フィードメッセージプレビュー", - "description": "友達フィードの最後のメッセージのプレビューを表示します", - "properties": { - "amount": { - "name": "量", - "description": "プレビューするメッセージの量" - } - } - }, - "snap_preview": { - "name": "スナッププレビュー", - "description": "チャットで未読のスナップの横に小さなプレビューを表示します" - }, - "bootstrap_override": { - "name": "ブートストラップのオーバーライド", - "description": "ユーザーインターフェースのブートストラップ設定をオーバーライドします", - "properties": { - "app_appearance": { - "name": "アプリの外観", - "description": "永続的なアプリの外観を設定します" - }, - "home_tab": { - "name": "ホームタブ", - "description": "Snapchatを開くときのスタートアップタブをオーバーライドします" - } - } - }, - "force_amoled_theme": { - "name": "Amoledダークモード", - "description": "ダークテーマに真の黒の背景を使用します" - }, - "map_friend_nametags": { - "name": "強化された友達マップのネームタグ", - "description": "Snapmapの友達のネームタグを改善します" - }, - "prevent_message_list_auto_scroll": { - "name": "メッセージリストの自動スクロールを防止", - "description": "メッセージの送受信時にメッセージリストが一番下にスクロールするのを防ぎます" - }, - "streak_expiration_info": { - "name": "連続記録の有効期限情報を表示", - "description": "連続記録カウンターの横に連続記録の有効期限タイマーを表示します" - }, - "hide_friend_feed_entry": { - "name": "友達フィードのエントリを非表示", - "description": "友達フィードから特定の友達を非表示にします\nこの機能を管理するにはソーシャルタブを使用してください" - }, - "hide_streak_restore": { - "name": "連続記録の復元を非表示", - "description": "友達フィードの復元ボタンを非表示にします" - }, - "hide_quick_add_suggestions": { - "name": "クイック追加の提案を非表示", - "description": "クイック追加の友達の提案を削除します" - }, - "hide_story_suggestions": { - "name": "ストーリーの提案を非表示", - "description": "ストーリーページから提案を削除します" - }, - "hide_ui_components": { - "name": "UIコンポーネントを非表示", - "description": "非表示にするUIコンポーネントを選択" - }, - "opera_media_quick_info": { - "name": "Operaメディアクイック情報", - "description": "operaビューアのコンテキストメニューで作成日などのメディアの有用な情報を表示します" - }, - "old_bitmoji_selfie": { - "name": "古いBitmojiセルフィー", - "description": "古いSnapchatバージョンのBitmojiセルフィーを復活させます" - }, - "disable_spotlight": { - "name": "Spotlightを無効にする", - "description": "Spotlightページを無効にします" - }, - "friend_feed_menu_buttons": { - "name": "友達フィードメニューボタン", - "description": "友達フィードメニューに表示するボタンを選択" - }, - "auto_close_friend_feed_menu": { - "name": "友達フィードメニューを自動で閉じる", - "description": "設定ボタンを押すと友達フィードメニューを自動的に閉じます" - }, - "vertical_story_viewer": { - "name": "縦型ストーリービューア", - "description": "すべてのストーリーで縦型ストーリービューアを有効にします" - }, - "enable_friend_feed_menu_bar": { - "name": "友達フィードメニューバー", - "description": "新しい友達フィードメニューバーを有効にします" - }, - "message_indicators": { - "name": "メッセージインジケーター", - "description": "メッセージに特定のインジケーターアイコンを追加します\n注意:インジケーターは100%正確ではない場合があります" - }, - "stealth_mode_indicator": { - "name": "ステルスモードインジケーター", - "description": "ステルスモードの会話の横に👻絵文字を追加します" - }, - "edit_text_override": { - "name": "テキスト編集のオーバーライド", - "description": "テキストフィールドの動作をオーバーライドします" - }, - "prevent_forced_keyboard": { - "name": "強制キーボードを防止", - "description": "会話を開いたときにSnapchatが自動的にキーボードを表示するのを防ぎます" - }, - "settings_menu": { - "name": "設定メニュー", - "description": "PurrfectSnapメニューの開き方を変更します", - "options": { - "default": "デフォルト", - "legacy": "レガシー" - } - } - } - }, - "messaging": { - "name": "メッセージング", - "description": "友達との対話方法を変更", - "properties": { - "bypass_screenshot_detection": { - "name": "スクリーンショット検出をバイパス", - "description": "Snapchatがスクリーンショットを撮ったことを検出するのを防ぎます" - }, - "anonymous_story_viewing": { - "name": "匿名のストーリー閲覧", - "description": "他の人があなたが彼らのストーリーを見たことを知られないようにします" - }, - "prevent_story_rewatch_indicator": { - "name": "ストーリーの再視聴インジケーターを防止", - "description": "他の人があなたが彼らのストーリーを再視聴したことを知られないようにします" - }, - "hide_peek_a_peek": { - "name": "Peek-a-Peekを非表示", - "description": "チャットに半分スワイプしたときに通知が送信されるのを防ぎます" - }, - "hide_bitmoji_presence": { - "name": "Bitmojiのプレゼンスを非表示", - "description": "チャット中にBitmojiが表示されるのを防ぎます" - }, - "hide_typing_notifications": { - "name": "入力通知を非表示", - "description": "他の人があなたが入浴中であることを知られないようにします" - }, - "unlimited_snap_view_time": { - "name": "無制限のスナップ表示時間", - "description": "スナップの表示時間制限を解除します" - }, - "auto_mark_as_read": { - "name": "自動で既読にする", - "description": "ステルスモードが有効になっている場合でも、メッセージ/スナップを自動的に既読にします" - }, - "mark_snap_as_seen_button": { - "name": "スナップを既読にするボタン", - "description": "スナップ表示時に既読にするボタンを追加します。\nステルスモードが有効な場合でも機能します" - }, - "skip_when_marking_as_seen": { - "name": "既読にするときにスキップ", - "description": "スナップを既読にするときに自動的に次のスナップにスキップします。\nスナップを既読にするボタンと組み合わせて使用します" - }, - "loop_media_playback": { - "name": "メディアのループ再生", - "description": "スナップ/ストーリー表示時にメディアをループ再生します" - }, - "disable_replay_in_ff": { - "name": "FFでのリプレイを無効にする", - "description": "友達フィードからの長押しによるリプレイ機能を無効にします" - }, - "half_swipe_notifier": { - "name": "ハーフスワイプ通知", - "description": "誰かが会話に半分スワイプしたときに通知します", - "properties": { - "min_duration": { - "name": "最小期間", - "description": "ハーフスワイプの最小期間(秒)" - }, - "max_duration": { - "name": "最大期間", - "description": "ハーフスワイプの最大期間(秒)" - } - } - }, - "call_start_confirmation": { - "name": "通話開始の確認", - "description": "通話開始時に確認ダイアログを表示します" - }, - "unlimited_conversation_pinning": { - "name": "無制限の会話のピン留め", - "description": "ローカルで無制限の会話をピン留めできます" - }, - "disable_snap_mode_restrictions": { - "name": "スナップモードの制限を無効にする", - "description": "自己破壊スナップを制限なく表示できます" - }, - "prevent_message_sending": { - "name": "メッセージの送信を防止", - "description": "特定の種類のメッセージの送信を防止します" - }, - "friend_mutation_notifier": { - "name": "友達の変更通知", - "description": "友達のプロフィールで何かが変更されたときに通知します" - }, - "better_notifications": { - "name": "より良い通知", - "description": "受信した通知に詳細情報を追加します", - "properties": { - "group_notifications": { - "name": "グループ通知", - "description": "通知を1つにグループ化" - }, - "chat_preview": { - "name": "チャットプレビュー", - "description": "通知で受信したメッセージのプレビューを表示します" - }, - "media_preview": { - "name": "メディアプレビュー", - "description": "通知で選択したメディアタイプのプレビューを表示します" - }, - "media_caption": { - "name": "メディアキャプション", - "description": "通知でメディアの添付キャプションを表示します" - }, - "stacked_media_messages": { - "name": "スタックされたメディアメッセージ", - "description": "プレビューできない場合に複数のメディアメッセージを1つのテキスト通知に結合します。チャットプレビューと組み合わせて使用します" - }, - "friend_add_source": { - "name": "友達追加ソース", - "description": "通知で友達リクエストのソースを表示します" - }, - "reply_button": { - "name": "返信ボタン", - "description": "通知に返信ボタンを追加します" - }, - "smart_replies": { - "name": "スマートリプライ", - "description": "通知に提案された返信を追加します(Android 10以降)。返信ボタンと組み合わせて使用します" - }, - "download_button": { - "name": "ダウンロードボタン", - "description": "通知からメディアをダウンロードできます" - }, - "mark_as_read_button": { - "name": "既読にするボタン", - "description": "通知からメッセージを既読にできます" - }, - "mark_as_read_and_save_in_chat": { - "name": "既読にしてチャットに保存", - "description": "通知に既読にしてチャットに保存ボタンを追加します" - } - } - }, - "notification_blacklist": { - "name": "通知ブラックリスト", - "description": "ブロックする通知を選択" - }, - "message_logger": { - "name": "メッセージロガー", - "description": "メッセージの削除を防ぎます", - "properties": { - "keep_my_own_messages": { - "name": "自分のメッセージを保持", - "description": "自分のメッセージが削除されるのを防ぎます" - }, - "auto_purge": { - "name": "自動パージ", - "description": "指定した時間より古いキャッシュされたメッセージを自動的に削除します" - }, - "message_filter": { - "name": "メッセージフィルター", - "description": "ログに記録するメッセージを選択(すべてのメッセージの場合は空)" - }, - "deleted_message_color": { - "name": "削除されたメッセージの色", - "description": "削除されたメッセージの色を設定します" - } - } - }, - "auto_save_messages_in_conversations": { - "name": "会話のメッセージを自動保存", - "description": "会話のすべてのメッセージを自動的に保存します" - }, - "gallery_media_send_override": { - "name": "ギャラリーメディア送信のオーバーライド", - "description": "ギャラリーから送信するときのメディアソースを偽装します" - }, - "strip_media_metadata": { - "name": "メディアメタデータを削除", - "description": "メッセージとして送信する前にメディアのメタデータを削除します" - }, - "bypass_message_retention_policy": { - "name": "メッセージ保持ポリシーをバイパス", - "description": "メッセージ表示後に削除されるのを防ぎます" - }, - "bypass_message_action_restrictions": { - "name": "メッセージアクションの制限をバイパス", - "description": "スナップを開かずに反応したり、保存不可能なメッセージを保存したりできます" - }, - "remove_groups_locked_status": { - "name": "グループのロック状態を解除", - "description": "追い出された後もグループ情報を表示できます" - }, - "double_tap_chat_action": { - "name": "ダブルタップチャットアクション", - "description": "チャットでメッセージをダブルタップするとカスタムアクションを実行します" - }, - "double_tap_chat_action_custom_emoji": { - "name": "ダブルタップチャットアクションのカスタム絵文字リアクション", - "description": "ダブルタップチャットアクションのカスタム絵文字リアクションを設定します" - } - } - }, - "global": { - "name": "グローバル", - "description": "グローバルなSnapchat設定を調整", - "properties": { - "better_location": { - "name": "より良い場所", - "description": "Snapchatの場所を強化します", - "properties": { - "spoof_location": { - "name": "場所を偽装", - "description": "あなたの場所を指定したものに偽装します" - }, - "coordinates": { - "name": "座標", - "description": "偽装した場所の座標を設定します" - }, - "walk_radius": { - "name": "歩行半径", - "description": "この半径内でランダムに歩き回ります(フィート)" - }, - "always_update_location": { - "name": "常に場所を更新", - "description": "GPSデータが受信されなくてもSnapchatに場所の更新を強制します" - }, - "suspend_location_updates": { - "name": "場所の更新を一時停止", - "description": "あなたの場所が更新されるのを防ぎます" - }, - "spoof_battery_level": { - "name": "バッテリーレベルを偽装", - "description": "地図上でデバイスのバッテリーレベルを偽装します\n値は0から100の間でなければなりません" - }, - "spoof_headphones": { - "name": "ヘッドフォンを偽装", - "description": "地図上で音楽を聴いている状態を偽装します" - }, - "show_battery_level": { - "name": "バッテリーレベルを表示", - "description": "地図上で友達のバッテリーレベルを表示します" - } - } - }, - "snapchat_plus": { - "name": "スナップチャットプラス", - "description": "Snapchat Plusの機能を有効にします\n一部のサーバー側の機能は機能しない場合があります" - }, - "media_upload_quality": { - "name": "メディアアップロード品質", - "description": "メディアアップロード品質をオーバーライドします", - "properties": { - "force_video_upload_source_quality": { - "name": "ビデオアップロードのソース品質を強制", - "description": "ビデオアップロード時にSnapchatにソース品質の使用を強制します\nこれによりメディアからメタデータが削除されない場合があることに注意してください" - }, - "disable_image_compression": { - "name": "画像圧縮を無効にする", - "description": "メディアアップロード時に画像圧縮を無効にします" - }, - "custom_image_upload_format": { - "name": "カスタム画像アップロード形式", - "description": "カスタム画像アップロード形式を設定します\n最高の品質を得るには、ロスレス形式(PNGなど)を選択してください" - } - } - }, - "disable_confirmation_dialogs": { - "name": "確認ダイアログを無効にする", - "description": "選択したアクションを自動的に確認します" - }, - "auto_updater": { - "name": "自動アップデーター", - "description": "新しいアップデートを自動的に確認します" - }, - "disable_metrics": { - "name": "メトリクスを無効にする", - "description": "特定の分析データをSnapchatに送信するのをブロックします" - }, - "disable_story_sections": { - "name": "ストーリーセクションを無効にする", - "description": "ストーリーページからセクションを削除します\n正しく機能するには更新が必要な場合があります" - }, - "block_ads": { - "name": "広告をブロック", - "description": "広告の表示を防ぎます" - }, - "disable_custom_tabs": { - "name": "カスタムタブを無効にする", - "description": "Webブラウザではなく、サポートされているアプリケーションでリンクを開きます" - }, - "disable_permission_requests": { - "name": "権限リクエストを無効にする", - "description": "Snapchatが特定の権限を要求するのを防ぎます" - }, - "disable_memories_snap_feed": { - "name": "思い出のスナップフィードを無効にする", - "description": "カメラで上にスワイプしたときにSnapchatが最近の思い出を表示するのを防ぎます" - }, - "spotlight_comments_username": { - "name": "Spotlightコメントのユーザー名", - "description": "Spotlightコメントで作成者のユーザー名を表示します" - }, - "bypass_video_length_restriction": { - "name": "ビデオの長さの制限をバイパス", - "description": "単一:単一のビデオを送信します\n分割:編集後にビデオを分割します" - }, - "default_video_playback_rate": { - "name": "デフォルトのビデオ再生レート", - "description": "ビデオの再生のデフォルト速度を設定します\n値は0.1から4.0の間でなければなりません" - }, - "video_playback_rate_slider": { - "name": "ビデオ再生レートスライダー", - "description": "ビデオ再生レートを変更するためにoperaコンテキストメニューにスライダーを追加します\n注意:変更は後続のビデオにのみ適用されます" - }, - "disable_google_play_dialogs": { - "name": "Google Playサービスのダイアログを無効にする", - "description": "Google Playサービスの可用性ダイアログの表示を防止します" - }, - "default_volume_controls": { - "name": "デフォルトの音量コントロール", - "description": "Snapchatにシステムの音量コントロールの使用を強制します" - }, - "disable_telecom_framework": { - "name": "テレコムフレームワークを無効にする", - "description": "SnapchatがAndroidテレコムフレームワークを使用するのを防ぎます\nこれにより、通話中に音楽を聴くことができます" - }, - "hide_active_music": { - "name": "アクティブな音楽を非表示", - "description": "Snapchatがあなたが音楽を聴いていることを知るのを防ぎます\nこれにより、音楽を聴きながらコントロールボリュームボタンを使用してスナップを撮ることができます" - }, - "disable_snap_splitting": { - "name": "スナップの分割を無効にする", - "description": "スナップが複数の部分に分割されるのを防ぎます\n送信する写真はビデオに変わります" - } - } - }, - "rules": { - "name": "ルール", - "description": "個々の人々のための自動機能を管理" - }, - "camera": { - "name": "カメラ", - "description": "完璧なスナップのために適切な設定を調整", - "properties": { - "disable_cameras": { - "name": "カメラを無効にする", - "description": "Snapchatが選択したカメラを使用するのを防ぎます" - }, - "black_photos": { - "name": "黒い写真", - "description": "撮影した写真を黒い背景に置き換えます\nビデオは影響を受けません" - }, - "immersive_camera_preview": { - "name": "没入型プレビュー", - "description": "Snapchatがカメラプレビューをトリミングするのを防ぎます\nこれにより、一部のデバイスでカメラがちらつく可能性があります" - }, - "override_front_resolution": { - "name": "フロント解像度をオーバーライド", - "description": "フロントカメラのカメラ解像度をオーバーライドします" - }, - "override_back_resolution": { - "name": "バック解像度をオーバーライド", - "description": "バックカメラのカメラ解像度をオーバーライドします" - }, - "custom_resolution": { - "name": "カスタム解像度", - "description": "カスタムカメラ解像度を設定します、幅x高さ(例:1920x1080)。\nカスタム解像度はデバイスでサポートされている必要があります" - }, - "front_custom_frame_rate": { - "name": "フロントカスタムフレームレート", - "description": "フロントカメラのフレームレートをオーバーライドします" - }, - "back_custom_frame_rate": { - "name": "バックカスタムフレームレート", - "description": "バックカメラのフレームレートをオーバーライドします" - }, - "force_camera_source_encoding": { - "name": "カメラソースエンコーディングを強制", - "description": "カメラソースエンコーディングを強制します" - }, - "startup_default_camera": { - "name": "スタートアップデフォルトカメラ", - "description": "Snapchatを開くときのデフォルトカメラを設定します" - }, - "hevc_recording": { - "name": "HEVC録画", - "description": "ビデオ録画にHEVC(H.265)コーデックを使用します" - } - } - }, - "streaks_reminder": { - "name": "連続記録リマインダー", - "description": "定期的に連続記録について通知します", - "properties": { - "interval": { - "name": "間隔", - "description": "各リマインダーの間隔(時間)" - }, - "remaining_hours": { - "name": "残り時間", - "description": "通知が表示されるまでの残り時間(時間)" - }, - "group_notifications": { - "name": "グループ通知", - "description": "通知を1つにグループ化" - } - } - }, - "experimental": { - "name": "実験的", - "description": "実験的な機能", - "properties": { - "native_hooks": { - "name": "ネイティブフック", - "description": "Snapchatのネイティブコードにフックする安全でない機能", - "properties": { - "composer_hooks": { - "name": "コンポーザーフック", - "description": "コンポーザークロスプラットフォームUIフレームワークにコードを挿入します", - "properties": { - "show_first_created_username": { - "name": "最初に作成されたユーザー名を表示", - "description": "プロフィールページで現在のユーザー名の横に最初に作成されたユーザー名を表示します" - }, - "bypass_camera_roll_limit": { - "name": "カメラロールの制限をバイパス", - "description": "カメラロールから送信できるメディアの最大量を増やします" - }, - "custom_self_destruct_snap_delay": { - "name": "カスタム自己破壊スナップ遅延", - "description": "スナップ送信時に自己破壊タイマーのオプションを増やします" - }, - "composer_console": { - "name": "コンポーザーコンソール", - "description": "コンポーザーでJavaScriptコードを実行できます(arm64のみ)" - }, - "composer_logs": { - "name": "コンポーザーログ", - "description": "コンポーザーのコンソールログをPurrfectSnapにリダイレクトします" - } - } - }, - "disable_bitmoji": { - "name": "Bitmojiを無効にする", - "description": "友達プロフィールのBitmojiを無効にします" - }, - "custom_emoji_font": { - "name": "カスタム絵文字フォント", - "description": "カスタム絵文字フォントを使用できます。.ttfフォントでのみ機能します" - }, - "custom_shared_library": { - "name": "カスタム共有ライブラリ", - "description": "カスタム共有ライブラリをSnapchatにロードします。この機能はテスト目的のみです" - } - } - }, - "spoof": { - "name": "偽装", - "description": "あなたに関するさまざまな情報を偽装します", - "properties": { - "play_store_installer_package_name": { - "name": "Playストアインストーラーパッケージ名", - "description": "インストーラーパッケージ名をcom.android.vendingにオーバーライドします" - }, - "remove_vpn_transport_flag": { - "name": "VPNトランスポートフラグを削除", - "description": "SnapchatがVPNを検出するのを防ぎます" - }, - "remove_mock_location_flag": { - "name": "モックロケーションフラグを削除", - "description": "Snapchatがモックロケーションを検出するのを防ぎます" - } - } - }, - "convert_message_locally": { - "name": "メッセージをローカルで変換", - "description": "スナップをローカルでチャット外部メディアに変換します。これはチャットダウンロードコンテキストメニューに表示されます" - }, - "media_file_picker": { - "name": "メディアファイルピッカー", - "description": "ギャラリーから任意のビデオ/オーディオファイルを選択できます" - }, - "story_logger": { - "name": "ストーリーロガー", - "description": "友達のストーリーの履歴を提供します" - }, - "call_recorder": { - "name": "通話レコーダー", - "description": "音声通話を自動的に録音します" - }, - "account_switcher": { - "name": "アカウントスイッチャー", - "description": "ログアウトせずにアカウントを切り替えることができます\nメニューを開くには、Bitmojiプロフィールの横にある検索アイコンを長押しします\n注意:この機能は実験的なものであり、将来変更される可能性があります", - "properties": { - "auto_backup_current_account": { - "name": "現在のアカウントを自動バックアップ", - "description": "ログアウトまたはアカウント切り替え時に現在のアカウントを自動的にバックアップします" - } - } - }, - "better_transcript": { - "name": "より良いトランスクリプト", - "description": "ボイスノートのトランスクリプトを改善します", - "properties": { - "force_transcription": { - "name": "ボイスノートのトランスクリプションを強制", - "description": "すべてのボイスノートをトランスクリプトできます" - }, - "preferred_transcription_lang": { - "name": "優先トランスクリプション言語", - "description": "ボイスノートのトランスクリプトの優先言語(例:EN、ES、FR)" - }, - "notification_transcript": { - "name": "通知トランスクリプト", - "description": "通知でボイスノートをトランスクリプトします\nこの機能では、より良い通知でチャットプレビュー機能を有効にする必要があります" - } - } - }, - "voice_note_auto_play": { - "name": "ボイスノートの自動再生", - "description": "現在のボイスノートが終了すると、次のボイスノートが自動的に再生されます" - }, - "friend_notes": { - "name": "友達のメモ", - "description": "友達のプロフィールにメモを追加できます" - }, - "cof_experiments": { - "name": "COF実験", - "description": "未リリースの/ベータ版のSnapchat機能を有効にします" - }, - "context_menu_fix": { - "name": "コンテキストメニューの修正", - "description": "デバイスがオフラインのときに正しく表示されないため、友達フィードメニューを修復しようとします" - }, - "app_lock": { - "name": "アプリロック", - "description": "パスコードなしでSnapchatへのアクセスを防ぎます", - "properties": { - "lock_on_resume": { - "name": "再開時にロック", - "description": "再開時にアプリをロックします" - } - } - }, - "infinite_story_boost": { - "name": "無限のストーリーブースト", - "description": "ストーリーブーストの制限遅延をバイパス" - }, - "meo_passcode_bypass": { - "name": "My Eyes Onlyパスコードをバイパス", - "description": "My Eyes Onlyパスコードをバイパスします\nこれは、パスコードが以前に正しく入力された場合にのみ機能します" - }, - "no_friend_score_delay": { - "name": "友達のスコアの遅延なし", - "description": "友達のスコアを表示するときの遅延を削除します" - }, - "best_friend_pinning": { - "name": "親友のピン留め", - "description": "友達をナンバーワンの親友としてピン留めできます。注意:ピン留めされた親友はあなただけが見ることができます" - }, - "e2ee": { - "name": "エンドツーエンド暗号化", - "description": "共有秘密鍵を使用してAESでメッセージを暗号化します\nキーを安全な場所に保存してください!", - "properties": { - "encrypted_message_indicator": { - "name": "暗号化されたメッセージインジケーター", - "description": "あなただけに送信されたメッセージの横に🔒絵文字を追加します" - }, - "force_message_encryption": { - "name": "メッセージ暗号化を強制", - "description": "複数の会話が選択されている場合にのみ、E2E暗号化が有効になっていない人に暗号化されたメッセージを送信するのを防ぎます" - } - } - }, - "add_friend_source_spoof": { - "name": "友達追加ソースを偽装", - "description": "友達リクエストのソースを偽装します" - }, - "hidden_snapchat_plus_features": { - "name": "非表示のSnapchat Plus機能", - "description": "未リリースの/ベータ版のSnapchat Plus機能を有効にします\n古いSnapchatバージョンでは機能しない場合があります" - }, - "custom_streaks_expiration_format": { - "name": "カスタム連続記録有効期限形式", - "description": "連続記録の有効期限形式をカスタマイズします\n\n利用可能な変数:\n - %c:連続記録数\n - %e:砂時計絵文字\n - %d:日\n - %h:時間\n - %m:分\n - %s:秒\n - %w:残り時間" - }, - "prevent_forced_logout": { - "name": "強制ログアウトを防止", - "description": "別のデバイスでログインしたときにSnapchatがあなたをログアウトするのを防ぎます" - }, - "snapscore_changes": { - "name": "Snapscoreの変更", - "description": "友達のSnapscoreの変更を追跡します\nこの機能は新しいバージョンのSnapchatでのみ使用してください" - } - } - }, - "scripting": { - "name": "スクリプト", - "description": "PurrfectSnapを拡張するためにカスタムスクリプトを実行", - "properties": { - "developer_mode": { - "name": "開発者モード", - "description": "SnapchatのUIにデバッグ情報を表示します" - }, - "module_folder": { - "name": "モジュールフォルダ", - "description": "スクリプトが配置されているフォルダ" - }, - "auto_reload": { - "name": "自動リロード", - "description": "変更時にスクリプトを自動的にリロードします" - }, - "integrated_ui": { - "name": "統合UI", - "description": "スクリプトがSnapchatにカスタムUIコンポーネントを追加できるようにします" - }, - "disable_log_anonymization": { - "name": "ログの匿名化を無効にする", - "description": "ログの匿名化を無効にします" - }, - "disable_optimization": { - "name": "最適化を無効にする", - "description": "スクリプトの最適化を無効にします。これにより、パフォーマンスの問題が発生する可能性があります。" - } - } - }, - "friend_tracker": { - "name": "友達トラッカー", - "description": "Snapchatでの友達の活動を記録します", - "properties": { - "record_messaging_events": { - "name": "メッセージングイベントを記録", - "description": "スナップを開いたり、メッセージを読んだりするなどのメッセージングイベントを記録します。" - }, - "allow_running_in_background": { - "name": "バックグラウンドでの実行を許可", - "description": "トラッカーがバックグラウンドで実行できるようにします。注意:これにより、バッテリーが大幅に消耗します" - }, - "auto_purge": { - "name": "自動パージ", - "description": "指定した時間より古いキャッシュされたイベントを自動的に削除します" - } - } - } - }, - "options": { - "app_appearance": { - "always_light": "常にライト", - "always_dark": "常にダーク" - }, - "friend_feed_menu_buttons": { - "auto_download": "⬇️自動ダウンロード", - "auto_save": "💬メッセージを自動保存", - "unsaveable_messages": "⬇️保存不可能なメッセージ", - "auto_open_snaps": "📸スナップを自動で開く", - "stealth": "👻ステルスモード", - "mark_snaps_as_seen": "👀スナップを既読にする", - "mark_stories_as_seen_locally": "👀ストーリーをローカルで既読にする", - "conversation_info": "🧑‍🤝‍🧑会話情報", - "e2e_encryption": "🔒E2E暗号化を使用" - }, - "path_format": { - "create_author_folder": "作成者ごとにフォルダを作成", - "create_source_folder": "メディアソースタイプごとにフォルダを作成", - "append_hash": "ファイル名に一意のハッシュを追加", - "append_source": "ファイル名にメディアソースを追加", - "append_username": "ファイル名にユーザー名を追加", - "append_date_time": "ファイル名に日時を追加" - }, - "auto_download_sources": { - "friend_snaps": "友達のスナップ", - "friend_stories": "友達のストーリー", - "public_stories": "公開ストーリー", - "spotlight": "スポットライト" - }, - "logging": { - "started": "開始", - "success": "成功", - "progress": "進行中", - "failure": "失敗" - }, - "notifications": { - "chat_screenshot": "スクリーンショット", - "chat_screen_record": "画面録画", - "snap_replay": "スナップのリプレイ", - "camera_roll_save": "カメラロールに保存", - "chat": "チャット", - "chat_reply": "チャットの返信", - "snap": "スナップ", - "typing": "入力中", - "stories": "ストーリー", - "speaking": "話しています", - "chat_reaction": "DMリアクション", - "group_chat_reaction": "グループリアクション", - "initiate_audio": "着信音声通話", - "abandon_audio": "不在着信音声通話", - "initiate_video": "着信ビデオ通話", - "abandon_video": "不在着信ビデオ通話", - "map_live_location": "地図のライブロケーション" - }, - "gallery_media_send_override": { - "always_ask": "常に尋ねる", - "ORIGINAL": "オリジナルメディア", - "NOTE": "音声メモ", - "SNAP": "スナップ", - "SAVEABLE_SNAP": "保存可能なスナップ" - }, - "strip_media_metadata": { - "hide_caption_text": "キャプションテキストを非表示", - "hide_snap_filters": "スナップフィルターを非表示", - "hide_extras": "追加情報を非表示(例:メンション)", - "remove_audio_note_duration": "音声メモの長さを削除", - "remove_audio_note_transcript_capability": "音声メモのトランスクリプト機能を削除" - }, - "hide_ui_components": { - "hide_profile_call_buttons": "プロフィールの通話ボタンを削除", - "hide_chat_call_buttons": "チャットの通話ボタンを削除", - "hide_live_location_share_button": "ライブロケーション共有ボタンを削除", - "hide_stickers_button": "ステッカーボタンを削除", - "hide_voice_record_button": "音声録音ボタンを削除", - "hide_unread_chat_hint": "未読チャットのヒントを削除", - "hide_post_to_story_buttons": "スナップ送信前にストーリーに投稿ボタンを削除", - "hide_billboard_prompt": "友達フィードのビルボードプロンプトを削除", - "hide_snapchat_plus_gift_reminders": "会話のSnapchat Plusギフトリマインダーを削除", - "hide_map_reactions": "マップリアクションを削除" - }, - "hide_story_suggestions": { - "hide_suggested_friend_stories": "提案された友達のストーリーを非表示", - "hide_my_stories": "マイストーリーを非表示" - }, - "home_tab": { - "map": "マップ", - "chat": "チャット", - "camera": "カメラ", - "discover": "発見", - "spotlight": "スポットライト" - }, - "add_friend_source_spoof": { - "added_by_username": "ユーザー名で", - "added_by_mention": "メンションで", - "added_by_group_chat": "グループチャットで", - "added_by_qr_code": "QRコードで", - "added_by_community": "コミュニティで", - "added_by_quick_add": "クイック追加で(BANされるリスクが高い)" - }, - "bypass_video_length_restriction": { - "single": "単一メディア", - "split": "分割メディア" - }, - "old_bitmoji_selfie": { - "2d": "2D ビット文字", - "3d": "3D ビット文字" - }, - "disable_confirmation_dialogs": { - "erase_message": "メッセージを消去", - "remove_friend": "友達を削除", - "block_friend": "友達をブロック", - "ignore_friend": "友達を無視", - "hide_friend": "友達を非表示", - "hide_conversation": "会話を非表示", - "clear_conversation": "友達フィードから会話をクリア" - }, - "auto_reload": { - "snapchat_only": "Snapchatのみ", - "all": "すべて(Snapchat + PurrfectSnap)" - }, - "edit_text_override": { - "multi_line_chat_input": "複数行チャット入力", - "bypass_text_input_limit": "テキスト入力制限をバイパス" - }, - "auto_purge": { - "never": "なし", - "1_hour": "1時間", - "3_hours": "3時間", - "6_hours": "6時間", - "12_hours": "12時間", - "1_day": "1日", - "3_days": "3日", - "1_week": "1週間", - "2_weeks": "2週間", - "1_month": "1か月", - "3_months": "3か月", - "6_months": "6か月" - }, - "disable_story_sections": { - "friends": "友達", - "suggested_stories": "提案されたストーリー", - "following": "フォロー中", - "discover": "発見" - }, - "disable_cameras": { - "front": "フロントカメラ", - "back": "バックカメラ" - }, - "disable_permission_requests": { - "notifications": "通知", - "read_media_images": "メディア画像を読み込む", - "read_media_video": "メディアビデオを読み込む", - "camera": "カメラ", - "microphone": "マイク", - "location": "場所", - "read_contacts": "連絡先を読み込む", - "nearby_devices": "近くのデバイス", - "phone_calls": "電話" - }, - "message_indicators": { - "encryption_indicator": "あなただけに送信されたメッセージの横に🔒アイコンを追加します", - "platform_indicator": "メディアが送信されたプラットフォームのアイコンを追加します(例:Android、iOS、Web)", - "location_indicator": "場所が有効になっているときに送信されたスナップに📍アイコンを追加します", - "ovf_editor_indicator": "OVFエディタを使用してスナップが送信されたかどうかを示します", - "director_mode_indicator": "ディレクターモードを使用して送信されたスナップに🎬アイコンを追加します。これを使用してギャラリー画像をスナップとして送信できます" - }, - "auto_mark_as_read": { - "conversation_read": "メッセージ送信時に会話を既読にする", - "snap_reply": "返信時にスナップを既読にする", - "save_snap_in_chat": "ステルスモードでチャットに保存するときにスナップを既読にする" - }, - "friend_mutation_notifier": { - "remove_friend": "誰かがあなたを友達から削除したときに通知", - "birthday_changes": "誰かが誕生日を変更したときに通知", - "bitmoji_selfie_changes": "誰かがBitmojiセルフィーを変更したときに通知", - "bitmoji_avatar_changes": "誰かがBitmojiアバターを変更したときに通知", - "bitmoji_background_changes": "誰かがBitmojiの背景を変更したときに通知", - "bitmoji_scene_changes": "誰かがBitmojiシーンを変更したときに通知" - }, - "snapchat_plus": { - "not_subscribed": "未登録", - "basic": "基本", - "ad_free": "広告なし" - }, - "double_tap_chat_action": { - "like_message": "メッセージにいいね", - "copy_text": "テキストをクリップボードにコピー", - "delete_message": "メッセージを削除", - "mark_as_read": "既読にする", - "custom_emoji_reaction": "カスタム絵文字リアクション" - }, - "startup_default_camera": { - "front": "フロントカメラ", - "back": "バックカメラ" - } - } - }, - "friend_menu_option": { - "mark_snaps_as_seen": "スナップを既読にする", - "mark_stories_as_seen_locally": "ストーリーをローカルで既読にする", - "preview": "プレビュー", - "stealth_mode": "ステルスモード", - "auto_download_blacklist": "自動ダウンロードブラックリスト", - "anti_auto_save": "自動保存を防止" - }, - "content_type": { - "CHAT": "チャット", - "SNAP": "スナップ", - "EXTERNAL_MEDIA": "外部メディア", - "NOTE": "音声メモ", - "STICKER": "ステッカー", - "SHARE": "共有", - "STATUS": "ステータス", - "LOCATION": "場所", - "STATUS_SAVE_TO_CAMERA_ROLL": "カメラロールに保存済み", - "STATUS_CONVERSATION_CAPTURE_SCREENSHOT": "スクリーンショット", - "STATUS_CONVERSATION_CAPTURE_RECORD": "画面録画", - "STATUS_CALL_MISSED_VIDEO": "不在着信ビデオ通話", - "STATUS_CALL_MISSED_AUDIO": "不在着信音声通話", - "LIVE_LOCATION_SHARE": "ライブロケーションを共有", - "CREATIVE_TOOL_ITEM": "クリエイティブツールアイテム", - "FAMILY_CENTER_INVITE": "ファミリーセンターへの招待", - "FAMILY_CENTER_ACCEPT": "ファミリーセンターを承認", - "FAMILY_CENTER_LEAVE": "ファミリーセンターを退出", - "STATUS_PLUS_GIFT": "ステータスプラスギフト", - "TINY_SNAP": "小さなスナップ", - "STATUS_COUNTDOWN": "カウントダウン", - "MAP_REACTION": "マップリアクション" - }, - "media_download_source": { - "none": "なし", - "pending": "保留中", - "chat_media": "チャットメディア", - "story": "ストーリー", - "public_story": "公開ストーリー", - "spotlight": "スポットライト", - "profile_picture": "プロフィール写真", - "story_logger": "ストーリーロガー", - "message_logger": "メッセージロガー", - "merged": "マージ済み", - "voice_call": "音声通話" - }, - "chat_action_menu": { - "preview_button": "プレビュー", - "download_button": "ダウンロード", - "delete_logged_message_button": "ログに記録されたメッセージを削除", - "show_chat_edit_history": "チャット編集履歴を表示", - "convert_message": "メッセージを変換" - }, - "opera_context_menu": { - "download": "メディアをダウンロード", - "sent_at": "{date}に送信", - "created_at": "{date}に作成", - "expires_at": "{date}に期限切れ", - "media_size": "メディアサイズ:{size}", - "media_duration": "メディアの長さ:{duration}ミリ秒", - "show_debug_info": "デバッグ情報を表示" - }, - "modal_option": { - "profile_info": "プロフィール情報", - "close": "閉じる" - }, - "gallery_media_send_override": { - "multiple_media_toast": "一度に1つのメディアしか送信できません" - }, - "mark_as_seen": { - "no_unseen_snaps_toast": "未読のスナップはありません!", - "seen_toast": "既読にしました!", - "unseen_toast": "未読にしました!", - "already_seen_toast": "既に既読です!", - "already_unseen_toast": "既に未読です!" - }, - "conversation_preview": { - "streak_expiration": "{day}日{hour}時間{minute}分で期限切れ", - "total_messages": "送受信されたメッセージの合計:{count}", - "title": "プレビュー", - "unknown_user": "不明なユーザー", - "no_messages": "メッセージが見つかりません!" - }, - "profile_info": { - "title": "プロフィール情報", - "first_created_username": "最初に作成されたユーザー名", - "mutable_username": "変更可能なユーザー名", - "display_name": "表示名", - "added_date": "追加日", - "birthday": "誕生日:{month} {day}", - "hidden_birthday": "誕生日:非表示", - "friendship": "友達関係", - "add_source": "ソースを追加", - "snapchat_plus": "スナップチャットプラス", - "snapchat_plus_state": { - "subscribed": "登録済み", - "not_subscribed": "未登録" - } - }, - "friendship_link_type": { - "mutual": "相互", - "outgoing": "送信", - "blocked": "ブロック済み", - "deleted": "削除済み", - "following": "フォロー中", - "suggested": "提案", - "incoming": "受信", - "incoming_follower": "受信フォロワー" - }, - "bulk_messaging_action": { - "choose_action_title": "アクションを選択", - "progress_status": "{total}件中{index}件を処理中", - "selection_dialog_continue_button": "続行", - "confirmation_dialog": { - "title": "よろしいですか?", - "message": "これは選択したすべての友達に影響します。この操作は元に戻せません。" - }, - "actions": { - "remove_friends": "友達を削除", - "clear_conversations": "会話をクリア" - } - }, - "chat_export": { - "exporter_dialog": { - "select_conversations_title": "会話を選択", - "text_field_selection": "{amount}件選択済み", - "text_field_selection_all": "すべて", - "export_file_format_title": "ファイル形式をエクスポート", - "message_type_filter_title": "メッセージをタイプでフィルタリング", - "amount_of_messages_title": "メッセージ数(すべての場合は空白のまま)", - "download_medias_title": "メディアをダウンロード" - }, - "dialog_negative_button": "キャンセル", - "dialog_positive_button": "エクスポート", - "exported_to": "{path}にエクスポートしました", - "exporting_chats": "チャットをエクスポート中...", - "processing_chats": "{amount}件の会話を処理中...", - "export_fail": "会話{conversation}のエクスポートに失敗しました", - "writing_output": "出力を書き込み中...", - "finished": "完了!このダイアログを閉じることができます。", - "no_messages_found": "メッセージが見つかりません!", - "exporting_message": "会話{conversation}をエクスポート中..." - }, - "button": { - "ok": "わかりました", - "positive": "はい", - "negative": "いいえ", - "cancel": "キャンセル", - "open": "開く", - "download": "ダウンロード", - "send": "送信", - "restore_original": "オリジナルを復元", - "convert_external_media": "外部メディアを変換", - "save": "保存" - }, - "tracker_events": { - "conversation_enter": "会話に参加", - "conversation_exit": "会話から退出", - "started_typing": "入力を開始", - "stopped_typing": "入力を停止", - "started_speaking": "話し始めました", - "stopped_speaking": "話すのをやめました", - "started_peeking": "覗き見を開始", - "stopped_peeking": "覗き見を停止", - "message_read": "メッセージを既読", - "message_deleted": "メッセージを削除", - "message_saved": "メッセージを保存", - "message_unsaved": "メッセージの保存を解除", - "message_edited": "メッセージを編集", - "message_reaction_add": "メッセージリアクションを追加", - "message_reaction_remove": "メッセージリアクションを削除", - "snap_opened": "スナップを開きました", - "snap_replayed": "スナップをリプレイ", - "snap_replayed_twice": "スナップを2回リプレイ", - "snap_screenshot": "スナップのスクリーンショット", - "snap_screen_record": "スナップの画面録画" - }, - "tracker_actions": { - "log": "ログ", - "in_app_notification": "アプリ内通知", - "push_notification": "プッシュ通知", - "custom": "カスタム" - }, - "better_notifications": { - "button": { - "reply": "返信", - "download": "ダウンロード", - "mark_as_read": "既読にする" - } - }, - "profile_picture_downloader": { - "button": "プロフィール写真をダウンロード", - "title": "プロフィール写真ダウンローダー", - "avatar_option": "アバター", - "background_option": "背景" - }, - "call_start_confirmation": { - "dialog_title": "通話を開始", - "dialog_message": "通話を開始してもよろしいですか?" - }, - "half_swipe_notifier": { - "notification_channel_name": "ハーフスワイプ", - "notification_content_dm": "{friend}があなたのチャットに{duration}秒間ハーフスワイプしました", - "notification_content_group": "{friend}が{group}に{duration}秒間ハーフスワイプしました" - }, - "download_processor": { - "attachment_type": { - "snap": "スナップ", - "sticker": "ステッカー", - "gif": "GIF", - "external_media": "外部メディア", - "note": "メモ", - "original_story": "オリジナルストーリー" - }, - "select_attachments_title": "添付ファイルを選択", - "download_started_toast": "ダウンロードを開始しました", - "unsupported_content_type_toast": "サポートされていないコンテンツタイプです!", - "failed_no_longer_available_toast": "メディアは利用できなくなりました", - "no_attachments_toast": "添付ファイルが見つかりません!", - "already_queued_toast": "メディアは既にキューにあります!", - "already_downloaded_toast": "メディアは既にダウンロードされています!", - "content_saved_toast": "保存しました!", - "download_toast": "{path}をダウンロード中...", - "processing_toast": "{path}を処理中...", - "failed_generic_toast": "ダウンロードに失敗しました", - "failed_to_create_preview_toast": "プレビューの作成に失敗しました", - "failed_processing_toast": "処理に失敗しました {error}", - "failed_gallery_toast": "ギャラリーへの保存に失敗しました {error}", - "dash_no_chapter": "チャプターが見つかりません", - "dash_dialog": { - "title": "ダッシュメディアをダウンロード", - "download_all": "すべてダウンロード", - "segment_text": "セグメント{from} - {to}" - } - }, - "streaks_reminder": { - "notification_title": "連続記録", - "notification_text": "{hoursLeft}時間後に{friend}との連続記録が切れます" - }, - "biometric_auth": { - "unlock_button": "ロック解除", - "title": "Snapchatをロック解除", - "subtitle": "Snapchatをロック解除するには認証してください" - }, - "end_to_end_encryption": { - "toolbox": { - "no_shared_key": "この友達とはまだ共有シークレットがありません。新しいものを開始するには下をクリックしてください。", - "shared_key_fingerprint": "あなたの指紋は:\n\n{fingerprint}\n\n友達の指紋と一致することを確認してください!", - "initiate_exchange_button": "キー交換を開始" - }, - "confirmation_dialogs": { - "title": "エンドツーエンド暗号化", - "confirmation_1": "警告:これにより既存のキーが上書きされます。この友達からのすべての暗号化されたメッセージへのアクセスを失います。続行してもよろしいですか?", - "confirmation_2": "本当に続行してもよろしいですか?これが最後のチャンスです。" - }, - "unencrypted_conversation_send_failure_toast": "暗号化されたコンテンツを暗号化された会話と暗号化されていない会話の両方に送信することはできません!", - "native_hooks_send_failure_toast": "送信に失敗しました!設定でネイティブフックを有効にしてください。", - "no_participants_to_encrypt_toast": "この会話にはメッセージを暗号化する友達がいません!", - "encryption_failed_toast": "メッセージの暗号化に失敗しました!詳細はlogcatを確認してください。", - "accept_public_key_success_toast": "公開鍵が正常に受け入れられました!", - "accept_secret_key_success_toast": "完了!この友達と暗号化されたメッセージを送受信できるようになりました。", - "accept_public_key_failure_toast": "公開鍵の受け入れに失敗しました", - "accept_secret_key_failure_toast": "秘密鍵の受け入れに失敗しました", - "accept_secret_button": "シークレットを受け入れる", - "accept_public_key_button": "公開鍵を受け入れる", - "outgoing_pk_message": "キー交換リクエスト", - "outgoing_secret_message": "キー交換応答", - "incoming_pk_message": "公開鍵リクエストを受信しました。受け入れるには下をクリックしてください。", - "incoming_secret_message": "友達があなたの公開鍵を受け入れました。シークレットを受け入れるには下をクリックしてください。" - }, - "auto_open_snaps": { - "title": "スナップを自動で開く", - "notification_content": "{count}件のスナップを開きました" - }, - "friend_mutation_observer": { - "notification_channel_name": "友達の変更オブザーバー", - "friend_removed": "{username}があなたを友達から削除しました", - "birthday_removed": "{username}が誕生日({birthday})を削除しました", - "birthday_added": "{username}が誕生日({birthday})を追加しました", - "birthday_changed": "{username}が誕生日を{oldBirthday}から{newBirthday}に変更しました", - "bitmoji_selfie_changed": "{username}がBitmojiセルフィーを変更しました", - "bitmoji_avatar_changed": "{username}がBitmojiアバターを変更しました", - "bitmoji_background_changed": "{username}がBitmojiの背景を変更しました", - "bitmoji_scene_changed": "{username}がBitmojiシーンを変更しました" - }, - "material3_strings": { - "date_range_picker_start_headline": "開始", - "date_range_picker_end_headline": "終了", - "date_range_picker_title": "日付範囲を選択", - "date_picker_switch_to_calendar_mode": "カレンダー", - "date_picker_switch_to_input_mode": "入力", - "date_range_picker_scroll_to_previous_month": "前の月", - "date_range_picker_scroll_to_next_month": "次の月", - "date_picker_today_description": "今日", - "date_range_picker_day_in_range": "選択済み", - "date_input_invalid_for_pattern": "無効な日付", - "date_input_invalid_year_range": "無効な年", - "date_input_invalid_not_allowed": "無効な日付", - "date_range_input_invalid_range_input": "無効な日付範囲" - }, - "send_override_dialog": { - "title": "メディアを{type}として送信", - "duration": "長さ:{duration}", - "saveable_snap_hint": "チャットでスナップを保存可能にする", - "unlimited_duration": "無制限" - }, - "invalid_input_toast": "無効な入力です!有効な値を入力したことを確認してください。" -} \ No newline at end of file diff --git a/common/src/main/assets/lang/ja_JP.json b/common/src/main/assets/lang/ja_JP.json new file mode 100644 index 00000000..651c55d1 --- /dev/null +++ b/common/src/main/assets/lang/ja_JP.json @@ -0,0 +1,29 @@ +{ + "setup": { + "dialogs": { + "save_folder": "SnapEnhanceは、Snapchatからメディアをダウンロードして保存するためにストレージ許可が必要です。\nメディアをダウンロードする場所を選択してください。", + "select_save_folder_button": "フォルダを選択" + }, + "mappings": { + "dialog": "スナップチャットのさまざまなバージョンを動的にサポートするためには、SnapEnhanceが正常に機能するためには、マッピングが必要です。これには5秒以上かかりません。" + } + }, + "manager": { + "dialogs": { + "scripting_warning": { + "content": "SnapEnhance にはスクリプト ツールが含まれており、デバイス上でユーザー定義のコードを実行できます。 細心の注意を払い、既知の信頼できるソースからのみモジュールをインストールしてください。 未承認または未検証のモジュールは、システムにセキュリティ上のリスクをもたらす可能性があります。" + } + } + }, + "features": { + "properties": { + "experimental": { + "properties": { + "account_switcher": { + "description": "アカウントを切り替えることができますログアウトせずに Bitmoji プロフィールの横にある検索アイコンを長押ししてメニューを開きます 注: この機能は実験的なものであり、将来変更される可能性があります" + } + } + } + } + } +} diff --git a/common/src/main/assets/lang/kn.json b/common/src/main/assets/lang/kn.json deleted file mode 100644 index 233b0765..00000000 --- a/common/src/main/assets/lang/kn.json +++ /dev/null @@ -1,2022 +0,0 @@ -{ - "setup": { - "dialogs": { - "select_language": "ಭಾಷೆ ಆಯ್ಕೆಮಾಡಿ", - "save_folder": "PurrfectSnap ಗೆ Snapchat ನಿಂದ ಮಾಧ್ಯಮವನ್ನು ಡೌನ್‌ಲೋಡ್ ಮಾಡಲು ಮತ್ತು ಉಳಿಸಲು ಸಂಗ್ರಹಣೆ ಅನುಮತಿಗಳ ಅಗತ್ಯವಿದೆ.\nಮಾಧ್ಯಮವನ್ನು ಎಲ್ಲಿ ಡೌನ್‌ಲೋಡ್ ಮಾಡಬೇಕು ಎಂಬುದನ್ನು ದಯವಿಟ್ಟು ಆಯ್ಕೆಮಾಡಿ.", - "select_save_folder_button": "ಫೋಲ್ಡರ್ ಆಯ್ಕೆಮಾಡಿ" - }, - "mappings": { - "dialog": "ಮ್ಯಾಪಿಂಗ್‌ಗಳನ್ನು ರಚಿಸಲಾಗುತ್ತಿದೆ, ಇದಕ್ಕೆ ಸ್ವಲ್ಪ ಸಮಯ ತೆಗೆದುಕೊಳ್ಳಬಹುದು...", - "generate_failure_no_snapchat": "PurrfectSnap Snapchat ಅನ್ನು ಪತ್ತೆಹಚ್ಚಲು ಸಾಧ್ಯವಾಗಲಿಲ್ಲ, ದಯವಿಟ್ಟು Snapchat ಅನ್ನು ಮರುಸ್ಥಾಪಿಸಲು ಪ್ರಯತ್ನಿಸಿ.", - "generate_failure": "ಮ್ಯಾಪಿಂಗ್‌ಗಳನ್ನು ರಚಿಸಲು ಪ್ರಯತ್ನಿಸುವಾಗ ದೋಷ ಸಂಭವಿಸಿದೆ, ದಯವಿಟ್ಟು ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ." - }, - "permissions": { - "dialog": "ಮುಂದುವರೆಯಲು ನೀವು ಈ ಕೆಳಗಿನ ಅವಶ್ಯಕತೆಗಳನ್ನು ಪೂರೈಸಬೇಕು:", - "notification_access": "ಅಧಿಸೂಚನೆ ಪ್ರವೇಶ", - "battery_optimization": "ಬ್ಯಾಟರಿ ಆಪ್ಟಿಮೈಸೇಶನ್", - "display_over_other_apps": "ಇತರ ಅಪ್ಲಿಕೇಶನ್‌ಗಳ ಮೇಲೆ ಪ್ರದರ್ಶಿಸಿ", - "request_button": "ವಿನಂತಿ" - } - }, - "scopes": { - "friend": "ಸ್ನೇಹಿತ", - "group": "ಗುಂಪು" - }, - "manager": { - "routes": { - "tasks": "ಕಾರ್ಯಗಳು", - "features": "ವೈಶಿಷ್ಟ್ಯಗಳು", - "manage_rule_feature": "ನಿಯಮ ವೈಶಿಷ್ಟ್ಯವನ್ನು ನಿರ್ವಹಿಸಿ", - "home": "ಮುಖಪುಟ", - "home_settings": "ಸೆಟ್ಟಿಂಗ್‌ಗಳು", - "home_logs": "ಲಾಗ್‌ಗಳು", - "logger_history": "ಲಾಗರ್ ಇತಿಹಾಸ", - "logged_stories": "ಲಾಗ್ ಮಾಡಿದ ಕಥೆಗಳು", - "friend_tracker": "ಸ್ನೇಹಿತ ಟ್ರ್ಯಾಕರ್", - "edit_rule": "ನಿಯಮವನ್ನು ಸಂಪಾದಿಸಿ", - "file_imports": "ಫೈಲ್ ಆಮದುಗಳು", - "manage_repos": "ರೆಪೊಸಿಟರಿಗಳನ್ನು ನಿರ್ವಹಿಸಿ", - "social": "ಸಾಮಾಜಿಕ", - "manage_scope": "ವ್ಯಾಪ್ತಿಯನ್ನು ನಿರ್ವಹಿಸಿ", - "messaging_preview": "ಮುನ್ನೋಟ", - "scripts": "ಸ್ಕ್ರಿಪ್ಟ್‌ಗಳು", - "better_location": "ಉತ್ತಮ ಸ್ಥಳ" - }, - "sections": { - "home": { - "version_title": "v{versionName} · Eternal ನಿಂದ ಫೋರ್ಕ್ ಮಾಡಲಾಗಿದೆ", - "update_title": "PurrfectSnap ನವೀಕರಣ", - "update_content": "ಆವೃತ್ತಿ {version} ಲಭ್ಯವಿದೆ!", - "update_button": "ಡೌನ್‌ಲೋಡ್ ಮಾಡಿ", - "debug_build_summary_title": "ನೀವು PurrfectSnap ನ ಡೀಬಗ್ ಬಿಲ್ಡ್ ಅನ್ನು ಚಲಾಯಿಸುತ್ತಿದ್ದೀರಿ", - "debug_build_summary_content": "ಆವೃತ್ತಿ {versionName} ({versionCode})", - "debug_build_summary_date": "ಬಿಲ್ಡ್ ದಿನಾಂಕ: {date} ({days} ದಿನಗಳ ಹಿಂದೆ)", - "quick_actions_title": "ತ್ವರಿತ ಕ್ರಿಯೆಗಳು", - "download_icon_description": "ಡೌನ್‌ಲೋಡ್ ಮಾಡಿ", - "completed_icon_description": "ಪೂರ್ಣಗೊಂಡಿದೆ", - "failed_icon_description": "ವಿಫಲವಾಗಿದೆ", - "manage_quick_actions_description": "ತ್ವರಿತ ಕ್ರಿಯೆಗಳನ್ನು ನಿರ್ವಹಿಸಿ", - "quick_actions_icon_description": "ತ್ವರಿತ ಕ್ರಿಯೆಗಳು", - "add_quick_action_description": "ತ್ವರಿತ ಕ್ರಿಯೆಯನ್ನು ಸೇರಿಸಿ" - }, - "home_logs": { - "no_logs_hint": "ಯಾವುದೇ ಲಾಗ್‌ಗಳು ಲಭ್ಯವಿಲ್ಲ", - "clear_logs_button": "ಲಾಗ್‌ಗಳನ್ನು ತೆರವುಗೊಳಿಸಿ", - "export_logs_button": "ಲಾಗ್‌ಗಳನ್ನು ರಫ್ತು ಮಾಡಿ", - "saving_logs_toast": "ಲಾಗ್‌ಗಳನ್ನು ಉಳಿಸಲಾಗುತ್ತಿದೆ, ಇದಕ್ಕೆ ಸ್ವಲ್ಪ ಸಮಯ ತೆಗೆದುಕೊಳ್ಳಬಹುದು...", - "saved_logs_success_toast": "ಲಾಗ್‌ಗಳನ್ನು ಯಶಸ್ವಿಯಾಗಿ ಉಳಿಸಲಾಗಿದೆ", - "saved_logs_failure_toast": "ಲಾಗ್‌ಗಳನ್ನು ಉಳಿಸಲು ವಿಫಲವಾಗಿದೆ" - }, - "home_settings": { - "actions_title": "ಕ್ರಿಯೆಗಳು", - "message_logger_title": "ಸಂದೇಶ ಲಾಗರ್", - "debug_title": "ಡೀಬಗ್", - "success_toast": "ಮುಗಿದಿದೆ!", - "message_logger_summary": "{messageCount} ಸಂದೇಶಗಳು\n{storyCount} ಕಥೆಗಳು", - "export_button": "ರಫ್ತು ಮಾಡಿ", - "clear_button": "ತೆರವುಗೊಳಿಸಿ", - "view_logger_history_button": "ಲಾಗರ್ ಇತಿಹಾಸವನ್ನು ವೀಕ್ಷಿಸಿ", - "updates_title": "ನವೀಕರಣಗಳು", - "auto_update_check": "ನವೀಕರಣಗಳಿಗಾಗಿ ಸ್ವಯಂಚಾಲಿತವಾಗಿ ಪರಿಶೀಲಿಸಿ", - "update_check_frequency": "ನವೀಕರಣ ಪರಿಶೀಲನೆ ಆವರ್ತನ", - "update_check_frequency_daily": "ದೈನಂದಿನ", - "update_check_frequency_weekly": "ಸಾಪ್ತಾಹಿಕ", - "update_check_frequency_monthly": "ಮಾಸಿಕ", - "theme_icon_description": "ಥೀಮ್", - "app_theme_title": "ಅಪ್ಲಿಕೇಶನ್ ಥೀಮ್", - "theme_mode_system": "ಸಿಸ್ಟಮ್", - "theme_mode_light": "ಬೆಳಕು", - "theme_mode_dark": "ಕತ್ತಲೆ", - "ui_settings_title": "UI ಸೆಟ್ಟಿಂಗ್‌ಗಳು", - "haptic_feedback_label": "ಹ್ಯಾಪ್ಟಿಕ್ ಪ್ರತಿಕ್ರಿಯೆ", - "test_mode_label": "ಪರೀಕ್ಷಾ ಮೋಡ್ (ಡೀಬಗ್ ಮಾಡಲು ಮಾತ್ರ)", - "disable_feature_loading_label": "ವೈಶಿಷ್ಟ್ಯ ಲೋಡ್ ಮಾಡುವುದನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಿ", - "disable_auto_mapper_label": "ಸ್ವಯಂ ಮ್ಯಾಪರ್ ಅನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಿ", - "disable_bypass_indicator_label": "ಬೈಪಾಸ್ ಸ್ಥಿತಿ ಸೂಚಕವನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಿ", - "update_notification_channel_name": "PurrfectSnap ನವೀಕರಣಗಳು", - "update_notification_channel_description": "PurrfectSnap ನವೀಕರಣಗಳಿಗಾಗಿ ಅಧಿಸೂಚನೆಗಳು", - "update_notification_title": "PurrfectSnap ನವೀಕರಣ ಲಭ್ಯವಿದೆ", - "update_notification_text": "ಆವೃತ್ತಿ %s ಈಗ ಲಭ್ಯವಿದೆ.", - "export_database_failed_toast": "ಡೇಟಾಬೇಸ್ ರಫ್ತು ಮಾಡಲು ವಿಫಲವಾಗಿದೆ! {message}", - "clear_messages_failed_toast": "ಸಂದೇಶಗಳನ್ನು ತೆರವುಗೊಳಿಸಲು ವಿಫಲವಾಗಿದೆ! {message}", - "clear_file_failed_toast": "ಫೈಲ್ ತೆರವುಗೊಳಿಸಲು ವಿಫಲವಾಗಿದೆ! {message}", - "debug_file_config": "ಸಂರಚನೆ", - "debug_file_mappings": "ಮ್ಯಾಪಿಂಗ್‌ಗಳು", - "debug_file_message_logger": "ಸಂದೇಶ ಲಾಗರ್", - "debug_file_pinned_best_friend": "ಪಿನ್ ಮಾಡಿದ ಅತ್ಯುತ್ತಮ ಸ್ನೇಹಿತ", - "debug_file_native_sig_cache": "ಸ್ಥಳೀಯ ಸಹಿ ಸಂಗ್ರಹ" - }, - "tasks": { - "no_tasks": "ಯಾವುದೇ ಕಾರ್ಯಗಳಿಲ್ಲ", - "merge_button": "ವಿಲೀನಗೊಳಿಸಿ", - "failed_to_open_file": "ಫೈಲ್ ತೆರೆಯಲು ವಿಫಲವಾಗಿದೆ", - "merge_files_toast": "{count} ಫೈಲ್‌ಗಳನ್ನು ವಿಲೀನಗೊಳಿಸಲಾಗುತ್ತಿದೆ", - "remove_selected_tasks_title": "ಆಯ್ದ ಕಾರ್ಯಗಳನ್ನು ತೆಗೆದುಹಾಕಲು ನೀವು ಖಚಿತವಾಗಿದ್ದೀರಾ?", - "remove_all_tasks_title": "ಎಲ್ಲಾ ಕಾರ್ಯಗಳನ್ನು ತೆಗೆದುಹಾಕಲು ನೀವು ಖಚಿತವಾಗಿದ್ದೀರಾ?", - "delete_files_option": "ಫೈಲ್‌ಗಳನ್ನು ಸಹ ಅಳಿಸಿ", - "remove_selected_tasks_confirm": "{count} ಕಾರ್ಯಗಳನ್ನು ತೆಗೆದುಹಾಕುವುದೇ?", - "remove_all_tasks_confirm": "ಎಲ್ಲಾ ಕಾರ್ಯಗಳನ್ನು ತೆಗೆದುಹಾಕುವುದೇ?", - "clear_tasks_description": "ಕಾರ್ಯಗಳನ್ನು ತೆರವುಗೊಳಿಸಿ", - "file_not_found_icon_description": "ಫೈಲ್ ಕಂಡುಬಂದಿಲ್ಲ", - "image_icon_description": "ಚಿತ್ರ", - "video_icon_description": "ವೀಡಿಯೊ", - "audio_icon_description": "ಆಡಿಯೋ", - "file_icon_description": "ಫೈಲ್", - "download_icon_description": "ಡೌನ್‌ಲೋಡ್ ಮಾಡಿ", - "chat_action_icon_description": "ಚಾಟ್ ಕ್ರಿಯೆ", - "cancel_icon_description": "ರದ್ದುಮಾಡಿ", - "success_icon_description": "ಯಶಸ್ಸು", - "failure_icon_description": "ವೈಫಲ್ಯ", - "cancelled_icon_description": "ರದ್ದುಪಡಿಸಲಾಗಿದೆ", - "task_status_failure": "ವೈಫಲ್ಯ", - "task_status_cancelled": "ರದ್ದುಪಡಿಸಲಾಗಿದೆ" - }, - "features": { - "disabled": "ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ", - "export_option": "ರಫ್ತು ಮಾಡಿ", - "import_option": "ಆಮದು ಮಾಡಿ", - "reset_option": "ಮರುಹೊಂದಿಸಿ", - "config_export_success_toast": "ಸಂರಚನೆಯನ್ನು ಯಶಸ್ವಿಯಾಗಿ ರಫ್ತು ಮಾಡಲಾಗಿದೆ", - "config_import_success_toast": "ಸಂರಚನೆಯನ್ನು ಯಶಸ್ವಿಯಾಗಿ ಆಮದು ಮಾಡಲಾಗಿದೆ", - "config_import_failure_toast": "ಸಂರಚನೆಯನ್ನು ಆಮದು ಮಾಡಲು ವಿಫಲವಾಗಿದೆ {error}", - "config_export_failure_toast": "ಸಂರಚನೆಯನ್ನು ರಫ್ತು ಮಾಡಲು ವಿಫಲವಾಗಿದೆ {error}", - "saved_config_snackbar": "ಸಂರಚನೆಯನ್ನು ಉಳಿಸಲಾಗಿದೆ", - "older_required": "ಈ ವೈಶಿಷ್ಟ್ಯಕ್ಕೆ ಸರಿಯಾಗಿ ಕಾರ್ಯನಿರ್ವಹಿಸಲು Snapchat v{version} ಅಥವಾ ಹಳೆಯದು ಅಗತ್ಯವಿದೆ", - "newer_required": "ಈ ವೈಶಿಷ್ಟ್ಯಕ್ಕೆ ಸರಿಯಾಗಿ ಕಾರ್ಯನಿರ್ವಹಿಸಲು Snapchat v{version} ಅಥವಾ ಹೊಸದು ಅಗತ್ಯವಿದೆ", - "search_button": "ಹುಡುಕಿ" - }, - "manage_rule_feature": { - "disable_state_option": "ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ", - "disable_state_subtext": "ಯಾವುದೇ ಸ್ನೇಹಿತರು/ಗುಂಪುಗಳು ಪರಿಣಾಮ ಬೀರುವುದಿಲ್ಲ", - "whitelist_state_option": "ಯಾರೂ ಇಲ್ಲ, ಹೊರತು...", - "whitelist_state_subtext": "ಕೇವಲ {count} ಸ್ನೇಹಿತರು/ಗುಂಪುಗಳು ಈ ನಿಯಮದಿಂದ ಪ್ರಭಾವಿತರಾಗುತ್ತಾರೆ", - "whitelist_state_button": "ಅನುಮತಿಸಲಾದ ಸ್ನೇಹಿತರು/ಗುಂಪುಗಳನ್ನು ಆಯ್ಕೆಮಾಡಿ", - "blacklist_state_option": "ಎಲ್ಲರೂ, ಹೊರತು...", - "blacklist_state_subtext": "ಎಲ್ಲರೂ, {count} ಸ್ನೇಹಿತರು/ಗುಂಪುಗಳನ್ನು ಹೊರತುಪಡಿಸಿ, ಈ ನಿಯಮದಿಂದ ಪ್ರಭಾವಿತರಾಗುತ್ತಾರೆ", - "blacklist_state_button": "ಹೊರತುಪಡಿಸಿದ ಸ್ನೇಹಿತರು/ಗುಂಪುಗಳನ್ನು ಆಯ್ಕೆಮಾಡಿ", - "clear_list_button": "ಸ್ನೇಹಿತರು/ಗುಂಪುಗಳ ಪಟ್ಟಿಯನ್ನು ತೆರವುಗೊಳಿಸಿ", - "dialog_clear_confirmation_text": "ಪಟ್ಟಿಯನ್ನು ತೆರವುಗೊಳಿಸಲು ನೀವು ಖಚಿತವಾಗಿದ್ದೀರಾ?" - }, - "social": { - "friends_tab": "ಸ್ನೇಹಿತರು", - "groups_tab": "ಗುಂಪುಗಳು", - "empty_hint": "(ಖಾಲಿ)", - "streaks_expiration_short": "{hours}ಗಂ" - }, - "manage_scope": { - "logged_stories_button": "ಲಾಗ್ ಮಾಡಿದ ಕಥೆಗಳನ್ನು ತೋರಿಸಿ", - "e2ee_title": "ಎಂಡ್-ಟು-ಎಂಡ್ ಎನ್‌ಕ್ರಿಪ್ಶನ್", - "rules_title": "ನಿಯಮಗಳು", - "participants_text": "{count} ಭಾಗವಹಿಸುವವರು", - "not_found": "ಕಂಡುಬಂದಿಲ್ಲ", - "streaks_title": "ಸ್ಟ್ರೀಕ್ಸ್", - "streaks_length_text": "ಉದ್ದ: {length}", - "streaks_expiration_text": "{eta} ನಲ್ಲಿ ಅವಧಿ ಮುಗಿಯುತ್ತದೆ", - "streaks_expiration_text_expired": "ಅವಧಿ ಮುಗಿದಿದೆ", - "reminder_button": "ಜ್ಞಾಪನೆಯನ್ನು ಹೊಂದಿಸಿ", - "delete_scope_confirm_dialog_title": "ಒಂದು {scope} ಅನ್ನು ಅಳಿಸಲು ನೀವು ಖಚಿತವಾಗಿದ್ದೀರಾ?", - "notes_placeholder": "ಟಿಪ್ಪಣಿ ಸೇರಿಸಲು ಕ್ಲಿಕ್ ಮಾಡಿ", - "invalid_key_size_32_bytes": "ಅಮಾನ್ಯ ಕೀ ಗಾತ್ರ (32 ಬೈಟ್‌ಗಳಾಗಿರಬೇಕು)", - "successfully_imported_key": "ಕೀಯನ್ನು ಯಶಸ್ವಿಯಾಗಿ ಆಮದು ಮಾಡಲಾಗಿದೆ", - "failed_to_import_key": "ಕೀಯನ್ನು ಆಮದು ಮಾಡಲು ವಿಫಲವಾಗಿದೆ: {message}", - "export_base64_button": "ಬೇಸ್64 ರಫ್ತು ಮಾಡಿ", - "import_base64_button": "ಬೇಸ್64 ಆಮದು ಮಾಡಿ" - }, - "logged_stories": { - "story_failed_to_load": "ಲೋಡ್ ಮಾಡಲು ವಿಫಲವಾಗಿದೆ", - "no_stories": "ಯಾವುದೇ ಕಥೆಗಳು ಕಂಡುಬಂದಿಲ್ಲ", - "save_from_cache_button": "ಸಂಗ್ರಹದಿಂದ ಉಳಿಸಿ", - "downloaded_to_path": "{path} ಗೆ ಡೌನ್‌ಲೋಡ್ ಮಾಡಲಾಗಿದೆ", - "download_failed": "ಡೌನ್‌ಲೋಡ್ ವಿಫಲವಾಗಿದೆ: {message}", - "posted_at": "{date} ರಂದು ಪೋಸ್ಟ್ ಮಾಡಲಾಗಿದೆ", - "created_at": "{date} ರಂದು ರಚಿಸಲಾಗಿದೆ", - "failed_to_open_file": "ಫೈಲ್ ತೆರೆಯಲು ವಿಫಲವಾಗಿದೆ. ಹೆಚ್ಚಿನ ಮಾಹಿತಿಗಾಗಿ ಲಾಗ್‌ಗಳನ್ನು ಪರಿಶೀಲಿಸಿ", - "failed_to_get_file": "ಫೈಲ್ ಪಡೆಯಲು ವಿಫಲವಾಗಿದೆ" - }, - "messaging_preview": { - "processed_messages_toast": "{count} ಸಂದೇಶಗಳನ್ನು ಸಂಸ್ಕರಿಸಲಾಗಿದೆ", - "processed_messages_text": "{count} ಸಂದೇಶಗಳನ್ನು ಸಂಸ್ಕರಿಸಲಾಗಿದೆ", - "close_button_description": "ಮುಚ್ಚಿ", - "bridge_connection_failed": "ಸೇತುವೆಗೆ ಸಂಪರ್ಕಿಸಲು ವಿಫಲವಾಗಿದೆ. Snapchat ಹಿನ್ನೆಲೆಯಲ್ಲಿ ಚಾಲನೆಯಲ್ಲಿದೆಯೇ ಎಂದು ಖಚಿತಪಡಿಸಿಕೊಳ್ಳಿ", - "bridge_init_failed": "ಸಂದೇಶ ಕಳುಹಿಸುವ ಸೇತುವೆಯನ್ನು ಪ್ರಾರಂಭಿಸಲು ವಿಫಲವಾಗಿದೆ. Snapchat ಹಿನ್ನೆಲೆಯಲ್ಲಿ ಚಾಲನೆಯಲ್ಲಿದೆಯೇ ಎಂದು ಖಚಿತಪಡಿಸಿಕೊಳ್ಳಿ", - "message_fetch_failed": "ಸಂದೇಶಗಳನ್ನು ಪಡೆಯಲು ವಿಫಲವಾಗಿದೆ", - "no_message_hint": "ಯಾವುದೇ ಸಂದೇಶವಿಲ್ಲ", - "save_selection_option": "ಆಯ್ಕೆಯನ್ನು ಉಳಿಸಿ", - "save_all_option": "ಎಲ್ಲವನ್ನೂ ಉಳಿಸಿ", - "unsave_selection_option": "ಆಯ್ಕೆಯನ್ನು ಉಳಿಸಬೇಡಿ", - "unsave_all_option": "ಎಲ್ಲವನ್ನೂ ಉಳಿಸಬೇಡಿ", - "mark_selection_as_seen_option": "ಆಯ್ದ ಸ್ನ್ಯಾಪ್ ಅನ್ನು ನೋಡಿದಂತೆ ಗುರುತಿಸಿ", - "mark_all_as_seen_option": "ಎಲ್ಲಾ ಸ್ನ್ಯಾಪ್‌ಗಳನ್ನು ನೋಡಿದಂತೆ ಗುರುತಿಸಿ", - "delete_selection_option": "ಆಯ್ಕೆಯನ್ನು ಅಳಿಸಿ", - "delete_all_option": "ಎಲ್ಲವನ್ನೂ ಅಳಿಸಿ" - }, - "logger_history": { - "download_started_toast": "ಡೌನ್‌ಲೋಡ್ ಪ್ರಾರಂಭವಾಯಿತು!", - "download_success_toast": "{path} ಗೆ ಡೌನ್‌ಲೋಡ್ ಮಾಡಲಾಗಿದೆ", - "download_failed_toast": "{message} ಡೌನ್‌ಲೋಡ್ ಮಾಡಲು ವಿಫಲವಾಗಿದೆ", - "edited_at_text": "{message} ({date} ರಂದು ಸಂಪಾದಿಸಲಾಗಿದೆ)", - "download_button": "ಡೌನ್‌ಲೋಡ್ ಮಾಡಿ", - "select_conversation_placeholder": "ಒಂದು ಸಂಭಾಷಣೆಯನ್ನು ಆಯ್ಕೆಮಾಡಿ", - "close_button_description": "ಮುಚ್ಚಿ", - "search_button_description": "ಹುಡುಕಿ", - "list_friend_format": "ಸ್ನೇಹಿತ {name}", - "list_group_format": "ಗುಂಪು {name}", - "no_more_messages": "ಇನ್ನಷ್ಟು ಸಂದೇಶಗಳಿಲ್ಲ", - "reverse_order_checkbox": "ವಿಲೋಮ ಕ್ರಮ", - "chat_attachment": "ಲಗತ್ತು {index}", - "empty_message": "ಖಾಲಿ ಚಾಟ್ ಸಂದೇಶ", - "message_parse_failed": "ಸಂದೇಶವನ್ನು ಪಾರ್ಸ್ ಮಾಡಲು ವಿಫಲವಾಗಿದೆ", - "unknown_sender": "ಅಪರಿಚಿತ ಕಳುಹಿಸುವವರು", - "download_attachment_failed_toast": "ಲಗತ್ತನ್ನು ಡೌನ್‌ಲೋಡ್ ಮಾಡಲು ವಿಫಲವಾಗಿದೆ", - "log_header_format": "{username} ({type}) - {date}" - }, - "file_imports": { - "import_file_button": "ಫೈಲ್ ಆಮದು ಮಾಡಿ", - "file_not_found": "ಫೈಲ್ ಕಂಡುಬಂದಿಲ್ಲ", - "file_import_failed": "ಫೈಲ್ ಆಮದು ಮಾಡಲು ವಿಫಲವಾಗಿದೆ: {error}", - "file_imported": "ಫೈಲ್ ಯಶಸ್ವಿಯಾಗಿ ಆಮದು ಮಾಡಲಾಗಿದೆ", - "file_delete_failed": "ಫೈಲ್ ಅಳಿಸಲು ವಿಫಲವಾಗಿದೆ", - "no_files_hint": "ಇಲ್ಲಿ ನೀವು Snapchat ನಲ್ಲಿ ಬಳಸಲು ಫೈಲ್‌ಗಳನ್ನು ಆಮದು ಮಾಡಬಹುದು. ಫೈಲ್ ಆಮದು ಮಾಡಲು ಕೆಳಗಿನ ಬಟನ್ ಒತ್ತಿರಿ." - }, - "better_location": { - "spoofed_coordinates_title": "ಅಕ್ಷಾಂಶ {latitude}, ರೇಖಾಂಶ {longitude}", - "save_coordinates_dialog_title": "ನಿರ್ದೇಶಾಂಕಗಳನ್ನು ಉಳಿಸಿ", - "saved_name_dialog_hint": "ಉಳಿಸಿದ ಹೆಸರು", - "latitude_dialog_hint": "ಅಕ್ಷಾಂಶ", - "longitude_dialog_hint": "ರೇಖಾಂಶ", - "save_dialog_button": "ಉಳಿಸಿ", - "choose_location_button": "ಸ್ಥಳವನ್ನು ಆಯ್ಕೆಮಾಡಿ", - "teleport_to_friend_button": "ಸ್ನೇಹಿತನಿಗೆ ಟೆಲಿಪೋರ್ಟ್ ಮಾಡಿ", - "spoof_location_toggle": "ಸ್ಥಳವನ್ನು ವಂಚಿಸಿ", - "suspend_location_updates": "ಸ್ಥಳ ನವೀಕರಣಗಳನ್ನು ಸ್ಥಗಿತಗೊಳಿಸಿ", - "saved_coordinates_title": "ಉಳಿಸಿದ ನಿರ್ದೇಶಾಂಕಗಳು", - "no_saved_coordinates_hint": "ಯಾವುದೇ ಉಳಿಸಿದ ನಿರ್ದೇಶಾಂಕಗಳಿಲ್ಲ", - "delete_dialog_title": "ಉಳಿಸಿದ ನಿರ್ದೇಶಾಂಕವನ್ನು ಅಳಿಸಿ", - "delete_dialog_message": "ಈ ಉಳಿಸಿದ ನಿರ್ದೇಶಾಂಕವನ್ನು ಅಳಿಸಲು ನೀವು ಖಚಿತವಾಗಿದ್ದೀರಾ?", - "teleport_to_friend_title": "ಸ್ನೇಹಿತನಿಗೆ ಟೆಲಿಪೋರ್ಟ್ ಮಾಡಿ", - "search_bar": "ಹುಡುಕಿ", - "no_friends_map": "ನಕ್ಷೆಯಲ್ಲಿ ಯಾವುದೇ ಸ್ನೇಹಿತರಿಲ್ಲ", - "no_friends_found": "ಯಾವುದೇ ಸ್ನೇಹಿತರು ಕಂಡುಬಂದಿಲ್ಲ", - "edit_location_button_description": "ಸ್ಥಳವನ್ನು ಸಂಪಾದಿಸಿ", - "add_icon_description": "ಸೇರಿಸಿ", - "edit_icon_description": "ಸಂಪಾದಿಸಿ", - "delete_icon_description": "ಅಳಿಸಿ" - } - }, - "dialogs": { - "add_friend": { - "title": "ಸ್ನೇಹಿತ ಅಥವಾ ಗುಂಪನ್ನು ಸೇರಿಸಿ", - "search_hint": "ಹುಡುಕಿ", - "fetch_error": "ಡೇಟಾವನ್ನು ಪಡೆಯಲು ವಿಫಲವಾಗಿದೆ", - "category_groups": "ಗುಂಪುಗಳು", - "category_friends": "ಸ್ನೇಹಿತರು", - "participants_text": "{count} ಭಾಗವಹಿಸುವವರು", - "search_icon_description": "ಹುಡುಕಿ" - }, - "scripting_warning": { - "title": "ಎಚ್ಚರಿಕೆ", - "content": "PurrfectSnap ಒಂದು ಸ್ಕ್ರಿಪ್ಟಿಂಗ್ ಉಪಕರಣವನ್ನು ಒಳಗೊಂಡಿದೆ, ಇದು ನಿಮ್ಮ ಸಾಧನದಲ್ಲಿ ಬಳಕೆದಾರ-ವ್ಯಾಖ್ಯಾನಿತ ಕೋಡ್ ಅನ್ನು ಕಾರ್ಯಗತಗೊಳಿಸಲು ಅನುವು ಮಾಡಿಕೊಡುತ್ತದೆ. ತೀವ್ರ ಎಚ್ಚರಿಕೆ ವಹಿಸಿ ಮತ್ತು ತಿಳಿದಿರುವ, ವಿಶ್ವಾಸಾರ್ಹ ಮೂಲಗಳಿಂದ ಮಾತ್ರ ಮಾಡ್ಯೂಲ್‌ಗಳನ್ನು ಸ್ಥಾಪಿಸಿ. ಅನಧಿಕೃತ ಅಥವಾ ಪರಿಶೀಲಿಸದ ಮಾಡ್ಯೂಲ್‌ಗಳು ನಿಮ್ಮ ಸಿಸ್ಟಮ್‌ಗೆ ಭದ್ರತಾ ಅಪಾಯಗಳನ್ನು ಉಂಟುಮಾಡಬಹುದು." - }, - "reset_config": { - "title": "ಸಂರಚನೆಯನ್ನು ಮರುಹೊಂದಿಸಿ", - "content": "ಸಂರಚನೆಯನ್ನು ಮರುಹೊಂದಿಸಲು ನೀವು ಖಚಿತವಾಗಿದ್ದೀರಾ?", - "success_toast": "ಸಂರಚನೆಯನ್ನು ಯಶಸ್ವಿಯಾಗಿ ಮರುಹೊಂದಿಸಲಾಗಿದೆ" - }, - "export_config": { - "title": "ಸೂಕ್ಷ್ಮ ಡೇಟಾವನ್ನು ರಫ್ತು ಮಾಡುವುದೇ?", - "content": "ಸೂಕ್ಷ್ಮ ಡೇಟಾದೊಂದಿಗೆ ಸಂರಚನೆಯನ್ನು ರಫ್ತು ಮಾಡಲು ನೀವು ಬಯಸುವಿರಾ? (ಸ್ಥಳ ನಿರ್ದೇಶಾಂಕಗಳು, ಇತ್ಯಾದಿ)" - }, - "messaging_action": { - "title": "ಸಂಸ್ಕರಿಸಲು ವಿಷಯ ಪ್ರಕಾರಗಳನ್ನು ಆಯ್ಕೆಮಾಡಿ", - "select_all_button": "ಎಲ್ಲವನ್ನೂ ಆಯ್ಕೆಮಾಡಿ" - }, - "file_imports": { - "no_files_settings_hint": "ಯಾವುದೇ ಫೈಲ್‌ಗಳು ಕಂಡುಬಂದಿಲ್ಲ. ಫೈಲ್ ಆಮದುಗಳ ವಿಭಾಗದಲ್ಲಿ ಅಗತ್ಯವಿರುವ ಫೈಲ್‌ಗಳನ್ನು ನೀವು ಆಮದು ಮಾಡಿದ್ದೀರಿ ಎಂದು ಖಚಿತಪಡಿಸಿಕೊಳ್ಳಿ", - "settings_select_file_hint": "ಆಮದು ಮಾಡಿದ ಫೈಲ್ ಅನ್ನು ಆಯ್ಕೆಮಾಡಿ" - }, - "quick_actions_dialog": { - "title": "ತ್ವರಿತ ಕ್ರಿಯೆಗಳನ್ನು ಸಂಪಾದಿಸಿ", - "subtitle": "ನಿಮ್ಮ ತ್ವರಿತ ಕ್ರಿಯೆಗಳನ್ನು ಆಯ್ಕೆಮಾಡಿ ಮತ್ತು ಗಾತ್ರವನ್ನು ಬದಲಾಯಿಸಿ." - } - }, - "friend_tracker": { - "rules_tab": "ನಿಯಮಗಳು", - "logs_tab": "ಲಾಗ್‌ಗಳು", - "export_dialog_title": "ರಫ್ತು ಮಾಡಿ", - "bulk_export_button": "ಬೃಹತ್ ರಫ್ತು", - "individual_export_button": "ವೈಯಕ್ತಿಕ ರಫ್ತು", - "invalid_import_type_dialog_title": "ಅಮಾನ್ಯ ಆಮದು ಪ್ರಕಾರ", - "invalid_import_type_dialog_text": "ಆಯ್ದ ಫೈಲ್ ಈ ಆಮದು ಪ್ರಕಾರಕ್ಕೆ ಹೊಂದಿಕೆಯಾಗುವುದಿಲ್ಲ. ದಯವಿಟ್ಟು ಸರಿಯಾದ ಆಮದು ಪ್ರಕಾರವನ್ನು ಆಯ್ಕೆಮಾಡಿ.", - "import_dialog_title": "ಆಮದು ಮಾಡಿ", - "bulk_import_button": "ಬೃಹತ್ ಆಮದು", - "individual_import_button": "ವೈಯಕ್ತಿಕ ಆಮದು", - "import_button_description": "ಆಮದು ಮಾಡಿ", - "export_button_description": "ರಫ್ತು ಮಾಡಿ", - "export_button": "ರಫ್ತು ಮಾಡಿ", - "delete_button_description": "ಅಳಿಸಿ", - "delete_button": "ಅಳಿಸಿ", - "catalog_button_description": "ಕ್ಯಾಟಲಾಗ್", - "catalog_button": "ಕ್ಯಾಟಲಾಗ್", - "add_rule_button_description": "ನಿಯಮವನ್ನು ಸೇರಿಸಿ", - "add_rule_button": "ನಿಯಮವನ್ನು ಸೇರಿಸಿ", - "no_rules_found": "ಯಾವುದೇ ನಿಯಮಗಳು ಕಂಡುಬಂದಿಲ್ಲ", - "empty_rule_name": "(ಖಾಲಿ)", - "events_suffix": "ಘಟನೆಗಳು", - "scopes_suffix": "ವ್ಯಾಪ್ತಿಗಳು", - "select_rule_to_export_title": "ರಫ್ತು ಮಾಡಲು ನಿಯಮವನ್ನು ಆಯ್ಕೆಮಾಡಿ", - "deleted_logs_toast": "{count} ಲಾಗ್‌ಗಳನ್ನು ಅಳಿಸಲಾಗಿದೆ", - "delete_logs_dialog_title": "ಲಾಗ್‌ಗಳನ್ನು ಅಳಿಸುವುದೇ?", - "deleting_logs_dialog_text": "{count} ಲಾಗ್‌ಗಳನ್ನು ಅಳಿಸಲಾಗುತ್ತಿದೆ...", - "delete_logs_dialog_confirm_text": "ಇದು ಪ್ರಸ್ತುತ ಫಿಲ್ಟರ್ ಮತ್ತು ಹುಡುಕಾಟ ಪ್ರಶ್ನೆಯ ಆಧಾರದ ಮೇಲೆ ಲಾಗ್‌ಗಳನ್ನು ಅಳಿಸುತ್ತದೆ. ಈ ಕ್ರಿಯೆಯನ್ನು ರದ್ದುಗೊಳಿಸಲಾಗುವುದಿಲ್ಲ.", - "exported_logs_toast": "ಲಾಗ್‌ಗಳನ್ನು ರಫ್ತು ಮಾಡಲಾಗಿದೆ!", - "export_logs_failed_toast": "ಲಾಗ್‌ಗಳನ್ನು ರಫ್ತು ಮಾಡಲು ವಿಫಲವಾಗಿದೆ. ಹೆಚ್ಚಿನ ವಿವರಗಳಿಗಾಗಿ ಲಾಗ್‌ಕ್ಯಾಟ್ ಪರಿಶೀಲಿಸಿ.", - "export_logs_dialog_title": "ಲಾಗ್‌ಗಳನ್ನು ರಫ್ತು ಮಾಡುವುದೇ?", - "exporting_logs_dialog_text": "ಲಾಗ್‌ಗಳನ್ನು ರಫ್ತು ಮಾಡಲಾಗುತ್ತಿದೆ...", - "export_logs_dialog_confirm_text": "ಇದು ಪ್ರಸ್ತುತ ಫಿಲ್ಟರ್ ಮತ್ತು ಹುಡುಕಾಟ ಪ್ರಶ್ನೆಯ ಆಧಾರದ ಮೇಲೆ ಲಾಗ್‌ಗಳನ್ನು ರಫ್ತು ಮಾಡುತ್ತದೆ.", - "export_as_button": "{type} ಆಗಿ ರಫ್ತು ಮಾಡಿ", - "filters_title": "ಫಿಲ್ಟರ್‌ಗಳು", - "search_by_label": "ಹುಡುಕಾಟ", - "newest_first_label": "ಹೊಸದು ಮೊದಲು", - "since_label": "ನಂತರ", - "until_label": "ತನಕ", - "pick_a_date_button": "ದಿನಾಂಕವನ್ನು ಆರಿಸಿ", - "search_placeholder": "ಹುಡುಕಿ", - "filter_button_description": "ಫಿಲ್ಟರ್", - "clear_button_description": "ತೆರವುಗೊಳಿಸಿ", - "no_logs_found": "ಯಾವುದೇ ಲಾಗ್‌ಗಳು ಕಂಡುಬಂದಿಲ್ಲ", - "log_event_format": "{conversation} ನಲ್ಲಿ {event}", - "condition_only_inside_conversation": "ನಾನು ಸಂಭಾಷಣೆಯಲ್ಲಿದ್ದಾಗ ಮಾತ್ರ", - "condition_only_outside_conversation": "ನಾನು ಸಂಭಾಷಣೆಯ ಹೊರಗಿದ್ದಾಗ ಮಾತ್ರ", - "condition_only_when_app_active": "Snapchat ಸಕ್ರಿಯವಾಗಿದ್ದಾಗ ಮಾತ್ರ", - "condition_only_when_app_inactive": "Snapchat ನಿಷ್ಕ್ರಿಯವಾಗಿದ್ದಾಗ ಮಾತ್ರ", - "condition_no_push_notification_when_app_active": "Snapchat ಸಕ್ರಿಯವಾಗಿದ್ದಾಗ ಯಾವುದೇ ಪುಶ್ ಅಧಿಸೂಚನೆ ಇಲ್ಲ", - "add_event_dialog_title": "ಘಟನೆಯನ್ನು ಸೇರಿಸಿ", - "event_type_label": "ಘಟನೆಯ ಪ್ರಕಾರ", - "triggers_title": "ಪ್ರಚೋದಕಗಳು", - "conditions_title": "ಷರತ್ತುಗಳು", - "add_button": "ಸೇರಿಸಿ", - "default_rule_name": "ಕಸ್ಟಮ್ ನಿಯಮ", - "discard_changes_dialog_title": "ಬದಲಾವಣೆಗಳನ್ನು ತಿರಸ್ಕರಿಸುವುದೇ?", - "discard_changes_dialog_text": "ನೀವು ಉಳಿಸದ ಬದಲಾವಣೆಗಳನ್ನು ಹೊಂದಿದ್ದೀರಿ. ನೀವು ಅವುಗಳನ್ನು ತಿರಸ್ಕರಿಸಲು ಖಚಿತವಾಗಿದ್ದೀರಾ?", - "discard_button": "ತಿರಸ್ಕರಿಸಿ", - "cannot_save_rule_dialog_title": "ನಿಯಮವನ್ನು ಉಳಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ", - "cannot_save_rule_dialog_text": "ಉಳಿಸಲು ನಿಯಮವು ಕನಿಷ್ಠ ಒಂದು ಘಟನೆಯನ್ನು ಹೊಂದಿರಬೇಕು.", - "duplicate_rule_name_dialog_title": "ನಕಲಿ ನಿಯಮದ ಹೆಸರು", - "duplicate_rule_name_dialog_text": "ಈ ಹೆಸರಿನ ನಿಯಮವು ಈಗಾಗಲೇ ಅಸ್ತಿತ್ವದಲ್ಲಿದೆ. ದಯವಿಟ್ಟು ಬೇರೆ ಹೆಸರನ್ನು ಆಯ್ಕೆಮಾಡಿ.", - "delete_rule_dialog_title": "ನಿಯಮವನ್ನು ಅಳಿಸಿ", - "delete_rule_dialog_text": "ಈ ನಿಯಮವನ್ನು ಅಳಿಸಲು ನೀವು ಖಚಿತವಾಗಿದ್ದೀರಾ?", - "new_rule_title": "ಹೊಸ ನಿಯಮ", - "edit_rule_title": "ನಿಯಮವನ್ನು ಸಂಪಾದಿಸಿ", - "back_button_description": "ಹಿಂದೆ", - "save_button_description": "ಉಳಿಸಿ", - "general_section_title": "ಸಾಮಾನ್ಯ", - "rule_name_label": "ನಿಯಮದ ಹೆಸರು", - "author_name_label": "ಲೇಖಕರ ಹೆಸರು", - "scope_section_title": "ವ್ಯಾಪ್ತಿ", - "scope_all": "ಎಲ್ಲಾ", - "scope_whitelist": "ಶ್ವೇತಪಟ್ಟಿ", - "scope_blacklist": "ಕಪ್ಪುಪಟ್ಟಿ", - "select_friends_groups_button": "ಸ್ನೇಹಿತರು/ಗುಂಪುಗಳನ್ನು ಆಯ್ಕೆಮಾಡಿ ({count})", - "events_section_title": "ಘಟನೆಗಳು", - "add_event_button": "ಘಟನೆಯನ್ನು ಸೇರಿಸಿ", - "no_events_text": "ಯಾವುದೇ ಘಟನೆಗಳಿಲ್ಲ" - }, - "friend_tracker_catalog": { - "download_failed": "ಡೌನ್‌ಲೋಡ್ ವಿಫಲವಾಗಿದೆ: {code}", - "error": "ದೋಷ: {message}", - "no_repos_added": "ಯಾವುದೇ ರೆಪೊಸಿಟರಿಗಳನ್ನು ಸೇರಿಸಲಾಗಿಲ್ಲ.", - "no_rules_available": "ಯಾವುದೇ ರೆಪೊದಿಂದ ಯಾವುದೇ ನಿಯಮಗಳು ಲಭ್ಯವಿಲ್ಲ.", - "by_author": "{author} ಅವರಿಂದ", - "imported_button": "ಆಮದು ಮಾಡಲಾಗಿದೆ", - "import_button": "ಆಮದು ಮಾಡಿ", - "title": "ಸ್ನೇಹಿತ ಟ್ರ್ಯಾಕರ್ ಕ್ಯಾಟಲಾಗ್", - "manage_repos_description": "ರೆಪೊಸಿಟರಿಗಳನ್ನು ನಿರ್ವಹಿಸಿ" - }, - "friend_tracker_export": { - "title": "ನಿಯಮಗಳನ್ನು ರಫ್ತು ಮಾಡಿ", - "back_button_description": "ಹಿಂದೆ", - "exported_toast": "ಸ್ನೇಹಿತ ಟ್ರ್ಯಾಕರ್ ನಿಯಮಗಳನ್ನು ರಫ್ತು ಮಾಡಲಾಗಿದೆ!", - "export_failed_toast": "ನಿಯಮಗಳನ್ನು ರಫ್ತು ಮಾಡಲು ವಿಫಲವಾಗಿದೆ: {message}", - "save_button": "ಉಳಿಸಿ", - "expand_button_description": "ವಿಸ್ತರಿಸಿ" - }, - "friend_tracker_import": { - "title": "ನಿಯಮಗಳನ್ನು ಆಮದು ಮಾಡಿ", - "back_button_description": "ಹಿಂದೆ", - "imported_toast": "ಸ್ನೇಹಿತ ಟ್ರ್ಯಾಕರ್ ನಿಯಮಗಳನ್ನು ಆಮದು ಮಾಡಲಾಗಿದೆ!", - "import_failed_toast": "ನಿಯಮಗಳನ್ನು ಆಮದು ಮಾಡಲು ವಿಫಲವಾಗಿದೆ: {message}", - "confirm_button": "ದೃಢೀಕರಿಸಿ", - "expand_button_description": "ವಿಸ್ತರಿಸಿ" - }, - "friend_tracker_repos": { - "invalid_repo_title": "ಅಮಾನ್ಯ ರೆಪೊಸಿಟರಿ", - "add_repo_button": "ರೆಪೊಸಿಟರಿ ಸೇರಿಸಿ", - "add_repo_dialog_title": "ರೆಪೊಸಿಟರಿ URL ಸೇರಿಸಿ", - "repo_url_label": "ರೆಪೊಸಿಟರಿ URL", - "repo_added_toast": "ರೆಪೊಸಿಟರಿಯನ್ನು ಯಶಸ್ವಿಯಾಗಿ ಸೇರಿಸಲಾಗಿದೆ!", - "invalid_repo_error": "ಇದು ಮಾನ್ಯವಾದ ಸ್ನೇಹಿತ ಟ್ರ್ಯಾಕರ್ ರೆಪೊಸಿಟರಿಯಾಗಿ ಕಂಡುಬರುವುದಿಲ್ಲ.", - "add_repo_failed_toast": "ರೆಪೊಸಿಟರಿಯನ್ನು ಸೇರಿಸಲು ವಿಫಲವಾಗಿದೆ: {message}", - "add_button": "ಸೇರಿಸಿ", - "no_repos_added": "ಯಾವುದೇ ರೆಪೊಸಿಟರಿಗಳನ್ನು ಸೇರಿಸಲಾಗಿಲ್ಲ", - "remove_button": "ತೆಗೆದುಹಾಕಿ", - "remove_repo_dialog_title": "ರೆಪೊಸಿಟರಿಯನ್ನು ತೆಗೆದುಹಾಕಿ", - "remove_repo_dialog_text": "ಈ ರೆಪೊಸಿಟರಿಯನ್ನು ತೆಗೆದುಹಾಕಲು ನೀವು ಖಚಿತವಾಗಿದ್ದೀರಾ?" - }, - "navigation": { - "tracker_tab_label": "ಟ್ರ್ಯಾಕರ್", - "customize_bottom_bar_title": "ಕೆಳಗಿನ ಪಟ್ಟಿಯನ್ನು ಕಸ್ಟಮೈಸ್ ಮಾಡಿ", - "customize_bottom_bar_subtitle": "ಟ್ಯಾಬ್‌ಗಳನ್ನು ಮರುಹೊಂದಿಸಿ, ಸೇರಿಸಿ ಅಥವಾ ತೆಗೆದುಹಾಕಿ. ಗರಿಷ್ಠ ಐದು.", - "shown_tabs_title": "ತೋರಿಸಿದ ಟ್ಯಾಬ್‌ಗಳು", - "no_tabs_selected_text": "ಯಾವುದೇ ಟ್ಯಾಬ್‌ಗಳನ್ನು ಆಯ್ಕೆ ಮಾಡಲಾಗಿಲ್ಲ", - "available_tabs_title": "ಲಭ್ಯವಿರುವ ಟ್ಯಾಬ್‌ಗಳು", - "reset_button": "ಮರುಹೊಂದಿಸಿ", - "done_button": "ಮುಗಿದಿದೆ" - }, - "scripting": { - "script_already_installed": "ಸ್ಕ್ರಿಪ್ಟ್ ಈಗಾಗಲೇ ಸ್ಥಾಪಿಸಲಾಗಿದೆ!", - "downloading_script": "ಸ್ಕ್ರಿಪ್ಟ್ ಡೌನ್‌ಲೋಡ್ ಆಗುತ್ತಿದೆ...", - "script_downloaded": "{name} ಸ್ಕ್ರಿಪ್ಟ್ ಡೌನ್‌ಲೋಡ್ ಆಗಿದೆ!", - "download_script_failed": "ಸ್ಕ್ರಿಪ್ಟ್ ಡೌನ್‌ಲೋಡ್ ಮಾಡಲು ವಿಫಲವಾಗಿದೆ. ಹೆಚ್ಚಿನ ವಿವರಗಳಿಗಾಗಿ ಲಾಗ್‌ಗಳನ್ನು ಪರಿಶೀಲಿಸಿ", - "import_script_from_url_title": "URL ನಿಂದ ಸ್ಕ್ರಿಪ್ಟ್ ಆಮದು ಮಾಡಿ", - "import_script_warning": "ಎಚ್ಚರಿಕೆ: ಆಮದು ಮಾಡಿದ ಸ್ಕ್ರಿಪ್ಟ್‌ಗಳು ನಿಮ್ಮ ಸಾಧನಕ್ಕೆ ಹಾನಿಕಾರಕವಾಗಬಹುದು. ವಿಶ್ವಾಸಾರ್ಹ ಮೂಲಗಳಿಂದ ಮಾತ್ರ ಸ್ಕ್ರಿಪ್ಟ್‌ಗಳನ್ನು ಆಮದು ಮಾಡಿ.", - "enter_url_label": "ಇಲ್ಲಿ URL ನಮೂದಿಸಿ:", - "script_imported": "{name} ಸ್ಕ್ರಿಪ್ಟ್ ಆಮದು ಮಾಡಲಾಗಿದೆ!", - "import_failed": "ಸ್ಕ್ರಿಪ್ಟ್ ಆಮದು ಮಾಡಲು ವಿಫಲವಾಗಿದೆ. {message}. ಹೆಚ್ಚಿನ ವಿವರಗಳಿಗಾಗಿ ಲಾಗ್‌ಗಳನ್ನು ಪರಿಶೀಲಿಸಿ", - "import_button": "ಆಮದು ಮಾಡಿ", - "update_module_button": "ಮಾಡ್ಯೂಲ್ ನವೀಕರಿಸಿ", - "updating_script": "{name} ಸ್ಕ್ರಿಪ್ಟ್ ನವೀಕರಿಸಲಾಗುತ್ತಿದೆ...", - "module_not_found": "ಮಾಡ್ಯೂಲ್ ಕಂಡುಬಂದಿಲ್ಲ", - "updated_script": "{name} ಅನ್ನು ಆವೃತ್ತಿ {version} ಗೆ ನವೀಕರಿಸಲಾಗಿದೆ", - "update_module_failed": "ಮಾಡ್ಯೂಲ್ ನವೀಕರಿಸಲು ವಿಫಲವಾಗಿದೆ. ಹೆಚ್ಚಿನ ವಿವರಗಳಿಗಾಗಿ ಲಾಗ್‌ಗಳನ್ನು ಪರಿಶೀಲಿಸಿ", - "edit_module_button": "ಮಾಡ್ಯೂಲ್ ಸಂಪಾದಿಸಿ", - "open_module_failed": "ಮಾಡ್ಯೂಲ್ ಫೈಲ್ ತೆರೆಯಲು ವಿಫಲವಾಗಿದೆ. ಹೆಚ್ಚಿನ ವಿವರಗಳಿಗಾಗಿ ಲಾಗ್‌ಗಳನ್ನು ಪರಿಶೀಲಿಸಿ", - "clear_module_data_button": "ಮಾಡ್ಯೂಲ್ ಡೇಟಾವನ್ನು ತೆರವುಗೊಳಿಸಿ", - "module_data_cleared": "ಮಾಡ್ಯೂಲ್ ಡೇಟಾವನ್ನು ತೆರವುಗೊಳಿಸಲಾಗಿದೆ!", - "clear_module_data_failed": "ಮಾಡ್ಯೂಲ್ ಡೇಟಾವನ್ನು ತೆರವುಗೊಳಿಸಲು ವಿಫಲವಾಗಿದೆ. ಹೆಚ್ಚಿನ ವಿವರಗಳಿಗಾಗಿ ಲಾಗ್‌ಗಳನ್ನು ಪರಿಶೀಲಿಸಿ", - "delete_module_button": "ಮಾಡ್ಯೂಲ್ ಅಳಿಸಿ", - "deleted_script": "{name} ಸ್ಕ್ರಿಪ್ಟ್ ಅಳಿಸಲಾಗಿದೆ!", - "delete_module_failed": "ಮಾಡ್ಯೂಲ್ ಅಳಿಸಲು ವಿಫಲವಾಗಿದೆ. ಹೆಚ್ಚಿನ ವಿವರಗಳಿಗಾಗಿ ಲಾಗ್‌ಗಳನ್ನು ಪರಿಶೀಲಿಸಿ", - "actions_title": "ಕ್ರಿಯೆಗಳು", - "no_description": "ಯಾವುದೇ ವಿವರಣೆಯಿಲ್ಲ", - "update_available": "ನವೀಕರಣ ಲಭ್ಯವಿದೆ: {version}", - "actions_button": "ಕ್ರಿಯೆಗಳು", - "loaded_script": "{name} ಸ್ಕ್ರಿಪ್ಟ್ ಲೋಡ್ ಮಾಡಲಾಗಿದೆ", - "unloaded_script": "{name} ಸ್ಕ್ರಿಪ್ಟ್ ಅನ್‌ಲೋಡ್ ಮಾಡಲಾಗಿದೆ", - "enable_script_failed": "ಸ್ಕ್ರಿಪ್ಟ್ ಸಕ್ರಿಯಗೊಳಿಸಲು ವಿಫಲವಾಗಿದೆ. ಹೆಚ್ಚಿನ ವಿವರಗಳಿಗಾಗಿ ಲಾಗ್‌ಗಳನ್ನು ಪರಿಶೀಲಿಸಿ", - "disable_script_failed": "ಸ್ಕ್ರಿಪ್ಟ್ ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲು ವಿಫಲವಾಗಿದೆ. ಹೆಚ್ಚಿನ ವಿವರಗಳಿಗಾಗಿ ಲಾಗ್‌ಗಳನ್ನು ಪರಿಶೀಲಿಸಿ", - "select_scripts_folder_toast": "ದಯವಿಟ್ಟು ನಿಮ್ಮ ಸ್ಕ್ರಿಪ್ಟ್‌ಗಳ ಫೋಲ್ಡರ್ ಅನ್ನು ಆಯ್ಕೆಮಾಡಿ!", - "manage_repos_button": "ರೆಪೊಸಿಟರಿಗಳನ್ನು ನಿರ್ವಹಿಸಿ", - "import_from_url_button": "URL ನಿಂದ ಆಮದು ಮಾಡಿ", - "open_scripts_folder_button": "ಸ್ಕ್ರಿಪ್ಟ್‌ಗಳ ಫೋಲ್ಡರ್ ತೆರೆಯಿರಿ", - "no_settings_for_module": "ಈ ಮಾಡ್ಯೂಲ್‌ಗೆ ಯಾವುದೇ ಸೆಟ್ಟಿಂಗ್‌ಗಳಿಲ್ಲ", - "installed_scripts_tab": "ಸ್ಥಾಪಿಸಲಾದ ಸ್ಕ್ರಿಪ್ಟ್‌ಗಳು", - "catalog_tab": "ಕ್ಯಾಟಲಾಗ್", - "no_scripts_folder_selected_title": "ಯಾವುದೇ ಸ್ಕ್ರಿಪ್ಟ್‌ಗಳ ಫೋಲ್ಡರ್ ಆಯ್ಕೆ ಮಾಡಲಾಗಿಲ್ಲ", - "select_folder_button": "ಫೋಲ್ಡರ್ ಆಯ್ಕೆಮಾಡಿ", - "no_scripts_found_title": "ಯಾವುದೇ ಸ್ಕ್ರಿಪ್ಟ್‌ಗಳು ಕಂಡುಬಂದಿಲ್ಲ.", - "use_catalog_to_add_scripts": "ಸ್ಕ್ರಿಪ್ಟ್‌ಗಳನ್ನು ಸೇರಿಸಲು ಕ್ಯಾಟಲಾಗ್ ಟ್ಯಾಬ್ ಬಳಸಿ!", - "ok_button_timeout": "ಸರಿ ({timeout})", - "documentation_button": "ದಾಖಲೆ", - "catalog": { - "script_already_installed": "ಸ್ಕ್ರಿಪ್ಟ್ ಈಗಾಗಲೇ ಸ್ಥಾಪಿಸಲಾಗಿದೆ!", - "download_failed": "ಡೌನ್‌ಲೋಡ್ ವಿಫಲವಾಗಿದೆ: {code}", - "script_downloaded": "ಸ್ಕ್ರಿಪ್ಟ್ ಡೌನ್‌ಲೋಡ್ ಆಗಿದೆ!", - "could_not_create_file": "ಫೈಲ್ ರಚಿಸಲು ಸಾಧ್ಯವಾಗಲಿಲ್ಲ.", - "no_scripts_folder_selected": "ಯಾವುದೇ ಸ್ಕ್ರಿಪ್ಟ್‌ಗಳ ಫೋಲ್ಡರ್ ಆಯ್ಕೆ ಮಾಡಲಾಗಿಲ್ಲ.", - "error": "ದೋಷ: {message}", - "no_repos_added": "ಯಾವುದೇ ರೆಪೊಸಿಟರಿಗಳನ್ನು ಸೇರಿಸಲಾಗಿಲ್ಲ.", - "repo_list_info": "ಇಲ್ಲಿ ನೀವು ರೆಪೊಗಳ ಪಟ್ಟಿಯನ್ನು ಕಾಣಬಹುದು: ", - "link_text": "ಲಿಂಕ್", - "no_scripts_available": "ಯಾವುದೇ ರೆಪೊದಿಂದ ಯಾವುದೇ ಸ್ಕ್ರಿಪ್ಟ್‌ಗಳು ಲಭ್ಯವಿಲ್ಲ.", - "by_author": "{author} ಅವರಿಂದ", - "version": "ಆವೃತ್ತಿ: {version}", - "installed_button": "ಸ್ಥಾಪಿಸಲಾಗಿದೆ", - "download_button": "ಡೌನ್‌ಲೋಡ್ ಮಾಡಿ" - }, - "repos": { - "invalid_repo_title": "ಅಮಾನ್ಯ ರೆಪೊಸಿಟರಿ", - "add_repo_button": "ರೆಪೊಸಿಟರಿ ಸೇರಿಸಿ", - "add_repo_dialog_title": "ರೆಪೊಸಿಟರಿ URL ಸೇರಿಸಿ", - "repo_url_label": "ರೆಪೊಸಿಟರಿ URL", - "repo_added_toast": "ರೆಪೊಸಿಟರಿಯನ್ನು ಯಶಸ್ವಿಯಾಗಿ ಸೇರಿಸಲಾಗಿದೆ!", - "invalid_repo_error": "ಇದು ಮಾನ್ಯವಾದ ಸ್ಕ್ರಿಪ್ಟ್ ರೆಪೊಸಿಟರಿಯಾಗಿ ಕಂಡುಬರುವುದಿಲ್ಲ.", - "add_repo_failed_toast": "ರೆಪೊಸಿಟರಿಯನ್ನು ಸೇರಿಸಲು ವಿಫಲವಾಗಿದೆ: {message}", - "add_button": "ಸೇರಿಸಿ", - "no_repos_added": "ಯಾವುದೇ ರೆಪೊಸಿಟರಿಗಳನ್ನು ಸೇರಿಸಲಾಗಿಲ್ಲ", - "remove_button": "ತೆಗೆದುಹಾಕಿ", - "remove_repo_dialog_title": "ರೆಪೊಸಿಟರಿಯನ್ನು ತೆಗೆದುಹಾಕಿ", - "remove_repo_dialog_text": "ಈ ರೆಪೊಸಿಟರಿಯನ್ನು ತೆಗೆದುಹಾಕಲು ನೀವು ಖಚಿತವಾಗಿದ್ದೀರಾ?" - } - }, - "features": { - "config_import": { - "title": "ಆಮದು ದೃಢೀಕರಿಸಿ", - "back_button_description": "ಹಿಂದೆ", - "config_imported_toast": "ಸಂರಚನೆಯನ್ನು ಆಮದು ಮಾಡಲಾಗಿದೆ!", - "confirm_button": "ದೃಢೀಕರಿಸಿ", - "expand_button_description": "ವಿಸ್ತರಿಸಿ", - "enable_feature": "ವೈಶಿಷ್ಟ್ಯವನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಿ", - "enabled": "ಸಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ", - "disabled": "ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ" - }, - "config_export": { - "title": "ರಫ್ತು ಸಾರಾಂಶ", - "back_button_description": "ಹಿಂದೆ", - "save_button": "ಉಳಿಸಿ", - "expand_button_description": "ವಿಸ್ತರಿಸಿ", - "enable_feature": "ವೈಶಿಷ್ಟ್ಯವನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಿ", - "enabled": "ಸಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ", - "disabled": "ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ" - } - }, - "manage_repos": { - "title": "{type} ರೆಪೊಸಿಟರಿಗಳನ್ನು ನಿರ್ವಹಿಸಿ", - "add_repo_button": "ರೆಪೊಸಿಟರಿ ಸೇರಿಸಿ", - "add_repo_dialog_title": "ರೆಪೊಸಿಟರಿ URL ಸೇರಿಸಿ", - "repo_url_label": "ರೆಪೊಸಿಟರಿ URL", - "repo_added_successfully": "ರೆಪೊಸಿಟರಿಯನ್ನು ಯಶಸ್ವಿಯಾಗಿ ಸೇರಿಸಲಾಗಿದೆ!", - "add_repo_failed": "ರೆಪೊಸಿಟರಿಯನ್ನು ಸೇರಿಸಲು ವಿಫಲವಾಗಿದೆ: {message}", - "add_button": "ಸೇರಿಸಿ", - "no_repos_added": "ಯಾವುದೇ ರೆಪೊಸಿಟರಿಗಳನ್ನು ಸೇರಿಸಲಾಗಿಲ್ಲ", - "remove_button": "ತೆಗೆದುಹಾಕಿ" - } - }, - "rules": { - "toasts": { - "enabled": "{ruleName} ಸಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ", - "disabled": "{ruleName} ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ" - }, - "modes": { - "blacklist": "ಕಪ್ಪುಪಟ್ಟಿ ಮೋಡ್", - "whitelist": "ಶ್ವೇತಪಟ್ಟಿ ಮೋಡ್" - }, - "properties": { - "auto_download": { - "name": "ಸ್ವಯಂ ಡೌನ್‌ಲೋಡ್", - "description": "ಸ್ನ್ಯಾಪ್‌ಗಳನ್ನು ವೀಕ್ಷಿಸುವಾಗ ಸ್ವಯಂಚಾಲಿತವಾಗಿ ಡೌನ್‌ಲೋಡ್ ಮಾಡಿ", - "options": { - "blacklist": "ಸ್ವಯಂ ಡೌನ್‌ಲೋಡ್‌ನಿಂದ ಹೊರತುಪಡಿಸಿ", - "whitelist": "ಸ್ವಯಂ ಡೌನ್‌ಲೋಡ್" - } - }, - "stealth": { - "name": "ಸ್ಟೆಲ್ತ್ ಮೋಡ್", - "description": "ನೀವು ಅವರ ಸ್ನ್ಯಾಪ್‌ಗಳು/ಚಾಟ್‌ಗಳು ಮತ್ತು ಸಂಭಾಷಣೆಗಳನ್ನು ತೆರೆದಿದ್ದೀರಿ ಎಂದು ಯಾರಿಗೂ ತಿಳಿಯದಂತೆ ತಡೆಯುತ್ತದೆ", - "options": { - "blacklist": "ಸ್ಟೆಲ್ತ್ ಮೋಡ್‌ನಿಂದ ಹೊರತುಪಡಿಸಿ", - "whitelist": "ಸ್ಟೆಲ್ತ್ ಮೋಡ್" - } - }, - "auto_save": { - "name": "ಸ್ವಯಂ ಉಳಿಸು", - "description": "ಚಾಟ್ ಸಂದೇಶಗಳನ್ನು ವೀಕ್ಷಿಸುವಾಗ ಉಳಿಸುತ್ತದೆ", - "options": { - "blacklist": "ಸ್ವಯಂ ಉಳಿಸುದಿಂದ ಹೊರತುಪಡಿಸಿ", - "whitelist": "ಸ್ವಯಂ ಉಳಿಸು" - } - }, - "unsaveable_messages": { - "name": "ಉಳಿಸಲಾಗದ ಸಂದೇಶಗಳು", - "description": "ಇತರ ಜನರು ಚಾಟ್‌ನಲ್ಲಿ ಸಂದೇಶಗಳನ್ನು ಉಳಿಸುವುದನ್ನು ತಡೆಯುತ್ತದೆ", - "options": { - "blacklist": "ಉಳಿಸಲಾಗದ ಸಂದೇಶಗಳಿಂದ ಹೊರತುಪಡಿಸಿ", - "whitelist": "ಉಳಿಸಲಾಗದ ಸಂದೇಶಗಳು" - } - }, - "auto_open_snaps": { - "name": "ಸ್ನ್ಯಾಪ್‌ಗಳನ್ನು ಸ್ವಯಂ ತೆರೆಯಿರಿ", - "description": "ಸ್ನ್ಯಾಪ್‌ಗಳನ್ನು ಸ್ವೀಕರಿಸುವಾಗ ಸ್ವಯಂಚಾಲಿತವಾಗಿ ತೆರೆಯುತ್ತದೆ", - "options": { - "blacklist": "ಸ್ನ್ಯಾಪ್‌ಗಳನ್ನು ಸ್ವಯಂ ತೆರೆಯುವುದರಿಂದ ಹೊರತುಪಡಿಸಿ", - "whitelist": "ಸ್ನ್ಯಾಪ್‌ಗಳನ್ನು ಸ್ವಯಂ ತೆರೆಯಿರಿ" - } - }, - "hide_friend_feed": { - "name": "ಸ್ನೇಹಿತರ ಫೀಡ್‌ನಿಂದ ಮರೆಮಾಡಿ" - }, - "e2e_encryption": { - "name": "E2E ಎನ್‌ಕ್ರಿಪ್ಶನ್ ಬಳಸಿ" - }, - "pin_conversation": { - "name": "ಸಂಭಾಷಣೆಯನ್ನು ಪಿನ್ ಮಾಡಿ" - }, - "exclude_message_logger": { - "name": "ಸಂದೇಶ ಲಾಗರ್‌ನಿಂದ ಹೊರತುಪಡಿಸಿ" - } - } - }, - "actions": { - "clean_snapchat_cache": { - "name": "Snapchat ಸಂಗ್ರಹವನ್ನು ಸ್ವಚ್ಛಗೊಳಿಸಿ", - "description": "Snapchat ಸಂಗ್ರಹವನ್ನು ಸ್ವಚ್ಛಗೊಳಿಸುತ್ತದೆ" - }, - "manage_friend_list": { - "name": "ಸ್ನೇಹಿತರ ಪಟ್ಟಿಯನ್ನು ನಿರ್ವಹಿಸಿ", - "description": "ಬ್ಯಾಕಪ್ ಮಾಡುವಾಗ ನಿಮ್ಮ ಸ್ನೇಹಿತರ ಪಟ್ಟಿಯನ್ನು ಆಮದು/ರಫ್ತು ಮಾಡಿ" - }, - "export_chat_messages": { - "name": "ಚಾಟ್ ಸಂದೇಶಗಳನ್ನು ರಫ್ತು ಮಾಡಿ", - "description": "ಸಂಭಾಷಣೆಯ ಸಂದೇಶಗಳನ್ನು JSON/HTML/TXT ಫೈಲ್‌ಗೆ ರಫ್ತು ಮಾಡುತ್ತದೆ" - }, - "export_memories": { - "name": "ನೆನಪುಗಳನ್ನು ರಫ್ತು ಮಾಡಿ", - "description": "ನೆನಪುಗಳನ್ನು ZIP ಫೈಲ್‌ಗೆ ರಫ್ತು ಮಾಡುತ್ತದೆ" - }, - "bulk_messaging_action": { - "name": "ಬೃಹತ್ ಸಂದೇಶ ಕಳುಹಿಸುವ ಕ್ರಿಯೆ", - "description": "ಸ್ನೇಹಿತರನ್ನು ಅಳಿಸುವುದು ಅಥವಾ ಸಂಭಾಷಣೆಗಳನ್ನು ಬೃಹತ್ ಪ್ರಮಾಣದಲ್ಲಿ ಅಳಿಸುವಂತಹ ಕಾರ್ಯಾಚರಣೆಗಳನ್ನು ನಿರ್ವಹಿಸುತ್ತದೆ" - }, - "regen_mappings": { - "name": "ಮ್ಯಾಪಿಂಗ್‌ಗಳನ್ನು ಪುನರುತ್ಪಾದಿಸಿ", - "description": "ಮ್ಯಾಪಿಂಗ್‌ಗಳನ್ನು ಹಸ್ತಚಾಲಿತವಾಗಿ ಪುನರುತ್ಪಾದಿಸಿ" - }, - "change_language": { - "name": "ಭಾಷೆಯನ್ನು ಬದಲಾಯಿಸಿ", - "description": "PurrfectSnap ನ ಭಾಷೆಯನ್ನು ಬದಲಾಯಿಸಿ" - }, - "file_imports": { - "name": "ಫೈಲ್ ಆಮದುಗಳು", - "description": "Snapchat ನಲ್ಲಿ ಬಳಸಲು ಫೈಲ್‌ಗಳನ್ನು ಆಮದು ಮಾಡಿ" - }, - "friend_tracker": { - "name": "ಸ್ನೇಹಿತ ಟ್ರ್ಯಾಕರ್", - "description": "Snapchat ನಲ್ಲಿ ನಿಮ್ಮ ಸ್ನೇಹಿತರನ್ನು ಟ್ರ್ಯಾಕ್ ಮಾಡಿ" - }, - "logger_history": { - "name": "ಲಾಗರ್ ಇತಿಹಾಸ", - "description": "ಲಾಗ್ ಮಾಡಿದ ಸಂದೇಶಗಳ ಇತಿಹಾಸವನ್ನು ವೀಕ್ಷಿಸಿ" - } - }, - "features": { - "notices": { - "unstable": "⚠️ ಅಸ್ಥಿರ", - "ban_risk": "⚠️ ಈ ವೈಶಿಷ್ಟ್ಯವು ನಿಷೇಧಕ್ಕೆ ಕಾರಣವಾಗಬಹುದು", - "internal_behavior": "⚠️ ಇದು Snapchat ನ ಆಂತರಿಕ ನಡವಳಿಕೆಯನ್ನು ಮುರಿಯಬಹುದು" - }, - "properties": { - "downloader": { - "name": "ಡೌನ್‌ಲೋಡರ್", - "description": "Snapchat ಮಾಧ್ಯಮವನ್ನು ಡೌನ್‌ಲೋಡ್ ಮಾಡಿ", - "properties": { - "save_folder": { - "name": "ಫೋಲ್ಡರ್ ಉಳಿಸಿ", - "description": "ಎಲ್ಲಾ ಮಾಧ್ಯಮವನ್ನು ಡೌನ್‌ಲೋಡ್ ಮಾಡಬೇಕಾದ ಡೈರೆಕ್ಟರಿಯನ್ನು ಆಯ್ಕೆಮಾಡಿ" - }, - "auto_download_sources": { - "name": "ಸ್ವಯಂ ಡೌನ್‌ಲೋಡ್ ಮೂಲಗಳು", - "description": "ಸ್ವಯಂಚಾಲಿತವಾಗಿ ಡೌನ್‌ಲೋಡ್ ಮಾಡಲು ಮೂಲಗಳನ್ನು ಆಯ್ಕೆಮಾಡಿ" - }, - "prevent_self_auto_download": { - "name": "ಸ್ವಯಂ ಸ್ವಯಂ ಡೌನ್‌ಲೋಡ್ ಅನ್ನು ತಡೆಯಿರಿ", - "description": "ನಿಮ್ಮ ಸ್ವಂತ ಸ್ನ್ಯಾಪ್‌ಗಳನ್ನು ಸ್ವಯಂಚಾಲಿತವಾಗಿ ಡೌನ್‌ಲೋಡ್ ಮಾಡುವುದನ್ನು ತಡೆಯುತ್ತದೆ" - }, - "path_format": { - "name": "ಮಾರ್ಗ ಸ್ವರೂಪ", - "description": "ಫೈಲ್ ಮಾರ್ಗ ಸ್ವರೂಪವನ್ನು ನಿರ್ದಿಷ್ಟಪಡಿಸಿ" - }, - "allow_duplicate": { - "name": "ನಕಲನ್ನು ಅನುಮತಿಸಿ", - "description": "ಒಂದೇ ಮಾಧ್ಯಮವನ್ನು ಹಲವು ಬಾರಿ ಡೌನ್‌ಲೋಡ್ ಮಾಡಲು ಅನುಮತಿಸುತ್ತದೆ" - }, - "merge_overlays": { - "name": "ಓವರ್‌ಲೇಗಳನ್ನು ವಿಲೀನಗೊಳಿಸಿ", - "description": "ಸ್ನ್ಯಾಪ್‌ನ ಪಠ್ಯ ಮತ್ತು ಮಾಧ್ಯಮವನ್ನು ಒಂದೇ ಫೈಲ್‌ಗೆ ಸಂಯೋಜಿಸುತ್ತದೆ" - }, - "force_image_format": { - "name": "ಚಿತ್ರ ಸ್ವರೂಪವನ್ನು ಒತ್ತಾಯಿಸಿ", - "description": "ಚಿತ್ರಗಳನ್ನು ನಿರ್ದಿಷ್ಟ ಸ್ವರೂಪದಲ್ಲಿ ಉಳಿಸಲು ಒತ್ತಾಯಿಸುತ್ತದೆ" - }, - "force_voice_note_format": { - "name": "ಧ್ವನಿ ಟಿಪ್ಪಣಿ ಸ್ವರೂಪವನ್ನು ಒತ್ತಾಯಿಸಿ", - "description": "ಧ್ವನಿ ಟಿಪ್ಪಣಿಗಳನ್ನು ನಿರ್ದಿಷ್ಟ ಸ್ವರೂಪದಲ್ಲಿ ಉಳಿಸಲು ಒತ್ತಾಯಿಸುತ್ತದೆ" - }, - "auto_download_voice_notes": { - "name": "ಧ್ವನಿ ಟಿಪ್ಪಣಿಗಳನ್ನು ಸ್ವಯಂ ಡೌನ್‌ಲೋಡ್ ಮಾಡಿ", - "description": "ಧ್ವನಿ ಟಿಪ್ಪಣಿಗಳನ್ನು ಪ್ಲೇ ಮಾಡುವಾಗ ಸ್ವಯಂಚಾಲಿತವಾಗಿ ಡೌನ್‌ಲೋಡ್ ಮಾಡುತ್ತದೆ" - }, - "download_profile_pictures": { - "name": "ಪ್ರೊಫೈಲ್ ಚಿತ್ರಗಳನ್ನು ಡೌನ್‌ಲೋಡ್ ಮಾಡಿ", - "description": "ಪ್ರೊಫೈಲ್ ಪುಟದಿಂದ ಪ್ರೊಫೈಲ್ ಚಿತ್ರಗಳನ್ನು ಡೌನ್‌ಲೋಡ್ ಮಾಡಲು ನಿಮಗೆ ಅನುಮತಿಸುತ್ತದೆ" - }, - "opera_download_button": { - "name": "ಒಪೇರಾ ಡೌನ್‌ಲೋಡ್ ಬಟನ್", - "description": "ಸ್ನ್ಯಾಪ್ ವೀಕ್ಷಿಸುವಾಗ ಮೇಲಿನ ಬಲ ಮೂಲೆಯಲ್ಲಿ ಡೌನ್‌ಲೋಡ್ ಬಟನ್ ಅನ್ನು ಸೇರಿಸುತ್ತದೆ.\nಬಟನ್‌ಗಳ ಮೇಲೆ ದೀರ್ಘವಾಗಿ ಒತ್ತುವುದು ಡೌನ್‌ಲೋಡ್ ಅನ್ನು ಒತ್ತಾಯಿಸುತ್ತದೆ" - }, - "download_context_menu": { - "name": "ಡೌನ್‌ಲೋಡ್ ಸಂದರ್ಭ ಮೆನು", - "description": "ಸಂದರ್ಭ ಮೆನುವನ್ನು ಬಳಸಿಕೊಂಡು ಸಂಭಾಷಣೆ ಅಥವಾ ಕಥೆಯಿಂದ ಸಂದೇಶಗಳನ್ನು ಡೌನ್‌ಲೋಡ್/ಮುನ್ನೋಟಿಸಲು ನಿಮಗೆ ಅನುಮತಿಸುತ್ತದೆ.\nಬಟನ್‌ಗಳ ಮೇಲೆ ದೀರ್ಘವಾಗಿ ಒತ್ತುವುದು ಡೌನ್‌ಲೋಡ್ ಅನ್ನು ಒತ್ತಾಯಿಸುತ್ತದೆ" - }, - "ffmpeg_options": { - "name": "FFmpeg ಆಯ್ಕೆಗಳು", - "description": "ಹೆಚ್ಚುವರಿ FFmpeg ಆಯ್ಕೆಗಳನ್ನು ನಿರ್ದಿಷ್ಟಪಡಿಸಿ", - "properties": { - "threads": { - "name": "ಥ್ರೆಡ್‌ಗಳು", - "description": "ಬಳಸಬೇಕಾದ ಥ್ರೆಡ್‌ಗಳ ಸಂಖ್ಯೆ" - }, - "preset": { - "name": "ಪೂರ್ವನಿಗದಿ", - "description": "ಪರಿವರ್ತನೆಯ ವೇಗವನ್ನು ಹೊಂದಿಸಿ" - }, - "constant_rate_factor": { - "name": "ಸ್ಥಿರ ದರ ಅಂಶ", - "description": "ವೀಡಿಯೊ ಎನ್‌ಕೋಡರ್‌ಗಾಗಿ ಸ್ಥಿರ ದರ ಅಂಶವನ್ನು ಹೊಂದಿಸಿ\nlibx264 ಗಾಗಿ 0 ರಿಂದ 51 ರವರೆಗೆ" - }, - "video_bitrate": { - "name": "ವೀಡಿಯೊ ಬಿಟ್ರೇಟ್", - "description": "ವೀಡಿಯೊ ಬಿಟ್ರೇಟ್ ಅನ್ನು ಹೊಂದಿಸಿ (kbps)" - }, - "audio_bitrate": { - "name": "ಆಡಿಯೋ ಬಿಟ್ರೇಟ್", - "description": "ಆಡಿಯೋ ಬಿಟ್ರೇಟ್ ಅನ್ನು ಹೊಂದಿಸಿ (kbps)" - }, - "custom_video_codec": { - "name": "ಕಸ್ಟಮ್ ವೀಡಿಯೊ ಕೊಡೆಕ್", - "description": "ಕಸ್ಟಮ್ ವೀಡಿಯೊ ಕೊಡೆಕ್ ಅನ್ನು ಹೊಂದಿಸಿ (ಉದಾ. libx264)" - }, - "custom_audio_codec": { - "name": "ಕಸ್ಟಮ್ ಆಡಿಯೋ ಕೊಡೆಕ್", - "description": "ಕಸ್ಟಮ್ ಆಡಿಯೋ ಕೊಡೆಕ್ ಅನ್ನು ಹೊಂದಿಸಿ (ಉದಾ. AAC)" - } - } - }, - "logging": { - "name": "ಲಾಗಿಂಗ್", - "description": "ಮಾಧ್ಯಮ ಡೌನ್‌ಲೋಡ್ ಆಗುತ್ತಿರುವಾಗ ಟೋಸ್ಟ್‌ಗಳನ್ನು ತೋರಿಸುತ್ತದೆ" - }, - "custom_path_format": { - "name": "ಕಸ್ಟಮ್ ಮಾರ್ಗ ಸ್ವರೂಪ", - "description": "ಡೌನ್‌ಲೋಡ್ ಮಾಡಿದ ಮಾಧ್ಯಮಕ್ಕಾಗಿ ಕಸ್ಟಮ್ ಮಾರ್ಗ ಸ್ವರೂಪವನ್ನು ನಿರ್ದಿಷ್ಟಪಡಿಸಿ\n\nಲಭ್ಯವಿರುವ ವೇರಿಯಬಲ್‌ಗಳು:\n - %username%\n - %source%\n - %hash%\n - %date_time%" - } - } - }, - "user_interface": { - "name": "ಬಳಕೆದಾರ ಇಂಟರ್ಫೇಸ್", - "description": "Snapchat ನ ನೋಟ ಮತ್ತು ಅನುಭವವನ್ನು ಬದಲಾಯಿಸಿ", - "properties": { - "enable_app_appearance": { - "name": "ಅಪ್ಲಿಕೇಶನ್ ಗೋಚರತೆ ಸೆಟ್ಟಿಂಗ್‌ಗಳನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಿ", - "description": "ಮರೆಮಾಡಿದ ಅಪ್ಲಿಕೇಶನ್ ಗೋಚರತೆ ಸೆಟ್ಟಿಂಗ್ ಅನ್ನು ಸಕ್ರಿಯಗೊಳಿಸುತ್ತದೆ\nಹೊಸ Snapchat ಆವೃತ್ತಿಗಳಲ್ಲಿ ಅಗತ್ಯವಿಲ್ಲದಿರಬಹುದು" - }, - "friend_feed_message_preview": { - "name": "ಸ್ನೇಹಿತರ ಫೀಡ್ ಸಂದೇಶ ಮುನ್ನೋಟ", - "description": "ಸ್ನೇಹಿತರ ಫೀಡ್‌ನಲ್ಲಿ ಕೊನೆಯ ಸಂದೇಶಗಳ ಮುನ್ನೋಟವನ್ನು ತೋರಿಸುತ್ತದೆ", - "properties": { - "amount": { - "name": "ಪ್ರಮಾಣ", - "description": "ಮುನ್ನೋಟಿಸಲು ಸಂದೇಶಗಳ ಪ್ರಮಾಣ" - } - } - }, - "snap_preview": { - "name": "ಸ್ನ್ಯಾಪ್ ಮುನ್ನೋಟ", - "description": "ಚಾಟ್‌ನಲ್ಲಿ ನೋಡದ ಸ್ನ್ಯಾಪ್‌ಗಳ ಪಕ್ಕದಲ್ಲಿ ಸಣ್ಣ ಮುನ್ನೋಟವನ್ನು ಪ್ರದರ್ಶಿಸುತ್ತದೆ" - }, - "bootstrap_override": { - "name": "ಬೂಟ್‌ಸ್ಟ್ರಾಪ್ ಅತಿಕ್ರಮಣ", - "description": "ಬಳಕೆದಾರ ಇಂಟರ್ಫೇಸ್ ಬೂಟ್‌ಸ್ಟ್ರಾಪ್ ಸೆಟ್ಟಿಂಗ್‌ಗಳನ್ನು ಅತಿಕ್ರಮಿಸುತ್ತದೆ", - "properties": { - "app_appearance": { - "name": "ಅಪ್ಲಿಕೇಶನ್ ಗೋಚರತೆ", - "description": "ನಿರಂತರ ಅಪ್ಲಿಕೇಶನ್ ಗೋಚರತೆಯನ್ನು ಹೊಂದಿಸುತ್ತದೆ" - }, - "home_tab": { - "name": "ಮುಖಪುಟ ಟ್ಯಾಬ್", - "description": "Snapchat ತೆರೆಯುವಾಗ ಪ್ರಾರಂಭ ಟ್ಯಾಬ್ ಅನ್ನು ಅತಿಕ್ರಮಿಸುತ್ತದೆ" - } - } - }, - "force_amoled_theme": { - "name": "ಅಮೋಲೆಡ್ ಡಾರ್ಕ್ ಮೋಡ್", - "description": "ಡಾರ್ಕ್ ಥೀಮ್‌ಗಾಗಿ ನಿಜವಾದ ಕಪ್ಪು ಹಿನ್ನೆಲೆಯನ್ನು ಬಳಸುತ್ತದೆ" - }, - "map_friend_nametags": { - "name": "ವರ್ಧಿತ ಸ್ನೇಹಿತರ ನಕ್ಷೆ ನಾಮಫಲಕಗಳು", - "description": "ಸ್ನ್ಯಾಪ್‌ಮ್ಯಾಪ್‌ನಲ್ಲಿ ಸ್ನೇಹಿತರ ನಾಮಫಲಕಗಳನ್ನು ಸುಧಾರಿಸುತ್ತದೆ" - }, - "prevent_message_list_auto_scroll": { - "name": "ಸಂದೇಶ ಪಟ್ಟಿ ಸ್ವಯಂ ಸ್ಕ್ರಾಲ್ ತಡೆಯಿರಿ", - "description": "ಸಂದೇಶ ಕಳುಹಿಸುವಾಗ/ಸ್ವೀಕರಿಸುವಾಗ ಸಂದೇಶ ಪಟ್ಟಿಯು ಕೆಳಕ್ಕೆ ಸ್ಕ್ರಾಲ್ ಆಗುವುದನ್ನು ತಡೆಯುತ್ತದೆ" - }, - "streak_expiration_info": { - "name": "ಸ್ಟ್ರೀಕ್ ಮುಕ್ತಾಯ ಮಾಹಿತಿಯನ್ನು ತೋರಿಸಿ", - "description": "ಸ್ಟ್ರೀಕ್ಸ್ ಕೌಂಟರ್ ಪಕ್ಕದಲ್ಲಿ ಸ್ಟ್ರೀಕ್ ಮುಕ್ತಾಯ ಟೈಮರ್ ಅನ್ನು ತೋರಿಸುತ್ತದೆ" - }, - "hide_friend_feed_entry": { - "name": "ಸ್ನೇಹಿತರ ಫೀಡ್ ನಮೂದನ್ನು ಮರೆಮಾಡಿ", - "description": "ಸ್ನೇಹಿತರ ಫೀಡ್‌ನಿಂದ ನಿರ್ದಿಷ್ಟ ಸ್ನೇಹಿತನನ್ನು ಮರೆಮಾಡುತ್ತದೆ\nಈ ವೈಶಿಷ್ಟ್ಯವನ್ನು ನಿರ್ವಹಿಸಲು ಸಾಮಾಜಿಕ ಟ್ಯಾಬ್ ಬಳಸಿ" - }, - "hide_streak_restore": { - "name": "ಸ್ಟ್ರೀಕ್ ಮರುಸ್ಥಾಪನೆಯನ್ನು ಮರೆಮಾಡಿ", - "description": "ಸ್ನೇಹಿತರ ಫೀಡ್‌ನಲ್ಲಿ ಮರುಸ್ಥಾಪನೆ ಬಟನ್ ಅನ್ನು ಮರೆಮಾಡುತ್ತದೆ" - }, - "hide_quick_add_suggestions": { - "name": "ತ್ವರಿತ ಸೇರಿಸು ಸಲಹೆಗಳನ್ನು ಮರೆಮಾಡಿ", - "description": "ತ್ವರಿತ ಸೇರಿಸು ಸ್ನೇಹಿತರ ಸಲಹೆಗಳನ್ನು ತೆಗೆದುಹಾಕುತ್ತದೆ" - }, - "hide_story_suggestions": { - "name": "ಕಥೆ ಸಲಹೆಗಳನ್ನು ಮರೆಮಾಡಿ", - "description": "ಕಥೆಗಳ ಪುಟದಿಂದ ಸಲಹೆಗಳನ್ನು ತೆಗೆದುಹಾಕುತ್ತದೆ" - }, - "hide_ui_components": { - "name": "UI ಘಟಕಗಳನ್ನು ಮರೆಮಾಡಿ", - "description": "ಯಾವ UI ಘಟಕಗಳನ್ನು ಮರೆಮಾಡಬೇಕು ಎಂಬುದನ್ನು ಆಯ್ಕೆಮಾಡಿ" - }, - "opera_media_quick_info": { - "name": "ಒಪೇರಾ ಮಾಧ್ಯಮ ತ್ವರಿತ ಮಾಹಿತಿ", - "description": "ಒಪೇರಾ ವೀಕ್ಷಕ ಸಂದರ್ಭ ಮೆನುವಿನಲ್ಲಿ ರಚನೆಯ ದಿನಾಂಕದಂತಹ ಮಾಧ್ಯಮದ ಉಪಯುಕ್ತ ಮಾಹಿತಿಯನ್ನು ತೋರಿಸುತ್ತದೆ" - }, - "old_bitmoji_selfie": { - "name": "ಹಳೆಯ ಬಿಟ್‌ಮೋಜಿ ಸೆಲ್ಫಿ", - "description": "ಹಳೆಯ Snapchat ಆವೃತ್ತಿಗಳಿಂದ ಬಿಟ್‌ಮೋಜಿ ಸೆಲ್ಫಿಗಳನ್ನು ಮರಳಿ ತರುತ್ತದೆ" - }, - "disable_spotlight": { - "name": "ಸ್ಪಾಟ್‌ಲೈಟ್ ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಿ", - "description": "ಸ್ಪಾಟ್‌ಲೈಟ್ ಪುಟವನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸುತ್ತದೆ" - }, - "friend_feed_menu_buttons": { - "name": "ಸ್ನೇಹಿತರ ಫೀಡ್ ಮೆನು ಬಟನ್‌ಗಳು", - "description": "ಸ್ನೇಹಿತರ ಫೀಡ್ ಮೆನುವಿನಲ್ಲಿ ಯಾವ ಬಟನ್‌ಗಳನ್ನು ತೋರಿಸಬೇಕು ಎಂಬುದನ್ನು ಆಯ್ಕೆಮಾಡಿ" - }, - "auto_close_friend_feed_menu": { - "name": "ಸ್ನೇಹಿತರ ಫೀಡ್ ಮೆನುವನ್ನು ಸ್ವಯಂ ಮುಚ್ಚಿ", - "description": "ಸೆಟ್ಟಿಂಗ್ ಬಟನ್ ಒತ್ತಿದ ನಂತರ ಸ್ನೇಹಿತರ ಫೀಡ್ ಮೆನುವನ್ನು ಸ್ವಯಂಚಾಲಿತವಾಗಿ ಮುಚ್ಚುತ್ತದೆ" - }, - "vertical_story_viewer": { - "name": "ಲಂಬ ಕಥೆ ವೀಕ್ಷಕ", - "description": "ಎಲ್ಲಾ ಕಥೆಗಳಿಗೆ ಲಂಬ ಕಥೆ ವೀಕ್ಷಕವನ್ನು ಸಕ್ರಿಯಗೊಳಿಸುತ್ತದೆ" - }, - "enable_friend_feed_menu_bar": { - "name": "ಸ್ನೇಹಿತರ ಫೀಡ್ ಮೆನು ಬಾರ್", - "description": "ಹೊಸ ಸ್ನೇಹಿತರ ಫೀಡ್ ಮೆನು ಬಾರ್ ಅನ್ನು ಸಕ್ರಿಯಗೊಳಿಸುತ್ತದೆ" - }, - "message_indicators": { - "name": "ಸಂದೇಶ ಸೂಚಕಗಳು", - "description": "ಸಂದೇಶಗಳಿಗೆ ನಿರ್ದಿಷ್ಟ ಸೂಚಕ ಐಕಾನ್‌ಗಳನ್ನು ಸೇರಿಸುತ್ತದೆ\nಗಮನಿಸಿ: ಸೂಚಕಗಳು 100% ನಿಖರವಾಗಿಲ್ಲದಿರಬಹುದು" - }, - "stealth_mode_indicator": { - "name": "ಸ್ಟೆಲ್ತ್ ಮೋಡ್ ಸೂಚಕ", - "description": "ಸ್ಟೆಲ್ತ್ ಮೋಡ್‌ನಲ್ಲಿರುವ ಸಂಭಾಷಣೆಗಳ ಪಕ್ಕದಲ್ಲಿ 👻 ಎಮೋಜಿಯನ್ನು ಸೇರಿಸುತ್ತದೆ" - }, - "edit_text_override": { - "name": "ಪಠ್ಯ ಸಂಪಾದನೆಯನ್ನು ಅತಿಕ್ರಮಿಸಿ", - "description": "ಪಠ್ಯ ಕ್ಷೇತ್ರದ ನಡವಳಿಕೆಯನ್ನು ಅತಿಕ್ರಮಿಸುತ್ತದೆ" - }, - "prevent_forced_keyboard": { - "name": "ಬಲವಂತದ ಕೀಬೋರ್ಡ್ ತಡೆಯಿರಿ", - "description": "ನೀವು ಸಂಭಾಷಣೆಯನ್ನು ತೆರೆದಾಗ Snapchat ಸ್ವಯಂಚಾಲಿತವಾಗಿ ಕೀಬೋರ್ಡ್ ಅನ್ನು ಪಾಪ್ ಅಪ್ ಮಾಡುವುದನ್ನು ತಡೆಯುತ್ತದೆ" - }, - "settings_menu": { - "name": "ಸೆಟ್ಟಿಂಗ್‌ಗಳ ಮೆನು", - "description": "ನೀವು PurrfectSnap ಮೆನು ತೆರೆಯುವ ವಿಧಾನವನ್ನು ಬದಲಾಯಿಸುತ್ತದೆ", - "options": { - "default": "ಡೀಫಾಲ್ಟ್", - "legacy": "ಪರಂಪರೆ" - } - } - } - }, - "messaging": { - "name": "ಸಂದೇಶ ಕಳುಹಿಸುವಿಕೆ", - "description": "ನೀವು ಸ್ನೇಹಿತರೊಂದಿಗೆ ಹೇಗೆ ಸಂವಹನ ನಡೆಸುತ್ತೀರಿ ಎಂಬುದನ್ನು ಬದಲಾಯಿಸಿ", - "properties": { - "bypass_screenshot_detection": { - "name": "ಸ್ಕ್ರೀನ್‌ಶಾಟ್ ಪತ್ತೆಹಚ್ಚುವಿಕೆಯನ್ನು ಬೈಪಾಸ್ ಮಾಡಿ", - "description": "ನೀವು ಸ್ಕ್ರೀನ್‌ಶಾಟ್ ತೆಗೆದುಕೊಂಡಾಗ Snapchat ಪತ್ತೆಹಚ್ಚುವುದನ್ನು ತಡೆಯುತ್ತದೆ" - }, - "anonymous_story_viewing": { - "name": "ಅನಾಮಧೇಯ ಕಥೆ ವೀಕ್ಷಣೆ", - "description": "ನೀವು ಅವರ ಕಥೆಯನ್ನು ನೋಡಿದ್ದೀರಿ ಎಂದು ಯಾರಿಗೂ ತಿಳಿಯದಂತೆ ತಡೆಯುತ್ತದೆ" - }, - "prevent_story_rewatch_indicator": { - "name": "ಕಥೆ ಪುನರಾವರ್ತನೆ ಸೂಚಕವನ್ನು ತಡೆಯಿರಿ", - "description": "ನೀವು ಅವರ ಕಥೆಯನ್ನು ಮರು ವೀಕ್ಷಿಸಿದ್ದೀರಿ ಎಂದು ಯಾರಿಗೂ ತಿಳಿಯದಂತೆ ತಡೆಯುತ್ತದೆ" - }, - "hide_peek_a_peek": { - "name": "ಪೀಕ್-ಎ-ಪೀಕ್ ಮರೆಮಾಡಿ", - "description": "ನೀವು ಚಾಟ್‌ಗೆ ಅರ್ಧ ಸ್ವೈಪ್ ಮಾಡಿದಾಗ ಅಧಿಸೂಚನೆ ಕಳುಹಿಸುವುದನ್ನು ತಡೆಯುತ್ತದೆ" - }, - "hide_bitmoji_presence": { - "name": "ಬಿಟ್‌ಮೋಜಿ ಉಪಸ್ಥಿತಿಯನ್ನು ಮರೆಮಾಡಿ", - "description": "ಚಾಟ್‌ನಲ್ಲಿದ್ದಾಗ ನಿಮ್ಮ ಬಿಟ್‌ಮೋಜಿ ಪಾಪ್ ಅಪ್ ಆಗುವುದನ್ನು ತಡೆಯುತ್ತದೆ" - }, - "hide_typing_notifications": { - "name": "ಟೈಪಿಂಗ್ ಅಧಿಸೂಚನೆಗಳನ್ನು ಮರೆಮಾಡಿ", - "description": "ನೀವು ಸಂದೇಶ ಟೈಪ್ ಮಾಡುತ್ತಿರುವಾಗ ಯಾರಿಗೂ ತಿಳಿಯದಂತೆ ತಡೆಯುತ್ತದೆ" - }, - "unlimited_snap_view_time": { - "name": "ಅನಿಯಮಿತ ಸ್ನ್ಯಾಪ್ ವೀಕ್ಷಣೆ ಸಮಯ", - "description": "ಸ್ನ್ಯಾಪ್‌ಗಳನ್ನು ವೀಕ್ಷಿಸಲು ಸಮಯ ಮಿತಿಯನ್ನು ತೆಗೆದುಹಾಕುತ್ತದೆ" - }, - "auto_mark_as_read": { - "name": "ಸ್ವಯಂಚಾಲಿತವಾಗಿ ಓದಿದಂತೆ ಗುರುತಿಸಿ", - "description": "ಸ್ಟೆಲ್ತ್ ಮೋಡ್ ಸಕ್ರಿಯವಾಗಿದ್ದಾಗಲೂ ಸಂದೇಶಗಳು/ಸ್ನ್ಯಾಪ್‌ಗಳನ್ನು ಸ್ವಯಂಚಾಲಿತವಾಗಿ ಓದಿದಂತೆ ಗುರುತಿಸುತ್ತದೆ" - }, - "mark_snap_as_seen_button": { - "name": "ಸ್ನ್ಯಾಪ್ ಅನ್ನು ನೋಡಿದಂತೆ ಗುರುತಿಸಿ ಬಟನ್", - "description": "ಸ್ನ್ಯಾಪ್ ವೀಕ್ಷಿಸುವಾಗ ಅದನ್ನು ನೋಡಿದಂತೆ ಗುರುತಿಸಲು ಬಟನ್ ಅನ್ನು ಸೇರಿಸುತ್ತದೆ.\nಸ್ಟೆಲ್ತ್ ಮೋಡ್ ಸಕ್ರಿಯವಾಗಿದ್ದಾಗಲೂ ಇದು ಕಾರ್ಯನಿರ್ವಹಿಸುತ್ತದೆ" - }, - "skip_when_marking_as_seen": { - "name": "ನೋಡಿದಂತೆ ಗುರುತಿಸುವಾಗ ಸ್ಕಿಪ್ ಮಾಡಿ", - "description": "ಸ್ನ್ಯಾಪ್ ಅನ್ನು ನೋಡಿದಂತೆ ಗುರುತಿಸುವಾಗ ಸ್ವಯಂಚಾಲಿತವಾಗಿ ಮುಂದಿನ ಸ್ನ್ಯಾಪ್‌ಗೆ ಸ್ಕಿಪ್ ಮಾಡುತ್ತದೆ.\nಸ್ನ್ಯಾಪ್ ಅನ್ನು ನೋಡಿದಂತೆ ಗುರುತಿಸಿ ಬಟನ್‌ನೊಂದಿಗೆ ಸಂಯೋಜನೆಯಲ್ಲಿ ಬಳಸಿ" - }, - "loop_media_playback": { - "name": "ಲೂಪ್ ಮಾಧ್ಯಮ ಪ್ಲೇಬ್ಯಾಕ್", - "description": "ಸ್ನ್ಯಾಪ್‌ಗಳು/ಕಥೆಗಳನ್ನು ವೀಕ್ಷಿಸುವಾಗ ಮಾಧ್ಯಮ ಪ್ಲೇಬ್ಯಾಕ್ ಅನ್ನು ಲೂಪ್ ಮಾಡುತ್ತದೆ" - }, - "disable_replay_in_ff": { - "name": "FF ನಲ್ಲಿ ಮರುಪಂದ್ಯವನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಿ", - "description": "ಸ್ನೇಹಿತರ ಫೀಡ್‌ನಿಂದ ದೀರ್ಘವಾಗಿ ಒತ್ತುವ ಮೂಲಕ ಮರುಪಂದ್ಯ ಮಾಡುವ ಸಾಮರ್ಥ್ಯವನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸುತ್ತದೆ" - }, - "half_swipe_notifier": { - "name": "ಅರ್ಧ ಸ್ವೈಪ್ ಸೂಚಕ", - "description": "ಯಾರಾದರೂ ಸಂಭಾಷಣೆಗೆ ಅರ್ಧ ಸ್ವೈಪ್ ಮಾಡಿದಾಗ ನಿಮಗೆ ಸೂಚಿಸುತ್ತದೆ", - "properties": { - "min_duration": { - "name": "ಕನಿಷ್ಠ ಅವಧಿ", - "description": "ಅರ್ಧ ಸ್ವೈಪ್‌ನ ಕನಿಷ್ಠ ಅವಧಿ (ಸೆಕೆಂಡುಗಳಲ್ಲಿ)" - }, - "max_duration": { - "name": "ಗರಿಷ್ಠ ಅವಧಿ", - "description": "ಅರ್ಧ ಸ್ವೈಪ್‌ನ ಗರಿಷ್ಠ ಅವಧಿ (ಸೆಕೆಂಡುಗಳಲ್ಲಿ)" - } - } - }, - "call_start_confirmation": { - "name": "ಕರೆ ಪ್ರಾರಂಭ ದೃಢೀಕರಣ", - "description": "ಕರೆ ಪ್ರಾರಂಭಿಸುವಾಗ ದೃಢೀಕರಣ ಸಂವಾದವನ್ನು ತೋರಿಸುತ್ತದೆ" - }, - "unlimited_conversation_pinning": { - "name": "ಅನಿಯಮಿತ ಸಂಭಾಷಣೆ ಪಿನ್ನಿಂಗ್", - "description": "ಸ್ಥಳೀಯವಾಗಿ ಅನಿಯಮಿತ ಸಂಖ್ಯೆಯ ಸಂಭಾಷಣೆಗಳನ್ನು ಪಿನ್ ಮಾಡಲು ನಿಮಗೆ ಅನುಮತಿಸುತ್ತದೆ" - }, - "disable_snap_mode_restrictions": { - "name": "ಸ್ನ್ಯಾಪ್ ಮೋಡ್ ನಿರ್ಬಂಧಗಳನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಿ", - "description": "ನಿರ್ಬಂಧಗಳಿಲ್ಲದೆ ಸ್ವಯಂ-ನಾಶವಾಗುವ ಸ್ನ್ಯಾಪ್‌ಗಳನ್ನು ವೀಕ್ಷಿಸಲು ನಿಮಗೆ ಅನುಮತಿಸುತ್ತದೆ" - }, - "prevent_message_sending": { - "name": "ಸಂದೇಶ ಕಳುಹಿಸುವುದನ್ನು ತಡೆಯಿರಿ", - "description": "ಕೆಲವು ರೀತಿಯ ಸಂದೇಶಗಳನ್ನು ಕಳುಹಿಸುವುದನ್ನು ತಡೆಯುತ್ತದೆ" - }, - "friend_mutation_notifier": { - "name": "ಸ್ನೇಹಿತರ ರೂಪಾಂತರ ಸೂಚಕ", - "description": "ಸ್ನೇಹಿತರ ಪ್ರೊಫೈಲ್‌ನಲ್ಲಿ ಏನಾದರೂ ಬದಲಾದಾಗ ನಿಮಗೆ ಸೂಚಿಸುತ್ತದೆ" - }, - "better_notifications": { - "name": "ಉತ್ತಮ ಅಧಿಸೂಚನೆಗಳು", - "description": "ಸ್ವೀಕರಿಸಿದ ಅಧಿಸೂಚನೆಗಳಲ್ಲಿ ಹೆಚ್ಚಿನ ಮಾಹಿತಿಯನ್ನು ಸೇರಿಸುತ್ತದೆ", - "properties": { - "group_notifications": { - "name": "ಗುಂಪು ಅಧಿಸೂಚನೆಗಳು", - "description": "ಅಧಿಸೂಚನೆಗಳನ್ನು ಒಂದಾಗಿ ಗುಂಪು ಮಾಡಿ" - }, - "chat_preview": { - "name": "ಚಾಟ್ ಮುನ್ನೋಟ", - "description": "ಅಧಿಸೂಚನೆಯಲ್ಲಿ ಸ್ವೀಕರಿಸಿದ ಸಂದೇಶಗಳ ಮುನ್ನೋಟವನ್ನು ತೋರಿಸುತ್ತದೆ" - }, - "media_preview": { - "name": "ಮಾಧ್ಯಮ ಮುನ್ನೋಟ", - "description": "ಅಧಿಸೂಚನೆಯಲ್ಲಿ ಆಯ್ಕೆಮಾಡಿದ ಮಾಧ್ಯಮ ಪ್ರಕಾರಗಳ ಮುನ್ನೋಟವನ್ನು ತೋರಿಸುತ್ತದೆ" - }, - "media_caption": { - "name": "ಮಾಧ್ಯಮ ಶೀರ್ಷಿಕೆ", - "description": "ಅಧಿಸೂಚನೆಯಲ್ಲಿ ಮಾಧ್ಯಮದ ಲಗತ್ತಿಸಲಾದ ಶೀರ್ಷಿಕೆಯನ್ನು ತೋರಿಸುತ್ತದೆ" - }, - "stacked_media_messages": { - "name": "ಸ್ಟ್ಯಾಕ್ ಮಾಡಿದ ಮಾಧ್ಯಮ ಸಂದೇಶಗಳು", - "description": "ಅವುಗಳನ್ನು ಮುನ್ನೋಟಿಸಲು ಸಾಧ್ಯವಾಗದಿದ್ದಾಗ ಬಹು ಮಾಧ್ಯಮ ಸಂದೇಶಗಳನ್ನು ಒಂದೇ ಪಠ್ಯ ಅಧಿಸೂಚನೆಗೆ ಸಂಯೋಜಿಸುತ್ತದೆ. ಚಾಟ್ ಮುನ್ನೋಟದೊಂದಿಗೆ ಸಂಯೋಜನೆಯಲ್ಲಿ ಬಳಸಿ" - }, - "friend_add_source": { - "name": "ಸ್ನೇಹಿತರ ಸೇರಿಸು ಮೂಲ", - "description": "ಅಧಿಸೂಚನೆಯಲ್ಲಿ ಸ್ನೇಹಿತರ ವಿನಂತಿಯ ಮೂಲವನ್ನು ತೋರಿಸುತ್ತದೆ" - }, - "reply_button": { - "name": "ಪ್ರತ್ಯುತ್ತರ ಬಟನ್", - "description": "ಅಧಿಸೂಚನೆಗೆ ಪ್ರತ್ಯುತ್ತರ ಬಟನ್ ಅನ್ನು ಸೇರಿಸುತ್ತದೆ" - }, - "smart_replies": { - "name": "ಸ್ಮಾರ್ಟ್ ಪ್ರತ್ಯುತ್ತರಗಳು", - "description": "ಅಧಿಸೂಚನೆಗಳಿಗೆ ಸೂಚಿಸಿದ ಪ್ರತ್ಯುತ್ತರಗಳನ್ನು ಸೇರಿಸುತ್ತದೆ (Android 10+). ಪ್ರತ್ಯುತ್ತರ ಬಟನ್‌ನೊಂದಿಗೆ ಸಂಯೋಜನೆಯಲ್ಲಿ ಬಳಸಿ" - }, - "download_button": { - "name": "ಡೌನ್‌ಲೋಡ್ ಬಟನ್", - "description": "ಅಧಿಸೂಚನೆಯಿಂದ ಮಾಧ್ಯಮವನ್ನು ಡೌನ್‌ಲೋಡ್ ಮಾಡಲು ನಿಮಗೆ ಅನುಮತಿಸುತ್ತದೆ" - }, - "mark_as_read_button": { - "name": "ಓದಿದಂತೆ ಗುರುತಿಸಿ ಬಟನ್", - "description": "ಅಧಿಸೂಚನೆಯಿಂದ ಸಂದೇಶವನ್ನು ಓದಿದಂತೆ ಗುರುತಿಸಲು ನಿಮಗೆ ಅನುಮತಿಸುತ್ತದೆ" - }, - "mark_as_read_and_save_in_chat": { - "name": "ಓದಿದಂತೆ ಗುರುತಿಸಿ ಮತ್ತು ಚಾಟ್‌ನಲ್ಲಿ ಉಳಿಸಿ", - "description": "ಅಧಿಸೂಚನೆಗೆ ಓದಿದಂತೆ ಗುರುತಿಸಿ ಮತ್ತು ಚಾಟ್‌ನಲ್ಲಿ ಉಳಿಸಿ ಬಟನ್ ಅನ್ನು ಸೇರಿಸುತ್ತದೆ" - } - } - }, - "notification_blacklist": { - "name": "ಅಧಿಸೂಚನೆ ಕಪ್ಪುಪಟ್ಟಿ", - "description": "ಯಾವ ಅಧಿಸೂಚನೆಗಳನ್ನು ನಿರ್ಬಂಧಿಸಬೇಕು ಎಂಬುದನ್ನು ಆಯ್ಕೆಮಾಡಿ" - }, - "message_logger": { - "name": "ಸಂದೇಶ ಲಾಗರ್", - "description": "ಸಂದೇಶಗಳನ್ನು ಅಳಿಸುವುದನ್ನು ತಡೆಯುತ್ತದೆ", - "properties": { - "keep_my_own_messages": { - "name": "ನನ್ನ ಸ್ವಂತ ಸಂದೇಶಗಳನ್ನು ಇರಿಸಿ", - "description": "ನಿಮ್ಮ ಸ್ವಂತ ಸಂದೇಶಗಳನ್ನು ಅಳಿಸುವುದನ್ನು ತಡೆಯುತ್ತದೆ" - }, - "auto_purge": { - "name": "ಸ್ವಯಂ ಶುದ್ಧೀಕರಣ", - "description": "ನಿರ್ದಿಷ್ಟ ಸಮಯಕ್ಕಿಂತ ಹಳೆಯದಾದ ಸಂಗ್ರಹಿಸಲಾದ ಸಂದೇಶಗಳನ್ನು ಸ್ವಯಂಚಾಲಿತವಾಗಿ ಅಳಿಸುತ್ತದೆ" - }, - "message_filter": { - "name": "ಸಂದೇಶ ಫಿಲ್ಟರ್", - "description": "ಯಾವ ಸಂದೇಶಗಳನ್ನು ಲಾಗ್ ಮಾಡಬೇಕು ಎಂಬುದನ್ನು ಆಯ್ಕೆಮಾಡಿ (ಎಲ್ಲಾ ಸಂದೇಶಗಳಿಗೆ ಖಾಲಿ)" - }, - "deleted_message_color": { - "name": "ಅಳಿಸಲಾದ ಸಂದೇಶದ ಬಣ್ಣ", - "description": "ಅಳಿಸಲಾದ ಸಂದೇಶಗಳ ಬಣ್ಣವನ್ನು ಹೊಂದಿಸುತ್ತದೆ" - } - } - }, - "auto_save_messages_in_conversations": { - "name": "ಸಂಭಾಷಣೆಗಳಲ್ಲಿ ಸಂದೇಶಗಳನ್ನು ಸ್ವಯಂ ಉಳಿಸಿ", - "description": "ಸಂಭಾಷಣೆಗಳಲ್ಲಿ ಪ್ರತಿಯೊಂದು ಸಂದೇಶವನ್ನು ಸ್ವಯಂಚಾಲಿತವಾಗಿ ಉಳಿಸುತ್ತದೆ" - }, - "gallery_media_send_override": { - "name": "ಗ್ಯಾಲರಿ ಮಾಧ್ಯಮ ಕಳುಹಿಸುವಿಕೆಯನ್ನು ಅತಿಕ್ರಮಿಸಿ", - "description": "ಗ್ಯಾಲರಿಯಿಂದ ಕಳುಹಿಸುವಾಗ ಮಾಧ್ಯಮ ಮೂಲವನ್ನು ವಂಚಿಸುತ್ತದೆ" - }, - "strip_media_metadata": { - "name": "ಮಾಧ್ಯಮ ಮೆಟಾಡೇಟಾವನ್ನು ತೆಗೆದುಹಾಕಿ", - "description": "ಸಂದೇಶವಾಗಿ ಕಳುಹಿಸುವ ಮೊದಲು ಮಾಧ್ಯಮದ ಮೆಟಾಡೇಟಾವನ್ನು ತೆಗೆದುಹಾಕುತ್ತದೆ" - }, - "bypass_message_retention_policy": { - "name": "ಸಂದೇಶ ಉಳಿಸಿಕೊಳ್ಳುವ ನೀತಿಯನ್ನು ಬೈಪಾಸ್ ಮಾಡಿ", - "description": "ಸಂದೇಶಗಳನ್ನು ವೀಕ್ಷಿಸಿದ ನಂತರ ಅವುಗಳನ್ನು ಅಳಿಸುವುದನ್ನು ತಡೆಯುತ್ತದೆ" - }, - "bypass_message_action_restrictions": { - "name": "ಸಂದೇಶ ಕ್ರಿಯೆ ನಿರ್ಬಂಧಗಳನ್ನು ಬೈಪಾಸ್ ಮಾಡಿ", - "description": "ಸ್ನ್ಯಾಪ್ ತೆರೆಯದೆಯೇ ಅದಕ್ಕೆ ಪ್ರತಿಕ್ರಿಯಿಸಲು ಅಥವಾ ಉಳಿಸಲಾಗದ ಸಂದೇಶವನ್ನು ಉಳಿಸಲು ನಿಮಗೆ ಅನುಮತಿಸುತ್ತದೆ" - }, - "remove_groups_locked_status": { - "name": "ಗುಂಪುಗಳ ಲಾಕ್ ಸ್ಥಿತಿಯನ್ನು ತೆಗೆದುಹಾಕಿ", - "description": "ಹೊರಹಾಕಲ್ಪಟ್ಟ ನಂತರ ಗುಂಪು ಮಾಹಿತಿಯನ್ನು ವೀಕ್ಷಿಸಲು ನಿಮಗೆ ಅನುಮತಿಸುತ್ತದೆ" - }, - "double_tap_chat_action": { - "name": "ಡಬಲ್ ಟ್ಯಾಪ್ ಚಾಟ್ ಕ್ರಿಯೆ", - "description": "ಚಾಟ್‌ನಲ್ಲಿ ಸಂದೇಶವನ್ನು ಡಬಲ್ ಟ್ಯಾಪ್ ಮಾಡುವಾಗ ಕಸ್ಟಮ್ ಕ್ರಿಯೆಯನ್ನು ನಿರ್ವಹಿಸುತ್ತದೆ" - }, - "double_tap_chat_action_custom_emoji": { - "name": "ಡಬಲ್ ಟ್ಯಾಪ್ ಚಾಟ್ ಕ್ರಿಯೆ ಕಸ್ಟಮ್ ಎಮೋಜಿ ಪ್ರತಿಕ್ರಿಯೆ", - "description": "ಡಬಲ್ ಟ್ಯಾಪ್ ಚಾಟ್ ಕ್ರಿಯೆಗಾಗಿ ಕಸ್ಟಮ್ ಎಮೋಜಿ ಪ್ರತಿಕ್ರಿಯೆಯನ್ನು ಹೊಂದಿಸುತ್ತದೆ" - } - } - }, - "global": { - "name": "ಜಾಗತಿಕ", - "description": "ಜಾಗತಿಕ Snapchat ಸೆಟ್ಟಿಂಗ್‌ಗಳನ್ನು ತಿರುಚು", - "properties": { - "better_location": { - "name": "ಉತ್ತಮ ಸ್ಥಳ", - "description": "Snapchat ಸ್ಥಳವನ್ನು ಹೆಚ್ಚಿಸುತ್ತದೆ", - "properties": { - "spoof_location": { - "name": "ಸ್ಥಳವನ್ನು ವಂಚಿಸಿ", - "description": "ನಿಮ್ಮ ಸ್ಥಳವನ್ನು ನಿರ್ದಿಷ್ಟ ಒಂದಕ್ಕೆ ವಂಚಿಸುತ್ತದೆ" - }, - "coordinates": { - "name": "ನಿರ್ದೇಶಾಂಕಗಳು", - "description": "ವಂಚಿಸಿದ ಸ್ಥಳದ ನಿರ್ದೇಶಾಂಕಗಳನ್ನು ಹೊಂದಿಸಿ" - }, - "walk_radius": { - "name": "ನಡಿಗೆ ತ್ರಿಜ್ಯ", - "description": "ಈ ತ್ರಿಜ್ಯದೊಳಗೆ ಯಾದೃಚ್ಛಿಕವಾಗಿ ನಡೆಯಿರಿ (ಅಡಿ)" - }, - "always_update_location": { - "name": "ಯಾವಾಗಲೂ ಸ್ಥಳವನ್ನು ನವೀಕರಿಸಿ", - "description": "ಯಾವುದೇ GPS ಡೇಟಾ ಸ್ವೀಕರಿಸದಿದ್ದರೂ ಸಹ Snapchat ಅನ್ನು ಸ್ಥಳವನ್ನು ನವೀಕರಿಸಲು ಒತ್ತಾಯಿಸಿ" - }, - "suspend_location_updates": { - "name": "ಸ್ಥಳ ನವೀಕರಣಗಳನ್ನು ಸ್ಥಗಿತಗೊಳಿಸಿ", - "description": "ನಿಮ್ಮ ಸ್ಥಳವನ್ನು ನವೀಕರಿಸುವುದನ್ನು ತಡೆಯುತ್ತದೆ" - }, - "spoof_battery_level": { - "name": "ಬ್ಯಾಟರಿ ಮಟ್ಟವನ್ನು ವಂಚಿಸಿ", - "description": "ನಕ್ಷೆಯಲ್ಲಿ ನಿಮ್ಮ ಸಾಧನದ ಬ್ಯಾಟರಿ ಮಟ್ಟವನ್ನು ವಂಚಿಸುತ್ತದೆ\nಮೌಲ್ಯವು 0 ಮತ್ತು 100 ರ ನಡುವೆ ಇರಬೇಕು" - }, - "spoof_headphones": { - "name": "ಹೆಡ್‌ಫೋನ್‌ಗಳನ್ನು ವಂಚಿಸಿ", - "description": "ನಕ್ಷೆಯಲ್ಲಿ ಸಂಗೀತವನ್ನು ಕೇಳುವ ಸ್ಥಿತಿಯನ್ನು ವಂಚಿಸುತ್ತದೆ" - }, - "show_battery_level": { - "name": "ಬ್ಯಾಟರಿ ಮಟ್ಟವನ್ನು ತೋರಿಸಿ", - "description": "ನಕ್ಷೆಯಲ್ಲಿ ನಿಮ್ಮ ಸ್ನೇಹಿತರ ಬ್ಯಾಟರಿ ಮಟ್ಟವನ್ನು ತೋರಿಸುತ್ತದೆ" - } - } - }, - "snapchat_plus": { - "name": "ಸ್ನ್ಯಾಪ್‌ಚಾಟ್ ಪ್ಲಸ್", - "description": "Snapchat Plus ವೈಶಿಷ್ಟ್ಯಗಳನ್ನು ಸಕ್ರಿಯಗೊಳಿಸುತ್ತದೆ\nಕೆಲವು ಸರ್ವರ್-ಬದಿಯ ವೈಶಿಷ್ಟ್ಯಗಳು ಕಾರ್ಯನಿರ್ವಹಿಸದಿರಬಹುದು" - }, - "media_upload_quality": { - "name": "ಮಾಧ್ಯಮ ಅಪ್‌ಲೋಡ್ ಗುಣಮಟ್ಟ", - "description": "ಮಾಧ್ಯಮ ಅಪ್‌ಲೋಡ್ ಗುಣಮಟ್ಟವನ್ನು ಅತಿಕ್ರಮಿಸುತ್ತದೆ", - "properties": { - "force_video_upload_source_quality": { - "name": "ವೀಡಿಯೊ ಅಪ್‌ಲೋಡ್ ಮೂಲ ಗುಣಮಟ್ಟವನ್ನು ಒತ್ತಾಯಿಸಿ", - "description": "ವೀಡಿಯೊಗಳನ್ನು ಅಪ್‌ಲೋಡ್ ಮಾಡುವಾಗ ಮೂಲ ಗುಣಮಟ್ಟವನ್ನು ಬಳಸಲು Snapchat ಅನ್ನು ಒತ್ತಾಯಿಸುತ್ತದೆ\nಇದು ಮಾಧ್ಯಮದಿಂದ ಮೆಟಾಡೇಟಾವನ್ನು ತೆಗೆದುಹಾಕದಿರಬಹುದು ಎಂಬುದನ್ನು ದಯವಿಟ್ಟು ಗಮನಿಸಿ" - }, - "disable_image_compression": { - "name": "ಚಿತ್ರ ಸಂಕೋಚನವನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಿ", - "description": "ಮಾಧ್ಯಮವನ್ನು ಅಪ್‌ಲೋಡ್ ಮಾಡುವಾಗ ಚಿತ್ರ ಸಂಕೋಚನವನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸುತ್ತದೆ" - }, - "custom_image_upload_format": { - "name": "ಕಸ್ಟಮ್ ಚಿತ್ರ ಅಪ್‌ಲೋಡ್ ಸ್ವರೂಪ", - "description": "ಕಸ್ಟಮ್ ಚಿತ್ರ ಅಪ್‌ಲೋಡ್ ಸ್ವರೂಪವನ್ನು ಹೊಂದಿಸುತ್ತದೆ\nಉತ್ತಮ ಗುಣಮಟ್ಟಕ್ಕಾಗಿ ನಷ್ಟರಹಿತ ಸ್ವರೂಪವನ್ನು (PNG ನಂತಹ) ಆಯ್ಕೆಮಾಡಿ" - } - } - }, - "disable_confirmation_dialogs": { - "name": "ದೃಢೀಕರಣ ಸಂವಾದಗಳನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಿ", - "description": "ಆಯ್ದ ಕ್ರಿಯೆಗಳನ್ನು ಸ್ವಯಂಚಾಲಿತವಾಗಿ ದೃಢೀಕರಿಸುತ್ತದೆ" - }, - "auto_updater": { - "name": "ಸ್ವಯಂ ನವೀಕರಣಕಾರ", - "description": "ಹೊಸ ನವೀಕರಣಗಳಿಗಾಗಿ ಸ್ವಯಂಚಾಲಿತವಾಗಿ ಪರಿಶೀಲಿಸುತ್ತದೆ" - }, - "disable_metrics": { - "name": "ಮೆಟ್ರಿಕ್ಸ್ ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಿ", - "description": "Snapchat ಗೆ ನಿರ್ದಿಷ್ಟ ವಿಶ್ಲೇಷಣಾತ್ಮಕ ಡೇಟಾವನ್ನು ಕಳುಹಿಸುವುದನ್ನು ನಿರ್ಬಂಧಿಸುತ್ತದೆ" - }, - "disable_story_sections": { - "name": "ಕಥೆ ವಿಭಾಗಗಳನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಿ", - "description": "ಕಥೆಗಳ ಪುಟದಿಂದ ವಿಭಾಗಗಳನ್ನು ತೆಗೆದುಹಾಕುತ್ತದೆ\nಸರಿಯಾಗಿ ಕಾರ್ಯನಿರ್ವಹಿಸಲು ರಿಫ್ರೆಶ್ ಅಗತ್ಯವಿರಬಹುದು" - }, - "block_ads": { - "name": "ಜಾಹೀರಾತುಗಳನ್ನು ನಿರ್ಬಂಧಿಸಿ", - "description": "ಜಾಹೀರಾತುಗಳನ್ನು ಪ್ರದರ್ಶಿಸುವುದನ್ನು ತಡೆಯುತ್ತದೆ" - }, - "disable_custom_tabs": { - "name": "ಕಸ್ಟಮ್ ಟ್ಯಾಬ್‌ಗಳನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಿ", - "description": "ವೆಬ್ ಬ್ರೌಸರ್‌ನಲ್ಲಿ ಬದಲಾಗಿ ಬೆಂಬಲಿತ ಅಪ್ಲಿಕೇಶನ್‌ಗಳಲ್ಲಿ ಲಿಂಕ್‌ಗಳನ್ನು ತೆರೆಯುತ್ತದೆ" - }, - "disable_permission_requests": { - "name": "ಅನುಮತಿ ವಿನಂತಿಗಳನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಿ", - "description": "Snapchat ನಿರ್ದಿಷ್ಟ ಅನುಮತಿಗಳನ್ನು ಕೇಳುವುದನ್ನು ತಡೆಯುತ್ತದೆ" - }, - "disable_memories_snap_feed": { - "name": "ನೆನಪುಗಳ ಸ್ನ್ಯಾಪ್ ಫೀಡ್ ಅನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಿ", - "description": "ನೀವು ಕ್ಯಾಮೆರಾದಲ್ಲಿ ಮೇಲಕ್ಕೆ ಸ್ವೈಪ್ ಮಾಡಿದಾಗ Snapchat ಇತ್ತೀಚಿನ ನೆನಪುಗಳನ್ನು ತೋರಿಸುವುದನ್ನು ತಡೆಯುತ್ತದೆ" - }, - "spotlight_comments_username": { - "name": "ಸ್ಪಾಟ್‌ಲೈಟ್ ಕಾಮೆಂಟ್‌ಗಳ ಬಳಕೆದಾರಹೆಸರು", - "description": "ಸ್ಪಾಟ್‌ಲೈಟ್ ಕಾಮೆಂಟ್‌ಗಳಲ್ಲಿ ಲೇಖಕರ ಬಳಕೆದಾರಹೆಸರನ್ನು ತೋರಿಸುತ್ತದೆ" - }, - "bypass_video_length_restriction": { - "name": "ವೀಡಿಯೊ ಉದ್ದದ ನಿರ್ಬಂಧಗಳನ್ನು ಬೈಪಾಸ್ ಮಾಡಿ", - "description": "ಏಕ: ಒಂದೇ ವೀಡಿಯೊವನ್ನು ಕಳುಹಿಸುತ್ತದೆ\nವಿಭಜನೆ: ಸಂಪಾದಿಸಿದ ನಂತರ ವೀಡಿಯೊಗಳನ್ನು ವಿಭಜಿಸಿ" - }, - "default_video_playback_rate": { - "name": "ಡೀಫಾಲ್ಟ್ ವೀಡಿಯೊ ಪ್ಲೇಬ್ಯಾಕ್ ದರ", - "description": "ವೀಡಿಯೊಗಳ ಪ್ಲೇಬ್ಯಾಕ್‌ಗಾಗಿ ಡೀಫಾಲ್ಟ್ ವೇಗವನ್ನು ಹೊಂದಿಸುತ್ತದೆ\nಮೌಲ್ಯವು 0.1 ಮತ್ತು 4.0 ರ ನಡುವೆ ಇರಬೇಕು" - }, - "video_playback_rate_slider": { - "name": "ವೀಡಿಯೊ ಪ್ಲೇಬ್ಯಾಕ್ ದರ ಸ್ಲೈಡರ್", - "description": "ವೀಡಿಯೊ ಪ್ಲೇಬ್ಯಾಕ್ ದರವನ್ನು ಬದಲಾಯಿಸಲು ಒಪೇರಾ ಸಂದರ್ಭ ಮೆನುವಿನಲ್ಲಿ ಸ್ಲೈಡರ್ ಅನ್ನು ಸೇರಿಸುತ್ತದೆ\nಗಮನಿಸಿ: ಬದಲಾವಣೆಗಳು ನಂತರದ ವೀಡಿಯೊಗಳಿಗೆ ಮಾತ್ರ ಅನ್ವಯಿಸುತ್ತವೆ" - }, - "disable_google_play_dialogs": { - "name": "Google Play ಸೇವೆಗಳ ಸಂವಾದಗಳನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಿ", - "description": "Google Play ಸೇವೆಗಳ ಲಭ್ಯತೆಯ ಸಂವಾದಗಳನ್ನು ತೋರಿಸುವುದನ್ನು ತಡೆಯಿರಿ" - }, - "default_volume_controls": { - "name": "ಡೀಫಾಲ್ಟ್ ವಾಲ್ಯೂಮ್ ನಿಯಂತ್ರಣಗಳು", - "description": "Snapchat ಅನ್ನು ಸಿಸ್ಟಮ್ ವಾಲ್ಯೂಮ್ ನಿಯಂತ್ರಣಗಳನ್ನು ಬಳಸಲು ಒತ್ತಾಯಿಸುತ್ತದೆ" - }, - "disable_telecom_framework": { - "name": "ಟೆಲಿಕಾಂ ಫ್ರೇಮ್‌ವರ್ಕ್ ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಿ", - "description": "Snapchat ಅನ್ನು Android ಟೆಲಿಕಾಂ ಫ್ರೇಮ್‌ವರ್ಕ್ ಬಳಸುವುದನ್ನು ತಡೆಯುತ್ತದೆ\nಇದು ಕರೆ ಮಾಡುವಾಗ ಸಂಗೀತವನ್ನು ಕೇಳಲು ನಿಮಗೆ ಅನುಮತಿಸುತ್ತದೆ" - }, - "hide_active_music": { - "name": "ಸಕ್ರಿಯ ಸಂಗೀತವನ್ನು ಮರೆಮಾಡಿ", - "description": "ನೀವು ಸಂಗೀತವನ್ನು ಕೇಳುತ್ತಿದ್ದೀರಿ ಎಂದು Snapchat ತಿಳಿಯುವುದನ್ನು ತಡೆಯುತ್ತದೆ\nಇದು ಸಂಗೀತವನ್ನು ಕೇಳುವಾಗ ನಿಯಂತ್ರಣ ವಾಲ್ಯೂಮ್ ಬಟನ್‌ಗಳನ್ನು ಬಳಸಿಕೊಂಡು ಸ್ನ್ಯಾಪ್‌ಗಳನ್ನು ತೆಗೆದುಕೊಳ್ಳಲು ನಿಮಗೆ ಅನುಮತಿಸುತ್ತದೆ" - }, - "disable_snap_splitting": { - "name": "ಸ್ನ್ಯಾಪ್ ವಿಭಜನೆಯನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಿ", - "description": "ಸ್ನ್ಯಾಪ್‌ಗಳನ್ನು ಬಹು ಭಾಗಗಳಾಗಿ ವಿಭಜಿಸುವುದನ್ನು ತಡೆಯುತ್ತದೆ\nನೀವು ಕಳುಹಿಸುವ ಚಿತ್ರಗಳು ವೀಡಿಯೊಗಳಾಗಿ ಬದಲಾಗುತ್ತವೆ" - } - } - }, - "rules": { - "name": "ನಿಯಮಗಳು", - "description": "ವೈಯಕ್ತಿಕ ಜನರಿಗೆ ಸ್ವಯಂಚಾಲಿತ ವೈಶಿಷ್ಟ್ಯಗಳನ್ನು ನಿರ್ವಹಿಸಿ" - }, - "camera": { - "name": "ಕ್ಯಾಮೆರಾ", - "description": "ಪರಿಪೂರ್ಣ ಸ್ನ್ಯಾಪ್‌ಗಾಗಿ ಸರಿಯಾದ ಸೆಟ್ಟಿಂಗ್‌ಗಳನ್ನು ಹೊಂದಿಸಿ", - "properties": { - "disable_cameras": { - "name": "ಕ್ಯಾಮೆರಾಗಳನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಿ", - "description": "ಆಯ್ದ ಕ್ಯಾಮೆರಾಗಳನ್ನು ಬಳಸುವುದನ್ನು Snapchat ತಡೆಯುತ್ತದೆ" - }, - "black_photos": { - "name": "ಕಪ್ಪು ಫೋಟೋಗಳು", - "description": "ಸೆರೆಹಿಡಿದ ಫೋಟೋಗಳನ್ನು ಕಪ್ಪು ಹಿನ್ನೆಲೆಯೊಂದಿಗೆ ಬದಲಾಯಿಸುತ್ತದೆ\nವೀಡಿಯೊಗಳು ಪರಿಣಾಮ ಬೀರುವುದಿಲ್ಲ" - }, - "immersive_camera_preview": { - "name": "ತಲ್ಲೀನಗೊಳಿಸುವ ಮುನ್ನೋಟ", - "description": "Snapchat ಕ್ಯಾಮೆರಾ ಮುನ್ನೋಟವನ್ನು ಕ್ರಾಪ್ ಮಾಡುವುದನ್ನು ತಡೆಯುತ್ತದೆ\nಇದು ಕೆಲವು ಸಾಧನಗಳಲ್ಲಿ ಕ್ಯಾಮೆರಾ ಮಿನುಗುವಿಕೆಗೆ ಕಾರಣವಾಗಬಹುದು" - }, - "override_front_resolution": { - "name": "ಮುಂಭಾಗದ ರೆಸಲ್ಯೂಶನ್ ಅನ್ನು ಅತಿಕ್ರಮಿಸಿ", - "description": "ಮುಂಭಾಗದ ಕ್ಯಾಮೆರಾಗಾಗಿ ಕ್ಯಾಮೆರಾ ರೆಸಲ್ಯೂಶನ್ ಅನ್ನು ಅತಿಕ್ರಮಿಸುತ್ತದೆ" - }, - "override_back_resolution": { - "name": "ಹಿಂದಿನ ರೆಸಲ್ಯೂಶನ್ ಅನ್ನು ಅತಿಕ್ರಮಿಸಿ", - "description": "ಹಿಂದಿನ ಕ್ಯಾಮೆರಾಗಾಗಿ ಕ್ಯಾಮೆರಾ ರೆಸಲ್ಯೂಶನ್ ಅನ್ನು ಅತಿಕ್ರಮಿಸುತ್ತದೆ" - }, - "custom_resolution": { - "name": "ಕಸ್ಟಮ್ ರೆಸಲ್ಯೂಶನ್", - "description": "ಕಸ್ಟಮ್ ಕ್ಯಾಮೆರಾ ರೆಸಲ್ಯೂಶನ್ ಅನ್ನು ಹೊಂದಿಸುತ್ತದೆ, ಅಗಲ x ಎತ್ತರ (ಉದಾ. 1920x1080).\nಕಸ್ಟಮ್ ರೆಸಲ್ಯೂಶನ್ ನಿಮ್ಮ ಸಾಧನದಿಂದ ಬೆಂಬಲಿತವಾಗಿರಬೇಕು" - }, - "front_custom_frame_rate": { - "name": "ಮುಂಭಾಗದ ಕಸ್ಟಮ್ ಫ್ರೇಮ್ ದರ", - "description": "ಮುಂಭಾಗದ ಕ್ಯಾಮೆರಾದ ಫ್ರೇಮ್ ದರವನ್ನು ಅತಿಕ್ರಮಿಸುತ್ತದೆ" - }, - "back_custom_frame_rate": { - "name": "ಹಿಂದಿನ ಕಸ್ಟಮ್ ಫ್ರೇಮ್ ದರ", - "description": "ಹಿಂದಿನ ಕ್ಯಾಮೆರಾದ ಫ್ರೇಮ್ ದರವನ್ನು ಅತಿಕ್ರಮಿಸುತ್ತದೆ" - }, - "force_camera_source_encoding": { - "name": "ಕ್ಯಾಮೆರಾ ಮೂಲ ಎನ್‌ಕೋಡಿಂಗ್ ಅನ್ನು ಒತ್ತಾಯಿಸಿ", - "description": "ಕ್ಯಾಮೆರಾ ಮೂಲ ಎನ್‌ಕೋಡಿಂಗ್ ಅನ್ನು ಒತ್ತಾಯಿಸುತ್ತದೆ" - }, - "startup_default_camera": { - "name": "ಪ್ರಾರಂಭಿಕ ಡೀಫಾಲ್ಟ್ ಕ್ಯಾಮೆರಾ", - "description": "Snapchat ತೆರೆಯುವಾಗ ಡೀಫಾಲ್ಟ್ ಕ್ಯಾಮೆರಾವನ್ನು ಹೊಂದಿಸುತ್ತದೆ" - }, - "hevc_recording": { - "name": "HEVC ರೆಕಾರ್ಡಿಂಗ್", - "description": "ವೀಡಿಯೊ ರೆಕಾರ್ಡಿಂಗ್‌ಗಾಗಿ HEVC (H.265) ಕೊಡೆಕ್ ಅನ್ನು ಬಳಸುತ್ತದೆ" - } - } - }, - "streaks_reminder": { - "name": "ಸ್ಟ್ರೀಕ್ಸ್ ಜ್ಞಾಪನೆ", - "description": "ನಿಮ್ಮ ಸ್ಟ್ರೀಕ್ಸ್‌ಗಳ ಬಗ್ಗೆ ನಿಯತಕಾಲಿಕವಾಗಿ ನಿಮಗೆ ಸೂಚಿಸುತ್ತದೆ", - "properties": { - "interval": { - "name": "ಅಂತರ", - "description": "ಪ್ರತಿ ಜ್ಞಾಪನೆಯ ನಡುವಿನ ಅಂತರ (ಗಂಟೆಗಳು)" - }, - "remaining_hours": { - "name": "ಉಳಿದ ಸಮಯ", - "description": "ಅಧಿಸೂಚನೆಯನ್ನು ತೋರಿಸುವ ಮೊದಲು ಉಳಿದಿರುವ ಸಮಯ (ಗಂಟೆಗಳು)" - }, - "group_notifications": { - "name": "ಗುಂಪು ಅಧಿಸೂಚನೆಗಳು", - "description": "ಅಧಿಸೂಚನೆಗಳನ್ನು ಒಂದಾಗಿ ಗುಂಪು ಮಾಡಿ" - } - } - }, - "experimental": { - "name": "ಪ್ರಾಯೋಗಿಕ", - "description": "ಪ್ರಾಯೋಗಿಕ ವೈಶಿಷ್ಟ್ಯಗಳು", - "properties": { - "native_hooks": { - "name": "ಸ್ಥಳೀಯ ಹುಕ್ಸ್", - "description": "Snapchat ನ ಸ್ಥಳೀಯ ಕೋಡ್‌ಗೆ ಹುಕ್ ಮಾಡುವ ಅಸುರಕ್ಷಿತ ವೈಶಿಷ್ಟ್ಯಗಳು", - "properties": { - "composer_hooks": { - "name": "ಸಂಯೋಜಕ ಹುಕ್ಸ್", - "description": "ಸಂಯೋಜಕ ಕ್ರಾಸ್-ಪ್ಲಾಟ್‌ಫಾರ್ಮ್ UI ಫ್ರೇಮ್‌ವರ್ಕ್‌ಗೆ ಕೋಡ್ ಅನ್ನು ಚುಚ್ಚುತ್ತದೆ", - "properties": { - "show_first_created_username": { - "name": "ಮೊದಲು ರಚಿಸಲಾದ ಬಳಕೆದಾರಹೆಸರನ್ನು ತೋರಿಸಿ", - "description": "ಪ್ರೊಫೈಲ್ ಪುಟದಲ್ಲಿ ಪ್ರಸ್ತುತ ಬಳಕೆದಾರಹೆಸರಿನ ಪಕ್ಕದಲ್ಲಿ ಮೊದಲು ರಚಿಸಲಾದ ಬಳಕೆದಾರಹೆಸರನ್ನು ತೋರಿಸುತ್ತದೆ" - }, - "bypass_camera_roll_limit": { - "name": "ಕ್ಯಾಮೆರಾ ರೋಲ್ ಮಿತಿಯನ್ನು ಬೈಪಾಸ್ ಮಾಡಿ", - "description": "ನೀವು ಕ್ಯಾಮೆರಾ ರೋಲ್‌ನಿಂದ ಕಳುಹಿಸಬಹುದಾದ ಮಾಧ್ಯಮದ ಗರಿಷ್ಠ ಪ್ರಮಾಣವನ್ನು ಹೆಚ್ಚಿಸುತ್ತದೆ" - }, - "custom_self_destruct_snap_delay": { - "name": "ಕಸ್ಟಮ್ ಸ್ವಯಂ-ನಾಶ ಸ್ನ್ಯಾಪ್ ವಿಳಂಬ", - "description": "ಸ್ನ್ಯಾಪ್ ಕಳುಹಿಸುವಾಗ ಸ್ವಯಂ-ನಾಶ ಟೈಮರ್‌ಗಾಗಿ ಹೆಚ್ಚಿನ ಆಯ್ಕೆಗಳನ್ನು ನೀಡುತ್ತದೆ" - }, - "composer_console": { - "name": "ಸಂಯೋಜಕ ಕನ್ಸೋಲ್", - "description": "ಸಂಯೋಜಕದಲ್ಲಿ JavaScript ಕೋಡ್ ಅನ್ನು ಕಾರ್ಯಗತಗೊಳಿಸಲು ನಿಮಗೆ ಅನುಮತಿಸುತ್ತದೆ (arm64 ಮಾತ್ರ)" - }, - "composer_logs": { - "name": "ಸಂಯೋಜಕ ಲಾಗ್‌ಗಳು", - "description": "ಸಂಯೋಜಕದ ಕನ್ಸೋಲ್ ಲಾಗ್‌ಗಳನ್ನು PurrfectSnap ಗೆ ಮರುನಿರ್ದೇಶಿಸುತ್ತದೆ" - } - } - }, - "disable_bitmoji": { - "name": "ಬಿಟ್‌ಮೋಜಿ ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಿ", - "description": "ಸ್ನೇಹಿತರ ಪ್ರೊಫೈಲ್ ಬಿಟ್‌ಮೋಜಿಯನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸುತ್ತದೆ" - }, - "custom_emoji_font": { - "name": "ಕಸ್ಟಮ್ ಎಮೋಜಿ ಫಾಂಟ್", - "description": "ಕಸ್ಟಮ್ ಎಮೋಜಿ ಫಾಂಟ್ ಅನ್ನು ಬಳಸಲು ನಿಮಗೆ ಅನುಮತಿಸುತ್ತದೆ. .ttf ಫಾಂಟ್‌ಗಳೊಂದಿಗೆ ಮಾತ್ರ ಕಾರ್ಯನಿರ್ವಹಿಸುತ್ತದೆ" - }, - "custom_shared_library": { - "name": "ಕಸ್ಟಮ್ ಹಂಚಿದ ಗ್ರಂಥಾಲಯ", - "description": "Snapchat ಗೆ ಕಸ್ಟಮ್ ಹಂಚಿದ ಗ್ರಂಥಾಲಯವನ್ನು ಲೋಡ್ ಮಾಡುತ್ತದೆ. ಈ ವೈಶಿಷ್ಟ್ಯವು ಪರೀಕ್ಷಾ ಉದ್ದೇಶಗಳಿಗಾಗಿ ಮಾತ್ರ" - } - } - }, - "spoof": { - "name": "ವಂಚನೆ", - "description": "ನಿಮ್ಮ ಬಗ್ಗೆ ವಿವಿಧ ಮಾಹಿತಿಯನ್ನು ವಂಚಿಸಿ", - "properties": { - "play_store_installer_package_name": { - "name": "ಪ್ಲೇ ಸ್ಟೋರ್ ಸ್ಥಾಪಕ ಪ್ಯಾಕೇಜ್ ಹೆಸರು", - "description": "ಸ್ಥಾಪಕ ಪ್ಯಾಕೇಜ್ ಹೆಸರನ್ನು com.android.vending ಗೆ ಅತಿಕ್ರಮಿಸುತ್ತದೆ" - }, - "remove_vpn_transport_flag": { - "name": "VPN ಸಾರಿಗೆ ಫ್ಲ್ಯಾಗ್ ತೆಗೆದುಹಾಕಿ", - "description": "Snapchat VPN ಗಳನ್ನು ಪತ್ತೆಹಚ್ಚುವುದನ್ನು ತಡೆಯುತ್ತದೆ" - }, - "remove_mock_location_flag": { - "name": "ಅಣಕು ಸ್ಥಳ ಫ್ಲ್ಯಾಗ್ ತೆಗೆದುಹಾಕಿ", - "description": "Snapchat ಅಣಕು ಸ್ಥಳವನ್ನು ಪತ್ತೆಹಚ್ಚುವುದನ್ನು ತಡೆಯುತ್ತದೆ" - } - } - }, - "convert_message_locally": { - "name": "ಸಂದೇಶವನ್ನು ಸ್ಥಳೀಯವಾಗಿ ಪರಿವರ್ತಿಸಿ", - "description": "ಸ್ನ್ಯಾಪ್‌ಗಳನ್ನು ಸ್ಥಳೀಯವಾಗಿ ಚಾಟ್ ಬಾಹ್ಯ ಮಾಧ್ಯಮಕ್ಕೆ ಪರಿವರ್ತಿಸುತ್ತದೆ. ಇದು ಚಾಟ್ ಡೌನ್‌ಲೋಡ್ ಸಂದರ್ಭ ಮೆನುವಿನಲ್ಲಿ ಕಾಣಿಸಿಕೊಳ್ಳುತ್ತದೆ" - }, - "media_file_picker": { - "name": "ಮಾಧ್ಯಮ ಫೈಲ್ ಪಿಕ್ಕರ್", - "description": "ಗ್ಯಾಲರಿಯಿಂದ ಯಾವುದೇ ವೀಡಿಯೊ/ಆಡಿಯೋ ಫೈಲ್ ಅನ್ನು ಆಯ್ಕೆ ಮಾಡಲು ನಿಮಗೆ ಅನುಮತಿಸುತ್ತದೆ" - }, - "story_logger": { - "name": "ಕಥೆ ಲಾಗರ್", - "description": "ಸ್ನೇಹಿತರ ಕಥೆಗಳ ಇತಿಹಾಸವನ್ನು ಒದಗಿಸುತ್ತದೆ" - }, - "call_recorder": { - "name": "ಕರೆ ರೆಕಾರ್ಡರ್", - "description": "ಆಡಿಯೋ ಕರೆಗಳನ್ನು ಸ್ವಯಂಚಾಲಿತವಾಗಿ ರೆಕಾರ್ಡ್ ಮಾಡುತ್ತದೆ" - }, - "account_switcher": { - "name": "ಖಾತೆ ಬದಲಾಯಿಸುವವರು", - "description": "ಲಾಗ್ ಔಟ್ ಮಾಡದೆಯೇ ಖಾತೆಗಳ ನಡುವೆ ಬದಲಾಯಿಸಲು ನಿಮಗೆ ಅನುಮತಿಸುತ್ತದೆ\nಮೆನು ತೆರೆಯಲು ನಿಮ್ಮ ಬಿಟ್‌ಮೋಜಿ ಪ್ರೊಫೈಲ್ ಪಕ್ಕದಲ್ಲಿರುವ ಹುಡುಕಾಟ ಐಕಾನ್ ಮೇಲೆ ದೀರ್ಘವಾಗಿ ಒತ್ತಿರಿ\nಗಮನಿಸಿ: ಈ ವೈಶಿಷ್ಟ್ಯವು ಪ್ರಾಯೋಗಿಕವಾಗಿದೆ ಮತ್ತು ಭವಿಷ್ಯದಲ್ಲಿ ಬದಲಾಗುವ ಸಾಧ್ಯತೆಯಿದೆ", - "properties": { - "auto_backup_current_account": { - "name": "ಪ್ರಸ್ತುತ ಖಾತೆಯನ್ನು ಸ್ವಯಂ ಬ್ಯಾಕಪ್ ಮಾಡಿ", - "description": "ಲಾಗ್ ಔಟ್ ಮಾಡುವಾಗ ಅಥವಾ ಖಾತೆಗಳನ್ನು ಬದಲಾಯಿಸುವಾಗ ಪ್ರಸ್ತುತ ಖಾತೆಯನ್ನು ಸ್ವಯಂಚಾಲಿತವಾಗಿ ಬ್ಯಾಕಪ್ ಮಾಡುತ್ತದೆ" - } - } - }, - "better_transcript": { - "name": "ಉತ್ತಮ ಪ್ರತಿಲೇಖನ", - "description": "ಧ್ವನಿ ಟಿಪ್ಪಣಿ ಪ್ರತಿಲೇಖನವನ್ನು ಸುಧಾರಿಸುತ್ತದೆ", - "properties": { - "force_transcription": { - "name": "ಧ್ವನಿ ಟಿಪ್ಪಣಿ ಪ್ರತಿಲೇಖನವನ್ನು ಒತ್ತಾಯಿಸಿ", - "description": "ಎಲ್ಲಾ ಧ್ವನಿ ಟಿಪ್ಪಣಿಗಳನ್ನು ಪ್ರತಿಲೇಖನ ಮಾಡಲು ಅನುಮತಿಸುತ್ತದೆ" - }, - "preferred_transcription_lang": { - "name": "ಆದ್ಯತೆಯ ಪ್ರತಿಲೇಖನ ಭಾಷೆ", - "description": "ಧ್ವನಿ ಟಿಪ್ಪಣಿ ಪ್ರತಿಲೇಖನಕ್ಕಾಗಿ ಆದ್ಯತೆಯ ಭಾಷೆ (ಉದಾ. EN, ES, FR)" - }, - "notification_transcript": { - "name": "ಅಧಿಸೂಚನೆ ಪ್ರತಿಲೇಖನ", - "description": "ಅಧಿಸೂಚನೆಗಳಲ್ಲಿ ಧ್ವನಿ ಟಿಪ್ಪಣಿಗಳನ್ನು ಪ್ರತಿಲೇಖನ ಮಾಡುತ್ತದೆ\nಈ ವೈಶಿಷ್ಟ್ಯಕ್ಕೆ ಉತ್ತಮ ಅಧಿಸೂಚನೆಗಳಲ್ಲಿ ಚಾಟ್ ಮುನ್ನೋಟ ವೈಶಿಷ್ಟ್ಯವನ್ನು ಸಕ್ರಿಯಗೊಳಿಸುವ ಅಗತ್ಯವಿದೆ" - } - } - }, - "voice_note_auto_play": { - "name": "ಧ್ವನಿ ಟಿಪ್ಪಣಿ ಸ್ವಯಂ ಪ್ಲೇ", - "description": "ಪ್ರಸ್ತುತ ಧ್ವನಿ ಟಿಪ್ಪಣಿ ಮುಗಿದ ನಂತರ ಮುಂದಿನ ಧ್ವನಿ ಟಿಪ್ಪಣಿಯನ್ನು ಸ್ವಯಂಚಾಲಿತವಾಗಿ ಪ್ಲೇ ಮಾಡುತ್ತದೆ" - }, - "friend_notes": { - "name": "ಸ್ನೇಹಿತರ ಟಿಪ್ಪಣಿಗಳು", - "description": "ಸ್ನೇಹಿತರ ಪ್ರೊಫೈಲ್‌ಗಳಿಗೆ ಟಿಪ್ಪಣಿಗಳನ್ನು ಸೇರಿಸಲು ನಿಮಗೆ ಅನುಮತಿಸುತ್ತದೆ" - }, - "cof_experiments": { - "name": "COF ಪ್ರಯೋಗಗಳು", - "description": "ಬಿಡುಗಡೆಯಾಗದ/ಬೀಟಾ Snapchat ವೈಶಿಷ್ಟ್ಯಗಳನ್ನು ಸಕ್ರಿಯಗೊಳಿಸುತ್ತದೆ" - }, - "context_menu_fix": { - "name": "ಸಂದರ್ಭ ಮೆನು ಸರಿಪಡಿಸಿ", - "description": "ಸಾಧನವು ಆಫ್‌ಲೈನ್‌ನಲ್ಲಿದ್ದಾಗ ಸರಿಯಾಗಿ ಪ್ರದರ್ಶಿಸಲಾಗದ ಕಾರಣ ಸ್ನೇಹಿತರ ಫೀಡ್ ಮೆನುವನ್ನು ಸರಿಪಡಿಸಲು ಪ್ರಯತ್ನಿಸಿ" - }, - "app_lock": { - "name": "ಅಪ್ಲಿಕೇಶನ್ ಲಾಕ್", - "description": "ಪಾಸ್‌ಕೋಡ್ ಇಲ್ಲದೆ Snapchat ಗೆ ಪ್ರವೇಶವನ್ನು ತಡೆಯುತ್ತದೆ", - "properties": { - "lock_on_resume": { - "name": "ಪುನರಾರಂಭದಲ್ಲಿ ಲಾಕ್ ಮಾಡಿ", - "description": "ಅಪ್ಲಿಕೇಶನ್ ಅನ್ನು ಮರು ತೆರೆದಾಗ ಅದನ್ನು ಲಾಕ್ ಮಾಡುತ್ತದೆ" - } - } - }, - "infinite_story_boost": { - "name": "ಅನಂತ ಕಥೆ ವರ್ಧಕ", - "description": "ಕಥೆ ವರ್ಧಕ ಮಿತಿ ವಿಳಂಬವನ್ನು ಬೈಪಾಸ್ ಮಾಡಿ" - }, - "meo_passcode_bypass": { - "name": "ನನ್ನ ಕಣ್ಣುಗಳು ಮಾತ್ರ ಪಾಸ್‌ಕೋಡ್ ಬೈಪಾಸ್", - "description": "ನನ್ನ ಕಣ್ಣುಗಳು ಮಾತ್ರ ಪಾಸ್‌ಕೋಡ್ ಅನ್ನು ಬೈಪಾಸ್ ಮಾಡಿ\nಪಾಸ್‌ಕೋಡ್ ಅನ್ನು ಮೊದಲು ಸರಿಯಾಗಿ ನಮೂದಿಸಿದ್ದರೆ ಮಾತ್ರ ಇದು ಕಾರ್ಯನಿರ್ವಹಿಸುತ್ತದೆ" - }, - "no_friend_score_delay": { - "name": "ಯಾವುದೇ ಸ್ನೇಹಿತರ ಅಂಕ ವಿಳಂಬವಿಲ್ಲ", - "description": "ಸ್ನೇಹಿತರ ಅಂಕವನ್ನು ವೀಕ್ಷಿಸುವಾಗ ವಿಳಂಬವನ್ನು ತೆಗೆದುಹಾಕುತ್ತದೆ" - }, - "best_friend_pinning": { - "name": "ಅತ್ಯುತ್ತಮ ಸ್ನೇಹಿತರ ಪಿನ್ನಿಂಗ್", - "description": "ನಿಮ್ಮ ನಂಬರ್ ಒನ್ ಅತ್ಯುತ್ತಮ ಸ್ನೇಹಿತನಾಗಿ ಸ್ನೇಹಿತನನ್ನು ಪಿನ್ ಮಾಡಲು ನಿಮಗೆ ಅನುಮತಿಸುತ್ತದೆ. ಗಮನಿಸಿ: ನಿಮ್ಮ ಪಿನ್ ಮಾಡಿದ ಅತ್ಯುತ್ತಮ ಸ್ನೇಹಿತನನ್ನು ನೀವು ಮಾತ್ರ ನೋಡಬಹುದು" - }, - "e2ee": { - "name": "ಎಂಡ್-ಟು-ಎಂಡ್ ಎನ್‌ಕ್ರಿಪ್ಶನ್", - "description": "ಹಂಚಿದ ರಹಸ್ಯ ಕೀಯನ್ನು ಬಳಸಿಕೊಂಡು AES ನೊಂದಿಗೆ ನಿಮ್ಮ ಸಂದೇಶಗಳನ್ನು ಎನ್‌ಕ್ರಿಪ್ಟ್ ಮಾಡುತ್ತದೆ\nನಿಮ್ಮ ಕೀಯನ್ನು ಎಲ್ಲೋ ಸುರಕ್ಷಿತವಾಗಿ ಉಳಿಸಲು ಖಚಿತಪಡಿಸಿಕೊಳ್ಳಿ!", - "properties": { - "encrypted_message_indicator": { - "name": "ಎನ್‌ಕ್ರಿಪ್ಟ್ ಮಾಡಿದ ಸಂದೇಶ ಸೂಚಕ", - "description": "ಎನ್‌ಕ್ರಿಪ್ಟ್ ಮಾಡಿದ ಸಂದೇಶಗಳ ಪಕ್ಕದಲ್ಲಿ 🔒 ಎಮೋಜಿಯನ್ನು ಸೇರಿಸುತ್ತದೆ" - }, - "force_message_encryption": { - "name": "ಸಂದೇಶ ಎನ್‌ಕ್ರಿಪ್ಶನ್ ಅನ್ನು ಒತ್ತಾಯಿಸಿ", - "description": "ಬಹು ಸಂಭಾಷಣೆಗಳನ್ನು ಆಯ್ಕೆಮಾಡಿದಾಗ ಮಾತ್ರ E2E ಎನ್‌ಕ್ರಿಪ್ಶನ್ ಸಕ್ರಿಯಗೊಳಿಸದ ಜನರಿಗೆ ಎನ್‌ಕ್ರಿಪ್ಟ್ ಮಾಡಿದ ಸಂದೇಶಗಳನ್ನು ಕಳುಹಿಸುವುದನ್ನು ತಡೆಯುತ್ತದೆ" - } - } - }, - "add_friend_source_spoof": { - "name": "ಸ್ನೇಹಿತರ ಸೇರಿಸು ಮೂಲ ವಂಚನೆ", - "description": "ಸ್ನೇಹಿತರ ವಿನಂತಿಯ ಮೂಲವನ್ನು ವಂಚಿಸುತ್ತದೆ" - }, - "hidden_snapchat_plus_features": { - "name": "ಮರೆಮಾಡಿದ Snapchat Plus ವೈಶಿಷ್ಟ್ಯಗಳು", - "description": "ಬಿಡುಗಡೆಯಾಗದ/ಬೀಟಾ Snapchat Plus ವೈಶಿಷ್ಟ್ಯಗಳನ್ನು ಸಕ್ರಿಯಗೊಳಿಸುತ್ತದೆ\nಹಳೆಯ Snapchat ಆವೃತ್ತಿಗಳಲ್ಲಿ ಕಾರ್ಯನಿರ್ವಹಿಸದಿರಬಹುದು" - }, - "custom_streaks_expiration_format": { - "name": "ಕಸ್ಟಮ್ ಸ್ಟ್ರೀಕ್ಸ್ ಮುಕ್ತಾಯ ಸ್ವರೂಪ", - "description": "ಸ್ಟ್ರೀಕ್ಸ್ ಮುಕ್ತಾಯ ಸ್ವರೂಪವನ್ನು ಕಸ್ಟಮೈಸ್ ಮಾಡುತ್ತದೆ\n\nಲಭ್ಯವಿರುವ ವೇರಿಯಬಲ್‌ಗಳು:\n - %c: ಸ್ಟ್ರೀಕ್ಸ್ ಎಣಿಕೆ\n - %e: ಮರಳು ಗಡಿಯಾರ ಎಮೋಜಿ\n - %d: ದಿನಗಳು\n - %h: ಗಂಟೆಗಳು\n - %m: ನಿಮಿಷಗಳು\n - %s: ಸೆಕೆಂಡುಗಳು\n - %w: ಉಳಿದ ಸಮಯ" - }, - "prevent_forced_logout": { - "name": "ಬಲವಂತದ ಲಾಗ್‌ಔಟ್ ತಡೆಯಿರಿ", - "description": "ನೀವು ಇನ್ನೊಂದು ಸಾಧನದಲ್ಲಿ ಲಾಗಿನ್ ಮಾಡಿದಾಗ Snapchat ನಿಮ್ಮನ್ನು ಲಾಗ್ ಔಟ್ ಮಾಡುವುದನ್ನು ತಡೆಯುತ್ತದೆ" - }, - "snapscore_changes": { - "name": "ಸ್ನ್ಯಾಪ್‌ಸ್ಕೋರ್ ಬದಲಾವಣೆಗಳು", - "description": "ಸ್ನೇಹಿತರ ಸ್ನ್ಯಾಪ್‌ಸ್ಕೋರ್‌ನಲ್ಲಿನ ಬದಲಾವಣೆಗಳನ್ನು ಟ್ರ್ಯಾಕ್ ಮಾಡುತ್ತದೆ\nಈ ವೈಶಿಷ್ಟ್ಯವನ್ನು Snapchat ನ ಹೊಸ ಆವೃತ್ತಿಗಳಲ್ಲಿ ಮಾತ್ರ ಬಳಸಿ" - } - } - }, - "scripting": { - "name": "ಸ್ಕ್ರಿಪ್ಟಿಂಗ್", - "description": "PurrfectSnap ಅನ್ನು ವಿಸ್ತರಿಸಲು ಕಸ್ಟಮ್ ಸ್ಕ್ರಿಪ್ಟ್‌ಗಳನ್ನು ಚಲಾಯಿಸಿ", - "properties": { - "developer_mode": { - "name": "ಡೆವಲಪರ್ ಮೋಡ್", - "description": "Snapchat ನ UI ನಲ್ಲಿ ಡೀಬಗ್ ಮಾಹಿತಿಯನ್ನು ತೋರಿಸುತ್ತದೆ" - }, - "module_folder": { - "name": "ಮಾಡ್ಯೂಲ್ ಫೋಲ್ಡರ್", - "description": "ಸ್ಕ್ರಿಪ್ಟ್‌ಗಳು ಇರುವ ಫೋಲ್ಡರ್" - }, - "auto_reload": { - "name": "ಸ್ವಯಂ ಮರುಲೋಡ್", - "description": "ಅವು ಬದಲಾದಾಗ ಸ್ಕ್ರಿಪ್ಟ್‌ಗಳನ್ನು ಸ್ವಯಂಚಾಲಿತವಾಗಿ ಮರುಲೋಡ್ ಮಾಡುತ್ತದೆ" - }, - "integrated_ui": { - "name": "ಸಂಯೋಜಿತ UI", - "description": "ಸ್ಕ್ರಿಪ್ಟ್‌ಗಳು Snapchat ಗೆ ಕಸ್ಟಮ್ UI ಘಟಕಗಳನ್ನು ಸೇರಿಸಲು ಅನುಮತಿಸುತ್ತದೆ" - }, - "disable_log_anonymization": { - "name": "ಲಾಗ್ ಅನಾಮಧೇಯತೆಯನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಿ", - "description": "ಲಾಗ್‌ಗಳ ಅನಾಮಧೇಯತೆಯನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸುತ್ತದೆ" - }, - "disable_optimization": { - "name": "ಆಪ್ಟಿಮೈಸೇಶನ್ ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಿ", - "description": "ಸ್ಕ್ರಿಪ್ಟ್‌ಗಳ ಆಪ್ಟಿಮೈಸೇಶನ್ ಅನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸುತ್ತದೆ. ಇದು ಕಾರ್ಯಕ್ಷಮತೆಯ ಸಮಸ್ಯೆಗಳನ್ನು ಉಂಟುಮಾಡಬಹುದು." - } - } - }, - "friend_tracker": { - "name": "ಸ್ನೇಹಿತ ಟ್ರ್ಯಾಕರ್", - "description": "Snapchat ನಲ್ಲಿ ಸ್ನೇಹಿತರ ಚಟುವಟಿಕೆಯನ್ನು ದಾಖಲಿಸುತ್ತದೆ", - "properties": { - "record_messaging_events": { - "name": "ಸಂದೇಶ ಕಳುಹಿಸುವ ಘಟನೆಗಳನ್ನು ದಾಖಲಿಸಿ", - "description": "ಸ್ನ್ಯಾಪ್ ತೆರೆಯುವುದು, ಸಂದೇಶವನ್ನು ಓದುವುದು ಮುಂತಾದ ಸಂದೇಶ ಕಳುಹಿಸುವ ಘಟನೆಗಳನ್ನು ದಾಖಲಿಸುತ್ತದೆ." - }, - "allow_running_in_background": { - "name": "ಹಿನ್ನೆಲೆಯಲ್ಲಿ ಚಾಲನೆಯಲ್ಲಿರಲು ಅನುಮತಿಸಿ", - "description": "ಟ್ರ್ಯಾಕರ್ ಹಿನ್ನೆಲೆಯಲ್ಲಿ ಚಲಾಯಿಸಲು ಅನುಮತಿಸುತ್ತದೆ. ಗಮನಿಸಿ: ಇದು ನಿಮ್ಮ ಬ್ಯಾಟರಿಯನ್ನು ಗಮನಾರ್ಹವಾಗಿ ಹರಿಸುತ್ತದೆ" - }, - "auto_purge": { - "name": "ಸ್ವಯಂ ಶುದ್ಧೀಕರಣ", - "description": "ನಿರ್ದಿಷ್ಟ ಸಮಯಕ್ಕಿಂತ ಹಳೆಯದಾದ ಸಂಗ್ರಹಿಸಲಾದ ಘಟನೆಗಳನ್ನು ಸ್ವಯಂಚಾಲಿತವಾಗಿ ಅಳಿಸುತ್ತದೆ" - } - } - } - }, - "options": { - "app_appearance": { - "always_light": "ಯಾವಾಗಲೂ ಬೆಳಕು", - "always_dark": "ಯಾವಾಗಲೂ ಕತ್ತಲೆ" - }, - "friend_feed_menu_buttons": { - "auto_download": "⬇️ ಸ್ವಯಂ ಡೌನ್‌ಲೋಡ್", - "auto_save": "💬 ಸಂದೇಶಗಳನ್ನು ಸ್ವಯಂ ಉಳಿಸಿ", - "unsaveable_messages": "⬇️ ಉಳಿಸಲಾಗದ ಸಂದೇಶಗಳು", - "auto_open_snaps": "📸 ಸ್ನ್ಯಾಪ್‌ಗಳನ್ನು ಸ್ವಯಂ ತೆರೆಯಿರಿ", - "stealth": "👻 ಸ್ಟೆಲ್ತ್ ಮೋಡ್", - "mark_snaps_as_seen": "👀 ಸ್ನ್ಯಾಪ್‌ಗಳನ್ನು ನೋಡಿದಂತೆ ಗುರುತಿಸಿ", - "mark_stories_as_seen_locally": "👀 ಕಥೆಗಳನ್ನು ಸ್ಥಳೀಯವಾಗಿ ನೋಡಿದಂತೆ ಗುರುತಿಸಿ", - "conversation_info": "🧑‍🤝‍🧑 ಸಂಭಾಷಣೆ ಮಾಹಿತಿ", - "e2e_encryption": "🔒 E2E ಎನ್‌ಕ್ರಿಪ್ಶನ್ ಬಳಸಿ" - }, - "path_format": { - "create_author_folder": "ಪ್ರತಿ ಲೇಖಕರಿಗೆ ಫೋಲ್ಡರ್ ರಚಿಸಿ", - "create_source_folder": "ಪ್ರತಿ ಮಾಧ್ಯಮ ಮೂಲ ಪ್ರಕಾರಕ್ಕೆ ಫೋಲ್ಡರ್ ರಚಿಸಿ", - "append_hash": "ಫೈಲ್ ಹೆಸರಿಗೆ ಒಂದು ಅನನ್ಯ ಹ್ಯಾಶ್ ಸೇರಿಸಿ", - "append_source": "ಫೈಲ್ ಹೆಸರಿಗೆ ಮಾಧ್ಯಮ ಮೂಲವನ್ನು ಸೇರಿಸಿ", - "append_username": "ಫೈಲ್ ಹೆಸರಿಗೆ ಬಳಕೆದಾರಹೆಸರನ್ನು ಸೇರಿಸಿ", - "append_date_time": "ಫೈಲ್ ಹೆಸರಿಗೆ ದಿನಾಂಕ ಮತ್ತು ಸಮಯವನ್ನು ಸೇರಿಸಿ" - }, - "auto_download_sources": { - "friend_snaps": "ಸ್ನೇಹಿತರ ಸ್ನ್ಯಾಪ್‌ಗಳು", - "friend_stories": "ಸ್ನೇಹಿತರ ಕಥೆಗಳು", - "public_stories": "ಸಾರ್ವಜನಿಕ ಕಥೆಗಳು", - "spotlight": "ಸ್ಪಾಟ್‌ಲೈಟ್" - }, - "logging": { - "started": "ಪ್ರಾರಂಭವಾಯಿತು", - "success": "ಯಶಸ್ಸು", - "progress": "ಪ್ರಗತಿ", - "failure": "ವೈಫಲ್ಯ" - }, - "notifications": { - "chat_screenshot": "ಸ್ಕ್ರೀನ್‌ಶಾಟ್", - "chat_screen_record": "ಸ್ಕ್ರೀನ್ ರೆಕಾರ್ಡ್", - "snap_replay": "ಸ್ನ್ಯಾಪ್ ಮರುಪಂದ್ಯ", - "camera_roll_save": "ಕ್ಯಾಮೆರಾ ರೋಲ್‌ಗೆ ಉಳಿಸಿ", - "chat": "ಚಾಟ್", - "chat_reply": "ಚಾಟ್ ಪ್ರತ್ಯುತ್ತರ", - "snap": "ಸ್ನ್ಯಾಪ್", - "typing": "ಟೈಪ್ ಮಾಡುತ್ತಿದೆ", - "stories": "ಕಥೆಗಳು", - "speaking": "ಮಾತನಾಡುತ್ತಿದೆ", - "chat_reaction": "DM ಪ್ರತಿಕ್ರಿಯೆ", - "group_chat_reaction": "ಗುಂಪು ಪ್ರತಿಕ್ರಿಯೆ", - "initiate_audio": "ಒಳಬರುವ ಆಡಿಯೋ ಕರೆ", - "abandon_audio": "ಕಳೆದುಹೋದ ಆಡಿಯೋ ಕರೆ", - "initiate_video": "ಒಳಬರುವ ವೀಡಿಯೊ ಕರೆ", - "abandon_video": "ಕಳೆದುಹೋದ ವೀಡಿಯೊ ಕರೆ", - "map_live_location": "ನಕ್ಷೆ ಲೈವ್ ಸ್ಥಳ" - }, - "gallery_media_send_override": { - "always_ask": "ಯಾವಾಗಲೂ ಕೇಳಿ", - "ORIGINAL": "ಮೂಲ ಮಾಧ್ಯಮ", - "NOTE": "ಆಡಿಯೋ ಟಿಪ್ಪಣಿ", - "SNAP": "ಸ್ನ್ಯಾಪ್", - "SAVEABLE_SNAP": "ಉಳಿಸಬಹುದಾದ ಸ್ನ್ಯಾಪ್" - }, - "strip_media_metadata": { - "hide_caption_text": "ಶೀರ್ಷಿಕೆ ಪಠ್ಯವನ್ನು ಮರೆಮಾಡಿ", - "hide_snap_filters": "ಸ್ನ್ಯಾಪ್ ಫಿಲ್ಟರ್‌ಗಳನ್ನು ಮರೆಮಾಡಿ", - "hide_extras": "ಹೆಚ್ಚುವರಿಗಳನ್ನು ಮರೆಮಾಡಿ (ಉದಾ. ಉಲ್ಲೇಖಗಳು)", - "remove_audio_note_duration": "ಆಡಿಯೋ ಟಿಪ್ಪಣಿ ಅವಧಿಯನ್ನು ತೆಗೆದುಹಾಕಿ", - "remove_audio_note_transcript_capability": "ಆಡಿಯೋ ಟಿಪ್ಪಣಿ ಪ್ರತಿಲೇಖನ ಸಾಮರ್ಥ್ಯವನ್ನು ತೆಗೆದುಹಾಕಿ" - }, - "hide_ui_components": { - "hide_profile_call_buttons": "ಪ್ರೊಫೈಲ್ ಕರೆ ಬಟನ್‌ಗಳನ್ನು ತೆಗೆದುಹಾಕಿ", - "hide_chat_call_buttons": "ಚಾಟ್ ಕರೆ ಬಟನ್‌ಗಳನ್ನು ತೆಗೆದುಹಾಕಿ", - "hide_live_location_share_button": "ಲೈವ್ ಸ್ಥಳ ಹಂಚಿಕೆ ಬಟನ್ ತೆಗೆದುಹಾಕಿ", - "hide_stickers_button": "ಸ್ಟಿಕ್ಕರ್‌ಗಳ ಬಟನ್ ತೆಗೆದುಹಾಕಿ", - "hide_voice_record_button": "ಧ್ವನಿ ರೆಕಾರ್ಡ್ ಬಟನ್ ತೆಗೆದುಹಾಕಿ", - "hide_unread_chat_hint": "ಓದದ ಚಾಟ್ ಸುಳಿವನ್ನು ತೆಗೆದುಹಾಕಿ", - "hide_post_to_story_buttons": "ಸ್ನ್ಯಾಪ್ ಕಳುಹಿಸುವ ಮೊದಲು ಕಥೆಗೆ ಪೋಸ್ಟ್ ಬಟನ್‌ಗಳನ್ನು ತೆಗೆದುಹಾಕಿ", - "hide_billboard_prompt": "ಸ್ನೇಹಿತರ ಫೀಡ್‌ನಲ್ಲಿ ಬಿಲ್ಬೋರ್ಡ್ ಪ್ರಾಂಪ್ಟ್ ತೆಗೆದುಹಾಕಿ", - "hide_snapchat_plus_gift_reminders": "ಸಂಭಾಷಣೆಗಳಲ್ಲಿ Snapchat Plus ಉಡುಗೊರೆ ಜ್ಞಾಪನೆಗಳನ್ನು ತೆಗೆದುಹಾಕಿ", - "hide_map_reactions": "ನಕ್ಷೆ ಪ್ರತಿಕ್ರಿಯೆಗಳನ್ನು ತೆಗೆದುಹಾಕಿ" - }, - "hide_story_suggestions": { - "hide_suggested_friend_stories": "ಸೂಚಿಸಿದ ಸ್ನೇಹಿತರ ಕಥೆಗಳನ್ನು ಮರೆಮಾಡಿ", - "hide_my_stories": "ನನ್ನ ಕಥೆಗಳನ್ನು ಮರೆಮಾಡಿ" - }, - "home_tab": { - "map": "ನಕ್ಷೆ", - "chat": "ಚಾಟ್", - "camera": "ಕ್ಯಾಮೆರಾ", - "discover": "ಅನ್ವೇಷಿಸಿ", - "spotlight": "ಸ್ಪಾಟ್‌ಲೈಟ್" - }, - "add_friend_source_spoof": { - "added_by_username": "ಬಳಕೆದಾರಹೆಸರಿನಿಂದ", - "added_by_mention": "ಉಲ್ಲೇಖದಿಂದ", - "added_by_group_chat": "ಗುಂಪು ಚಾಟ್‌ನಿಂದ", - "added_by_qr_code": "QR ಕೋಡ್‌ನಿಂದ", - "added_by_community": "ಸಮುದಾಯದಿಂದ", - "added_by_quick_add": "ತ್ವರಿತ ಸೇರಿಸುವಿಕೆಯಿಂದ (ನಿಷೇಧಕ್ಕೊಳಗಾಗುವ ಹೆಚ್ಚಿನ ಅಪಾಯ)" - }, - "bypass_video_length_restriction": { - "single": "ಏಕ ಮಾಧ್ಯಮ", - "split": "ವಿಭಜಿತ ಮಾಧ್ಯಮ" - }, - "old_bitmoji_selfie": { - "2d": "2D ಬಿಟ್‌ಮೋಜಿ", - "3d": "3D ಬಿಟ್‌ಮೋಜಿ" - }, - "disable_confirmation_dialogs": { - "erase_message": "ಸಂದೇಶವನ್ನು ಅಳಿಸಿ", - "remove_friend": "ಸ್ನೇಹಿತನನ್ನು ತೆಗೆದುಹಾಕಿ", - "block_friend": "ಸ್ನೇಹಿತನನ್ನು ನಿರ್ಬಂಧಿಸಿ", - "ignore_friend": "ಸ್ನೇಹಿತನನ್ನು ನಿರ್ಲಕ್ಷಿಸಿ", - "hide_friend": "ಸ್ನೇಹಿತನನ್ನು ಮರೆಮಾಡಿ", - "hide_conversation": "ಸಂಭಾಷಣೆಯನ್ನು ಮರೆಮಾಡಿ", - "clear_conversation": "ಸ್ನೇಹಿತರ ಫೀಡ್‌ನಿಂದ ಸಂಭಾಷಣೆಯನ್ನು ತೆರವುಗೊಳಿಸಿ" - }, - "auto_reload": { - "snapchat_only": "Snapchat ಮಾತ್ರ", - "all": "ಎಲ್ಲಾ (Snapchat + PurrfectSnap)" - }, - "edit_text_override": { - "multi_line_chat_input": "ಬಹು ಸಾಲಿನ ಚಾಟ್ ಇನ್‌ಪುಟ್", - "bypass_text_input_limit": "ಪಠ್ಯ ಇನ್‌ಪುಟ್ ಮಿತಿಯನ್ನು ಬೈಪಾಸ್ ಮಾಡಿ" - }, - "auto_purge": { - "never": "ಎಂದಿಗೂ ಇಲ್ಲ", - "1_hour": "1 ಗಂಟೆ", - "3_hours": "3 ಗಂಟೆಗಳು", - "6_hours": "6 ಗಂಟೆಗಳು", - "12_hours": "12 ಗಂಟೆಗಳು", - "1_day": "1 ದಿನ", - "3_days": "3 ದಿನಗಳು", - "1_week": "1 ವಾರ", - "2_weeks": "2 ವಾರಗಳು", - "1_month": "1 ತಿಂಗಳು", - "3_months": "3 ತಿಂಗಳುಗಳು", - "6_months": "6 ತಿಂಗಳುಗಳು" - }, - "disable_story_sections": { - "friends": "ಸ್ನೇಹಿತರು", - "suggested_stories": "ಸೂಚಿಸಿದ ಕಥೆಗಳು", - "following": "ಅನುಸರಿಸಲಾಗುತ್ತಿದೆ", - "discover": "ಅನ್ವೇಷಿಸಿ" - }, - "disable_cameras": { - "front": "ಮುಂಭಾಗದ ಕ್ಯಾಮೆರಾ", - "back": "ಹಿಂದಿನ ಕ್ಯಾಮೆರಾ" - }, - "disable_permission_requests": { - "notifications": "ಅಧಿಸೂಚನೆಗಳು", - "read_media_images": "ಮಾಧ್ಯಮ ಚಿತ್ರಗಳನ್ನು ಓದಿ", - "read_media_video": "ಮಾಧ್ಯಮ ವೀಡಿಯೊವನ್ನು ಓದಿ", - "camera": "ಕ್ಯಾಮೆರಾ", - "microphone": "ಮೈಕ್ರೋಫೋನ್", - "location": "ಸ್ಥಳ", - "read_contacts": "ಸಂಪರ್ಕಗಳನ್ನು ಓದಿ", - "nearby_devices": "ಹತ್ತಿರದ ಸಾಧನಗಳು", - "phone_calls": "ಫೋನ್ ಕರೆಗಳು" - }, - "message_indicators": { - "encryption_indicator": "ನಿಮಗೆ ಮಾತ್ರ ಕಳುಹಿಸಲಾದ ಸಂದೇಶಗಳ ಪಕ್ಕದಲ್ಲಿ 🔒 ಐಕಾನ್ ಅನ್ನು ಸೇರಿಸುತ್ತದೆ", - "platform_indicator": "ಯಾವ ಪ್ಲಾಟ್‌ಫಾರ್ಮ್‌ನಿಂದ ಮಾಧ್ಯಮವನ್ನು ಕಳುಹಿಸಲಾಗಿದೆ ಎಂಬುದರ ಪ್ಲಾಟ್‌ಫಾರ್ಮ್ ಐಕಾನ್ ಅನ್ನು ಸೇರಿಸುತ್ತದೆ (ಉದಾ. Android, iOS, Web)", - "location_indicator": "ಸ್ಥಳವನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಿದಾಗ ಕಳುಹಿಸಲಾದ ಸ್ನ್ಯಾಪ್‌ಗಳಿಗೆ 📍 ಐಕಾನ್ ಅನ್ನು ಸೇರಿಸುತ್ತದೆ", - "ovf_editor_indicator": "OVF ಸಂಪಾದಕವನ್ನು ಬಳಸಿಕೊಂಡು ಸ್ನ್ಯಾಪ್ ಕಳುಹಿಸಲಾಗಿದೆಯೇ ಎಂದು ಸೂಚಿಸುತ್ತದೆ", - "director_mode_indicator": "ನಿರ್ದೇಶಕ ಮೋಡ್ ಬಳಸಿ ಕಳುಹಿಸಲಾದ ಸ್ನ್ಯಾಪ್‌ಗಳಿಗೆ 🎬 ಐಕಾನ್ ಅನ್ನು ಸೇರಿಸುತ್ತದೆ, ಇದನ್ನು ಗ್ಯಾಲರಿ ಚಿತ್ರಗಳನ್ನು ಸ್ನ್ಯಾಪ್‌ಗಳಾಗಿ ಕಳುಹಿಸಲು ಬಳಸಬಹುದು" - }, - "auto_mark_as_read": { - "conversation_read": "ಸಂದೇಶ ಕಳುಹಿಸುವಾಗ ಸಂಭಾಷಣೆಯನ್ನು ಓದಿದಂತೆ ಗುರುತಿಸಿ", - "snap_reply": "ಸ್ನ್ಯಾಪ್‌ಗಳಿಗೆ ಪ್ರತ್ಯುತ್ತರಿಸುವಾಗ ಅವುಗಳನ್ನು ಓದಿದಂತೆ ಗುರುತಿಸಿ", - "save_snap_in_chat": "ಸ್ಟೆಲ್ತ್ ಮೋಡ್‌ನಲ್ಲಿದ್ದಾಗ ಚಾಟ್‌ನಲ್ಲಿ ಸ್ನ್ಯಾಪ್‌ಗಳನ್ನು ಉಳಿಸುವಾಗ ಅವುಗಳನ್ನು ಓದಿದಂತೆ ಗುರುತಿಸಿ" - }, - "friend_mutation_notifier": { - "remove_friend": "ಯಾರಾದರೂ ನಿಮ್ಮನ್ನು ಸ್ನೇಹಿತರಾಗಿ ತೆಗೆದುಹಾಕಿದಾಗ ಸೂಚಿಸಿ", - "birthday_changes": "ಯಾರಾದರೂ ತಮ್ಮ ಜನ್ಮದಿನವನ್ನು ಬದಲಾಯಿಸಿದಾಗ ಸೂಚಿಸಿ", - "bitmoji_selfie_changes": "ಯಾರಾದರೂ ತಮ್ಮ ಬಿಟ್‌ಮೋಜಿ ಸೆಲ್ಫಿಯನ್ನು ಬದಲಾಯಿಸಿದಾಗ ಸೂಚಿಸಿ", - "bitmoji_avatar_changes": "ಯಾರಾದರೂ ತಮ್ಮ ಬಿಟ್‌ಮೋಜಿ ಅವತಾರವನ್ನು ಬದಲಾಯಿಸಿದಾಗ ಸೂಚಿಸಿ", - "bitmoji_background_changes": "ಯಾರಾದರೂ ತಮ್ಮ ಬಿಟ್‌ಮೋಜಿ ಹಿನ್ನೆಲೆಯನ್ನು ಬದಲಾಯಿಸಿದಾಗ ಸೂಚಿಸಿ", - "bitmoji_scene_changes": "ಯಾರಾದರೂ ತಮ್ಮ ಬಿಟ್‌ಮೋಜಿ ದೃಶ್ಯವನ್ನು ಬದಲಾಯಿಸಿದಾಗ ಸೂಚಿಸಿ" - }, - "snapchat_plus": { - "not_subscribed": "ಚಂದಾದಾರರಾಗಿಲ್ಲ", - "basic": "ಮೂಲ", - "ad_free": "ಜಾಹೀರಾತು ಮುಕ್ತ" - }, - "double_tap_chat_action": { - "like_message": "ಸಂದೇಶವನ್ನು ಇಷ್ಟಪಡಿ", - "copy_text": "ಪಠ್ಯವನ್ನು ಕ್ಲಿಪ್‌ಬೋರ್ಡ್‌ಗೆ ನಕಲಿಸಿ", - "delete_message": "ಸಂದೇಶವನ್ನು ಅಳಿಸಿ", - "mark_as_read": "ಓದಿದಂತೆ ಗುರುತಿಸಿ", - "custom_emoji_reaction": "ಕಸ್ಟಮ್ ಎಮೋಜಿ ಪ್ರತಿಕ್ರಿಯೆ" - }, - "startup_default_camera": { - "front": "ಮುಂಭಾಗದ ಕ್ಯಾಮೆರಾ", - "back": "ಹಿಂದಿನ ಕ್ಯಾಮೆರಾ" - } - } - }, - "friend_menu_option": { - "mark_snaps_as_seen": "ಸ್ನ್ಯಾಪ್‌ಗಳನ್ನು ನೋಡಿದಂತೆ ಗುರುತಿಸಿ", - "mark_stories_as_seen_locally": "ಕಥೆಗಳನ್ನು ಸ್ಥಳೀಯವಾಗಿ ನೋಡಿದಂತೆ ಗುರುತಿಸಿ", - "preview": "ಮುನ್ನೋಟ", - "stealth_mode": "ಸ್ಟೆಲ್ತ್ ಮೋಡ್", - "auto_download_blacklist": "ಸ್ವಯಂ ಡೌನ್‌ಲೋಡ್ ಕಪ್ಪುಪಟ್ಟಿ", - "anti_auto_save": "ವಿರೋಧಿ ಸ್ವಯಂ ಉಳಿಸು" - }, - "content_type": { - "CHAT": "ಚಾಟ್", - "SNAP": "ಸ್ನ್ಯಾಪ್", - "EXTERNAL_MEDIA": "ಬಾಹ್ಯ ಮಾಧ್ಯಮ", - "NOTE": "ಆಡಿಯೋ ಟಿಪ್ಪಣಿ", - "STICKER": "ಸ್ಟಿಕ್ಕರ್", - "SHARE": "ಹಂಚಿಕೊಳ್ಳಿ", - "STATUS": "ಸ್ಥಿತಿ", - "LOCATION": "ಸ್ಥಳ", - "STATUS_SAVE_TO_CAMERA_ROLL": "ಕ್ಯಾಮೆರಾ ರೋಲ್‌ಗೆ ಉಳಿಸಲಾಗಿದೆ", - "STATUS_CONVERSATION_CAPTURE_SCREENSHOT": "ಸ್ಕ್ರೀನ್‌ಶಾಟ್", - "STATUS_CONVERSATION_CAPTURE_RECORD": "ಸ್ಕ್ರೀನ್ ರೆಕಾರ್ಡ್", - "STATUS_CALL_MISSED_VIDEO": "ತಪ್ಪಿದ ವೀಡಿಯೊ ಕರೆ", - "STATUS_CALL_MISSED_AUDIO": "ತಪ್ಪಿದ ಆಡಿಯೋ ಕರೆ", - "LIVE_LOCATION_SHARE": "ಲೈವ್ ಸ್ಥಳ ಹಂಚಿಕೊಳ್ಳಿ", - "CREATIVE_TOOL_ITEM": "ಸೃಜನಾತ್ಮಕ ಉಪಕರಣ ಐಟಂ", - "FAMILY_CENTER_INVITE": "ಕುಟುಂಬ ಕೇಂದ್ರ ಆಹ್ವಾನ", - "FAMILY_CENTER_ACCEPT": "ಕುಟುಂಬ ಕೇಂದ್ರವನ್ನು ಸ್ವೀಕರಿಸಿ", - "FAMILY_CENTER_LEAVE": "ಕುಟುಂಬ ಕೇಂದ್ರವನ್ನು ಬಿಡಿ", - "STATUS_PLUS_GIFT": "ಸ್ಥಿತಿ ಪ್ಲಸ್ ಉಡುಗೊರೆ", - "TINY_SNAP": "ಸಣ್ಣ ಸ್ನ್ಯಾಪ್", - "STATUS_COUNTDOWN": "ಕೌಂಟ್‌ಡೌನ್", - "MAP_REACTION": "ನಕ್ಷೆ ಪ್ರತಿಕ್ರಿಯೆ" - }, - "media_download_source": { - "none": "ಯಾವುದೂ ಇಲ್ಲ", - "pending": "ಬಾಕಿ", - "chat_media": "ಚಾಟ್ ಮಾಧ್ಯಮ", - "story": "ಕಥೆ", - "public_story": "ಸಾರ್ವಜನಿಕ ಕಥೆ", - "spotlight": "ಸ್ಪಾಟ್‌ಲೈಟ್", - "profile_picture": "ಪ್ರೊಫೈಲ್ ಚಿತ್ರ", - "story_logger": "ಕಥೆ ಲಾಗರ್", - "message_logger": "ಸಂದೇಶ ಲಾಗರ್", - "merged": "ವಿಲೀನಗೊಂಡಿದೆ", - "voice_call": "ಧ್ವನಿ ಕರೆ" - }, - "chat_action_menu": { - "preview_button": "ಮುನ್ನೋಟ", - "download_button": "ಡೌನ್‌ಲೋಡ್ ಮಾಡಿ", - "delete_logged_message_button": "ಲಾಗ್ ಮಾಡಿದ ಸಂದೇಶವನ್ನು ಅಳಿಸಿ", - "show_chat_edit_history": "ಚಾಟ್ ಸಂಪಾದನೆ ಇತಿಹಾಸವನ್ನು ತೋರಿಸಿ", - "convert_message": "ಸಂದೇಶವನ್ನು ಪರಿವರ್ತಿಸಿ" - }, - "opera_context_menu": { - "download": "ಮಾಧ್ಯಮ ಡೌನ್‌ಲೋಡ್ ಮಾಡಿ", - "sent_at": "{date} ರಂದು ಕಳುಹಿಸಲಾಗಿದೆ", - "created_at": "{date} ರಂದು ರಚಿಸಲಾಗಿದೆ", - "expires_at": "{date} ರಂದು ಅವಧಿ ಮುಗಿಯುತ್ತದೆ", - "media_size": "ಮಾಧ್ಯಮ ಗಾತ್ರ: {size}", - "media_duration": "ಮಾಧ್ಯಮ ಅವಧಿ: {duration} ms", - "show_debug_info": "ಡೀಬಗ್ ಮಾಹಿತಿಯನ್ನು ತೋರಿಸಿ" - }, - "modal_option": { - "profile_info": "ಪ್ರೊಫೈಲ್ ಮಾಹಿತಿ", - "close": "ಮುಚ್ಚಿ" - }, - "gallery_media_send_override": { - "multiple_media_toast": "ನೀವು ಒಂದು ಸಮಯದಲ್ಲಿ ಕೇವಲ ಒಂದು ಮಾಧ್ಯಮವನ್ನು ಕಳುಹಿಸಬಹುದು" - }, - "mark_as_seen": { - "no_unseen_snaps_toast": "ಯಾವುದೇ ನೋಡದ ಸ್ನ್ಯಾಪ್‌ಗಳು ಕಂಡುಬಂದಿಲ್ಲ!", - "seen_toast": "ನೋಡಿದಂತೆ ಗುರುತಿಸಲಾಗಿದೆ!", - "unseen_toast": "ನೋಡದಂತೆ ಗುರುತಿಸಲಾಗಿದೆ!", - "already_seen_toast": "ಈಗಾಗಲೇ ನೋಡಿದಂತೆ ಗುರುತಿಸಲಾಗಿದೆ!", - "already_unseen_toast": "ಈಗಾಗಲೇ ನೋಡದಂತೆ ಗುರುತಿಸಲಾಗಿದೆ!" - }, - "conversation_preview": { - "streak_expiration": "{day} ದಿನಗಳು {hour} ಗಂಟೆಗಳು {minute} ನಿಮಿಷಗಳಲ್ಲಿ ಅವಧಿ ಮುಗಿಯುತ್ತದೆ", - "total_messages": "ಕಳುಹಿಸಿದ/ಸ್ವೀಕರಿಸಿದ ಒಟ್ಟು ಸಂದೇಶಗಳು: {count}", - "title": "ಮುನ್ನೋಟ", - "unknown_user": "ಅಪರಿಚಿತ ಬಳಕೆದಾರ", - "no_messages": "ಯಾವುದೇ ಸಂದೇಶಗಳು ಕಂಡುಬಂದಿಲ್ಲ!" - }, - "profile_info": { - "title": "ಪ್ರೊಫೈಲ್ ಮಾಹಿತಿ", - "first_created_username": "ಮೊದಲು ರಚಿಸಲಾದ ಬಳಕೆದಾರಹೆಸರು", - "mutable_username": "ಬದಲಾಯಿಸಬಹುದಾದ ಬಳಕೆದಾರಹೆಸರು", - "display_name": "ಪ್ರದರ್ಶನ ಹೆಸರು", - "added_date": "ಸೇರಿಸಿದ ದಿನಾಂಕ", - "birthday": "ಜನ್ಮದಿನ : {month} {day}", - "hidden_birthday": "ಜನ್ಮದಿನ : ಮರೆಮಾಡಲಾಗಿದೆ", - "friendship": "ಸ್ನೇಹ", - "add_source": "ಮೂಲವನ್ನು ಸೇರಿಸಿ", - "snapchat_plus": "ಸ್ನ್ಯಾಪ್‌ಚಾಟ್ ಪ್ಲಸ್", - "snapchat_plus_state": { - "subscribed": "ಚಂದಾದಾರರಾಗಿದ್ದಾರೆ", - "not_subscribed": "ಚಂದಾದಾರರಾಗಿಲ್ಲ" - } - }, - "friendship_link_type": { - "mutual": "ಪರಸ್ಪರ", - "outgoing": "ಹೊರಹೋಗುವ", - "blocked": "ನಿರ್ಬಂಧಿಸಲಾಗಿದೆ", - "deleted": "ಅಳಿಸಲಾಗಿದೆ", - "following": "ಅನುಸರಿಸಲಾಗುತ್ತಿದೆ", - "suggested": "ಸೂಚಿಸಲಾಗಿದೆ", - "incoming": "ಒಳಬರುವ", - "incoming_follower": "ಒಳಬರುವ ಅನುಯಾಯಿ" - }, - "bulk_messaging_action": { - "choose_action_title": "ಒಂದು ಕ್ರಿಯೆಯನ್ನು ಆಯ್ಕೆಮಾಡಿ", - "progress_status": "{total} ರಲ್ಲಿ {index} ಅನ್ನು ಸಂಸ್ಕರಿಸಲಾಗುತ್ತಿದೆ", - "selection_dialog_continue_button": "ಮುಂದುವರಿಸಿ", - "confirmation_dialog": { - "title": "ನೀವು ಖಚಿತವಾಗಿದ್ದೀರಾ?", - "message": "ಇದು ಎಲ್ಲಾ ಆಯ್ಕೆಮಾಡಿದ ಸ್ನೇಹಿತರ ಮೇಲೆ ಪರಿಣಾಮ ಬೀರುತ್ತದೆ. ಈ ಕ್ರಿಯೆಯನ್ನು ರದ್ದುಗೊಳಿಸಲಾಗುವುದಿಲ್ಲ." - }, - "actions": { - "remove_friends": "ಸ್ನೇಹಿತರನ್ನು ತೆಗೆದುಹಾಕಿ", - "clear_conversations": "ಸಂಭಾಷಣೆಗಳನ್ನು ತೆರವುಗೊಳಿಸಿ" - } - }, - "chat_export": { - "exporter_dialog": { - "select_conversations_title": "ಸಂಭಾಷಣೆಗಳನ್ನು ಆಯ್ಕೆಮಾಡಿ", - "text_field_selection": "{amount} ಆಯ್ಕೆಮಾಡಲಾಗಿದೆ", - "text_field_selection_all": "ಎಲ್ಲಾ", - "export_file_format_title": "ಫೈಲ್ ಸ್ವರೂಪವನ್ನು ರಫ್ತು ಮಾಡಿ", - "message_type_filter_title": "ಪ್ರಕಾರದ ಮೂಲಕ ಸಂದೇಶಗಳನ್ನು ಫಿಲ್ಟರ್ ಮಾಡಿ", - "amount_of_messages_title": "ಸಂದೇಶಗಳ ಪ್ರಮಾಣ (ಎಲ್ಲದಕ್ಕೂ ಖಾಲಿ ಬಿಡಿ)", - "download_medias_title": "ಮಾಧ್ಯಮವನ್ನು ಡೌನ್‌ಲೋಡ್ ಮಾಡಿ" - }, - "dialog_negative_button": "ರದ್ದುಮಾಡಿ", - "dialog_positive_button": "ರಫ್ತು ಮಾಡಿ", - "exported_to": "{path} ಗೆ ರಫ್ತು ಮಾಡಲಾಗಿದೆ", - "exporting_chats": "ಚಾಟ್‌ಗಳನ್ನು ರಫ್ತು ಮಾಡಲಾಗುತ್ತಿದೆ...", - "processing_chats": "{amount} ಸಂಭಾಷಣೆಗಳನ್ನು ಸಂಸ್ಕರಿಸಲಾಗುತ್ತಿದೆ...", - "export_fail": "ಸಂಭಾಷಣೆ {conversation} ಅನ್ನು ರಫ್ತು ಮಾಡಲು ವಿಫಲವಾಗಿದೆ", - "writing_output": "ಔಟ್‌ಪುಟ್ ಬರೆಯಲಾಗುತ್ತಿದೆ...", - "finished": "ಮುಗಿದಿದೆ! ನೀವು ಈಗ ಈ ಸಂವಾದವನ್ನು ಮುಚ್ಚಬಹುದು.", - "no_messages_found": "ಯಾವುದೇ ಸಂದೇಶಗಳು ಕಂಡುಬಂದಿಲ್ಲ!", - "exporting_message": "{conversation} ಅನ್ನು ರಫ್ತು ಮಾಡಲಾಗುತ್ತಿದೆ..." - }, - "button": { - "ok": "ಸರಿ", - "positive": "ಹೌದು", - "negative": "ಇಲ್ಲ", - "cancel": "ರದ್ದುಮಾಡಿ", - "open": "ತೆರೆಯಿರಿ", - "download": "ಡೌನ್‌ಲೋಡ್ ಮಾಡಿ", - "send": "ಕಳುಹಿಸಿ", - "restore_original": "ಮೂಲವನ್ನು ಮರುಸ್ಥಾಪಿಸಿ", - "convert_external_media": "ಬಾಹ್ಯ ಮಾಧ್ಯಮವನ್ನು ಪರಿವರ್ತಿಸಿ", - "save": "ಉಳಿಸಿ" - }, - "tracker_events": { - "conversation_enter": "ಸಂಭಾಷಣೆಯನ್ನು ಪ್ರವೇಶಿಸಿ", - "conversation_exit": "ಸಂಭಾಷಣೆಯಿಂದ ನಿರ್ಗಮಿಸಿ", - "started_typing": "ಟೈಪ್ ಮಾಡಲು ಪ್ರಾರಂಭಿಸಿದೆ", - "stopped_typing": "ಟೈಪ್ ಮಾಡುವುದನ್ನು ನಿಲ್ಲಿಸಿದೆ", - "started_speaking": "ಮಾತನಾಡಲು ಪ್ರಾರಂಭಿಸಿದೆ", - "stopped_speaking": "ಮಾತನಾಡುವುದನ್ನು ನಿಲ್ಲಿಸಿದೆ", - "started_peeking": "ನೋಡಲು ಪ್ರಾರಂಭಿಸಿದೆ", - "stopped_peeking": "ನೋಡುವುದನ್ನು ನಿಲ್ಲಿಸಿದೆ", - "message_read": "ಸಂದೇಶವನ್ನು ಓದಲಾಗಿದೆ", - "message_deleted": "ಸಂದೇಶವನ್ನು ಅಳಿಸಲಾಗಿದೆ", - "message_saved": "ಸಂದೇಶವನ್ನು ಉಳಿಸಲಾಗಿದೆ", - "message_unsaved": "ಸಂದೇಶವನ್ನು ಉಳಿಸಲಾಗಿಲ್ಲ", - "message_edited": "ಸಂದೇಶವನ್ನು ಸಂಪಾದಿಸಲಾಗಿದೆ", - "message_reaction_add": "ಸಂದೇಶ ಪ್ರತಿಕ್ರಿಯೆಯನ್ನು ಸೇರಿಸಿ", - "message_reaction_remove": "ಸಂದೇಶ ಪ್ರತಿಕ್ರಿಯೆಯನ್ನು ತೆಗೆದುಹಾಕಿ", - "snap_opened": "ಸ್ನ್ಯಾಪ್ ತೆರೆಯಲಾಗಿದೆ", - "snap_replayed": "ಸ್ನ್ಯಾಪ್ ಅನ್ನು ಮರುಪಂದ್ಯ ಮಾಡಲಾಗಿದೆ", - "snap_replayed_twice": "ಸ್ನ್ಯಾಪ್ ಅನ್ನು ಎರಡು ಬಾರಿ ಮರುಪಂದ್ಯ ಮಾಡಲಾಗಿದೆ", - "snap_screenshot": "ಸ್ನ್ಯಾಪ್ ಸ್ಕ್ರೀನ್‌ಶಾಟ್", - "snap_screen_record": "ಸ್ನ್ಯಾಪ್ ಸ್ಕ್ರೀನ್ ರೆಕಾರ್ಡ್" - }, - "tracker_actions": { - "log": "ಲಾಗ್", - "in_app_notification": "ಅಪ್ಲಿಕೇಶನ್‌ನಲ್ಲಿನ ಅಧಿಸೂಚನೆ", - "push_notification": "ಪುಶ್ ಅಧಿಸೂಚನೆ", - "custom": "ಕಸ್ಟಮ್" - }, - "better_notifications": { - "button": { - "reply": "ಪ್ರತ್ಯುತ್ತರಿಸಿ", - "download": "ಡೌನ್‌ಲೋಡ್ ಮಾಡಿ", - "mark_as_read": "ಓದಿದಂತೆ ಗುರುತಿಸಿ" - } - }, - "profile_picture_downloader": { - "button": "ಪ್ರೊಫೈಲ್ ಚಿತ್ರವನ್ನು ಡೌನ್‌ಲೋಡ್ ಮಾಡಿ", - "title": "ಪ್ರೊಫೈಲ್ ಚಿತ್ರ ಡೌನ್‌ಲೋಡರ್", - "avatar_option": "ಅವತಾರ್", - "background_option": "ಹಿನ್ನೆಲೆ" - }, - "call_start_confirmation": { - "dialog_title": "ಕರೆ ಪ್ರಾರಂಭಿಸಿ", - "dialog_message": "ಕರೆ ಪ್ರಾರಂಭಿಸಲು ನೀವು ಖಚಿತವಾಗಿದ್ದೀರಾ?" - }, - "half_swipe_notifier": { - "notification_channel_name": "ಅರ್ಧ ಸ್ವೈಪ್", - "notification_content_dm": "{friend} ಇದೀಗ ನಿಮ್ಮ ಚಾಟ್‌ಗೆ {duration} ಸೆಕೆಂಡುಗಳ ಕಾಲ ಅರ್ಧ ಸ್ವೈಪ್ ಮಾಡಿದ್ದಾರೆ", - "notification_content_group": "{friend} ಇದೀಗ {group} ಗೆ {duration} ಸೆಕೆಂಡುಗಳ ಕಾಲ ಅರ್ಧ ಸ್ವೈಪ್ ಮಾಡಿದ್ದಾರೆ" - }, - "download_processor": { - "attachment_type": { - "snap": "ಸ್ನ್ಯಾಪ್", - "sticker": "ಸ್ಟಿಕ್ಕರ್", - "gif": "ಗಡಿ", - "external_media": "ಬಾಹ್ಯ ಮಾಧ್ಯಮ", - "note": "ಟಿಪ್ಪಣಿ", - "original_story": "ಮೂಲ ಕಥೆ" - }, - "select_attachments_title": "ಲಗತ್ತುಗಳನ್ನು ಆಯ್ಕೆಮಾಡಿ", - "download_started_toast": "ಡೌನ್‌ಲೋಡ್ ಪ್ರಾರಂಭವಾಯಿತು", - "unsupported_content_type_toast": "ಬೆಂಬಲಿಸದ ವಿಷಯ ಪ್ರಕಾರ!", - "failed_no_longer_available_toast": "ಮಾಧ್ಯಮ ಇನ್ನು ಮುಂದೆ ಲಭ್ಯವಿಲ್ಲ", - "no_attachments_toast": "ಯಾವುದೇ ಲಗತ್ತುಗಳು ಕಂಡುಬಂದಿಲ್ಲ!", - "already_queued_toast": "ಮಾಧ್ಯಮ ಈಗಾಗಲೇ ಸರದಿಯಲ್ಲಿದೆ!", - "already_downloaded_toast": "ಮಾಧ್ಯಮ ಈಗಾಗಲೇ ಡೌನ್‌ಲೋಡ್ ಆಗಿದೆ!", - "content_saved_toast": "ಉಳಿಸಲಾಗಿದೆ!", - "download_toast": "{path} ಡೌನ್‌ಲೋಡ್ ಆಗುತ್ತಿದೆ...", - "processing_toast": "{path} ಸಂಸ್ಕರಿಸಲಾಗುತ್ತಿದೆ...", - "failed_generic_toast": "ಡೌನ್‌ಲೋಡ್ ವಿಫಲವಾಗಿದೆ", - "failed_to_create_preview_toast": "ಮುನ್ನೋಟವನ್ನು ರಚಿಸಲು ವಿಫಲವಾಗಿದೆ", - "failed_processing_toast": "ಸಂಸ್ಕರಣೆ ವಿಫಲವಾಗಿದೆ {error}", - "failed_gallery_toast": "ಗ್ಯಾಲರಿಗೆ ಉಳಿಸಲು ವಿಫಲವಾಗಿದೆ {error}", - "dash_no_chapter": "ಯಾವುದೇ ಅಧ್ಯಾಯ ಕಂಡುಬಂದಿಲ್ಲ", - "dash_dialog": { - "title": "ಡ್ಯಾಶ್ ಮಾಧ್ಯಮವನ್ನು ಡೌನ್‌ಲೋಡ್ ಮಾಡಿ", - "download_all": "ಎಲ್ಲವನ್ನೂ ಡೌನ್‌ಲೋಡ್ ಮಾಡಿ", - "segment_text": "ವಿಭಾಗ {from} - {to}" - } - }, - "streaks_reminder": { - "notification_title": "ಸ್ಟ್ರೀಕ್ಸ್", - "notification_text": "ನೀವು {hoursLeft} ಗಂಟೆಗಳಲ್ಲಿ {friend} ನೊಂದಿಗೆ ನಿಮ್ಮ ಸ್ಟ್ರೀಕ್ ಅನ್ನು ಕಳೆದುಕೊಳ್ಳುತ್ತೀರಿ" - }, - "biometric_auth": { - "unlock_button": "ಅನ್ಲಾಕ್ ಮಾಡಿ", - "title": "Snapchat ಅನ್ಲಾಕ್ ಮಾಡಿ", - "subtitle": "Snapchat ಅನ್ಲಾಕ್ ಮಾಡಲು ದಯವಿಟ್ಟು ದೃಢೀಕರಿಸಿ" - }, - "end_to_end_encryption": { - "toolbox": { - "no_shared_key": "ನೀವು ಈ ಸ್ನೇಹಿತನೊಂದಿಗೆ ಇನ್ನೂ ಹಂಚಿದ ರಹಸ್ಯವನ್ನು ಹೊಂದಿಲ್ಲ. ಹೊಸದನ್ನು ಪ್ರಾರಂಭಿಸಲು ಕೆಳಗೆ ಕ್ಲಿಕ್ ಮಾಡಿ.", - "shared_key_fingerprint": "ನಿಮ್ಮ ಫಿಂಗರ್‌ಪ್ರಿಂಟ್:\n\n{fingerprint}\n\nಇದು ನಿಮ್ಮ ಸ್ನೇಹಿತನ ಫಿಂಗರ್‌ಪ್ರಿಂಟ್‌ಗೆ ಹೊಂದಿಕೆಯಾಗಿದೆಯೇ ಎಂದು ಖಚಿತಪಡಿಸಿಕೊಳ್ಳಿ!", - "initiate_exchange_button": "ಕೀ ವಿನಿಮಯವನ್ನು ಪ್ರಾರಂಭಿಸಿ" - }, - "confirmation_dialogs": { - "title": "ಎಂಡ್-ಟು-ಎಂಡ್ ಎನ್‌ಕ್ರಿಪ್ಶನ್", - "confirmation_1": "ಎಚ್ಚರಿಕೆ: ಇದು ನಿಮ್ಮ ಅಸ್ತಿತ್ವದಲ್ಲಿರುವ ಕೀಯನ್ನು ಅತಿಕ್ರಮಿಸುತ್ತದೆ. ಈ ಸ್ನೇಹಿತನಿಂದ ಎಲ್ಲಾ ಎನ್‌ಕ್ರಿಪ್ಟ್ ಮಾಡಿದ ಸಂದೇಶಗಳಿಗೆ ನೀವು ಪ್ರವೇಶವನ್ನು ಕಳೆದುಕೊಳ್ಳುತ್ತೀರಿ. ನೀವು ಮುಂದುವರಿಯಲು ಖಚಿತವಾಗಿದ್ದೀರಾ?", - "confirmation_2": "ನೀವು ನಿಜವಾಗಿಯೂ ಮುಂದುವರಿಯಲು ಖಚಿತವಾಗಿದ್ದೀರಾ? ಇದು ಹಿಂದೆ ಸರಿಯಲು ನಿಮ್ಮ ಕೊನೆಯ ಅವಕಾಶ." - }, - "unencrypted_conversation_send_failure_toast": "ನೀವು ಎನ್‌ಕ್ರಿಪ್ಟ್ ಮಾಡಿದ ಮತ್ತು ಎನ್‌ಕ್ರಿಪ್ಟ್ ಮಾಡದ ಎರಡೂ ಸಂಭಾಷಣೆಗಳಿಗೆ ಎನ್‌ಕ್ರಿಪ್ಟ್ ಮಾಡಿದ ವಿಷಯವನ್ನು ಕಳುಹಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ!", - "native_hooks_send_failure_toast": "ಕಳುಹಿಸಲು ವಿಫಲವಾಗಿದೆ! ದಯವಿಟ್ಟು ಸೆಟ್ಟಿಂಗ್‌ಗಳಲ್ಲಿ ಸ್ಥಳೀಯ ಹುಕ್ಸ್‌ಗಳನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಿ.", - "no_participants_to_encrypt_toast": "ಈ ಸಂಭಾಷಣೆಯಲ್ಲಿ ಸಂದೇಶಗಳನ್ನು ಎನ್‌ಕ್ರಿಪ್ಟ್ ಮಾಡಲು ನಿಮಗೆ ಯಾವುದೇ ಸ್ನೇಹಿತರಿಲ್ಲ!", - "encryption_failed_toast": "ಸಂದೇಶವನ್ನು ಎನ್‌ಕ್ರಿಪ್ಟ್ ಮಾಡಲು ವಿಫಲವಾಗಿದೆ! ಹೆಚ್ಚಿನ ವಿವರಗಳಿಗಾಗಿ ಲಾಗ್‌ಕ್ಯಾಟ್ ಪರಿಶೀಲಿಸಿ.", - "accept_public_key_success_toast": "ಸಾರ್ವಜನಿಕ ಕೀಯನ್ನು ಯಶಸ್ವಿಯಾಗಿ ಸ್ವೀಕರಿಸಲಾಗಿದೆ!", - "accept_secret_key_success_toast": "ಮುಗಿದಿದೆ! ನೀವು ಈಗ ಈ ಸ್ನೇಹಿತನೊಂದಿಗೆ ಎನ್‌ಕ್ರಿಪ್ಟ್ ಮಾಡಿದ ಸಂದೇಶಗಳನ್ನು ಕಳುಹಿಸಬಹುದು ಮತ್ತು ಸ್ವೀಕರಿಸಬಹುದು.", - "accept_public_key_failure_toast": "ಸಾರ್ವಜನಿಕ ಕೀಯನ್ನು ಸ್ವೀಕರಿಸಲು ವಿಫಲವಾಗಿದೆ", - "accept_secret_key_failure_toast": "ರಹಸ್ಯ ಕೀಯನ್ನು ಸ್ವೀಕರಿಸಲು ವಿಫಲವಾಗಿದೆ", - "accept_secret_button": "ರಹಸ್ಯವನ್ನು ಸ್ವೀಕರಿಸಿ", - "accept_public_key_button": "ಸಾರ್ವಜನಿಕ ಕೀಯನ್ನು ಸ್ವೀಕರಿಸಿ", - "outgoing_pk_message": "ಕೀ ವಿನಿಮಯ ವಿನಂತಿ", - "outgoing_secret_message": "ಕೀ ವಿನಿಮಯ ಪ್ರತಿಕ್ರಿಯೆ", - "incoming_pk_message": "ನೀವು ಇದೀಗ ಸಾರ್ವಜನಿಕ ಕೀ ವಿನಂತಿಯನ್ನು ಸ್ವೀಕರಿಸಿದ್ದೀರಿ. ಅದನ್ನು ಸ್ವೀಕರಿಸಲು ಕೆಳಗೆ ಕ್ಲಿಕ್ ಮಾಡಿ.", - "incoming_secret_message": "ನಿಮ್ಮ ಸ್ನೇಹಿತ ಇದೀಗ ನಿಮ್ಮ ಸಾರ್ವಜನಿಕ ಕೀಯನ್ನು ಸ್ವೀಕರಿಸಿದ್ದಾರೆ. ರಹಸ್ಯವನ್ನು ಸ್ವೀಕರಿಸಲು ಕೆಳಗೆ ಕ್ಲಿಕ್ ಮಾಡಿ." - }, - "auto_open_snaps": { - "title": "ಸ್ನ್ಯಾಪ್‌ಗಳನ್ನು ಸ್ವಯಂ ತೆರೆಯಿರಿ", - "notification_content": "{count} ಸ್ನ್ಯಾಪ್‌ಗಳನ್ನು ತೆರೆಯಲಾಗಿದೆ" - }, - "friend_mutation_observer": { - "notification_channel_name": "ಸ್ನೇಹಿತರ ರೂಪಾಂತರ ವೀಕ್ಷಕ", - "friend_removed": "{username} ನಿಮ್ಮನ್ನು ಸ್ನೇಹಿತರಾಗಿ ತೆಗೆದುಹಾಕಿದ್ದಾರೆ", - "birthday_removed": "{username} ತಮ್ಮ ಜನ್ಮದಿನವನ್ನು ({birthday}) ತೆಗೆದುಹಾಕಿದ್ದಾರೆ", - "birthday_added": "{username} ತಮ್ಮ ಜನ್ಮದಿನವನ್ನು ({birthday}) ಸೇರಿಸಿದ್ದಾರೆ", - "birthday_changed": "{username} ತಮ್ಮ ಜನ್ಮದಿನವನ್ನು {oldBirthday} ರಿಂದ {newBirthday} ಗೆ ಬದಲಾಯಿಸಿದ್ದಾರೆ", - "bitmoji_selfie_changed": "{username} ತಮ್ಮ ಬಿಟ್‌ಮೋಜಿ ಸೆಲ್ಫಿಯನ್ನು ಬದಲಾಯಿಸಿದ್ದಾರೆ", - "bitmoji_avatar_changed": "{username} ತಮ್ಮ ಬಿಟ್‌ಮೋಜಿ ಅವತಾರವನ್ನು ಬದಲಾಯಿಸಿದ್ದಾರೆ", - "bitmoji_background_changed": "{username} ತಮ್ಮ ಬಿಟ್‌ಮೋಜಿ ಹಿನ್ನೆಲೆಯನ್ನು ಬದಲಾಯಿಸಿದ್ದಾರೆ", - "bitmoji_scene_changed": "{username} ತಮ್ಮ ಬಿಟ್‌ಮೋಜಿ ದೃಶ್ಯವನ್ನು ಬದಲಾಯಿಸಿದ್ದಾರೆ" - }, - "material3_strings": { - "date_range_picker_start_headline": "ಇಂದ", - "date_range_picker_end_headline": "ವರೆಗೆ", - "date_range_picker_title": "ದಿನಾಂಕ ಶ್ರೇಣಿಯನ್ನು ಆಯ್ಕೆಮಾಡಿ", - "date_picker_switch_to_calendar_mode": "ಕ್ಯಾಲೆಂಡರ್", - "date_picker_switch_to_input_mode": "ಇನ್‌ಪುಟ್", - "date_range_picker_scroll_to_previous_month": "ಹಿಂದಿನ ತಿಂಗಳು", - "date_range_picker_scroll_to_next_month": "ಮುಂದಿನ ತಿಂಗಳು", - "date_picker_today_description": "ಇಂದು", - "date_range_picker_day_in_range": "ಆಯ್ಕೆಮಾಡಲಾಗಿದೆ", - "date_input_invalid_for_pattern": "ಅಮಾನ್ಯ ದಿನಾಂಕ", - "date_input_invalid_year_range": "ಅಮಾನ್ಯ ವರ್ಷ", - "date_input_invalid_not_allowed": "ಅಮಾನ್ಯ ದಿನಾಂಕ", - "date_range_input_invalid_range_input": "ಅಮಾನ್ಯ ದಿನಾಂಕ ಶ್ರೇಣಿ" - }, - "send_override_dialog": { - "title": "{type} ಆಗಿ ಮಾಧ್ಯಮವನ್ನು ಕಳುಹಿಸಿ", - "duration": "ಅವಧಿ: {duration}", - "saveable_snap_hint": "ಚಾಟ್‌ನಲ್ಲಿ ಸ್ನ್ಯಾಪ್ ಅನ್ನು ಉಳಿಸಬಹುದಾದಂತೆ ಮಾಡಿ", - "unlimited_duration": "ಅನಿಯಮಿತ" - }, - "invalid_input_toast": "ಅಮಾನ್ಯ ಇನ್‌ಪುಟ್! ನೀವು ಮಾನ್ಯ ಮೌಲ್ಯವನ್ನು ನಮೂದಿಸಿದ್ದೀರಿ ಎಂದು ಖಚಿತಪಡಿಸಿಕೊಳ್ಳಿ." -} \ No newline at end of file diff --git a/common/src/main/assets/lang/ko_KR.json b/common/src/main/assets/lang/ko_KR.json index 82ffc58d..679ee5de 100644 --- a/common/src/main/assets/lang/ko_KR.json +++ b/common/src/main/assets/lang/ko_KR.json @@ -1,2022 +1,17 @@ { "setup": { "dialogs": { + "select_save_folder_button": "폴더 선택", "select_language": "언어 선택", - "save_folder": "PurrfectSnap은 Snapchat에서 미디어를 다운로드하고 저장하기 위해 저장소 권한이 필요합니다.\n미디어를 다운로드할 위치를 선택하세요.", - "select_save_folder_button": "폴더 선택" + "save_folder": "SnapEnhance에는 Snapchat에서 미디어를 다운로드하고 저장하려면 저장소 권한이 필요합니다.\n미디어를 다운로드할 위치를 선택하세요." }, "mappings": { - "dialog": "매핑 생성 중, 시간이 걸릴 수 있습니다...", - "generate_failure_no_snapchat": "PurrfectSnap이 Snapchat을 감지하지 못했습니다. Snapchat을 다시 설치해 보세요.", - "generate_failure": "매핑 생성 중 오류가 발생했습니다. 다시 시도해 주세요." + "dialog": "매핑을 생성하는 중입니다. 다소 시간이 걸릴 수 있습니다...", + "generate_failure_no_snapchat": "SnapEnhance가 Snapchat을 감지할 수 없습니다. Snapchat을 다시 설치해 보십시오.", + "generate_failure": "매핑을 생성하는 중에 오류가 발생했습니다. 다시 시도해 주세요." }, "permissions": { - "dialog": "계속하려면 다음 요구 사항을 충족해야 합니다.", - "notification_access": "알림 접근", - "battery_optimization": "배터리 최적화", - "display_over_other_apps": "다른 앱 위에 표시", - "request_button": "요청" + "dialog": "계속하려면 다음 요구 사항을 충족해야 합니다." } - }, - "scopes": { - "friend": "친구", - "group": "그룹" - }, - "manager": { - "routes": { - "tasks": "작업", - "features": "기능", - "manage_rule_feature": "규칙 기능 관리", - "home": "홈", - "home_settings": "설정", - "home_logs": "로그", - "logger_history": "로거 기록", - "logged_stories": "기록된 스토리", - "friend_tracker": "친구 추적기", - "edit_rule": "규칙 편집", - "file_imports": "파일 가져오기", - "manage_repos": "리포지토리 관리", - "social": "소셜", - "manage_scope": "범위 관리", - "messaging_preview": "미리보기", - "scripts": "스크립트", - "better_location": "더 나은 위치" - }, - "sections": { - "home": { - "version_title": "v{versionName} · Eternal이 포크함", - "update_title": "PurrfectSnap 업데이트", - "update_content": "버전 {version}을 사용할 수 있습니다!", - "update_button": "다운로드", - "debug_build_summary_title": "PurrfectSnap의 디버그 빌드를 실행 중입니다.", - "debug_build_summary_content": "버전 {versionName} ({versionCode})", - "debug_build_summary_date": "빌드 날짜: {date} ({days}일 전)", - "quick_actions_title": "빠른 작업", - "download_icon_description": "다운로드", - "completed_icon_description": "완료됨", - "failed_icon_description": "실패함", - "manage_quick_actions_description": "빠른 작업 관리", - "quick_actions_icon_description": "빠른 작업", - "add_quick_action_description": "빠른 작업 추가" - }, - "home_logs": { - "no_logs_hint": "사용 가능한 로그 없음", - "clear_logs_button": "로그 지우기", - "export_logs_button": "로그 내보내기", - "saving_logs_toast": "로그 저장 중, 시간이 걸릴 수 있습니다...", - "saved_logs_success_toast": "로그가 성공적으로 저장되었습니다.", - "saved_logs_failure_toast": "로그 저장 실패" - }, - "home_settings": { - "actions_title": "작업", - "message_logger_title": "메시지 로거", - "debug_title": "디버그", - "success_toast": "완료!", - "message_logger_summary": "{messageCount}개의 메시지\n{storyCount}개의 스토리", - "export_button": "내보내기", - "clear_button": "지우기", - "view_logger_history_button": "로거 기록 보기", - "updates_title": "업데이트", - "auto_update_check": "자동으로 업데이트 확인", - "update_check_frequency": "업데이트 확인 빈도", - "update_check_frequency_daily": "매일", - "update_check_frequency_weekly": "매주", - "update_check_frequency_monthly": "매월", - "theme_icon_description": "테마", - "app_theme_title": "앱 테마", - "theme_mode_system": "시스템", - "theme_mode_light": "라이트", - "theme_mode_dark": "다크", - "ui_settings_title": "UI 설정", - "haptic_feedback_label": "햅틱 피드백", - "test_mode_label": "테스트 모드(디버깅 전용)", - "disable_feature_loading_label": "기능 로딩 비활성화", - "disable_auto_mapper_label": "자동 매퍼 비활성화", - "disable_bypass_indicator_label": "바이패스 상태 표시기 비활성화", - "update_notification_channel_name": "PurrfectSnap 업데이트", - "update_notification_channel_description": "PurrfectSnap 업데이트 알림", - "update_notification_title": "PurrfectSnap 업데이트 가능", - "update_notification_text": "버전 %s를 지금 사용할 수 있습니다.", - "export_database_failed_toast": "데이터베이스 내보내기 실패! {message}", - "clear_messages_failed_toast": "메시지 지우기 실패! {message}", - "clear_file_failed_toast": "파일 지우기 실패! {message}", - "debug_file_config": "구성", - "debug_file_mappings": "매핑", - "debug_file_message_logger": "메시지 로거", - "debug_file_pinned_best_friend": "고정된 가장 친한 친구", - "debug_file_native_sig_cache": "네이티브 서명 캐시" - }, - "tasks": { - "no_tasks": "작업 없음", - "merge_button": "병합", - "failed_to_open_file": "파일 열기 실패", - "merge_files_toast": "{count}개의 파일 병합 중", - "remove_selected_tasks_title": "선택한 작업을 제거하시겠습니까?", - "remove_all_tasks_title": "모든 작업을 제거하시겠습니까?", - "delete_files_option": "파일도 삭제", - "remove_selected_tasks_confirm": "{count}개의 작업을 제거하시겠습니까?", - "remove_all_tasks_confirm": "모든 작업을 제거하시겠습니까?", - "clear_tasks_description": "작업 지우기", - "file_not_found_icon_description": "파일을 찾을 수 없음", - "image_icon_description": "이미지", - "video_icon_description": "비디오", - "audio_icon_description": "오디오", - "file_icon_description": "파일", - "download_icon_description": "다운로드", - "chat_action_icon_description": "채팅 작업", - "cancel_icon_description": "취소", - "success_icon_description": "성공", - "failure_icon_description": "실패", - "cancelled_icon_description": "취소됨", - "task_status_failure": "실패", - "task_status_cancelled": "취소됨" - }, - "features": { - "disabled": "비활성화됨", - "export_option": "내보내기", - "import_option": "가져오기", - "reset_option": "재설정", - "config_export_success_toast": "구성이 성공적으로 내보내졌습니다.", - "config_import_success_toast": "구성이 성공적으로 가져와졌습니다.", - "config_import_failure_toast": "구성 가져오기 실패 {error}", - "config_export_failure_toast": "구성 내보내기 실패 {error}", - "saved_config_snackbar": "구성이 저장되었습니다.", - "older_required": "이 기능이 올바르게 작동하려면 Snapchat v{version} 이전 버전이 필요합니다.", - "newer_required": "이 기능이 올바르게 작동하려면 Snapchat v{version} 이후 버전이 필요합니다.", - "search_button": "검색" - }, - "manage_rule_feature": { - "disable_state_option": "비활성화됨", - "disable_state_subtext": "영향을 받는 친구/그룹이 없습니다.", - "whitelist_state_option": "아무도 제외하고...", - "whitelist_state_subtext": "이 규칙은 {count}명의 친구/그룹에만 영향을 미칩니다.", - "whitelist_state_button": "허용된 친구/그룹 선택", - "blacklist_state_option": "모두 제외하고...", - "blacklist_state_subtext": "이 규칙은 {count}명의 친구/그룹을 제외한 모든 사람에게 영향을 미칩니다.", - "blacklist_state_button": "제외된 친구/그룹 선택", - "clear_list_button": "친구/그룹 목록 지우기", - "dialog_clear_confirmation_text": "목록을 지우시겠습니까?" - }, - "social": { - "friends_tab": "친구", - "groups_tab": "그룹", - "empty_hint": "(비어 있음)", - "streaks_expiration_short": "{hours}시간" - }, - "manage_scope": { - "logged_stories_button": "기록된 스토리 보기", - "e2ee_title": "종단 간 암호화", - "rules_title": "규칙", - "participants_text": "{count}명의 참가자", - "not_found": "찾을 수 없음", - "streaks_title": "연속 기록", - "streaks_length_text": "길이: {length}", - "streaks_expiration_text": "{eta} 후에 만료됨", - "streaks_expiration_text_expired": "만료됨", - "reminder_button": "알림 설정", - "delete_scope_confirm_dialog_title": "{scope}을(를) 삭제하시겠습니까?", - "notes_placeholder": "메모를 추가하려면 클릭하세요.", - "invalid_key_size_32_bytes": "잘못된 키 크기(32바이트여야 함)", - "successfully_imported_key": "키를 성공적으로 가져왔습니다.", - "failed_to_import_key": "키 가져오기 실패: {message}", - "export_base64_button": "Base64 내보내기", - "import_base64_button": "Base64 가져오기" - }, - "logged_stories": { - "story_failed_to_load": "로드 실패", - "no_stories": "스토리를 찾을 수 없음", - "save_from_cache_button": "캐시에서 저장", - "downloaded_to_path": "{path}에 다운로드됨", - "download_failed": "다운로드 실패: {message}", - "posted_at": "{date}에 게시됨", - "created_at": "{date}에 생성됨", - "failed_to_open_file": "파일 열기 실패. 자세한 내용은 로그를 확인하세요.", - "failed_to_get_file": "파일 가져오기 실패" - }, - "messaging_preview": { - "processed_messages_toast": "{count}개의 메시지 처리됨", - "processed_messages_text": "{count}개의 메시지 처리됨", - "close_button_description": "닫기", - "bridge_connection_failed": "브리지에 연결하지 못했습니다. Snapchat이 백그라운드에서 실행 중인지 확인하세요.", - "bridge_init_failed": "메시징 브리지 초기화 실패. Snapchat이 백그라운드에서 실행 중인지 확인하세요.", - "message_fetch_failed": "메시지 가져오기 실패", - "no_message_hint": "메시지 없음", - "save_selection_option": "선택 항목 저장", - "save_all_option": "모두 저장", - "unsave_selection_option": "선택 항목 저장 취소", - "unsave_all_option": "모두 저장 취소", - "mark_selection_as_seen_option": "선택한 스냅을 읽음으로 표시", - "mark_all_as_seen_option": "모든 스냅을 읽음으로 표시", - "delete_selection_option": "선택 항목 삭제", - "delete_all_option": "모두 삭제" - }, - "logger_history": { - "download_started_toast": "다운로드가 시작되었습니다!", - "download_success_toast": "{path}에 다운로드됨", - "download_failed_toast": "{message} 다운로드 실패", - "edited_at_text": "{message} ({date}에 편집됨)", - "download_button": "다운로드", - "select_conversation_placeholder": "대화 선택", - "close_button_description": "닫기", - "search_button_description": "검색", - "list_friend_format": "친구 {name}", - "list_group_format": "그룹 {name}", - "no_more_messages": "더 이상 메시지 없음", - "reverse_order_checkbox": "역순", - "chat_attachment": "첨부 파일 {index}", - "empty_message": "빈 채팅 메시지", - "message_parse_failed": "메시지 구문 분석 실패", - "unknown_sender": "알 수 없는 발신자", - "download_attachment_failed_toast": "첨부 파일 다운로드 실패", - "log_header_format": "{username} ({type}) - {date}" - }, - "file_imports": { - "import_file_button": "파일 가져오기", - "file_not_found": "파일을 찾을 수 없음", - "file_import_failed": "파일 가져오기 실패: {error}", - "file_imported": "파일을 성공적으로 가져왔습니다.", - "file_delete_failed": "파일 삭제 실패", - "no_files_hint": "여기에서 Snapchat에서 사용할 파일을 가져올 수 있습니다. 아래 버튼을 눌러 파일을 가져옵니다." - }, - "better_location": { - "spoofed_coordinates_title": "위도 {latitude}, 경도 {longitude}", - "save_coordinates_dialog_title": "좌표 저장", - "saved_name_dialog_hint": "저장된 이름", - "latitude_dialog_hint": "위도", - "longitude_dialog_hint": "경도", - "save_dialog_button": "저장", - "choose_location_button": "위치 선택", - "teleport_to_friend_button": "친구에게 순간이동", - "spoof_location_toggle": "위치 속이기", - "suspend_location_updates": "위치 업데이트 일시 중지", - "saved_coordinates_title": "저장된 좌표", - "no_saved_coordinates_hint": "저장된 좌표 없음", - "delete_dialog_title": "저장된 좌표 삭제", - "delete_dialog_message": "이 저장된 좌표를 삭제하시겠습니까?", - "teleport_to_friend_title": "친구에게 순간이동", - "search_bar": "검색", - "no_friends_map": "지도에 친구 없음", - "no_friends_found": "친구를 찾을 수 없음", - "edit_location_button_description": "위치 편집", - "add_icon_description": "추가", - "edit_icon_description": "편집", - "delete_icon_description": "삭제" - } - }, - "dialogs": { - "add_friend": { - "title": "친구 또는 그룹 추가", - "search_hint": "검색", - "fetch_error": "데이터 가져오기 실패", - "category_groups": "그룹", - "category_friends": "친구", - "participants_text": "{count}명의 참가자", - "search_icon_description": "검색" - }, - "scripting_warning": { - "title": "경고", - "content": "PurrfectSnap에는 스크립팅 도구가 포함되어 있어 장치에서 사용자 정의 코드를 실행할 수 있습니다. 각별한 주의를 기울이고 신뢰할 수 있는 알려진 소스에서만 모듈을 설치하세요. 승인되지 않았거나 확인되지 않은 모듈은 시스템에 보안 위험을 초래할 수 있습니다." - }, - "reset_config": { - "title": "구성 재설정", - "content": "구성을 재설정하시겠습니까?", - "success_toast": "구성이 성공적으로 재설정되었습니다." - }, - "export_config": { - "title": "민감한 데이터 내보내기?", - "content": "민감한 데이터(예: 위치 좌표 등)와 함께 구성을 내보내시겠습니까?" - }, - "messaging_action": { - "title": "처리할 콘텐츠 유형 선택", - "select_all_button": "모두 선택" - }, - "file_imports": { - "no_files_settings_hint": "파일을 찾을 수 없습니다. 파일 가져오기 섹션에서 필요한 파일을 가져왔는지 확인하세요.", - "settings_select_file_hint": "가져온 파일 선택" - }, - "quick_actions_dialog": { - "title": "빠른 작업 편집", - "subtitle": "빠른 작업을 선택하고 크기를 조정하세요." - } - }, - "friend_tracker": { - "rules_tab": "규칙", - "logs_tab": "로그", - "export_dialog_title": "내보내기", - "bulk_export_button": "대량 내보내기", - "individual_export_button": "개별 내보내기", - "invalid_import_type_dialog_title": "잘못된 가져오기 유형", - "invalid_import_type_dialog_text": "선택한 파일은 이 가져오기 유형과 호환되지 않습니다. 올바른 가져오기 유형을 선택하세요.", - "import_dialog_title": "가져오기", - "bulk_import_button": "대량 가져오기", - "individual_import_button": "개별 가져오기", - "import_button_description": "가져오기", - "export_button_description": "내보내기", - "export_button": "내보내기", - "delete_button_description": "삭제", - "delete_button": "삭제", - "catalog_button_description": "카탈로그", - "catalog_button": "카탈로그", - "add_rule_button_description": "규칙 추가", - "add_rule_button": "규칙 추가", - "no_rules_found": "규칙을 찾을 수 없음", - "empty_rule_name": "(비어 있음)", - "events_suffix": "이벤트", - "scopes_suffix": "범위", - "select_rule_to_export_title": "내보낼 규칙 선택", - "deleted_logs_toast": "{count}개의 로그 삭제됨", - "delete_logs_dialog_title": "로그를 삭제하시겠습니까?", - "deleting_logs_dialog_text": "{count}개의 로그 삭제 중...", - "delete_logs_dialog_confirm_text": "현재 필터 및 검색어에 따라 로그가 삭제됩니다. 이 작업은 되돌릴 수 없습니다.", - "exported_logs_toast": "로그가 내보내졌습니다!", - "export_logs_failed_toast": "로그 내보내기 실패. 자세한 내용은 logcat을 확인하세요.", - "export_logs_dialog_title": "로그를 내보내시겠습니까?", - "exporting_logs_dialog_text": "로그 내보내기 중...", - "export_logs_dialog_confirm_text": "현재 필터 및 검색어에 따라 로그가 내보내집니다.", - "export_as_button": "{type}으로 내보내기", - "filters_title": "필터", - "search_by_label": "검색 기준", - "newest_first_label": "최신순", - "since_label": "이후", - "until_label": "까지", - "pick_a_date_button": "날짜 선택", - "search_placeholder": "검색", - "filter_button_description": "필터", - "clear_button_description": "지우기", - "no_logs_found": "로그를 찾을 수 없음", - "log_event_format": "{conversation}에서 {event}", - "condition_only_inside_conversation": "대화 중에만", - "condition_only_outside_conversation": "대화 외부에서만", - "condition_only_when_app_active": "Snapchat이 활성화된 경우에만", - "condition_only_when_app_inactive": "Snapchat이 비활성화된 경우에만", - "condition_no_push_notification_when_app_active": "Snapchat이 활성화된 경우 알림 없음", - "add_event_dialog_title": "이벤트 추가", - "event_type_label": "이벤트 유형", - "triggers_title": "트리거", - "conditions_title": "조건", - "add_button": "추가", - "default_rule_name": "사용자 지정 규칙", - "discard_changes_dialog_title": "변경 사항을 취소하시겠습니까?", - "discard_changes_dialog_text": "저장되지 않은 변경 사항이 있습니다. 취소하시겠습니까?", - "discard_button": "취소", - "cannot_save_rule_dialog_title": "규칙을 저장할 수 없음", - "cannot_save_rule_dialog_text": "규칙을 저장하려면 하나 이상의 이벤트가 있어야 합니다.", - "duplicate_rule_name_dialog_title": "중복된 규칙 이름", - "duplicate_rule_name_dialog_text": "이 이름의 규칙이 이미 있습니다. 다른 이름을 선택하세요.", - "delete_rule_dialog_title": "규칙 삭제", - "delete_rule_dialog_text": "이 규칙을 삭제하시겠습니까?", - "new_rule_title": "새 규칙", - "edit_rule_title": "규칙 편집", - "back_button_description": "뒤로", - "save_button_description": "저장", - "general_section_title": "일반", - "rule_name_label": "규칙 이름", - "author_name_label": "작성자 이름", - "scope_section_title": "범위", - "scope_all": "모두", - "scope_whitelist": "화이트리스트", - "scope_blacklist": "블랙리스트", - "select_friends_groups_button": "친구/그룹 선택({count})", - "events_section_title": "이벤트", - "add_event_button": "이벤트 추가", - "no_events_text": "이벤트 없음" - }, - "friend_tracker_catalog": { - "download_failed": "다운로드 실패: {code}", - "error": "오류: {message}", - "no_repos_added": "추가된 리포지토리 없음.", - "no_rules_available": "어떤 리포지토리에서도 사용할 수 있는 규칙이 없습니다.", - "by_author": "{author} 작성", - "imported_button": "가져옴", - "import_button": "가져오기", - "title": "친구 추적기 카탈로그", - "manage_repos_description": "리포지토리 관리" - }, - "friend_tracker_export": { - "title": "규칙 내보내기", - "back_button_description": "뒤로", - "exported_toast": "친구 추적기 규칙이 내보내졌습니다!", - "export_failed_toast": "규칙 내보내기 실패: {message}", - "save_button": "저장", - "expand_button_description": "확장" - }, - "friend_tracker_import": { - "title": "규칙 가져오기", - "back_button_description": "뒤로", - "imported_toast": "친구 추적기 규칙이 가져와졌습니다!", - "import_failed_toast": "규칙 가져오기 실패: {message}", - "confirm_button": "확인", - "expand_button_description": "확장" - }, - "friend_tracker_repos": { - "invalid_repo_title": "잘못된 리포지토리", - "add_repo_button": "리포지토리 추가", - "add_repo_dialog_title": "리포지토리 URL 추가", - "repo_url_label": "리포지토리 URL", - "repo_added_toast": "리포지토리가 성공적으로 추가되었습니다!", - "invalid_repo_error": "유효한 친구 추적기 리포지토리가 아닌 것 같습니다.", - "add_repo_failed_toast": "리포지토리 추가 실패: {message}", - "add_button": "추가", - "no_repos_added": "추가된 리포지토리 없음", - "remove_button": "제거", - "remove_repo_dialog_title": "리포지토리 제거", - "remove_repo_dialog_text": "이 리포지토리를 제거하시겠습니까?" - }, - "navigation": { - "tracker_tab_label": "추적기", - "customize_bottom_bar_title": "하단 바 사용자 지정", - "customize_bottom_bar_subtitle": "탭 순서를 변경하거나 추가 또는 제거합니다. 최대 5개.", - "shown_tabs_title": "표시된 탭", - "no_tabs_selected_text": "선택된 탭 없음", - "available_tabs_title": "사용 가능한 탭", - "reset_button": "재설정", - "done_button": "완료" - }, - "scripting": { - "script_already_installed": "스크립트가 이미 설치되었습니다!", - "downloading_script": "스크립트 다운로드 중...", - "script_downloaded": "{name} 스크립트가 다운로드되었습니다!", - "download_script_failed": "스크립트 다운로드 실패. 자세한 내용은 로그를 확인하세요.", - "import_script_from_url_title": "URL에서 스크リプト 가져오기", - "import_script_warning": "경고: 가져온 스크립트는 장치에 해로울 수 있습니다. 신뢰할 수 있는 소스에서만 스크립트를 가져오세요.", - "enter_url_label": "여기에 URL을 입력하세요:", - "script_imported": "{name} 스크リプト가 가져와졌습니다!", - "import_failed": "스크립트 가져오기 실패. {message}. 자세한 내용은 로그를 확인하세요.", - "import_button": "가져오기", - "update_module_button": "모듈 업데이트", - "updating_script": "{name} 스크립트 업데이트 중...", - "module_not_found": "모듈을 찾을 수 없음", - "updated_script": "{name}을(를) 버전 {version}으로 업데이트했습니다.", - "update_module_failed": "모듈 업데이트 실패. 자세한 내용은 로그를 확인하세요.", - "edit_module_button": "모듈 편집", - "open_module_failed": "모듈 파일 열기 실패. 자세한 내용은 로그를 확인하세요.", - "clear_module_data_button": "모듈 데이터 지우기", - "module_data_cleared": "모듈 데이터가 지워졌습니다!", - "clear_module_data_failed": "모듈 데이터 지우기 실패. 자세한 내용은 로그를 확인하세요.", - "delete_module_button": "모듈 삭제", - "deleted_script": "{name} 스크립트가 삭제되었습니다!", - "delete_module_failed": "모듈 삭제 실패. 자세한 내용은 로그를 확인하세요.", - "actions_title": "작업", - "no_description": "설명 없음", - "update_available": "업데이트 가능: {version}", - "actions_button": "작업", - "loaded_script": "{name} 스크립트가 로드되었습니다.", - "unloaded_script": "{name} 스크립트가 언로드되었습니다.", - "enable_script_failed": "스크립트 활성화 실패. 자세한 내용은 로그를 확인하세요.", - "disable_script_failed": "스크립트 비활성화 실패. 자세한 내용은 로그를 확인하세요.", - "select_scripts_folder_toast": "스크립트 폴더를 선택하세요!", - "manage_repos_button": "리포지토리 관리", - "import_from_url_button": "URL에서 가져오기", - "open_scripts_folder_button": "스크립트 폴더 열기", - "no_settings_for_module": "이 모듈에는 설정이 없습니다.", - "installed_scripts_tab": "설치된 스크립트", - "catalog_tab": "카탈로그", - "no_scripts_folder_selected_title": "선택된 스크립트 폴더 없음", - "select_folder_button": "폴더 선택", - "no_scripts_found_title": "스크립트를 찾을 수 없음.", - "use_catalog_to_add_scripts": "카탈로그 탭을 사용하여 스크립트를 추가하세요!", - "ok_button_timeout": "확인({timeout})", - "documentation_button": "문서", - "catalog": { - "script_already_installed": "스크립트가 이미 설치되었습니다!", - "download_failed": "다운로드 실패: {code}", - "script_downloaded": "스크립트가 다운로드되었습니다!", - "could_not_create_file": "파일을 만들 수 없습니다.", - "no_scripts_folder_selected": "선택된 스크립트 폴더 없음.", - "error": "오류: {message}", - "no_repos_added": "추가된 리포지토리 없음.", - "repo_list_info": "여기에서 리포지토리 목록을 찾을 수 있습니다: ", - "link_text": "링크", - "no_scripts_available": "어떤 리포지토리에서도 사용할 수 있는 스크립트가 없습니다.", - "by_author": "{author} 작성", - "version": "버전: {version}", - "installed_button": "설치됨", - "download_button": "다운로드" - }, - "repos": { - "invalid_repo_title": "잘못된 리포지토리", - "add_repo_button": "리포지토리 추가", - "add_repo_dialog_title": "리포지토리 URL 추가", - "repo_url_label": "리포지토리 URL", - "repo_added_toast": "리포지토리가 성공적으로 추가되었습니다!", - "invalid_repo_error": "유효한 스크립트 리포지토리가 아닌 것 같습니다.", - "add_repo_failed_toast": "리포지토리 추가 실패: {message}", - "add_button": "추가", - "no_repos_added": "추가된 리포지토리 없음", - "remove_button": "제거", - "remove_repo_dialog_title": "리포지토리 제거", - "remove_repo_dialog_text": "이 리포지토리를 제거하시겠습니까?" - } - }, - "features": { - "config_import": { - "title": "가져오기 확인", - "back_button_description": "뒤로", - "config_imported_toast": "구성을 가져왔습니다!", - "confirm_button": "확인", - "expand_button_description": "확장", - "enable_feature": "기능 활성화", - "enabled": "활성화됨", - "disabled": "비활성화됨" - }, - "config_export": { - "title": "내보내기 요약", - "back_button_description": "뒤로", - "save_button": "저장", - "expand_button_description": "확장", - "enable_feature": "기능 활성화", - "enabled": "활성화됨", - "disabled": "비활성화됨" - } - }, - "manage_repos": { - "title": "{type} 리포지토리 관리", - "add_repo_button": "리포지토리 추가", - "add_repo_dialog_title": "리포지토리 URL 추가", - "repo_url_label": "리포지토리 URL", - "repo_added_successfully": "리포지토리가 성공적으로 추가되었습니다!", - "add_repo_failed": "리포지토리 추가 실패: {message}", - "add_button": "추가", - "no_repos_added": "추가된 리포지토리 없음", - "remove_button": "제거" - } - }, - "rules": { - "toasts": { - "enabled": "{ruleName} 활성화됨", - "disabled": "{ruleName} 비활성화됨" - }, - "modes": { - "blacklist": "블랙리스트 모드", - "whitelist": "화이트리스트 모드" - }, - "properties": { - "auto_download": { - "name": "자동 다운로드", - "description": "스냅을 볼 때 자동으로 다운로드", - "options": { - "blacklist": "자동 다운로드에서 제외", - "whitelist": "자동 다운로드" - } - }, - "stealth": { - "name": "스텔스 모드", - "description": "다른 사람이 내가 그들의 스냅/채팅 및 대화를 열었는지 알 수 없도록 합니다.", - "options": { - "blacklist": "스텔스 모드에서 제외", - "whitelist": "스텔스 모드" - } - }, - "auto_save": { - "name": "자동 저장", - "description": "채팅 메시지를 볼 때 저장", - "options": { - "blacklist": "자동 저장에서 제외", - "whitelist": "자동 저장" - } - }, - "unsaveable_messages": { - "name": "저장할 수 없는 메시지", - "description": "다른 사람이 채팅에서 메시지를 저장하는 것을 방지합니다.", - "options": { - "blacklist": "저장할 수 없는 메시지에서 제외", - "whitelist": "저장할 수 없는 메시지" - } - }, - "auto_open_snaps": { - "name": "스냅 자동 열기", - "description": "스냅을 받을 때 자동으로 엽니다.", - "options": { - "blacklist": "스냅 자동 열기에서 제외", - "whitelist": "스냅 자동 열기" - } - }, - "hide_friend_feed": { - "name": "친구 피드에서 숨기기" - }, - "e2e_encryption": { - "name": "E2E 암호화 사용" - }, - "pin_conversation": { - "name": "대화 고정" - }, - "exclude_message_logger": { - "name": "메시지 로거에서 제외" - } - } - }, - "actions": { - "clean_snapchat_cache": { - "name": "Snapchat 캐시 지우기", - "description": "Snapchat 캐시를 지웁니다." - }, - "manage_friend_list": { - "name": "친구 목록 관리", - "description": "백업 시 친구 목록을 가져오거나 내보냅니다." - }, - "export_chat_messages": { - "name": "채팅 메시지 내보내기", - "description": "대화 메시지를 JSON/HTML/TXT 파일로 내보냅니다." - }, - "export_memories": { - "name": "추억 내보내기", - "description": "추억을 ZIP 파일로 내보냅니다." - }, - "bulk_messaging_action": { - "name": "대량 메시징 작업", - "description": "친구 삭제 또는 대화 대량 삭제와 같은 작업을 수행합니다." - }, - "regen_mappings": { - "name": "매핑 다시 생성", - "description": "매핑을 수동으로 다시 생성합니다." - }, - "change_language": { - "name": "언어 변경", - "description": "PurrfectSnap의 언어를 변경합니다." - }, - "file_imports": { - "name": "파일 가져오기", - "description": "Snapchat에서 사용할 파일을 가져옵니다." - }, - "friend_tracker": { - "name": "친구 추적기", - "description": "Snapchat에서 친구를 추적합니다." - }, - "logger_history": { - "name": "로거 기록", - "description": "기록된 메시지의 기록을 봅니다." - } - }, - "features": { - "notices": { - "unstable": "⚠️ 불안정", - "ban_risk": "⚠️ 이 기능은 차단을 유발할 수 있습니다.", - "internal_behavior": "⚠️ Snapchat의 내부 동작을 손상시킬 수 있습니다." - }, - "properties": { - "downloader": { - "name": "다운로더", - "description": "Snapchat 미디어 다운로드", - "properties": { - "save_folder": { - "name": "폴더 저장", - "description": "모든 미디어를 다운로드할 디렉터리를 선택하세요." - }, - "auto_download_sources": { - "name": "자동 다운로드 소스", - "description": "자동으로 다운로드할 소스를 선택하세요." - }, - "prevent_self_auto_download": { - "name": "자체 자동 다운로드 방지", - "description": "자신의 스냅이 자동으로 다운로드되는 것을 방지합니다." - }, - "path_format": { - "name": "경로 형식", - "description": "파일 경로 형식을 지정하세요." - }, - "allow_duplicate": { - "name": "중복 허용", - "description": "동일한 미디어를 여러 번 다운로드할 수 있습니다." - }, - "merge_overlays": { - "name": "오버레이 병합", - "description": "스냅의 텍스트와 미디어를 단일 파일로 결합합니다." - }, - "force_image_format": { - "name": "이미지 형식 강제", - "description": "이미지를 지정된 형식으로 저장하도록 강제합니다." - }, - "force_voice_note_format": { - "name": "음성 메모 형식 강제", - "description": "음성 메모를 지정된 형식으로 저장하도록 강제합니다." - }, - "auto_download_voice_notes": { - "name": "음성 메모 자동 다운로드", - "description": "음성 메모를 재생할 때 자동으로 다운로드합니다." - }, - "download_profile_pictures": { - "name": "프로필 사진 다운로드", - "description": "프로필 페이지에서 프로필 사진을 다운로드할 수 있습니다." - }, - "opera_download_button": { - "name": "Opera 다운로드 버튼", - "description": "스냅을 볼 때 오른쪽 상단에 다운로드 버튼을 추가합니다.\n버튼을 길게 누르면 강제로 다운로드됩니다." - }, - "download_context_menu": { - "name": "다운로드 컨텍스트 메뉴", - "description": "컨텍스트 메뉴를 사용하여 대화 또는 스토리에서 메시지를 다운로드/미리보기할 수 있습니다.\n버튼을 길게 누르면 강제로 다운로드됩니다." - }, - "ffmpeg_options": { - "name": "FFmpeg 옵션", - "description": "추가 FFmpeg 옵션을 지정하세요.", - "properties": { - "threads": { - "name": "스레드", - "description": "사용할 스레드 수" - }, - "preset": { - "name": "프리셋", - "description": "변환 속도 설정" - }, - "constant_rate_factor": { - "name": "고정 속도 계수", - "description": "비디오 인코더의 고정 속도 계수 설정\nlibx264의 경우 0에서 51까지" - }, - "video_bitrate": { - "name": "비디오 비트 전송률", - "description": "비디오 비트 전송률 설정(kbps)" - }, - "audio_bitrate": { - "name": "오디오 비트 전송률", - "description": "오디오 비트 전송률 설정(kbps)" - }, - "custom_video_codec": { - "name": "사용자 지정 비디오 코덱", - "description": "사용자 지정 비디오 코덱 설정(예: libx264)" - }, - "custom_audio_codec": { - "name": "사용자 지정 오디오 코덱", - "description": "사용자 지정 오디오 코덱 설정(예: AAC)" - } - } - }, - "logging": { - "name": "로깅", - "description": "미디어 다운로드 시 토스트 메시지 표시" - }, - "custom_path_format": { - "name": "사용자 지정 경로 형식", - "description": "다운로드한 미디어의 사용자 지정 경로 형식 지정\n\n사용 가능한 변수:\n - %username%\n - %source%\n - %hash%\n - %date_time%" - } - } - }, - "user_interface": { - "name": "사용자 인터페이스", - "description": "Snapchat의 모양과 느낌 변경", - "properties": { - "enable_app_appearance": { - "name": "앱 모양 설정 활성화", - "description": "숨겨진 앱 모양 설정을 활성화합니다.\n최신 Snapchat 버전에서는 필요하지 않을 수 있습니다." - }, - "friend_feed_message_preview": { - "name": "친구 피드 메시지 미리보기", - "description": "친구 피드에 마지막 메시지의 미리보기를 표시합니다.", - "properties": { - "amount": { - "name": "양", - "description": "미리 볼 메시지 양" - } - } - }, - "snap_preview": { - "name": "스냅 미리보기", - "description": "채팅에서 보지 않은 스냅 옆에 작은 미리보기를 표시합니다." - }, - "bootstrap_override": { - "name": "부트스트랩 재정의", - "description": "사용자 인터페이스 부트스트랩 설정을 재정의합니다.", - "properties": { - "app_appearance": { - "name": "앱 모양", - "description": "영구적인 앱 모양을 설정합니다." - }, - "home_tab": { - "name": "홈 탭", - "description": "Snapchat을 열 때 시작 탭을 재정의합니다." - } - } - }, - "force_amoled_theme": { - "name": "Amoled 다크 모드", - "description": "다크 테마에 순수 검정 배경을 사용합니다." - }, - "map_friend_nametags": { - "name": "향상된 친구 지도 이름표", - "description": "Snapmap에서 친구의 이름표를 개선합니다." - }, - "prevent_message_list_auto_scroll": { - "name": "메시지 목록 자동 스크롤 방지", - "description": "메시지를 보내거나 받을 때 메시지 목록이 맨 아래로 스크롤되는 것을 방지합니다." - }, - "streak_expiration_info": { - "name": "연속 기록 만료 정보 표시", - "description": "연속 기록 카운터 옆에 연속 기록 만료 타이머를 표시합니다." - }, - "hide_friend_feed_entry": { - "name": "친구 피드 항목 숨기기", - "description": "친구 피드에서 특정 친구를 숨깁니다.\n이 기능을 관리하려면 소셜 탭을 사용하세요." - }, - "hide_streak_restore": { - "name": "연속 기록 복원 숨기기", - "description": "친구 피드에서 복원 버튼을 숨깁니다." - }, - "hide_quick_add_suggestions": { - "name": "빠른 추가 제안 숨기기", - "description": "빠른 추가 친구 제안을 제거합니다." - }, - "hide_story_suggestions": { - "name": "스토리 제안 숨기기", - "description": "스토리 페이지에서 제안을 제거합니다." - }, - "hide_ui_components": { - "name": "UI 구성 요소 숨기기", - "description": "숨길 UI 구성 요소를 선택하세요." - }, - "opera_media_quick_info": { - "name": "Opera 미디어 빠른 정보", - "description": "opera 뷰어 컨텍스트 메뉴에 생성 날짜와 같은 미디어의 유용한 정보를 표시합니다." - }, - "old_bitmoji_selfie": { - "name": "오래된 Bitmoji 셀카", - "description": "이전 Snapchat 버전의 Bitmoji 셀카를 다시 가져옵니다." - }, - "disable_spotlight": { - "name": "Spotlight 비활성화", - "description": "Spotlight 페이지를 비활성화합니다." - }, - "friend_feed_menu_buttons": { - "name": "친구 피드 메뉴 버튼", - "description": "친구 피드 메뉴에 표시할 버튼을 선택하세요." - }, - "auto_close_friend_feed_menu": { - "name": "친구 피드 메뉴 자동 닫기", - "description": "설정 버튼을 누르면 친구 피드 메뉴가 자동으로 닫힙니다." - }, - "vertical_story_viewer": { - "name": "세로 스토리 뷰어", - "description": "모든 스토리에 대해 세로 스토리 뷰어를 활성화합니다." - }, - "enable_friend_feed_menu_bar": { - "name": "친구 피드 메뉴 바", - "description": "새로운 친구 피드 메뉴 바를 활성화합니다." - }, - "message_indicators": { - "name": "메시지 표시기", - "description": "메시지에 특정 표시기 아이콘을 추가합니다.\n참고: 표시기가 100% 정확하지 않을 수 있습니다." - }, - "stealth_mode_indicator": { - "name": "스텔스 모드 표시기", - "description": "스텔스 모드의 대화 옆에 👻 이모티콘을 추가합니다." - }, - "edit_text_override": { - "name": "텍스트 편집 재정의", - "description": "텍스트 필드 동작을 재정의합니다." - }, - "prevent_forced_keyboard": { - "name": "강제 키보드 방지", - "description": "대화를 열 때 Snapchat이 자동으로 키보드를 표시하는 것을 방지합니다." - }, - "settings_menu": { - "name": "설정 메뉴", - "description": "PurrfectSnap 메뉴를 여는 방식을 변경합니다.", - "options": { - "default": "기본값", - "legacy": "레거시" - } - } - } - }, - "messaging": { - "name": "메시징", - "description": "친구와 상호 작용하는 방식 변경", - "properties": { - "bypass_screenshot_detection": { - "name": "스크린샷 감지 우회", - "description": "스크린샷을 찍을 때 Snapchat이 감지하는 것을 방지합니다." - }, - "anonymous_story_viewing": { - "name": "익명 스토리 보기", - "description": "다른 사람이 내가 그들의 스토리를 본 것을 알 수 없도록 합니다." - }, - "prevent_story_rewatch_indicator": { - "name": "스토리 재시청 표시기 방지", - "description": "다른 사람이 내가 그들의 스토리를 다시 본 것을 알 수 없도록 합니다." - }, - "hide_peek_a_peek": { - "name": "Peek-a-Peek 숨기기", - "description": "채팅에 반쯤 스와이프할 때 알림이 전송되는 것을 방지합니다." - }, - "hide_bitmoji_presence": { - "name": "Bitmoji 존재 숨기기", - "description": "채팅 중에 Bitmoji가 나타나는 것을 방지합니다." - }, - "hide_typing_notifications": { - "name": "입력 알림 숨기기", - "description": "다른 사람이 내가 메시지를 입력하고 있다는 것을 알 수 없도록 합니다." - }, - "unlimited_snap_view_time": { - "name": "무제한 스냅 보기 시간", - "description": "스냅 보기 시간 제한을 제거합니다." - }, - "auto_mark_as_read": { - "name": "자동으로 읽음으로 표시", - "description": "스텔스 모드가 활성화된 경우에도 메시지/스냅을 자동으로 읽음으로 표시합니다." - }, - "mark_snap_as_seen_button": { - "name": "스냅을 읽음으로 표시 버튼", - "description": "스냅을 볼 때 읽음으로 표시하는 버튼을 추가합니다.\n스텔스 모드가 활성화된 경우에도 작동합니다." - }, - "skip_when_marking_as_seen": { - "name": "읽음으로 표시할 때 건너뛰기", - "description": "스냅을 읽음으로 표시할 때 자동으로 다음 스냅으로 건너뜁니다.\n스냅을 읽음으로 표시 버튼과 함께 사용하세요." - }, - "loop_media_playback": { - "name": "미디어 루프 재생", - "description": "스냅/스토리를 볼 때 미디어를 루프 재생합니다." - }, - "disable_replay_in_ff": { - "name": "FF에서 다시 보기 비활성화", - "description": "친구 피드에서 길게 눌러 다시 보는 기능을 비활성화합니다." - }, - "half_swipe_notifier": { - "name": "반 스와이프 알림", - "description": "누군가 대화에 반쯤 스와이프하면 알려줍니다.", - "properties": { - "min_duration": { - "name": "최소 시간", - "description": "반 스와이프의 최소 시간(초)" - }, - "max_duration": { - "name": "최대 시간", - "description": "반 스와이프의 최대 시간(초)" - } - } - }, - "call_start_confirmation": { - "name": "통화 시작 확인", - "description": "통화를 시작할 때 확인 대화 상자를 표시합니다." - }, - "unlimited_conversation_pinning": { - "name": "무제한 대화 고정", - "description": "로컬에서 무제한으로 대화를 고정할 수 있습니다." - }, - "disable_snap_mode_restrictions": { - "name": "스냅 모드 제한 비활성화", - "description": "제한 없이 자동 파괴 스냅을 볼 수 있습니다." - }, - "prevent_message_sending": { - "name": "메시지 전송 방지", - "description": "특정 유형의 메시지 전송을 방지합니다." - }, - "friend_mutation_notifier": { - "name": "친구 변경 알림", - "description": "친구 프로필에 변경 사항이 있을 때 알려줍니다." - }, - "better_notifications": { - "name": "더 나은 알림", - "description": "받은 알림에 더 많은 정보를 추가합니다.", - "properties": { - "group_notifications": { - "name": "그룹 알림", - "description": "알림을 하나로 그룹화" - }, - "chat_preview": { - "name": "채팅 미리보기", - "description": "알림에 받은 메시지의 미리보기를 표시합니다." - }, - "media_preview": { - "name": "미디어 미리보기", - "description": "알림에 선택한 미디어 유형의 미리보기를 표시합니다." - }, - "media_caption": { - "name": "미디어 캡션", - "description": "알림에 미디어의 첨부된 캡션을 표시합니다." - }, - "stacked_media_messages": { - "name": "스택된 미디어 메시지", - "description": "미리 볼 수 없을 때 여러 미디어 메시지를 하나의 텍스트 알림으로 결합합니다. 채팅 미리보기와 함께 사용하세요." - }, - "friend_add_source": { - "name": "친구 추가 소스", - "description": "알림에 친구 요청의 소스를 표시합니다." - }, - "reply_button": { - "name": "답장 버튼", - "description": "알림에 답장 버튼을 추가합니다." - }, - "smart_replies": { - "name": "스마트 답장", - "description": "알림에 제안된 답장을 추가합니다(Android 10 이상). 답장 버튼과 함께 사용하세요." - }, - "download_button": { - "name": "다운로드 버튼", - "description": "알림에서 미디어를 다운로드할 수 있습니다." - }, - "mark_as_read_button": { - "name": "읽음으로 표시 버튼", - "description": "알림에서 메시지를 읽음으로 표시할 수 있습니다." - }, - "mark_as_read_and_save_in_chat": { - "name": "읽음으로 표시하고 채팅에 저장", - "description": "알림에 읽음으로 표시하고 채팅에 저장 버튼을 추가합니다." - } - } - }, - "notification_blacklist": { - "name": "알림 블랙리스트", - "description": "차단할 알림을 선택하세요." - }, - "message_logger": { - "name": "메시지 로거", - "description": "메시지가 삭제되는 것을 방지합니다.", - "properties": { - "keep_my_own_messages": { - "name": "내 메시지 유지", - "description": "자신의 메시지가 삭제되는 것을 방지합니다." - }, - "auto_purge": { - "name": "자동 제거", - "description": "지정된 시간보다 오래된 캐시된 메시지를 자동으로 삭제합니다." - }, - "message_filter": { - "name": "메시지 필터", - "description": "기록할 메시지를 선택하세요(모든 메시지의 경우 비워 둠)." - }, - "deleted_message_color": { - "name": "삭제된 메시지 색상", - "description": "삭제된 메시지의 색상을 설정합니다." - } - } - }, - "auto_save_messages_in_conversations": { - "name": "대화에서 메시지 자동 저장", - "description": "대화의 모든 메시지를 자동으로 저장합니다." - }, - "gallery_media_send_override": { - "name": "갤러리 미디어 전송 재정의", - "description": "갤러리에서 보낼 때 미디어 소스를 속입니다." - }, - "strip_media_metadata": { - "name": "미디어 메타데이터 제거", - "description": "메시지로 보내기 전에 미디어의 메타데이터를 제거합니다." - }, - "bypass_message_retention_policy": { - "name": "메시지 보존 정책 우회", - "description": "메시지를 본 후 삭제되는 것을 방지합니다." - }, - "bypass_message_action_restrictions": { - "name": "메시지 작업 제한 우회", - "description": "스냅을 열지 않고 반응하거나 저장할 수 없는 메시지를 저장할 수 있습니다." - }, - "remove_groups_locked_status": { - "name": "그룹 잠금 상태 제거", - "description": "추방된 후 그룹 정보를 볼 수 있습니다." - }, - "double_tap_chat_action": { - "name": "더블 탭 채팅 작업", - "description": "채팅에서 메시지를 더블 탭하면 사용자 지정 작업을 수행합니다." - }, - "double_tap_chat_action_custom_emoji": { - "name": "더블 탭 채팅 작업 사용자 지정 이모티콘 반응", - "description": "더블 탭 채팅 작업에 대한 사용자 지정 이모티콘 반응을 설정합니다." - } - } - }, - "global": { - "name": "전역", - "description": "전역 Snapchat 설정 조정", - "properties": { - "better_location": { - "name": "더 나은 위치", - "description": "Snapchat 위치를 향상시킵니다.", - "properties": { - "spoof_location": { - "name": "위치 속이기", - "description": "위치를 지정된 위치로 속입니다." - }, - "coordinates": { - "name": "좌표", - "description": "속인 위치의 좌표를 설정합니다." - }, - "walk_radius": { - "name": "걷기 반경", - "description": "이 반경 내에서 무작위로 걷습니다(피트)." - }, - "always_update_location": { - "name": "항상 위치 업데이트", - "description": "GPS 데이터가 수신되지 않아도 Snapchat이 위치를 업데이트하도록 강제합니다." - }, - "suspend_location_updates": { - "name": "위치 업데이트 일시 중지", - "description": "위치가 업데이트되는 것을 방지합니다." - }, - "spoof_battery_level": { - "name": "배터리 수준 속이기", - "description": "지도에서 장치의 배터리 수준을 속입니다.\n값은 0에서 100 사이여야 합니다." - }, - "spoof_headphones": { - "name": "헤드폰 속이기", - "description": "지도에서 음악을 듣는 상태를 속입니다." - }, - "show_battery_level": { - "name": "배터리 수준 표시", - "description": "지도에서 친구의 배터리 수준을 표시합니다." - } - } - }, - "snapchat_plus": { - "name": "스냅챗 플러스", - "description": "Snapchat Plus 기능을 활성화합니다.\n일부 서버 측 기능은 작동하지 않을 수 있습니다." - }, - "media_upload_quality": { - "name": "미디어 업로드 품질", - "description": "미디어 업로드 품질을 재정의합니다.", - "properties": { - "force_video_upload_source_quality": { - "name": "비디오 업로드 소스 품질 강제", - "description": "비디오를 업로드할 때 Snapchat이 소스 품질을 사용하도록 강제합니다.\n이렇게 하면 미디어에서 메타데이터가 제거되지 않을 수 있습니다." - }, - "disable_image_compression": { - "name": "이미지 압축 비활성화", - "description": "미디어를 업로드할 때 이미지 압축을 비활성화합니다." - }, - "custom_image_upload_format": { - "name": "사용자 지정 이미지 업로드 형식", - "description": "사용자 지정 이미지 업로드 형식을 설정합니다.\n최상의 품질을 위해 무손실 형식(예: PNG)을 선택하세요." - } - } - }, - "disable_confirmation_dialogs": { - "name": "확인 대화 상자 비활성화", - "description": "선택한 작업을 자동으로 확인합니다." - }, - "auto_updater": { - "name": "자동 업데이터", - "description": "새 업데이트를 자동으로 확인합니다." - }, - "disable_metrics": { - "name": "메트릭 비활성화", - "description": "Snapchat에 특정 분석 데이터를 보내는 것을 차단합니다." - }, - "disable_story_sections": { - "name": "스토리 섹션 비활성화", - "description": "스토리 페이지에서 섹션을 제거합니다.\n올바르게 작동하려면 새로 고침해야 할 수 있습니다." - }, - "block_ads": { - "name": "광고 차단", - "description": "광고가 표시되는 것을 방지합니다." - }, - "disable_custom_tabs": { - "name": "사용자 지정 탭 비활성화", - "description": "웹 브라우저 대신 지원되는 응용 프로그램에서 링크를 엽니다." - }, - "disable_permission_requests": { - "name": "권한 요청 비활성화", - "description": "Snapchat이 특정 권한을 요청하는 것을 방지합니다." - }, - "disable_memories_snap_feed": { - "name": "추억 스냅 피드 비활성화", - "description": "카메라에서 위로 스와이프할 때 Snapchat이 최근 추억을 표시하는 것을 방지합니다." - }, - "spotlight_comments_username": { - "name": "Spotlight 댓글 사용자 이름", - "description": "Spotlight 댓글에 작성자의 사용자 이름을 표시합니다." - }, - "bypass_video_length_restriction": { - "name": "비디오 길이 제한 우회", - "description": "단일: 단일 비디오를 보냅니다.\n분할: 편집 후 비디오를 분할합니다." - }, - "default_video_playback_rate": { - "name": "기본 비디오 재생 속도", - "description": "비디오 재생의 기본 속도를 설정합니다.\n값은 0.1에서 4.0 사이여야 합니다." - }, - "video_playback_rate_slider": { - "name": "비디오 재생 속도 슬라이더", - "description": "비디오 재생 속도를 변경하기 위해 opera 컨텍스트 메뉴에 슬라이더를 추가합니다.\n참고: 변경 사항은 후속 비디오에만 적용됩니다." - }, - "disable_google_play_dialogs": { - "name": "Google Play 서비스 대화 상자 비활성화", - "description": "Google Play 서비스 가용성 대화 상자가 표시되는 것을 방지합니다." - }, - "default_volume_controls": { - "name": "기본 볼륨 컨트롤", - "description": "Snapchat이 시스템 볼륨 컨트롤을 사용하도록 강제합니다." - }, - "disable_telecom_framework": { - "name": "통신 프레임워크 비활성화", - "description": "Snapchat이 Android 통신 프레임워크를 사용하는 것을 방지합니다.\n이렇게 하면 통화 중에 음악을 들을 수 있습니다." - }, - "hide_active_music": { - "name": "활성 음악 숨기기", - "description": "Snapchat이 내가 음악을 듣고 있다는 것을 알 수 없도록 합니다.\n이렇게 하면 음악을 들으면서 볼륨 조절 버튼을 사용하여 스냅을 찍을 수 있습니다." - }, - "disable_snap_splitting": { - "name": "스냅 분할 비활성화", - "description": "스냅이 여러 부분으로 분할되는 것을 방지합니다.\n보내는 사진이 비디오로 바뀝니다." - } - } - }, - "rules": { - "name": "규칙", - "description": "개별 사용자에 대한 자동 기능 관리" - }, - "camera": { - "name": "카메라", - "description": "완벽한 스냅을 위해 올바른 설정 조정", - "properties": { - "disable_cameras": { - "name": "카메라 비활성화", - "description": "Snapchat이 선택한 카메라를 사용하는 것을 방지합니다." - }, - "black_photos": { - "name": "검은색 사진", - "description": "촬영한 사진을 검은색 배경으로 바꿉니다.\n비디오는 영향을 받지 않습니다." - }, - "immersive_camera_preview": { - "name": "몰입형 미리보기", - "description": "Snapchat이 카메라 미리보기를 자르는 것을 방지합니다.\n일부 장치에서 카메라가 깜박일 수 있습니다." - }, - "override_front_resolution": { - "name": "전면 해상도 재정의", - "description": "전면 카메라의 카메라 해상도를 재정의합니다." - }, - "override_back_resolution": { - "name": "후면 해상도 재정의", - "description": "후면 카메라의 카메라 해상도를 재정의합니다." - }, - "custom_resolution": { - "name": "사용자 지정 해상도", - "description": "사용자 지정 카메라 해상도를 설정합니다. 너비 x 높이(예: 1920x1080).\n사용자 지정 해상도는 장치에서 지원해야 합니다." - }, - "front_custom_frame_rate": { - "name": "전면 사용자 지정 프레임 속도", - "description": "전면 카메라의 프레임 속도를 재정의합니다." - }, - "back_custom_frame_rate": { - "name": "후면 사용자 지정 프레임 속도", - "description": "후면 카메라의 프레임 속도를 재정의합니다." - }, - "force_camera_source_encoding": { - "name": "카메라 소스 인코딩 강제", - "description": "카메라 소스 인코딩을 강제합니다." - }, - "startup_default_camera": { - "name": "시작 기본 카메라", - "description": "Snapchat을 열 때 기본 카메라를 설정합니다." - }, - "hevc_recording": { - "name": "HEVC 녹화", - "description": "비디오 녹화에 HEVC(H.265) 코덱을 사용합니다." - } - } - }, - "streaks_reminder": { - "name": "연속 기록 알림", - "description": "연속 기록에 대해 주기적으로 알려줍니다.", - "properties": { - "interval": { - "name": "간격", - "description": "각 알림 사이의 간격(시간)" - }, - "remaining_hours": { - "name": "남은 시간", - "description": "알림이 표시되기까지 남은 시간(시간)" - }, - "group_notifications": { - "name": "그룹 알림", - "description": "알림을 하나로 그룹화" - } - } - }, - "experimental": { - "name": "실험적", - "description": "실험적 기능", - "properties": { - "native_hooks": { - "name": "네이티브 후크", - "description": "Snapchat의 네이티브 코드에 후크하는 안전하지 않은 기능", - "properties": { - "composer_hooks": { - "name": "컴포저 후크", - "description": "컴포저 크로스 플랫폼 UI 프레임워크에 코드를 삽입합니다.", - "properties": { - "show_first_created_username": { - "name": "처음 생성된 사용자 이름 표시", - "description": "프로필 페이지의 현재 사용자 이름 옆에 처음 생성된 사용자 이름을 표시합니다." - }, - "bypass_camera_roll_limit": { - "name": "카메라 롤 제한 우회", - "description": "카메라 롤에서 보낼 수 있는 미디어의 최대 양을 늘립니다." - }, - "custom_self_destruct_snap_delay": { - "name": "사용자 지정 자동 파괴 스냅 지연", - "description": "스냅을 보낼 때 자동 파괴 타이머에 대한 더 많은 옵션을 제공합니다." - }, - "composer_console": { - "name": "컴포저 콘솔", - "description": "컴포저에서 JavaScript 코드를 실행할 수 있습니다(arm64만 해당)." - }, - "composer_logs": { - "name": "컴포저 로그", - "description": "컴포저의 콘솔 로그를 PurrfectSnap으로 리디렉션합니다." - } - } - }, - "disable_bitmoji": { - "name": "Bitmoji 비활성화", - "description": "친구 프로필 Bitmoji를 비활성화합니다." - }, - "custom_emoji_font": { - "name": "사용자 지정 이모티콘 글꼴", - "description": "사용자 지정 이모티콘 글꼴을 사용할 수 있습니다. .ttf 글꼴에서만 작동합니다." - }, - "custom_shared_library": { - "name": "사용자 지정 공유 라이브러리", - "description": "사용자 지정 공유 라이브러리를 Snapchat에 로드합니다. 이 기능은 테스트 목적으로만 사용됩니다." - } - } - }, - "spoof": { - "name": "스푸핑", - "description": "자신에 대한 다양한 정보를 속입니다.", - "properties": { - "play_store_installer_package_name": { - "name": "Play 스토어 설치 프로그램 패키지 이름", - "description": "설치 프로그램 패키지 이름을 com.android.vending으로 재정의합니다." - }, - "remove_vpn_transport_flag": { - "name": "VPN 전송 플래그 제거", - "description": "Snapchat이 VPN을 감지하는 것을 방지합니다." - }, - "remove_mock_location_flag": { - "name": "모의 위치 플래グ 제거", - "description": "Snapchat이 모의 위치를 감지하는 것을 방지합니다." - } - } - }, - "convert_message_locally": { - "name": "로컬에서 메시지 변환", - "description": "스냅을 로컬에서 채팅 외부 미디어로 변환합니다. 이는 채팅 다운로드 컨텍스트 메뉴에 나타납니다." - }, - "media_file_picker": { - "name": "미디어 파일 선택기", - "description": "갤러리에서 모든 비디오/오디오 파일을 선택할 수 있습니다." - }, - "story_logger": { - "name": "스토리 로거", - "description": "친구 스토리의 기록을 제공합니다." - }, - "call_recorder": { - "name": "통화 녹음기", - "description": "음성 통화를 자동으로 녹음합니다." - }, - "account_switcher": { - "name": "계정 전환기", - "description": "로그아웃하지 않고 계정 간에 전환할 수 있습니다.\n메뉴를 열려면 Bitmoji 프로필 옆의 검색 아이콘을 길게 누릅니다.\n참고: 이 기능은 실험적이며 향후 변경될 수 있습니다.", - "properties": { - "auto_backup_current_account": { - "name": "현재 계정 자동 백업", - "description": "로그아웃하거나 계정을 전환할 때 현재 계정을 자동으로 백업합니다." - } - } - }, - "better_transcript": { - "name": "더 나은 녹취록", - "description": "음성 메모 녹취록을 개선합니다.", - "properties": { - "force_transcription": { - "name": "음성 메모 녹취 강제", - "description": "모든 음성 메모를 녹취할 수 있습니다." - }, - "preferred_transcription_lang": { - "name": "선호하는 녹취 언어", - "description": "음성 메모 녹취에 선호하는 언어(예: EN, ES, FR)" - }, - "notification_transcript": { - "name": "알림 녹취록", - "description": "알림에서 음성 메모를 녹취합니다.\n이 기능을 사용하려면 더 나은 알림에서 채팅 미리보기 기능을 활성화해야 합니다." - } - } - }, - "voice_note_auto_play": { - "name": "음성 메모 자동 재생", - "description": "현재 음성 메모가 끝나면 다음 음성 메모를 자동으로 재생합니다." - }, - "friend_notes": { - "name": "친구 메모", - "description": "친구 프로필에 메모를 추가할 수 있습니다." - }, - "cof_experiments": { - "name": "COF 실험", - "description": "미공개/베타 Snapchat 기능을 활성화합니다." - }, - "context_menu_fix": { - "name": "컨텍스트 메뉴 수정", - "description": "장치가 오프라인일 때 올바르게 표시되지 않을 수 있으므로 친구 피드 메뉴를 복구하려고 시도합니다." - }, - "app_lock": { - "name": "앱 잠금", - "description": "암호 없이 Snapchat에 액세스하는 것을 방지합니다.", - "properties": { - "lock_on_resume": { - "name": "재개 시 잠금", - "description": "다시 열 때 앱을 잠급니다." - } - } - }, - "infinite_story_boost": { - "name": "무한 스토리 부스트", - "description": "스토리 부스트 제한 지연을 우회합니다." - }, - "meo_passcode_bypass": { - "name": "My Eyes Only 암호 우회", - "description": "My Eyes Only 암호를 우회합니다.\n암호가 이전에 올바르게 입력된 경우에만 작동합니다." - }, - "no_friend_score_delay": { - "name": "친구 점수 지연 없음", - "description": "친구 점수를 볼 때 지연을 제거합니다." - }, - "best_friend_pinning": { - "name": "가장 친한 친구 고정", - "description": "친구를 최고의 친구로 고정할 수 있습니다. 참고: 고정된 가장 친한 친구는 나만 볼 수 있습니다." - }, - "e2ee": { - "name": "종단 간 암호화", - "description": "공유 비밀 키를 사용하여 AES로 메시지를 암호화합니다.\n키를 안전한 곳에 보관하세요!", - "properties": { - "encrypted_message_indicator": { - "name": "암호화된 메시지 표시기", - "description": "암호화된 메시지 옆에 🔒 이모티콘을 추가합니다." - }, - "force_message_encryption": { - "name": "메시지 암호화 강제", - "description": "여러 대화가 선택된 경우에만 E2E 암호화가 활성화되지 않은 사람에게 암호화된 메시지를 보내는 것을 방지합니다." - } - } - }, - "add_friend_source_spoof": { - "name": "친구 추가 소스 속이기", - "description": "친구 요청의 소스를 속입니다." - }, - "hidden_snapchat_plus_features": { - "name": "숨겨진 Snapchat Plus 기능", - "description": "미공개/베타 Snapchat Plus 기능을 활성화합니다.\n이전 Snapchat 버전에서는 작동하지 않을 수 있습니다." - }, - "custom_streaks_expiration_format": { - "name": "사용자 지정 연속 기록 만료 형식", - "description": "연속 기록 만료 형식을 사용자 지정합니다.\n\n사용 가능한 변수:\n - %c: 연속 기록 수\n - %e: 모래시계 이모티콘\n - %d: 일\n - %h: 시간\n - %m: 분\n - %s: 초\n - %w: 남은 시간" - }, - "prevent_forced_logout": { - "name": "강제 로그아웃 방지", - "description": "다른 장치에서 로그인할 때 Snapchat이 로그아웃하는 것을 방지합니다." - }, - "snapscore_changes": { - "name": "Snapscore 변경 사항", - "description": "친구의 Snapscore 변경 사항을 추적합니다.\n이 기능은 최신 버전의 Snapchat에서만 사용하세요." - } - } - }, - "scripting": { - "name": "스크립팅", - "description": "PurrfectSnap을 확장하기 위해 사용자 지정 스크립트를 실행합니다.", - "properties": { - "developer_mode": { - "name": "개발자 모드", - "description": "Snapchat의 UI에 디버그 정보를 표시합니다." - }, - "module_folder": { - "name": "모듈 폴더", - "description": "스크립트가 있는 폴더" - }, - "auto_reload": { - "name": "자동 새로고침", - "description": "스크립트가 변경될 때 자동으로 새로고침합니다." - }, - "integrated_ui": { - "name": "통합 UI", - "description": "스크립트가 Snapchat에 사용자 지정 UI 구성 요소를 추가할 수 있도록 합니다." - }, - "disable_log_anonymization": { - "name": "로그 익명화 비활성화", - "description": "로그의 익명화를 비활성화합니다." - }, - "disable_optimization": { - "name": "최적화 비활성화", - "description": "스크립트의 최적화를 비활성화합니다. 성능 문제가 발생할 수 있습니다." - } - } - }, - "friend_tracker": { - "name": "친구 추적기", - "description": "Snapchat에서 친구의 활동을 기록합니다.", - "properties": { - "record_messaging_events": { - "name": "메시징 이벤트 기록", - "description": "스냅 열기, 메시지 읽기 등과 같은 메시징 이벤트를 기록합니다." - }, - "allow_running_in_background": { - "name": "백그라운드에서 실행 허용", - "description": "추적기가 백그라운드에서 실행되도록 허용합니다. 참고: 배터리가 크게 소모됩니다." - }, - "auto_purge": { - "name": "자동 제거", - "description": "지정된 시간보다 오래된 캐시된 이벤트를 자동으로 삭제합니다." - } - } - } - }, - "options": { - "app_appearance": { - "always_light": "항상 라이트", - "always_dark": "항상 다크" - }, - "friend_feed_menu_buttons": { - "auto_download": "⬇️ 자동 다운로드", - "auto_save": "💬 메시지 자동 저장", - "unsaveable_messages": "⬇️ 저장할 수 없는 메시지", - "auto_open_snaps": "📸 스냅 자동 열기", - "stealth": "👻 스텔스 모드", - "mark_snaps_as_seen": "👀 스냅을 읽음으로 표시", - "mark_stories_as_seen_locally": "👀 스토리를 로컬에서 읽음으로 표시", - "conversation_info": "🧑‍🤝‍🧑 대화 정보", - "e2e_encryption": "🔒 E2E 암호화 사용" - }, - "path_format": { - "create_author_folder": "작성자별로 폴더 만들기", - "create_source_folder": "미디어 소스 유형별로 폴더 만들기", - "append_hash": "파일 이름에 고유 해시 추가", - "append_source": "파일 이름에 미디어 소스 추가", - "append_username": "파일 이름에 사용자 이름 추가", - "append_date_time": "파일 이름에 날짜 및 시간 추가" - }, - "auto_download_sources": { - "friend_snaps": "친구 스냅", - "friend_stories": "친구 스토리", - "public_stories": "공개 스토리", - "spotlight": "스포트라이트" - }, - "logging": { - "started": "시작됨", - "success": "성공", - "progress": "진행 중", - "failure": "실패" - }, - "notifications": { - "chat_screenshot": "스크린샷", - "chat_screen_record": "화면 녹화", - "snap_replay": "스냅 다시 보기", - "camera_roll_save": "카메라 롤에 저장", - "chat": "채팅", - "chat_reply": "채팅 답장", - "snap": "스냅", - "typing": "입력 중", - "stories": "스토리", - "speaking": "말하는 중", - "chat_reaction": "DM 반응", - "group_chat_reaction": "그룹 반응", - "initiate_audio": "수신 음성 통화", - "abandon_audio": "부재중 음성 통화", - "initiate_video": "수신 영상 통화", - "abandon_video": "부재중 영상 통화", - "map_live_location": "지도 라이브 위치" - }, - "gallery_media_send_override": { - "always_ask": "항상 묻기", - "ORIGINAL": "원본 미디어", - "NOTE": "음성 메모", - "SNAP": "스냅", - "SAVEABLE_SNAP": "저장 가능한 스냅" - }, - "strip_media_metadata": { - "hide_caption_text": "캡션 텍스트 숨기기", - "hide_snap_filters": "스냅 필터 숨기기", - "hide_extras": "추가 항목 숨기기(예: 멘션)", - "remove_audio_note_duration": "음성 메모 길이 제거", - "remove_audio_note_transcript_capability": "음성 메모 녹취 기능 제거" - }, - "hide_ui_components": { - "hide_profile_call_buttons": "프로필 통화 버튼 제거", - "hide_chat_call_buttons": "채팅 통화 버튼 제거", - "hide_live_location_share_button": "라이브 위치 공유 버튼 제거", - "hide_stickers_button": "스티커 버튼 제거", - "hide_voice_record_button": "음성 녹음 버튼 제거", - "hide_unread_chat_hint": "읽지 않은 채팅 힌트 제거", - "hide_post_to_story_buttons": "스냅 전송 전 스토리에 게시 버튼 제거", - "hide_billboard_prompt": "친구 피드에서 빌보드 프롬프트 제거", - "hide_snapchat_plus_gift_reminders": "대화에서 Snapchat Plus 선물 알림 제거", - "hide_map_reactions": "지도 반응 제거" - }, - "hide_story_suggestions": { - "hide_suggested_friend_stories": "제안된 친구 스토리 숨기기", - "hide_my_stories": "내 스토리 숨기기" - }, - "home_tab": { - "map": "지도", - "chat": "채팅", - "camera": "카메라", - "discover": "발견", - "spotlight": "스포트라이트" - }, - "add_friend_source_spoof": { - "added_by_username": "사용자 이름으로", - "added_by_mention": "멘션으로", - "added_by_group_chat": "그룹 채팅으로", - "added_by_qr_code": "QR 코드로", - "added_by_community": "커뮤니티로", - "added_by_quick_add": "빠른 추가로(차단될 위험 높음)" - }, - "bypass_video_length_restriction": { - "single": "단일 미디어", - "split": "분할 미디어" - }, - "old_bitmoji_selfie": { - "2d": "2D 비트모지", - "3d": "3D 비트모지" - }, - "disable_confirmation_dialogs": { - "erase_message": "메시지 지우기", - "remove_friend": "친구 삭제", - "block_friend": "친구 차단", - "ignore_friend": "친구 무시", - "hide_friend": "친구 숨기기", - "hide_conversation": "대화 숨기기", - "clear_conversation": "친구 피드에서 대화 지우기" - }, - "auto_reload": { - "snapchat_only": "Snapchat만", - "all": "모두(Snapchat + PurrfectSnap)" - }, - "edit_text_override": { - "multi_line_chat_input": "여러 줄 채팅 입력", - "bypass_text_input_limit": "텍스트 입력 제한 우회" - }, - "auto_purge": { - "never": "없음", - "1_hour": "1시간", - "3_hours": "3시간", - "6_hours": "6시간", - "12_hours": "12시간", - "1_day": "1일", - "3_days": "3일", - "1_week": "1주", - "2_weeks": "2주", - "1_month": "1개월", - "3_months": "3개월", - "6_months": "6개월" - }, - "disable_story_sections": { - "friends": "친구", - "suggested_stories": "제안된 스토리", - "following": "팔로잉", - "discover": "발견" - }, - "disable_cameras": { - "front": "전면 카메라", - "back": "후면 카메라" - }, - "disable_permission_requests": { - "notifications": "알림", - "read_media_images": "미디어 이미지 읽기", - "read_media_video": "미디어 비디오 읽기", - "camera": "카메라", - "microphone": "마이크", - "location": "위치", - "read_contacts": "연락처 읽기", - "nearby_devices": "주변 장치", - "phone_calls": "전화 통화" - }, - "message_indicators": { - "encryption_indicator": "나에게만 전송된 메시지 옆에 🔒 아이콘을 추가합니다.", - "platform_indicator": "미디어가 전송된 플랫폼 아이콘을 추가합니다(예: Android, iOS, 웹).", - "location_indicator": "위치가 활성화된 상태로 전송된 스냅에 📍 아이콘을 추가합니다.", - "ovf_editor_indicator": "OVF 편집기를 사용하여 스냅이 전송되었는지 여부를 나타냅니다.", - "director_mode_indicator": "갤러리 이미지를 스냅으로 보내는 데 사용할 수 있는 디렉터 모드를 사용하여 전송된 스냅에 🎬 아이콘을 추가합니다." - }, - "auto_mark_as_read": { - "conversation_read": "메시지를 보낼 때 대화를 읽음으로 표시", - "snap_reply": "스냅에 답장할 때 읽음으로 표시", - "save_snap_in_chat": "스텔스 모드에서 채팅에 저장할 때 스냅을 읽음으로 표시" - }, - "friend_mutation_notifier": { - "remove_friend": "누군가 나를 친구에서 삭제하면 알림", - "birthday_changes": "누군가 생일을 변경하면 알림", - "bitmoji_selfie_changes": "누군가 Bitmoji 셀카를 변경하면 알림", - "bitmoji_avatar_changes": "누군가 Bitmoji 아바타를 변경하면 알림", - "bitmoji_background_changes": "누군가 Bitmoji 배경을 변경하면 알림", - "bitmoji_scene_changes": "누군가 Bitmoji 장면을 변경하면 알림" - }, - "snapchat_plus": { - "not_subscribed": "구독하지 않음", - "basic": "기본", - "ad_free": "광고 없음" - }, - "double_tap_chat_action": { - "like_message": "메시지 좋아요", - "copy_text": "클립보드에 텍스트 복사", - "delete_message": "메시지 삭제", - "mark_as_read": "읽음으로 표시", - "custom_emoji_reaction": "사용자 지정 이모티콘 반응" - }, - "startup_default_camera": { - "front": "전면 카메라", - "back": "후면 카메라" - } - } - }, - "friend_menu_option": { - "mark_snaps_as_seen": "스냅을 읽음으로 표시", - "mark_stories_as_seen_locally": "스토리를 로컬에서 읽음으로 표시", - "preview": "미리보기", - "stealth_mode": "스텔스 모드", - "auto_download_blacklist": "자동 다운로드 블랙리스트", - "anti_auto_save": "자동 저장 방지" - }, - "content_type": { - "CHAT": "채팅", - "SNAP": "스냅", - "EXTERNAL_MEDIA": "외부 미디어", - "NOTE": "음성 메모", - "STICKER": "스티커", - "SHARE": "공유", - "STATUS": "상태", - "LOCATION": "위치", - "STATUS_SAVE_TO_CAMERA_ROLL": "카메라 롤에 저장됨", - "STATUS_CONVERSATION_CAPTURE_SCREENSHOT": "스크린샷", - "STATUS_CONVERSATION_CAPTURE_RECORD": "화면 녹화", - "STATUS_CALL_MISSED_VIDEO": "부재중 영상 통화", - "STATUS_CALL_MISSED_AUDIO": "부재중 음성 통화", - "LIVE_LOCATION_SHARE": "라이브 위치 공유", - "CREATIVE_TOOL_ITEM": "크리에이티브 도구 항목", - "FAMILY_CENTER_INVITE": "가족 센터 초대", - "FAMILY_CENTER_ACCEPT": "가족 센터 수락", - "FAMILY_CENTER_LEAVE": "가족 센터 탈퇴", - "STATUS_PLUS_GIFT": "상태 플러스 선물", - "TINY_SNAP": "작은 스냅", - "STATUS_COUNTDOWN": "카운트다운", - "MAP_REACTION": "지도 반응" - }, - "media_download_source": { - "none": "없음", - "pending": "대기 중", - "chat_media": "채팅 미디어", - "story": "스토리", - "public_story": "공개 스토리", - "spotlight": "스포트라이트", - "profile_picture": "프로필 사진", - "story_logger": "스토리 로거", - "message_logger": "메시지 로거", - "merged": "병합됨", - "voice_call": "음성 통화" - }, - "chat_action_menu": { - "preview_button": "미리보기", - "download_button": "다운로드", - "delete_logged_message_button": "기록된 메시지 삭제", - "show_chat_edit_history": "채팅 편집 기록 보기", - "convert_message": "메시지 변환" - }, - "opera_context_menu": { - "download": "미디어 다운로드", - "sent_at": "{date}에 보냄", - "created_at": "{date}에 생성됨", - "expires_at": "{date}에 만료됨", - "media_size": "미디어 크기: {size}", - "media_duration": "미디어 길이: {duration}ms", - "show_debug_info": "디버그 정보 보기" - }, - "modal_option": { - "profile_info": "프로필 정보", - "close": "닫기" - }, - "gallery_media_send_override": { - "multiple_media_toast": "한 번에 하나의 미디어만 보낼 수 있습니다." - }, - "mark_as_seen": { - "no_unseen_snaps_toast": "보지 않은 스냅이 없습니다!", - "seen_toast": "읽음으로 표시됨!", - "unseen_toast": "읽지 않음으로 표시됨!", - "already_seen_toast": "이미 읽음으로 표시됨!", - "already_unseen_toast": "이미 읽지 않음으로 표시됨!" - }, - "conversation_preview": { - "streak_expiration": "{day}일 {hour}시간 {minute}분 후에 만료됨", - "total_messages": "총 송수신 메시지: {count}", - "title": "미리보기", - "unknown_user": "알 수 없는 사용자", - "no_messages": "메시지를 찾을 수 없음!" - }, - "profile_info": { - "title": "프로필 정보", - "first_created_username": "처음 생성된 사용자 이름", - "mutable_username": "변경 가능한 사용자 이름", - "display_name": "표시 이름", - "added_date": "추가된 날짜", - "birthday": "생일: {month} {day}", - "hidden_birthday": "생일: 숨김", - "friendship": "친구 관계", - "add_source": "소스 추가", - "snapchat_plus": "스냅챗 플러스", - "snapchat_plus_state": { - "subscribed": "구독함", - "not_subscribed": "구독하지 않음" - } - }, - "friendship_link_type": { - "mutual": "상호", - "outgoing": "나가는", - "blocked": "차단됨", - "deleted": "삭제됨", - "following": "팔로잉", - "suggested": "제안됨", - "incoming": "들어오는", - "incoming_follower": "들어오는 팔로워" - }, - "bulk_messaging_action": { - "choose_action_title": "작업 선택", - "progress_status": "{total} 중 {index} 처리 중", - "selection_dialog_continue_button": "계속", - "confirmation_dialog": { - "title": "확실합니까?", - "message": "선택한 모든 친구에게 영향을 미칩니다. 이 작업은 되돌릴 수 없습니다." - }, - "actions": { - "remove_friends": "친구 삭제", - "clear_conversations": "대화 지우기" - } - }, - "chat_export": { - "exporter_dialog": { - "select_conversations_title": "대화 선택", - "text_field_selection": "{amount}개 선택됨", - "text_field_selection_all": "모두", - "export_file_format_title": "파일 형식 내보내기", - "message_type_filter_title": "유형별로 메시지 필터링", - "amount_of_messages_title": "메시지 양(모두의 경우 비워 둠)", - "download_medias_title": "미디어 다운로드" - }, - "dialog_negative_button": "취소", - "dialog_positive_button": "내보내기", - "exported_to": "{path}로 내보냄", - "exporting_chats": "채팅 내보내기 중...", - "processing_chats": "{amount}개의 대화 처리 중...", - "export_fail": "대화 {conversation} 내보내기 실패", - "writing_output": "출력 쓰는 중...", - "finished": "완료! 이제 이 대화 상자를 닫을 수 있습니다.", - "no_messages_found": "메시지를 찾을 수 없음!", - "exporting_message": "{conversation} 내보내기 중..." - }, - "button": { - "ok": "확인", - "positive": "예", - "negative": "아니요", - "cancel": "취소", - "open": "열기", - "download": "다운로드", - "send": "보내기", - "restore_original": "원본 복원", - "convert_external_media": "외부 미디어 변환", - "save": "저장" - }, - "tracker_events": { - "conversation_enter": "대화 참여", - "conversation_exit": "대화 나가기", - "started_typing": "입력 시작", - "stopped_typing": "입력 중지", - "started_speaking": "말하기 시작", - "stopped_speaking": "말하기 중지", - "started_peeking": "엿보기 시작", - "stopped_peeking": "엿보기 중지", - "message_read": "메시지 읽음", - "message_deleted": "메시지 삭제됨", - "message_saved": "메시지 저장됨", - "message_unsaved": "메시지 저장되지 않음", - "message_edited": "메시지 편집됨", - "message_reaction_add": "메시지 반응 추가", - "message_reaction_remove": "메시지 반응 제거", - "snap_opened": "스냅 열림", - "snap_replayed": "스냅 다시 보기", - "snap_replayed_twice": "스냅 두 번 다시 보기", - "snap_screenshot": "스냅 스크린샷", - "snap_screen_record": "스냅 화면 녹화" - }, - "tracker_actions": { - "log": "로그", - "in_app_notification": "인앱 알림", - "push_notification": "푸시 알림", - "custom": "사용자 지정" - }, - "better_notifications": { - "button": { - "reply": "답장", - "download": "다운로드", - "mark_as_read": "읽음으로 표시" - } - }, - "profile_picture_downloader": { - "button": "프로필 사진 다운로드", - "title": "프로필 사진 다운로더", - "avatar_option": "아바타", - "background_option": "배경" - }, - "call_start_confirmation": { - "dialog_title": "통화 시작", - "dialog_message": "통화를 시작하시겠습니까?" - }, - "half_swipe_notifier": { - "notification_channel_name": "반 스와이프", - "notification_content_dm": "{friend}님이 {duration}초 동안 채팅에 반쯤 스와이프했습니다.", - "notification_content_group": "{friend}님이 {group}에 {duration}초 동안 반쯤 스와이프했습니다." - }, - "download_processor": { - "attachment_type": { - "snap": "스냅", - "sticker": "스티커", - "gif": "GIF", - "external_media": "외부 미디어", - "note": "메모", - "original_story": "원본 스토리" - }, - "select_attachments_title": "첨부 파일 선택", - "download_started_toast": "다운로드가 시작되었습니다.", - "unsupported_content_type_toast": "지원되지 않는 콘텐츠 유형입니다!", - "failed_no_longer_available_toast": "미디어를 더 이상 사용할 수 없습니다.", - "no_attachments_toast": "첨부 파일을 찾을 수 없습니다!", - "already_queued_toast": "미디어가 이미 대기열에 있습니다!", - "already_downloaded_toast": "미디어가 이미 다운로드되었습니다!", - "content_saved_toast": "저장되었습니다!", - "download_toast": "{path} 다운로드 중...", - "processing_toast": "{path} 처리 중...", - "failed_generic_toast": "다운로드 실패", - "failed_to_create_preview_toast": "미리보기 생성 실패", - "failed_processing_toast": "처리 실패 {error}", - "failed_gallery_toast": "갤러리에 저장 실패 {error}", - "dash_no_chapter": "챕터를 찾을 수 없음", - "dash_dialog": { - "title": "대시 미디어 다운로드", - "download_all": "모두 다운로드", - "segment_text": "세그먼트 {from} - {to}" - } - }, - "streaks_reminder": { - "notification_title": "연속 기록", - "notification_text": "{hoursLeft}시간 후에 {friend}님과의 연속 기록이 끊어집니다." - }, - "biometric_auth": { - "unlock_button": "잠금 해제", - "title": "Snapchat 잠금 해제", - "subtitle": "Snapchat을 잠금 해제하려면 인증하세요." - }, - "end_to_end_encryption": { - "toolbox": { - "no_shared_key": "이 친구와 공유된 비밀이 아직 없습니다. 새 비밀을 시작하려면 아래를 클릭하세요.", - "shared_key_fingerprint": "지문은 다음과 같습니다:\n\n{fingerprint}\n\n친구의 지문과 일치하는지 확인하세요!", - "initiate_exchange_button": "키 교환 시작" - }, - "confirmation_dialogs": { - "title": "종단 간 암호화", - "confirmation_1": "경고: 기존 키를 덮어씁니다. 이 친구로부터의 모든 암호화된 메시지에 대한 액세스 권한을 잃게 됩니다. 계속하시겠습니까?", - "confirmation_2": "정말로 계속하시겠습니까? 이것이 마지막 기회입니다." - }, - "unencrypted_conversation_send_failure_toast": "암호화된 대화와 암호화되지 않은 대화 모두에 암호화된 콘텐츠를 보낼 수 없습니다!", - "native_hooks_send_failure_toast": "전송 실패! 설정에서 네이티브 후크를 활성화하세요.", - "no_participants_to_encrypt_toast": "이 대화에는 메시지를 암호화할 친구가 없습니다!", - "encryption_failed_toast": "메시지 암호화 실패! 자세한 내용은 logcat을 확인하세요.", - "accept_public_key_success_toast": "공개 키가 성공적으로 수락되었습니다!", - "accept_secret_key_success_toast": "완료! 이제 이 친구와 암호화된 메시지를 주고받을 수 있습니다.", - "accept_public_key_failure_toast": "공개 키 수락 실패", - "accept_secret_key_failure_toast": "비밀 키 수락 실패", - "accept_secret_button": "비밀 수락", - "accept_public_key_button": "공개 키 수락", - "outgoing_pk_message": "키 교환 요청", - "outgoing_secret_message": "키 교환 응답", - "incoming_pk_message": "공개 키 요청을 받았습니다. 수락하려면 아래를 클릭하세요.", - "incoming_secret_message": "친구가 방금 공개 키를 수락했습니다. 비밀을 수락하려면 아래를 클릭하세요." - }, - "auto_open_snaps": { - "title": "스냅 자동 열기", - "notification_content": "{count}개의 스냅이 열렸습니다." - }, - "friend_mutation_observer": { - "notification_channel_name": "친구 변경 관찰자", - "friend_removed": "{username}님이 나를 친구에서 삭제했습니다.", - "birthday_removed": "{username}님이 생일({birthday})을 삭제했습니다.", - "birthday_added": "{username}님이 생일({birthday})을 추가했습니다.", - "birthday_changed": "{username}님이 생일을 {oldBirthday}에서 {newBirthday}(으)로 변경했습니다.", - "bitmoji_selfie_changed": "{username}님이 Bitmoji 셀카를 변경했습니다.", - "bitmoji_avatar_changed": "{username}님이 Bitmoji 아바타를 변경했습니다.", - "bitmoji_background_changed": "{username}님이 Bitmoji 배경을 변경했습니다.", - "bitmoji_scene_changed": "{username}님이 Bitmoji 장면을 변경했습니다." - }, - "material3_strings": { - "date_range_picker_start_headline": "시작", - "date_range_picker_end_headline": "종료", - "date_range_picker_title": "날짜 범위 선택", - "date_picker_switch_to_calendar_mode": "달력", - "date_picker_switch_to_input_mode": "입력", - "date_range_picker_scroll_to_previous_month": "이전 달", - "date_range_picker_scroll_to_next_month": "다음 달", - "date_picker_today_description": "오늘", - "date_range_picker_day_in_range": "선택됨", - "date_input_invalid_for_pattern": "잘못된 날짜", - "date_input_invalid_year_range": "잘못된 연도", - "date_input_invalid_not_allowed": "잘못된 날짜", - "date_range_input_invalid_range_input": "잘못된 날짜 범위" - }, - "send_override_dialog": { - "title": "미디어를 {type}으로 보내기", - "duration": "길이: {duration}", - "saveable_snap_hint": "채팅에서 스냅을 저장할 수 있도록 만들기", - "unlimited_duration": "무제한" - }, - "invalid_input_toast": "잘못된 입력입니다! 유효한 값을 입력했는지 확인하세요." -} \ No newline at end of file + } +} diff --git a/common/src/main/assets/lang/la.json b/common/src/main/assets/lang/la.json index 302b0df4..96fd731a 100644 --- a/common/src/main/assets/lang/la.json +++ b/common/src/main/assets/lang/la.json @@ -1,2022 +1,239 @@ { - "setup": { - "dialogs": { - "select_language": "Linguam Selecta", - "save_folder": "PurrfectSnap requirit permissiones repono ut download et salvum Media ex Snapchat.\nElige locum ubi media debet esse recepta.", - "select_save_folder_button": "Selecta Folder" - }, - "mappings": { - "dialog": "Generans Mappings, hoc potest capere aliquantulum...", - "generate_failure_no_snapchat": "PurrfectSnap non potuit deprehendere Snapchat, conare reinstalling Snapchat.", - "generate_failure": "Error occurrit dum conatur generare mappings, conare iterum." - }, - "permissions": { - "dialog": "Continuare debes aptare sequentia requisita:", - "notification_access": "Accessus Notificatio", - "battery_optimization": "Optimisatio Pugna", - "display_over_other_apps": "Super Alias Apps Propono", - "request_button": "Request" - } - }, - "scopes": { - "friend": "Amicus", - "group": "Grex" - }, "manager": { "routes": { - "tasks": "Opera", - "features": "Features", - "manage_rule_feature": "Curo Regula Feature", - "home": "Domus", - "home_settings": "Occasus", - "home_logs": "Acta", - "logger_history": "Logger Historia", + "edit_rule": "Rulus scribere", + "features": "Posse", + "tasks": "Scribere", + "home": "Villa", + "home_settings": "Deus maximae", + "home_logs": "Papyrus", + "social": "Socius", + "logger_history": "Logger History", "logged_stories": "Initium Stories", "friend_tracker": "Amicus Tracker", - "edit_rule": "Recensere Regula", - "file_imports": "File Importat", - "manage_repos": "Curo Repositories", - "social": "Socialis", - "manage_scope": "Curo Scope", - "messaging_preview": "Praevisum", - "scripts": "Scripta", - "better_location": "Melior Locus" + "messaging_preview": "Praevius", + "scripts": "Scriptores", + "manage_scope": "Curo Scope" }, "sections": { "home": { - "version_title": "v{versionName} · furcatum ab Aeterno", - "update_title": "PurrfectSnap Update", - "update_content": "Versio {version} praesto est!", - "update_button": "Download", - "debug_build_summary_title": "Tu curris a debug aedificare de PurrfectSnap", - "debug_build_summary_content": "Versio {versionName} ({versionCode})", - "debug_build_summary_date": "Aedificare diem: {date} ({days} diebus ago)", - "quick_actions_title": "Velox Actiones", - "download_icon_description": "Download", - "completed_icon_description": "Completur", - "failed_icon_description": "Deficio", - "manage_quick_actions_description": "Curo Velox Actiones", - "quick_actions_icon_description": "Velox Actiones", - "add_quick_action_description": "Addere Velox Actio" + "update_title": "SnapEnhance Update", + "update_content": "Versione {version} praesto est!", + "update_button": "Download" }, "home_logs": { - "no_logs_hint": "Nulla acta praesto", - "clear_logs_button": "Acta Purgare", - "export_logs_button": "Acta Exportare", - "saving_logs_toast": "Salvum acta, hoc potest capere aliquantulum...", + "clear_logs_button": "Patet Acta publica omnia", + "export_logs_button": "Acta publica exportare", "saved_logs_success_toast": "Acta servata feliciter", - "saved_logs_failure_toast": "Deficio servare acta" + "saved_logs_failure_toast": "Non servare omnia", + "no_logs_hint": "Nulla omnia praesto", + "saving_logs_toast": "Salvis lignis, hoc potest capere aliquantulum..." }, "home_settings": { "actions_title": "Actiones", "message_logger_title": "Nuntius Logger", - "debug_title": "Debug", - "success_toast": "Actum!", - "message_logger_summary": "{messageCount} nuntii\n{storyCount} fabulae", + "debug_title": "Debugere", + "success_toast": "Finis!", + "message_logger_summary": "{messageCount} nuntia\n{storyCount} fabulas", "export_button": "Exportare", - "clear_button": "Purgare", - "view_logger_history_button": "Videre Logger Historia", - "updates_title": "Updates", - "auto_update_check": "Auto reprehendo pro updates", - "update_check_frequency": "Update reprehendo frequentia", - "update_check_frequency_daily": "Cotidie", - "update_check_frequency_weekly": "Weekly", - "update_check_frequency_monthly": "Menstrua", - "theme_icon_description": "Thema", - "app_theme_title": "App Thema", - "theme_mode_system": "Ratio", - "theme_mode_light": "Lux", - "theme_mode_dark": "Tenebris", - "ui_settings_title": "UI Occasus", - "haptic_feedback_label": "Haptic Feedback", - "test_mode_label": "Test Modus (TANTUM DEBUGGING)", - "disable_feature_loading_label": "Disable Feature Loading", - "disable_auto_mapper_label": "Disable Auto Mapper", - "disable_bypass_indicator_label": "Disable Bypass Status Indicator", - "update_notification_channel_name": "PurrfectSnap Updates", - "update_notification_channel_description": "Notificationes pro PurrfectSnap updates", - "update_notification_title": "PurrfectSnap Update Available", - "update_notification_text": "Version %s nunc praesto est.", - "export_database_failed_toast": "Deficio exportare database! {message}", - "clear_messages_failed_toast": "Deficio purgare nuntios! {message}", - "clear_file_failed_toast": "Deficio purgare file! {message}", - "debug_file_config": "Configuratio", - "debug_file_mappings": "Mappings", - "debug_file_message_logger": "Nuntius Logger", - "debug_file_pinned_best_friend": "Pinned Optimus Amicus", - "debug_file_native_sig_cache": "Nativus Signature Cache" + "clear_button": "Patet", + "view_logger_history_button": "View Logger History" }, "tasks": { - "no_tasks": "Nulla opera", - "merge_button": "Merge", - "failed_to_open_file": "Deficio aperire file", - "merge_files_toast": "Merging {count} files", - "remove_selected_tasks_title": "Certe vis tollere selecta opera?", - "remove_all_tasks_title": "Certe vis tollere omnia opera?", - "delete_files_option": "Etiam delere files", - "remove_selected_tasks_confirm": "Remove {count} opera?", - "remove_all_tasks_confirm": "Remove omnia opera?", - "clear_tasks_description": "Purgare opera", - "file_not_found_icon_description": "File non inventus", - "image_icon_description": "Imago", - "video_icon_description": "Video", - "audio_icon_description": "Audio", - "file_icon_description": "File", - "download_icon_description": "Download", - "chat_action_icon_description": "Chat Actio", - "cancel_icon_description": "Cancel", - "success_icon_description": "Successus", - "failure_icon_description": "Defectum", - "cancelled_icon_description": "Cancellatus", - "task_status_failure": "Defectum", - "task_status_cancelled": "Cancellatus" + "no_tasks": "Non opus", + "merge_files_toast": "Bus {numerare} imagini", + "remove_selected_tasks_title": "Certus esne munus electum tollere?", + "delete_files_option": "Etiam delete lima", + "remove_selected_tasks_confirm": "Aufer opera {numerare}?", + "remove_all_tasks_confirm": "Omnia opera amove?", + "remove_all_tasks_title": "Certus esne munus electum tollere?" }, "features": { - "disabled": "Disabled", + "disabled": "debilitatum", "export_option": "Exportare", "import_option": "Importare", "reset_option": "Reset", - "config_export_success_toast": "Config exportata feliciter", - "config_import_success_toast": "Config importata feliciter", - "config_import_failure_toast": "Deficio importare config {error}", - "config_export_failure_toast": "Deficio exportare config {error}", - "saved_config_snackbar": "Config salvus", - "older_required": "Hoc pluma requirit Snapchat v{version} aut vetustius ad operari recte", - "newer_required": "Hoc pluma requirit Snapchat v{version} aut recentius ad operari recte", - "search_button": "Quaerere" - }, - "manage_rule_feature": { - "disable_state_option": "Disabled", - "disable_state_subtext": "Nulli amici/gruppi afficientur", - "whitelist_state_option": "Nemo praeter ...", - "whitelist_state_subtext": "Tantum {count} amici/gruppi hac regula afficientur", - "whitelist_state_button": "Selecta permissus amici/gruppi", - "blacklist_state_option": "Omnes praeter ...", - "blacklist_state_subtext": "Omnes praeter {count} amici/gruppi hac regula afficientur", - "blacklist_state_button": "Selecta exclusi amici/gruppi", - "clear_list_button": "Purgare amici/gruppi album", - "dialog_clear_confirmation_text": "Certe vis purgare album?" + "config_export_success_toast": "Mando emitur feliciter", + "saved_config_snackbar": "Mando salvus", + "config_import_success_toast": "Mando importari feliciter", + "config_import_failure_toast": "Deficio ad config {errorem} importare" }, "social": { - "friends_tab": "Amici", - "groups_tab": "Gruppi", - "empty_hint": "(inane)", - "streaks_expiration_short": "{hours}h" + "friends_tab": "amici", + "groups_tab": "Groups", + "empty_hint": "(vacuus)", + "streaks_expiration_short": "{horas} h" }, "manage_scope": { - "logged_stories_button": "Monstrare Logged Stories", "e2ee_title": "Finis-ad-finem Encryption", - "rules_title": "Regulae", - "participants_text": "{count} participes", - "not_found": "Non inventus", - "streaks_title": "Streaks", + "rules_title": "Rulese", + "logged_stories_button": "Show Logged Storiese", + "participants_text": "{numerare} participantium", + "not_found": "Non inveni", + "streaks_title": "Striae", "streaks_length_text": "Longitudo: {length}", "streaks_expiration_text": "Expirat in {eta}", "streaks_expiration_text_expired": "Expiratus", - "reminder_button": "Pone Admonitio", - "delete_scope_confirm_dialog_title": "Certe vis delere {scope}?", - "notes_placeholder": "Click addere notam", - "invalid_key_size_32_bytes": "Invalid key magnitudine (debet esse 32 bytes)", - "successfully_imported_key": "Feliciter importata clavis", - "failed_to_import_key": "Deficio importare clavis: {message}", - "export_base64_button": "Exportare Base64", - "import_base64_button": "Importare Base64" + "reminder_button": "Set Lorem", + "delete_scope_confirm_dialog_title": "Visne delere a {scope}?" }, "logged_stories": { - "story_failed_to_load": "Deficio onerare", - "no_stories": "Nulla fabulas invenitur", - "save_from_cache_button": "Salva ex Cache", - "downloaded_to_path": "Downloaded ad {path}", - "download_failed": "Download defecit: {message}", - "posted_at": "Missae ad {date}", - "created_at": "Creatus ad {date}", - "failed_to_open_file": "Deficio aperire file. Reprehendo acta pro magis info", - "failed_to_get_file": "Deficio ut file" + "story_failed_to_load": "Deficio ad onus", + "no_stories": "Non fabulas invenerunt", + "save_from_cache_button": "Nisi ex Cache" }, "messaging_preview": { - "processed_messages_toast": "Processionaliter {count} nuntios", - "processed_messages_text": "Processionaliter {count} nuntios", - "close_button_description": "Claudere", - "bridge_connection_failed": "Deficio coniungere ad pontem. Fac Snapchat currit in background", - "bridge_init_failed": "Deficio initializare nuntius pontem. Fac Snapchat currit in background", - "message_fetch_failed": "Deficio arcessere nuntios", + "bridge_connection_failed": "Defecit coniungere ad Snapchat per pontem ministerium", + "bridge_init_failed": "Non initialize quantitatem pontis", + "message_fetch_failed": "Deficio arcessere", "no_message_hint": "Nulla nuntius", - "save_selection_option": "Salva Electio", - "save_all_option": "Salva Omnia", - "unsave_selection_option": "Unsave Electio", - "unsave_all_option": "Unsave Omnia", - "mark_selection_as_seen_option": "Mark electus Snap ut visum", - "mark_all_as_seen_option": "Mark omnes Snaps ut visum", - "delete_selection_option": "Delere Electio", - "delete_all_option": "Delere Omnia" - }, - "logger_history": { - "download_started_toast": "Download coepi!", - "download_success_toast": "Downloaded ad {path}", - "download_failed_toast": "Deficio ad download {message}", - "edited_at_text": "{message} (edited ad {date})", - "download_button": "Download", - "select_conversation_placeholder": "Select a colloquium", - "close_button_description": "Claudere", - "search_button_description": "Quaerere", - "list_friend_format": "Amicus {name}", - "list_group_format": "Grex {name}", - "no_more_messages": "Non magis nuntios", - "reverse_order_checkbox": "Reverse Ordine", - "chat_attachment": "Affectum {index}", - "empty_message": "Inanis Chat Nuntius", - "message_parse_failed": "Deficio ad parse nuntius", - "unknown_sender": "Ignorotus Mittens", - "download_attachment_failed_toast": "Deficio ad download affectum", - "log_header_format": "{username} ({type}) - {date}" - }, - "file_imports": { - "import_file_button": "Importare File", - "file_not_found": "File non inventus", - "file_import_failed": "Deficio importare file: {error}", - "file_imported": "File importata feliciter", - "file_delete_failed": "Deficio delere file", - "no_files_hint": "Hic potes importare files pro usu in Snapchat. Preme puga pyga infra ad importare file." - }, - "better_location": { - "spoofed_coordinates_title": "Lat {latitude}, Lng {longitude}", - "save_coordinates_dialog_title": "Salva Coordinatae", - "saved_name_dialog_hint": "Nomen Salvum", - "latitude_dialog_hint": "Latitudo", - "longitude_dialog_hint": "Longitudo", - "save_dialog_button": "Salva", - "choose_location_button": "Elige Locus", - "teleport_to_friend_button": "Teleportare ad Amicum", - "spoof_location_toggle": "Spoof Locus", - "suspend_location_updates": "Suspende Locus Updates", - "saved_coordinates_title": "Salvus Coordinatae", - "no_saved_coordinates_hint": "Nulla salvus coordinatae", - "delete_dialog_title": "Delere Salvus Coordinata", - "delete_dialog_message": "Certe vis delere hanc salvam coordinatam?", - "teleport_to_friend_title": "Teleportare ad Amicum", - "search_bar": "Quaerere", - "no_friends_map": "Nulli amici in tabula", - "no_friends_found": "Nulli amici inventi", - "edit_location_button_description": "Recensere Locus", - "add_icon_description": "Addere", - "edit_icon_description": "Recensere", - "delete_icon_description": "Delere" + "save_selection_option": "Salvum Electio", + "unsave_selection_option": "Electio unsave", + "unsave_all_option": "Invidere All", + "mark_selection_as_seen_option": "Mark lectus Snap ut videtur", + "mark_all_as_seen_option": "Nota omnia Snaps ut videtur", + "save_all_option": "Servare All" } }, "dialogs": { - "add_friend": { - "title": "Adde Amicum vel Group", - "search_hint": "Quaerere", - "fetch_error": "Deficio arcessere data", - "category_groups": "Gruppi", - "category_friends": "Amici", - "participants_text": "{count} participes", - "search_icon_description": "Quaerere" - }, "scripting_warning": { - "title": "Monitum", - "content": "PurrfectSnap includit instrumentum scriptionis, permittens exsecutionem usoris definitae codicis in fabrica tua. Utere summa cautione et tantum installare modulos ex notis, certis fontibus. Moduli non legitimi vel non verificati pericula securitatis systemati tuo ponere possunt." - }, - "reset_config": { - "title": "Reset config", - "content": "Certe vis reset config?", - "success_toast": "Config reset feliciter" - }, - "export_config": { - "title": "Exportare Sensitiva Data?", - "content": "Visne exportare config cum sensitiva data? (Sicut locus coordinatae, etc.)" - }, - "messaging_action": { - "title": "Elige contentus genera ad processum", - "select_all_button": "Omnia Selecta" - }, - "file_imports": { - "no_files_settings_hint": "Nulla files inventa. Fac te importasse requisita files in File Importat sectione", - "settings_select_file_hint": "Selecta importata file" - }, - "quick_actions_dialog": { - "title": "Recensere Velox Actiones", - "subtitle": "Selecta et magnitudine tua velox actiones." - } - }, - "friend_tracker": { - "rules_tab": "Regulae", - "logs_tab": "Acta", - "export_dialog_title": "Exportare", - "bulk_export_button": "Massa Exportare", - "individual_export_button": "Singula Exportare", - "invalid_import_type_dialog_title": "Invalidum Importare Typus", - "invalid_import_type_dialog_text": "Electus file non est compatible cum hoc importare genus. Elige rectam importare genus.", - "import_dialog_title": "Importare", - "bulk_import_button": "Massa Importare", - "individual_import_button": "Singula Importare", - "import_button_description": "Importare", - "export_button_description": "Exportare", - "export_button": "Exportare", - "delete_button_description": "Delere", - "delete_button": "Delere", - "catalog_button_description": "Catalogus", - "catalog_button": "Catalogus", - "add_rule_button_description": "Adde Regula", - "add_rule_button": "Adde Regula", - "no_rules_found": "Nulla regulae inventae", - "empty_rule_name": "(inane)", - "events_suffix": "eventus", - "scopes_suffix": "scopi", - "select_rule_to_export_title": "Selecta Regula ad Exportare", - "deleted_logs_toast": "Deletum {count} acta", - "delete_logs_dialog_title": "Delere acta?", - "deleting_logs_dialog_text": "Delens {count} acta...", - "delete_logs_dialog_confirm_text": "Hoc delebit acta fundatur in current filter et quaerere query. Hic actio non potest esse factum.", - "exported_logs_toast": "Exportata acta!", - "export_logs_failed_toast": "Deficio exportare acta. Reprehendo logcat pro magis details.", - "export_logs_dialog_title": "Exportare acta?", - "exporting_logs_dialog_text": "Exportans acta...", - "export_logs_dialog_confirm_text": "Hoc exportabit acta fundatur in current filter et quaerere query.", - "export_as_button": "Exportare ut {type}", - "filters_title": "Filtra", - "search_by_label": "Quaerere per", - "newest_first_label": "Novissima primum", - "since_label": "Cum", - "until_label": "Usque", - "pick_a_date_button": "Elige diem", - "search_placeholder": "Quaerere", - "filter_button_description": "Filtrum", - "clear_button_description": "Purgare", - "no_logs_found": "Nulla acta inventa", - "log_event_format": "{event} in {conversation}", - "condition_only_inside_conversation": "Tantum cum sum in colloquio", - "condition_only_outside_conversation": "Tantum cum sum extra colloquium", - "condition_only_when_app_active": "Tantum cum Snapchat est activum", - "condition_only_when_app_inactive": "Tantum cum Snapchat est non activum", - "condition_no_push_notification_when_app_active": "Nulla dis notificatio cum Snapchat est activum", - "add_event_dialog_title": "Adde Eventus", - "event_type_label": "Eventus genus", - "triggers_title": "Triggers", - "conditions_title": "Conditiones", - "add_button": "Addere", - "default_rule_name": "Custom Regula", - "discard_changes_dialog_title": "Rejicere Mutationes?", - "discard_changes_dialog_text": "Habes insalvatus mutationes. Certe vis rejicere eas?", - "discard_button": "Rejicere", - "cannot_save_rule_dialog_title": "Non potest salvare Regula", - "cannot_save_rule_dialog_text": "Regula debet habere saltem unum eventum ad salvandum.", - "duplicate_rule_name_dialog_title": "Duplicatus Regula Nomen", - "duplicate_rule_name_dialog_text": "Regula cum hoc nomine iam existit. Elige aliud nomen.", - "delete_rule_dialog_title": "Delere Regula", - "delete_rule_dialog_text": "Certe vis delere hanc regulam?", - "new_rule_title": "Nova Regula", - "edit_rule_title": "Recensere Regula", - "back_button_description": "Retro", - "save_button_description": "Salva", - "general_section_title": "Generale", - "rule_name_label": "Regula Nomen", - "author_name_label": "Auctor Nomen", - "scope_section_title": "Scopus", - "scope_all": "Omnes", - "scope_whitelist": "Whitelist", - "scope_blacklist": "Blacklist", - "select_friends_groups_button": "Selecta Amici/Gruppi ({count})", - "events_section_title": "Eventus", - "add_event_button": "Adde Eventus", - "no_events_text": "Nulla eventus" - }, - "friend_tracker_catalog": { - "download_failed": "Deficio download: {code}", - "error": "Error: {message}", - "no_repos_added": "Nulla repositoria addita.", - "no_rules_available": "Nulla regulae praesto ab aliquo repo.", - "by_author": "ab {author}", - "imported_button": "Importata", - "import_button": "Importare", - "title": "Amicus Tracker Catalogus", - "manage_repos_description": "Curo Repositories" - }, - "friend_tracker_export": { - "title": "Exportare Regulae", - "back_button_description": "Retro", - "exported_toast": "Amicus Tracker Regulae Exportatae!", - "export_failed_toast": "Deficio exportare regulas: {message}", - "save_button": "Salva", - "expand_button_description": "Expandere" - }, - "friend_tracker_import": { - "title": "Importare Regulae", - "back_button_description": "Retro", - "imported_toast": "Amicus Tracker Regulae Importatae!", - "import_failed_toast": "Deficio importare regulas: {message}", - "confirm_button": "Confirmare", - "expand_button_description": "Expandere" - }, - "friend_tracker_repos": { - "invalid_repo_title": "Invalidum Repositorium", - "add_repo_button": "Adde Repositorium", - "add_repo_dialog_title": "Adde Repositorium URL", - "repo_url_label": "Repositorium URL", - "repo_added_toast": "Repositorium additum feliciter!", - "invalid_repo_error": "Hoc non videtur esse validum Amicus Tracker repositorium.", - "add_repo_failed_toast": "Deficio addere repositorium: {message}", - "add_button": "Addere", - "no_repos_added": "Nulla repositoria addita", - "remove_button": "Removere", - "remove_repo_dialog_title": "Removere Repositorium", - "remove_repo_dialog_text": "Certe vis removere hoc repositorium?" - }, - "navigation": { - "tracker_tab_label": "Tracker", - "customize_bottom_bar_title": "Mos Bottom Bar", - "customize_bottom_bar_subtitle": "Reorder, addere vel removere tabs. Max quinque.", - "shown_tabs_title": "Monstratum Tabs", - "no_tabs_selected_text": "Nulla tabs selecta", - "available_tabs_title": "Praesto Tabs", - "reset_button": "Reset", - "done_button": "Actum" - }, - "scripting": { - "script_already_installed": "Script iam installed!", - "downloading_script": "Downloading script...", - "script_downloaded": "Script {name} downloaded!", - "download_script_failed": "Deficio ad download script. Reprehendo acta pro magis details", - "import_script_from_url_title": "Importare Script ex URL", - "import_script_warning": "Monitum: Importata scripta possunt esse noxia tuo artificio. Tantum importare scripta ex notis, certis fontibus.", - "enter_url_label": "Intra URL hic:", - "script_imported": "Script {name} importata!", - "import_failed": "Deficio importare script. {message}. Reprehendo acta pro magis details", - "import_button": "Importare", - "update_module_button": "Update Modulo", - "updating_script": "Updating script {name}...", - "module_not_found": "Modulo non inventus", - "updated_script": "Updated {name} ad versionem {version}", - "update_module_failed": "Deficio ad update modulo. Reprehendo acta pro magis details", - "edit_module_button": "Recensere Modulo", - "open_module_failed": "Deficio aperire modulo file. Reprehendo acta pro magis details", - "clear_module_data_button": "Purgare Modulo Data", - "module_data_cleared": "Modulo data purgata!", - "clear_module_data_failed": "Deficio purgare modulo data. Reprehendo acta pro magis details", - "delete_module_button": "Delere Modulo", - "deleted_script": "Deletum script {name}!", - "delete_module_failed": "Deficio delere modulo. Reprehendo acta pro magis details", - "actions_title": "Actiones", - "no_description": "Nulla descriptio", - "update_available": "Update praesto: {version}", - "actions_button": "Actiones", - "loaded_script": "Oneratus script {name}", - "unloaded_script": "Exoneratus script {name}", - "enable_script_failed": "Deficio ad enable script. Reprehendo acta pro magis details", - "disable_script_failed": "Deficio ad disable script. Reprehendo acta pro magis details", - "select_scripts_folder_toast": "Elige tuum scripta folder!", - "manage_repos_button": "Curo Repos", - "import_from_url_button": "Importare ex URL", - "open_scripts_folder_button": "Aperire Scripta Folder", - "no_settings_for_module": "Hoc modulo non habet aliquem occasus", - "installed_scripts_tab": "Installed Scripta", - "catalog_tab": "Catalogus", - "no_scripts_folder_selected_title": "Nulla scripta folder selecta", - "select_folder_button": "Selecta folder", - "no_scripts_found_title": "Nulla scripta inventa.", - "use_catalog_to_add_scripts": "Utere catalogus tab ad addere scripta!", - "ok_button_timeout": "OK ({timeout})", - "documentation_button": "Documenta", - "catalog": { - "script_already_installed": "Script iam installed!", - "download_failed": "Deficio download: {code}", - "script_downloaded": "Script downloaded!", - "could_not_create_file": "Non potuit creare file.", - "no_scripts_folder_selected": "Nulla scripta folder selecta.", - "error": "Error: {message}", - "no_repos_added": "Nulla repositoria addita.", - "repo_list_info": "Hic potes invenire album repos: ", - "link_text": "Link", - "no_scripts_available": "Nulla scripta praesto ab aliquo repo.", - "by_author": "ab {author}", - "version": "Versio: {version}", - "installed_button": "Installed", - "download_button": "Download" - }, - "repos": { - "invalid_repo_title": "Invalidum Repositorium", - "add_repo_button": "Adde Repositorium", - "add_repo_dialog_title": "Adde Repositorium URL", - "repo_url_label": "Repositorium URL", - "repo_added_toast": "Repositorium additum feliciter!", - "invalid_repo_error": "Hoc non videtur esse validum Script repositorium.", - "add_repo_failed_toast": "Deficio addere repositorium: {message}", - "add_button": "Addere", - "no_repos_added": "Nulla repositoria addita", - "remove_button": "Removere", - "remove_repo_dialog_title": "Removere Repositorium", - "remove_repo_dialog_text": "Certe vis removere hoc repositorium?" - } - }, - "features": { - "config_import": { - "title": "Confirmare Importare", - "back_button_description": "Retro", - "config_imported_toast": "Config Importata!", - "confirm_button": "Confirmare", - "expand_button_description": "Expandere", - "enable_feature": "Admitte Feature", - "enabled": "Enabled", - "disabled": "Disabled" - }, - "config_export": { - "title": "Exportare Summarium", - "back_button_description": "Retro", - "save_button": "Salva", - "expand_button_description": "Expandere", - "enable_feature": "Admitte Feature", - "enabled": "Enabled", - "disabled": "Disabled" - } - }, - "manage_repos": { - "title": "Curo {type} Repositoria", - "add_repo_button": "Adde Repositorium", - "add_repo_dialog_title": "Adde Repositorium URL", - "repo_url_label": "Repositorium URL", - "repo_added_successfully": "Repositorium additum feliciter!", - "add_repo_failed": "Deficio addere repositorium: {message}", - "add_button": "Addere", - "no_repos_added": "Nulla repositoria addita", - "remove_button": "Removere" - } - }, - "rules": { - "toasts": { - "enabled": "{ruleName} enabled", - "disabled": "{ruleName} disabled" - }, - "modes": { - "blacklist": "Blacklist modus", - "whitelist": "Whitelist modus" - }, - "properties": { - "auto_download": { - "name": "Auto download", - "description": "Automatice download Snaps cum inspicientes eos", - "options": { - "blacklist": "Exclude ab Auto Download", - "whitelist": "Auto Download" - } - }, - "stealth": { - "name": "Furtim Modus", - "description": "Prohibet quemquam scire te aperuisse suas Snaps/Chats et colloquia", - "options": { - "blacklist": "Exclude a Furtim Modus", - "whitelist": "Furtim modus" - } - }, - "auto_save": { - "name": "Auto Salvum", - "description": "Salvat Chat Nuntios cum inspicientes eos", - "options": { - "blacklist": "Exclude ab Auto salvum", - "whitelist": "Auto salvum" - } - }, - "unsaveable_messages": { - "name": "Insalvabilia Nuntios", - "description": "Prohibet nuntios salvari in chat ab aliis hominibus", - "options": { - "blacklist": "Exclude ab Insalvabilia Nuntios", - "whitelist": "Insalvabilia Nuntios" - } - }, - "auto_open_snaps": { - "name": "Auto Aperi Snaps", - "description": "Automatice aperit Snaps cum recipiens eos", - "options": { - "blacklist": "Exclude ab Auto Aperi Snaps", - "whitelist": "Auto Aperi Snaps" - } - }, - "hide_friend_feed": { - "name": "Celare ab Amico Feed" - }, - "e2e_encryption": { - "name": "Utere E2E Encryption" - }, - "pin_conversation": { - "name": "Pin Conversatio" - }, - "exclude_message_logger": { - "name": "Exclude a Nuntius Logger" + "content": "SnapEnhance instrumentum scriptionis includit, supplicium usoris definiti codicis in fabrica permittens. Summa cautione utere et tantum modulos ex notis, certis auctoribus institue. Moduli non legitimi vel non probati possunt pericula securitatis in ratiocinatione tua ponere." } } }, - "actions": { - "clean_snapchat_cache": { - "name": "Munda Snapchat Cache", - "description": "Mundat Snapchat Cache" + "setup": { + "dialogs": { + "select_language": "Lingua cupere", + "select_save_folder_button": "Ordnerus cupere", + "save_folder": "SnapEnhance requirit PRAECLUSIO permissiones ut download et salvum Media ex Snapchat.\nElige locum ubi instrumentorum communicationis socialis debet esse recepta." }, - "manage_friend_list": { - "name": "Curo Amicus Index", - "description": "Importare/exportare amicos tuos album cum tergum sursum" + "permissions": { + "notification_access": "Nervus alloware", + "battery_optimization": "Akkutis perfectio", + "display_over_other_apps": "Druber cuper", + "request_button": "Voluntas", + "dialog": "Pergere debes aptare sequentia requisita:" }, - "export_chat_messages": { - "name": "Exportare Chat Nuntios", - "description": "Exportat colloquium nuntios in JSON/HTML/TXT file" - }, - "export_memories": { - "name": "Exportare Memoriae", - "description": "Exportat memorias in ZIP file" - }, - "bulk_messaging_action": { - "name": "Massa Nuntius Actio", - "description": "Peragit operationes sicut delere amicos vel massa deletio colloquiorum" - }, - "regen_mappings": { - "name": "Regenerare Mappings", - "description": "Manuale regenerare mappings" - }, - "change_language": { - "name": "Mutare Linguam", - "description": "Mutare linguam PurrfectSnap" - }, - "file_imports": { - "name": "File Importat", - "description": "Importare files pro usu in Snapchat" - }, - "friend_tracker": { - "name": "Amicus Tracker", - "description": "Track tuos amicos in Snapchat" - }, - "logger_history": { - "name": "Logger Historia", - "description": "Videre historiam logged nuntios" + "mappings": { + "dialog": "Generating Mappings, hoc modicum tempus capere potest.", + "generate_failure_no_snapchat": "SnapEnhance Snapchat deprehendere potuit, Aliquam Snapchat reinstalling.", + "generate_failure": "Error occurrit dum mappings generare conatur, iterum conare." } }, + "scopes": { + "friend": "Amicus", + "group": "Magnas" + }, "features": { - "notices": { - "unstable": "⚠ Instabilis", - "ban_risk": "⚠ Hoc pluma potest facere bans", - "internal_behavior": "⚠ Hoc potest frangere Snapchat internum mores" - }, "properties": { "downloader": { - "name": "Downloader", - "description": "Download Snapchat Media", "properties": { - "save_folder": { - "name": "Salva Folder", - "description": "Selecta directorium ad quod omnia media debet esse downloaded ad" - }, - "auto_download_sources": { - "name": "Auto Download Fontes", - "description": "Selecta fontes ad automatice download ex" - }, - "prevent_self_auto_download": { - "name": "Preoccupo Sui Auto Download", - "description": "Prohibet tua Snaps ex esse downloaded automatice" - }, - "path_format": { - "name": "Semita Forma", - "description": "Specificare File Semita Forma" - }, - "allow_duplicate": { - "name": "Permitte Duplicatus", - "description": "Permittit idem media esse downloaded pluries" - }, - "merge_overlays": { - "name": "Merge Overlays", - "description": "Coniungit Textum et media a Snap in unum file" - }, - "force_image_format": { - "name": "Cogere Imago Forma", - "description": "Cogit imagines servari in determinata Forma" - }, - "force_voice_note_format": { - "name": "Cogere Vox Nota Forma", - "description": "Cogit Vox Notae servari in determinata Forma" - }, - "auto_download_voice_notes": { - "name": "Auto Download Vox Notae", - "description": "Automatice downloads vox notae cum ludens eos" - }, - "download_profile_pictures": { - "name": "Download Profile Pictures", - "description": "Permittit te download Profile Pictures ex profile pagina" - }, - "opera_download_button": { - "name": "Opera Download Puga", - "description": "Addit download puga in summo dextro angulo cum inspicientes a Snap.\nLongum prelum in globulis coget download" + "custom_path_format": { + "description": "Denota est consuetudo semita forma pro media downloaded\n\nPraesto variabiles:\n - %username%\n - %source%\n - %hash%\n - %date_time%" }, "download_context_menu": { - "name": "Download Contextus Menu", - "description": "Permittit te download/praevisum nuntios ex colloquio vel fabula utens contextu menu.\nLongum prelum in globulis coget download" + "description": "Permittit te ut nuntia ex colloquio vel historia utens tabulas contexta notas extrahere/praevisum.\nLong torcular in bullarum et opprimere download" }, - "ffmpeg_options": { - "name": "FFmpeg Optiones", - "description": "Specificare additional FFmpeg optiones", - "properties": { - "threads": { - "name": "Fila", - "description": "Moles filis uti" - }, - "preset": { - "name": "Preset", - "description": "Pone celeritatem conversionis" - }, - "constant_rate_factor": { - "name": "Constans Rate Factor", - "description": "Pone constantem rate factorem pro video encoder\nEx 0 ad 51 pro libx264" - }, - "video_bitrate": { - "name": "Video Bitrate", - "description": "Pone video bitrate (kbps)" - }, - "audio_bitrate": { - "name": "Audio Bitrate", - "description": "Pone audio bitrate (kbps)" - }, - "custom_video_codec": { - "name": "Custom Video Codec", - "description": "Pone consuetudo Video Codec (eg libx264)" - }, - "custom_audio_codec": { - "name": "Custom Audio Codec", - "description": "Pone consuetudo Audio Codec (eg AAC)" - } - } - }, - "logging": { - "name": "Logging", - "description": "Ostendit toasts cum media est downloading" - }, - "custom_path_format": { - "name": "Custom Semita Forma", - "description": "Specificare consuetudo semita forma pro downloaded media\n\nPraesto variabiles:\n - %username%\n - %source%\n - %hash%\n - %date_time%" + "opera_download_button": { + "description": "Bullam download in summo angulo dextro addit cum Snap spectabat.\nLong torcular in bullarum et opprimere download" } } }, "user_interface": { - "name": "User Interface", - "description": "Muta aspectum et sentire de Snapchat", "properties": { - "enable_app_appearance": { - "name": "Admitte App Aspectus Occasus", - "description": "Admittit occultatum App Aspectus Occasus\nNon potest requiri in recentioribus Snapchat versionibus" - }, - "friend_feed_message_preview": { - "name": "Amicus Feed Nuntius Praevisum", - "description": "Ostendit praevisum ultimarum nuntiorum in Amico Feed", - "properties": { - "amount": { - "name": "Moles", - "description": "Moles nuntiorum ad praevisum" - } - } - }, - "snap_preview": { - "name": "Snap Praevisum", - "description": "Ostendit parvum praevisum iuxta invisibilia Snaps in chat" - }, - "bootstrap_override": { - "name": "Bootstrap Override", - "description": "Overrides user interface bootstrap occasus", - "properties": { - "app_appearance": { - "name": "App Aspectus", - "description": "Pone pertinax App Aspectus" - }, - "home_tab": { - "name": "Domus Tab", - "description": "Overrides startup tab cum aperire Snapchat" - } - } - }, - "force_amoled_theme": { - "name": "Amoled Tenebris Modus", - "description": "Utitur verum nigrum background pro tenebris thema" - }, - "map_friend_nametags": { - "name": "Consectetur Amicus Map Nametags", - "description": "Meliorat Nametags amicorum in Snapmap" - }, - "prevent_message_list_auto_scroll": { - "name": "Prohibe Nuntius Index Auto Scroll", - "description": "Prohibet nuntius album a scrolling ad imum cum mittens / recipiens nuntium" - }, - "streak_expiration_info": { - "name": "Monstra Streak Expiratio Info", - "description": "Monstrat Streak Expiratio timer iuxta Streaks contra" - }, "hide_friend_feed_entry": { - "name": "Celare Amicus Feed Ingressum", - "description": "Celat specificum amicum ab Amico Feed\nUtere socialis tab ad curo hoc pluma" - }, - "hide_streak_restore": { - "name": "Celare Streak Restituere", - "description": "Celat Restituere puga in amico feed" - }, - "hide_quick_add_suggestions": { - "name": "Celare Velox Adde Suggestiones", - "description": "Removet velox adde amicus suggestiones" - }, - "hide_story_suggestions": { - "name": "Celare Fabula Suggestiones", - "description": "Removet suggestiones ex Stories pagina" - }, - "hide_ui_components": { - "name": "Celare UI Components", - "description": "Selecta quae UI components ad celare" - }, - "opera_media_quick_info": { - "name": "Opera Media Velox Info", - "description": "Ostendit utilem informationem de media sicut creaturae diem in opera videntium contextu menu" - }, - "old_bitmoji_selfie": { - "name": "Vetus Bitmoji Selfie", - "description": "Reducit Bitmoji selfies ex vetustioribus Snapchat versionibus" - }, - "disable_spotlight": { - "name": "Disable Spotlight", - "description": "Disables Spotlight pagina" - }, - "friend_feed_menu_buttons": { - "name": "Amicus Feed Menu Puga", - "description": "Selecta quae puga pyga ut ostenderet in Amico Feed Menu" - }, - "auto_close_friend_feed_menu": { - "name": "Auto Close Amicus Feed Menu", - "description": "Automatice claudit Amicus Feed Menu post premens occasum puga" - }, - "vertical_story_viewer": { - "name": "Verticalis Fabula Viewer", - "description": "Admittit verticalis fabula videntium pro omnibus fabulis" - }, - "enable_friend_feed_menu_bar": { - "name": "Admitte Amicus Feed Menu Bar", - "description": "Admittit novum Amicus Feed Menu Bar" - }, - "message_indicators": { - "name": "Nuntius Indicatores", - "description": "Addit specifica Indicatores icones ad nuntios\nNota: Indicatores non potest esse 100% accurate" - }, - "stealth_mode_indicator": { - "name": "Furtim Modus Indicator", - "description": "Addit 👻 emoji iuxta colloquia in furtim modus" - }, - "edit_text_override": { - "name": "Recensere Textum Override", - "description": "Overrides textum agri mores" - }, - "prevent_forced_keyboard": { - "name": "Prohibe Coactus Cantiones", - "description": "Prohibet Snapchat ab automatice papaver sursum tincidunt cum aperire colloquium" - }, - "settings_menu": { - "name": "Occasus Menu", - "description": "Mutat viam aperire PurrfectSnap menu", - "options": { - "default": "Default", - "legacy": "Legatum" - } - } - } - }, - "messaging": { - "name": "Nuntius", - "description": "Muta quomodo inter se agere cum amicis", - "properties": { - "bypass_screenshot_detection": { - "name": "Bypass Screenshot Deprehensio", - "description": "Prohibet Snapchat a deprehendere cum accipere screenshot" - }, - "anonymous_story_viewing": { - "name": "Anonymous Fabula Viewing", - "description": "Prohibet quemquam scire te vidisse fabulam suam" - }, - "prevent_story_rewatch_indicator": { - "name": "Prohibe Fabula Rewatch Indicator", - "description": "Prohibet quemquam scire te rewatched fabulam suam" - }, - "hide_peek_a_peek": { - "name": "Celare Peek-a-Peek", - "description": "Prohibet notificatio a mitti cum dimidium ungunt in chat" - }, - "hide_bitmoji_presence": { - "name": "Celare Bitmoji Praesentia", - "description": "Prohibet tuum Bitmoji a papaver sursum dum in Chat" - }, - "hide_typing_notifications": { - "name": "Celare Typing Notificationes", - "description": "Prohibet quemquam scire te typing nuntium" - }, - "unlimited_snap_view_time": { - "name": "Infinitus Snap View Tempus", - "description": "Removet Tempus Limitatio pro viewing Snaps" - }, - "auto_mark_as_read": { - "name": "Auto Mark ut Lectus", - "description": "Automatice notat nuntios/snaps ut legitur etiam cum Furtim Modus est enabled" - }, - "mark_snap_as_seen_button": { - "name": "Mark Snap ut Visum Puga", - "description": "Addit puga pyga ut notet Snap ut visum cum inspicientes eam.\nHoc operabitur etiam cum Furtim Modus est enabled" - }, - "skip_when_marking_as_seen": { - "name": "Skip Cum Notans ut Visum", - "description": "Automatice skips ad proximum Snap cum notans a Snap ut visum.\nUtere in compositione cum Mark Snap ut Visum Puga" - }, - "loop_media_playback": { - "name": "Loop Media Playback", - "description": "Loops media playback cum inspicientes Snaps / Stories" - }, - "disable_replay_in_ff": { - "name": "Disable Replay in FF", - "description": "Disables facultatem ad replay cum diu torcular a Amico Feed" - }, - "half_swipe_notifier": { - "name": "Dimidium Swipe Notifier", - "description": "Notificat te cum aliquis dimidium swipes in colloquium", - "properties": { - "min_duration": { - "name": "Minimum Duratio", - "description": "Minimum duratio dimidium ungunt (in secundis)" - }, - "max_duration": { - "name": "Maximum Duratio", - "description": "Maximum duratio dimidium ungunt (in secundis)" - } - } - }, - "call_start_confirmation": { - "name": "Voca Satus Confirmatio", - "description": "Ostendit confirmationem dialogum cum incipiens vocatio" - }, - "unlimited_conversation_pinning": { - "name": "Infinitus Conversatio Pinning", - "description": "Permittit te suspendere infinitam quantitatem colloquiorum localiter" - }, - "disable_snap_mode_restrictions": { - "name": "Disable Snap Modus Restrictiones", - "description": "Permittit te videre auto-destruens Snaps sine restrictionibus" - }, - "prevent_message_sending": { - "name": "Prohibe Nuntius Mittens", - "description": "Prohibet mittens quaedam genera nuntiorum" - }, - "friend_mutation_notifier": { - "name": "Amicus Mutatio Notifier", - "description": "Notificat te cum aliquid mutat in amico profile" - }, - "better_notifications": { - "name": "Melius Notificationes", - "description": "Addit magis notitia in accepit notificationes", - "properties": { - "group_notifications": { - "name": "Group Notificationes", - "description": "Group notificationes in unum" - }, - "chat_preview": { - "name": "Chat Praevisum", - "description": "Ostendit praevisum accepit nuntios in notificatione" - }, - "media_preview": { - "name": "Media Praevisum", - "description": "Ostendit praevisum selectae media genera in notificatione" - }, - "media_caption": { - "name": "Media Caption", - "description": "Ostendit attachiatus caption de media in notificatione" - }, - "stacked_media_messages": { - "name": "Stacked Media Nuntios", - "description": "Coniungit multiplex media nuntios in unum textum notificatio cum non possunt praevideri. Utere in compositione cum Chat Praevisum" - }, - "friend_add_source": { - "name": "Amicus Adde Fons", - "description": "Ostendit fontem amici petitionem in notificatione" - }, - "reply_button": { - "name": "Respondeo Puga", - "description": "Addit respondeo puga ad notificationem" - }, - "smart_replies": { - "name": "Smert Responsa", - "description": "Addit suggessit responsa ad notificationes (Android 10+). Utere in compositione cum Respondeo Puga" - }, - "download_button": { - "name": "Download Puga", - "description": "Permittit te download media ex notificatione" - }, - "mark_as_read_button": { - "name": "Mark ut Lectus Puga", - "description": "Permittit te notare nuntium ut legitur ex notificatione" - }, - "mark_as_read_and_save_in_chat": { - "name": "Mark ut Lectus et Salva in Chat", - "description": "Addit notam ut legitur et salva in chat puga ad notificationem" - } - } - }, - "notification_blacklist": { - "name": "Notificatio Blacklist", - "description": "Selecta notificationes quae debet adepto clausus" - }, - "message_logger": { - "name": "Nuntius Logger", - "description": "Prohibet nuntios a deleta", - "properties": { - "keep_my_own_messages": { - "name": "Serva Mea Nuntios", - "description": "Prohibet tua nuntios a deleta" - }, - "auto_purge": { - "name": "Auto Purga", - "description": "Automatice delet conditivo nuntios qui sunt maior quam certa moles temporis" - }, - "message_filter": { - "name": "Nuntius Filter", - "description": "Selecta quae nuntios debet adepto initium (inanis pro omnibus nuntiis)" - }, - "deleted_message_color": { - "name": "Deletum Nuntius Color", - "description": "Pone colorem deleti nuntios" - } - } - }, - "auto_save_messages_in_conversations": { - "name": "Auto Salva Nuntios in Conversationibus", - "description": "Automatice salvat omnem nuntium in colloquiis" - }, - "gallery_media_send_override": { - "name": "Gallery Media Mitte Override", - "description": "Spoofs media fons cum mittens ex Gallery" - }, - "strip_media_metadata": { - "name": "Exue Media Metadata", - "description": "Removet metadata de media ante mittens ut nuntium" - }, - "bypass_message_retention_policy": { - "name": "Bypass Nuntius Retentio Politia", - "description": "Prohibet nuntios a deleta post inspicientes eos" - }, - "bypass_message_action_restrictions": { - "name": "Bypass Nuntius Actio Restrictiones", - "description": "Permittit te agere ad frangeretur sine aperuit eam vel salvare unsaveable nuntius" - }, - "remove_groups_locked_status": { - "name": "Remove Groups Locked Status", - "description": "Permittit te videre coetus notitia post calce" - }, - "double_tap_chat_action": { - "name": "Duplex Tap Chat Actio", - "description": "Peragit consuetudo actio cum duplex percutiens nuntium in chat" - }, - "double_tap_chat_action_custom_emoji": { - "name": "Duplex Tap Chat Actio Custom Emoji Reactio", - "description": "Pone consuetudo emoji reactionem pro duplex ICTUS chat actio" - } - } - }, - "global": { - "name": "Globalis", - "description": "Tweak Globalis Snapchat Occasus", - "properties": { - "better_location": { - "name": "Melior Locus", - "description": "Consectetur Snapchat Locus", - "properties": { - "spoof_location": { - "name": "Spoof Locus", - "description": "Spoofs tuum locum ad certum unum" - }, - "coordinates": { - "name": "Coordinatae", - "description": "Pone coordinatas spoofed locus" - }, - "walk_radius": { - "name": "Ambulare Radius", - "description": "Passim ambulare in hoc radio (ft)" - }, - "always_update_location": { - "name": "Semper Update Locus", - "description": "Cogere Snapchat ad update locum etiam si nulla GPS data recipitur" - }, - "suspend_location_updates": { - "name": "Suspende Locus Updates", - "description": "Prohibet tuum locum ab adaequatione" - }, - "spoof_battery_level": { - "name": "Spoof Pugna Level", - "description": "Spoofs pugna gradu tuo artificio in tabula\nValor debet esse inter 0 et 100" - }, - "spoof_headphones": { - "name": "Spoof Headphones", - "description": "Spoofs statum audiendi musicam in tabula" - }, - "show_battery_level": { - "name": "Monstra Pugna Level", - "description": "Monstrat pugna gradu amicorum tuorum in tabula" - } - } - }, - "snapchat_plus": { - "name": "Snapchat Plus", - "description": "Admittit Snapchat Plus features\nQuidam Servo-sided features non operari" - }, - "media_upload_quality": { - "name": "Media Upload Qualitas", - "description": "Overrides media upload qualitas", - "properties": { - "force_video_upload_source_quality": { - "name": "Cogere Video Upload Fons Qualitas", - "description": "Cogit Snapchat uti fons qualitas cum uploading videos\nNota quaeso quod hoc non potest removere metadata ex media" - }, - "disable_image_compression": { - "name": "Disable Imago Compressio", - "description": "Disables imago compressio cum uploading media" - }, - "custom_image_upload_format": { - "name": "Custom Imago Upload Forma", - "description": "Pone consuetudo imago upload forma\nSelecta a lossless forma (sicut PNG) pro optima qualitate" - } - } - }, - "disable_confirmation_dialogs": { - "name": "Disable Confirmatio Dialogi", - "description": "Automatice confirmat selectas actiones" - }, - "auto_updater": { - "name": "Auto Updater", - "description": "Automatice compescit pro novis updates" - }, - "disable_metrics": { - "name": "Disable Metrica", - "description": "Obstructionum mittens specifica analytica data ad Snapchat" - }, - "disable_story_sections": { - "name": "Disable Fabula Sectiones", - "description": "Removet sectiones ex Stories pagina\nPotest requirere a refice ad operari recte" - }, - "block_ads": { - "name": "Obstructionum Ads", - "description": "Prohibet Adscriptiones a proponendum" - }, - "disable_custom_tabs": { - "name": "Disable Custom Tabs", - "description": "Aperit nexus in suffultus applicationes potius quam in Web Browser" - }, - "disable_permission_requests": { - "name": "Disable Permissio Petitiones", - "description": "Prohibet Snapchat a petendo specifica permissiones" - }, - "disable_memories_snap_feed": { - "name": "Disable Memoriae Snap Feed", - "description": "Prohibet Snapchat a ostendens recens memorias cum tu ungunt sursum in camera" - }, - "spotlight_comments_username": { - "name": "Spotlight Comments Username", - "description": "Ostendit auctor username in Spotlight comments" - }, - "bypass_video_length_restriction": { - "name": "Bypass Video Longitudo Restrictiones", - "description": "Singula: mittit unum video\nSplit: scindit videos post edere" - }, - "default_video_playback_rate": { - "name": "Default Video Playback Rate", - "description": "Pone default celeritatem pro playback de videos\nValor debet esse inter 0.1 et 4.0" - }, - "video_playback_rate_slider": { - "name": "Video Playback Rate Slider", - "description": "Addit lapsus in opera contextu menu mutare video playback rate\nNota: Mutationes tantum applicare ad subsequent videos" - }, - "disable_google_play_dialogs": { - "name": "Disable Google Play Services Dialogi", - "description": "Prohibe Google Play Services disponibilitate dialogi a proponendum" - }, - "default_volume_controls": { - "name": "Default Volume Imperium", - "description": "Cogit Snapchat uti ratio voluminis imperium" - }, - "disable_telecom_framework": { - "name": "Disable Telecom Framework", - "description": "Prohibet Snapchat ab usura Android Telecom framework\nHoc permittit te audire musicam dum in vocatio" - }, - "hide_active_music": { - "name": "Celare Activa Musica", - "description": "Prohibet Snapchat a scire te audire musicam\nHoc permittet te accipere snaps utens imperium volumen globulis dum audire musicam" - }, - "disable_snap_splitting": { - "name": "Disable Snap Scindens", - "description": "Prohibet Snaps ab esse scissum in plures partes\nPicturae quas mittis convertentur in videos" - } - } - }, - "rules": { - "name": "Regulae", - "description": "Curo Automatic Features pro singulis hominibus" - }, - "camera": { - "name": "Camera", - "description": "Adjustare ius occasus pro perfecta frangeretur", - "properties": { - "disable_cameras": { - "name": "Disable Cameras", - "description": "Prohibet Snapchat ab usura selectae cameras" - }, - "black_photos": { - "name": "Nigrum Photos", - "description": "Reponit captas imagines cum nigro background\nVideos non afficiuntur" - }, - "immersive_camera_preview": { - "name": "Immersive Praevisum", - "description": "Prohibet Snapchat a Cropping Camera praevisum\nHoc potest facere camera ad flicker in quibusdam machinis" - }, - "override_front_resolution": { - "name": "Override Front Resolutio", - "description": "Overrides camera resolutio pro fronte camera" - }, - "override_back_resolution": { - "name": "Override Tergum Resolutio", - "description": "Overrides camera resolutio pro tergo camera" - }, - "custom_resolution": { - "name": "Custom Resolutio", - "description": "Pone consuetudo camera resolutio, latitudo x altitudo (eg 1920x1080).\nConsuetudo resolutio debet esse suffulta a tuo artificio" - }, - "front_custom_frame_rate": { - "name": "Front Custom Frame Rate", - "description": "Overrides fronte camera frame rate" - }, - "back_custom_frame_rate": { - "name": "Tergum Custom Frame Rate", - "description": "Overrides tergo camera frame rate" - }, - "force_camera_source_encoding": { - "name": "Cogere Camera Fons Encoding", - "description": "Cogit camera fons encoding" - }, - "startup_default_camera": { - "name": "Satus Default Camera", - "description": "Pone default camera cum aperire Snapchat" - }, - "hevc_recording": { - "name": "HEVC Recording", - "description": "Utitur HEVC (H.265) codec pro video recording" - } - } - }, - "streaks_reminder": { - "name": "Streaks Admonitio", - "description": "Periodice te notificat de tuis Streaks", - "properties": { - "interval": { - "name": "Intervallum", - "description": "Intervallum inter singulas admonitiones (horas)" - }, - "remaining_hours": { - "name": "Reliquum Tempus", - "description": "Reliqua moles temporis antequam notificatio ostenditur (horas)" - }, - "group_notifications": { - "name": "Group Notificationes", - "description": "Group notificationes in unum" + "description": "Amicus certus in amicum ab amico Feed\nUtere socialis tab administrare haec factura" } } }, "experimental": { - "name": "Experimentalis", - "description": "Experimentalis features", "properties": { - "native_hooks": { - "name": "Nativus Hooks", - "description": "Insecure Features qui hamum in Snapchat nativum codicem", + "e2ee": { + "description": "Encryptas epistulas tuas cum AES clavis secreto communi utens\nFac ut clavem tuam alicubi incolumem serves!", "properties": { - "composer_hooks": { - "name": "Composer Hooks", - "description": "Injects codicem in Composer crucis-platform UI framework", - "properties": { - "show_first_created_username": { - "name": "Monstra Primum Creatum Username", - "description": "Monstrat primum creatum username iuxta currentem username in profile pagina" - }, - "bypass_camera_roll_limit": { - "name": "Bypass Camera Roll Limes", - "description": "Augeat maximam quantitatem mediae quam potes mittere ex camera roll" - }, - "custom_self_destruct_snap_delay": { - "name": "Custom Se Destruere Snap Mora", - "description": "Dat plures optiones pro se-destruere timer cum mittens Snap" - }, - "composer_console": { - "name": "Composer Console", - "description": "Permittit te exsequi JavaScript codicem in Composer (arm64 tantum)" - }, - "composer_logs": { - "name": "Composer Acta", - "description": "Redirects console acta Composer ad PurrfectSnap" - } - } - }, - "disable_bitmoji": { - "name": "Disable Bitmoji", - "description": "Disables Amici Profile Bitmoji" - }, - "custom_emoji_font": { - "name": "Custom Emoji Font", - "description": "Permittit te uti consuetudo emoji font. Tantum operatur cum .ttf fonts" - }, - "custom_shared_library": { - "name": "Custom Shared Library", - "description": "Onerat consuetudo communis bibliotheca in Snapchat. Hoc pluma est tantum ad probationem proposita" + "force_message_encryption": { + "description": "Prohibet mittens nuntios encrypted ad eos qui non habent E2E Encryption solum cum multiplex colloquia eliguntur" } } }, - "spoof": { - "name": "Spoof", - "description": "Spoof varia notitia de te", - "properties": { - "play_store_installer_package_name": { - "name": "Play Store Installer Package Nomen", - "description": "Overrides installer sarcina nomen ad com.android.vending" - }, - "remove_vpn_transport_flag": { - "name": "Remove VPN Transport Vexillum", - "description": "Prohibet Snapchat a deprehendere VPNs" - }, - "remove_mock_location_flag": { - "name": "Remove Mock Locus Vexillum", - "description": "Prohibet Snapchat a deprehendere Mock locus" - } - } - }, - "convert_message_locally": { - "name": "Converte Nuntius Loci", - "description": "Converte snaps ad chat externa media localiter. Hoc apparet in chat download contextu menu" - }, - "media_file_picker": { - "name": "Media File Picker", - "description": "Permittit te eligere aliquem video/audio file ex gallery" - }, - "story_logger": { - "name": "Fabula Logger", - "description": "Praebet historiam amicorum fabulas" - }, - "call_recorder": { - "name": "Voca Recorder", - "description": "Automatice monumentis audio vocat" - }, "account_switcher": { - "name": "Ratio Switcher", - "description": "Permittit te commutandum inter rationes sine logging out\nLongum prelum in quaerere iconem iuxta tuum Bitmoji profile aperire menu\nNota: Hoc pluma est experimentalis et verisimile mutare in posterum", - "properties": { - "auto_backup_current_account": { - "name": "Auto Tergum Current Ratio", - "description": "Automatice terga sursum current propter cum logging de vel switching rationes" - } - } - }, - "better_transcript": { - "name": "Melius Transcript", - "description": "Meliorat vocem nota transcript", - "properties": { - "force_transcription": { - "name": "Cogere Vox Nota Transcriptio", - "description": "Permittit omnes vocem notas transcribi" - }, - "preferred_transcription_lang": { - "name": "Praeferenda Transcriptio Lingua", - "description": "Praeferenda lingua pro voce nota transcript (eg EN, ES, FR)" - }, - "notification_transcript": { - "name": "Notificatio Transcript", - "description": "Transcribit vocem notas in notificationibus\nHoc pluma requirit Chat Praevisum pluma ut enabled in Melius Notificationes" - } - } - }, - "voice_note_auto_play": { - "name": "Vox Nota Auto Play", - "description": "Automatice ludit proximum vocem nota post currentem unum finit" - }, - "friend_notes": { - "name": "Amicus Notae", - "description": "Permittit te addere notas ad amicos profiles" - }, - "cof_experiments": { - "name": "COF Experimenta", - "description": "Admittit unreleased/beta Snapchat features" - }, - "context_menu_fix": { - "name": "Contextus Menu Fix", - "description": "Conatus reparare Amicus Feed Menu ut cum fabrica est offline non potest proponendum recte" - }, - "app_lock": { - "name": "App Lock", - "description": "Prohibet accessum ad Snapchat sine passcode", - "properties": { - "lock_on_resume": { - "name": "Lock in Resume", - "description": "Serae app cum suus 'reopened" - } - } - }, - "infinite_story_boost": { - "name": "Infinita Fabula Boost", - "description": "Bypass Fabula Boost Limes mora" - }, - "meo_passcode_bypass": { - "name": "Mea Oculi Tantum Passcode Bypass", - "description": "Bypass Mea Oculi Tantum passcode\nHoc solum operatur si passcode recte ante initum est" - }, - "no_friend_score_delay": { - "name": "Nullus Amicus Score Mora", - "description": "Removet moram cum inspicientes Amici Score" - }, - "best_friend_pinning": { - "name": "Optimus Amicus Pinning", - "description": "Permittit te suspendere amicum ut numerus unus optimus amicus. Nota: Tantum potes videre tuum pinned optimum amicum" - }, - "e2ee": { - "name": "Finis-ad-finem Encryption", - "description": "Encrypts tuum nuntios cum AES utens communi secreto clavis\nFac ut salvum tuum clavis alicubi tutum!", - "properties": { - "encrypted_message_indicator": { - "name": "Encrypted Nuntius Indicator", - "description": "Addit 🔒 emoji iuxta encrypted nuntios" - }, - "force_message_encryption": { - "name": "Cogere Nuntius Encryption", - "description": "Prohibet mittens encrypted nuntios ad homines qui non habent E2E Encryption enabled tantum cum multiplex colloquia sunt selectae" - } - } - }, - "add_friend_source_spoof": { - "name": "Adde Amicus Fons Spoof", - "description": "Spoofs fontem Amici Request" - }, - "hidden_snapchat_plus_features": { - "name": "Occultus Snapchat Plus Features", - "description": "Admittit unreleased/beta Snapchat Plus features\nNon potest operari in vetustioribus Snapchat versionibus" + "description": "Permittit ut commutandum inter rationes sine colligationem e\nLongum premunt in icone investigationis proximam ad profile Bitmoji ut tabulam aperiant\nNota: Haec factura experimentalis est et in futuro verisimile mutatio est" }, "custom_streaks_expiration_format": { - "name": "Custom Streaks Expiratio Forma", - "description": "Customizes Streaks Expiratio forma\n\nPraesto variabiles:\n - %c: Streaks Comitem\n - %e: Horologium Emoji\n - %d: Dies\n - %h: Horae\n - %m: Minuta\n - %s: Secunda\n - %w: Reliquum Tempus" + "description": "Virgae Expiration forma customizes\n\nPraesto variabiles:\n - %c: Virgae Comitis\n - %e: Hourglass Emoji\n - %d: Diebus\n - % h: Horae\n - %m: Minutes\n - %s: Secundi\n -% w: Reliquis Tempus" }, - "prevent_forced_logout": { - "name": "Prohibe Coactus Logout", - "description": "Prohibet Snapchat a logging te cum login in alio artificio" + "best_friend_pinning": { + "description": "Permittit tibi amicum suspendere, ut numero unus amicus. Nota: Tantum potes videre te amicissimo confixi" }, - "snapscore_changes": { - "name": "Snapscore Mutationes", - "description": "Vestigia mutationes in amicis Snapscore\nUtere hoc pluma in recentioribus versionibus Snapchat tantum" + "meo_passcode_bypass": { + "description": "Bypass in oculis meis tantum passcode\nHoc modo operatur, si passcode ante recte ingressus est" } } }, - "scripting": { - "name": "Scripting", - "description": "Curre consuetudo scripta ad extendere PurrfectSnap", + "global": { "properties": { - "developer_mode": { - "name": "Developer Modus", - "description": "Ostendit debug info in Snapchat UI" + "hide_active_music": { + "description": "Prohibet Snapchat scire cupis musicam audire\nHoc tibi permittet ut globuli volumen imperium adhibeas snaps ut musicam audias" }, - "module_folder": { - "name": "Modulo Folder", - "description": "Folder ubi scripta sunt locata" + "media_upload_quality": { + "properties": { + "force_video_upload_source_quality": { + "description": "Copiae Snapchat utendi fons qualis est cum uploading videos\nNota quaeso quod hoc metadata ex instrumentis non removeat" + }, + "custom_image_upload_format": { + "description": "Morem imaginis onerationis\nformat\nSelect a lossless format (sicut PNG)\npro optima qualitate" + } + } }, - "auto_reload": { - "name": "Auto Reload", - "description": "Automatice reloads scripta cum mutantur" + "video_playback_rate_slider": { + "description": "Lapsus lapsus addit in menu contextus operae ut ratem video playback mutare\nNota: Mutationes tantum applicare ad subsequent videos" }, - "integrated_ui": { - "name": "Integrata UI", - "description": "Permittit scripta addere consuetudo UI components ad Snapchat" - }, - "disable_log_anonymization": { - "name": "Disable Log Anonymization", - "description": "Disables anonymization de acta" - }, - "disable_optimization": { - "name": "Disable Optimization", - "description": "Disables optimiizationem scriptorum. Hoc potest facere perficientur quaestiones." + "better_location": { + "properties": { + "spoof_battery_level": { + "description": "Spoofs pila gradu tuom in tabula\nValorem debet esse inter 0 et 100" + } + } } } }, - "friend_tracker": { - "name": "Amicus Tracker", - "description": "Records amici actio in Snapchat", + "camera": { "properties": { - "record_messaging_events": { - "name": "Record Nuntius Eventus", - "description": "Records nuntius eventus sicut aperire frangeretur, legere nuntium, etc." + "custom_resolution": { + "description": "Consuetudo constituit cameram solutionis, latitudinis x altitudinis (v.g. 1920x1080).\nConsuetudo resolutio tuom sustentari debet" }, - "allow_running_in_background": { - "name": "Permitte Currens in Background", - "description": "Permittit tracker currere in background. Nota: Hoc signanter exhauriet tuum altilium" + "immersive_camera_preview": { + "description": "Prohibet Snapchat ex tondentes Camerae preview\nHoc faciat cameram flammis quibusdam machinis" + } + } + }, + "messaging": { + "properties": { + "better_notifications": { + "properties": { + "stacked_media_messages": { + "description": "Multa media nuntia in unum textum notificatio coniungit cum praevideri non possunt. Utere respectu Chat Praevius" + } + } }, - "auto_purge": { - "name": "Auto Purga", - "description": "Automatice delet conditivo eventus qui sunt maior quam certa moles temporis" + "bypass_message_action_restrictions": { + "description": "Permittit te agere cum frangeretur sine aperto aut nuntio inexplicabili salvare" } } } }, "options": { - "app_appearance": { - "always_light": "Semper Lux", - "always_dark": "Semper Tenebris" - }, - "friend_feed_menu_buttons": { - "auto_download": "⬇️ Auto Download", - "auto_save": "💬 Auto Salva Nuntios", - "unsaveable_messages": "⬇️ Insalvabilia Nuntios", - "auto_open_snaps": "📷 Auto Aperi Snaps", - "stealth": "👻 Furtim Modus", - "mark_snaps_as_seen": "👀 Mark Snaps ut visum", - "mark_stories_as_seen_locally": "👀 Mark Stories ut visum localiter", - "conversation_info": "👤 Conversatio Info", - "e2e_encryption": "🔒 Utere E2E Encryption" - }, - "path_format": { - "create_author_folder": "Crea folder pro singulis auctor", - "create_source_folder": "Crea folder pro singulis media fons genus", - "append_hash": "Adde unicum hash ad file nomen", - "append_source": "Adde media fons ad file nomen", - "append_username": "Adde username ad file nomen", - "append_date_time": "Adde diem et tempus ad file nomen" - }, - "auto_download_sources": { - "friend_snaps": "Amicus Snaps", - "friend_stories": "Amicus Stories", - "public_stories": "Publica Stories", - "spotlight": "Spotlight" - }, - "logging": { - "started": "Coepi", - "success": "Successus", - "progress": "Progressus", - "failure": "Defectum" - }, - "notifications": { - "chat_screenshot": "Screenshot", - "chat_screen_record": "Screen Record", - "snap_replay": "Snap Replay", - "camera_roll_save": "Camera Roll Salva", - "chat": "Chat", - "chat_reply": "Chat Respondeo", - "snap": "Snap", - "typing": "Typing", - "stories": "Stories", - "speaking": "Loquens", - "chat_reaction": "DM Reactio", - "group_chat_reaction": "Group Reactio", - "initiate_audio": "Ineuntes Audio Voca", - "abandon_audio": "Missed Audio Voca", - "initiate_video": "Ineuntes Video Voca", - "abandon_video": "Missed Video Voca", - "map_live_location": "Map Live Locus" - }, - "gallery_media_send_override": { - "always_ask": "Semper Quaerere", - "ORIGINAL": "Originale Media", - "NOTE": "Audio Nota", - "SNAP": "Snap", - "SAVEABLE_SNAP": "Salvabile Snap" - }, - "strip_media_metadata": { - "hide_caption_text": "Celare Caption Text", - "hide_snap_filters": "Celare Snap Filtra", - "hide_extras": "Celare Extras (eg mentiones)", - "remove_audio_note_duration": "Remove Audio Nota Duratio", - "remove_audio_note_transcript_capability": "Remove Audio Nota Transcript Facultas" - }, - "hide_ui_components": { - "hide_profile_call_buttons": "Remove Profile Voca Puga", - "hide_chat_call_buttons": "Remove Chat Voca Puga", - "hide_live_location_share_button": "Remove Live Locus Share Puga", - "hide_stickers_button": "Remove Stickers Puga", - "hide_voice_record_button": "Remove Vox Record Puga", - "hide_unread_chat_hint": "Remove Lectus Chat Admonitus", - "hide_post_to_story_buttons": "Remove Post ad Fabula puga ante mittens a Snap", - "hide_billboard_prompt": "Remove Billboard Promptus In Amici Feed", - "hide_snapchat_plus_gift_reminders": "Remove Snapchat Plus donum admonitiones in colloquiis", - "hide_map_reactions": "Remove Map Reactiones" - }, - "hide_story_suggestions": { - "hide_suggested_friend_stories": "Celare suggessit amicus fabulas", - "hide_my_stories": "Celare Mea Stories" - }, - "home_tab": { - "map": "Map", - "chat": "Chat", - "camera": "Camera", - "discover": "Discover", - "spotlight": "Spotlight" - }, - "add_friend_source_spoof": { - "added_by_username": "Per Username", - "added_by_mention": "Per Mentionem", - "added_by_group_chat": "Per Group Chat", - "added_by_qr_code": "Per QR Code", - "added_by_community": "Per Communitatem", - "added_by_quick_add": "Per Velox Adde (altum periculum esse interdictum)" - }, - "bypass_video_length_restriction": { - "single": "Singula media", - "split": "Scindit media" - }, - "old_bitmoji_selfie": { - "2d": "2D Bitmoji", - "3d": "3D Bitmoji" - }, - "disable_confirmation_dialogs": { - "erase_message": "Erase Nuntius", - "remove_friend": "Remove Amicus", - "block_friend": "Block Amicus", - "ignore_friend": "Ignorare Amicus", - "hide_friend": "Celare Amicus", - "hide_conversation": "Celare Conversatio", - "clear_conversation": "Purgare Conversatio ab Amico Feed" - }, - "auto_reload": { - "snapchat_only": "Snapchat Tantum", - "all": "Omnes (Snapchat + PurrfectSnap)" - }, - "edit_text_override": { - "multi_line_chat_input": "Multi Linea Chat Input", - "bypass_text_input_limit": "Bypass Text Input Limes" - }, - "auto_purge": { - "never": "Numquam", - "1_hour": "1 Hora", - "3_hours": "3 Horae", - "6_hours": "6 Horae", - "12_hours": "12 Horae", - "1_day": "1 Dies", - "3_days": "3 Dies", - "1_week": "1 Hebdomada", - "2_weeks": "2 Hebdomadae", - "1_month": "1 Mensis", - "3_months": "3 Menses", - "6_months": "6 Menses" - }, - "disable_story_sections": { - "friends": "Amici", - "suggested_stories": "Suggessit Stories", - "following": "Sequens", - "discover": "Discover" - }, - "disable_cameras": { - "front": "Front Camera", - "back": "Tergum Camera" - }, - "disable_permission_requests": { - "notifications": "Notificationes", - "read_media_images": "Legere Media Imagines", - "read_media_video": "Legere Media Video", - "camera": "Camera", - "microphone": "Microphone", - "location": "Locus", - "read_contacts": "Legere Contactus", - "nearby_devices": "Prope Devices", - "phone_calls": "Phone Vocat" - }, "message_indicators": { - "encryption_indicator": "Addit 🔒 iconem iuxta nuntios qui missi sunt tantum tibi", - "platform_indicator": "Addit platform iconem ex quo media missus est (eg Android, iOS, Web)", - "location_indicator": "Addit 📍 iconem ad snaps cum missi sunt cum loco enabled", - "ovf_editor_indicator": "Indicat si frangeretur missus est utens OVF Editor", - "director_mode_indicator": "Addit 🎬 iconem ad snaps cum missi sunt utens Director Modus, qui potest adhiberi ad mittere gallery imagines ut snaps" - }, - "auto_mark_as_read": { - "conversation_read": "Mark colloquium ut legitur cum mittens nuntium", - "snap_reply": "Mark snaps ut legitur cum respondens eis", - "save_snap_in_chat": "Mark snaps ut legitur cum salvum eos in chat dum in Furtim Modus" - }, - "friend_mutation_notifier": { - "remove_friend": "Notificare cum aliquis te removet ut amicus", - "birthday_changes": "Notificare cum aliquis mutat suum diem natalem", - "bitmoji_selfie_changes": "Notificare cum aliquis mutat suum Bitmoji selfie", - "bitmoji_avatar_changes": "Notificare cum aliquis mutat suum Bitmoji avatar", - "bitmoji_background_changes": "Notificare cum aliquis mutat suum Bitmoji background", - "bitmoji_scene_changes": "Notificare cum aliquis mutat suum Bitmoji scaena" - }, - "snapchat_plus": { - "not_subscribed": "Non Subscriptus", - "basic": "Basic", - "ad_free": "Ad Free" - }, - "double_tap_chat_action": { - "like_message": "Sicut Nuntius", - "copy_text": "Exemplar Text ad Clipboard", - "delete_message": "Delere Nuntius", - "mark_as_read": "Mark ut Lectus", - "custom_emoji_reaction": "Custom Emoji Reactio" - }, - "startup_default_camera": { - "front": "Front Camera", - "back": "Tergum Camera" + "director_mode_indicator": "Iconem addit ad tortum cum missis utens Modus Directoris, qui adhiberi potest imagines gallery mittere ut tortum." } } }, - "friend_menu_option": { - "mark_snaps_as_seen": "Mark Snaps ut visum", - "mark_stories_as_seen_locally": "Mark Stories ut visum localiter", - "preview": "Praevisum", - "stealth_mode": "Furtim Modus", - "auto_download_blacklist": "Auto Download Blacklist", - "anti_auto_save": "Anti Auto Salvum" - }, - "content_type": { - "CHAT": "Chat", - "SNAP": "Snap", - "EXTERNAL_MEDIA": "Externa Media", - "NOTE": "Audio Nota", - "STICKER": "Sticker", - "SHARE": "Share", - "STATUS": "Status", - "LOCATION": "Locus", - "STATUS_SAVE_TO_CAMERA_ROLL": "Salvus ad Camera Roll", - "STATUS_CONVERSATION_CAPTURE_SCREENSHOT": "Screenshot", - "STATUS_CONVERSATION_CAPTURE_RECORD": "Screen Record", - "STATUS_CALL_MISSED_VIDEO": "Missed Video Voca", - "STATUS_CALL_MISSED_AUDIO": "Missed Audio Voca", - "LIVE_LOCATION_SHARE": "Live Locus Share", - "CREATIVE_TOOL_ITEM": "Creative Ferramenta Item", - "FAMILY_CENTER_INVITE": "Familia Centrum Invita", - "FAMILY_CENTER_ACCEPT": "Familia Centrum Accipe", - "FAMILY_CENTER_LEAVE": "Familia Centrum Relinque", - "STATUS_PLUS_GIFT": "Status Plus Donum", - "TINY_SNAP": "Parvus Snap", - "STATUS_COUNTDOWN": "Countdown", - "MAP_REACTION": "Map Reactio" - }, - "media_download_source": { - "none": "Nullus", - "pending": "Pendente", - "chat_media": "Chat Media", - "story": "Fabula", - "public_story": "Publica Fabula", - "spotlight": "Spotlight", - "profile_picture": "Profile Imago", - "story_logger": "Fabula Logger", - "message_logger": "Nuntius Logger", - "merged": "Merged", - "voice_call": "Vox Voca" - }, - "chat_action_menu": { - "preview_button": "Praevisum", - "download_button": "Download", - "delete_logged_message_button": "Delere Logged Nuntius", - "show_chat_edit_history": "Monstrare Chat Recensere Historia", - "convert_message": "Converte Nuntius" - }, - "opera_context_menu": { - "download": "Download Media", - "sent_at": "Missus ad {date}", - "created_at": "Creatus ad {date}", - "expires_at": "Expirat ad {date}", - "media_size": "Media magnitudine: {size}", - "media_duration": "Media duratio: {duration} ms", - "show_debug_info": "Monstrare Debug Info" - }, - "modal_option": { - "profile_info": "Profile Info", - "close": "Claudere" - }, - "gallery_media_send_override": { - "multiple_media_toast": "Potes tantum mittere unum media ad tempus" - }, - "mark_as_seen": { - "no_unseen_snaps_toast": "Nulla invisibilia Snaps inventa!", - "seen_toast": "Notatum ut visum!", - "unseen_toast": "Notatum ut invisibile!", - "already_seen_toast": "Iam notatum ut visum!", - "already_unseen_toast": "Iam notatum ut invisibile!" - }, - "conversation_preview": { - "streak_expiration": "expirat in {day} diebus {hour} horis {minute} minutis", - "total_messages": "Summa missis/acceptis nuntiis: {count}", - "title": "Praevisum", - "unknown_user": "Ignorotus User", - "no_messages": "Nulla nuntia inventa!" - }, - "profile_info": { - "title": "Profile Info", - "first_created_username": "Primum Creatum Username", - "mutable_username": "Mutabile Username", - "display_name": "Propono Nomen", - "added_date": "Addita Dies", - "birthday": "Natalis : {month} {day}", - "hidden_birthday": "Natalis : Occultus", - "friendship": "Amicitia", - "add_source": "Adde Fons", - "snapchat_plus": "Snapchat Plus", - "snapchat_plus_state": { - "subscribed": "Subscriptus", - "not_subscribed": "Non Subscriptus" - } - }, - "friendship_link_type": { - "mutual": "Mutuus", - "outgoing": "Exiens", - "blocked": "Clausus", - "deleted": "Deletus", - "following": "Sequens", - "suggested": "Suggessit", - "incoming": "Ineuntes", - "incoming_follower": "Ineuntes Sequens" - }, - "bulk_messaging_action": { - "choose_action_title": "Elige actionem", - "progress_status": "Processus {index} de {total}", - "selection_dialog_continue_button": "Perge", - "confirmation_dialog": { - "title": "Certe?", - "message": "Hoc afficiet omnes selectos amicos. Hic actio non potest esse factum." - }, - "actions": { - "remove_friends": "Remove Amicos", - "clear_conversations": "Purgare Conversationes" - } - }, - "chat_export": { - "exporter_dialog": { - "select_conversations_title": "Selecta Conversationes", - "text_field_selection": "{amount} selecta", - "text_field_selection_all": "Omnes", - "export_file_format_title": "Exportare File Forma", - "message_type_filter_title": "Filtra Nuntios per Typus", - "amount_of_messages_title": "Moles Nuntiorum (relinque blank pro omnibus)", - "download_medias_title": "Download Medias" - }, - "dialog_negative_button": "Cancel", - "dialog_positive_button": "Exportare", - "exported_to": "Exportata ad {path}", - "exporting_chats": "Exportans Chats...", - "processing_chats": "Processus {amount} colloquia...", - "export_fail": "Deficio exportare colloquium {conversation}", - "writing_output": "Scribens output...", - "finished": "Actum! Nunc potes claudere hoc dialogum.", - "no_messages_found": "Nulla nuntia inventa!", - "exporting_message": "Exportans {conversation}..." - }, - "button": { - "ok": "OK", - "positive": "Ita", - "negative": "Non", - "cancel": "Cancel", - "open": "Aperi", - "download": "Download", - "send": "Mitte", - "restore_original": "Restitue Originale", - "convert_external_media": "Converte Externa Media", - "save": "Salva" - }, - "tracker_events": { - "conversation_enter": "Conversatio Intra", - "conversation_exit": "Conversatio Exitus", - "started_typing": "Coepi Typing", - "stopped_typing": "Stetit Typing", - "started_speaking": "Coepi Loquens", - "stopped_speaking": "Stetit Loquens", - "started_peeking": "Coepi Peeking", - "stopped_peeking": "Stetit Peeking", - "message_read": "Nuntius Lectus", - "message_deleted": "Nuntius Deletus", - "message_saved": "Nuntius Salvus", - "message_unsaved": "Nuntius Insalvus", - "message_edited": "Nuntius Editus", - "message_reaction_add": "Nuntius Reactio Adde", - "message_reaction_remove": "Nuntius Reactio Remove", - "snap_opened": "Snap Apertus", - "snap_replayed": "Snap Replayed", - "snap_replayed_twice": "Snap Replayed Bis", - "snap_screenshot": "Snap Screenshot", - "snap_screen_record": "Snap Screen Record" - }, - "tracker_actions": { - "log": "Acta", - "in_app_notification": "In-App Notificatio", - "push_notification": "Dis Notificatio", - "custom": "Custom" - }, - "better_notifications": { - "button": { - "reply": "Respondeo", - "download": "Download", - "mark_as_read": "Mark ut Lectus" - } - }, - "profile_picture_downloader": { - "button": "Download Profile Imago", - "title": "Profile Imago Downloader", - "avatar_option": "Avatar", - "background_option": "Background" - }, - "call_start_confirmation": { - "dialog_title": "Satus Voca", - "dialog_message": "Certe vis incipere vocatio?" - }, - "half_swipe_notifier": { - "notification_channel_name": "Dimidium Swipe", - "notification_content_dm": "{friend} iustus dimidium-swiped in tuum chat pro {duration} secundis", - "notification_content_group": "{friend} iustus dimidium-swiped in {group} pro {duration} secundis" - }, - "download_processor": { - "attachment_type": { - "snap": "Snap", - "sticker": "Sticker", - "gif": "GIF", - "external_media": "Externa Media", - "note": "Nota", - "original_story": "Originalis Fabula" - }, - "select_attachments_title": "Selecta affectus", - "download_started_toast": "Download coepi", - "unsupported_content_type_toast": "Unsupported contentus genus!", - "failed_no_longer_available_toast": "Media non diutius praesto", - "no_attachments_toast": "Nulla affectus inventa!", - "already_queued_toast": "Media iam in queue!", - "already_downloaded_toast": "Media iam downloaded!", - "content_saved_toast": "Salvus!", - "download_toast": "Downloading {path}...", - "processing_toast": "Processus {path}...", - "failed_generic_toast": "Deficio ad download", - "failed_to_create_preview_toast": "Deficio creare praevisum", - "failed_processing_toast": "Deficio processus {error}", - "failed_gallery_toast": "Deficio salvis ad gallery {error}", - "dash_no_chapter": "Nulla caput inventum", - "dash_dialog": { - "title": "Download offendas media", - "download_all": "Download Omnia", - "segment_text": "Segmentum {from} - {to}" - } - }, - "streaks_reminder": { - "notification_title": "Streaks", - "notification_text": "Perdes tuum Streak cum {friend} in {hoursLeft} horis" - }, - "biometric_auth": { - "unlock_button": "Reserare", - "title": "Reserare Snapchat", - "subtitle": "Quaeso authenticas ad reserare Snapchat" - }, "end_to_end_encryption": { - "toolbox": { - "no_shared_key": "Non habes communem secretum cum hoc amico adhuc. Preme infra ad novum inchoandum.", - "shared_key_fingerprint": "Tua fingerprint est:\n\n{fingerprint}\n\nFac ut inspicias si congruit cum fingerprint amici tui!", - "initiate_exchange_button": "Inchoare Key Exchange" - }, "confirmation_dialogs": { - "title": "Finis-ad-finem encryption", - "confirmation_1": "MONITUM: Hoc erit overwrite tuum existentem clavem. Perdes accessum ad omnes encrypted nuntios ab hoc amico. Certus es vis permanere?", - "confirmation_2": "Esne VERE certus vis permanere? Hoc est ultimum tuum casum ad recedere." + "confirmation_1": "MONITUM: Haec rescribere clavem tuam existentem. Accessum solves ad omnes epistulas encryptas ab hoc amico. Certus esne vis permanere?" }, - "unencrypted_conversation_send_failure_toast": "Non potes mittere encrypted contentus ad utrumque encrypted et unencrypted colloquia!", - "native_hooks_send_failure_toast": "Deficio mittere! Quaeso enable Nativus Hooks in occasus.", - "no_participants_to_encrypt_toast": "Non habes aliquem amicos in hoc colloquio ad encrypt nuntios cum!", - "encryption_failed_toast": "Deficio encrypt nuntius! Reprehendo logcat pro magis details.", - "accept_public_key_success_toast": "Publica clavis feliciter accepta!", - "accept_secret_key_success_toast": "Actum! Nunc potes mittere et recipere encrypted nuntios cum hoc amico.", - "accept_public_key_failure_toast": "Deficio accipere publicam clavem", - "accept_secret_key_failure_toast": "Deficio accipere secretam clavem", - "accept_secret_button": "Accipe Secretum", - "accept_public_key_button": "Accipe Publicam Clavem", - "outgoing_pk_message": "Key commutatio petitio", - "outgoing_secret_message": "Key commutatio responsum", - "incoming_pk_message": "Tu modo accepisti publicam clavem petitionem. Preme infra ad accipere eam.", - "incoming_secret_message": "Amicus tuus modo accepit tuam publicam clavem. Preme infra ad accipere secretum." - }, - "auto_open_snaps": { - "title": "Auto Aperi Snaps", - "notification_content": "{count} Snaps aperuit" - }, - "friend_mutation_observer": { - "notification_channel_name": "Amicus Mutatio Observer", - "friend_removed": "{username} te removit ut amicus", - "birthday_removed": "{username} removit suum natalem ({birthday})", - "birthday_added": "{username} addidit suum natalem ({birthday})", - "birthday_changed": "{username} mutavit suum natalem ab {oldBirthday} ad {newBirthday}", - "bitmoji_selfie_changed": "{username} mutavit suum Bitmoji selfie", - "bitmoji_avatar_changed": "{username} mutavit suum Bitmoji avatar", - "bitmoji_background_changed": "{username} mutavit suum Bitmoji background", - "bitmoji_scene_changed": "{username} mutavit suum Bitmoji scaena" - }, - "material3_strings": { - "date_range_picker_start_headline": "Ab", - "date_range_picker_end_headline": "Ad", - "date_range_picker_title": "Selecta dies range", - "date_picker_switch_to_calendar_mode": "Calendarium", - "date_picker_switch_to_input_mode": "Input", - "date_range_picker_scroll_to_previous_month": "Mensis praeteritus", - "date_range_picker_scroll_to_next_month": "Proximus mensis", - "date_picker_today_description": "Hodie", - "date_range_picker_day_in_range": "Selecta", - "date_input_invalid_for_pattern": "Invalidum diem", - "date_input_invalid_year_range": "Invalidum annum", - "date_input_invalid_not_allowed": "Invalidum diem", - "date_range_input_invalid_range_input": "Invalidum diem range" - }, - "send_override_dialog": { - "title": "Mitte media ut {type}", - "duration": "Duratio: {duration}", - "saveable_snap_hint": "Fac Snap salvabile in chat", - "unlimited_duration": "Infinitus" - }, - "invalid_input_toast": "Invalidum input! Fac te intravit validum valorem." -} \ No newline at end of file + "toolbox": { + "no_shared_key": "Secretum communi cum amico nondum habes. Preme infra novam inchoare." + } + } +} diff --git a/common/src/main/assets/lang/lv_LV.json b/common/src/main/assets/lang/lv_LV.json new file mode 100644 index 00000000..c9054f25 --- /dev/null +++ b/common/src/main/assets/lang/lv_LV.json @@ -0,0 +1,44 @@ +{ + "setup": { + "mappings": { + "generate_failure_no_snapchat": "SnapEnhance nespēja atrast Snapchat, lūdzu, mēģiniet atkārtoti instalēt Snapchat.", + "dialog": "Lai dinamiski atbalstītu plašu Snapchat versiju klāstu, lai SnapEnhance darbotos pareizi, ir nepieciešamas kartēšanas, un tas neaizņems vairāk par 5 sekundēm.", + "generate_failure": "Mēģinot ģenerēt kartēšanu, radās kļūda, lūdzu, mēģiniet vēlreiz." + }, + "dialogs": { + "select_save_folder_button": "Atlasiet mapi", + "select_language": "Atlasiet valodu", + "save_folder": "SnapEnhance ir nepieciešamas glabāšanas atļaujas, lai lejupielādētu un saglabātu multivides no Snapchat.\nLūdzu, izvēlieties atrašanās vietu, kur multivides līdzekļi jālejupielādē." + }, + "permissions": { + "dialog": "Lai turpinātu, jums ir jāatbilst šādām prasībām:", + "notification_access": "Paziņojuma piekļuve", + "battery_optimization": "Akumulatora optimizācija", + "display_over_other_apps": "Displejs virs citām lietotnēm", + "request_button": "Pieprasījums" + } + }, + "manager": { + "routes": { + "logged_stories": "Story Žurnāls", + "features": "Funkcijas", + "home": "Sākums", + "home_settings": "Iestatijumi", + "logger_history": "Žurnāla Vēsture", + "home_logs": "Žurnāli", + "tasks": "Uzdevumi", + "social": "Sociāls" + }, + "sections": { + "home": { + "update_title": "SnapEnhance atjauninājums", + "update_content": "Versija {version} ir pieejama!", + "update_button": "Lejuplādēt" + } + } + }, + "scopes": { + "friend": "Draugs", + "group": "Grupa" + } +} diff --git a/common/src/main/assets/lang/ml_IN.json b/common/src/main/assets/lang/ml_IN.json new file mode 100644 index 00000000..9d5a8edd --- /dev/null +++ b/common/src/main/assets/lang/ml_IN.json @@ -0,0 +1,937 @@ +{ + "rules": { + "properties": { + "stealth": { + "options": { + "blacklist": "സ്റ്റെൽത്ത് മോഡിൽ നിന്ന് ഒഴിവാക്കുക", + "whitelist": "സ്റ്റെൽത്ത് മോഡ്" + }, + "description": "നിങ്ങൾ അവരുടെ സ്നാപ്പുകൾ/ചാറ്റുകൾ, സംഭാഷണങ്ങൾ എന്നിവ തുറന്നിട്ടുണ്ടെന്ന് അറിയുന്നതിൽ നിന്ന് ആരെയും തടയുന്നു", + "name": "സ്റ്റെൽത്ത് മോഡ്" + }, + "auto_download": { + "options": { + "whitelist": "സ്വയമേവ ഡൗൺലോഡ് ചെയ്യുന്നു", + "blacklist": "ഓട്ടോ ഡൗൺലോഡിൽ നിന്ന് ഒഴിവാക്കുക" + }, + "description": "സ്നാപ്പുകൾ കാണുമ്പോൾ അവ സ്വയമേവ ഡൗൺലോഡ് ചെയ്യുക", + "name": "യാന്ത്രിക ഡൗൺലോഡ്" + }, + "auto_save": { + "name": "സ്വയമേവ സംരക്ഷിക്കുക", + "description": "ചാറ്റ് സന്ദേശങ്ങൾ കാണുമ്പോൾ അവ സംരക്ഷിക്കുന്നു", + "options": { + "blacklist": "സ്വയമേവ സംരക്ഷിക്കുന്നതിൽ നിന്ന് ഒഴിവാക്കുക", + "whitelist": "സ്വയമേവ സംരക്ഷിക്കുക" + } + }, + "e2e_encryption": { + "name": "E2E എൻക്രിപ്ഷൻ ഉപയോഗിക്കുക" + }, + "pin_conversation": { + "name": "സംഭാഷണം പിൻ ചെയ്യുക" + }, + "unsaveable_messages": { + "name": "സംരക്ഷിക്കാൻ കഴിയാത്ത സന്ദേശങ്ങൾ", + "options": { + "blacklist": "സംരക്ഷിക്കാനാകാത്ത സന്ദേശങ്ങളിൽ നിന്ന് ഒഴിവാക്കുക", + "whitelist": "സംരക്ഷിക്കാൻ കഴിയാത്ത സന്ദേശങ്ങൾ" + }, + "description": "മറ്റ് ആളുകൾ ചാറ്റിൽ സന്ദേശങ്ങൾ സംരക്ഷിക്കുന്നത് തടയുന്നു" + }, + "hide_friend_feed": { + "name": "ഫ്രണ്ട് ഫീഡിൽ നിന്ന് മറയ്ക്കുക" + } + }, + "modes": { + "blacklist": "ബ്ലാക്ക്‌ലിസ്റ്റ് മോഡ്", + "whitelist": "വൈറ്റ്‌ലിസ്റ്റ് മോഡ്" + } + }, + "manager": { + "routes": { + "home_logs": "രേഖകൾ", + "scripts": "സ്ക്രിപ്റ്റുകൾ", + "home_settings": "ക്രമീകരണങ്ങൾ", + "features": "ഫീച്ചറുകൾ", + "home": "വീട്", + "tasks": "ചുമതലകൾ", + "social": "സാമൂഹിക", + "messaging_preview": "മുഴുവനായും" + }, + "sections": { + "social": { + "streaks_expiration_short": "{hours}h" + }, + "features": { + "disabled": "അപ്രാപ്തമാക്കി" + }, + "tasks": { + "no_tasks": "ജോലികളൊന്നുമില്ല" + }, + "home": { + "update_content": "വേർഷൻ {version} ഇപ്പോൾ ലഭ്യമാണ്", + "update_title": "സ്നാപ്ഇൻഹാൻസ് പുതുക്കൽ", + "update_button": "ശേഖരിക്കുക" + }, + "home_logs": { + "no_logs_hint": "ലോഗ്സ് ലഭ്യമല്ല", + "saving_logs_toast": "ലോഗുകൾ സേവ് ചെയുന്നു, അൽപ്പ സമയം കാത്തിരിക്കുക", + "clear_logs_button": "ക്ലിയർ ലോഗ്‌സ്", + "export_logs_button": "എക്സ്പോർട്ട് ലോക്‌സ്", + "saved_logs_success_toast": "വിജയകരമായി ലോഗ്‌സ് സേവ് ചെയ്തു", + "saved_logs_failure_toast": "Logs സേവ് ചെയ്യുന്നത് പരാജയപ്പെട്ടു" + }, + "home_settings": { + "actions_title": "പ്രവർത്തികൾ", + "debug_title": "തെറ്റ്" + } + }, + "dialogs": { + "scripting_warning": { + "content": "SnapEnhance-ൽ ഒരു സ്‌ക്രിപ്റ്റിംഗ് ടൂൾ ഉൾപ്പെടുന്നു, ഇത് നിങ്ങളുടെ ഉപകരണത്തിൽ ഉപയോക്തൃ-നിർവചിച്ച കോഡ് നടപ്പിലാക്കാൻ അനുവദിക്കുന്നു. അതീവ ജാഗ്രത പാലിക്കുക, അറിയപ്പെടുന്നതും വിശ്വസനീയവുമായ ഉറവിടങ്ങളിൽ നിന്നുള്ള മൊഡ്യൂളുകൾ മാത്രം ഇൻസ്റ്റാൾ ചെയ്യുക. അംഗീകൃതമല്ലാത്തതോ സ്ഥിരീകരിക്കാത്തതോ ആയ മൊഡ്യൂളുകൾ നിങ്ങളുടെ സിസ്റ്റത്തിന് സുരക്ഷാ അപകടങ്ങൾ സൃഷ്ടിച്ചേക്കാം.", + "title": "മുന്നറിയിപ്പ്" + }, + "add_friend": { + "title": "സുഹൃത്തിനെയോ ഗ്രൂപ്പിനെയോ ചേർക്കുക", + "search_hint": "തിരയുക", + "fetch_error": "ഡാറ്റ ലഭ്യമാക്കുന്നതിൽ പരാജയപ്പെട്ടു", + "category_friends": "സുഹൃത്തുക്കൾ", + "category_groups": "ഗ്രൂപ്പുകൾ" + } + } + }, + "setup": { + "mappings": { + "dialog": "വൈവിധ്യമാർന്ന Snapchat പതിപ്പുകളെ ചലനാത്മകമായി പിന്തുണയ്ക്കുന്നതിന്, SnapEnhance ശരിയായി പ്രവർത്തിക്കുന്നതിന് മാപ്പിംഗുകൾ ആവശ്യമാണ്, ഇതിന് 5 സെക്കൻഡിൽ കൂടുതൽ എടുക്കരുത്.", + "generate_failure_no_snapchat": "SnapEnhance-ന് Snapchat കണ്ടെത്താനായില്ല, Snapchat വീണ്ടും ഇൻസ്റ്റാൾ ചെയ്യാൻ ശ്രമിക്കുക.", + "generate_failure": "മാപ്പിംഗുകൾ സൃഷ്ടിക്കാൻ ശ്രമിക്കുമ്പോൾ ഒരു പിശക് സംഭവിച്ചു, ദയവായി വീണ്ടും ശ്രമിക്കുക." + }, + "dialogs": { + "select_save_folder_button": "ഫോൾഡർ തിരഞ്ഞെടുക്കുക", + "save_folder": "സ്നാപ്ചാറ്റിൽ നിന്ന് മീഡിയ ഡൗൺലോഡ് ചെയ്യാനും സംരക്ഷിക്കാനും SnapEnhance-ന് സ്റ്റോറേജ് അനുമതികൾ ആവശ്യമാണ്\nമീഡിയ ഡൗൺലോഡ് ചെയ്യേണ്ട സ്ഥലം തിരഞ്ഞെടുക്കുക.", + "select_language": "ഭാഷ തിരഞ്ഞെടുക്കുക" + }, + "permissions": { + "battery_optimization": "ബാറ്ററി ഒപ്റ്റിമൈസേഷൻ", + "display_over_other_apps": "മറ്റ് ആപ്പുകളിൽ പ്രദർശിപ്പിക്കുക", + "notification_access": "അറിയിപ്പ് ആക്സസ്", + "dialog": "തുടരുന്നതിന് നിങ്ങൾ ഇനിപ്പറയുന്ന ആവശ്യകതകൾ പാലിക്കേണ്ടതുണ്ട്:", + "request_button": "അഭ്യർത്ഥിക്കുക" + } + }, + "material3_strings": { + "date_range_input_invalid_range_input": "അസാധുവായ തീയതി ശ്രേണി", + "date_range_picker_scroll_to_previous_month": "കഴിഞ്ഞ മാസം", + "date_picker_switch_to_input_mode": "ഇൻപുട്ട്", + "date_range_picker_day_in_range": "തിരഞ്ഞെടുത്തു", + "date_input_invalid_for_pattern": "അസാധുവായ തീയതി", + "date_picker_today_description": "ഇന്ന്", + "date_picker_switch_to_calendar_mode": "കലണ്ടർ", + "date_range_picker_end_headline": "ലേക്ക്", + "date_range_picker_scroll_to_next_month": "അടുത്ത മാസം", + "date_input_invalid_year_range": "അസാധുവായ വർഷം", + "date_range_picker_start_headline": "നിന്ന്", + "date_range_picker_title": "തീയതി ശ്രേണി തിരഞ്ഞെടുക്കുക", + "date_input_invalid_not_allowed": "അസാധുവായ തീയതി" + }, + "features": { + "properties": { + "user_interface": { + "properties": { + "streak_expiration_info": { + "description": "സ്ട്രീക്ക് കൗണ്ടറിന് അടുത്തായി ഒരു സ്ട്രീക്ക് എക്‌സ്‌പറേഷൻ ടൈമർ കാണിക്കുന്നു", + "name": "സ്ട്രീക്ക് കാലഹരണപ്പെടൽ വിവരം കാണിക്കുക" + }, + "bootstrap_override": { + "description": "ഉപയോക്തൃ ഇന്റർഫേസ് ബൂട്ട്സ്ട്രാപ്പ് ക്രമീകരണങ്ങൾ അസാധുവാക്കുന്നു", + "properties": { + "app_appearance": { + "description": "സ്ഥിരമായ ആപ്പ് രൂപഭാവം സജ്ജമാക്കുന്നു", + "name": "ആപ്പ് രൂപഭാവം" + }, + "home_tab": { + "name": "ഹോം ടാബ്", + "description": "Snapchat തുറക്കുമ്പോൾ സ്റ്റാർട്ടപ്പ് ടാബ് അസാധുവാക്കുന്നു" + } + }, + "name": "ബൂട്ട്സ്ട്രാപ്പ് അസാധുവാക്കുക" + }, + "opera_media_quick_info": { + "description": "ഓപ്പറ വ്യൂവർ സന്ദർഭ മെനുവിൽ സൃഷ്ടിച്ച തീയതി പോലുള്ള മീഡിയയുടെ ഉപയോഗപ്രദമായ വിവരങ്ങൾ കാണിക്കുന്നു", + "name": "ഓപ്പറ മീഡിയ ദ്രുത വിവരങ്ങൾ" + }, + "map_friend_nametags": { + "description": "സ്നാപ്പ്മാപ്പിലെ സുഹൃത്തുക്കളുടെ നെയിംടാഗുകൾ മെച്ചപ്പെടുത്തുന്നു", + "name": "മെച്ചപ്പെടുത്തിയ ചങ്ങാതി മാപ്പ് നെയിംടാഗുകൾ" + }, + "vertical_story_viewer": { + "name": "ലംബമായ സ്റ്റോറി വ്യൂവർ", + "description": "എല്ലാ സ്റ്റോറികൾക്കും വെർട്ടിക്കൽ സ്റ്റോറി വ്യൂവർ പ്രവർത്തനക്ഷമമാക്കുന്നു" + }, + "friend_feed_menu_buttons": { + "name": "ഫ്രണ്ട് ഫീഡ് മെനു ബട്ടണുകൾ", + "description": "ഫ്രണ്ട് ഫീഡ് മെനുവിൽ കാണിക്കേണ്ട ബട്ടണുകൾ തിരഞ്ഞെടുക്കുക" + }, + "disable_spotlight": { + "description": "സ്പോട്ട്‌ലൈറ്റ് പേജ് പ്രവർത്തനരഹിതമാക്കുന്നു", + "name": "സ്പോട്ട്ലൈറ്റ് പ്രവർത്തനരഹിതമാക്കുക" + }, + "friend_feed_message_preview": { + "name": "ഫ്രണ്ട് ഫീഡ് സന്ദേശ പ്രിവ്യൂ", + "description": "ഫ്രണ്ട് ഫീഡിലെ അവസാന സന്ദേശങ്ങളുടെ പ്രിവ്യൂ കാണിക്കുന്നു", + "properties": { + "amount": { + "name": "തുക", + "description": "പ്രിവ്യൂ ചെയ്യാനുള്ള സന്ദേശങ്ങളുടെ അളവ്" + } + } + }, + "enable_friend_feed_menu_bar": { + "description": "പുതിയ ഫ്രണ്ട് ഫീഡ് മെനു ബാർ പ്രവർത്തനക്ഷമമാക്കുന്നു", + "name": "ഫ്രണ്ട് ഫീഡ് മെനു ബാർ" + }, + "old_bitmoji_selfie": { + "name": "പഴയ ബിറ്റ്‌മോജി സെൽഫി", + "description": "പഴയ Snapchat പതിപ്പുകളിൽ നിന്ന് Bitmoji സെൽഫികൾ തിരികെ കൊണ്ടുവരുന്നു" + }, + "hide_ui_components": { + "description": "ഏത് UI ഘടകങ്ങളാണ് മറയ്ക്കേണ്ടതെന്ന് തിരഞ്ഞെടുക്കുക", + "name": "UI ഘടകങ്ങൾ മറയ്ക്കുക" + }, + "prevent_message_list_auto_scroll": { + "name": "സന്ദേശ ലിസ്റ്റ് സ്വയമേവ സ്ക്രോൾ ചെയ്യുന്നത് തടയുക", + "description": "ഒരു സന്ദേശം അയയ്‌ക്കുമ്പോൾ/സ്വീകരിക്കുമ്പോൾ സന്ദേശ പട്ടിക താഴേക്ക് സ്ക്രോൾ ചെയ്യുന്നതിൽ നിന്ന് തടയുന്നു" + }, + "edit_text_override": { + "name": "വാചകം തിരുത്തുക", + "description": "ടെക്സ്റ്റ് ഫീൽഡ് പെരുമാറ്റം അസാധുവാക്കുന്നു" + }, + "enable_app_appearance": { + "description": "മറഞ്ഞിരിക്കുന്ന ആപ്പ് രൂപഭാവ ക്രമീകരണം പ്രവർത്തനക്ഷമമാക്കുന്നു\nപുതിയ Snapchat പതിപ്പുകളിൽ ആവശ്യമില്ലായിരിക്കാം", + "name": "ആപ്പ് രൂപഭാവ ക്രമീകരണങ്ങൾ പ്രവർത്തനക്ഷമമാക്കുക" + }, + "snap_preview": { + "name": "സ്നാപ്പ് പ്രിവ്യൂ", + "description": "ചാറ്റിൽ കാണാത്ത സ്നാപ്പുകൾക്ക് അടുത്തായി ഒരു ചെറിയ പ്രിവ്യൂ പ്രദർശിപ്പിക്കുന്നു" + }, + "hide_friend_feed_entry": { + "description": "ഫ്രണ്ട് ഫീഡിൽ നിന്ന് ഒരു പ്രത്യേക സുഹൃത്തിനെ മറയ്ക്കുന്നു\nഈ ഫീച്ചർ മാനേജ് ചെയ്യാൻ സോഷ്യൽ ടാബ് ഉപയോഗിക്കുക", + "name": "ഫ്രണ്ട് ഫീഡ് എൻട്രി മറയ്ക്കുക" + }, + "hide_streak_restore": { + "description": "ഫ്രണ്ട് ഫീഡിലെ Restore ബട്ടൺ മറയ്ക്കുന്നു", + "name": "സ്ട്രീക്ക് വീണ്ടെടുക്കൽ മറയ്ക്കുക" + } + }, + "name": "ഉപയോക്തൃ ഇന്റർഫേസ്", + "description": "Snapchat-ന്റെ രൂപവും ഭാവവും മാറ്റുക" + }, + "camera": { + "properties": { + "hevc_recording": { + "name": "HEVC റെക്കോർഡിംഗ്", + "description": "വീഡിയോ റെക്കോർഡിംഗിനായി HEVC (H.265) കോഡെക് ഉപയോഗിക്കുന്നു" + }, + "immersive_camera_preview": { + "description": "ക്യാമറ പ്രിവ്യൂ ക്രോപ്പ് ചെയ്യുന്നതിൽ നിന്ന് Snapchat തടയുന്നു\nചില ഉപകരണങ്ങളിൽ ക്യാമറ മിന്നാൻ ഇത് കാരണമായേക്കാം", + "name": "ഇമ്മേഴ്‌സീവ് പ്രിവ്യൂ" + }, + "black_photos": { + "description": "എടുത്ത ഫോട്ടോകൾക്ക് പകരം കറുപ്പ് പശ്ചാത്തലം നൽകുന്നു\nവീഡിയോകളെ ബാധിക്കില്ല", + "name": "കറുത്ത ഫോട്ടോകൾ" + }, + "force_camera_source_encoding": { + "description": "ക്യാമറ ഉറവിട എൻകോഡിംഗിനെ നിർബന്ധിക്കുന്നു", + "name": "നിർബന്ധിത ക്യാമറ ഉറവിട എൻകോഡിംഗ്" + } + }, + "description": "മികച്ച സ്നാപ്പിനായി ശരിയായ ക്രമീകരണങ്ങൾ ക്രമീകരിക്കുക", + "name": "ക്യാമറ" + }, + "global": { + "properties": { + "disable_confirmation_dialogs": { + "name": "സ്ഥിരീകരണ ഡയലോഗുകൾ പ്രവർത്തനരഹിതമാക്കുക", + "description": "തിരഞ്ഞെടുത്ത പ്രവർത്തനങ്ങൾ സ്വയമേവ സ്ഥിരീകരിക്കുന്നു" + }, + "disable_google_play_dialogs": { + "name": "Google Play സേവന ഡയലോഗുകൾ പ്രവർത്തനരഹിതമാക്കുക", + "description": "Google Play സേവനങ്ങളുടെ ലഭ്യത ഡയലോഗുകൾ കാണിക്കുന്നതിൽ നിന്ന് തടയുക" + }, + "disable_snap_splitting": { + "name": "സ്നാപ്പ് വിഭജനം പ്രവർത്തനരഹിതമാക്കുക", + "description": "Snaps ഒന്നിലധികം ഭാഗങ്ങളായി വിഭജിക്കപ്പെടുന്നത് തടയുന്നു\nനിങ്ങൾ അയയ്ക്കുന്ന ചിത്രങ്ങൾ വീഡിയോകളായി മാറും" + }, + "spotlight_comments_username": { + "name": "സ്പോട്ട്ലൈറ്റ് അഭിപ്രായങ്ങളുടെ ഉപയോക്തൃനാമം", + "description": "സ്‌പോട്ട്‌ലൈറ്റ് അഭിപ്രായങ്ങളിൽ രചയിതാവിന്റെ ഉപയോക്തൃനാമം കാണിക്കുന്നു" + }, + "auto_updater": { + "description": "പുതിയ അപ്ഡേറ്റുകൾക്കായി സ്വയമേവ പരിശോധിക്കുന്നു", + "name": "യാന്ത്രിക അപ്‌ഡേറ്റർ" + }, + "disable_metrics": { + "name": "മെട്രിക്‌സ് പ്രവർത്തനരഹിതമാക്കുക", + "description": "Snapchat-ലേക്ക് നിർദ്ദിഷ്ട അനലിറ്റിക് ഡാറ്റ അയയ്ക്കുന്നത് തടയുന്നു" + }, + "bypass_video_length_restriction": { + "description": "സിംഗിൾ: ഒരൊറ്റ വീഡിയോ അയയ്ക്കുന്നു\nവിഭജിക്കുക: എഡിറ്റ് ചെയ്ത ശേഷം വീഡിയോകൾ വിഭജിക്കുക", + "name": "വീഡിയോ ദൈർഘ്യ നിയന്ത്രണങ്ങൾ മറികടക്കുക" + }, + "snapchat_plus": { + "name": "സ്നാപ്ചാറ്റ് പ്ലസ്", + "description": "Snapchat പ്ലസ് ഫീച്ചറുകൾ പ്രവർത്തനക്ഷമമാക്കുന്നു\nചില സെർവർ-വശങ്ങളുള്ള സവിശേഷതകൾ പ്രവർത്തിച്ചേക്കില്ല" + }, + "block_ads": { + "name": "പരസ്യങ്ങൾ തടയുക", + "description": "പരസ്യങ്ങൾ പ്രദർശിപ്പിക്കുന്നത് തടയുന്നു" + } + }, + "name": "ആഗോള", + "description": "ഗ്ലോബൽ സ്‌നാപ്ചാറ്റ് ക്രമീകരണങ്ങൾ മാറ്റുക" + }, + "downloader": { + "properties": { + "force_voice_note_format": { + "name": "ഫോഴ്സ് വോയ്സ് നോട്ട് ഫോർമാറ്റ്", + "description": "വോയ്‌സ് നോട്ടുകൾ ഒരു നിർദ്ദിഷ്‌ട ഫോർമാറ്റിൽ സേവ് ചെയ്യാൻ നിർബന്ധിക്കുന്നു" + }, + "ffmpeg_options": { + "properties": { + "constant_rate_factor": { + "description": "വീഡിയോ എൻകോഡറിനായി സ്ഥിരമായ നിരക്ക് ഘടകം സജ്ജമാക്കുക\nlibx264-ന് 0 മുതൽ 51 വരെ", + "name": "സ്ഥിരമായ നിരക്ക് ഘടകം" + }, + "custom_audio_codec": { + "name": "ഇഷ്‌ടാനുസൃത ഓഡിയോ കോഡെക്", + "description": "ഒരു ഇഷ്‌ടാനുസൃത ഓഡിയോ കോഡെക് സജ്ജീകരിക്കുക (ഉദാ. AAC)" + }, + "video_bitrate": { + "name": "വീഡിയോ ബിറ്റ്റേറ്റ്", + "description": "വീഡിയോ ബിറ്റ്റേറ്റ് (kbps) സജ്ജമാക്കുക" + }, + "threads": { + "description": "ഉപയോഗിക്കേണ്ട ത്രെഡുകളുടെ അളവ്", + "name": "ത്രെഡുകൾ" + }, + "custom_video_codec": { + "description": "ഒരു ഇഷ്‌ടാനുസൃത വീഡിയോ കോഡെക് സജ്ജീകരിക്കുക (ഉദാ. libx264)", + "name": "ഇഷ്‌ടാനുസൃത വീഡിയോ കോഡെക്" + }, + "audio_bitrate": { + "name": "ഓഡിയോ ബിറ്റ്റേറ്റ്", + "description": "ഓഡിയോ ബിറ്റ്റേറ്റ് (kbps) സജ്ജമാക്കുക" + }, + "preset": { + "name": "പ്രീസെറ്റ്", + "description": "പരിവർത്തനത്തിന്റെ വേഗത സജ്ജമാക്കുക" + } + }, + "name": "FFmpeg ഓപ്ഷനുകൾ", + "description": "അധിക FFmpeg ഓപ്ഷനുകൾ വ്യക്തമാക്കുക" + }, + "prevent_self_auto_download": { + "description": "നിങ്ങളുടെ സ്വന്തം സ്നാപ്പുകൾ സ്വയമേവ ഡൗൺലോഡ് ചെയ്യുന്നതിൽ നിന്ന് തടയുന്നു", + "name": "സ്വയം യാന്ത്രിക ഡൗൺലോഡ് തടയുക" + }, + "download_profile_pictures": { + "description": "പ്രൊഫൈൽ പേജിൽ നിന്ന് പ്രൊഫൈൽ ചിത്രങ്ങൾ ഡൗൺലോഡ് ചെയ്യാൻ നിങ്ങളെ അനുവദിക്കുന്നു", + "name": "പ്രൊഫൈൽ ചിത്രങ്ങൾ ഡൗൺലോഡ് ചെയ്യുക" + }, + "auto_download_sources": { + "description": "സ്വയമേവ ഡൗൺലോഡ് ചെയ്യാനുള്ള ഉറവിടങ്ങൾ തിരഞ്ഞെടുക്കുക", + "name": "സ്വയമേവ ഡൗൺലോഡ് ഉറവിടങ്ങൾ" + }, + "allow_duplicate": { + "name": "ഡ്യൂപ്ലിക്കേറ്റ് അനുവദിക്കുക", + "description": "ഒരേ മീഡിയ ഒന്നിലധികം തവണ ഡൗൺലോഡ് ചെയ്യാൻ അനുവദിക്കുന്നു" + }, + "custom_path_format": { + "description": "ഡൗൺലോഡ് ചെയ്‌ത മീഡിയയ്‌ക്കായി ഒരു ഇഷ്‌ടാനുസൃത പാത്ത് ഫോർമാറ്റ് വ്യക്തമാക്കുക\n\nലഭ്യമായ വേരിയബിളുകൾ:\n - %ഉപയോക്തൃനാമം%\n - %ഉറവിടം%\n - %ഹാഷ്%\n - %തീയതി സമയം%", + "name": "ഇഷ്‌ടാനുസൃത പാത്ത് ഫോർമാറ്റ്" + }, + "force_image_format": { + "name": "ഫോഴ്സ് ഇമേജ് ഫോർമാറ്റ്", + "description": "ചിത്രങ്ങൾ ഒരു നിർദ്ദിഷ്ട ഫോർമാറ്റിൽ സംരക്ഷിക്കാൻ നിർബന്ധിക്കുന്നു" + }, + "opera_download_button": { + "description": "ഒരു Snap കാണുമ്പോൾ മുകളിൽ വലത് കോണിൽ ഒരു ഡൗൺലോഡ് ബട്ടൺ ചേർക്കുന്നു", + "name": "ഓപ്പറ ഡൗൺലോഡ് ബട്ടൺ" + }, + "save_folder": { + "name": "ഫോൾഡർ സംരക്ഷിക്കുക", + "description": "എല്ലാ മീഡിയയും ഡൗൺലോഡ് ചെയ്യേണ്ട ഡയറക്‌ടറി തിരഞ്ഞെടുക്കുക" + }, + "merge_overlays": { + "name": "ഓവർലേകൾ ലയിപ്പിക്കുക", + "description": "ഒരു സ്‌നാപ്പിന്റെ ടെക്‌സ്‌റ്റും മീഡിയയും ഒരു ഫയലായി സംയോജിപ്പിക്കുന്നു" + }, + "logging": { + "description": "മീഡിയ ഡൗൺലോഡ് ചെയ്യുമ്പോൾ ടോസ്റ്റുകൾ കാണിക്കുന്നു", + "name": "ലോഗിംഗ്" + }, + "path_format": { + "name": "പാത്ത് ഫോർമാറ്റ്", + "description": "ഫയൽ പാത്ത് ഫോർമാറ്റ് വ്യക്തമാക്കുക" + } + }, + "description": "Snapchat മീഡിയ ഡൗൺലോഡ് ചെയ്യുക", + "name": "ഡൗൺലോഡർ" + }, + "experimental": { + "properties": { + "spoof": { + "properties": { + "remove_mock_location_flag": { + "name": "മോക്ക് ലൊക്കേഷൻ ഫ്ലാഗ് നീക്കം ചെയ്യുക", + "description": "മോക്ക് ലൊക്കേഷൻ കണ്ടെത്തുന്നതിൽ നിന്ന് Snapchat തടയുന്നു" + }, + "remove_vpn_transport_flag": { + "description": "VPN-കൾ കണ്ടെത്തുന്നതിൽ നിന്ന് Snapchat തടയുന്നു", + "name": "VPN ട്രാൻസ്പോർട്ട് ഫ്ലാഗ് നീക്കം ചെയ്യുക" + }, + "play_store_installer_package_name": { + "description": "com.android.vending എന്നതിലേക്ക് ഇൻസ്റ്റാളർ പാക്കേജിന്റെ പേര് അസാധുവാക്കുന്നു", + "name": "പ്ലേ സ്റ്റോർ ഇൻസ്റ്റാളർ പാക്കേജിന്റെ പേര്" + } + }, + "description": "നിങ്ങളെക്കുറിച്ചുള്ള വിവിധ വിവരങ്ങൾ കബളിപ്പിക്കുക", + "name": "സ്പൂഫ്" + }, + "native_hooks": { + "properties": { + "disable_bitmoji": { + "description": "ചങ്ങാതിമാരുടെ പ്രൊഫൈൽ ബിറ്റ്മോജി പ്രവർത്തനരഹിതമാക്കുന്നു", + "name": "ബിറ്റ്‌മോജി പ്രവർത്തനരഹിതമാക്കുക" + } + }, + "description": "Snapchat-ന്റെ നേറ്റീവ് കോഡിലേക്ക് ഹുക്ക് ചെയ്യുന്ന സുരക്ഷിതമല്ലാത്ത ഫീച്ചറുകൾ", + "name": "നേറ്റീവ് ഹുക്കുകൾ" + }, + "convert_message_locally": { + "description": "പ്രാദേശികമായി ബാഹ്യ മീഡിയ ചാറ്റ് ചെയ്യാൻ സ്നാപ്പുകൾ പരിവർത്തനം ചെയ്യുന്നു. ചാറ്റ് ഡൗൺലോഡ് സന്ദർഭ മെനുവിൽ ഇത് ദൃശ്യമാകും", + "name": "സന്ദേശം പ്രാദേശികമായി പരിവർത്തനം ചെയ്യുക" + }, + "story_logger": { + "name": "സ്റ്റോറി ലോഗർ", + "description": "സുഹൃത്തുക്കളുടെ കഥകളുടെ ചരിത്രം നൽകുന്നു" + }, + "infinite_story_boost": { + "name": "അനന്തമായ കഥ ബൂസ്റ്റ്", + "description": "സ്റ്റോറി ബൂസ്റ്റ് പരിധി കാലതാമസം മറികടക്കുക" + }, + "no_friend_score_delay": { + "name": "ഫ്രണ്ട് സ്‌കോർ കാലതാമസം ഇല്ല", + "description": "ഒരു ഫ്രണ്ട്സ് സ്കോർ കാണുമ്പോഴുള്ള കാലതാമസം നീക്കം ചെയ്യുന്നു" + }, + "e2ee": { + "properties": { + "encrypted_message_indicator": { + "name": "എൻക്രിപ്റ്റ് ചെയ്ത സന്ദേശ സൂചകം", + "description": "എൻക്രിപ്റ്റ് ചെയ്ത സന്ദേശങ്ങൾക്ക് അടുത്തായി ഒരു 🔒 ഇമോജി ചേർക്കുന്നു" + }, + "force_message_encryption": { + "name": "നിർബന്ധിത സന്ദേശ എൻക്രിപ്ഷൻ", + "description": "ഒന്നിലധികം സംഭാഷണങ്ങൾ തിരഞ്ഞെടുക്കുമ്പോൾ മാത്രം E2E എൻക്രിപ്ഷൻ പ്രവർത്തനക്ഷമമാക്കാത്ത ആളുകൾക്ക് എൻക്രിപ്റ്റ് ചെയ്ത സന്ദേശങ്ങൾ അയക്കുന്നത് തടയുന്നു" + } + }, + "name": "എൻഡ്-ടു-എൻഡ് എൻക്രിപ്ഷൻ", + "description": "പങ്കിട്ട രഹസ്യ കീ ഉപയോഗിച്ച് AES ഉപയോഗിച്ച് നിങ്ങളുടെ സന്ദേശങ്ങൾ എൻക്രിപ്റ്റ് ചെയ്യുന്നു\nനിങ്ങളുടെ താക്കോൽ സുരക്ഷിതമായി എവിടെയെങ്കിലും സൂക്ഷിക്കുന്നത് ഉറപ്പാക്കുക!" + }, + "add_friend_source_spoof": { + "name": "സുഹൃത്ത് ഉറവിട സ്പൂഫ് ചേർക്കുക", + "description": "ഒരു സുഹൃത്ത് അഭ്യർത്ഥനയുടെ ഉറവിടം കബളിപ്പിക്കുന്നു" + }, + "hidden_snapchat_plus_features": { + "name": "മറഞ്ഞിരിക്കുന്ന Snapchat പ്ലസ് ഫീച്ചറുകൾ", + "description": "റിലീസ് ചെയ്യാത്ത/ബീറ്റ Snapchat പ്ലസ് ഫീച്ചറുകൾ പ്രവർത്തനക്ഷമമാക്കുന്നു\nപഴയ Snapchat പതിപ്പുകളിൽ പ്രവർത്തിച്ചേക്കില്ല" + }, + "prevent_forced_logout": { + "name": "നിർബന്ധിത ലോഗ്ഔട്ട് തടയുക", + "description": "നിങ്ങൾ മറ്റൊരു ഉപകരണത്തിൽ ലോഗിൻ ചെയ്യുമ്പോൾ നിങ്ങളെ ലോഗ് ഔട്ട് ചെയ്യുന്നതിൽ നിന്ന് Snapchat തടയുന്നു" + }, + "meo_passcode_bypass": { + "name": "എന്റെ കണ്ണുകൾ മാത്രം പാസ്‌കോഡ് ബൈപാസ്", + "description": "മൈ ഐസ് ഒൺലി പാസ്‌കോഡ് ബൈപാസ് ചെയ്യുക\nമുമ്പ് പാസ്‌കോഡ് ശരിയായി നൽകിയിട്ടുണ്ടെങ്കിൽ മാത്രമേ ഇത് പ്രവർത്തിക്കൂ" + } + }, + "description": "പരീക്ഷണാത്മക സവിശേഷതകൾ", + "name": "പരീക്ഷണാത്മകം" + }, + "messaging": { + "properties": { + "notification_blacklist": { + "name": "നോട്ടിഫിക്കേഷൻ ബ്ലാക്ക്‌ലിസ്റ്റ്", + "description": "ബ്ലോക്ക് ചെയ്യേണ്ട അറിയിപ്പുകൾ തിരഞ്ഞെടുക്കുക" + }, + "prevent_message_sending": { + "name": "സന്ദേശം അയയ്ക്കുന്നത് തടയുക", + "description": "ചില തരത്തിലുള്ള സന്ദേശങ്ങൾ അയക്കുന്നത് തടയുന്നു" + }, + "message_logger": { + "properties": { + "message_filter": { + "name": "സന്ദേശ ഫിൽട്ടർ", + "description": "ഏതൊക്കെ സന്ദേശങ്ങളാണ് ലോഗിൻ ചെയ്യേണ്ടതെന്ന് തിരഞ്ഞെടുക്കുക (എല്ലാ സന്ദേശങ്ങൾക്കും ശൂന്യം)" + }, + "auto_purge": { + "description": "നിർദ്ദിഷ്‌ട സമയത്തേക്കാൾ പഴയ കാഷെ ചെയ്‌ത സന്ദേശങ്ങൾ സ്വയമേവ ഇല്ലാതാക്കുന്നു", + "name": "യാന്ത്രിക ശുദ്ധീകരണം" + }, + "keep_my_own_messages": { + "name": "എന്റെ സ്വന്തം സന്ദേശങ്ങൾ സൂക്ഷിക്കുക", + "description": "നിങ്ങളുടെ സ്വന്തം സന്ദേശങ്ങൾ ഇല്ലാതാക്കുന്നതിൽ നിന്ന് തടയുന്നു" + } + }, + "description": "സന്ദേശങ്ങൾ ഇല്ലാതാക്കുന്നത് തടയുന്നു", + "name": "സന്ദേശ ലോഗർ" + }, + "anonymous_story_viewing": { + "name": "അജ്ഞാത കഥ കാണൽ", + "description": "നിങ്ങൾ അവരുടെ കഥ കണ്ടുവെന്ന് അറിയുന്നതിൽ നിന്ന് ആരെയും തടയുന്നു" + }, + "loop_media_playback": { + "name": "ലൂപ്പ് മീഡിയ പ്ലേബാക്ക്", + "description": "സ്നാപ്പുകൾ / സ്റ്റോറികൾ കാണുമ്പോൾ മീഡിയ പ്ലേബാക്ക് ലൂപ്പ് ചെയ്യുന്നു" + }, + "disable_replay_in_ff": { + "description": "ഫ്രണ്ട് ഫീഡിൽ നിന്ന് ദീർഘനേരം അമർത്തി വീണ്ടും പ്ലേ ചെയ്യാനുള്ള കഴിവ് പ്രവർത്തനരഹിതമാക്കുന്നു", + "name": "FF-ൽ റീപ്ലേ പ്രവർത്തനരഹിതമാക്കുക" + }, + "call_start_confirmation": { + "name": "കോൾ ആരംഭ സ്ഥിരീകരണം", + "description": "ഒരു കോൾ ആരംഭിക്കുമ്പോൾ ഒരു സ്ഥിരീകരണ ഡയലോഗ് കാണിക്കുന്നു" + }, + "half_swipe_notifier": { + "properties": { + "min_duration": { + "name": "കുറഞ്ഞ ദൈർഘ്യം", + "description": "പകുതി സ്വൈപ്പിന്റെ ഏറ്റവും കുറഞ്ഞ ദൈർഘ്യം (സെക്കൻഡിൽ)" + }, + "max_duration": { + "description": "പകുതി സ്വൈപ്പിന്റെ പരമാവധി ദൈർഘ്യം (സെക്കൻഡിൽ)", + "name": "പരമാവധി ദൈർഘ്യം" + } + }, + "name": "ഹാഫ് സ്വൈപ്പ് നോട്ടിഫയർ", + "description": "ആരെങ്കിലും സംഭാഷണത്തിലേക്ക് പാതി സ്വൈപ്പ് ചെയ്യുമ്പോൾ നിങ്ങളെ അറിയിക്കും" + }, + "bypass_screenshot_detection": { + "description": "നിങ്ങൾ സ്‌ക്രീൻഷോട്ട് എടുക്കുമ്പോൾ സ്‌നാപ്ചാറ്റ് കണ്ടെത്തുന്നതിൽ നിന്ന് തടയുന്നു", + "name": "ബൈപാസ് സ്ക്രീൻഷോട്ട് കണ്ടെത്തൽ" + }, + "gallery_media_send_override": { + "description": "ഗാലറിയിൽ നിന്ന് അയയ്‌ക്കുമ്പോൾ മീഡിയ ഉറവിടം കബളിപ്പിക്കുന്നു", + "name": "ഗാലറി മീഡിയ അയയ്‌ക്കുക അസാധുവാക്കുക" + }, + "strip_media_metadata": { + "description": "ഒരു സന്ദേശമായി അയയ്‌ക്കുന്നതിന് മുമ്പ് മീഡിയയുടെ മെറ്റാഡാറ്റ നീക്കംചെയ്യുന്നു", + "name": "സ്ട്രിപ്പ് മീഡിയ മെറ്റാഡാറ്റ" + }, + "better_notifications": { + "description": "ലഭിച്ച അറിയിപ്പുകളിൽ കൂടുതൽ വിവരങ്ങൾ ചേർക്കുന്നു", + "name": "മികച്ച അറിയിപ്പുകൾ" + }, + "auto_save_messages_in_conversations": { + "name": "സന്ദേശങ്ങൾ സ്വയമേവ സംരക്ഷിക്കുക", + "description": "സംഭാഷണങ്ങളിലെ എല്ലാ സന്ദേശങ്ങളും സ്വയമേവ സംരക്ഷിക്കുന്നു" + }, + "bypass_message_retention_policy": { + "name": "ബൈപാസ് സന്ദേശം നിലനിർത്തൽ നയം", + "description": "സന്ദേശങ്ങൾ കണ്ടതിന് ശേഷം ഇല്ലാതാക്കുന്നത് തടയുന്നു" + }, + "prevent_story_rewatch_indicator": { + "name": "സ്റ്റോറി റീവാച്ച് ഇൻഡിക്കേറ്റർ തടയുക", + "description": "നിങ്ങൾ അവരുടെ കഥ വീണ്ടും കണ്ടുവെന്ന് അറിയുന്നതിൽ നിന്ന് ആരെയും തടയുന്നു" + }, + "hide_bitmoji_presence": { + "name": "ബിറ്റ്‌മോജി സാന്നിധ്യം മറയ്ക്കുക", + "description": "ചാറ്റിൽ ആയിരിക്കുമ്പോൾ നിങ്ങളുടെ ബിറ്റ്‌മോജി പോപ്പ് അപ്പ് ചെയ്യുന്നത് തടയുന്നു" + }, + "unlimited_snap_view_time": { + "name": "അൺലിമിറ്റഡ് സ്നാപ്പ് കാഴ്ച സമയം", + "description": "സ്നാപ്പുകൾ കാണുന്നതിനുള്ള സമയ പരിധി നീക്കം ചെയ്യുന്നു" + }, + "hide_typing_notifications": { + "description": "നിങ്ങൾ ഒരു സന്ദേശം ടൈപ്പുചെയ്യുന്നത് അറിയുന്നതിൽ നിന്ന് ആരെയും തടയുന്നു", + "name": "ടൈപ്പിംഗ് അറിയിപ്പുകൾ മറയ്ക്കുക" + }, + "hide_peek_a_peek": { + "description": "നിങ്ങൾ ഒരു ചാറ്റിലേക്ക് പകുതി സ്വൈപ്പ് ചെയ്യുമ്പോൾ അറിയിപ്പ് അയയ്ക്കുന്നത് തടയുന്നു", + "name": "പീക്ക്-എ-പീക്ക് മറയ്ക്കുക" + } + }, + "name": "സന്ദേശമയയ്ക്കൽ", + "description": "നിങ്ങൾ സുഹൃത്തുക്കളുമായി ഇടപഴകുന്ന രീതി മാറ്റുക" + }, + "streaks_reminder": { + "properties": { + "group_notifications": { + "description": "ഗ്രൂപ്പ് അറിയിപ്പുകൾ ഒറ്റ ഒന്നായി", + "name": "ഗ്രൂപ്പ് അറിയിപ്പുകൾ" + }, + "interval": { + "name": "ഇടവേള", + "description": "ഓരോ ഓർമ്മപ്പെടുത്തലുകൾക്കിടയിലുള്ള ഇടവേള (മണിക്കൂറുകൾ)" + }, + "remaining_hours": { + "name": "ശേഷിക്കുന്ന സമയം", + "description": "അറിയിപ്പിന് മുമ്പുള്ള ശേഷിക്കുന്ന സമയം കാണിക്കുന്നു" + } + }, + "description": "നിങ്ങളുടെ സ്ട്രീക്കുകളെക്കുറിച്ച് ആനുകാലികമായി നിങ്ങളെ അറിയിക്കുന്നു", + "name": "സ്ട്രീക്കുകൾ ഓർമ്മപ്പെടുത്തൽ" + }, + "rules": { + "description": "വ്യക്തിഗത ആളുകൾക്കായി സ്വയമേവയുള്ള സവിശേഷതകൾ നിയന്ത്രിക്കുക", + "name": "നിയമങ്ങൾ" + }, + "scripting": { + "description": "SnapEnhance വിപുലീകരിക്കാൻ ഇഷ്ടാനുസൃത സ്ക്രിപ്റ്റുകൾ പ്രവർത്തിപ്പിക്കുക", + "name": "സ്ക്രിപ്റ്റിംഗ്", + "properties": { + "developer_mode": { + "name": "ഡെവലപ്പർ മോഡ്", + "description": "Snapchat-ന്റെ UI-യിൽ ഡീബഗ് വിവരങ്ങൾ കാണിക്കുന്നു" + }, + "module_folder": { + "name": "മൊഡ്യൂൾ ഫോൾഡർ", + "description": "സ്ക്രിപ്റ്റുകൾ സ്ഥിതി ചെയ്യുന്ന ഫോൾഡർ" + }, + "auto_reload": { + "name": "യാന്ത്രികമായി വീണ്ടും ലോഡുചെയ്യുക", + "description": "സ്ക്രിപ്റ്റുകൾ മാറുമ്പോൾ അവ സ്വയമേവ റീലോഡ് ചെയ്യുന്നു" + }, + "integrated_ui": { + "name": "ഇന്റഗ്രേറ്റഡ് യുഐ", + "description": "Snapchat-ലേക്ക് ഇഷ്‌ടാനുസൃത UI ഘടകങ്ങൾ ചേർക്കാൻ സ്‌ക്രിപ്റ്റുകളെ അനുവദിക്കുന്നു" + }, + "disable_log_anonymization": { + "name": "ലോഗ് അജ്ഞാതമാക്കൽ പ്രവർത്തനരഹിതമാക്കുക", + "description": "ലോഗുകളുടെ അജ്ഞാതവൽക്കരണം പ്രവർത്തനരഹിതമാക്കുന്നു" + } + } + } + }, + "notices": { + "internal_behavior": "⚠ ഇത് Snapchat ആന്തരിക സ്വഭാവത്തെ തകർത്തേക്കാം", + "ban_risk": "⚠ ഈ സവിശേഷത വിലക്കുകൾക്ക് കാരണമായേക്കാം", + "unstable": "⚠ അസ്ഥിരമാണ്" + }, + "options": { + "friend_feed_menu_buttons": { + "auto_download": "⬇️ ഓട്ടോ ഡൗൺലോഡ്", + "auto_save": "💬 സന്ദേശങ്ങൾ സ്വയമേവ സംരക്ഷിക്കുക", + "unsaveable_messages": "⬇️ സംരക്ഷിക്കാനാവാത്ത സന്ദേശങ്ങൾ", + "stealth": "👻 സ്റ്റെൽത്ത് മോഡ്", + "conversation_info": "👤 സംഭാഷണ വിവരം", + "e2e_encryption": "🔒 E2E എൻക്രിപ്ഷൻ ഉപയോഗിക്കുക", + "mark_snaps_as_seen": "👀 Snaps കണ്ടതായി അടയാളപ്പെടുത്തുക", + "mark_stories_as_seen_locally": "👀 പ്രാദേശികമായി കാണുന്ന കഥകൾ അടയാളപ്പെടുത്തുക" + }, + "path_format": { + "create_author_folder": "ഓരോ രചയിതാവിനും ഫോൾഡർ സൃഷ്ടിക്കുക", + "create_source_folder": "ഓരോ മീഡിയ ഉറവിട തരത്തിനും ഫോൾഡർ സൃഷ്‌ടിക്കുക", + "append_hash": "ഫയലിന്റെ പേരിൽ ഒരു അദ്വിതീയ ഹാഷ് ചേർക്കുക", + "append_username": "ഫയലിന്റെ പേരിലേക്ക് ഉപയോക്തൃനാമം ചേർക്കുക", + "append_date_time": "ഫയലിന്റെ പേരിൽ തീയതിയും സമയവും ചേർക്കുക", + "append_source": "ഫയലിന്റെ പേരിലേക്ക് മീഡിയ ഉറവിടം ചേർക്കുക" + }, + "auto_download_sources": { + "friend_stories": "സുഹൃത്ത് കഥകൾ", + "public_stories": "പൊതു കഥകൾ", + "spotlight": "സ്പോട്ട്ലൈറ്റ്", + "friend_snaps": "സുഹൃത്ത് സ്നാപ്സ്" + }, + "logging": { + "progress": "പുരോഗതി", + "failure": "പരാജയം", + "started": "ആരംഭിച്ചു", + "success": "വിജയം" + }, + "notifications": { + "chat_screenshot": "സ്ക്രീൻഷോട്ട്", + "chat_screen_record": "സ്ക്രീൻ റെക്കോർഡ്", + "snap_replay": "സ്നാപ്പ് റീപ്ലേ", + "camera_roll_save": "ക്യാമറ റോൾ സേവ്", + "chat": "ചാറ്റ്", + "chat_reply": "ചാറ്റ് മറുപടി", + "snap": "സ്നാപ്പ്", + "typing": "ടൈപ്പിംഗ്", + "stories": "കഥകൾ", + "group_chat_reaction": "ഗ്രൂപ്പ് പ്രതികരണം", + "initiate_audio": "ഇൻകമിംഗ് ഓഡിയോ കോൾ", + "abandon_audio": "മിസ്‌ഡ് ഓഡിയോ കോൾ", + "abandon_video": "മിസ്‌ഡ് വീഡിയോ കോൾ", + "chat_reaction": "ഡിഎം പ്രതികരണം", + "initiate_video": "ഇൻകമിംഗ് വീഡിയോ കോൾ" + }, + "gallery_media_send_override": { + "ORIGINAL": "ഒറിജിനൽ", + "NOTE": "ഓഡിയോ കുറിപ്പ്", + "SNAP": "സ്നാപ്പ്" + }, + "strip_media_metadata": { + "hide_snap_filters": "സ്നാപ്പ് ഫിൽട്ടറുകൾ മറയ്ക്കുക", + "hide_extras": "എക്സ്ട്രാകൾ മറയ്ക്കുക (ഉദാ. പരാമർശങ്ങൾ)", + "remove_audio_note_transcript_capability": "ഓഡിയോ നോട്ട് ട്രാൻസ്ക്രിപ്റ്റ് ശേഷി നീക്കം ചെയ്യുക", + "hide_caption_text": "അടിക്കുറിപ്പ് വാചകം മറയ്ക്കുക", + "remove_audio_note_duration": "ഓഡിയോ നോട്ട് ദൈർഘ്യം നീക്കം ചെയ്യുക" + }, + "hide_ui_components": { + "hide_chat_call_buttons": "ചാറ്റ് കോൾ ബട്ടണുകൾ നീക്കം ചെയ്യുക", + "hide_live_location_share_button": "തത്സമയ ലൊക്കേഷൻ പങ്കിടൽ ബട്ടൺ നീക്കം ചെയ്യുക", + "hide_voice_record_button": "വോയ്സ് റെക്കോർഡ് ബട്ടൺ നീക്കം ചെയ്യുക", + "hide_profile_call_buttons": "പ്രൊഫൈൽ കോൾ ബട്ടണുകൾ നീക്കം ചെയ്യുക", + "hide_stickers_button": "സ്റ്റിക്കറുകൾ ബട്ടൺ നീക്കം ചെയ്യുക", + "hide_unread_chat_hint": "വായിക്കാത്ത ചാറ്റ് സൂചന നീക്കം ചെയ്യുക" + }, + "home_tab": { + "map": "മാപ്പ്", + "chat": "ചാറ്റ്", + "camera": "ക്യാമറ", + "discover": "കണ്ടെത്തുക", + "spotlight": "സ്പോട്ട്ലൈറ്റ്" + }, + "add_friend_source_spoof": { + "added_by_mention": "പരാമർശം വഴി", + "added_by_group_chat": "ഗ്രൂപ്പ് ചാറ്റ് വഴി", + "added_by_qr_code": "QR കോഡ് വഴി", + "added_by_community": "കമ്മ്യൂണിറ്റി പ്രകാരം", + "added_by_username": "ഉപയോക്തൃനാമം പ്രകാരം" + }, + "bypass_video_length_restriction": { + "single": "ഏക മാധ്യമം", + "split": "സ്പ്ലിറ്റ് മീഡിയ" + }, + "old_bitmoji_selfie": { + "2d": "2D ബിറ്റ്‌മോജി", + "3d": "3D ബിറ്റ്‌മോജി" + }, + "disable_confirmation_dialogs": { + "block_friend": "സുഹൃത്തിനെ തടയുക", + "ignore_friend": "സുഹൃത്തിനെ അവഗണിക്കുക", + "hide_friend": "സുഹൃത്തിനെ മറയ്ക്കുക", + "hide_conversation": "സംഭാഷണം മറയ്ക്കുക", + "remove_friend": "സുഹൃത്തിനെ നീക്കം ചെയ്യുക", + "clear_conversation": "ഫ്രണ്ട് ഫീഡിൽ നിന്ന് സംഭാഷണം മായ്‌ക്കുക" + }, + "auto_reload": { + "snapchat_only": "Snapchat മാത്രം", + "all": "എല്ലാം (Snapchat SnapEnhance)" + }, + "edit_text_override": { + "multi_line_chat_input": "മൾട്ടി ലൈൻ ചാറ്റ് ഇൻപുട്ട്", + "bypass_text_input_limit": "ബൈപാസ് ടെക്സ്റ്റ് ഇൻപുട്ട് പരിധി" + }, + "auto_purge": { + "never": "ഒരിക്കലുമില്ല", + "1_hour": "1 മണിക്കൂർ", + "3_hours": "3 മണിക്കൂർ", + "6_hours": "6 മണിക്കൂർ", + "12_hours": "12 മണിക്കൂർ", + "1_day": "1 ദിവസം", + "3_days": "3 ദിവസം", + "1_week": "1 ആഴ്ച", + "2_weeks": "2 ആഴ്ച", + "1_month": "1 മാസം", + "3_months": "3 മാസം", + "6_months": "6 മാസം" + }, + "app_appearance": { + "always_light": "എപ്പോഴും വെളിച്ചം", + "always_dark": "എപ്പോഴും ഇരുട്ട്" + } + } + }, + "content_type": { + "NOTE": "ഓഡിയോ കുറിപ്പ്", + "STATUS": "പദവി", + "STATUS_SAVE_TO_CAMERA_ROLL": "ക്യാമറ റോളിൽ സംരക്ഷിച്ചു", + "STATUS_CONVERSATION_CAPTURE_SCREENSHOT": "സ്ക്രീൻഷോട്ട്", + "STATUS_CONVERSATION_CAPTURE_RECORD": "സ്ക്രീൻ റെക്കോർഡ്", + "STATUS_CALL_MISSED_VIDEO": "മിസ്‌ഡ് വീഡിയോ കോൾ", + "SNAP": "സ്നാപ്പ്", + "STATUS_COUNTDOWN": "കൗണ്ട്ഡൗൺ", + "STICKER": "സ്റ്റിക്കർ", + "LOCATION": "സ്ഥാനം", + "STATUS_CALL_MISSED_AUDIO": "മിസ്‌ഡ് ഓഡിയോ കോൾ", + "CHAT": "ചാറ്റ്", + "EXTERNAL_MEDIA": "ബാഹ്യ മാധ്യമങ്ങൾ", + "CREATIVE_TOOL_ITEM": "ക്രിയേറ്റീവ് ടൂൾ ഇനം", + "FAMILY_CENTER_INVITE": "കുടുംബ കേന്ദ്രം ക്ഷണം", + "FAMILY_CENTER_ACCEPT": "കുടുംബ കേന്ദ്രം സ്വീകരിക്കുക", + "FAMILY_CENTER_LEAVE": "ഫാമിലി സെന്റർ ലീവ്", + "STATUS_PLUS_GIFT": "സ്റ്റാറ്റസ് പ്ലസ് സമ്മാനം", + "TINY_SNAP": "ചെറിയ സ്നാപ്പ്", + "LIVE_LOCATION_SHARE": "തത്സമയ ലൊക്കേഷൻ പങ്കിടുക" + }, + "profile_info": { + "snapchat_plus_state": { + "not_subscribed": "സബ്സ്ക്രൈബ് ചെയ്തിട്ടില്ല", + "subscribed": "സബ്സ്ക്രൈബ് ചെയ്തു" + }, + "title": "പ്രൊഫൈൽ വിവരം", + "snapchat_plus": "സ്നാപ്ചാറ്റ് പ്ലസ്", + "friendship": "സൗഹൃദം", + "add_source": "ഉറവിടം ചേർക്കുക", + "birthday": "ജന്മദിനം : {മാസം} {ദിവസം}", + "display_name": "പ്രദർശന നാമം", + "added_date": "ചേർത്ത തീയതി", + "first_created_username": "ആദ്യം സൃഷ്ടിച്ച ഉപയോക്തൃനാമം", + "hidden_birthday": "ജന്മദിനം: മറഞ്ഞിരിക്കുന്നു", + "mutable_username": "മാറ്റാവുന്ന ഉപയോക്തൃനാമം" + }, + "friendship_link_type": { + "mutual": "പരസ്പരമുള്ള", + "blocked": "തടഞ്ഞു", + "deleted": "ഇല്ലാതാക്കി", + "following": "പിന്തുടരുന്നു", + "suggested": "നിർദ്ദേശിച്ചു", + "incoming_follower": "ഇൻകമിംഗ് ഫോളോവർ", + "outgoing": "ഔട്ട്ഗോയിംഗ്", + "incoming": "ഇൻകമിംഗ്" + }, + "media_download_source": { + "public_story": "പൊതു കഥ", + "spotlight": "സ്പോട്ട്ലൈറ്റ്", + "profile_picture": "പ്രൊഫൈൽ ചിത്രം", + "chat_media": "ചാറ്റ് മീഡിയ", + "story": "കഥ", + "merged": "ലയിപ്പിച്ചു", + "none": "ഒന്നുമില്ല", + "pending": "തീർപ്പാക്കാത്തത്", + "story_logger": "സ്റ്റോറി ലോഗർ" + }, + "chat_action_menu": { + "download_button": "ഡൗൺലോഡ്", + "delete_logged_message_button": "ലോഗിൻ ചെയ്ത സന്ദേശം ഇല്ലാതാക്കുക", + "preview_button": "പ്രിവ്യൂ", + "convert_message": "സന്ദേശം പരിവർത്തനം ചെയ്യുക" + }, + "modal_option": { + "close": "അടയ്ക്കുക", + "profile_info": "പ്രൊഫൈൽ വിവരം" + }, + "conversation_preview": { + "streak_expiration": "{day} ദിവസം {hour} മണിക്കൂർ {minute} മിനിറ്റിനുള്ളിൽ കാലഹരണപ്പെടുന്നു", + "total_messages": "ആകെ അയച്ച/ലഭിച്ച സന്ദേശങ്ങൾ: {count}", + "title": "പ്രിവ്യൂ", + "unknown_user": "അജ്ഞാത ഉപയോക്താവ്" + }, + "opera_context_menu": { + "created_at": "{date}-ന് സൃഷ്‌ടിച്ചത്", + "expires_at": "{date}-ന് കാലഹരണപ്പെടുന്നു", + "media_duration": "മീഡിയ ദൈർഘ്യം: {duration} ms", + "show_debug_info": "ഡീബഗ് വിവരം കാണിക്കുക", + "sent_at": "{date}-ന് അയച്ചു", + "media_size": "മീഡിയ വലുപ്പം: {size}", + "download": "മീഡിയ ഡൗൺലോഡ് ചെയ്യുക" + }, + "bulk_messaging_action": { + "progress_status": "{total}-ന്റെ {index} പ്രോസസ്സ് ചെയ്യുന്നു", + "selection_dialog_continue_button": "തുടരുക", + "actions": { + "remove_friends": "സുഹൃത്തുക്കളെ നീക്കം ചെയ്യുക", + "clear_conversations": "വ്യക്തമായ സംഭാഷണങ്ങൾ" + }, + "confirmation_dialog": { + "message": "ഇത് തിരഞ്ഞെടുത്ത എല്ലാ സുഹൃത്തുക്കളെയും ബാധിക്കും. ഈ പ്രവർത്തനം പഴയപടിയാക്കാനാകില്ല.", + "title": "നിങ്ങൾക്ക് ഉറപ്പാണോ?" + }, + "choose_action_title": "ഒരു പ്രവർത്തനം തിരഞ്ഞെടുക്കുക" + }, + "chat_export": { + "exporter_dialog": { + "select_conversations_title": "സംഭാഷണങ്ങൾ തിരഞ്ഞെടുക്കുക", + "text_field_selection": "{തുക} തിരഞ്ഞെടുത്തു", + "text_field_selection_all": "എല്ലാം", + "export_file_format_title": "ഫയൽ ഫോർമാറ്റ് കയറ്റുമതി ചെയ്യുക", + "download_medias_title": "Medias ഡൗൺലോഡ് ചെയ്യുക", + "message_type_filter_title": "തരം അനുസരിച്ച് സന്ദേശങ്ങൾ ഫിൽട്ടർ ചെയ്യുക", + "amount_of_messages_title": "സന്ദേശങ്ങളുടെ അളവ് (എല്ലാവർക്കും ശൂന്യമായി വിടുക)" + }, + "dialog_negative_button": "റദ്ദാക്കുക", + "dialog_positive_button": "കയറ്റുമതി", + "exported_to": "{path}-ലേക്ക് കയറ്റുമതി ചെയ്തു", + "exporting_chats": "ചാറ്റുകൾ കയറ്റുമതി ചെയ്യുന്നു...", + "export_fail": "സംഭാഷണം {conversation} കയറ്റുമതി ചെയ്യാനായില്ല", + "writing_output": "ഔട്ട്പുട്ട് എഴുതുന്നു...", + "finished": "ചെയ്തു! നിങ്ങൾക്ക് ഇപ്പോൾ ഈ ഡയലോഗ് അടയ്ക്കാം.", + "no_messages_found": "സന്ദേശങ്ങളൊന്നും കണ്ടെത്തിയില്ല!", + "exporting_message": "{conversation} എക്‌സ്‌പോർട്ട് ചെയ്യുന്നു...", + "processing_chats": "{amount} സംഭാഷണങ്ങൾ പ്രോസസ്സ് ചെയ്യുന്നു..." + }, + "button": { + "ok": "ശരി", + "positive": "അതെ", + "negative": "ഇല്ല", + "cancel": "റദ്ദാക്കുക", + "download": "ഡൗൺലോഡ്", + "open": "തുറക്കുക" + }, + "better_notifications": { + "button": { + "reply": "മറുപടി", + "download": "ഡൗൺലോഡ്", + "mark_as_read": "വായിച്ചതായി അടയാളപ്പെടുത്തുക" + } + }, + "profile_picture_downloader": { + "button": "പ്രൊഫൈൽ ചിത്രം ഡൗൺലോഡ് ചെയ്യുക", + "avatar_option": "അവതാർ", + "background_option": "പശ്ചാത്തലം", + "title": "പ്രൊഫൈൽ ചിത്രം ഡൗൺലോഡർ" + }, + "call_start_confirmation": { + "dialog_title": "കോൾ ആരംഭിക്കുക", + "dialog_message": "നിങ്ങൾക്ക് ഒരു കോൾ ആരംഭിക്കണമെന്ന് തീർച്ചയാണോ?" + }, + "half_swipe_notifier": { + "notification_channel_name": "പകുതി സ്വൈപ്പ് ചെയ്യുക", + "notification_content_group": "{friend} {group}-ലേക്ക് {duration} സെക്കൻഡ് പകുതി സ്വൈപ്പ് ചെയ്തു", + "notification_content_dm": "{സുഹൃത്ത്} നിങ്ങളുടെ ചാറ്റിലേക്ക് {duration} സെക്കൻഡ് പകുതി സ്വൈപ്പ് ചെയ്തു" + }, + "download_processor": { + "attachment_type": { + "snap": "സ്നാപ്പ്", + "sticker": "സ്റ്റിക്കർ", + "external_media": "ബാഹ്യ മാധ്യമങ്ങൾ", + "note": "കുറിപ്പ്", + "original_story": "ഒറിജിനൽ സ്റ്റോറി" + }, + "download_started_toast": "ഡൗൺലോഡ് ആരംഭിച്ചു", + "unsupported_content_type_toast": "പിന്തുണയ്‌ക്കാത്ത ഉള്ളടക്ക തരം!", + "failed_no_longer_available_toast": "മീഡിയ ഇനി ലഭ്യമല്ല", + "no_attachments_toast": "അറ്റാച്ചുമെന്റുകളൊന്നും കണ്ടെത്തിയില്ല!", + "already_queued_toast": "മാധ്യമങ്ങൾ ഇതിനകം ക്യൂവിലാണ്!", + "already_downloaded_toast": "മീഡിയ ഇതിനകം ഡൗൺലോഡ് ചെയ്‌തു!", + "download_toast": "{path} ഡൗൺലോഡ് ചെയ്യുന്നു...", + "failed_generic_toast": "ഡൗൺലോഡ് ചെയ്യാനായില്ല", + "failed_to_create_preview_toast": "പ്രിവ്യൂ സൃഷ്ടിക്കുന്നതിൽ പരാജയപ്പെട്ടു", + "failed_gallery_toast": "ഗാലറിയിൽ സംരക്ഷിക്കുന്നതിൽ പരാജയപ്പെട്ടു {പിശക്}", + "select_attachments_title": "ഡൗൺലോഡ് ചെയ്യാൻ അറ്റാച്ച്‌മെന്റുകൾ തിരഞ്ഞെടുക്കുക", + "processing_toast": "{path} പ്രോസസ്സ് ചെയ്യുന്നു...", + "failed_processing_toast": "പ്രോസസ്സിംഗ് പരാജയപ്പെട്ടു {പിശക്}" + }, + "streaks_reminder": { + "notification_title": "വരകൾ", + "notification_text": "{hoursLeft} മണിക്കൂറിനുള്ളിൽ {സുഹൃത്തുമായുള്ള നിങ്ങളുടെ സ്ട്രീക്ക് നിങ്ങൾക്ക് നഷ്ടപ്പെടും" + }, + "gallery_media_send_override": { + "multiple_media_toast": "നിങ്ങൾക്ക് ഒരു സമയം ഒരു മീഡിയ മാത്രമേ അയയ്ക്കാൻ കഴിയൂ" + }, + "friend_menu_option": { + "mark_snaps_as_seen": "Snaps കണ്ടതായി അടയാളപ്പെടുത്തുക", + "mark_stories_as_seen_locally": "പ്രാദേശികമായി കാണുന്ന കഥകൾ അടയാളപ്പെടുത്തുക", + "preview": "പ്രിവ്യൂ", + "stealth_mode": "സ്റ്റെൽത്ത് മോഡ്", + "auto_download_blacklist": "ഓട്ടോ ഡൗൺലോഡ് ബ്ലാക്ക്‌ലിസ്റ്റ്", + "anti_auto_save": "ആന്റി ഓട്ടോ സേവ്" + }, + "scopes": { + "friend": "സുഹൃത്ത്", + "group": "കുട്ടായ്മ" + } +} diff --git a/common/src/main/assets/lang/mr.json b/common/src/main/assets/lang/mr.json deleted file mode 100644 index 7a0ee36d..00000000 --- a/common/src/main/assets/lang/mr.json +++ /dev/null @@ -1,2022 +0,0 @@ -{ - "setup": { - "dialogs": { - "select_language": "भाषा निवडा", - "save_folder": "प्युरफेक्टस्नॅपला स्नॅपचॅटमधून मीडिया डाउनलोड आणि जतन करण्यासाठी स्टोरेज परवानग्या आवश्यक आहेत.\nकृपया ज्या ठिकाणी मीडिया डाउनलोड केले जावे ते ठिकाण निवडा.", - "select_save_folder_button": "फोल्डर निवडा" - }, - "mappings": { - "dialog": "मॅपिंग तयार करणे, यास थोडा वेळ लागू शकेल ...", - "generate_failure_no_snapchat": "पुर्रफेक्टस्नॅप स्नॅपचॅट शोधण्यात अक्षम होता, कृपया स्नॅपचॅट पुन्हा स्थापित करण्याचा प्रयत्न करा.", - "generate_failure": "मॅपिंग व्युत्पन्न करण्याचा प्रयत्न करताना एक त्रुटी आली, कृपया पुन्हा प्रयत्न करा." - }, - "permissions": { - "dialog": "सुरू ठेवण्यासाठी आपल्याला खालील आवश्यकता फिट करणे आवश्यक आहे:", - "notification_access": "सूचना प्रवेश", - "battery_optimization": "बॅटरी ऑप्टिमायझेशन", - "display_over_other_apps": "इतर अॅप्सवर प्रदर्शित करा", - "request_button": "विनंती" - } - }, - "scopes": { - "friend": "मित्र", - "group": "गट" - }, - "manager": { - "routes": { - "tasks": "कार्ये", - "features": "वैशिष्ट्ये", - "manage_rule_feature": "नियम वैशिष्ट्य व्यवस्थापित करा", - "home": "मुख्यपृष्ठ", - "home_settings": "सेटिंग्ज", - "home_logs": "लॉग", - "logger_history": "लॉगर इतिहास", - "logged_stories": "लॉग केलेल्या कथा", - "friend_tracker": "मित्र ट्रॅकर", - "edit_rule": "नियम संपादित करा", - "file_imports": "फाईल आयात", - "manage_repos": "रेपॉजिटरीज व्यवस्थापित करा", - "social": "सामाजिक", - "manage_scope": "व्याप्ती व्यवस्थापित करा", - "messaging_preview": "पूर्वावलोकन", - "scripts": "स्क्रिप्ट्स", - "better_location": "चांगले स्थान" - }, - "sections": { - "home": { - "version_title": "v{versionName} · Eternal द्वारे फोर्क केलेले", - "update_title": "PurrfectSnap अद्यतन", - "update_content": "आवृत्ती {version} उपलब्ध आहे!", - "update_button": "डाउनलोड करा", - "debug_build_summary_title": "आपण पुर्रफेक्ट्सनॅपची डीबग बिल्ड चालवित आहात", - "debug_build_summary_content": "आवृत्ती {versionName} ({versionCode})", - "debug_build_summary_date": "बिल्ड तारीख: {date} ({days} दिवसांपूर्वी)", - "quick_actions_title": "द्रुत क्रिया", - "download_icon_description": "डाउनलोड करा", - "completed_icon_description": "पूर्ण", - "failed_icon_description": "अयशस्वी", - "manage_quick_actions_description": "द्रुत क्रिया व्यवस्थापित करा", - "quick_actions_icon_description": "द्रुत क्रिया", - "add_quick_action_description": "द्रुत क्रिया जोडा" - }, - "home_logs": { - "no_logs_hint": "लॉग उपलब्ध नाहीत", - "clear_logs_button": "लॉग साफ करा", - "export_logs_button": "लॉग निर्यात करा", - "saving_logs_toast": "लॉग जतन करणे, यास थोडा वेळ लागू शकेल ...", - "saved_logs_success_toast": "लॉग यशस्वीरित्या जतन केले", - "saved_logs_failure_toast": "लॉग जतन करण्यात अयशस्वी" - }, - "home_settings": { - "actions_title": "क्रिया", - "message_logger_title": "संदेश लॉगर", - "debug_title": "डीबग", - "success_toast": "पूर्ण झाले!", - "message_logger_summary": "{messageCount} संदेश\n{storyCount} कथा", - "export_button": "निर्यात", - "clear_button": "स्पष्ट", - "view_logger_history_button": "लॉगर इतिहास पहा", - "updates_title": "अद्यतने", - "auto_update_check": "अद्यतनांसाठी स्वयं तपासणी करा", - "update_check_frequency": "वारंवारता अद्यतनित करा", - "update_check_frequency_daily": "दररोज", - "update_check_frequency_weekly": "साप्ताहिक", - "update_check_frequency_monthly": "मासिक", - "theme_icon_description": "थीम", - "app_theme_title": "अ‍ॅप थीम", - "theme_mode_system": "प्रणाली", - "theme_mode_light": "प्रकाश", - "theme_mode_dark": "गडद", - "ui_settings_title": "UI सेटिंग्ज", - "haptic_feedback_label": "हॅप्टिक अभिप्राय", - "test_mode_label": "चाचणी मोड (केवळ डीबगिंगसाठी)", - "disable_feature_loading_label": "वैशिष्ट्य लोडिंग अक्षम करा", - "disable_auto_mapper_label": "ऑटो मॅपर अक्षम करा", - "disable_bypass_indicator_label": "बायपास स्थिती निर्देशक अक्षम करा", - "update_notification_channel_name": "PurrfectSnap अद्यतने", - "update_notification_channel_description": "PurrfectSnap अद्यतनांसाठी सूचना", - "update_notification_title": "PurrfectSnap अद्यतन उपलब्ध", - "update_notification_text": "आवृत्ती %s आता उपलब्ध आहे.", - "export_database_failed_toast": "डेटाबेस निर्यात करण्यात अयशस्वी! {message}", - "clear_messages_failed_toast": "संदेश साफ करण्यात अयशस्वी! {message}", - "clear_file_failed_toast": "फाईल साफ करण्यात अयशस्वी! {message}", - "debug_file_config": "कॉन्फिगरेशन", - "debug_file_mappings": "मॅपिंग्ज", - "debug_file_message_logger": "संदेश लॉगर", - "debug_file_pinned_best_friend": "पिन केलेला चांगला मित्र", - "debug_file_native_sig_cache": "मूळ स्वाक्षरी कॅशे" - }, - "tasks": { - "no_tasks": "कार्ये नाहीत", - "merge_button": "विलीनीकरण", - "failed_to_open_file": "फाईल उघडण्यात अयशस्वी", - "merge_files_toast": "विलीनीकरण {count} फायली", - "remove_selected_tasks_title": "आपणास खात्री आहे की आपण निवडलेली कार्ये काढू इच्छिता?", - "remove_all_tasks_title": "आपणास खात्री आहे की आपण सर्व कार्ये काढू इच्छिता?", - "delete_files_option": "फायली देखील हटवा", - "remove_selected_tasks_confirm": "{count} कार्ये काढा?", - "remove_all_tasks_confirm": "सर्व कार्ये काढा?", - "clear_tasks_description": "स्पष्ट कार्ये", - "file_not_found_icon_description": "फाईल सापडली नाही", - "image_icon_description": "प्रतिमा", - "video_icon_description": "व्हिडिओ", - "audio_icon_description": "ऑडिओ", - "file_icon_description": "फाईल", - "download_icon_description": "डाउनलोड करा", - "chat_action_icon_description": "गप्पा क्रिया", - "cancel_icon_description": "रद्द करा", - "success_icon_description": "यश", - "failure_icon_description": "अयशस्वी", - "cancelled_icon_description": "रद्द", - "task_status_failure": "अयशस्वी", - "task_status_cancelled": "रद्द" - }, - "features": { - "disabled": "अक्षम", - "export_option": "निर्यात", - "import_option": "आयात", - "reset_option": "रीसेट", - "config_export_success_toast": "कॉन्फिगरेशन यशस्वीरित्या निर्यात केले", - "config_import_success_toast": "कॉन्फिगरेशन यशस्वीरित्या आयात केले", - "config_import_failure_toast": "कॉन्फिगरेशन आयात करण्यात अयशस्वी {error}", - "config_export_failure_toast": "कॉन्फिगरेशन निर्यात करण्यात अयशस्वी {error}", - "saved_config_snackbar": "कॉन्फिगरेशन जतन केले", - "older_required": "या वैशिष्ट्यास योग्यरित्या कार्य करण्यासाठी स्नॅपचॅट v{version} किंवा त्याहून अधिक आवश्यक आहे", - "newer_required": "या वैशिष्ट्यासाठी स्नॅपचॅट v{version} किंवा योग्यरित्या कार्य करण्यासाठी नवीन आवश्यक आहे", - "search_button": "शोध" - }, - "manage_rule_feature": { - "disable_state_option": "अक्षम", - "disable_state_subtext": "कोणत्याही मित्र/गटांवर परिणाम होणार नाही", - "whitelist_state_option": "वगळता कोणीही नाही ...", - "whitelist_state_subtext": "केवळ {count} मित्र/गट या नियमांमुळे प्रभावित होतील", - "whitelist_state_button": "अनुमत मित्र/गट निवडा", - "blacklist_state_option": "वगळता प्रत्येकजण ...", - "blacklist_state_subtext": "या नियमांमुळे {count} मित्र/गट वगळता प्रत्येकजण प्रभावित होईल", - "blacklist_state_button": "वगळलेले मित्र/गट निवडा", - "clear_list_button": "मित्र/गटांची यादी साफ करा", - "dialog_clear_confirmation_text": "आपणास खात्री आहे की आपण यादी साफ करू इच्छिता?" - }, - "social": { - "friends_tab": "मित्र", - "groups_tab": "गट", - "empty_hint": "(रिक्त)", - "streaks_expiration_short": "{hours} तास" - }, - "manage_scope": { - "logged_stories_button": "लॉग केलेल्या कथा दर्शवा", - "e2ee_title": "एंड-टू-एंड एन्क्रिप्शन", - "rules_title": "नियम", - "participants_text": "{count} सहभागी", - "not_found": "सापडले नाही", - "streaks_title": "पट्ट्या", - "streaks_length_text": "लांबी: {length}", - "streaks_expiration_text": "{eta} मध्ये कालबाह्य होईल", - "streaks_expiration_text_expired": "कालबाह्य झाले", - "reminder_button": "स्मरणपत्र सेट करा", - "delete_scope_confirm_dialog_title": "आपणास खात्री आहे की आपण {scope} हटवू इच्छिता?", - "notes_placeholder": "एक टीप जोडण्यासाठी क्लिक करा", - "invalid_key_size_32_bytes": "अवैध की आकार (32 बाइट असणे आवश्यक आहे)", - "successfully_imported_key": "यशस्वीरित्या आयात की", - "failed_to_import_key": "की आयात करण्यात अयशस्वी: {message}", - "export_base64_button": "निर्यात बेस 64", - "import_base64_button": "आयात बेस 64" - }, - "logged_stories": { - "story_failed_to_load": "लोड करण्यात अयशस्वी", - "no_stories": "कोणत्याही कथा सापडल्या नाहीत", - "save_from_cache_button": "कॅशेमधून जतन करा", - "downloaded_to_path": "{path} वर डाउनलोड केले", - "download_failed": "डाउनलोड अयशस्वी: {message}", - "posted_at": "{date} वर पोस्ट केले", - "created_at": "{date} येथे तयार केले", - "failed_to_open_file": "फाईल उघडण्यात अयशस्वी. अधिक माहितीसाठी लॉग तपासा", - "failed_to_get_file": "फाईल मिळविण्यात अयशस्वी" - }, - "messaging_preview": { - "processed_messages_toast": "प्रक्रिया केलेले {count} संदेश", - "processed_messages_text": "प्रक्रिया केलेले {count} संदेश", - "close_button_description": "बंद", - "bridge_connection_failed": "पुलाशी कनेक्ट करण्यात अयशस्वी. पार्श्वभूमीवर स्नॅपचॅट चालू असल्याचे सुनिश्चित करा", - "bridge_init_failed": "मेसेजिंग ब्रिज आरंभ करण्यात अयशस्वी. पार्श्वभूमीवर स्नॅपचॅट चालू असल्याचे सुनिश्चित करा", - "message_fetch_failed": "संदेश आणण्यात अयशस्वी", - "no_message_hint": "कोणताही संदेश नाही", - "save_selection_option": "निवड जतन करा", - "save_all_option": "सर्व जतन करा", - "unsave_selection_option": "निवड रद्द करा", - "unsave_all_option": "सर्व अनस करा", - "mark_selection_as_seen_option": "पाहिल्याप्रमाणे निवडलेला स्नॅप चिन्हांकित करा", - "mark_all_as_seen_option": "पाहिल्याप्रमाणे सर्व स्नॅप्स चिन्हांकित करा", - "delete_selection_option": "निवड हटवा", - "delete_all_option": "सर्व हटवा" - }, - "logger_history": { - "download_started_toast": "डाउनलोड प्रारंभ!", - "download_success_toast": "{path} वर डाउनलोड केले", - "download_failed_toast": "{message} डाउनलोड करण्यात अयशस्वी", - "edited_at_text": "{message} ({date} वर संपादित केलेले)", - "download_button": "डाउनलोड करा", - "select_conversation_placeholder": "संभाषण निवडा", - "close_button_description": "बंद", - "search_button_description": "शोध", - "list_friend_format": "मित्र {name}", - "list_group_format": "गट {name}", - "no_more_messages": "आणखी संदेश नाहीत", - "reverse_order_checkbox": "उलट ऑर्डर", - "chat_attachment": "संलग्नक {index}", - "empty_message": "रिक्त गप्पा संदेश", - "message_parse_failed": "संदेश विश्लेषित करण्यात अयशस्वी", - "unknown_sender": "अज्ञात प्रेषक", - "download_attachment_failed_toast": "संलग्नक डाउनलोड करण्यात अयशस्वी", - "log_header_format": "{username} ({type}) - {date}" - }, - "file_imports": { - "import_file_button": "आयात फाइल", - "file_not_found": "फाईल सापडली नाही", - "file_import_failed": "फाइल आयात करण्यात अयशस्वी: {error}", - "file_imported": "फाइल यशस्वीरित्या आयात केली", - "file_delete_failed": "फाईल हटविण्यात अयशस्वी", - "no_files_hint": "येथे आपण स्नॅपचॅटमध्ये वापरासाठी फायली आयात करू शकता. फाईल आयात करण्यासाठी खालील बटण दाबा." - }, - "better_location": { - "spoofed_coordinates_title": "लॅट {latitude}, एलएनजी {longitude}", - "save_coordinates_dialog_title": "समन्वय जतन करा", - "saved_name_dialog_hint": "जतन केलेले नाव", - "latitude_dialog_hint": "अक्षांश", - "longitude_dialog_hint": "रेखांश", - "save_dialog_button": "जतन करा", - "choose_location_button": "स्थान निवडा", - "teleport_to_friend_button": "मित्राला टेलिपोर्ट", - "spoof_location_toggle": "स्पूफ स्थान", - "suspend_location_updates": "स्थान अद्यतने निलंबित करा", - "saved_coordinates_title": "जतन केलेले निर्देशांक", - "no_saved_coordinates_hint": "जतन केलेले निर्देशांक नाही", - "delete_dialog_title": "जतन केलेले समन्वय हटवा", - "delete_dialog_message": "आपणास खात्री आहे की आपण हे जतन केलेले समन्वय हटवू इच्छिता?", - "teleport_to_friend_title": "मित्राला टेलिपोर्ट", - "search_bar": "शोध", - "no_friends_map": "नकाशावर मित्र नाहीत", - "no_friends_found": "कोणतेही मित्र सापडले नाहीत", - "edit_location_button_description": "स्थान संपादित करा", - "add_icon_description": "जोडा", - "edit_icon_description": "संपादित करा", - "delete_icon_description": "हटवा" - } - }, - "dialogs": { - "add_friend": { - "title": "मित्र किंवा गट जोडा", - "search_hint": "शोध", - "fetch_error": "डेटा आणण्यात अयशस्वी", - "category_groups": "गट", - "category_friends": "मित्र", - "participants_text": "{count} सहभागी", - "search_icon_description": "शोध" - }, - "scripting_warning": { - "title": "चेतावणी", - "content": "आपल्या डिव्हाइसवरील वापरकर्ता-परिभाषित कोडची अंमलबजावणी करण्यास अनुमती देणारी, प्युरफेक्ट्सनॅपमध्ये एक स्क्रिप्टिंग टूल समाविष्ट आहे. अत्यंत सावधगिरी बाळगा आणि केवळ ज्ञात, विश्वसनीय स्त्रोतांमधून मॉड्यूल स्थापित करा. अनधिकृत किंवा असत्यापित मॉड्यूल्स आपल्या सिस्टमला सुरक्षा जोखीम असू शकतात." - }, - "reset_config": { - "title": "रीसेट कॉन्फिगरेशन", - "content": "आपणास खात्री आहे की आपण कॉन्फिगरेशन रीसेट करू इच्छिता?", - "success_toast": "कॉन्फिगरेशन यशस्वीरित्या रीसेट करा" - }, - "export_config": { - "title": "संवेदनशील डेटा निर्यात?", - "content": "आपण संवेदनशील डेटासह कॉन्फिगरेशन निर्यात करू इच्छिता? (जसे की स्थान समन्वय इ.)" - }, - "messaging_action": { - "title": "प्रक्रियेसाठी सामग्रीचे प्रकार निवडा", - "select_all_button": "सर्व निवडा" - }, - "file_imports": { - "no_files_settings_hint": "कोणत्याही फायली सापडल्या नाहीत. आपण फाइल आयात विभागात आवश्यक फायली आयात केल्या असल्याचे सुनिश्चित करा", - "settings_select_file_hint": "आयात केलेली फाईल निवडा" - }, - "quick_actions_dialog": { - "title": "द्रुत क्रिया संपादित करा", - "subtitle": "आपल्या द्रुत क्रिया निवडा आणि आकार द्या." - } - }, - "friend_tracker": { - "rules_tab": "नियम", - "logs_tab": "लॉग", - "export_dialog_title": "निर्यात", - "bulk_export_button": "मोठ्या प्रमाणात निर्यात", - "individual_export_button": "वैयक्तिक निर्यात", - "invalid_import_type_dialog_title": "अवैध आयात प्रकार", - "invalid_import_type_dialog_text": "निवडलेली फाइल या आयात प्रकाराशी सुसंगत नाही. कृपया योग्य आयात प्रकार निवडा.", - "import_dialog_title": "आयात", - "bulk_import_button": "मोठ्या प्रमाणात आयात", - "individual_import_button": "वैयक्तिक आयात", - "import_button_description": "आयात", - "export_button_description": "निर्यात", - "export_button": "निर्यात", - "delete_button_description": "हटवा", - "delete_button": "हटवा", - "catalog_button_description": "कॅटलॉग", - "catalog_button": "कॅटलॉग", - "add_rule_button_description": "नियम जोडा", - "add_rule_button": "नियम जोडा", - "no_rules_found": "कोणतेही नियम सापडले नाहीत", - "empty_rule_name": "(रिक्त)", - "events_suffix": "घटना", - "scopes_suffix": "स्कोप", - "select_rule_to_export_title": "निर्यात करण्यासाठी नियम निवडा", - "deleted_logs_toast": "हटविले {count} लॉग", - "delete_logs_dialog_title": "लॉग हटवा?", - "deleting_logs_dialog_text": "हटवित आहे {count} लॉग ...", - "delete_logs_dialog_confirm_text": "हे वर्तमान फिल्टर आणि शोध क्वेरीवर आधारित लॉग हटवेल. ही क्रिया पूर्ववत केली जाऊ शकत नाही.", - "exported_logs_toast": "निर्यात नोंदी!", - "export_logs_failed_toast": "लॉग निर्यात करण्यात अयशस्वी. अधिक तपशीलांसाठी लॉगकॅट तपासा.", - "export_logs_dialog_title": "लॉग निर्यात?", - "exporting_logs_dialog_text": "लॉग निर्यात करीत आहे ...", - "export_logs_dialog_confirm_text": "हे सध्याच्या फिल्टर आणि शोध क्वेरीवर आधारित लॉग निर्यात करेल.", - "export_as_button": "{type} म्हणून निर्यात करा", - "filters_title": "फिल्टर", - "search_by_label": "द्वारे शोध", - "newest_first_label": "प्रथम नवीन", - "since_label": "तेव्हापासून", - "until_label": "पर्यंत", - "pick_a_date_button": "तारीख निवडा", - "search_placeholder": "शोध", - "filter_button_description": "फिल्टर", - "clear_button_description": "स्पष्ट", - "no_logs_found": "लॉग आढळले नाहीत", - "log_event_format": "{event} मध्ये {conversation}", - "condition_only_inside_conversation": "जेव्हा मी संभाषणात असतो तेव्हाच", - "condition_only_outside_conversation": "जेव्हा मी संभाषण बाहेर असतो तेव्हाच", - "condition_only_when_app_active": "जेव्हा स्नॅपचॅट सक्रिय असेल तेव्हाच", - "condition_only_when_app_inactive": "जेव्हा स्नॅपचॅट निष्क्रिय असेल तेव्हाच", - "condition_no_push_notification_when_app_active": "स्नॅपचॅट सक्रिय असताना कोणतीही सूचना नाही", - "add_event_dialog_title": "कार्यक्रम जोडा", - "event_type_label": "कार्यक्रम प्रकार", - "triggers_title": "ट्रिगर", - "conditions_title": "अटी", - "add_button": "जोडा", - "default_rule_name": "सानुकूल नियम", - "discard_changes_dialog_title": "बदल टाकून द्या?", - "discard_changes_dialog_text": "आपल्याकडे जतन न केलेले बदल आहेत. आपणास खात्री आहे की आपण त्यांना टाकून देऊ इच्छिता?", - "discard_button": "टाकून द्या", - "cannot_save_rule_dialog_title": "नियम जतन करू शकत नाही", - "cannot_save_rule_dialog_text": "नियमात कमीतकमी एक कार्यक्रम असणे आवश्यक आहे.", - "duplicate_rule_name_dialog_title": "डुप्लिकेट नियम नाव", - "duplicate_rule_name_dialog_text": "या नावाचा नियम आधीपासून अस्तित्त्वात आहे. कृपया एक भिन्न नाव निवडा.", - "delete_rule_dialog_title": "नियम हटवा", - "delete_rule_dialog_text": "आपणास खात्री आहे की आपण हा नियम हटवू इच्छिता?", - "new_rule_title": "नवीन नियम", - "edit_rule_title": "नियम संपादित करा", - "back_button_description": "मागे", - "save_button_description": "जतन करा", - "general_section_title": "सामान्य", - "rule_name_label": "नियम नाव", - "author_name_label": "लेखकाचे नाव", - "scope_section_title": "व्याप्ती", - "scope_all": "सर्व", - "scope_whitelist": "श्वेतसूची", - "scope_blacklist": "ब्लॅकलिस्ट", - "select_friends_groups_button": "मित्र/गट निवडा ({count})", - "events_section_title": "घटना", - "add_event_button": "कार्यक्रम जोडा", - "no_events_text": "नाही इव्हेंट्स" - }, - "friend_tracker_catalog": { - "download_failed": "अयशस्वी डाउनलोड: {code}", - "error": "त्रुटी: {message}", - "no_repos_added": "कोणतेही रेपॉजिटरी जोडले नाहीत.", - "no_rules_available": "कोणत्याही रेपोकडून कोणतेही नियम उपलब्ध नाहीत.", - "by_author": "{author} द्वारा", - "imported_button": "आयात", - "import_button": "आयात", - "title": "मित्र ट्रॅकर कॅटलॉग", - "manage_repos_description": "रेपॉजिटरीज व्यवस्थापित करा" - }, - "friend_tracker_export": { - "title": "निर्यात नियम", - "back_button_description": "मागे", - "exported_toast": "मित्र ट्रॅकर नियम निर्यात!", - "export_failed_toast": "नियम निर्यात करण्यात अयशस्वी: {message}", - "save_button": "जतन करा", - "expand_button_description": "विस्तृत करा" - }, - "friend_tracker_import": { - "title": "आयात नियम", - "back_button_description": "मागे", - "imported_toast": "मित्र ट्रॅकर नियम आयात!", - "import_failed_toast": "नियम आयात करण्यात अयशस्वी: {message}", - "confirm_button": "पुष्टी करा", - "expand_button_description": "विस्तृत करा" - }, - "friend_tracker_repos": { - "invalid_repo_title": "अवैध रेपॉजिटरी", - "add_repo_button": "रेपॉजिटरी जोडा", - "add_repo_dialog_title": "रेपॉजिटरी URL जोडा", - "repo_url_label": "रेपॉजिटरी URL", - "repo_added_toast": "रेपॉजिटरी यशस्वीरित्या जोडली!", - "invalid_repo_error": "हे एक वैध मित्र ट्रॅकर रेपॉजिटरी असल्याचे दिसत नाही.", - "add_repo_failed_toast": "रेपॉजिटरी जोडण्यात अयशस्वी: {message}", - "add_button": "जोडा", - "no_repos_added": "कोणतेही रेपॉजिटरी जोडले नाहीत", - "remove_button": "काढा", - "remove_repo_dialog_title": "रेपॉजिटरी काढा", - "remove_repo_dialog_text": "आपणास खात्री आहे की आपण हे रेपॉजिटरी काढू इच्छिता?" - }, - "navigation": { - "tracker_tab_label": "ट्रॅकर", - "customize_bottom_bar_title": "तळाशी बार सानुकूलित करा", - "customize_bottom_bar_subtitle": "पुनर्क्रमित करा, टॅब जोडा किंवा काढा. जास्तीत जास्त पाच.", - "shown_tabs_title": "टॅब दर्शविले", - "no_tabs_selected_text": "कोणतेही टॅब निवडलेले नाहीत", - "available_tabs_title": "उपलब्ध टॅब", - "reset_button": "रीसेट", - "done_button": "पूर्ण झाले" - }, - "scripting": { - "script_already_installed": "स्क्रिप्ट आधीच स्थापित!", - "downloading_script": "स्क्रिप्ट डाउनलोड करीत आहे ...", - "script_downloaded": "स्क्रिप्ट {name} डाउनलोड केले!", - "download_script_failed": "स्क्रिप्ट डाउनलोड करण्यात अयशस्वी. अधिक तपशीलांसाठी लॉग तपासा", - "import_script_from_url_title": "URL वरून स्क्रिप्ट आयात करा", - "import_script_warning": "चेतावणी: आयात केलेल्या स्क्रिप्ट्स आपल्या डिव्हाइससाठी हानिकारक असू शकतात. केवळ विश्वासू स्त्रोतांकडून स्क्रिप्ट आयात करा.", - "enter_url_label": "येथे URL प्रविष्ट करा:", - "script_imported": "स्क्रिप्ट {name} आयात केले!", - "import_failed": "स्क्रिप्ट आयात करण्यात अयशस्वी. {message}. अधिक तपशीलांसाठी लॉग तपासा", - "import_button": "आयात", - "update_module_button": "मॉड्यूल अद्यतनित करा", - "updating_script": "स्क्रिप्ट अद्यतनित करीत आहे {name}...", - "module_not_found": "मॉड्यूल सापडला नाही", - "updated_script": "आवृत्तीवर {name} अद्यतनित केले {version}", - "update_module_failed": "मॉड्यूल अद्यतनित करण्यात अयशस्वी. अधिक तपशीलांसाठी लॉग तपासा", - "edit_module_button": "मॉड्यूल संपादित करा", - "open_module_failed": "मॉड्यूल फाइल उघडण्यात अयशस्वी. अधिक तपशीलांसाठी लॉग तपासा", - "clear_module_data_button": "मॉड्यूल डेटा साफ करा", - "module_data_cleared": "मॉड्यूल डेटा साफ केला!", - "clear_module_data_failed": "मॉड्यूल डेटा साफ करण्यात अयशस्वी. अधिक तपशीलांसाठी लॉग तपासा", - "delete_module_button": "मॉड्यूल हटवा", - "deleted_script": "हटविलेली स्क्रिप्ट {name}!", - "delete_module_failed": "मॉड्यूल हटविण्यात अयशस्वी. अधिक तपशीलांसाठी लॉग तपासा", - "actions_title": "क्रिया", - "no_description": "कोणतेही वर्णन नाही", - "update_available": "अद्यतन उपलब्ध: {version}", - "actions_button": "क्रिया", - "loaded_script": "लोड केलेली स्क्रिप्ट {name}", - "unloaded_script": "अनलोड केलेली स्क्रिप्ट {name}", - "enable_script_failed": "स्क्रिप्ट सक्षम करण्यात अयशस्वी. अधिक तपशीलांसाठी लॉग तपासा", - "disable_script_failed": "स्क्रिप्ट अक्षम करण्यात अयशस्वी. अधिक तपशीलांसाठी लॉग तपासा", - "select_scripts_folder_toast": "कृपया आपले स्क्रिप्ट्स फोल्डर निवडा!", - "manage_repos_button": "रेपो व्यवस्थापित करा", - "import_from_url_button": "URL वरून आयात करा", - "open_scripts_folder_button": "स्क्रिप्ट्स फोल्डर उघडा", - "no_settings_for_module": "या मॉड्यूलमध्ये कोणतीही सेटिंग्ज नाहीत", - "installed_scripts_tab": "स्थापित स्क्रिप्ट्स", - "catalog_tab": "कॅटलॉग", - "no_scripts_folder_selected_title": "कोणतेही स्क्रिप्ट फोल्डर निवडलेले नाही", - "select_folder_button": "फोल्डर निवडा", - "no_scripts_found_title": "कोणतीही स्क्रिप्ट सापडली नाही.", - "use_catalog_to_add_scripts": "स्क्रिप्ट जोडण्यासाठी कॅटलॉग टॅब वापरा!", - "ok_button_timeout": "ठीक आहे ({timeout})", - "documentation_button": "दस्तऐवजीकरण", - "catalog": { - "script_already_installed": "स्क्रिप्ट आधीच स्थापित!", - "download_failed": "अयशस्वी डाउनलोड: {code}", - "script_downloaded": "स्क्रिप्ट डाउनलोड!", - "could_not_create_file": "फाईल तयार करू शकत नाही.", - "no_scripts_folder_selected": "कोणतेही स्क्रिप्ट फोल्डर निवडलेले नाही.", - "error": "त्रुटी: {message}", - "no_repos_added": "कोणतेही रेपॉजिटरी जोडले नाहीत.", - "repo_list_info": "येथे आपण रेपोसची यादी शोधू शकता:", - "link_text": "दुवा", - "no_scripts_available": "कोणत्याही रेपोमधून कोणतीही स्क्रिप्ट उपलब्ध नाहीत.", - "by_author": "{author} द्वारा", - "version": "आवृत्ती: {version}", - "installed_button": "स्थापित", - "download_button": "डाउनलोड करा" - }, - "repos": { - "invalid_repo_title": "अवैध रेपॉजिटरी", - "add_repo_button": "रेपॉजिटरी जोडा", - "add_repo_dialog_title": "रेपॉजिटरी URL जोडा", - "repo_url_label": "रेपॉजिटरी URL", - "repo_added_toast": "रेपॉजिटरी यशस्वीरित्या जोडली!", - "invalid_repo_error": "हे एक वैध स्क्रिप्ट रेपॉजिटरी असल्याचे दिसत नाही.", - "add_repo_failed_toast": "रेपॉजिटरी जोडण्यात अयशस्वी: {message}", - "add_button": "जोडा", - "no_repos_added": "कोणतेही रेपॉजिटरी जोडले नाहीत", - "remove_button": "काढा", - "remove_repo_dialog_title": "रेपॉजिटरी काढा", - "remove_repo_dialog_text": "आपणास खात्री आहे की आपण हे रेपॉजिटरी काढू इच्छिता?" - } - }, - "features": { - "config_import": { - "title": "आयातीची पुष्टी करा", - "back_button_description": "मागे", - "config_imported_toast": "कॉन्फिगरेशन आयात केले!", - "confirm_button": "पुष्टी करा", - "expand_button_description": "विस्तृत करा", - "enable_feature": "वैशिष्ट्य सक्षम करा", - "enabled": "सक्षम", - "disabled": "अक्षम" - }, - "config_export": { - "title": "निर्यात सारांश", - "back_button_description": "मागे", - "save_button": "जतन करा", - "expand_button_description": "विस्तृत करा", - "enable_feature": "वैशिष्ट्य सक्षम करा", - "enabled": "सक्षम", - "disabled": "अक्षम" - } - }, - "manage_repos": { - "title": "{type} रेपॉजिटरी व्यवस्थापित करा", - "add_repo_button": "रेपॉजिटरी जोडा", - "add_repo_dialog_title": "रेपॉजिटरी URL जोडा", - "repo_url_label": "रेपॉजिटरी URL", - "repo_added_successfully": "रेपॉजिटरी यशस्वीरित्या जोडली!", - "add_repo_failed": "रेपॉजिटरी जोडण्यात अयशस्वी: {message}", - "add_button": "जोडा", - "no_repos_added": "कोणतेही रेपॉजिटरी जोडले नाहीत", - "remove_button": "काढा" - } - }, - "rules": { - "toasts": { - "enabled": "{ruleName} सक्षम केले", - "disabled": "{ruleName} अक्षम केले" - }, - "modes": { - "blacklist": "ब्लॅकलिस्ट मोड", - "whitelist": "श्वेतसूची मोड" - }, - "properties": { - "auto_download": { - "name": "ऑटो डाउनलोड", - "description": "स्नॅप्स पहात असताना स्वयंचलितपणे डाउनलोड करा", - "options": { - "blacklist": "ऑटो डाउनलोडमधून वगळा", - "whitelist": "ऑटो डाउनलोड" - } - }, - "stealth": { - "name": "स्टील्थ मोड", - "description": "आपण त्यांचे स्नॅप्स/गप्पा आणि संभाषणे उघडल्या आहेत हे जाणून घेण्यास कोणालाही प्रतिबंधित करते", - "options": { - "blacklist": "स्टील्थ मोडमधून वगळा", - "whitelist": "स्टील्थ मोड" - } - }, - "auto_save": { - "name": "ऑटो सेव्ह", - "description": "गप्पा संदेश पाहताना जतन करते", - "options": { - "blacklist": "ऑटो सेव्हमधून वगळा", - "whitelist": "ऑटो सेव्ह" - } - }, - "unsaveable_messages": { - "name": "अप्रशिक्षित संदेश", - "description": "संदेश इतर लोकांच्या गप्पांमध्ये जतन होण्यापासून प्रतिबंधित करते", - "options": { - "blacklist": "अयोग्य संदेशांमधून वगळा", - "whitelist": "अप्रशिक्षित संदेश" - } - }, - "auto_open_snaps": { - "name": "ऑटो ओपन स्नॅप्स", - "description": "त्यांना प्राप्त करताना स्वयंचलितपणे स्नॅप्स उघडते", - "options": { - "blacklist": "ऑटो ओपन स्नॅप्समधून वगळा", - "whitelist": "ऑटो ओपन स्नॅप्स" - } - }, - "hide_friend_feed": { - "name": "मित्र फीड पासून लपवा" - }, - "e2e_encryption": { - "name": "ई 2 ई कूटबद्धीकरण वापरा" - }, - "pin_conversation": { - "name": "पिन संभाषण" - }, - "exclude_message_logger": { - "name": "संदेश लॉगरमधून वगळा" - } - } - }, - "actions": { - "clean_snapchat_cache": { - "name": "स्नॅपचॅट कॅशे स्वच्छ करा", - "description": "स्नॅपचॅट कॅशे साफ करते" - }, - "manage_friend_list": { - "name": "मित्र यादी व्यवस्थापित करा", - "description": "बॅक अप घेताना आपल्या मित्रांची यादी आयात/निर्यात करा" - }, - "export_chat_messages": { - "name": "गप्पा संदेश निर्यात करा", - "description": "JSON/HTML/txt फाईलमध्ये संभाषण संदेश निर्यात करते" - }, - "export_memories": { - "name": "आठवणी निर्यात करा", - "description": "झिप फाईलमध्ये आठवणी निर्यात करते" - }, - "bulk_messaging_action": { - "name": "बल्क मेसेजिंग अ‍ॅक्शन", - "description": "मित्र हटविणे किंवा संभाषणे मोठ्या प्रमाणात हटविणे यासारख्या ऑपरेशन्स करते" - }, - "regen_mappings": { - "name": "पुनरुत्पादित मॅपिंग", - "description": "मॅन्युअली मॅपिंग पुन्हा तयार करा" - }, - "change_language": { - "name": "भाषा बदला", - "description": "PurrfectSnap ची भाषा बदला" - }, - "file_imports": { - "name": "फाईल आयात", - "description": "स्नॅपचॅटमध्ये वापरण्यासाठी फायली आयात करा" - }, - "friend_tracker": { - "name": "मित्र ट्रॅकर", - "description": "स्नॅपचॅटवर आपल्या मित्रांचा मागोवा घ्या" - }, - "logger_history": { - "name": "लॉगर इतिहास", - "description": "लॉग केलेल्या संदेशांचा इतिहास पहा" - } - }, - "features": { - "notices": { - "unstable": "⚠ अस्थिर", - "ban_risk": "⚠ या वैशिष्ट्यामुळे बंदी येऊ शकते", - "internal_behavior": "⚠ हे स्नॅपचॅट अंतर्गत वर्तन खंडित करू शकते" - }, - "properties": { - "downloader": { - "name": "डाउनलोडर", - "description": "स्नॅपचॅट मीडिया डाउनलोड करा", - "properties": { - "save_folder": { - "name": "फोल्डर जतन करा", - "description": "ज्या निर्देशिकेवर सर्व माध्यम डाउनलोड केले जावेत ते निवडा" - }, - "auto_download_sources": { - "name": "ऑटो डाउनलोड स्त्रोत", - "description": "येथून स्वयंचलितपणे डाउनलोड करण्यासाठी स्त्रोत निवडा" - }, - "prevent_self_auto_download": { - "name": "सेल्फ ऑटो डाउनलोड प्रतिबंधित करा", - "description": "आपल्या स्वत: च्या स्नॅप्सला स्वयंचलितपणे डाउनलोड होण्यापासून प्रतिबंधित करते" - }, - "path_format": { - "name": "पथ स्वरूप", - "description": "फाइल पथ स्वरूप निर्दिष्ट करा" - }, - "allow_duplicate": { - "name": "डुप्लिकेटला परवानगी द्या", - "description": "समान माध्यमांना एकाधिक वेळा डाउनलोड करण्यास अनुमती देते" - }, - "merge_overlays": { - "name": "आच्छादन विलीन करा", - "description": "मजकूर आणि स्नॅपचे मीडिया एकाच फाईलमध्ये एकत्र करते" - }, - "force_image_format": { - "name": "प्रतिमा स्वरूप सक्ती करा", - "description": "निर्दिष्ट स्वरूपात जतन करण्यासाठी प्रतिमा प्रतिमा" - }, - "force_voice_note_format": { - "name": "व्हॉईस नोट स्वरूप सक्ती करा", - "description": "एका निर्दिष्ट स्वरूपात जतन करण्यासाठी व्हॉईस नोट्स फोर्सेस" - }, - "auto_download_voice_notes": { - "name": "ऑटो डाउनलोड व्हॉईस नोट्स", - "description": "व्हॉईस नोट्स खेळताना स्वयंचलितपणे डाउनलोड करते" - }, - "download_profile_pictures": { - "name": "प्रोफाइल चित्रे डाउनलोड करा", - "description": "आपल्याला प्रोफाइल पृष्ठावरून प्रोफाइल चित्रे डाउनलोड करण्याची परवानगी देते" - }, - "opera_download_button": { - "name": "ऑपेरा डाउनलोड बटण", - "description": "स्नॅप पहात असताना वरच्या उजव्या कोपर्‍यात डाउनलोड बटण जोडते.\nलाँग प्रेस ऑन बटणे डाउनलोड सक्ती करतील" - }, - "download_context_menu": { - "name": "संदर्भ मेनू डाउनलोड करा", - "description": "संदर्भ मेनूचा वापर करून संभाषण किंवा कथेतून संदेश डाउनलोड/पूर्वावलोकन करण्याची परवानगी देते.\nलाँग प्रेस ऑन बटणे डाउनलोड सक्ती करतील" - }, - "ffmpeg_options": { - "name": "एफएफएमपीईजी पर्याय", - "description": "अतिरिक्त एफएफएमपीईजी पर्याय निर्दिष्ट करा", - "properties": { - "threads": { - "name": "धागे", - "description": "वापरण्यासाठी धाग्यांचे प्रमाण" - }, - "preset": { - "name": "प्रीसेट", - "description": "रूपांतरणाची गती सेट करा" - }, - "constant_rate_factor": { - "name": "स्थिर दर घटक", - "description": "व्हिडिओ एन्कोडरसाठी स्थिर दर घटक सेट करा\nLibx264 साठी 0 ते 51 पर्यंत" - }, - "video_bitrate": { - "name": "व्हिडिओ बिटरेट", - "description": "व्हिडिओ बिटरेट (केबीपीएस) सेट करा" - }, - "audio_bitrate": { - "name": "ऑडिओ बिटरेट", - "description": "ऑडिओ बिटरेट (केबीपीएस) सेट करा" - }, - "custom_video_codec": { - "name": "सानुकूल व्हिडिओ कोडेक", - "description": "एक सानुकूल व्हिडिओ कोडेक सेट करा (उदा. Libx264)" - }, - "custom_audio_codec": { - "name": "सानुकूल ऑडिओ कोडेक", - "description": "एक सानुकूल ऑडिओ कोडेक सेट करा (उदा. एएसी)" - } - } - }, - "logging": { - "name": "लॉगिंग", - "description": "मीडिया डाउनलोड करत असताना टोस्ट दर्शविते" - }, - "custom_path_format": { - "name": "सानुकूल पथ स्वरूप", - "description": "डाउनलोड केलेल्या माध्यमांसाठी सानुकूल पथ स्वरूप निर्दिष्ट करा\n\nउपलब्ध व्हेरिएबल्स:\n - %username%\n - %source%\n - %hash%\n - %date_time%" - } - } - }, - "user_interface": { - "name": "वापरकर्ता इंटरफेस", - "description": "स्नॅपचॅटचा देखावा आणि भावना बदला", - "properties": { - "enable_app_appearance": { - "name": "अ‍ॅप देखावा सेटिंग्ज सक्षम करा", - "description": "लपविलेले अ‍ॅप देखावा सेटिंग सक्षम करते\nनवीन स्नॅपचॅट आवृत्तीवर आवश्यक असू शकत नाही" - }, - "friend_feed_message_preview": { - "name": "मित्र फीड संदेश पूर्वावलोकन", - "description": "मित्र फीडमधील शेवटच्या संदेशांचे पूर्वावलोकन दर्शविते", - "properties": { - "amount": { - "name": "रक्कम", - "description": "पूर्वावलोकन करण्यासाठी संदेशांची रक्कम" - } - } - }, - "snap_preview": { - "name": "स्नॅप पूर्वावलोकन", - "description": "गप्पांमध्ये न पाहिलेले स्नॅप्सच्या पुढे एक लहान पूर्वावलोकन प्रदर्शित करते" - }, - "bootstrap_override": { - "name": "बूटस्ट्रॅप ओव्हरराइड", - "description": "वापरकर्ता इंटरफेस बूटस्ट्रॅप सेटिंग्ज अधिलिखित करा", - "properties": { - "app_appearance": { - "name": "अ‍ॅप देखावा", - "description": "सतत अ‍ॅप देखावा सेट करते" - }, - "home_tab": { - "name": "मुख्यपृष्ठ टॅब", - "description": "स्नॅपचॅट उघडताना स्टार्टअप टॅब ओव्हरराइड्स" - } - } - }, - "force_amoled_theme": { - "name": "एमोलेड डार्क मोड", - "description": "गडद थीमसाठी खरी काळी पार्श्वभूमी वापरते" - }, - "map_friend_nametags": { - "name": "वर्धित मित्र नकाशा नेमटॅग", - "description": "स्नॅपमॅपवर मित्रांच्या नेमटॅग सुधारते" - }, - "prevent_message_list_auto_scroll": { - "name": "संदेश सूची ऑटो स्क्रोल प्रतिबंधित करा", - "description": "संदेश पाठविताना/प्राप्त करताना संदेश सूचीला तळाशी स्क्रोल होण्यापासून प्रतिबंधित करते" - }, - "streak_expiration_info": { - "name": "स्ट्रीक कालबाह्यता माहिती दर्शवा", - "description": "स्ट्रीक्स काउंटरच्या पुढे एक स्ट्रीक कालबाह्यता टाइमर दर्शवितो" - }, - "hide_friend_feed_entry": { - "name": "मित्र फीड एंट्री लपवा", - "description": "मित्र फीडमधील एका विशिष्ट मित्राला लपवते\nहे वैशिष्ट्य व्यवस्थापित करण्यासाठी सामाजिक टॅब वापरा" - }, - "hide_streak_restore": { - "name": "रीस्टोर लावा लपवा", - "description": "मित्र फीड मधील रीस्टोर बटण लपवते" - }, - "hide_quick_add_suggestions": { - "name": "द्रुत जोडा सूचना लपवा", - "description": "द्रुत जोडा मित्र सूचना काढून टाकते" - }, - "hide_story_suggestions": { - "name": "कथा सूचना लपवा", - "description": "कथा पृष्ठावरील सूचना काढून टाकतात" - }, - "hide_ui_components": { - "name": "यूआय घटक लपवा", - "description": "कोणते यूआय घटक लपवायचे ते निवडा" - }, - "opera_media_quick_info": { - "name": "ऑपेरा मीडिया द्रुत माहिती", - "description": "ऑपेरा व्ह्यूअर संदर्भ मेनूमधील निर्मिती तारखेसारख्या माध्यमांची उपयुक्त माहिती दर्शविते" - }, - "old_bitmoji_selfie": { - "name": "ओल्ड बिटमोजी सेल्फी", - "description": "जुन्या स्नॅपचॅट आवृत्त्यांमधून बिटमोजी सेल्फी परत आणते" - }, - "disable_spotlight": { - "name": "स्पॉटलाइट अक्षम करा", - "description": "स्पॉटलाइट पृष्ठ अक्षम करते" - }, - "friend_feed_menu_buttons": { - "name": "मित्र फीड मेनू बटणे", - "description": "मित्र फीड मेनूमध्ये कोणती बटणे दर्शवायची ते निवडा" - }, - "auto_close_friend_feed_menu": { - "name": "ऑटो क्लोज फ्रेंड फीड मेनू", - "description": "सेटिंग बटण दाबल्यानंतर स्वयंचलितपणे फ्रेंड फीड मेनू बंद करते" - }, - "vertical_story_viewer": { - "name": "अनुलंब कथा दर्शक", - "description": "सर्व कथांसाठी अनुलंब कथा दर्शक सक्षम करते" - }, - "enable_friend_feed_menu_bar": { - "name": "मित्र फीड मेनू बार", - "description": "नवीन मित्र फीड मेनू बार सक्षम करते" - }, - "message_indicators": { - "name": "संदेश निर्देशक", - "description": "संदेशांमध्ये विशिष्ट निर्देशक चिन्ह जोडते\nटीपः निर्देशक 100% अचूक असू शकत नाहीत" - }, - "stealth_mode_indicator": { - "name": "स्टील्थ मोड सूचक", - "description": "स्टील्थ मोडमधील संभाषणांच्या पुढे एक 👻 इमोजी जोडते" - }, - "edit_text_override": { - "name": "मजकूर अधिलिखित संपादित करा", - "description": "मजकूर फील्ड वर्तन अधिलिखित करते" - }, - "prevent_forced_keyboard": { - "name": "सक्तीने कीबोर्ड प्रतिबंधित करा", - "description": "आपण संभाषण उघडता तेव्हा स्नॅपचॅटला स्वयंचलितपणे कीबोर्ड पॉप अप करण्यापासून प्रतिबंधित करते" - }, - "settings_menu": { - "name": "सेटिंग्ज मेनू", - "description": "आपण प्युरफेक्ट्सनॅप मेनू उघडण्याचा मार्ग बदलतो", - "options": { - "default": "डीफॉल्ट", - "legacy": "लेगसी" - } - } - } - }, - "messaging": { - "name": "मेसेजिंग", - "description": "आपण मित्रांशी कसे संवाद साधता ते बदला", - "properties": { - "bypass_screenshot_detection": { - "name": "बायपास स्क्रीनशॉट शोध", - "description": "आपण स्क्रीनशॉट घेता तेव्हा स्नॅपचॅटला शोधण्यापासून प्रतिबंधित करते" - }, - "anonymous_story_viewing": { - "name": "अज्ञात कथा पाहणे", - "description": "आपण त्यांची कथा पाहिल्यापासून कोणालाही प्रतिबंधित करते" - }, - "prevent_story_rewatch_indicator": { - "name": "स्टोरी रीवॉच निर्देशक प्रतिबंधित करा", - "description": "आपण त्यांची कथा पुन्हा पाहिली हे जाणून घेण्यास कोणालाही प्रतिबंधित करते" - }, - "hide_peek_a_peek": { - "name": "डोकावून पहा", - "description": "जेव्हा आपण चॅटमध्ये अर्धा स्वाइप करता तेव्हा सूचना पाठविण्यापासून प्रतिबंधित करते" - }, - "hide_bitmoji_presence": { - "name": "बिटमोजी उपस्थिती लपवा", - "description": "गप्पांमध्ये असताना आपल्या बिटमोजीला पॉप अप करण्यापासून प्रतिबंधित करते" - }, - "hide_typing_notifications": { - "name": "टाइपिंग सूचना लपवा", - "description": "आपण संदेश टाइप करत आहात हे कोणालाही कळण्यापासून प्रतिबंधित करते" - }, - "unlimited_snap_view_time": { - "name": "अमर्यादित स्नॅप दृश्य वेळ", - "description": "स्नॅप्स पाहण्याची वेळ मर्यादा काढून टाकते" - }, - "auto_mark_as_read": { - "name": "वाचन म्हणून ऑटो मार्क", - "description": "स्टील्थ मोड सक्षम केल्यावरही वाचल्याप्रमाणे स्वयंचलितपणे संदेश/स्नॅप्स चिन्हांकित करते" - }, - "mark_snap_as_seen_button": { - "name": "पाहिले बटण म्हणून स्नॅप चिन्हांकित करा", - "description": "स्नॅपला पहात असताना चिन्हांकित करण्यासाठी एक बटण जोडते.\nहे स्टील्थ मोड सक्षम केले तरीही कार्य करेल" - }, - "skip_when_marking_as_seen": { - "name": "पाहिल्याप्रमाणे चिन्हांकित करताना वगळा", - "description": "पाहिल्याप्रमाणे स्नॅप चिन्हांकित करताना स्वयंचलितपणे पुढील स्नॅपवर जा.\nपाहिले बटण म्हणून मार्क स्नॅपसह संयोजनात वापरा" - }, - "loop_media_playback": { - "name": "लूप मीडिया प्लेबॅक", - "description": "स्नॅप्स / कथा पाहताना मीडिया प्लेबॅक लूप्स" - }, - "disable_replay_in_ff": { - "name": "एफएफ मध्ये रीप्ले अक्षम करा", - "description": "मित्र फीडकडून लांब प्रेससह पुन्हा प्ले करण्याची क्षमता अक्षम करते" - }, - "half_swipe_notifier": { - "name": "अर्धा स्वाइप नोटिफायर", - "description": "जेव्हा एखादी व्यक्ती संभाषणात स्वाइप करते तेव्हा आपल्याला सूचित करते", - "properties": { - "min_duration": { - "name": "किमान कालावधी", - "description": "अर्ध्या स्वाइपचा किमान कालावधी (सेकंदात)" - }, - "max_duration": { - "name": "जास्तीत जास्त कालावधी", - "description": "अर्ध्या स्वाइपचा जास्तीत जास्त कालावधी (सेकंदात)" - } - } - }, - "call_start_confirmation": { - "name": "कॉल प्रारंभ पुष्टीकरण", - "description": "कॉल सुरू करताना पुष्टीकरण संवाद दर्शवितो" - }, - "unlimited_conversation_pinning": { - "name": "अमर्यादित संभाषण पिनिंग", - "description": "आपल्याला स्थानिक पातळीवर अमर्यादित संभाषणे पिन करण्याची परवानगी देते" - }, - "disable_snap_mode_restrictions": { - "name": "स्नॅप मोड निर्बंध अक्षम करा", - "description": "निर्बंधाशिवाय आपल्याला स्वत: ची नकार देणारी स्नॅप्स पाहण्याची परवानगी देते" - }, - "prevent_message_sending": { - "name": "संदेश पाठविणे प्रतिबंधित करा", - "description": "विशिष्ट प्रकारचे संदेश पाठविण्यास प्रतिबंधित करते" - }, - "friend_mutation_notifier": { - "name": "मित्र उत्परिवर्तन नोटिफायर", - "description": "जेव्हा एखाद्या मित्राच्या प्रोफाइलमध्ये काहीतरी बदलते तेव्हा आपल्याला सूचित करते" - }, - "better_notifications": { - "name": "चांगल्या सूचना", - "description": "प्राप्त सूचनांमध्ये अधिक माहिती जोडते", - "properties": { - "group_notifications": { - "name": "गट सूचना", - "description": "गट सूचना एकाच मध्ये" - }, - "chat_preview": { - "name": "गप्पांचे पूर्वावलोकन", - "description": "अधिसूचना मध्ये प्राप्त झालेल्या संदेशांचे पूर्वावलोकन दर्शविते" - }, - "media_preview": { - "name": "मीडिया पूर्वावलोकन", - "description": "सूचनेमध्ये निवडलेल्या मीडिया प्रकारांचे पूर्वावलोकन दर्शविते" - }, - "media_caption": { - "name": "मीडिया मथळा", - "description": "अधिसूचना मध्ये माध्यमांचे संलग्न मथळा दर्शवितो" - }, - "stacked_media_messages": { - "name": "स्टॅक केलेले मीडिया संदेश", - "description": "जेव्हा त्यांचे पूर्वावलोकन केले जाऊ शकत नाही तेव्हा एकाधिक मीडिया संदेशांना एका मजकूर अधिसूचनेत जोडते. गप्पा पूर्वावलोकनासह संयोजनात वापरा" - }, - "friend_add_source": { - "name": "मित्र जोडा स्त्रोत", - "description": "अधिसूचना मध्ये मित्र विनंतीचा स्रोत दर्शवितो" - }, - "reply_button": { - "name": "प्रत्युत्तर बटण", - "description": "सूचनेमध्ये उत्तर बटण जोडते" - }, - "smart_replies": { - "name": "स्मार्ट प्रत्युत्तरे", - "description": "सूचनांना सूचित केलेल्या प्रत्युत्तरे जोडतात (Android 10+). उत्तर बटणासह संयोजनात वापरा" - }, - "download_button": { - "name": "डाउनलोड बटण", - "description": "आपल्याला सूचनेवरून मीडिया डाउनलोड करण्याची परवानगी देते" - }, - "mark_as_read_button": { - "name": "वाचन बटण म्हणून चिन्हांकित करा", - "description": "सूचनेवरून वाचल्याप्रमाणे आपल्याला संदेश चिन्हांकित करण्याची परवानगी देते" - }, - "mark_as_read_and_save_in_chat": { - "name": "चॅटमध्ये वाचा आणि सेव्ह म्हणून चिन्हांकित करा", - "description": "अधिसूचनामध्ये चॅट बटणावर वाचन आणि सेव्ह म्हणून एक चिन्ह जोडते" - } - } - }, - "notification_blacklist": { - "name": "अधिसूचना ब्लॅकलिस्ट", - "description": "अवरोधित केलेल्या सूचना निवडा" - }, - "message_logger": { - "name": "संदेश लॉगर", - "description": "संदेश हटविण्यापासून प्रतिबंधित करते", - "properties": { - "keep_my_own_messages": { - "name": "माझे स्वतःचे संदेश ठेवा", - "description": "आपले स्वतःचे संदेश हटविण्यापासून प्रतिबंधित करते" - }, - "auto_purge": { - "name": "ऑटो पर्ज", - "description": "निर्दिष्ट वेळेपेक्षा जुने कॅश केलेले संदेश स्वयंचलितपणे हटवते" - }, - "message_filter": { - "name": "संदेश फिल्टर", - "description": "कोणते संदेश लॉग इन करावे ते निवडा (सर्व संदेशांसाठी रिक्त)" - }, - "deleted_message_color": { - "name": "संदेश रंग हटविला", - "description": "हटविलेल्या संदेशांचा रंग सेट करते" - } - } - }, - "auto_save_messages_in_conversations": { - "name": "संदेश स्वयं सेव्ह करा", - "description": "संभाषणांमध्ये प्रत्येक संदेश स्वयंचलितपणे जतन करतो" - }, - "gallery_media_send_override": { - "name": "गॅलरी मीडिया ओव्हरराइड पाठवते", - "description": "गॅलरीमधून पाठविताना मीडिया स्त्रोताची फसवणूक करते" - }, - "strip_media_metadata": { - "name": "पट्टी मीडिया मेटाडेटा", - "description": "संदेश म्हणून पाठवण्यापूर्वी माध्यमांचा मेटाडेटा काढून टाकतो" - }, - "bypass_message_retention_policy": { - "name": "बायपास संदेश धारणा धोरण", - "description": "संदेश पाहल्यानंतर हटविण्यापासून प्रतिबंधित करते" - }, - "bypass_message_action_restrictions": { - "name": "बायपास संदेश कृती निर्बंध", - "description": "आपल्याला तो न उघडता स्नॅपवर प्रतिक्रिया देण्याची किंवा एक अप्रिय संदेश जतन करण्यास अनुमती देते" - }, - "remove_groups_locked_status": { - "name": "गट लॉक केलेली स्थिती काढा", - "description": "लाथ मारल्यानंतर आपल्याला गट माहिती पाहण्याची परवानगी देते" - }, - "double_tap_chat_action": { - "name": "डबल टॅप चॅट अ‍ॅक्शन", - "description": "चॅटमध्ये संदेश डबल टॅप करताना सानुकूल कृती करते" - }, - "double_tap_chat_action_custom_emoji": { - "name": "डबल टॅप चॅट अ‍ॅक्शन सानुकूल इमोजी प्रतिक्रिया", - "description": "डबल टॅप चॅट क्रियेसाठी सानुकूल इमोजी प्रतिक्रिया सेट करते" - } - } - }, - "global": { - "name": "जागतिक", - "description": "ग्लोबल स्नॅपचॅट सेटिंग्ज चिमटा", - "properties": { - "better_location": { - "name": "चांगले स्थान", - "description": "स्नॅपचॅट स्थान वर्धित करते", - "properties": { - "spoof_location": { - "name": "स्पूफ स्थान", - "description": "निर्दिष्ट एकाकडे आपले स्थान स्पूफ करते" - }, - "coordinates": { - "name": "समन्वय", - "description": "स्पूफ्ड स्थानाचे निर्देशांक सेट करा" - }, - "walk_radius": { - "name": "चाला त्रिज्या", - "description": "सहजपणे या त्रिज्या (एफटी) च्या आत फिरा" - }, - "always_update_location": { - "name": "नेहमीच स्थान अद्यतनित करा", - "description": "कोणताही जीपीएस डेटा प्राप्त झाला नाही तरीही स्नॅपचॅटला स्थान अद्यतनित करण्यासाठी सक्ती करा" - }, - "suspend_location_updates": { - "name": "स्थान अद्यतने निलंबित करा", - "description": "आपले स्थान अद्यतनित होण्यापासून प्रतिबंधित करते" - }, - "spoof_battery_level": { - "name": "स्पूफ बॅटरी पातळी", - "description": "नकाशावर आपल्या डिव्हाइसची बॅटरी पातळी तयार करते\nमूल्य 0 ते 100 दरम्यान असणे आवश्यक आहे" - }, - "spoof_headphones": { - "name": "स्पूफ हेडफोन", - "description": "नकाशावर संगीत ऐकण्याची स्थिती स्पूफ करते" - }, - "show_battery_level": { - "name": "बॅटरी पातळी दर्शवा", - "description": "नकाशावर आपल्या मित्रांची बॅटरी पातळी दर्शवते" - } - } - }, - "snapchat_plus": { - "name": "स्नॅपचॅट प्लस", - "description": "स्नॅपचॅट प्लस वैशिष्ट्ये सक्षम करते\nकाही सर्व्हर-बाजूची वैशिष्ट्ये कार्य करू शकत नाहीत" - }, - "media_upload_quality": { - "name": "मीडिया अपलोड गुणवत्ता", - "description": "मीडिया अपलोड गुणवत्ता अधिलिखित करते", - "properties": { - "force_video_upload_source_quality": { - "name": "सक्ती व्हिडिओ अपलोड स्त्रोत गुणवत्ता", - "description": "व्हिडिओ अपलोड करताना स्नॅपचॅटला स्त्रोत गुणवत्ता वापरण्यासाठी सक्ती केली जाते\nकृपया लक्षात घ्या की हे माध्यमांमधून मेटाडेटा काढू शकत नाही" - }, - "disable_image_compression": { - "name": "प्रतिमा कॉम्प्रेशन अक्षम करा", - "description": "मीडिया अपलोड करताना प्रतिमा कॉम्प्रेशन अक्षम करते" - }, - "custom_image_upload_format": { - "name": "सानुकूल प्रतिमा अपलोड स्वरूप", - "description": "एक सानुकूल प्रतिमा अपलोड स्वरूप सेट करते\nउत्कृष्ट गुणवत्तेसाठी लॉसलेस फॉरमॅट (पीएनजी सारखे) निवडा" - } - } - }, - "disable_confirmation_dialogs": { - "name": "पुष्टीकरण संवाद अक्षम करा", - "description": "स्वयंचलितपणे निवडलेल्या क्रियांची पुष्टी करते" - }, - "auto_updater": { - "name": "ऑटो अपडेटर", - "description": "नवीन अद्यतनांसाठी स्वयंचलितपणे तपासणी करते" - }, - "disable_metrics": { - "name": "मेट्रिक्स अक्षम करा", - "description": "स्नॅपचॅटवर विशिष्ट विश्लेषक डेटा पाठविणारे ब्लॉक्स" - }, - "disable_story_sections": { - "name": "कथा विभाग अक्षम करा", - "description": "कथा पृष्ठावरील विभाग काढून टाकते\nयोग्यरित्या कार्य करण्यासाठी रीफ्रेश आवश्यक असू शकते" - }, - "block_ads": { - "name": "जाहिराती ब्लॉक", - "description": "जाहिराती प्रदर्शित होण्यापासून प्रतिबंधित करते" - }, - "disable_custom_tabs": { - "name": "सानुकूल टॅब अक्षम करा", - "description": "वेब ब्राउझरऐवजी समर्थित अनुप्रयोगांमध्ये दुवे उघडते" - }, - "disable_permission_requests": { - "name": "परवानगी विनंत्या अक्षम करा", - "description": "स्नॅपचॅटला विशिष्ट परवानग्या विचारण्यापासून प्रतिबंधित करते" - }, - "disable_memories_snap_feed": { - "name": "आठवणी अक्षम करा स्नॅप फीड", - "description": "आपण कॅमेर्‍यामध्ये स्वाइप करता तेव्हा अलीकडील आठवणी दर्शविण्यापासून स्नॅपचॅटला प्रतिबंधित करते" - }, - "spotlight_comments_username": { - "name": "स्पॉटलाइट टिप्पण्या वापरकर्तानाव", - "description": "स्पॉटलाइट टिप्पण्यांमध्ये लेखक वापरकर्तानाव दर्शविते" - }, - "bypass_video_length_restriction": { - "name": "बायपास व्हिडिओ लांबी निर्बंध", - "description": "एकल: एक व्हिडिओ पाठवते\nविभाजित: संपादनानंतर स्प्लिट व्हिडिओ" - }, - "default_video_playback_rate": { - "name": "डीफॉल्ट व्हिडिओ प्लेबॅक दर", - "description": "व्हिडिओंच्या प्लेबॅकसाठी डीफॉल्ट गती सेट करते\nमूल्य 0.1 आणि 4.0 दरम्यान असणे आवश्यक आहे" - }, - "video_playback_rate_slider": { - "name": "व्हिडिओ प्लेबॅक रेट स्लाइडर", - "description": "व्हिडिओ प्लेबॅक दर बदलण्यासाठी ऑपेरा संदर्भ मेनूमध्ये स्लाइडर जोडते\nटीपः बदल केवळ त्यानंतरच्या व्हिडिओंवर लागू होतात" - }, - "disable_google_play_dialogs": { - "name": "Google Play सेवा संवाद अक्षम करा", - "description": "Google Play सेवा उपलब्धता संवाद दर्शविण्यापासून प्रतिबंधित करा" - }, - "default_volume_controls": { - "name": "डीफॉल्ट व्हॉल्यूम नियंत्रणे", - "description": "सिस्टम व्हॉल्यूम कंट्रोल्स वापरण्यासाठी स्नॅपचॅटला सक्ती करते" - }, - "disable_telecom_framework": { - "name": "टेलिकॉम फ्रेमवर्क अक्षम करा", - "description": "स्नॅपचॅटला Android टेलिकॉम फ्रेमवर्क वापरण्यापासून प्रतिबंधित करते\nहे आपल्याला कॉलवर असताना संगीत ऐकण्याची परवानगी देते" - }, - "hide_active_music": { - "name": "सक्रिय संगीत लपवा", - "description": "आपण संगीत ऐकत आहात हे जाणून घेण्यापासून स्नॅपचॅटला प्रतिबंधित करते\nहे आपल्याला संगीत ऐकत असताना कंट्रोल व्हॉल्यूम बटणे वापरुन स्नॅप्स घेण्यास अनुमती देईल" - }, - "disable_snap_splitting": { - "name": "स्नॅप स्प्लिटिंग अक्षम करा", - "description": "स्नॅप्सला एकाधिक भागांमध्ये विभाजित होण्यापासून प्रतिबंधित करते\nआपण पाठविलेली चित्रे व्हिडिओंमध्ये बदलतील" - } - } - }, - "rules": { - "name": "नियम", - "description": "वैयक्तिक लोकांसाठी स्वयंचलित वैशिष्ट्ये व्यवस्थापित करा" - }, - "camera": { - "name": "कॅमेरा", - "description": "परिपूर्ण स्नॅपसाठी योग्य सेटिंग्ज समायोजित करा", - "properties": { - "disable_cameras": { - "name": "कॅमेरे अक्षम करा", - "description": "स्नॅपचॅटला निवडलेले कॅमेरे वापरण्यापासून प्रतिबंधित करते" - }, - "black_photos": { - "name": "काळा फोटो", - "description": "काळ्या पार्श्वभूमीसह कॅप्चर केलेले फोटो पुनर्स्थित करते\nव्हिडिओंवर परिणाम होत नाही" - }, - "immersive_camera_preview": { - "name": "विसर्जित पूर्वावलोकन", - "description": "स्नॅपचॅटला कॅमेरा पूर्वावलोकन क्रॉप करण्यापासून प्रतिबंधित करते\nयामुळे काही डिव्हाइसवर कॅमेरा चमकू शकेल" - }, - "override_front_resolution": { - "name": "ओव्हरराइड फ्रंट रिझोल्यूशन", - "description": "फ्रंट कॅमेर्‍यासाठी कॅमेरा रिझोल्यूशन अधिलिखित करते" - }, - "override_back_resolution": { - "name": "मागे रिझोल्यूशन ओव्हरराइड", - "description": "मागील कॅमेर्‍यासाठी कॅमेरा रिझोल्यूशन ओव्हरराइड्स" - }, - "custom_resolution": { - "name": "सानुकूल ठराव", - "description": "एक सानुकूल कॅमेरा रिझोल्यूशन सेट करते, रुंदी एक्स उंची (उदा. 1920x1080).\nसानुकूल रिझोल्यूशन आपल्या डिव्हाइसद्वारे समर्थित असणे आवश्यक आहे" - }, - "front_custom_frame_rate": { - "name": "समोर सानुकूल फ्रेम दर", - "description": "फ्रंट कॅमेरा फ्रेम रेट ओव्हरराइड्स" - }, - "back_custom_frame_rate": { - "name": "परत सानुकूल फ्रेम दर", - "description": "बॅक कॅमेरा फ्रेम रेट ओव्हरराइड्स" - }, - "force_camera_source_encoding": { - "name": "कॅमेरा स्त्रोत एन्कोडिंग सक्तीने", - "description": "कॅमेरा स्त्रोत एन्कोडिंगला सक्तीने" - }, - "startup_default_camera": { - "name": "स्टार्टअप डीफॉल्ट कॅमेरा", - "description": "स्नॅपचॅट उघडताना डीफॉल्ट कॅमेरा सेट करते" - }, - "hevc_recording": { - "name": "एचईव्हीसी रेकॉर्डिंग", - "description": "व्हिडिओ रेकॉर्डिंगसाठी एचईव्हीसी (एच .265) कोडेक वापरते" - } - } - }, - "streaks_reminder": { - "name": "स्ट्रेक्स स्मरणपत्र", - "description": "वेळोवेळी आपल्याला आपल्या रेषांबद्दल सूचित करते", - "properties": { - "interval": { - "name": "मध्यांतर", - "description": "प्रत्येक स्मरणपत्रांमधील मध्यांतर (तास)" - }, - "remaining_hours": { - "name": "उर्वरित वेळ", - "description": "अधिसूचना दर्शविण्यापूर्वी उर्वरित वेळ (तास)" - }, - "group_notifications": { - "name": "गट सूचना", - "description": "गट सूचना एकाच मध्ये" - } - } - }, - "experimental": { - "name": "प्रायोगिक", - "description": "प्रायोगिक वैशिष्ट्ये", - "properties": { - "native_hooks": { - "name": "नेटिव्ह हुक", - "description": "स्नॅपचॅटच्या मूळ कोडमध्ये हुक करणारी असुरक्षित वैशिष्ट्ये", - "properties": { - "composer_hooks": { - "name": "संगीतकार हुक", - "description": "संगीतकार क्रॉस-प्लॅटफॉर्म यूआय फ्रेमवर्कमध्ये कोड इंजेक्ट करते", - "properties": { - "show_first_created_username": { - "name": "प्रथम तयार केलेले वापरकर्तानाव दर्शवा", - "description": "प्रोफाइल पृष्ठावरील वर्तमान वापरकर्तानावाच्या पुढे प्रथम तयार केलेले वापरकर्तानाव दर्शविते" - }, - "bypass_camera_roll_limit": { - "name": "बायपास कॅमेरा रोल मर्यादा", - "description": "आपण कॅमेरा रोलमधून पाठवू शकता अशा जास्तीत जास्त माध्यमांची वाढ करते" - }, - "custom_self_destruct_snap_delay": { - "name": "सानुकूल सेल्फ डिस्ट्रक्ट स्नॅप विलंब", - "description": "स्नॅप पाठविताना सेल्फ-डिस्ट्रक्ट टाइमरसाठी अधिक पर्याय देते" - }, - "composer_console": { - "name": "संगीतकार कन्सोल", - "description": "आपल्याला संगीतकारात जावास्क्रिप्ट कोड कार्यान्वित करण्याची परवानगी देते (केवळ एआरएम 64)" - }, - "composer_logs": { - "name": "संगीतकार लॉग", - "description": "संगीतकाराचे कन्सोल लॉग पुनर्निर्देशित करते" - } - } - }, - "disable_bitmoji": { - "name": "बिटमोजी अक्षम करा", - "description": "मित्रांना प्रोफाइल बिटमोजी अक्षम करते" - }, - "custom_emoji_font": { - "name": "सानुकूल इमोजी फॉन्ट", - "description": "आपल्याला सानुकूल इमोजी फॉन्ट वापरण्याची परवानगी देते. केवळ .ttf फॉन्टसह कार्य करते" - }, - "custom_shared_library": { - "name": "सानुकूल सामायिक लायब्ररी", - "description": "स्नॅपचॅटमध्ये सानुकूल सामायिक लायब्ररी लोड करते. हे वैशिष्ट्य केवळ चाचणीच्या उद्देशाने आहे" - } - } - }, - "spoof": { - "name": "फसवणूक", - "description": "आपल्याबद्दल विविध माहितीची फसवणूक", - "properties": { - "play_store_installer_package_name": { - "name": "प्ले स्टोअर इंस्टॉलर पॅकेज नाव", - "description": "Com.android.vending वर इंस्टॉलर पॅकेज नाव अधिलिखित करते" - }, - "remove_vpn_transport_flag": { - "name": "व्हीपीएन ट्रान्सपोर्ट ध्वज काढा", - "description": "स्नॅपचॅटला व्हीपीएन शोधण्यापासून प्रतिबंधित करते" - }, - "remove_mock_location_flag": { - "name": "मॉक स्थान ध्वज काढा", - "description": "स्नॅपचॅटला मॉक स्थान शोधण्यापासून प्रतिबंधित करते" - } - } - }, - "convert_message_locally": { - "name": "स्थानिकपणे संदेश रूपांतरित करा", - "description": "बाह्य माध्यमांना स्थानिक पातळीवर चॅट करण्यासाठी स्नॅप्सचे रूपांतर करते. हे चॅट डाउनलोड संदर्भ मेनूमध्ये दिसते" - }, - "media_file_picker": { - "name": "मीडिया फाइल पिकर", - "description": "आपल्याला गॅलरीमधून कोणतीही व्हिडिओ/ऑडिओ फाइल निवडण्याची परवानगी देते" - }, - "story_logger": { - "name": "कथा लॉगर", - "description": "मित्रांच्या कथांचा इतिहास प्रदान करतो" - }, - "call_recorder": { - "name": "कॉल रेकॉर्डर", - "description": "स्वयंचलितपणे ऑडिओ कॉल रेकॉर्ड करा" - }, - "account_switcher": { - "name": "खाते स्विचर", - "description": "आपल्याला लॉग आउट न करता खात्यांमधील स्विच करण्याची परवानगी देते\nमेनू उघडण्यासाठी आपल्या बिटमोजी प्रोफाइलच्या पुढील शोध चिन्हावर लांब दाबा\nटीपः हे वैशिष्ट्य प्रायोगिक आहे आणि भविष्यात बदलू शकेल", - "properties": { - "auto_backup_current_account": { - "name": "ऑटो बॅकअप चालू खाते", - "description": "खाती लॉग इन करताना किंवा स्विच करताना स्वयंचलितपणे चालू खात्याचा बॅक अप घेतो" - } - } - }, - "better_transcript": { - "name": "चांगले उतारे", - "description": "व्हॉईस नोट उतारे सुधारते", - "properties": { - "force_transcription": { - "name": "व्हॉईस नोट लिप्यंतरण सक्ती करा", - "description": "सर्व व्हॉईस नोट्स लिप्यंतरित करण्यास अनुमती देते" - }, - "preferred_transcription_lang": { - "name": "पसंतीची लिप्यंतरण भाषा", - "description": "व्हॉईस नोट ट्रान्सक्रिप्टसाठी पसंतीची भाषा (उदा. एन, ईएस, एफआर)" - }, - "notification_transcript": { - "name": "सूचना उतारे", - "description": "सूचनांमध्ये व्हॉईस नोट्स लिप्यंतरित करते\nया वैशिष्ट्यासाठी चॅट पूर्वावलोकन वैशिष्ट्य चांगल्या सूचनांमध्ये सक्षम करणे आवश्यक आहे" - } - } - }, - "voice_note_auto_play": { - "name": "व्हॉईस नोट ऑटो प्ले", - "description": "सध्याच्या पूर्ण झाल्यानंतर स्वयंचलितपणे पुढील व्हॉईस नोट प्ले करते" - }, - "friend_notes": { - "name": "मित्र नोट्स", - "description": "आपल्याला मित्र प्रोफाइलमध्ये नोट्स जोडण्याची परवानगी देते" - }, - "cof_experiments": { - "name": "सीओएफ प्रयोग", - "description": "रिलीझेड/बीटा स्नॅपचॅट वैशिष्ट्ये सक्षम करते" - }, - "context_menu_fix": { - "name": "संदर्भ मेनू निराकरण", - "description": "मित्र फीड मेनूची दुरुस्ती करण्याचा प्रयत्न करा जेव्हा डिव्हाइस ऑफलाइन असेल तेव्हा ते योग्यरित्या प्रदर्शित केले जाऊ शकत नाही" - }, - "app_lock": { - "name": "अ‍ॅप लॉक", - "description": "पासकोडशिवाय स्नॅपचॅटमध्ये प्रवेश प्रतिबंधित करते", - "properties": { - "lock_on_resume": { - "name": "रेझ्युमे वर लॉक करा", - "description": "अ‍ॅप पुन्हा उघडल्यावर लॉक करते" - } - } - }, - "infinite_story_boost": { - "name": "अनंत कथा वाढ", - "description": "कथेला बायपास बूस्ट मर्यादा विलंब" - }, - "meo_passcode_bypass": { - "name": "माझे डोळे फक्त पासकोड बायपास", - "description": "माझे डोळे फक्त पासकोड बायपास\nहे केवळ आधीच कार्य करेल जर पासकोड योग्यरित्या प्रविष्ट केला गेला असेल" - }, - "no_friend_score_delay": { - "name": "मित्र स्कोअर विलंब नाही", - "description": "मित्रांचे स्कोअर पाहताना विलंब दूर करते" - }, - "best_friend_pinning": { - "name": "सर्वोत्तम मित्र पिनिंग", - "description": "आपल्या मित्राला आपला प्रथम क्रमांकाचा सर्वात चांगला मित्र म्हणून पिन करण्याची परवानगी देतो. टीप: केवळ आपण आपला पिन केलेला सर्वोत्तम मित्र पाहू शकता" - }, - "e2ee": { - "name": "एंड-टू-एंड एन्क्रिप्शन", - "description": "सामायिक गुप्त की वापरुन एईएससह आपले संदेश कूटबद्ध करते\nआपली की कुठेतरी सुरक्षित जतन करण्याचे सुनिश्चित करा!", - "properties": { - "encrypted_message_indicator": { - "name": "कूटबद्ध संदेश निर्देशक", - "description": "कूटबद्ध संदेशांच्या पुढे एक 🔒 इमोजी जोडते" - }, - "force_message_encryption": { - "name": "सक्ती संदेश एन्क्रिप्शन", - "description": "ज्या लोकांना ई 2 ई कूटबद्धीकरण नाही अशा लोकांना एन्क्रिप्ट केलेले संदेश पाठविण्यास प्रतिबंधित करते जेव्हा एकाधिक संभाषणे निवडली जातात" - } - } - }, - "add_friend_source_spoof": { - "name": "मित्र स्त्रोत स्पूफ जोडा", - "description": "मित्र विनंतीचा स्रोत स्पूफ करतो" - }, - "hidden_snapchat_plus_features": { - "name": "लपविलेले स्नॅपचॅट प्लस वैशिष्ट्ये", - "description": "रिलीझेड/बीटा स्नॅपचॅट प्लस वैशिष्ट्ये सक्षम करते\nजुन्या स्नॅपचॅट आवृत्त्यांवर कार्य करू शकत नाही" - }, - "custom_streaks_expiration_format": { - "name": "सानुकूल रेषा कालबाह्यता स्वरूप", - "description": "स्ट्रीक्स कालबाह्यता स्वरूप सानुकूलित करते\n\nउपलब्ध व्हेरिएबल्स:\n - %सी: स्ट्रेक्स मोजणी\n - %ई: तासग्लास इमोजी\n - %डी: दिवस\n - %एच: तास\n - %मी: मिनिटे\n - %s: सेकंद\n - %डब्ल्यू: उर्वरित वेळ" - }, - "prevent_forced_logout": { - "name": "सक्तीने लॉगआउट प्रतिबंधित करा", - "description": "आपण दुसर्‍या डिव्हाइसवर लॉगिन करता तेव्हा स्नॅपचॅटला लॉगिंग करण्यापासून प्रतिबंधित करते" - }, - "snapscore_changes": { - "name": "स्नॅपस्कोर बदल", - "description": "मित्रांच्या स्नॅपस्कोरमधील बदलांचा मागोवा घ्या\nहे वैशिष्ट्य केवळ स्नॅपचॅटच्या नवीन आवृत्त्यांमध्ये वापरा" - } - } - }, - "scripting": { - "name": "स्क्रिप्टिंग", - "description": "पुर्रफेक्ट्सनॅप वाढविण्यासाठी सानुकूल स्क्रिप्ट चालवा", - "properties": { - "developer_mode": { - "name": "विकसक मोड", - "description": "स्नॅपचॅटच्या यूआय वर डीबग माहिती दर्शविते" - }, - "module_folder": { - "name": "मॉड्यूल फोल्डर", - "description": "जेथे स्क्रिप्ट आहेत त्या फोल्डर" - }, - "auto_reload": { - "name": "स्वयं रीलोड", - "description": "जेव्हा ते बदलतात तेव्हा स्वयंचलितपणे स्क्रिप्ट रीलोड करतात" - }, - "integrated_ui": { - "name": "एकात्मिक UI", - "description": "स्नॅपचॅटमध्ये सानुकूल यूआय घटक जोडण्यासाठी स्क्रिप्टला परवानगी देते" - }, - "disable_log_anonymization": { - "name": "लॉग अज्ञातकरण अक्षम करा", - "description": "लॉगचे अनामिकीकरण अक्षम करते" - }, - "disable_optimization": { - "name": "ऑप्टिमायझेशन अक्षम करा", - "description": "स्क्रिप्टचे ऑप्टिमायझेशन अक्षम करते. यामुळे कामगिरीचे प्रश्न उद्भवू शकतात." - } - } - }, - "friend_tracker": { - "name": "मित्र ट्रॅकर", - "description": "स्नॅपचॅटवर मित्राची क्रिया नोंदवते", - "properties": { - "record_messaging_events": { - "name": "रेकॉर्ड मेसेजिंग इव्हेंट", - "description": "स्नॅप उघडणे, संदेश वाचणे इ. यासारख्या संदेशांचे संदेश रेकॉर्ड करतात." - }, - "allow_running_in_background": { - "name": "पार्श्वभूमीत धावण्याची परवानगी द्या", - "description": "पार्श्वभूमीवर ट्रॅकरला चालविण्यास अनुमती देते. टीपः हे आपली बॅटरी लक्षणीय प्रमाणात काढून टाकेल" - }, - "auto_purge": { - "name": "ऑटो पर्ज", - "description": "निर्दिष्ट वेळेपेक्षा जुने कॅश्ड इव्हेंट स्वयंचलितपणे हटवते" - } - } - } - }, - "options": { - "app_appearance": { - "always_light": "नेहमी हलके", - "always_dark": "नेहमी गडद" - }, - "friend_feed_menu_buttons": { - "auto_download": "⬇ ऑटो डाउनलोड", - "auto_save": "Messages संदेश स्वयं सेव्ह करतात", - "unsaveable_messages": "⬇ अप्रशिक्षित संदेश", - "auto_open_snaps": "📷 ऑटो ओपन स्नॅप्स", - "stealth": "👻 स्टील्थ मोड", - "mark_snaps_as_seen": "Sack पाहिल्याप्रमाणे चिन्हांकित करा", - "mark_stories_as_seen_locally": "Local स्थानिक पातळीवर पाहिल्याप्रमाणे कथा चिन्हांकित करा", - "conversation_info": "👤 संभाषण माहिती", - "e2e_encryption": "E ई 2 ई एन्क्रिप्शन वापरा" - }, - "path_format": { - "create_author_folder": "प्रत्येक लेखकासाठी फोल्डर तयार करा", - "create_source_folder": "प्रत्येक मीडिया स्त्रोताच्या प्रकारासाठी फोल्डर तयार करा", - "append_hash": "फाईलच्या नावावर एक अद्वितीय हॅश जोडा", - "append_source": "फाईलच्या नावावर मीडिया स्रोत जोडा", - "append_username": "फाइल नावावर वापरकर्तानाव जोडा", - "append_date_time": "फाईलच्या नावावर तारीख आणि वेळ जोडा" - }, - "auto_download_sources": { - "friend_snaps": "मित्र स्नॅप्स", - "friend_stories": "मित्र कथा", - "public_stories": "सार्वजनिक कथा", - "spotlight": "स्पॉटलाइट" - }, - "logging": { - "started": "प्रारंभ झाला", - "success": "यश", - "progress": "प्रगती", - "failure": "अयशस्वी" - }, - "notifications": { - "chat_screenshot": "स्क्रीनशॉट", - "chat_screen_record": "स्क्रीन रेकॉर्ड", - "snap_replay": "स्नॅप रीप्ले", - "camera_roll_save": "कॅमेरा रोल सेव्ह", - "chat": "गप्पा", - "chat_reply": "गप्पा उत्तर", - "snap": "स्नॅप", - "typing": "टायपिंग", - "stories": "कथा", - "speaking": "बोलणे", - "chat_reaction": "डीएम प्रतिक्रिया", - "group_chat_reaction": "गट प्रतिक्रिया", - "initiate_audio": "इनकमिंग ऑडिओ कॉल", - "abandon_audio": "ऑडिओ कॉल चुकला", - "initiate_video": "इनकमिंग व्हिडिओ कॉल", - "abandon_video": "व्हिडिओ कॉल चुकला", - "map_live_location": "लाइव्ह स्थान नकाशा" - }, - "gallery_media_send_override": { - "always_ask": "नेहमी विचारा", - "ORIGINAL": "मूळ मीडिया", - "NOTE": "ऑडिओ नोट", - "SNAP": "स्नॅप", - "SAVEABLE_SNAP": "बचत करण्यायोग्य स्नॅप" - }, - "strip_media_metadata": { - "hide_caption_text": "मथळा मजकूर लपवा", - "hide_snap_filters": "स्नॅप फिल्टर लपवा", - "hide_extras": "अतिरिक्त लपवा (उदा. उल्लेख)", - "remove_audio_note_duration": "ऑडिओ टीप कालावधी काढा", - "remove_audio_note_transcript_capability": "ऑडिओ टीप ट्रान्सक्रिप्ट क्षमता काढा" - }, - "hide_ui_components": { - "hide_profile_call_buttons": "प्रोफाइल कॉल बटणे काढा", - "hide_chat_call_buttons": "चॅट कॉल बटणे काढा", - "hide_live_location_share_button": "थेट स्थान सामायिक करा बटण काढा", - "hide_stickers_button": "स्टिकर्स बटण काढा", - "hide_voice_record_button": "व्हॉईस रेकॉर्ड बटण काढा", - "hide_unread_chat_hint": "न वाचलेले चॅट इशारा काढा", - "hide_post_to_story_buttons": "स्नॅप पाठवण्यापूर्वी स्टोरी बटणावर पोस्ट काढा", - "hide_billboard_prompt": "मित्र फीडमध्ये बिलबोर्ड प्रॉम्प्ट काढा", - "hide_snapchat_plus_gift_reminders": "संभाषणांमध्ये स्नॅपचॅट प्लस गिफ्ट स्मरणपत्रे काढा", - "hide_map_reactions": "नकाशा प्रतिक्रिया काढा" - }, - "hide_story_suggestions": { - "hide_suggested_friend_stories": "सुचविलेल्या मित्र कथा लपवा", - "hide_my_stories": "माझ्या कथा लपवा" - }, - "home_tab": { - "map": "नकाशा", - "chat": "गप्पा", - "camera": "कॅमेरा", - "discover": "शोधा", - "spotlight": "स्पॉटलाइट" - }, - "add_friend_source_spoof": { - "added_by_username": "वापरकर्तानाव द्वारे", - "added_by_mention": "उल्लेख करून", - "added_by_group_chat": "गट चॅटद्वारे", - "added_by_qr_code": "क्यूआर कोडद्वारे", - "added_by_community": "समुदायाद्वारे", - "added_by_quick_add": "द्रुत जोडाद्वारे (बंदी घालण्याचा उच्च जोखीम)" - }, - "bypass_video_length_restriction": { - "single": "एकल मीडिया", - "split": "विभाजित मीडिया" - }, - "old_bitmoji_selfie": { - "2d": "2 डी बिटमोजी", - "3d": "3 डी बिटमोजी" - }, - "disable_confirmation_dialogs": { - "erase_message": "संदेश मिटवा", - "remove_friend": "मित्र काढा", - "block_friend": "ब्लॉक मित्र", - "ignore_friend": "मित्राकडे दुर्लक्ष करा", - "hide_friend": "मित्र लपवा", - "hide_conversation": "संभाषण लपवा", - "clear_conversation": "मित्र फीड कडून स्पष्ट संभाषण" - }, - "auto_reload": { - "snapchat_only": "फक्त स्नॅपचॅट", - "all": "सर्व (स्नॅपचॅट + पुर्रफेक्ट्सनॅप)" - }, - "edit_text_override": { - "multi_line_chat_input": "मल्टी लाइन चॅट इनपुट", - "bypass_text_input_limit": "मजकूर इनपुट मर्यादा बायपास" - }, - "auto_purge": { - "never": "कधीही नाही", - "1_hour": "1 तास", - "3_hours": "3 तास", - "6_hours": "6 तास", - "12_hours": "12 तास", - "1_day": "1 दिवस", - "3_days": "3 दिवस", - "1_week": "1 आठवडा", - "2_weeks": "2 आठवडे", - "1_month": "1 महिना", - "3_months": "3 महिने", - "6_months": "6 महिने" - }, - "disable_story_sections": { - "friends": "मित्र", - "suggested_stories": "सुचविलेल्या कथा", - "following": "खालील", - "discover": "शोधा" - }, - "disable_cameras": { - "front": "फ्रंट कॅमेरा", - "back": "बॅक कॅमेरा" - }, - "disable_permission_requests": { - "notifications": "सूचना", - "read_media_images": "मीडिया प्रतिमा वाचा", - "read_media_video": "मीडिया व्हिडिओ वाचा", - "camera": "कॅमेरा", - "microphone": "मायक्रोफोन", - "location": "स्थान", - "read_contacts": "संपर्क वाचा", - "nearby_devices": "जवळपासची साधने", - "phone_calls": "फोन कॉल" - }, - "message_indicators": { - "encryption_indicator": "केवळ आपल्याला पाठविलेल्या संदेशांच्या पुढे एक 🔒 चिन्ह जोडते", - "platform_indicator": "प्लॅटफॉर्म चिन्ह जोडते ज्यामधून मीडिया पाठविला गेला (उदा. Android, iOS, वेब)", - "location_indicator": "जेव्हा त्यांना स्थान सक्षम केले जाते तेव्हा स्नॅप्समध्ये एक 📍 चिन्ह जोडते", - "ovf_editor_indicator": "ओव्हीएफ संपादक वापरुन स्नॅप पाठविला गेला आहे हे सूचित करते", - "director_mode_indicator": "दिग्दर्शक मोडचा वापर करून त्यांना पाठविले जाते तेव्हा स्नॅप्समध्ये एक ✏ चिन्ह जोडते, जे गॅलरी प्रतिमा स्नॅप्स म्हणून पाठविण्यासाठी वापरले जाऊ शकते" - }, - "auto_mark_as_read": { - "conversation_read": "संदेश पाठविताना वाचन म्हणून संभाषण चिन्हांकित करा", - "snap_reply": "त्यांना प्रत्युत्तर देताना वाचल्याप्रमाणे चिन्हांकित करा", - "save_snap_in_chat": "स्टिल्थ मोडमध्ये असताना चॅटमध्ये जतन करताना वाचलेले चिन्हांकित करा" - }, - "friend_mutation_notifier": { - "remove_friend": "जेव्हा कोणी आपल्याला मित्र म्हणून काढून टाकते तेव्हा सूचित करा", - "birthday_changes": "जेव्हा कोणी त्यांचा वाढदिवस बदलतो तेव्हा सूचित करा", - "bitmoji_selfie_changes": "जेव्हा कोणी त्यांचा बिटमोजी सेल्फी बदलतो तेव्हा सूचित करा", - "bitmoji_avatar_changes": "जेव्हा कोणी त्यांचे बिटमोजी अवतार बदलते तेव्हा सूचित करा", - "bitmoji_background_changes": "जेव्हा कोणी त्यांची बिटमोजी पार्श्वभूमी बदलते तेव्हा सूचित करा", - "bitmoji_scene_changes": "जेव्हा कोणी त्यांचे बिटमोजी देखावा बदलते तेव्हा सूचित करा" - }, - "snapchat_plus": { - "not_subscribed": "सदस्यता घेतली नाही", - "basic": "मूलभूत", - "ad_free": "एडी विनामूल्य" - }, - "double_tap_chat_action": { - "like_message": "संदेश प्रमाणे", - "copy_text": "क्लिपबोर्डवर मजकूर कॉपी करा", - "delete_message": "संदेश हटवा", - "mark_as_read": "वाचन म्हणून चिन्हांकित करा", - "custom_emoji_reaction": "सानुकूल इमोजी प्रतिक्रिया" - }, - "startup_default_camera": { - "front": "फ्रंट कॅमेरा", - "back": "बॅक कॅमेरा" - } - } - }, - "friend_menu_option": { - "mark_snaps_as_seen": "चिन्ह पाहिल्याप्रमाणे चिन्हांकित करा", - "mark_stories_as_seen_locally": "स्थानिक पातळीवर पाहिल्याप्रमाणे कथा चिन्हांकित करा", - "preview": "पूर्वावलोकन", - "stealth_mode": "स्टील्थ मोड", - "auto_download_blacklist": "ऑटो डाउनलोड ब्लॅकलिस्ट", - "anti_auto_save": "अँटी ऑटो सेव्ह" - }, - "content_type": { - "CHAT": "गप्पा", - "SNAP": "स्नॅप", - "EXTERNAL_MEDIA": "बाह्य माध्यम", - "NOTE": "ऑडिओ नोट", - "STICKER": "स्टिकर", - "SHARE": "वाटा", - "STATUS": "स्थिती", - "LOCATION": "स्थान", - "STATUS_SAVE_TO_CAMERA_ROLL": "कॅमेरा रोलमध्ये सेव्ह", - "STATUS_CONVERSATION_CAPTURE_SCREENSHOT": "स्क्रीनशॉट", - "STATUS_CONVERSATION_CAPTURE_RECORD": "स्क्रीन रेकॉर्ड", - "STATUS_CALL_MISSED_VIDEO": "व्हिडिओ कॉल चुकला", - "STATUS_CALL_MISSED_AUDIO": "ऑडिओ कॉल चुकला", - "LIVE_LOCATION_SHARE": "थेट स्थान सामायिक करा", - "CREATIVE_TOOL_ITEM": "क्रिएटिव्ह टूल आयटम", - "FAMILY_CENTER_INVITE": "कौटुंबिक केंद्र आमंत्रित करा", - "FAMILY_CENTER_ACCEPT": "कौटुंबिक केंद्र स्वीकारा", - "FAMILY_CENTER_LEAVE": "कौटुंबिक केंद्र रजा", - "STATUS_PLUS_GIFT": "स्थिती तसेच भेट", - "TINY_SNAP": "लहान स्नॅप", - "STATUS_COUNTDOWN": "काउंटडाउन", - "MAP_REACTION": "नकाशा प्रतिक्रिया" - }, - "media_download_source": { - "none": "काहीही नाही", - "pending": "प्रलंबित", - "chat_media": "गप्पा मीडिया", - "story": "कथा", - "public_story": "सार्वजनिक कथा", - "spotlight": "स्पॉटलाइट", - "profile_picture": "प्रोफाइल चित्र", - "story_logger": "कथा लॉगर", - "message_logger": "संदेश लॉगर", - "merged": "विलीन", - "voice_call": "व्हॉईस कॉल" - }, - "chat_action_menu": { - "preview_button": "पूर्वावलोकन", - "download_button": "डाउनलोड करा", - "delete_logged_message_button": "लॉग केलेला संदेश हटवा", - "show_chat_edit_history": "गप्पा संपादन इतिहास दर्शवा", - "convert_message": "संदेश रूपांतरित करा" - }, - "opera_context_menu": { - "download": "मीडिया डाउनलोड करा", - "sent_at": "{date} वर पाठविले", - "created_at": "{date} येथे तयार केले", - "expires_at": "{date} वर कालबाह्य होईल", - "media_size": "मीडिया आकार: {size}", - "media_duration": "मीडिया कालावधी: {duration} ms", - "show_debug_info": "डीबग माहिती दर्शवा" - }, - "modal_option": { - "profile_info": "प्रोफाइल माहिती", - "close": "बंद" - }, - "gallery_media_send_override": { - "multiple_media_toast": "आपण एकाच वेळी फक्त एक मीडिया पाठवू शकता" - }, - "mark_as_seen": { - "no_unseen_snaps_toast": "कोणतेही न पाहिलेले स्नॅप्स सापडले नाहीत!", - "seen_toast": "पाहिल्याप्रमाणे चिन्हांकित!", - "unseen_toast": "न पाहिलेले म्हणून चिन्हांकित!", - "already_seen_toast": "आधीच पाहिल्याप्रमाणे चिन्हांकित!", - "already_unseen_toast": "आधीच न पाहिलेले म्हणून चिन्हांकित!" - }, - "conversation_preview": { - "streak_expiration": "{day} दिवसांमध्ये कालबाह्य होईल {hour} तास {minute} मिनिटे", - "total_messages": "एकूण पाठविले/प्राप्त संदेश: {count}", - "title": "पूर्वावलोकन", - "unknown_user": "अज्ञात वापरकर्ता", - "no_messages": "कोणतेही संदेश सापडले नाहीत!" - }, - "profile_info": { - "title": "प्रोफाइल माहिती", - "first_created_username": "प्रथम वापरकर्तानाव तयार केले", - "mutable_username": "परिवर्तनीय वापरकर्तानाव", - "display_name": "प्रदर्शन नाव", - "added_date": "जोडलेली तारीख", - "birthday": "वाढदिवस: {month} {day}", - "hidden_birthday": "वाढदिवस: लपलेले", - "friendship": "मैत्री", - "add_source": "स्त्रोत जोडा", - "snapchat_plus": "स्नॅपचॅट प्लस", - "snapchat_plus_state": { - "subscribed": "सदस्यता घेतली", - "not_subscribed": "सदस्यता घेतली नाही" - } - }, - "friendship_link_type": { - "mutual": "परस्पर", - "outgoing": "आउटगोइंग", - "blocked": "अवरोधित", - "deleted": "हटविले", - "following": "खालील", - "suggested": "सुचविले", - "incoming": "इनकमिंग", - "incoming_follower": "इनकमिंग अनुयायी" - }, - "bulk_messaging_action": { - "choose_action_title": "कृती निवडा", - "progress_status": "प्रक्रिया {index} of {total}", - "selection_dialog_continue_button": "सुरू ठेवा", - "confirmation_dialog": { - "title": "तुम्हाला खात्री आहे का?", - "message": "याचा परिणाम सर्व निवडलेल्या मित्रांवर होईल. ही क्रिया पूर्ववत केली जाऊ शकत नाही." - }, - "actions": { - "remove_friends": "मित्र काढा", - "clear_conversations": "स्पष्ट संभाषणे" - } - }, - "chat_export": { - "exporter_dialog": { - "select_conversations_title": "संभाषणे निवडा", - "text_field_selection": "{amount} निवडले", - "text_field_selection_all": "सर्व", - "export_file_format_title": "फाइल स्वरूप निर्यात करा", - "message_type_filter_title": "प्रकारानुसार संदेश फिल्टर करा", - "amount_of_messages_title": "संदेशांची रक्कम (सर्वांसाठी रिक्त ठेवा)", - "download_medias_title": "मेडियास डाउनलोड करा" - }, - "dialog_negative_button": "रद्द करा", - "dialog_positive_button": "निर्यात", - "exported_to": "{path} वर निर्यात", - "exporting_chats": "गप्पा निर्यात करीत आहे ...", - "processing_chats": "प्रक्रिया {amount} संभाषणे ...", - "export_fail": "संभाषण निर्यात करण्यात अयशस्वी {conversation}", - "writing_output": "लेखन आउटपुट ...", - "finished": "पूर्ण झाले! आपण आता हा संवाद बंद करू शकता.", - "no_messages_found": "कोणतेही संदेश सापडले नाहीत!", - "exporting_message": "निर्यात {conversation}..." - }, - "button": { - "ok": "ठीक आहे", - "positive": "होय", - "negative": "नाही", - "cancel": "रद्द करा", - "open": "उघडा", - "download": "डाउनलोड करा", - "send": "पाठवा", - "restore_original": "मूळ पुनर्संचयित करा", - "convert_external_media": "बाह्य माध्यमांना रूपांतरित करा", - "save": "जतन करा" - }, - "tracker_events": { - "conversation_enter": "संभाषण प्रविष्ट करा", - "conversation_exit": "संभाषणातून बाहेर पडा", - "started_typing": "टाइप करणे सुरू केले", - "stopped_typing": "टाइप करणे थांबविले", - "started_speaking": "बोलू लागले", - "stopped_speaking": "बोलणे थांबविले", - "started_peeking": "डोकावण्यास सुरुवात केली", - "stopped_peeking": "डोकावलेले थांबले", - "message_read": "संदेश वाचला", - "message_deleted": "संदेश हटविला", - "message_saved": "संदेश वाचला", - "message_unsaved": "संदेश जतन केला नाही", - "message_edited": "संदेश संपादित", - "message_reaction_add": "संदेश प्रतिक्रिया जोडा", - "message_reaction_remove": "संदेश प्रतिक्रिया काढा", - "snap_opened": "स्नॅप उघडला", - "snap_replayed": "स्नॅप पुन्हा प्ले केले", - "snap_replayed_twice": "स्नॅपने दोनदा पुन्हा प्ले केले", - "snap_screenshot": "स्नॅप स्क्रीनशॉट", - "snap_screen_record": "स्नॅप स्क्रीन रेकॉर्ड" - }, - "tracker_actions": { - "log": "लॉग", - "in_app_notification": "अ‍ॅप-मधील सूचना", - "push_notification": "पुश सूचना", - "custom": "सानुकूल" - }, - "better_notifications": { - "button": { - "reply": "प्रत्युत्तर द्या", - "download": "डाउनलोड करा", - "mark_as_read": "वाचन म्हणून चिन्हांकित करा" - } - }, - "profile_picture_downloader": { - "button": "प्रोफाइल चित्र डाउनलोड करा", - "title": "प्रोफाइल चित्र डाउनलोडर", - "avatar_option": "अवतार", - "background_option": "पार्श्वभूमी" - }, - "call_start_confirmation": { - "dialog_title": "कॉल प्रारंभ करा", - "dialog_message": "आपणास खात्री आहे की आपण कॉल सुरू करू इच्छिता?" - }, - "half_swipe_notifier": { - "notification_channel_name": "अर्धा स्वाइप", - "notification_content_dm": "{friend} {duration} सेकंदासाठी आपल्या चॅटमध्ये फक्त अर्धा-स्वॅप केले", - "notification_content_group": "{friend} {group} मध्ये फक्त अर्धा-स्वॅप केलेले {duration} सेकंद" - }, - "download_processor": { - "attachment_type": { - "snap": "स्नॅप", - "sticker": "स्टिकर", - "gif": "Gif", - "external_media": "बाह्य माध्यम", - "note": "टीप", - "original_story": "मूळ कथा" - }, - "select_attachments_title": "संलग्नक निवडा", - "download_started_toast": "डाउनलोड प्रारंभ", - "unsupported_content_type_toast": "असमर्थित सामग्री प्रकार!", - "failed_no_longer_available_toast": "मीडिया यापुढे उपलब्ध नाही", - "no_attachments_toast": "कोणतेही संलग्नक आढळले नाहीत!", - "already_queued_toast": "मीडिया आधीच रांगेत आहे!", - "already_downloaded_toast": "मीडिया आधीच डाउनलोड केले आहे!", - "content_saved_toast": "सेव्ह!", - "download_toast": "डाउनलोड करीत आहे {path}...", - "processing_toast": "प्रक्रिया {path}...", - "failed_generic_toast": "डाउनलोड करण्यात अयशस्वी", - "failed_to_create_preview_toast": "पूर्वावलोकन तयार करण्यात अयशस्वी", - "failed_processing_toast": "अयशस्वी प्रक्रिया {error}", - "failed_gallery_toast": "गॅलरीमध्ये बचत अयशस्वी {error}", - "dash_no_chapter": "कोणताही अध्याय सापडला नाही", - "dash_dialog": { - "title": "डॅश मीडिया डाउनलोड करा", - "download_all": "सर्व डाउनलोड करा", - "segment_text": "विभाग {from} - {to}" - } - }, - "streaks_reminder": { - "notification_title": "पट्ट्या", - "notification_text": "आपण {hoursLeft} तासात {friend} सोबत आपला स्ट्रीक गमावाल" - }, - "biometric_auth": { - "unlock_button": "अनलॉक", - "title": "स्नॅपचॅट अनलॉक करा", - "subtitle": "कृपया स्नॅपचॅट अनलॉक करण्यासाठी प्रमाणीकृत करा" - }, - "end_to_end_encryption": { - "toolbox": { - "no_shared_key": "आपल्याकडे अद्याप या मित्रासह सामायिक रहस्य नाही. नवीन सुरू करण्यासाठी खाली क्लिक करा.", - "shared_key_fingerprint": "आपला फिंगरप्रिंट आहे:\n\n{fingerprint}\n\nते आपल्या मित्राच्या फिंगरप्रिंटशी जुळते की नाही हे तपासून पहा!", - "initiate_exchange_button": "की एक्सचेंज आरंभ करा" - }, - "confirmation_dialogs": { - "title": "एंड-टू-एंड एन्क्रिप्शन", - "confirmation_1": "चेतावणी: हे आपली विद्यमान की अधिलिखित करेल. आपण या मित्राकडून सर्व कूटबद्ध संदेशांमध्ये प्रवेश सोडू शकाल. आपणास खात्री आहे की आपण सुरू ठेवू इच्छिता?", - "confirmation_2": "आपणास खात्री आहे की आपण सुरू ठेवू इच्छिता? परत जाण्याची ही आपली शेवटची संधी आहे." - }, - "unencrypted_conversation_send_failure_toast": "आपण कूटबद्ध आणि विनाअनुदानित दोन्ही संभाषणांना एनक्रिप्टेड सामग्री पाठवू शकत नाही!", - "native_hooks_send_failure_toast": "पाठविण्यात अयशस्वी! कृपया सेटिंग्जमध्ये नेटिव्ह हुक सक्षम करा.", - "no_participants_to_encrypt_toast": "या संभाषणात आपल्याकडे संदेश कूटबद्ध करण्यासाठी कोणतेही मित्र नाहीत!", - "encryption_failed_toast": "संदेश कूटबद्ध करण्यात अयशस्वी! अधिक तपशीलांसाठी लॉगकॅट तपासा.", - "accept_public_key_success_toast": "सार्वजनिक की यशस्वीरित्या स्वीकारली!", - "accept_secret_key_success_toast": "पूर्ण झाले! आपण आता या मित्रासह कूटबद्ध संदेश पाठवू आणि प्राप्त करू शकता.", - "accept_public_key_failure_toast": "सार्वजनिक की स्वीकारण्यात अयशस्वी", - "accept_secret_key_failure_toast": "गुप्त की स्वीकारण्यात अयशस्वी", - "accept_secret_button": "रहस्य स्वीकारा", - "accept_public_key_button": "सार्वजनिक की स्वीकारा", - "outgoing_pk_message": "की एक्सचेंज विनंती", - "outgoing_secret_message": "की एक्सचेंज प्रतिसाद", - "incoming_pk_message": "आपल्याला नुकतीच सार्वजनिक की विनंती मिळाली. ते स्वीकारण्यासाठी खाली क्लिक करा.", - "incoming_secret_message": "आपल्या मित्राने नुकतीच आपली सार्वजनिक की स्वीकारली. रहस्य स्वीकारण्यासाठी खाली क्लिक करा." - }, - "auto_open_snaps": { - "title": "ऑटो ओपन स्नॅप्स", - "notification_content": "{count} स्नॅप्स उघडले" - }, - "friend_mutation_observer": { - "notification_channel_name": "मित्र उत्परिवर्तन निरीक्षक", - "friend_removed": "{username} ने आपल्याला मित्र म्हणून काढून टाकले आहे", - "birthday_removed": "{username} ने त्यांचा वाढदिवस ({birthday}) काढून टाकला आहे", - "birthday_added": "{username} ने त्यांचा वाढदिवस ({birthday}) जोडला आहे", - "birthday_changed": "{username} ने त्यांचा वाढदिवस {oldBirthday} वरून {newBirthday} मध्ये बदलला आहे", - "bitmoji_selfie_changed": "{username} ने त्यांचा बिटमोजी सेल्फी बदलला आहे", - "bitmoji_avatar_changed": "{username} ने त्यांचे बिटमोजी अवतार बदलले आहे", - "bitmoji_background_changed": "{username} ने त्यांची बिटमोजी पार्श्वभूमी बदलली आहे", - "bitmoji_scene_changed": "{username} ने त्यांचे बिटमोजी देखावा बदलला आहे" - }, - "material3_strings": { - "date_range_picker_start_headline": "पासून", - "date_range_picker_end_headline": "टू", - "date_range_picker_title": "तारीख श्रेणी निवडा", - "date_picker_switch_to_calendar_mode": "कॅलेंडर", - "date_picker_switch_to_input_mode": "इनपुट", - "date_range_picker_scroll_to_previous_month": "मागील महिना", - "date_range_picker_scroll_to_next_month": "पुढील महिन्यात", - "date_picker_today_description": "आज", - "date_range_picker_day_in_range": "निवडलेले", - "date_input_invalid_for_pattern": "अवैध तारीख", - "date_input_invalid_year_range": "अवैध वर्ष", - "date_input_invalid_not_allowed": "अवैध तारीख", - "date_range_input_invalid_range_input": "अवैध तारीख श्रेणी" - }, - "send_override_dialog": { - "title": "{type} म्हणून मीडिया पाठवा", - "duration": "कालावधी: {duration}", - "saveable_snap_hint": "गप्पांमध्ये स्नॅप सेव्ह करण्यायोग्य बनवा", - "unlimited_duration": "अमर्यादित" - }, - "invalid_input_toast": "अवैध इनपुट! आपण वैध मूल्य प्रविष्ट केले असल्याचे सुनिश्चित करा." -} \ No newline at end of file diff --git a/common/src/main/assets/lang/ms.json b/common/src/main/assets/lang/ms.json deleted file mode 100644 index 4379c4e6..00000000 --- a/common/src/main/assets/lang/ms.json +++ /dev/null @@ -1,2022 +0,0 @@ -{ - "setup": { - "dialogs": { - "select_language": "Pilih bahasa", - "save_folder": "PurrFectSnap memerlukan kebenaran penyimpanan untuk memuat turun dan menyimpan media dari Snapchat.\nSila pilih lokasi di mana media perlu dimuat turun.", - "select_save_folder_button": "Pilih folder" - }, - "mappings": { - "dialog": "Menjana pemetaan, ini mungkin mengambil sedikit masa ...", - "generate_failure_no_snapchat": "PurrfectSnap tidak dapat mengesan Snapchat, sila cuba memasang semula Snapchat.", - "generate_failure": "Ralat berlaku semasa cuba menjana pemetaan, sila cuba lagi." - }, - "permissions": { - "dialog": "Untuk meneruskan anda perlu memenuhi syarat berikut:", - "notification_access": "Akses pemberitahuan", - "battery_optimization": "Pengoptimuman bateri", - "display_over_other_apps": "Paparkan aplikasi lain", - "request_button": "Permintaan" - } - }, - "scopes": { - "friend": "Kawan", - "group": "Kumpulan" - }, - "manager": { - "routes": { - "tasks": "Tugas", - "features": "Ciri -ciri", - "manage_rule_feature": "Menguruskan ciri peraturan", - "home": "Rumah", - "home_settings": "Tetapan", - "home_logs": "Log", - "logger_history": "Sejarah Logger", - "logged_stories": "Cerita Log", - "friend_tracker": "Pengesan rakan", - "edit_rule": "Edit peraturan", - "file_imports": "Import fail", - "manage_repos": "Menguruskan repositori", - "social": "Sosial", - "manage_scope": "Mengurus skop", - "messaging_preview": "Pratonton", - "scripts": "Skrip", - "better_location": "Lokasi yang lebih baik" - }, - "sections": { - "home": { - "version_title": "v{versionName} · bercabang oleh abadi", - "update_title": "Kemas kini PurrFectSnap", - "update_content": "Versi {version} tersedia!", - "update_button": "Muat turun", - "debug_build_summary_title": "Anda menjalankan debug membina purrfectsnap", - "debug_build_summary_content": "Versi {versionName} ({versionCode})", - "debug_build_summary_date": "Tarikh Bina: {date} ({days} hari yang lalu)", - "quick_actions_title": "Tindakan cepat", - "download_icon_description": "Muat turun", - "completed_icon_description": "Selesai", - "failed_icon_description": "Gagal", - "manage_quick_actions_description": "Menguruskan tindakan cepat", - "quick_actions_icon_description": "Tindakan cepat", - "add_quick_action_description": "Tambah tindakan cepat" - }, - "home_logs": { - "no_logs_hint": "Tiada log tersedia", - "clear_logs_button": "Jelas log", - "export_logs_button": "Log Eksport", - "saving_logs_toast": "Menyimpan log, ini mungkin mengambil sedikit masa ...", - "saved_logs_success_toast": "Log disimpan dengan jayanya", - "saved_logs_failure_toast": "Gagal menyimpan balak" - }, - "home_settings": { - "actions_title": "Tindakan", - "message_logger_title": "Logger mesej", - "debug_title": "Debug", - "success_toast": "Selesai!", - "message_logger_summary": "{messageCount} Mesej\n{storyCount} Cerita", - "export_button": "Eksport", - "clear_button": "Jelas", - "view_logger_history_button": "Lihat sejarah logger", - "updates_title": "Kemas kini", - "auto_update_check": "Cek Auto untuk Kemas Kini", - "update_check_frequency": "Kemas kini frekuensi cek", - "update_check_frequency_daily": "Setiap hari", - "update_check_frequency_weekly": "Mingguan", - "update_check_frequency_monthly": "Bulanan", - "theme_icon_description": "Tema", - "app_theme_title": "Tema aplikasi", - "theme_mode_system": "Sistem", - "theme_mode_light": "Cahaya", - "theme_mode_dark": "Gelap", - "ui_settings_title": "Tetapan UI", - "haptic_feedback_label": "Maklum balas haptik", - "test_mode_label": "Mod ujian (untuk debug sahaja)", - "disable_feature_loading_label": "Lumpuhkan pemuatan ciri", - "disable_auto_mapper_label": "Lumpuhkan Mapper Auto", - "disable_bypass_indicator_label": "Lumpuhkan penunjuk status pintasan", - "update_notification_channel_name": "Kemas kini PurrFectSnap", - "update_notification_channel_description": "Pemberitahuan untuk kemas kini purrfectsnap", - "update_notification_title": "Kemas kini PurrFectSnap tersedia", - "update_notification_text": "Versi %S kini tersedia.", - "export_database_failed_toast": "Gagal mengeksport pangkalan data! {message}", - "clear_messages_failed_toast": "Gagal membersihkan mesej! {message}", - "clear_file_failed_toast": "Gagal membersihkan fail! {message}", - "debug_file_config": "Konfigurasi", - "debug_file_mappings": "Pemetaan", - "debug_file_message_logger": "Logger mesej", - "debug_file_pinned_best_friend": "Sahabat terbaik", - "debug_file_native_sig_cache": "Cache tandatangan asli" - }, - "tasks": { - "no_tasks": "Tiada tugas", - "merge_button": "Bergabung", - "failed_to_open_file": "Gagal membuka fail", - "merge_files_toast": "Menggabungkan fail {count}", - "remove_selected_tasks_title": "Adakah anda pasti mahu membuang tugas yang dipilih?", - "remove_all_tasks_title": "Adakah anda pasti mahu mengeluarkan semua tugas?", - "delete_files_option": "Juga padamkan fail", - "remove_selected_tasks_confirm": "Keluarkan tugas {count}?", - "remove_all_tasks_confirm": "Keluarkan semua tugas?", - "clear_tasks_description": "Tugas yang jelas", - "file_not_found_icon_description": "Fail tidak dijumpai", - "image_icon_description": "Imej", - "video_icon_description": "Video", - "audio_icon_description": "Audio", - "file_icon_description": "Fail", - "download_icon_description": "Muat turun", - "chat_action_icon_description": "Tindakan sembang", - "cancel_icon_description": "Batalkan", - "success_icon_description": "Kejayaan", - "failure_icon_description": "Kegagalan", - "cancelled_icon_description": "Dibatalkan", - "task_status_failure": "Kegagalan", - "task_status_cancelled": "Dibatalkan" - }, - "features": { - "disabled": "Kurang upaya", - "export_option": "Eksport", - "import_option": "Import", - "reset_option": "Tetapkan semula", - "config_export_success_toast": "Konfigurasi dieksport dengan jayanya", - "config_import_success_toast": "Konfigurasi diimport dengan jayanya", - "config_import_failure_toast": "Gagal mengimport config {error}", - "config_export_failure_toast": "Gagal mengeksport config {error}", - "saved_config_snackbar": "Konfigurasi disimpan", - "older_required": "Ciri ini memerlukan snapchat v{version} atau lebih tua untuk berfungsi dengan betul", - "newer_required": "Ciri ini memerlukan snapchat v{version} atau lebih baru berfungsi dengan betul", - "search_button": "Cari" - }, - "manage_rule_feature": { - "disable_state_option": "Kurang upaya", - "disable_state_subtext": "Tidak ada rakan/kumpulan yang akan terjejas", - "whitelist_state_option": "Tiada siapa kecuali ...", - "whitelist_state_subtext": "Hanya {count} rakan/kumpulan akan dipengaruhi oleh peraturan ini", - "whitelist_state_button": "Pilih rakan/kumpulan yang dibenarkan", - "blacklist_state_option": "Semua orang kecuali ...", - "blacklist_state_subtext": "Semua orang kecuali {count} rakan/kumpulan akan dipengaruhi oleh peraturan ini", - "blacklist_state_button": "Pilih rakan/kumpulan yang dikecualikan", - "clear_list_button": "Senarai rakan/kumpulan yang jelas", - "dialog_clear_confirmation_text": "Adakah anda pasti ingin membersihkan senarai?" - }, - "social": { - "friends_tab": "Rakan", - "groups_tab": "Kumpulan", - "empty_hint": "(kosong)", - "streaks_expiration_short": "{hours}H" - }, - "manage_scope": { - "logged_stories_button": "Tunjukkan cerita log", - "e2ee_title": "Penyulitan akhir-ke-akhir", - "rules_title": "Peraturan", - "participants_text": "{count} Peserta", - "not_found": "Tidak dijumpai", - "streaks_title": "Streaks", - "streaks_length_text": "Panjang: {length}", - "streaks_expiration_text": "Tamat dalam {eta}", - "streaks_expiration_text_expired": "Tamat tempoh", - "reminder_button": "Tetapkan peringatan", - "delete_scope_confirm_dialog_title": "Adakah anda pasti mahu memadam {scope}?", - "notes_placeholder": "Klik untuk menambah nota", - "invalid_key_size_32_bytes": "Saiz kunci tidak sah (mestilah 32 bait)", - "successfully_imported_key": "Berjaya mengimport kunci", - "failed_to_import_key": "Gagal mengimport kunci: {message}", - "export_base64_button": "Eksport Base64", - "import_base64_button": "Import Base64" - }, - "logged_stories": { - "story_failed_to_load": "Gagal memuatkan", - "no_stories": "Tiada cerita yang dijumpai", - "save_from_cache_button": "Simpan dari cache", - "downloaded_to_path": "Dimuat turun ke {path}", - "download_failed": "Muat turun gagal: {message}", - "posted_at": "Dihantar di {date}", - "created_at": "Dibuat di {date}", - "failed_to_open_file": "Gagal membuka fail. Semak log untuk maklumat lanjut", - "failed_to_get_file": "Gagal mendapatkan fail" - }, - "messaging_preview": { - "processed_messages_toast": "Diproses {count} mesej", - "processed_messages_text": "Diproses {count} mesej", - "close_button_description": "Tutup", - "bridge_connection_failed": "Gagal menyambung ke jambatan. Pastikan Snapchat berjalan di latar belakang", - "bridge_init_failed": "Gagal memulakan Jambatan Pemesejan. Pastikan Snapchat berjalan di latar belakang", - "message_fetch_failed": "Gagal mengambil mesej", - "no_message_hint": "Tiada mesej", - "save_selection_option": "Simpan pemilihan", - "save_all_option": "Simpan semua", - "unsave_selection_option": "Pemilihan yang tidak selamat", - "unsave_all_option": "Tidak selamat semua", - "mark_selection_as_seen_option": "Tandakan snap yang dipilih seperti yang dilihat", - "mark_all_as_seen_option": "Tandakan semua snap seperti yang dilihat", - "delete_selection_option": "Padam pemilihan", - "delete_all_option": "Padam semua" - }, - "logger_history": { - "download_started_toast": "Muat turun bermula!", - "download_success_toast": "Dimuat turun ke {path}", - "download_failed_toast": "Gagal memuat turun {message}", - "edited_at_text": "{message} (diedit di {date})", - "download_button": "Muat turun", - "select_conversation_placeholder": "Pilih perbualan", - "close_button_description": "Tutup", - "search_button_description": "Cari", - "list_friend_format": "Rakan {name}", - "list_group_format": "Kumpulan {name}", - "no_more_messages": "Tiada lagi mesej", - "reverse_order_checkbox": "Urutan terbalik", - "chat_attachment": "Lampiran {index}", - "empty_message": "Mesej sembang kosong", - "message_parse_failed": "Gagal menghuraikan mesej", - "unknown_sender": "Pengirim yang tidak diketahui", - "download_attachment_failed_toast": "Gagal memuat turun lampiran", - "log_header_format": "{username} ({type}) - {date}" - }, - "file_imports": { - "import_file_button": "Import fail", - "file_not_found": "Fail tidak dijumpai", - "file_import_failed": "Gagal mengimport fail: {error}", - "file_imported": "Fail yang diimport dengan jayanya", - "file_delete_failed": "Gagal memadam fail", - "no_files_hint": "Di sini anda boleh mengimport fail untuk digunakan di Snapchat. Tekan butang di bawah untuk mengimport fail." - }, - "better_location": { - "spoofed_coordinates_title": "Lat {latitude}, lng {longitude}", - "save_coordinates_dialog_title": "Simpan koordinat", - "saved_name_dialog_hint": "Nama yang disimpan", - "latitude_dialog_hint": "Latitud", - "longitude_dialog_hint": "Longitud", - "save_dialog_button": "Simpan", - "choose_location_button": "Pilih Lokasi", - "teleport_to_friend_button": "Teleport kepada rakan", - "spoof_location_toggle": "Lokasi spoof", - "suspend_location_updates": "Menggantung kemas kini lokasi", - "saved_coordinates_title": "Koordinat yang disimpan", - "no_saved_coordinates_hint": "Tiada koordinat yang disimpan", - "delete_dialog_title": "Padam koordinat yang disimpan", - "delete_dialog_message": "Adakah anda pasti mahu memadamkan koordinat yang disimpan ini?", - "teleport_to_friend_title": "Teleport kepada rakan", - "search_bar": "Cari", - "no_friends_map": "Tidak ada kawan di peta", - "no_friends_found": "Tidak ada kawan yang dijumpai", - "edit_location_button_description": "Edit lokasi", - "add_icon_description": "Tambah", - "edit_icon_description": "Edit", - "delete_icon_description": "Padam" - } - }, - "dialogs": { - "add_friend": { - "title": "Tambah rakan atau kumpulan", - "search_hint": "Cari", - "fetch_error": "Gagal mengambil data", - "category_groups": "Kumpulan", - "category_friends": "Rakan", - "participants_text": "{count} Peserta", - "search_icon_description": "Cari" - }, - "scripting_warning": { - "title": "Amaran", - "content": "PurrFectSnap termasuk alat skrip, yang membolehkan pelaksanaan kod yang ditentukan pengguna pada peranti anda. Gunakan berhati -hati dan hanya memasang modul dari sumber yang diketahui dan boleh dipercayai. Modul yang tidak dibenarkan atau tidak disahkan boleh menimbulkan risiko keselamatan kepada sistem anda." - }, - "reset_config": { - "title": "Tetapkan semula konfigurasi", - "content": "Adakah anda pasti mahu menetapkan semula konfigurasi?", - "success_toast": "Config Reset dengan jayanya" - }, - "export_config": { - "title": "Data sensitif eksport?", - "content": "Adakah anda ingin mengeksport konfigurasi dengan data sensitif? (Seperti koordinat lokasi, dll.)" - }, - "messaging_action": { - "title": "Pilih jenis kandungan untuk diproses", - "select_all_button": "Pilih Semua" - }, - "file_imports": { - "no_files_settings_hint": "Tiada fail yang dijumpai. Pastikan anda telah mengimport fail yang diperlukan di bahagian Import Fail", - "settings_select_file_hint": "Pilih fail yang diimport" - }, - "quick_actions_dialog": { - "title": "Edit tindakan cepat", - "subtitle": "Pilih dan saiz tindakan cepat anda." - } - }, - "friend_tracker": { - "rules_tab": "Peraturan", - "logs_tab": "Log", - "export_dialog_title": "Eksport", - "bulk_export_button": "Eksport pukal", - "individual_export_button": "Eksport individu", - "invalid_import_type_dialog_title": "Jenis import tidak sah", - "invalid_import_type_dialog_text": "Fail yang dipilih tidak serasi dengan jenis import ini. Sila pilih jenis import yang betul.", - "import_dialog_title": "Import", - "bulk_import_button": "Import pukal", - "individual_import_button": "Import individu", - "import_button_description": "Import", - "export_button_description": "Eksport", - "export_button": "Eksport", - "delete_button_description": "Padam", - "delete_button": "Padam", - "catalog_button_description": "Katalog", - "catalog_button": "Katalog", - "add_rule_button_description": "Tambah peraturan", - "add_rule_button": "Tambah peraturan", - "no_rules_found": "Tiada peraturan yang dijumpai", - "empty_rule_name": "(kosong)", - "events_suffix": "peristiwa", - "scopes_suffix": "skop", - "select_rule_to_export_title": "Pilih Peraturan untuk Mengeksport", - "deleted_logs_toast": "Dipadam {count} log", - "delete_logs_dialog_title": "Padam log?", - "deleting_logs_dialog_text": "Memadamkan {count} Log ...", - "delete_logs_dialog_confirm_text": "Ini akan memadam log berdasarkan penapis semasa dan pertanyaan carian. Tindakan ini tidak dapat dibatalkan.", - "exported_logs_toast": "Log yang dieksport!", - "export_logs_failed_toast": "Gagal mengeksport log. Semak LogCat untuk maklumat lanjut.", - "export_logs_dialog_title": "Log Eksport?", - "exporting_logs_dialog_text": "Mengeksport log ...", - "export_logs_dialog_confirm_text": "Ini akan mengeksport log berdasarkan penapis semasa dan pertanyaan carian.", - "export_as_button": "Eksport sebagai {type}", - "filters_title": "Penapis", - "search_by_label": "Cari oleh", - "newest_first_label": "Terkini pertama", - "since_label": "Sejak", - "until_label": "Sehingga", - "pick_a_date_button": "Pilih tarikh", - "search_placeholder": "Cari", - "filter_button_description": "Penapis", - "clear_button_description": "Jelas", - "no_logs_found": "Tiada balak dijumpai", - "log_event_format": "{event} di {conversation}", - "condition_only_inside_conversation": "Hanya semasa saya di dalam perbualan", - "condition_only_outside_conversation": "Hanya semasa saya di luar perbualan", - "condition_only_when_app_active": "Hanya ketika Snapchat aktif", - "condition_only_when_app_inactive": "Hanya apabila Snapchat tidak aktif", - "condition_no_push_notification_when_app_active": "Tiada pemberitahuan ketika Snapchat aktif", - "add_event_dialog_title": "Tambah acara", - "event_type_label": "Jenis Acara", - "triggers_title": "Pencetus", - "conditions_title": "Keadaan", - "add_button": "Tambah", - "default_rule_name": "Peraturan tersuai", - "discard_changes_dialog_title": "Buang perubahan?", - "discard_changes_dialog_text": "Anda mempunyai perubahan yang tidak diselamatkan. Adakah anda pasti mahu membuangnya?", - "discard_button": "Buang", - "cannot_save_rule_dialog_title": "Tidak dapat menyimpan peraturan", - "cannot_save_rule_dialog_text": "Peraturan mesti mempunyai sekurang -kurangnya satu peristiwa untuk disimpan.", - "duplicate_rule_name_dialog_title": "Nama peraturan pendua", - "duplicate_rule_name_dialog_text": "Peraturan dengan nama ini sudah ada. Sila pilih nama yang berbeza.", - "delete_rule_dialog_title": "Padam peraturan", - "delete_rule_dialog_text": "Adakah anda pasti mahu memadamkan peraturan ini?", - "new_rule_title": "Peraturan baru", - "edit_rule_title": "Edit peraturan", - "back_button_description": "Kembali", - "save_button_description": "Simpan", - "general_section_title": "Umum", - "rule_name_label": "Nama peraturan", - "author_name_label": "Nama Pengarang", - "scope_section_title": "Skop", - "scope_all": "Semua", - "scope_whitelist": "Whitelist", - "scope_blacklist": "Senarai Hitam", - "select_friends_groups_button": "Pilih rakan/kumpulan ({count})", - "events_section_title": "Peristiwa", - "add_event_button": "Tambah acara", - "no_events_text": "Tiada peristiwa" - }, - "friend_tracker_catalog": { - "download_failed": "Muat turun gagal: {code}", - "error": "Ralat: {message}", - "no_repos_added": "Tiada repositori ditambah.", - "no_rules_available": "Tiada peraturan yang tersedia dari mana -mana repo.", - "by_author": "oleh {author}", - "imported_button": "Diimport", - "import_button": "Import", - "title": "Katalog Tracker Rakan", - "manage_repos_description": "Menguruskan repositori" - }, - "friend_tracker_export": { - "title": "Peraturan eksport", - "back_button_description": "Kembali", - "exported_toast": "Peraturan pelacak rakan dieksport!", - "export_failed_toast": "Gagal mengeksport peraturan: {message}", - "save_button": "Simpan", - "expand_button_description": "Berkembang" - }, - "friend_tracker_import": { - "title": "Peraturan import", - "back_button_description": "Kembali", - "imported_toast": "Peraturan Tracker Rakan diimport!", - "import_failed_toast": "Gagal mengimport peraturan: {message}", - "confirm_button": "Mengesahkan", - "expand_button_description": "Berkembang" - }, - "friend_tracker_repos": { - "invalid_repo_title": "Repositori tidak sah", - "add_repo_button": "Tambah repositori", - "add_repo_dialog_title": "Tambah URL repositori", - "repo_url_label": "URL Repositori", - "repo_added_toast": "Repositori ditambah dengan jayanya!", - "invalid_repo_error": "Ini tidak kelihatan sebagai repositori pelacak rakan yang sah.", - "add_repo_failed_toast": "Gagal menambah repositori: {message}", - "add_button": "Tambah", - "no_repos_added": "Tiada repositori ditambah", - "remove_button": "Keluarkan", - "remove_repo_dialog_title": "Keluarkan repositori", - "remove_repo_dialog_text": "Adakah anda pasti mahu mengeluarkan repositori ini?" - }, - "navigation": { - "tracker_tab_label": "Pelacak", - "customize_bottom_bar_title": "Sesuaikan bar bawah", - "customize_bottom_bar_subtitle": "Menyusun semula, menambah atau mengeluarkan tab. Maksimum lima.", - "shown_tabs_title": "Tab yang ditunjukkan", - "no_tabs_selected_text": "Tiada tab dipilih", - "available_tabs_title": "Tab yang ada", - "reset_button": "Tetapkan semula", - "done_button": "Selesai" - }, - "scripting": { - "script_already_installed": "Skrip sudah dipasang!", - "downloading_script": "Memuat turun skrip ...", - "script_downloaded": "Skrip {name} Muat turun!", - "download_script_failed": "Gagal memuat turun skrip. Semak log untuk maklumat lanjut", - "import_script_from_url_title": "Skrip import dari URL", - "import_script_warning": "Amaran: Skrip yang diimport boleh membahayakan peranti anda. Hanya skrip import dari sumber yang dipercayai.", - "enter_url_label": "Masukkan URL di sini:", - "script_imported": "Skrip {name} diimport!", - "import_failed": "Gagal mengimport skrip. {message}. Semak log untuk maklumat lanjut", - "import_button": "Import", - "update_module_button": "Modul kemas kini", - "updating_script": "Mengemas kini skrip {name}...", - "module_not_found": "Modul tidak dijumpai", - "updated_script": "Dikemas kini {name} ke versi {version}", - "update_module_failed": "Gagal mengemas kini modul. Semak log untuk maklumat lanjut", - "edit_module_button": "Edit modul", - "open_module_failed": "Gagal membuka fail modul. Semak log untuk maklumat lanjut", - "clear_module_data_button": "Data modul yang jelas", - "module_data_cleared": "Data modul dibersihkan!", - "clear_module_data_failed": "Gagal membersihkan data modul. Semak log untuk maklumat lanjut", - "delete_module_button": "Padam modul", - "deleted_script": "Skrip yang dipadam {name}!", - "delete_module_failed": "Gagal memadam modul. Semak log untuk maklumat lanjut", - "actions_title": "Tindakan", - "no_description": "Tiada penerangan", - "update_available": "Kemas kini tersedia: {version}", - "actions_button": "Tindakan", - "loaded_script": "Skrip dimuat {name}", - "unloaded_script": "Skrip yang dipunggah {name}", - "enable_script_failed": "Gagal membolehkan skrip. Semak log untuk maklumat lanjut", - "disable_script_failed": "Gagal melumpuhkan skrip. Semak log untuk maklumat lanjut", - "select_scripts_folder_toast": "Sila pilih folder skrip anda!", - "manage_repos_button": "Menguruskan repos", - "import_from_url_button": "Import dari URL", - "open_scripts_folder_button": "Buka Folder Skrip", - "no_settings_for_module": "Modul ini tidak mempunyai tetapan", - "installed_scripts_tab": "Skrip dipasang", - "catalog_tab": "Katalog", - "no_scripts_folder_selected_title": "Tiada folder skrip yang dipilih", - "select_folder_button": "Pilih folder", - "no_scripts_found_title": "Tiada skrip dijumpai.", - "use_catalog_to_add_scripts": "Gunakan tab Katalog untuk menambah skrip!", - "ok_button_timeout": "Ok ({timeout})", - "documentation_button": "Dokumentasi", - "catalog": { - "script_already_installed": "Skrip sudah dipasang!", - "download_failed": "Muat turun gagal: {code}", - "script_downloaded": "Skrip dimuat turun!", - "could_not_create_file": "Tidak dapat membuat fail.", - "no_scripts_folder_selected": "Tiada folder skrip yang dipilih.", - "error": "Ralat: {message}", - "no_repos_added": "Tiada repositori ditambah.", - "repo_list_info": "Di sini anda boleh mencari senarai repos:", - "link_text": "Pautan", - "no_scripts_available": "Tiada skrip yang tersedia dari mana -mana repo.", - "by_author": "oleh {author}", - "version": "Versi: {version}", - "installed_button": "Dipasang", - "download_button": "Muat turun" - }, - "repos": { - "invalid_repo_title": "Repositori tidak sah", - "add_repo_button": "Tambah repositori", - "add_repo_dialog_title": "Tambah URL repositori", - "repo_url_label": "URL Repositori", - "repo_added_toast": "Repositori ditambah dengan jayanya!", - "invalid_repo_error": "Ini tidak kelihatan sebagai repositori skrip yang sah.", - "add_repo_failed_toast": "Gagal menambah repositori: {message}", - "add_button": "Tambah", - "no_repos_added": "Tiada repositori ditambah", - "remove_button": "Keluarkan", - "remove_repo_dialog_title": "Keluarkan repositori", - "remove_repo_dialog_text": "Adakah anda pasti mahu mengeluarkan repositori ini?" - } - }, - "features": { - "config_import": { - "title": "Sahkan import", - "back_button_description": "Kembali", - "config_imported_toast": "Konfigurasi diimport!", - "confirm_button": "Mengesahkan", - "expand_button_description": "Berkembang", - "enable_feature": "Membolehkan ciri", - "enabled": "Didayakan", - "disabled": "Kurang upaya" - }, - "config_export": { - "title": "Ringkasan Eksport", - "back_button_description": "Kembali", - "save_button": "Simpan", - "expand_button_description": "Berkembang", - "enable_feature": "Membolehkan ciri", - "enabled": "Didayakan", - "disabled": "Kurang upaya" - } - }, - "manage_repos": { - "title": "Mengurus repositori {featureName}", - "add_repo_button": "Tambah repositori", - "add_repo_dialog_title": "Tambah URL repositori", - "repo_url_label": "URL Repositori", - "repo_added_successfully": "Repositori ditambah dengan jayanya!", - "add_repo_failed": "Gagal menambah repositori: {message}", - "add_button": "Tambah", - "no_repos_added": "Tiada repositori ditambah", - "remove_button": "Keluarkan" - } - }, - "rules": { - "toasts": { - "enabled": "{ruleName} diaktifkan", - "disabled": "{ruleName} Dilumpuhkan" - }, - "modes": { - "blacklist": "Mod senarai hitam", - "whitelist": "Mod Whitelist" - }, - "properties": { - "auto_download": { - "name": "Muat turun automatik", - "description": "Muat turun secara automatik ketika melihatnya", - "options": { - "blacklist": "Kecualikan dari muat turun automatik", - "whitelist": "Muat turun automatik" - } - }, - "stealth": { - "name": "Mod stealth", - "description": "Menghalang sesiapa daripada mengetahui bahawa anda telah membuka snap/sembang dan perbualan mereka", - "options": { - "blacklist": "Tidak termasuk dari mod stealth", - "whitelist": "Mod stealth" - } - }, - "auto_save": { - "name": "Simpan Auto", - "description": "Menyimpan mesej sembang semasa melihatnya", - "options": { - "blacklist": "Kecualikan dari Simpan Auto", - "whitelist": "Simpan Auto" - } - }, - "unsaveable_messages": { - "name": "Mesej yang tidak dapat disimpan", - "description": "Menghalang mesej daripada diselamatkan dalam sembang oleh orang lain", - "options": { - "blacklist": "Tidak termasuk mesej yang tidak dapat diselamatkan", - "whitelist": "Mesej yang tidak dapat disimpan" - } - }, - "auto_open_snaps": { - "name": "Auto Open Snaps", - "description": "Secara automatik membuka snap semasa menerimanya", - "options": { - "blacklist": "Kecualikan dari Snaps Terbuka Auto", - "whitelist": "Auto Open Snaps" - } - }, - "hide_friend_feed": { - "name": "Bersembunyi dari suapan rakan" - }, - "e2e_encryption": { - "name": "Gunakan penyulitan E2E" - }, - "pin_conversation": { - "name": "Perbualan pin" - }, - "exclude_message_logger": { - "name": "Tidak termasuk dari logger mesej" - } - } - }, - "actions": { - "clean_snapchat_cache": { - "name": "Clean Snapchat Cache", - "description": "Membersihkan cache snapchat" - }, - "manage_friend_list": { - "name": "Urus senarai rakan", - "description": "Mengimport/mengeksport senarai rakan anda semasa disandarkan" - }, - "export_chat_messages": { - "name": "Eksport mesej sembang", - "description": "Mengeksport mesej perbualan ke dalam fail JSON/HTML/TXT" - }, - "export_memories": { - "name": "Kenangan eksport", - "description": "Mengeksport kenangan ke dalam fail zip" - }, - "bulk_messaging_action": { - "name": "Tindakan pemesejan pukal", - "description": "Melakukan operasi seperti memadam rakan atau penghapusan banyak perbualan" - }, - "regen_mappings": { - "name": "Mappings Regenerate", - "description": "Pemetaan semula secara manual" - }, - "change_language": { - "name": "Tukar bahasa", - "description": "Tukar bahasa purrfectsnap" - }, - "file_imports": { - "name": "Import fail", - "description": "Import fail untuk digunakan di Snapchat" - }, - "friend_tracker": { - "name": "Pengesan rakan", - "description": "Jejaki rakan anda di Snapchat" - }, - "logger_history": { - "name": "Sejarah Logger", - "description": "Lihat sejarah mesej log masuk" - } - }, - "features": { - "notices": { - "unstable": "⚠ Tidak stabil", - "ban_risk": "⚠ Ciri ini boleh menyebabkan larangan", - "internal_behavior": "⚠ Ini boleh memecahkan tingkah laku dalaman Snapchat" - }, - "properties": { - "downloader": { - "name": "Pemuat turun", - "description": "Muat turun Snapchat Media", - "properties": { - "save_folder": { - "name": "Simpan folder", - "description": "Pilih direktori yang mana semua media harus dimuat turun" - }, - "auto_download_sources": { - "name": "Sumber muat turun automatik", - "description": "Pilih sumber untuk memuat turun secara automatik" - }, - "prevent_self_auto_download": { - "name": "Cegah muat turun automatik diri", - "description": "Menghalang snaps anda sendiri daripada dimuat turun secara automatik" - }, - "path_format": { - "name": "Format Laluan", - "description": "Tentukan format laluan fail" - }, - "allow_duplicate": { - "name": "Benarkan pendua", - "description": "Membolehkan media yang sama dimuat turun beberapa kali" - }, - "merge_overlays": { - "name": "Menggabungkan overlays", - "description": "Menggabungkan teks dan media snap ke dalam satu fail" - }, - "force_image_format": { - "name": "Format imej daya", - "description": "Memaksa imej yang akan disimpan dalam format yang ditentukan" - }, - "force_voice_note_format": { - "name": "Format nota suara memaksa", - "description": "Nota suara memaksa disimpan dalam format yang ditentukan" - }, - "auto_download_voice_notes": { - "name": "Nota suara muat turun automatik", - "description": "Memuat turun nota suara secara automatik semasa memainkannya" - }, - "download_profile_pictures": { - "name": "Muat turun gambar profil", - "description": "Membolehkan anda memuat turun gambar profil dari halaman profil" - }, - "opera_download_button": { - "name": "Butang muat turun opera", - "description": "Menambah butang muat turun di sudut kanan atas apabila melihat snap.\nTekan panjang pada butang akan memaksa muat turun" - }, - "download_context_menu": { - "name": "Muat turun menu konteks", - "description": "Membolehkan anda memuat turun/pratonton mesej dari perbualan atau cerita menggunakan menu konteks.\nTekan panjang pada butang akan memaksa muat turun" - }, - "ffmpeg_options": { - "name": "Pilihan FFMPEG", - "description": "Tentukan pilihan FFMPEG tambahan", - "properties": { - "threads": { - "name": "Benang", - "description": "Jumlah utas untuk digunakan" - }, - "preset": { - "name": "Pratetap", - "description": "Tetapkan kelajuan penukaran" - }, - "constant_rate_factor": { - "name": "Faktor kadar yang berterusan", - "description": "Tetapkan faktor kadar malar untuk pengekod video\nDari 0 hingga 51 untuk libx264" - }, - "video_bitrate": { - "name": "Bitrate video", - "description": "Tetapkan bitrate video (KBPS)" - }, - "audio_bitrate": { - "name": "Bitrate audio", - "description": "Tetapkan Bitrate Audio (KBPS)" - }, - "custom_video_codec": { - "name": "Codec video tersuai", - "description": "Tetapkan codec video tersuai (mis. Libx264)" - }, - "custom_audio_codec": { - "name": "Codec Audio Custom", - "description": "Tetapkan codec audio tersuai (mis. AAC)" - } - } - }, - "logging": { - "name": "Pembalakan", - "description": "Menunjukkan toast semasa media memuat turun" - }, - "custom_path_format": { - "name": "Format laluan tersuai", - "description": "Tentukan format laluan tersuai untuk media yang dimuat turun\n\nPembolehubah yang tersedia:\n - %nama pengguna %\n - %sumber %\n - %hash %\n - %date_time %" - } - } - }, - "user_interface": { - "name": "Antara muka pengguna", - "description": "Tukar rupa dan rasa Snapchat", - "properties": { - "enable_app_appearance": { - "name": "Dayakan tetapan penampilan aplikasi", - "description": "Membolehkan tetapan penampilan aplikasi tersembunyi\nMungkin tidak diperlukan pada versi Snapchat yang lebih baru" - }, - "friend_feed_message_preview": { - "name": "Pratonton mesej suapan rakan", - "description": "Menunjukkan pratonton mesej terakhir dalam suapan rakan", - "properties": { - "amount": { - "name": "Jumlah", - "description": "Jumlah mesej untuk dipratonton" - } - } - }, - "snap_preview": { - "name": "Pratonton snap", - "description": "Memaparkan pratonton kecil di sebelah gambaran yang tidak kelihatan dalam sembang" - }, - "bootstrap_override": { - "name": "Bootstrap override", - "description": "Mengatasi tetapan bootstrap antara muka pengguna", - "properties": { - "app_appearance": { - "name": "Penampilan App", - "description": "Menetapkan penampilan aplikasi yang berterusan" - }, - "home_tab": { - "name": "Tab Rumah", - "description": "Mengatasi tab permulaan ketika membuka Snapchat" - } - } - }, - "force_amoled_theme": { - "name": "Mod gelap AMOLED", - "description": "Menggunakan latar belakang hitam yang benar untuk tema gelap" - }, - "map_friend_nametags": { - "name": "Nametag peta rakan yang dipertingkatkan", - "description": "Meningkatkan nametag rakan -rakan di snapmap" - }, - "prevent_message_list_auto_scroll": { - "name": "Cegah Senarai Mesej Tatal Auto", - "description": "Menghalang senarai mesej dari menatal ke bahagian bawah semasa menghantar/menerima mesej" - }, - "streak_expiration_info": { - "name": "Tunjukkan maklumat tamat tempoh coretan", - "description": "Menunjukkan pemasa tamat tempoh bersebelahan dengan kaunter coretan" - }, - "hide_friend_feed_entry": { - "name": "Sembunyikan kemasukan suapan rakan", - "description": "Menyembunyikan rakan tertentu dari suapan rakan\nGunakan tab Sosial untuk menguruskan ciri ini" - }, - "hide_streak_restore": { - "name": "Menyembunyikan pemulihan coretan", - "description": "Menyembunyikan butang pemulihan pada makanan rakan" - }, - "hide_quick_add_suggestions": { - "name": "Sembunyikan Cadangan Tambah Cepat", - "description": "Menghilangkan Cadangan Tambah Rakan Pantas" - }, - "hide_story_suggestions": { - "name": "Menyembunyikan cadangan cerita", - "description": "Mengeluarkan cadangan dari halaman cerita" - }, - "hide_ui_components": { - "name": "Menyembunyikan komponen UI", - "description": "Pilih komponen UI yang hendak disembunyikan" - }, - "opera_media_quick_info": { - "name": "Maklumat cepat media opera", - "description": "Menunjukkan maklumat berguna media seperti Tarikh Penciptaan dalam Menu Konteks Opera Viewer" - }, - "old_bitmoji_selfie": { - "name": "Bitmoji selfie lama", - "description": "Mengembalikan selfies Bitmoji dari versi Snapchat yang lebih tua" - }, - "disable_spotlight": { - "name": "Lumpuhkan Spotlight", - "description": "Melumpuhkan halaman sorotan" - }, - "friend_feed_menu_buttons": { - "name": "Butang menu suapan rakan", - "description": "Pilih butang mana yang hendak ditunjukkan dalam menu suapan rakan" - }, - "auto_close_friend_feed_menu": { - "name": "Menu suapan rakan rapat automatik", - "description": "Secara automatik menutup menu suapan rakan setelah menekan butang tetapan" - }, - "vertical_story_viewer": { - "name": "Penonton cerita menegak", - "description": "Membolehkan penonton cerita menegak untuk semua cerita" - }, - "enable_friend_feed_menu_bar": { - "name": "Bar menu suapan rakan", - "description": "Membolehkan bar menu suapan rakan baru" - }, - "message_indicators": { - "name": "Petunjuk mesej", - "description": "Menambah ikon petunjuk tertentu ke mesej\nNota: Petunjuk mungkin tidak 100% tepat" - }, - "stealth_mode_indicator": { - "name": "Penunjuk Mod Stealth", - "description": "Menambah 👻 emoji di sebelah perbualan dalam mod stealth" - }, - "edit_text_override": { - "name": "Edit teks Override", - "description": "Mengatasi tingkah laku medan teks" - }, - "prevent_forced_keyboard": { - "name": "Mencegah papan kekunci paksa", - "description": "Menghalang Snapchat dari secara automatik muncul papan kekunci semasa anda membuka perbualan" - }, - "settings_menu": { - "name": "Menu Tetapan", - "description": "Perubahan cara anda membuka menu purrfectsnap", - "options": { - "default": "Lalai", - "legacy": "Warisan" - } - } - } - }, - "messaging": { - "name": "Pemesejan", - "description": "Tukar bagaimana anda berinteraksi dengan rakan", - "properties": { - "bypass_screenshot_detection": { - "name": "Pengesanan tangkapan skrin bypass", - "description": "Menghalang Snapchat daripada mengesan semasa anda mengambil tangkapan skrin" - }, - "anonymous_story_viewing": { - "name": "Tontonan cerita tanpa nama", - "description": "Menghalang sesiapa daripada mengetahui bahawa anda telah melihat cerita mereka" - }, - "prevent_story_rewatch_indicator": { - "name": "Mencegah penunjuk kisah cerita", - "description": "Menghalang sesiapa daripada mengetahui bahawa anda telah mengulangi kisah mereka" - }, - "hide_peek_a_peek": { - "name": "Sembunyikan Peek-A-Peek", - "description": "Menghalang pemberitahuan daripada dihantar apabila anda meleret ke dalam sembang" - }, - "hide_bitmoji_presence": { - "name": "Menyembunyikan kehadiran Bitmoji", - "description": "Menghalang bitmoji anda dari muncul semasa berbual" - }, - "hide_typing_notifications": { - "name": "Menyembunyikan pemberitahuan menaip", - "description": "Menghalang sesiapa daripada mengetahui bahawa anda menaip mesej" - }, - "unlimited_snap_view_time": { - "name": "Masa Lihat Snap Tanpa Had", - "description": "Mengeluarkan had masa untuk melihat snaps" - }, - "auto_mark_as_read": { - "name": "Tanda automatik seperti dibaca", - "description": "Menandakan mesej/snap secara automatik seperti yang dibaca walaupun mod stealth diaktifkan" - }, - "mark_snap_as_seen_button": { - "name": "Tandakan Snap Seperti Butang yang Dilihat", - "description": "Menambah butang untuk menandakan snap seperti yang dilihat ketika melihatnya.\nIni akan berfungsi walaupun mod stealth diaktifkan" - }, - "skip_when_marking_as_seen": { - "name": "Langkau ketika menandakan seperti yang dilihat", - "description": "Secara automatik melangkau ke snap seterusnya apabila menandakan snap seperti yang dilihat.\nGunakan dalam kombinasi dengan snap Mark sebagai butang yang dilihat" - }, - "loop_media_playback": { - "name": "Main balik media gelung", - "description": "Loops Media Main balik semasa melihat Snaps / Story" - }, - "disable_replay_in_ff": { - "name": "Lumpuhkan replay di ff", - "description": "Melumpuhkan keupayaan untuk dimainkan semula dengan akhbar panjang dari suapan rakan" - }, - "half_swipe_notifier": { - "name": "Pemberitahuan separuh sapu", - "description": "Memberitahu anda apabila seseorang separuh melayari perbualan", - "properties": { - "min_duration": { - "name": "Tempoh minimum", - "description": "Tempoh minimum sapu separuh (dalam saat)" - }, - "max_duration": { - "name": "Tempoh maksimum", - "description": "Tempoh maksimum sapu separuh (dalam saat)" - } - } - }, - "call_start_confirmation": { - "name": "Pengesahan Mula Panggilan", - "description": "Menunjukkan dialog pengesahan semasa memulakan panggilan" - }, - "unlimited_conversation_pinning": { - "name": "Perbualan tanpa had", - "description": "Membolehkan anda mencatatkan perbualan yang tidak terhad secara tempatan" - }, - "disable_snap_mode_restrictions": { - "name": "Lumpuhkan sekatan mod snap", - "description": "Membolehkan anda melihat pemusnah diri tanpa sekatan" - }, - "prevent_message_sending": { - "name": "Cegah menghantar mesej", - "description": "Menghalang menghantar jenis mesej tertentu" - }, - "friend_mutation_notifier": { - "name": "Pemberitahuan mutasi rakan", - "description": "Memberitahu anda apabila sesuatu berubah dalam profil rakan" - }, - "better_notifications": { - "name": "Pemberitahuan yang lebih baik", - "description": "Menambah lebih banyak maklumat dalam pemberitahuan yang diterima", - "properties": { - "group_notifications": { - "name": "Pemberitahuan Kumpulan", - "description": "Pemberitahuan kumpulan menjadi satu" - }, - "chat_preview": { - "name": "Pratonton sembang", - "description": "Menunjukkan pratonton mesej yang diterima dalam pemberitahuan" - }, - "media_preview": { - "name": "Pratonton Media", - "description": "Menunjukkan pratonton jenis media yang dipilih dalam pemberitahuan" - }, - "media_caption": { - "name": "Kapsyen Media", - "description": "Menunjukkan kapsyen media yang dilampirkan dalam pemberitahuan" - }, - "stacked_media_messages": { - "name": "Mesej media yang disusun", - "description": "Menggabungkan pelbagai mesej media ke dalam satu pemberitahuan teks apabila mereka tidak dapat dipratonton. Gunakan dalam kombinasi dengan pratonton sembang" - }, - "friend_add_source": { - "name": "Rakan tambah sumber", - "description": "Menunjukkan sumber permintaan rakan dalam pemberitahuan" - }, - "reply_button": { - "name": "Butang balasan", - "description": "Menambah butang balasan ke pemberitahuan" - }, - "smart_replies": { - "name": "Balasan pintar", - "description": "Menambah balasan yang dicadangkan kepada pemberitahuan (Android 10+). Gunakan dalam kombinasi dengan butang balasan" - }, - "download_button": { - "name": "Butang muat turun", - "description": "Membolehkan anda memuat turun media dari pemberitahuan" - }, - "mark_as_read_button": { - "name": "Tandakan sebagai butang baca", - "description": "Membolehkan anda menandakan mesej seperti yang dibaca dari pemberitahuan" - }, - "mark_as_read_and_save_in_chat": { - "name": "Tandakan sebagai baca dan simpan dalam sembang", - "description": "Menambah tanda sebagai Baca dan simpan dalam butang sembang ke pemberitahuan" - } - } - }, - "notification_blacklist": { - "name": "Pemberitahuan Blacklist", - "description": "Pilih pemberitahuan yang sepatutnya disekat" - }, - "message_logger": { - "name": "Logger mesej", - "description": "Menghalang mesej daripada dipadamkan", - "properties": { - "keep_my_own_messages": { - "name": "Simpan mesej saya sendiri", - "description": "Menghalang mesej anda sendiri daripada dipadamkan" - }, - "auto_purge": { - "name": "Pembersihan auto", - "description": "Memadam mesej cache secara automatik yang lebih tua daripada jumlah masa yang ditentukan" - }, - "message_filter": { - "name": "Penapis Mesej", - "description": "Pilih mesej mana yang harus dilog (kosong untuk semua mesej)" - }, - "deleted_message_color": { - "name": "Warna mesej yang dipadam", - "description": "Menetapkan warna mesej yang dipadam" - } - } - }, - "auto_save_messages_in_conversations": { - "name": "Mesej Simpan Auto", - "description": "Secara automatik menjimatkan setiap mesej dalam perbualan" - }, - "gallery_media_send_override": { - "name": "Galeri Media Hantar Mengatasi", - "description": "Spoofs sumber media semasa menghantar dari galeri" - }, - "strip_media_metadata": { - "name": "Metadata media strip", - "description": "Membuang metadata media sebelum menghantar sebagai mesej" - }, - "bypass_message_retention_policy": { - "name": "Dasar pengekalan mesej pintasan", - "description": "Menghalang mesej daripada dipadam setelah melihatnya" - }, - "bypass_message_action_restrictions": { - "name": "Sekatan tindakan pintasan mesej", - "description": "Membolehkan anda bertindak balas terhadap snap tanpa membukanya atau menyimpan mesej yang tidak dapat diselamatkan" - }, - "remove_groups_locked_status": { - "name": "Keluarkan status terkunci kumpulan", - "description": "Membolehkan anda melihat maklumat kumpulan setelah ditendang" - }, - "double_tap_chat_action": { - "name": "Tindakan sembang ketuk berganda", - "description": "Melakukan tindakan tersuai ketika mengetuk dua mesej dalam sembang" - }, - "double_tap_chat_action_custom_emoji": { - "name": "Double Tap Chat Tindakan Reaksi Emoji Custom", - "description": "Menetapkan reaksi emoji tersuai untuk tindakan sembang ketuk berganda" - } - } - }, - "global": { - "name": "Global", - "description": "Tweak Tetapan Snapchat Global", - "properties": { - "better_location": { - "name": "Lokasi yang lebih baik", - "description": "Meningkatkan lokasi Snapchat", - "properties": { - "spoof_location": { - "name": "Lokasi spoof", - "description": "Spoofs lokasi anda ke yang ditentukan" - }, - "coordinates": { - "name": "Koordinat", - "description": "Tetapkan koordinat lokasi spoofed" - }, - "walk_radius": { - "name": "Walk Radius", - "description": "Berjalan secara rawak dalam jejari ini (kaki)" - }, - "always_update_location": { - "name": "Sentiasa mengemas kini lokasi", - "description": "Paksa Snapchat untuk mengemas kini lokasi walaupun tiada data GPS diterima" - }, - "suspend_location_updates": { - "name": "Menggantung kemas kini lokasi", - "description": "Menghalang lokasi anda daripada dikemas kini" - }, - "spoof_battery_level": { - "name": "Tahap bateri spoof", - "description": "Spoofs tahap bateri peranti anda di peta\nNilai mestilah antara 0 dan 100" - }, - "spoof_headphones": { - "name": "Fon kepala spoof", - "description": "Spoofs status mendengar muzik di peta" - }, - "show_battery_level": { - "name": "Tunjukkan tahap bateri", - "description": "Menunjukkan tahap bateri rakan anda di peta" - } - } - }, - "snapchat_plus": { - "name": "Snapchat Plus", - "description": "Membolehkan ciri Snapchat Plus\nBeberapa ciri pelayan mungkin tidak berfungsi" - }, - "media_upload_quality": { - "name": "Kualiti muat naik media", - "description": "Mengatasi kualiti muat naik media", - "properties": { - "force_video_upload_source_quality": { - "name": "Memaksa video memuat naik kualiti sumber", - "description": "Memaksa Snapchat untuk menggunakan kualiti sumber semasa memuat naik video\nSila ambil perhatian bahawa ini mungkin tidak mengeluarkan metadata dari media" - }, - "disable_image_compression": { - "name": "Lumpuhkan pemampatan imej", - "description": "Melumpuhkan mampatan imej semasa memuat naik media" - }, - "custom_image_upload_format": { - "name": "Format muat naik gambar tersuai", - "description": "Menetapkan format muat naik gambar tersuai\nPilih format lossless (seperti PNG) untuk kualiti terbaik" - } - } - }, - "disable_confirmation_dialogs": { - "name": "Lumpuhkan dialog pengesahan", - "description": "Mengesahkan tindakan yang dipilih secara automatik" - }, - "auto_updater": { - "name": "Pengemaskinian automatik", - "description": "Pemeriksaan secara automatik untuk kemas kini baru" - }, - "disable_metrics": { - "name": "Lumpuhkan metrik", - "description": "Blok Menghantar Data Analitik Khusus ke Snapchat" - }, - "disable_story_sections": { - "name": "Lumpuhkan bahagian cerita", - "description": "Mengeluarkan bahagian dari halaman cerita\nMungkin memerlukan penyegaran berfungsi dengan baik" - }, - "block_ads": { - "name": "Blok iklan", - "description": "Menghalang iklan daripada dipaparkan" - }, - "disable_custom_tabs": { - "name": "Lumpuhkan tab tersuai", - "description": "Membuka pautan dalam aplikasi yang disokong dan bukannya dalam penyemak imbas web" - }, - "disable_permission_requests": { - "name": "Lumpuhkan permintaan kebenaran", - "description": "Menghalang Snapchat daripada meminta kebenaran tertentu" - }, - "disable_memories_snap_feed": { - "name": "Lumpuhkan Kenangan Snap Feed", - "description": "Menghalang Snapchat daripada menunjukkan kenangan baru -baru ini apabila anda meleret ke kamera" - }, - "spotlight_comments_username": { - "name": "Comments Comments Nama Pengguna", - "description": "Menunjukkan Nama Pengguna Pengarang Dalam Komen Sorotan" - }, - "bypass_video_length_restriction": { - "name": "Potongan Latihan Panjang Video", - "description": "Bujang: Menghantar satu video\nSplit: Split Video setelah mengedit" - }, - "default_video_playback_rate": { - "name": "Kadar main balik video lalai", - "description": "Menetapkan kelajuan lalai untuk main balik video\nNilai mestilah antara 0.1 dan 4.0" - }, - "video_playback_rate_slider": { - "name": "Slider kadar main balik video", - "description": "Menambah gelangsar dalam menu konteks opera untuk menukar kadar main balik video\nNota: Perubahan hanya digunakan untuk video berikutnya" - }, - "disable_google_play_dialogs": { - "name": "Lumpuhkan Dialog Perkhidmatan Google Play", - "description": "Cegah dialog ketersediaan perkhidmatan Google Play dari yang ditunjukkan" - }, - "default_volume_controls": { - "name": "Kawalan kelantangan lalai", - "description": "Angkatan Snapchat untuk menggunakan kawalan kelantangan sistem" - }, - "disable_telecom_framework": { - "name": "Lumpuhkan rangka kerja telekom", - "description": "Menghalang Snapchat daripada menggunakan kerangka telekom Android\nIni membolehkan anda mendengar muzik semasa dalam panggilan" - }, - "hide_active_music": { - "name": "Menyembunyikan muzik aktif", - "description": "Menghalang Snapchat daripada mengetahui bahawa anda sedang mendengar muzik\nIni akan membolehkan anda mengambil snap menggunakan butang kelantangan kawalan semasa mendengar muzik" - }, - "disable_snap_splitting": { - "name": "Lumpuhkan pemisahan snap", - "description": "Menghalang snaps daripada dibahagikan kepada pelbagai bahagian\nGambar yang anda hantar akan menjadi video" - } - } - }, - "rules": { - "name": "Peraturan", - "description": "Mengurus ciri automatik untuk individu" - }, - "camera": { - "name": "Kamera", - "description": "Sesuaikan tetapan yang betul untuk snap yang sempurna", - "properties": { - "disable_cameras": { - "name": "Lumpuhkan kamera", - "description": "Menghalang Snapchat daripada menggunakan kamera yang dipilih" - }, - "black_photos": { - "name": "Foto hitam", - "description": "Menggantikan gambar yang ditangkap dengan latar belakang hitam\nVideo tidak terjejas" - }, - "immersive_camera_preview": { - "name": "Pratonton Immersive", - "description": "Menghalang Snapchat dari menanam pratonton kamera\nIni mungkin menyebabkan kamera berkedip pada beberapa peranti" - }, - "override_front_resolution": { - "name": "Mengatasi resolusi depan", - "description": "Mengatasi resolusi kamera untuk kamera depan" - }, - "override_back_resolution": { - "name": "Mengatasi resolusi belakang", - "description": "Mengatasi resolusi kamera untuk kamera belakang" - }, - "custom_resolution": { - "name": "Resolusi tersuai", - "description": "Menetapkan resolusi kamera tersuai, ketinggian x lebar (mis. 1920x1080).\nResolusi tersuai mesti disokong oleh peranti anda" - }, - "front_custom_frame_rate": { - "name": "Kadar bingkai tersuai depan", - "description": "Mengatasi kadar bingkai kamera depan" - }, - "back_custom_frame_rate": { - "name": "Kadar bingkai tersuai kembali", - "description": "Mengatasi kadar bingkai kamera belakang" - }, - "force_camera_source_encoding": { - "name": "Memaksa pengekodan sumber kamera", - "description": "Memaksa pengekodan sumber kamera" - }, - "startup_default_camera": { - "name": "Kamera lalai permulaan", - "description": "Menetapkan kamera lalai semasa membuka Snapchat" - }, - "hevc_recording": { - "name": "Rakaman HEVC", - "description": "Menggunakan codec HEVC (H.265) untuk rakaman video" - } - } - }, - "streaks_reminder": { - "name": "Peringatan Streaks", - "description": "Secara berkala memberitahu anda mengenai garis -garis anda", - "properties": { - "interval": { - "name": "Selang", - "description": "Selang antara setiap peringatan (jam)" - }, - "remaining_hours": { - "name": "Baki masa", - "description": "Baki masa sebelum pemberitahuan ditunjukkan (jam)" - }, - "group_notifications": { - "name": "Pemberitahuan Kumpulan", - "description": "Pemberitahuan kumpulan menjadi satu" - } - } - }, - "experimental": { - "name": "Eksperimen", - "description": "Ciri -ciri eksperimen", - "properties": { - "native_hooks": { - "name": "Cangkuk asli", - "description": "Ciri -ciri yang tidak selamat yang menyambung ke kod asli Snapchat", - "properties": { - "composer_hooks": { - "name": "Cangkuk komposer", - "description": "Suntikan kod ke dalam kerangka UI silang platform komposer", - "properties": { - "show_first_created_username": { - "name": "Tunjukkan Nama Pengguna Dibuat Pertama", - "description": "Menunjukkan nama pengguna pertama yang dibuat di sebelah nama pengguna semasa di halaman profil" - }, - "bypass_camera_roll_limit": { - "name": "Had roll kamera pintasan", - "description": "Meningkatkan jumlah maksimum media yang boleh anda hantar dari roll kamera" - }, - "custom_self_destruct_snap_delay": { - "name": "Kelewatan Snap Destruct tersuai tersuai", - "description": "Memberi lebih banyak pilihan untuk pemasa merosakkan diri semasa menghantar snap" - }, - "composer_console": { - "name": "Konsol Komposer", - "description": "Membolehkan anda melaksanakan kod JavaScript dalam komposer (ARM64 sahaja)" - }, - "composer_logs": { - "name": "Log komposer", - "description": "Pengalihan Log Konsol Komposer ke PurrFectSnap" - } - } - }, - "disable_bitmoji": { - "name": "Lumpuhkan Bitmoji", - "description": "Melumpuhkan profil rakan bitmoji" - }, - "custom_emoji_font": { - "name": "Font emoji adat", - "description": "Membolehkan anda menggunakan font emoji tersuai. Hanya berfungsi dengan fon .ttf" - }, - "custom_shared_library": { - "name": "Perpustakaan bersama tersuai", - "description": "Memuatkan perpustakaan bersama tersuai ke Snapchat. Ciri ini hanya untuk tujuan ujian" - } - } - }, - "spoof": { - "name": "Spoof", - "description": "Spoof pelbagai maklumat mengenai anda", - "properties": { - "play_store_installer_package_name": { - "name": "Main Nama Pakej Pemasang Kedai", - "description": "Mengatasi nama pakej pemasang ke com.android.vending" - }, - "remove_vpn_transport_flag": { - "name": "Keluarkan bendera pengangkutan VPN", - "description": "Menghalang Snapchat daripada mengesan VPN" - }, - "remove_mock_location_flag": { - "name": "Keluarkan bendera lokasi mengejek", - "description": "Menghalang Snapchat daripada mengesan lokasi mengejek" - } - } - }, - "convert_message_locally": { - "name": "Tukar mesej secara tempatan", - "description": "Menukar snap untuk berbual media luaran tempatan. Ini muncul dalam menu konteks muat turun sembang" - }, - "media_file_picker": { - "name": "Pemetik fail media", - "description": "Membolehkan anda memilih sebarang fail video/audio dari galeri" - }, - "story_logger": { - "name": "Logger cerita", - "description": "Menyediakan sejarah cerita rakan" - }, - "call_recorder": { - "name": "Panggilan perakam", - "description": "Merekodkan panggilan audio secara automatik" - }, - "account_switcher": { - "name": "Penukar akaun", - "description": "Membolehkan anda beralih antara akaun tanpa log keluar\nTekan panjang pada ikon carian di sebelah profil Bitmoji anda untuk membuka menu\nNota: Ciri ini adalah percubaan dan kemungkinan akan berubah pada masa akan datang", - "properties": { - "auto_backup_current_account": { - "name": "Akaun semasa sandaran automatik", - "description": "Secara automatik menyokong akaun semasa semasa log keluar atau menukar akaun" - } - } - }, - "better_transcript": { - "name": "Transkrip yang lebih baik", - "description": "Meningkatkan transkrip nota suara", - "properties": { - "force_transcription": { - "name": "Transkripsi nota suara daya", - "description": "Membolehkan semua nota suara disalin" - }, - "preferred_transcription_lang": { - "name": "Bahasa transkripsi yang lebih disukai", - "description": "Bahasa pilihan untuk transkrip nota suara (mis. En, es, fr)" - }, - "notification_transcript": { - "name": "Transkrip pemberitahuan", - "description": "Menyalin nota suara dalam pemberitahuan\nCiri ini memerlukan ciri pratonton sembang untuk didayakan dalam pemberitahuan yang lebih baik" - } - } - }, - "voice_note_auto_play": { - "name": "Nota Suara Auto Play", - "description": "Secara automatik memainkan nota suara seterusnya setelah selesai sekarang" - }, - "friend_notes": { - "name": "Nota rakan", - "description": "Membolehkan anda menambah nota kepada profil rakan" - }, - "cof_experiments": { - "name": "Eksperimen COF", - "description": "Membolehkan Ciri -ciri Snapchat/Beta Snapchat" - }, - "context_menu_fix": { - "name": "Menetapkan menu konteks", - "description": "Cuba membaiki menu suapan rakan seperti ketika peranti di luar talian ia tidak dapat dipaparkan dengan betul" - }, - "app_lock": { - "name": "Kunci aplikasi", - "description": "Menghalang akses ke snapchat tanpa kod laluan", - "properties": { - "lock_on_resume": { - "name": "Kunci resume", - "description": "Mengunci aplikasi apabila dibuka semula" - } - } - }, - "infinite_story_boost": { - "name": "Boost Story Infinite", - "description": "Memintas kelewatan had cerita cerita" - }, - "meo_passcode_bypass": { - "name": "Mata saya hanya memintas kod laluan", - "description": "Memintas mata saya hanya kod laluan\nIni hanya akan berfungsi jika kod laluan telah dimasukkan dengan betul sebelum ini" - }, - "no_friend_score_delay": { - "name": "Tiada kelewatan skor rakan", - "description": "Membuang kelewatan ketika melihat skor rakan" - }, - "best_friend_pinning": { - "name": "Kawan baik menyematkan", - "description": "Membolehkan anda memasukkan rakan sebagai sahabat nombor satu anda. Catatan: Hanya anda yang dapat melihat sahabat anda yang disandarkan" - }, - "e2ee": { - "name": "Penyulitan akhir-ke-akhir", - "description": "Menyulitkan mesej anda dengan AES menggunakan kunci rahsia bersama\nPastikan untuk menyimpan kunci anda di tempat yang selamat!", - "properties": { - "encrypted_message_indicator": { - "name": "Petunjuk mesej yang disulitkan", - "description": "Menambah emoji 🔒 di sebelah mesej yang disulitkan" - }, - "force_message_encryption": { - "name": "Penyulitan mesej", - "description": "Menghalang menghantar mesej yang disulitkan kepada orang yang tidak mempunyai enkripsi E2E diaktifkan hanya apabila berbilang perbualan dipilih" - } - } - }, - "add_friend_source_spoof": { - "name": "Tambah spoof sumber rakan", - "description": "Spoofs sumber permintaan rakan" - }, - "hidden_snapchat_plus_features": { - "name": "Ciri -ciri Snapchat Plus Tersembunyi", - "description": "Membolehkan ciri -ciri yang tidak dilepaskan/beta Snapchat Plus\nMungkin tidak berfungsi pada versi snapchat yang lebih tua" - }, - "custom_streaks_expiration_format": { - "name": "Format tamat tempoh coretan tersuai", - "description": "Menyesuaikan format tamat jalur\n\nPembolehubah yang tersedia:\n - %C: Kiraan Streaks\n - %E: Emoji Hourglass\n - %D: Hari\n - %H: Jam\n - %m: minit\n - %S: Seconds\n - %w: baki masa" - }, - "prevent_forced_logout": { - "name": "Mencegah logout paksa", - "description": "Menghalang Snapchat daripada melog masuk semasa anda log masuk ke peranti lain" - }, - "snapscore_changes": { - "name": "Perubahan snapscore", - "description": "Jejak Perubahan pada rakan Snapscore\nGunakan ciri ini dalam versi Snapchat yang lebih baru sahaja" - } - } - }, - "scripting": { - "name": "Skrip", - "description": "Jalankan skrip tersuai untuk melanjutkan purrfectsnap", - "properties": { - "developer_mode": { - "name": "Mod pemaju", - "description": "Menunjukkan maklumat debug mengenai UI Snapchat" - }, - "module_folder": { - "name": "Folder modul", - "description": "Folder di mana skrip berada" - }, - "auto_reload": { - "name": "Tambah nilai automatik", - "description": "Muat semula skrip secara automatik apabila mereka berubah" - }, - "integrated_ui": { - "name": "UI bersepadu", - "description": "Membolehkan skrip menambah komponen UI tersuai untuk snapchat" - }, - "disable_log_anonymization": { - "name": "Lumpuhkan Log Anonymization", - "description": "Melumpuhkan pengabaian balak" - }, - "disable_optimization": { - "name": "Lumpuhkan pengoptimuman", - "description": "Melumpuhkan pengoptimuman skrip. Ini boleh menyebabkan masalah prestasi." - } - } - }, - "friend_tracker": { - "name": "Pengesan rakan", - "description": "Rekod aktiviti rakan di Snapchat", - "properties": { - "record_messaging_events": { - "name": "Rekod peristiwa pemesejan", - "description": "Acara pemesejan rekod seperti membuka snap, membaca mesej, dll." - }, - "allow_running_in_background": { - "name": "Benarkan berjalan di latar belakang", - "description": "Membolehkan pelacak berjalan di latar belakang. Nota: Ini akan mengalirkan bateri dengan ketara" - }, - "auto_purge": { - "name": "Pembersihan auto", - "description": "Memadam peristiwa cache yang lebih tua daripada jumlah masa yang ditentukan" - } - } - } - }, - "options": { - "app_appearance": { - "always_light": "Sentiasa ringan", - "always_dark": "Selalu gelap" - }, - "friend_feed_menu_buttons": { - "auto_download": "⬇️ muat turun auto", - "auto_save": "💬 Mesej Simpan Auto", - "unsaveable_messages": "⬇️ Mesej yang tidak dapat disimpan", - "auto_open_snaps": "📷 Auto Open Snaps", - "stealth": "👻 Mod Stealth", - "mark_snaps_as_seen": "👀 Tandakan terkunci seperti yang dilihat", - "mark_stories_as_seen_locally": "👀 Tandakan cerita seperti yang dilihat secara tempatan", - "conversation_info": "👤 Maklumat perbualan", - "e2e_encryption": "🔒 Gunakan penyulitan E2E" - }, - "path_format": { - "create_author_folder": "Buat folder untuk setiap pengarang", - "create_source_folder": "Buat folder untuk setiap jenis sumber media", - "append_hash": "Tambahkan hash unik ke nama fail", - "append_source": "Tambahkan sumber media ke nama fail", - "append_username": "Tambahkan nama pengguna ke nama fail", - "append_date_time": "Tambahkan tarikh dan masa ke nama fail" - }, - "auto_download_sources": { - "friend_snaps": "Rakan terkena", - "friend_stories": "Cerita rakan", - "public_stories": "Cerita Awam", - "spotlight": "Tumpuan" - }, - "logging": { - "started": "Bermula", - "success": "Kejayaan", - "progress": "Kemajuan", - "failure": "Kegagalan" - }, - "notifications": { - "chat_screenshot": "Tangkapan skrin", - "chat_screen_record": "Rekod Skrin", - "snap_replay": "Snap Replay", - "camera_roll_save": "Simpan roll kamera", - "chat": "Berbual", - "chat_reply": "Balas sembang", - "snap": "Snap", - "typing": "Menaip", - "stories": "Cerita", - "speaking": "Bercakap", - "chat_reaction": "Reaksi DM", - "group_chat_reaction": "Tindak balas kumpulan", - "initiate_audio": "Panggilan audio masuk", - "abandon_audio": "Panggilan audio yang tidak dijawab", - "initiate_video": "Panggilan video masuk", - "abandon_video": "Panggilan video yang tidak dijawab", - "map_live_location": "Peta live lokasi" - }, - "gallery_media_send_override": { - "always_ask": "Selalu bertanya", - "ORIGINAL": "Media asal", - "NOTE": "Nota audio", - "SNAP": "Snap", - "SAVEABLE_SNAP": "Snap yang boleh diselamatkan" - }, - "strip_media_metadata": { - "hide_caption_text": "Menyembunyikan teks kapsyen", - "hide_snap_filters": "Sembunyikan penapis snap", - "hide_extras": "Sembunyikan tambahan (mis. Sebutan)", - "remove_audio_note_duration": "Keluarkan tempoh nota audio", - "remove_audio_note_transcript_capability": "Keluarkan keupayaan transkrip nota audio" - }, - "hide_ui_components": { - "hide_profile_call_buttons": "Keluarkan butang panggilan profil", - "hide_chat_call_buttons": "Keluarkan butang panggilan sembang", - "hide_live_location_share_button": "Keluarkan butang kongsi lokasi langsung", - "hide_stickers_button": "Keluarkan butang pelekat", - "hide_voice_record_button": "Keluarkan butang rekod suara", - "hide_unread_chat_hint": "Keluarkan petunjuk sembang belum dibaca", - "hide_post_to_story_buttons": "Keluarkan butang pos ke cerita sebelum menghantar snap", - "hide_billboard_prompt": "Keluarkan Billboard Prompt dalam Feed Friends", - "hide_snapchat_plus_gift_reminders": "Keluarkan snapchat ditambah peringatan hadiah dalam perbualan", - "hide_map_reactions": "Keluarkan reaksi peta" - }, - "hide_story_suggestions": { - "hide_suggested_friend_stories": "Menyembunyikan kisah rakan yang dicadangkan", - "hide_my_stories": "Sembunyikan cerita saya" - }, - "home_tab": { - "map": "Peta", - "chat": "Berbual", - "camera": "Kamera", - "discover": "Cari", - "spotlight": "Tumpuan" - }, - "add_friend_source_spoof": { - "added_by_username": "Oleh nama pengguna", - "added_by_mention": "Dengan sebutan", - "added_by_group_chat": "Oleh sembang kumpulan", - "added_by_qr_code": "Oleh kod QR", - "added_by_community": "Oleh komuniti", - "added_by_quick_add": "Dengan tambah cepat (risiko tinggi diharamkan)" - }, - "bypass_video_length_restriction": { - "single": "Media tunggal", - "split": "Media berpecah" - }, - "old_bitmoji_selfie": { - "2d": "2d Bitmoji", - "3d": "3d Bitmoji" - }, - "disable_confirmation_dialogs": { - "erase_message": "Memadam mesej", - "remove_friend": "Keluarkan rakan", - "block_friend": "Blok kawan", - "ignore_friend": "Abaikan rakan", - "hide_friend": "Menyembunyikan rakan", - "hide_conversation": "Menyembunyikan perbualan", - "clear_conversation": "Perbualan yang jelas dari Feed Rakan" - }, - "auto_reload": { - "snapchat_only": "Snapchat sahaja", - "all": "Semua (snapchat + purrfectsnap)" - }, - "edit_text_override": { - "multi_line_chat_input": "Input sembang berbilang baris", - "bypass_text_input_limit": "Memintas had input teks" - }, - "auto_purge": { - "never": "Tidak pernah", - "1_hour": "1 jam", - "3_hours": "3 jam", - "6_hours": "6 jam", - "12_hours": "12 jam", - "1_day": "1 hari", - "3_days": "3 hari", - "1_week": "1 minggu", - "2_weeks": "2 minggu", - "1_month": "1 bulan", - "3_months": "3 bulan", - "6_months": "6 bulan" - }, - "disable_story_sections": { - "friends": "Rakan", - "suggested_stories": "Cerita yang dicadangkan", - "following": "Berikut", - "discover": "Cari" - }, - "disable_cameras": { - "front": "Kamera depan", - "back": "Kamera belakang" - }, - "disable_permission_requests": { - "notifications": "Pemberitahuan", - "read_media_images": "Baca imej media", - "read_media_video": "Baca video media", - "camera": "Kamera", - "microphone": "Mikrofon", - "location": "Lokasi", - "read_contacts": "Baca kenalan", - "nearby_devices": "Peranti berdekatan", - "phone_calls": "Panggilan telefon" - }, - "message_indicators": { - "encryption_indicator": "Menambah ikon 🔒 di sebelah mesej yang hanya dihantar kepada anda", - "platform_indicator": "Menambah ikon platform dari mana media dihantar (mis. Android, iOS, Web)", - "location_indicator": "Menambah ikon 📍 untuk terkunci apabila mereka dihantar dengan lokasi yang diaktifkan", - "ovf_editor_indicator": "Menunjukkan jika snap telah dihantar menggunakan editor ovf", - "director_mode_indicator": "Menambah ikon ✏️ untuk terkunci apabila mereka dihantar menggunakan mod pengarah, yang boleh digunakan untuk menghantar imej galeri sebagai snaps" - }, - "auto_mark_as_read": { - "conversation_read": "Tandakan perbualan seperti dibaca semasa menghantar mesej", - "snap_reply": "Tanda Snaps seperti dibaca ketika membalasnya", - "save_snap_in_chat": "Tandakan Snaps Seperti yang dibaca ketika menyimpannya dalam sembang semasa dalam mod Stealth" - }, - "friend_mutation_notifier": { - "remove_friend": "Beritahu ketika seseorang menghilangkan anda sebagai kawan", - "birthday_changes": "Beritahu ketika seseorang mengubah hari lahir mereka", - "bitmoji_selfie_changes": "Beritahu ketika seseorang mengubah selfie bitmoji mereka", - "bitmoji_avatar_changes": "Beritahu ketika seseorang menukar avatar bitmoji mereka", - "bitmoji_background_changes": "Memberitahu apabila seseorang mengubah latar belakang bitmoji mereka", - "bitmoji_scene_changes": "Beritahu ketika seseorang mengubah adegan bitmoji mereka" - }, - "snapchat_plus": { - "not_subscribed": "Tidak melanggan", - "basic": "Asas", - "ad_free": "Iklan percuma" - }, - "double_tap_chat_action": { - "like_message": "Seperti mesej", - "copy_text": "Salin teks ke papan klip", - "delete_message": "Padam mesej", - "mark_as_read": "Tandakan sebagai baca", - "custom_emoji_reaction": "Reaksi emoji adat" - }, - "startup_default_camera": { - "front": "Kamera depan", - "back": "Kamera belakang" - } - } - }, - "friend_menu_option": { - "mark_snaps_as_seen": "Tandakan Snaps Seperti yang Dilihat", - "mark_stories_as_seen_locally": "Tandakan cerita seperti yang dilihat secara tempatan", - "preview": "Pratonton", - "stealth_mode": "Mod stealth", - "auto_download_blacklist": "Auto Muat turun Blacklist", - "anti_auto_save": "Anti Auto Simpan" - }, - "content_type": { - "CHAT": "Berbual", - "SNAP": "Snap", - "EXTERNAL_MEDIA": "Media luaran", - "NOTE": "Nota audio", - "STICKER": "Pelekat", - "SHARE": "Berkongsi", - "STATUS": "Status", - "LOCATION": "Lokasi", - "STATUS_SAVE_TO_CAMERA_ROLL": "Disimpan ke roll kamera", - "STATUS_CONVERSATION_CAPTURE_SCREENSHOT": "Tangkapan skrin", - "STATUS_CONVERSATION_CAPTURE_RECORD": "Rekod Skrin", - "STATUS_CALL_MISSED_VIDEO": "Panggilan video yang tidak dijawab", - "STATUS_CALL_MISSED_AUDIO": "Panggilan audio yang tidak dijawab", - "LIVE_LOCATION_SHARE": "Saham lokasi langsung", - "CREATIVE_TOOL_ITEM": "Item alat kreatif", - "FAMILY_CENTER_INVITE": "Jemputan Pusat Keluarga", - "FAMILY_CENTER_ACCEPT": "Pusat keluarga menerima", - "FAMILY_CENTER_LEAVE": "Cuti pusat keluarga", - "STATUS_PLUS_GIFT": "Status ditambah hadiah", - "TINY_SNAP": "Snap kecil", - "STATUS_COUNTDOWN": "Countdown", - "MAP_REACTION": "Reaksi MAP" - }, - "media_download_source": { - "none": "Tiada", - "pending": "Belum selesai", - "chat_media": "Media sembang", - "story": "Cerita", - "public_story": "Kisah awam", - "spotlight": "Tumpuan", - "profile_picture": "Gambar profil", - "story_logger": "Logger cerita", - "message_logger": "Logger mesej", - "merged": "Digabungkan", - "voice_call": "Panggilan suara" - }, - "chat_action_menu": { - "preview_button": "Pratonton", - "download_button": "Muat turun", - "delete_logged_message_button": "Padam mesej log", - "show_chat_edit_history": "Tunjukkan Sejarah Edit Sembang", - "convert_message": "Menukar mesej" - }, - "opera_context_menu": { - "download": "Muat turun media", - "sent_at": "Dihantar ke {date}", - "created_at": "Dibuat di {date}", - "expires_at": "Tamat pada {date}", - "media_size": "Saiz media: {size}", - "media_duration": "Tempoh media: {duration} ms", - "show_debug_info": "Tunjukkan maklumat debug" - }, - "modal_option": { - "profile_info": "Maklumat profil", - "close": "Tutup" - }, - "gallery_media_send_override": { - "multiple_media_toast": "Anda hanya boleh menghantar satu media pada satu masa" - }, - "mark_as_seen": { - "no_unseen_snaps_toast": "Tidak ada yang tidak dapat dilihat!", - "seen_toast": "Ditandakan seperti yang dilihat!", - "unseen_toast": "Ditandai sebagai tidak kelihatan!", - "already_seen_toast": "Sudah ditandakan seperti yang dilihat!", - "already_unseen_toast": "Sudah ditandakan sebagai tidak kelihatan!" - }, - "conversation_preview": { - "streak_expiration": "tamat tempoh {day} hari {hour} jam {minute} minit", - "total_messages": "Jumlah mesej yang dihantar/diterima: {count}", - "title": "Pratonton", - "unknown_user": "Pengguna yang tidak diketahui", - "no_messages": "Tiada mesej yang dijumpai!" - }, - "profile_info": { - "title": "Maklumat profil", - "first_created_username": "Nama pengguna pertama yang dibuat", - "mutable_username": "Nama Pengguna Mutable", - "display_name": "Nama paparan", - "added_date": "Tarikh ditambah", - "birthday": "Ulang tahun: {month} {day}", - "hidden_birthday": "Hari Lahir: Tersembunyi", - "friendship": "Persahabatan", - "add_source": "Tambah sumber", - "snapchat_plus": "Snapchat Plus", - "snapchat_plus_state": { - "subscribed": "Melanggan", - "not_subscribed": "Tidak melanggan" - } - }, - "friendship_link_type": { - "mutual": "Bersama", - "outgoing": "Keluar", - "blocked": "Disekat", - "deleted": "Dipadam", - "following": "Berikut", - "suggested": "Dicadangkan", - "incoming": "Masuk", - "incoming_follower": "Pengikut masuk" - }, - "bulk_messaging_action": { - "choose_action_title": "Pilih tindakan", - "progress_status": "Memproses {index} {total}", - "selection_dialog_continue_button": "Teruskan", - "confirmation_dialog": { - "title": "Adakah anda pasti?", - "message": "Ini akan menjejaskan semua rakan terpilih. Tindakan ini tidak dapat dibatalkan." - }, - "actions": { - "remove_friends": "Keluarkan rakan", - "clear_conversations": "Perbualan yang jelas" - } - }, - "chat_export": { - "exporter_dialog": { - "select_conversations_title": "Pilih perbualan", - "text_field_selection": "{amount} dipilih", - "text_field_selection_all": "Semua", - "export_file_format_title": "Format fail eksport", - "message_type_filter_title": "Tapis Mesej mengikut Jenis", - "amount_of_messages_title": "Jumlah mesej (biarkan kosong untuk semua)", - "download_medias_title": "Muat turun Media" - }, - "dialog_negative_button": "Batalkan", - "dialog_positive_button": "Eksport", - "exported_to": "Dieksport ke {path}", - "exporting_chats": "Mengeksport sembang ...", - "processing_chats": "Memproses {amount} perbualan ...", - "export_fail": "Gagal mengeksport perbualan {conversation}", - "writing_output": "Output menulis ...", - "finished": "Selesai! Anda kini boleh menutup dialog ini.", - "no_messages_found": "Tiada mesej yang dijumpai!", - "exporting_message": "Mengeksport {conversationName}..." - }, - "button": { - "ok": "Ok", - "positive": "Ya", - "negative": "Tidak", - "cancel": "Batalkan", - "open": "Buka", - "download": "Muat turun", - "send": "Hantar", - "restore_original": "Pulihkan asal", - "convert_external_media": "Tukar media luaran", - "save": "Simpan" - }, - "tracker_events": { - "conversation_enter": "Perbualan masuk", - "conversation_exit": "Keluar perbualan", - "started_typing": "Mula menaip", - "stopped_typing": "Berhenti menaip", - "started_speaking": "Mula bercakap", - "stopped_speaking": "Berhenti bercakap", - "started_peeking": "Mula mengintip", - "stopped_peeking": "Berhenti mengintip", - "message_read": "Mesej Baca", - "message_deleted": "Mesej dipadam", - "message_saved": "Mesej disimpan", - "message_unsaved": "Mesej yang tidak diselamatkan", - "message_edited": "Mesej diedit", - "message_reaction_add": "Tambah reaksi mesej", - "message_reaction_remove": "Reaksi mesej Buang", - "snap_opened": "Snap dibuka", - "snap_replayed": "Snap dimainkan semula", - "snap_replayed_twice": "Snap dimainkan semula dua kali", - "snap_screenshot": "Snap screenshot", - "snap_screen_record": "Rekod Skrin Snap" - }, - "tracker_actions": { - "log": "Log", - "in_app_notification": "Pemberitahuan dalam aplikasinya", - "push_notification": "Pemberitahuan tolak", - "custom": "Adat" - }, - "better_notifications": { - "button": { - "reply": "Balas", - "download": "Muat turun", - "mark_as_read": "Tandakan sebagai baca" - } - }, - "profile_picture_downloader": { - "button": "Muat turun gambar profil", - "title": "Pemuat gambar gambar profil", - "avatar_option": "Avatar", - "background_option": "Latar belakang" - }, - "call_start_confirmation": { - "dialog_title": "Mula panggilan", - "dialog_message": "Adakah anda pasti mahu memulakan panggilan?" - }, - "half_swipe_notifier": { - "notification_channel_name": "Separuh sapu", - "notification_content_dm": "{friend} Hadkan setengah swiped ke dalam sembang anda untuk {duration} saat", - "notification_content_group": "{friend} hanya setengah swiped ke {group} untuk {duration} saat" - }, - "download_processor": { - "attachment_type": { - "snap": "Snap", - "sticker": "Pelekat", - "gif": "Gif", - "external_media": "Media luaran", - "note": "Nota", - "original_story": "Cerita asal" - }, - "select_attachments_title": "Pilih lampiran", - "download_started_toast": "Muat turun bermula", - "unsupported_content_type_toast": "Jenis kandungan yang tidak disokong!", - "failed_no_longer_available_toast": "Media tidak lagi tersedia", - "no_attachments_toast": "Tiada lampiran dijumpai!", - "already_queued_toast": "Media sudah dalam barisan!", - "already_downloaded_toast": "Media sudah dimuat turun!", - "content_saved_toast": "Disimpan!", - "download_toast": "Memuat turun {friendlyName}...", - "processing_toast": "Memproses {friendlyName}...", - "failed_generic_toast": "Gagal memuat turun", - "failed_to_create_preview_toast": "Gagal membuat pratonton", - "failed_processing_toast": "Gagal pemprosesan {error}", - "failed_gallery_toast": "Gagal penjimatan ke galeri {error}", - "dash_no_chapter": "Tiada bab yang dijumpai", - "dash_dialog": { - "title": "Muat turun media dash", - "download_all": "Muat turun semua", - "segment_text": "Segmen {from} - {to}" - } - }, - "streaks_reminder": { - "notification_title": "Streaks", - "notification_text": "Anda akan kehilangan coretan anda dengan {friend} dalam jam {hoursLeft}" - }, - "biometric_auth": { - "unlock_button": "Buka kunci", - "title": "Buka kunci Snapchat", - "subtitle": "Sila sahkan untuk membuka kunci Snapchat" - }, - "end_to_end_encryption": { - "toolbox": { - "no_shared_key": "Anda belum mempunyai rahsia bersama rakan ini. Klik di bawah untuk memulakan yang baru.", - "shared_key_fingerprint": "Cap jari anda adalah:\n\n{fingerprint}\n\nPastikan untuk memeriksa sama ada ia sepadan dengan cap jari rakan anda!", - "initiate_exchange_button": "Memulakan pertukaran utama" - }, - "confirmation_dialogs": { - "title": "Penyulitan akhir-ke-akhir", - "confirmation_1": "Amaran: Ini akan menimpa kunci anda yang sedia ada. Anda akan kehilangan akses kepada semua mesej yang disulitkan dari rakan ini. Adakah anda pasti mahu meneruskan?", - "confirmation_2": "Adakah anda benar -benar pasti anda mahu meneruskan? Ini adalah peluang terakhir anda untuk mundur." - }, - "unencrypted_conversation_send_failure_toast": "Anda tidak boleh menghantar kandungan yang disulitkan kepada perbualan yang disulitkan dan tidak disulitkan!", - "native_hooks_send_failure_toast": "Gagal menghantar! Sila aktifkan cangkuk asli dalam tetapan.", - "no_participants_to_encrypt_toast": "Anda tidak mempunyai kawan dalam perbualan ini untuk menyulitkan mesej dengan!", - "encryption_failed_toast": "Gagal menyulitkan mesej! Semak LogCat untuk maklumat lanjut.", - "accept_public_key_success_toast": "Kunci awam berjaya diterima!", - "accept_secret_key_success_toast": "Selesai! Anda kini boleh menghantar dan menerima mesej yang disulitkan dengan rakan ini.", - "accept_public_key_failure_toast": "Gagal menerima kunci awam", - "accept_secret_key_failure_toast": "Gagal menerima kunci rahsia", - "accept_secret_button": "Terima rahsia", - "accept_public_key_button": "Terima kunci awam", - "outgoing_pk_message": "Permintaan pertukaran utama", - "outgoing_secret_message": "Tindak balas pertukaran utama", - "incoming_pk_message": "Anda baru sahaja menerima permintaan utama awam. Klik di bawah untuk menerimanya.", - "incoming_secret_message": "Rakan anda hanya menerima kunci awam anda. Klik di bawah untuk menerima rahsia." - }, - "auto_open_snaps": { - "title": "Auto Open Snaps", - "notification_content": "{count} Snaps dibuka" - }, - "friend_mutation_observer": { - "notification_channel_name": "Pemerhati Mutasi Rakan", - "friend_removed": "{username} telah menghapuskan anda sebagai kawan", - "birthday_removed": "{username} telah mengeluarkan hari lahir mereka ({birthday})", - "birthday_added": "{username} telah menambah hari lahir mereka ({birthday})", - "birthday_changed": "{username} telah mengubah hari lahir mereka dari {oldBirthday} ke {newBirthday}", - "bitmoji_selfie_changed": "{username} telah mengubah selfie bitmoji mereka", - "bitmoji_avatar_changed": "{username} telah menukar avatar bitmoji mereka", - "bitmoji_background_changed": "{username} telah mengubah latar belakang bitmoji mereka", - "bitmoji_scene_changed": "{username} telah mengubah adegan bitmoji mereka" - }, - "material3_strings": { - "date_range_picker_start_headline": "Dari", - "date_range_picker_end_headline": "Ke", - "date_range_picker_title": "Pilih julat tarikh", - "date_picker_switch_to_calendar_mode": "Kalendar", - "date_picker_switch_to_input_mode": "Input", - "date_range_picker_scroll_to_previous_month": "Bulan sebelumnya", - "date_range_picker_scroll_to_next_month": "Bulan depan", - "date_picker_today_description": "Hari ini", - "date_range_picker_day_in_range": "Dipilih", - "date_input_invalid_for_pattern": "Tarikh tidak sah", - "date_input_invalid_year_range": "Tahun tidak sah", - "date_input_invalid_not_allowed": "Tarikh tidak sah", - "date_range_input_invalid_range_input": "Julat tarikh tidak sah" - }, - "send_override_dialog": { - "title": "Hantar media sebagai {type}", - "duration": "Tempoh: {duration}", - "saveable_snap_hint": "Jadikan snap boleh diselamatkan dalam sembang", - "unlimited_duration": "Tidak terhad" - }, - "invalid_input_toast": "Input tidak sah! Pastikan anda memasukkan nilai yang sah." -} \ No newline at end of file diff --git a/common/src/main/assets/lang/nb_NO.json b/common/src/main/assets/lang/nb_NO.json new file mode 100644 index 00000000..e42d193d --- /dev/null +++ b/common/src/main/assets/lang/nb_NO.json @@ -0,0 +1,211 @@ +{ + "manager": { + "routes": { + "home_logs": "Loggføring", + "scripts": "Skript", + "home_settings": "Innstillinger", + "features": "Funksjoner", + "home": "Hjem", + "tasks": "Gjøremål", + "logger_history": "Loggføringshistorie", + "logged_stories": "Loggede historier", + "messaging_preview": "Forhåndsvisning", + "social": "Sosialt", + "manage_scope": "Administrer omfang", + "better_location": "Bedre Posisjon", + "file_imports": "Fil-importer", + "edit_rule": "Rediger Regel", + "friend_tracker": "Vennesporing" + }, + "sections": { + "social": { + "streaks_expiration_short": "{hours}t", + "friends_tab": "Venner", + "groups_tab": "Grupper", + "empty_hint": "(tom)" + }, + "features": { + "disabled": "Deaktivert", + "config_import_success_toast": "Importering av konfigurasjon vellykket", + "config_export_success_toast": "Eksportering av konfigurasjon vellykket", + "export_option": "Eksporter", + "reset_option": "Tilbakestill", + "config_import_failure_toast": "Feil under importering av konfigurasjon {error}", + "config_export_failure_toast": "Feil under eksportering av konfigurasjon {error}", + "saved_config_snackbar": "Konfigurasjon lagret", + "import_option": "Importer" + }, + "tasks": { + "no_tasks": "Ingen gjøremål", + "remove_all_tasks_title": "Er du sikker på at du vil fjerne alle gjøremål?", + "failed_to_open_file": "Feil under åpning av fil", + "merge_files_toast": "Slår sammen {count} filer", + "remove_selected_tasks_title": "Er du sikker på at du vil fjerne valgte gjøremål?", + "delete_files_option": "Slett filer også", + "remove_selected_tasks_confirm": "Fjern {count} gjøremål?", + "remove_all_tasks_confirm": "Fjern alle gjøremål?" + }, + "home": { + "update_content": "Versjon {versjon} er tilgjengelig!", + "update_button": "Last ned", + "update_title": "SnapEnhance Oppdatering", + "debug_build_summary_title": "Du kjører et feilsøkingsbyggversjon av SnapEnhance", + "debug_build_summary_date": "Byggversjonsdato: {date} ({days} dager siden)", + "quick_actions_title": "Kjappe Handlinger", + "debug_build_summary_content": "Versjon {versionName} ({versionCode})", + "version_title": "v{versionName} · av eternal" + }, + "home_logs": { + "no_logs_hint": "Ingen logger tilgjengelig", + "clear_logs_button": "Slett Logg", + "export_logs_button": "Eksporter Logg", + "saving_logs_toast": "Lagrer logg, dette kan ta en stund ...", + "saved_logs_success_toast": "Logg lagret vellykket", + "saved_logs_failure_toast": "Feil under lagring av logg" + }, + "home_settings": { + "actions_title": "Handlinger", + "success_toast": "Ferdig!", + "message_logger_summary": "{messageCount} meldinger\n{storyCount} historier", + "message_logger_title": "Meldingslogger", + "export_button": "Eksporter", + "clear_button": "Rensk", + "view_logger_history_button": "Se logghistorikk", + "debug_title": "Feilsøking" + }, + "manage_scope": { + "logged_stories_button": "Vis loggede historier", + "streaks_expiration_text_expired": "Utgått", + "e2ee_title": "Ende-til-ende-kryptering", + "streaks_length_text": "Lengde: {length}", + "streaks_expiration_text": "Utgår om {eta}", + "delete_scope_confirm_dialog_title": "Er du sikker på at du vil slette en {scope}?", + "rules_title": "Regler", + "streaks_title": "Streaks", + "reminder_button": "Sett påminnelse", + "participants_text": "{count} deltakere", + "not_found": "Ikke funnet" + }, + "logged_stories": { + "story_failed_to_load": "Feil under lasting", + "no_stories": "Ingen historier funnet" + } + }, + "dialogs": { + "add_friend": { + "search_hint": "Søk", + "category_friends": "Venner", + "category_groups": "Grupper", + "title": "Legg til venn eller gruppe", + "fetch_error": "Kunne ikke hente data" + }, + "scripting_warning": { + "title": "Advarsel", + "content": "SnapEnhance inkluderer et skriptverktøy som tillater utføring av brukerdefinert kode på enheten din. Vær ekstremt forsiktig og installer kun moduler fra kjente, pålitelige kilder. Uautoriserte eller uverifiserte moduler kan utgjøre sikkerhetsrisikoer for systemet ditt." + } + } + }, + "setup": { + "mappings": { + "dialog": "For å dynamisk støtte et bredt spekter av Snapchat-versjoner, er kartlegging nødvendig for at SnapEnhance skal fungere ordentlig, dette bør ikke ta mer enn 5 sekunder.", + "generate_failure_no_snapchat": "SnapEnhance kunne ikke oppdage Snapchat, prøv å installere Snapchat på nytt.", + "generate_failure": "Det oppstod en feil under forsøk på å generere kartlegginger. Prøv igjen." + }, + "dialogs": { + "select_save_folder_button": "Velg mappe", + "select_language": "Velg språk", + "save_folder": "SnapEnhance krever lagrings tillatelser for og laste ned og lagre media fra snapchaf. Vennligst velg hvor filene skal lagres" + }, + "permissions": { + "battery_optimization": "Batterioptimalisering", + "display_over_other_apps": "Vis over andre apper", + "notification_access": "Varslingstilgang", + "request_button": "Forespør", + "dialog": "For å fortsette må du oppfylle følgende krav:" + } + }, + "rules": { + "modes": { + "blacklist": "Svartelistingsmodus", + "whitelist": "Hvitlistingsmodus" + }, + "properties": { + "auto_save": { + "options": { + "whitelist": "Automatisk lagring", + "blacklist": "Ekskluder fra Automatisk lagring" + }, + "name": "Automatisk lagring", + "description": "Lagrer chatmeldinger når du ser dem" + }, + "auto_download": { + "name": "Automatisk nedlasting", + "options": { + "blacklist": "Ekskluder fra Automatisk nedlasting", + "whitelist": "Automatisk nedlasting" + }, + "description": "Automatisk last ned snapper når du ser dem" + }, + "unsaveable_messages": { + "name": "Meldinger som ikke kan lagres", + "description": "Forhindrer meldinger fra å bli lagret i chat av andre personer", + "options": { + "blacklist": "Ekskluder fra Meldinger som ikke kan lagres" + } + }, + "stealth": { + "description": "Forhindrer noen fra å vite at du har åpnet snappene/chattene og samtalene dems", + "options": { + "whitelist": "Smugmodus", + "blacklist": "Ekskluder fra smugmodus" + }, + "name": "Smugmodus" + } + }, + "toasts": { + "disabled": "{ruleName} deaktivert", + "enabled": "{ruleName} aktivert" + } + }, + "features": { + "properties": { + "downloader": { + "properties": { + "ffmpeg_options": { + "properties": { + "video_bitrate": { + "name": "Videobitrate", + "description": "Sett videobitraten (kbps)" + }, + "threads": { + "name": "Tråder" + }, + "audio_bitrate": { + "name": "Lydbitrate", + "description": "Sett lydbitraten (kbps)" + }, + "custom_video_codec": { + "name": "Egendefinert videokodek" + } + } + } + } + }, + "user_interface": { + "properties": { + "bootstrap_override": { + "properties": { + "home_tab": { + "name": "Hjemmefane" + } + } + } + } + } + } + }, + "scopes": { + "friend": "Venn", + "group": "Gruppe" + } +} diff --git a/common/src/main/assets/lang/nl.json b/common/src/main/assets/lang/nl.json index 15256399..19a3b921 100644 --- a/common/src/main/assets/lang/nl.json +++ b/common/src/main/assets/lang/nl.json @@ -1,2022 +1,461 @@ { "setup": { "dialogs": { - "select_language": "Selecteer Taal", - "save_folder": "PurrfectSnap vereist opslagrechten om media van Snapchat te downloaden en op te slaan.\nKies de locatie waar media naartoe moeten worden gedownload.", + "select_language": "Taal Selecteren", + "save_folder": "SnapEnhance vereist opslagrechten om media van Snapchat te downloaden en op te slaan.\nKies de downloadlocatie.", "select_save_folder_button": "Selecteer Map" }, "mappings": { - "dialog": "Het genereren van toewijzingen, dit kan even duren...", - "generate_failure_no_snapchat": "PurrfectSnap kon Snapchat niet detecteren. Probeer Snapchat opnieuw te installeren.", - "generate_failure": "Er is een fout opgetreden bij het genereren van toewijzingen. Probeer het opnieuw." + "dialog": "Calibreren, dit kan even duren...", + "generate_failure_no_snapchat": "SnapEnhance kon Snapchat niet detecteren, probeer Snapchat opnieuw te installeren.", + "generate_failure": "Er is een fout opgetreden tijdens het calibreren, probeer het opnieuw." }, "permissions": { - "dialog": "Om door te gaan, moet u aan de volgende vereisten voldoen:", + "dialog": "Om door te gaan moet je voldoen aan de volgende vereisten:", "notification_access": "Toegang tot meldingen", - "battery_optimization": "Batterij-optimalisatie", - "display_over_other_apps": "Weergave via andere apps", - "request_button": "Verzoek" + "battery_optimization": "Accu optimalisatie", + "display_over_other_apps": "Weergeven vóór andere apps", + "request_button": "Aanvraag" } }, - "scopes": { - "friend": "Vriend", - "group": "Groep" - }, "manager": { "routes": { - "tasks": "Taken", "features": "Functies", - "manage_rule_feature": "Regelfunctie beheren", - "home": "Thuis", + "home": "Startscherm", "home_settings": "Instellingen", - "home_logs": "Logboeken", - "logger_history": "Logboekgeschiedenis", - "logged_stories": "Gelogde verhalen", - "friend_tracker": "Vriendentracker", - "edit_rule": "Regel bewerken", - "file_imports": "Bestanden importeren", - "manage_repos": "Beheer opslagplaatsen", + "home_logs": "Logs", "social": "Sociaal", - "manage_scope": "Beheer bereik", - "messaging_preview": "Voorbeeld", "scripts": "Scripts", - "better_location": "Betere locatie" + "manage_scope": "Scope beheren", + "messaging_preview": "Voorbeeld", + "tasks": "Taken", + "logger_history": "Log geschiedenis", + "logged_stories": "Gelogde Stories", + "friend_tracker": "Vrienden vinder", + "edit_rule": "Regel bewerken", + "better_location": "Betere Locatie", + "file_imports": "Geïmporteerde bestanden", + "theming": "Thema's", + "edit_theme": "Thema bewerken", + "manage_repos": "Repositories Beheren" }, "sections": { - "home": { - "version_title": "v{versionName} · gevorkt door Eternal", - "update_title": "PurrfectSnap-update", - "update_content": "Versie {version} is beschikbaar!", - "update_button": "Downloaden", - "debug_build_summary_title": "U voert een debug-build van PurrfectSnap uit", - "debug_build_summary_content": "Versie {versionName} ({versionCode})", - "debug_build_summary_date": "Bouwdatum: {date} ({days} dagen geleden)", - "quick_actions_title": "Snelle acties", - "download_icon_description": "Downloaden", - "completed_icon_description": "Voltooid", - "failed_icon_description": "Mislukt", - "manage_quick_actions_description": "Beheer snelle acties", - "quick_actions_icon_description": "Snelle acties", - "add_quick_action_description": "Voeg snelle actie toe" + "features": { + "disabled": "Uitgeschakeld", + "export_option": "Exporteer", + "import_option": "Impoteer", + "reset_option": "Opnieuw instellen", + "config_export_success_toast": "Config succesvol geëxporteerd", + "config_import_success_toast": "Config succesvol geïmporteerd", + "config_import_failure_toast": "Gefaald om config te importeren {error}", + "saved_config_snackbar": "Config opgeslagen", + "config_export_failure_toast": "Configuratie kan niet worden geëxporteerd {error}" }, - "home_logs": { - "no_logs_hint": "Geen logboeken beschikbaar", - "clear_logs_button": "Logboeken wissen", - "export_logs_button": "Logboeken exporteren", - "saving_logs_toast": "Logboeken opslaan, dit kan even duren...", - "saved_logs_success_toast": "Logboeken zijn succesvol opgeslagen", - "saved_logs_failure_toast": "Kan logboeken niet opslaan" - }, - "home_settings": { - "actions_title": "Acties", - "message_logger_title": "Berichtenlogger", - "debug_title": "Foutopsporing", - "success_toast": "Klaar!", - "message_logger_summary": "{messageCount} berichten\n{storyCount} verhalen", - "export_button": "Exporteren", - "clear_button": "Duidelijk", - "view_logger_history_button": "Loggergeschiedenis bekijken", - "updates_title": "Updates", - "auto_update_check": "Automatische controle op updates", - "update_check_frequency": "Controlefrequentie bijwerken", - "update_check_frequency_daily": "Dagelijks", - "update_check_frequency_weekly": "Wekelijks", - "update_check_frequency_monthly": "Maandelijks", - "theme_icon_description": "Thema", - "app_theme_title": "App-thema", - "theme_mode_system": "Systeem", - "theme_mode_light": "Licht", - "theme_mode_dark": "Donker", - "ui_settings_title": "UI-instellingen", - "haptic_feedback_label": "Haptische feedback", - "test_mode_label": "Testmodus (ALLEEN VOOR DEBUGGING)", - "disable_feature_loading_label": "Schakel het laden van functies uit", - "disable_auto_mapper_label": "Schakel Auto Mapper uit", - "disable_bypass_indicator_label": "Schakel de bypass-statusindicator uit", - "update_notification_channel_name": "PurrfectSnap-updates", - "update_notification_channel_description": "Meldingen voor PurrfectSnap-updates", - "update_notification_title": "PurrfectSnap-update beschikbaar", - "update_notification_text": "Versie {version} is nu beschikbaar.", - "export_database_failed_toast": "Kan de database niet exporteren! {message}", - "clear_messages_failed_toast": "Kan berichten niet wissen! {message}", - "clear_file_failed_toast": "Kan het bestand niet wissen! {message}", - "debug_file_config": "Configuratie", - "debug_file_mappings": "Toewijzingen", - "debug_file_message_logger": "Berichtenlogger", - "debug_file_pinned_best_friend": "Beste vriend vastgemaakt", - "debug_file_native_sig_cache": "Native handtekeningcache" + "social": { + "streaks_expiration_short": "{hours}u", + "friends_tab": "Vrienden", + "groups_tab": "Groepen", + "empty_hint": "(leeg)" }, "tasks": { "no_tasks": "Geen taken", - "merge_button": "Samenvoegen", - "failed_to_open_file": "Kan bestand niet openen", - "merge_files_toast": "{count} bestanden samenvoegen", - "remove_selected_tasks_title": "Weet u zeker dat u geselecteerde taken wilt verwijderen?", - "remove_all_tasks_title": "Weet u zeker dat u alle taken wilt verwijderen?", - "delete_files_option": "Verwijder ook bestanden", + "remove_all_tasks_confirm": "Verwijder alle taken?", + "remove_selected_tasks_title": "Weet je zeker dat je de geselecteerde taak wilt verwijderen?", + "remove_all_tasks_title": "Weet je zeker dat je alle taken wilt verwijderen?", + "merge_files_toast": "{count} bestand(en) samenvoegen", "remove_selected_tasks_confirm": "{count} taken verwijderen?", - "remove_all_tasks_confirm": "Alle taken verwijderen?", - "clear_tasks_description": "Duidelijke taken", - "file_not_found_icon_description": "Bestand niet gevonden", - "image_icon_description": "Afbeelding", - "video_icon_description": "Video", - "audio_icon_description": "Audio", - "file_icon_description": "Bestand", - "download_icon_description": "Downloaden", - "chat_action_icon_description": "Chat-actie", - "cancel_icon_description": "Annuleren", - "success_icon_description": "Succes", - "failure_icon_description": "Mislukking", - "cancelled_icon_description": "Geannuleerd", - "task_status_failure": "Mislukking", - "task_status_cancelled": "Geannuleerd" + "delete_files_option": "Verwijderen ook bestanden", + "failed_to_open_file": "Bestand kan niet worden geopend" }, - "features": { - "disabled": "Gehandicapt", - "export_option": "Exporteren", - "import_option": "Importeren", - "reset_option": "Opnieuw instellen", - "config_export_success_toast": "Configuratie succesvol geëxporteerd", - "config_import_success_toast": "Configuratie succesvol geïmporteerd", - "config_import_failure_toast": "Kan configuratie {error} niet importeren", - "config_export_failure_toast": "Kan configuratie {error} niet exporteren", - "saved_config_snackbar": "Configuratie opgeslagen", - "older_required": "Deze functie vereist dat Snapchat v{version} of ouder correct werkt", - "newer_required": "Deze functie vereist dat Snapchat v{version} of nieuwer correct werkt", - "search_button": "Zoekopdracht" + "home": { + "update_title": "SnapEnhance Update", + "update_content": "Versie {versie} is beschikbaar!", + "update_button": "Download", + "version_title": "v{versionName} · door eternal", + "debug_build_summary_title": "Je gebruikt een debug versie van SnapEnhance", + "debug_build_summary_content": "Versie {versionName} ({versionCode})", + "debug_build_summary_date": "Build datum: {date} ({days} dagen geleden)", + "quick_actions_title": "Snelle Acties" }, - "manage_rule_feature": { - "disable_state_option": "Gehandicapt", - "disable_state_subtext": "Er worden geen vrienden/groepen beïnvloed", - "whitelist_state_option": "Niemand behalve...", - "whitelist_state_subtext": "Alleen {count} vrienden/groepen vallen onder deze regel", - "whitelist_state_button": "Selecteer toegestane vrienden/groepen", - "blacklist_state_option": "Iedereen behalve...", - "blacklist_state_subtext": "Deze regel geldt voor iedereen behalve {count} vrienden/groepen", - "blacklist_state_button": "Selecteer uitgesloten vrienden/groepen", - "clear_list_button": "Wis de lijst met vrienden/groepen", - "dialog_clear_confirmation_text": "Weet u zeker dat u de lijst wilt wissen?" + "home_logs": { + "no_logs_hint": "Geen logs beschikbaar", + "export_logs_button": "Exporteer logs", + "saving_logs_toast": "Logs opslaan, dit kan een ogenblik duren ...", + "saved_logs_success_toast": "Logs opslagen gelukt", + "saved_logs_failure_toast": "Gefaald om logs op te slaan", + "clear_logs_button": "Logs wissen" }, - "social": { - "friends_tab": "Vrienden", - "groups_tab": "Groepen", - "empty_hint": "(leeg)", - "streaks_expiration_short": "{hours}h" + "home_settings": { + "actions_title": "Acties", + "message_logger_title": "Berichten logger", + "success_toast": "Klaar!", + "export_button": "Exporteren", + "debug_title": "Debug", + "view_logger_history_button": "Bekijk Logs Geschiedenis", + "message_logger_summary": "{messageCount} berichten\n{storyCount} verhalen", + "clear_button": "Wissen" }, "manage_scope": { - "logged_stories_button": "Toon ingelogde verhalen", - "e2ee_title": "End-to-end-codering", + "logged_stories_button": "Toon gelogde verhalen", + "e2ee_title": "Eind-tot-eind encryptie", "rules_title": "Regels", - "participants_text": "{count} deelnemers", + "participants_text": "{aantal} deelnemers", "not_found": "Niet gevonden", - "streaks_title": "Strepen", - "streaks_length_text": "Lengte: {length}", - "streaks_expiration_text": "Verloopt over {eta}", + "streaks_title": "Reeksen", + "streaks_length_text": "Lengte: {lengte}", + "streaks_expiration_text": "Verloopt in {eta}", "streaks_expiration_text_expired": "Verlopen", - "reminder_button": "Herinnering instellen", - "delete_scope_confirm_dialog_title": "Weet u zeker dat u een {scope} wilt verwijderen?", - "notes_placeholder": "Klik om een ​​notitie toe te voegen", - "invalid_key_size_32_bytes": "Ongeldige sleutelgrootte (moet 32 ​​bytes zijn)", - "successfully_imported_key": "Sleutel geïmporteerd", - "failed_to_import_key": "Kan sleutel niet importeren: {message}", - "export_base64_button": "Base64 exporteren", - "import_base64_button": "Importeer Base64" + "reminder_button": "Zet herinnering", + "delete_scope_confirm_dialog_title": "Weet u zeker dat u {scope} wilt verwijderen?" }, "logged_stories": { - "story_failed_to_load": "Kan niet laden", + "story_failed_to_load": "Gefaald om te laden", "no_stories": "Geen verhalen gevonden", - "save_from_cache_button": "Opslaan uit cache", - "downloaded_to_path": "Gedownload naar {path}", - "download_failed": "Downloaden mislukt: {message}", - "posted_at": "Geplaatst op {date}", - "created_at": "Gemaakt op {date}", - "failed_to_open_file": "Kan bestand niet openen. Controleer logboeken voor meer informatie", - "failed_to_get_file": "Kan bestand niet ophalen" + "save_from_cache_button": "Opslaan uit Cache" }, "messaging_preview": { - "processed_messages_toast": "{count} berichten verwerkt", - "processed_messages_text": "{count} berichten verwerkt", - "close_button_description": "Dichtbij", - "bridge_connection_failed": "Kan geen verbinding maken met de bridge. Zorg ervoor dat Snapchat op de achtergrond actief is", - "bridge_init_failed": "Kan de berichtenbrug niet initialiseren. Zorg ervoor dat Snapchat op de achtergrond actief is", - "message_fetch_failed": "Kan berichten niet ophalen", + "message_fetch_failed": "Gefaald op berichten op te halen", "no_message_hint": "Geen bericht", "save_selection_option": "Selectie opslaan", - "save_all_option": "Bewaar alles", + "save_all_option": "Alles Opslaan", + "mark_selection_as_seen_option": "Snap selecteren als gezien", + "bridge_connection_failed": "Kan geen verbinding maken met de brug. Zorg dat Snapchat op de achtergrond aanstaat", + "bridge_init_failed": "Kan de berichtenbrug niet initialiseren. Zorg dat Snapchat op de achtergrond aanstaat", "unsave_selection_option": "Selectie niet opslaan", "unsave_all_option": "Alles niet opslaan", - "mark_selection_as_seen_option": "Markeer de geselecteerde Snap zoals gezien", - "mark_all_as_seen_option": "Markeer alle Snaps zoals gezien", + "mark_all_as_seen_option": "Markeer alle Snaps als gezien", "delete_selection_option": "Selectie verwijderen", "delete_all_option": "Alles verwijderen" }, "logger_history": { - "download_started_toast": "Downloaden gestart!", - "download_success_toast": "Gedownload naar {path}", - "download_failed_toast": "Kan {message} niet downloaden", - "edited_at_text": "{message} (bewerkt op {date})", - "download_button": "Downloaden", - "select_conversation_placeholder": "Selecteer een gesprek", - "close_button_description": "Dichtbij", - "search_button_description": "Zoekopdracht", + "reverse_order_checkbox": "Omgekeerde Volgorde", "list_friend_format": "Vriend {name}", "list_group_format": "Groep {name}", "no_more_messages": "Geen berichten meer", - "reverse_order_checkbox": "Omgekeerde volgorde", "chat_attachment": "Bijlage {index}", "empty_message": "Leeg chatbericht", "message_parse_failed": "Kan het bericht niet parseren", - "unknown_sender": "Onbekende afzender", - "download_attachment_failed_toast": "Kan bijlage niet downloaden", - "log_header_format": "{username} ({type}) - {date}" - }, - "file_imports": { - "import_file_button": "Bestand importeren", - "file_not_found": "Bestand niet gevonden", - "file_import_failed": "Kan bestand niet importeren: {error}", - "file_imported": "Bestand geïmporteerd", - "file_delete_failed": "Kan bestand niet verwijderen", - "no_files_hint": "Hier kun je bestanden importeren voor gebruik in Snapchat. Druk op onderstaande knop om een ​​bestand te importeren." + "unknown_sender": "Onbekende Afzender", + "download_attachment_failed_toast": "Kan bijlage niet downloaden" }, "better_location": { - "spoofed_coordinates_title": "Lat {latitude}, Lng {longitude}", - "save_coordinates_dialog_title": "Coördinaten opslaan", - "saved_name_dialog_hint": "Opgeslagen naam", - "latitude_dialog_hint": "Breedte", - "longitude_dialog_hint": "Lengte", - "save_dialog_button": "Redden", - "choose_location_button": "Kies Locatie", - "teleport_to_friend_button": "Teleporteren naar vriend", - "spoof_location_toggle": "Spoof-locatie", - "suspend_location_updates": "Locatie-updates opschorten", - "saved_coordinates_title": "Opgeslagen coördinaten", - "no_saved_coordinates_hint": "Geen opgeslagen coördinaten", - "delete_dialog_title": "Verwijder opgeslagen coördinaten", - "delete_dialog_message": "Weet u zeker dat u deze opgeslagen coördinaat wilt verwijderen?", - "teleport_to_friend_title": "Teleporteren naar vriend", - "search_bar": "Zoekopdracht", - "no_friends_map": "Geen vrienden op de kaart", + "save_dialog_button": "Opslaan", + "save_coordinates_dialog_title": "Coördinaten Opslaan", + "saved_name_dialog_hint": "Naam Opgeslagen", + "delete_dialog_title": "Verwijder Opgeslagen Coördinaat", + "latitude_dialog_hint": "Latitude", + "longitude_dialog_hint": "Longitude", + "spoof_location_toggle": "Locatie Spoofen", + "choose_location_button": "Locatie Kiezen", + "teleport_to_friend_button": "Teleporteer naar Vriend", "no_friends_found": "Geen vrienden gevonden", - "edit_location_button_description": "Locatie bewerken", - "add_icon_description": "Toevoegen", - "edit_icon_description": "Bewerking", - "delete_icon_description": "Verwijderen" + "suspend_location_updates": "Locatie Updates Pauzeren", + "saved_coordinates_title": "Coördinaten Opgeslagen", + "no_saved_coordinates_hint": "Geen opgeslagen coördinaten", + "delete_dialog_message": "Weet je zeker dat je dit opgeslagen coördinaat wilt verwijderen?", + "teleport_to_friend_title": "Teleporteer naar Vriend", + "spoofed_coordinates_title": "Lat {latitude}, Lng {longitude}", + "search_bar": "Zoeken", + "no_friends_map": "Geen vrienden op de kaart" + }, + "file_imports": { + "file_not_found": "Bestand niet gevonden", + "file_import_failed": "Bestand kan niet worden geïmporteerd: {error}", + "file_delete_failed": "Bestand kan niet worden verwijderd", + "file_imported": "Bestand succesvol geïmporteerd", + "no_files_hint": "Hier kan je bestanden importeren om in Snapchat te gebruiken. Druk op de onderstaande knop om een bestand te importeren.", + "import_file_button": "Bestand Importeren" + }, + "theming": { + "no_themes_hint": "Geen thema's gevonden" } }, "dialogs": { "add_friend": { "title": "Vriend of groep toevoegen", - "search_hint": "Zoekopdracht", + "search_hint": "Zoeken", "fetch_error": "Kan gegevens niet ophalen", "category_groups": "Groepen", - "category_friends": "Vrienden", - "participants_text": "{count} deelnemers", - "search_icon_description": "Zoekopdracht" + "category_friends": "Vrienden" }, "scripting_warning": { "title": "Waarschuwing", - "content": "PurrfectSnap bevat een scripttool waarmee door de gebruiker gedefinieerde code op uw apparaat kan worden uitgevoerd. Wees uiterst voorzichtig en installeer alleen modules van bekende, betrouwbare bronnen. Niet-geautoriseerde of niet-geverifieerde modules kunnen veiligheidsrisico's voor uw systeem opleveren." + "content": "SnapEnhance bevat een scripting-tool, waarmee door de gebruiker gedefinieerde code op uw apparaat kan worden uitgevoerd. Wees uiterst voorzichtig en installeer alleen modules van bekende, betrouwbare bronnen. Niet-geautoriseerde of niet-geverifieerde modules kunnen beveiligingsrisico's voor uw systeem opleveren." }, "reset_config": { "title": "Configuratie resetten", "content": "Weet u zeker dat u de configuratie wilt resetten?", - "success_toast": "Configuratie-reset succesvol" - }, - "export_config": { - "title": "Gevoelige gegevens exporteren?", - "content": "Wilt u de configuratie met gevoelige gegevens exporteren? (Zoals locatiecoördinaten, enz.)" + "success_toast": "Configuratie succesvol gereset" }, "messaging_action": { "title": "Kies inhoudstypen om te verwerken", - "select_all_button": "Selecteer Alles" + "select_all_button": "Alles Selecteren" + }, + "export_config": { + "content": "Wil je de configuratie met gevoelige data exporteren? (Zoals locatie coördinaten, etc.)", + "title": "Gevoelige Data Exporteren?" }, "file_imports": { - "no_files_settings_hint": "Geen bestanden gevonden. Zorg ervoor dat u de vereiste bestanden hebt geïmporteerd in de sectie Bestand importeren", + "no_files_settings_hint": "Geen bestanden gevonden. Zorg dat je de benodigde bestanden hebt geïmporteerd in de Geïmporteerde Bestanden sectie", "settings_select_file_hint": "Selecteer een geïmporteerd bestand" - }, - "quick_actions_dialog": { - "title": "Snelle acties bewerken", - "subtitle": "Selecteer uw snelle acties en pas de grootte ervan aan." } - }, - "friend_tracker": { - "rules_tab": "Regels", - "logs_tab": "Logboeken", - "export_dialog_title": "Exporteren", - "bulk_export_button": "Bulkexport", - "individual_export_button": "Individuele export", - "invalid_import_type_dialog_title": "Ongeldig importtype", - "invalid_import_type_dialog_text": "Het geselecteerde bestand is niet compatibel met dit importtype. Selecteer het juiste importtype.", - "import_dialog_title": "Importeren", - "bulk_import_button": "Bulkimport", - "individual_import_button": "Individuele import", - "import_button_description": "Importeren", - "export_button_description": "Exporteren", - "export_button": "Exporteren", - "delete_button_description": "Verwijderen", - "delete_button": "Verwijderen", - "catalog_button_description": "Catalogus", - "catalog_button": "Catalogus", - "add_rule_button_description": "Regel toevoegen", - "add_rule_button": "Regel toevoegen", - "no_rules_found": "Geen regels gevonden", - "empty_rule_name": "(leeg)", - "events_suffix": "evenementen", - "scopes_suffix": "reikwijdten", - "select_rule_to_export_title": "Selecteer Regel om te exporteren", - "deleted_logs_toast": "{count} logs verwijderd", - "delete_logs_dialog_title": "Logboeken verwijderen?", - "deleting_logs_dialog_text": "{count} logbestanden verwijderen...", - "delete_logs_dialog_confirm_text": "Hiermee worden logboeken verwijderd op basis van het huidige filter en de zoekopdracht. Deze actie kan niet ongedaan worden gemaakt.", - "exported_logs_toast": "Geëxporteerde logboeken!", - "export_logs_failed_toast": "Kan logboeken niet exporteren. Controleer logcat voor meer details.", - "export_logs_dialog_title": "Logboeken exporteren?", - "exporting_logs_dialog_text": "Logboeken exporteren...", - "export_logs_dialog_confirm_text": "Hiermee worden logboeken geëxporteerd op basis van het huidige filter en de zoekopdracht.", - "export_as_button": "Exporteren als {type}", - "filters_title": "Filters", - "search_by_label": "Zoek op", - "newest_first_label": "Nieuwste eerst", - "since_label": "Sinds", - "until_label": "Tot", - "pick_a_date_button": "Kies een datum", - "search_placeholder": "Zoekopdracht", - "filter_button_description": "Filter", - "clear_button_description": "Duidelijk", - "no_logs_found": "Geen logboeken gevonden", - "log_event_format": "{event} in {conversation}", - "condition_only_inside_conversation": "Alleen als ik in gesprek ben", - "condition_only_outside_conversation": "Alleen als ik buiten een gesprek ben", - "condition_only_when_app_active": "Alleen als Snapchat actief is", - "condition_only_when_app_inactive": "Alleen als Snapchat inactief is", - "condition_no_push_notification_when_app_active": "Geen melding wanneer Snapchat actief is", - "add_event_dialog_title": "Evenement toevoegen", - "event_type_label": "Type evenement", - "triggers_title": "Triggers", - "conditions_title": "Voorwaarden", - "add_button": "Toevoegen", - "default_rule_name": "Aangepaste regel", - "discard_changes_dialog_title": "Wijzigingen negeren?", - "discard_changes_dialog_text": "U heeft niet-opgeslagen wijzigingen. Weet je zeker dat je ze wilt weggooien?", - "discard_button": "Weggooien", - "cannot_save_rule_dialog_title": "Kan regel niet opslaan", - "cannot_save_rule_dialog_text": "Een regel moet ten minste één gebeurtenis hebben om op te slaan.", - "duplicate_rule_name_dialog_title": "Dubbele regelnaam", - "duplicate_rule_name_dialog_text": "Er bestaat al een regel met deze naam. Kies een andere naam.", - "delete_rule_dialog_title": "Regel verwijderen", - "delete_rule_dialog_text": "Weet u zeker dat u deze regel wilt verwijderen?", - "new_rule_title": "Nieuwe regel", - "edit_rule_title": "Regel bewerken", - "back_button_description": "Rug", - "save_button_description": "Redden", - "general_section_title": "Algemeen", - "rule_name_label": "Regelnaam", - "author_name_label": "Auteur Naam", - "scope_section_title": "Domein", - "scope_all": "Alle", - "scope_whitelist": "Witte lijst", - "scope_blacklist": "Zwarte lijst", - "select_friends_groups_button": "Selecteer Vrienden/Groepen ({count})", - "events_section_title": "Evenementen", - "add_event_button": "Evenement toevoegen", - "no_events_text": "Geen evenementen" - }, - "friend_tracker_catalog": { - "download_failed": "Mislukte download: {code}", - "error": "Fout: {message}", - "no_repos_added": "Geen opslagplaatsen toegevoegd.", - "no_rules_available": "Er zijn geen regels beschikbaar vanuit een repository.", - "by_author": "door {author}", - "imported_button": "Geïmporteerd", - "import_button": "Importeren", - "title": "Friend Tracker-catalogus", - "manage_repos_description": "Beheer opslagplaatsen" - }, - "friend_tracker_export": { - "title": "Exportregels", - "back_button_description": "Rug", - "exported_toast": "Friend Tracker-regels geëxporteerd!", - "export_failed_toast": "Kan regels niet exporteren: {message}", - "save_button": "Redden", - "expand_button_description": "Uitbreiden" - }, - "friend_tracker_import": { - "title": "Importregels", - "back_button_description": "Rug", - "imported_toast": "Friend Tracker-regels geïmporteerd!", - "import_failed_toast": "Kan regels niet importeren: {message}", - "confirm_button": "Bevestigen", - "expand_button_description": "Uitbreiden" - }, - "friend_tracker_repos": { - "invalid_repo_title": "Ongeldige opslagplaats", - "add_repo_button": "Voeg opslagplaats toe", - "add_repo_dialog_title": "Repository-URL toevoegen", - "repo_url_label": "Repository-URL", - "repo_added_toast": "Repository succesvol toegevoegd!", - "invalid_repo_error": "Dit lijkt geen geldige Friend Tracker-repository te zijn.", - "add_repo_failed_toast": "Kan opslagplaats niet toevoegen: {message}", - "add_button": "Toevoegen", - "no_repos_added": "Geen opslagplaatsen toegevoegd", - "remove_button": "Verwijderen", - "remove_repo_dialog_title": "Verwijder de opslagplaats", - "remove_repo_dialog_text": "Weet u zeker dat u deze opslagplaats wilt verwijderen?" - }, - "navigation": { - "tracker_tab_label": "Volger", - "customize_bottom_bar_title": "Pas de onderste balk aan", - "customize_bottom_bar_subtitle": "Tabbladen opnieuw ordenen, toevoegen of verwijderen. Maximaal vijf.", - "shown_tabs_title": "Getoonde tabbladen", - "no_tabs_selected_text": "Geen tabbladen geselecteerd", - "available_tabs_title": "Beschikbare tabbladen", - "reset_button": "Opnieuw instellen", - "done_button": "Klaar" - }, - "scripting": { - "script_already_installed": "Script al geïnstalleerd!", - "downloading_script": "Script downloaden...", - "script_downloaded": "Script {name} gedownload!", - "download_script_failed": "Kan script niet downloaden. Controleer de logboeken voor meer details", - "import_script_from_url_title": "Script importeren uit URL", - "import_script_warning": "Waarschuwing: geïmporteerde scripts kunnen schadelijk zijn voor uw apparaat. Importeer alleen scripts van vertrouwde bronnen.", - "enter_url_label": "Voer hier de URL in:", - "script_imported": "Script {name} geïmporteerd!", - "import_failed": "Kan script niet importeren. {message}. Controleer de logboeken voor meer details", - "import_button": "Importeren", - "update_module_button": "Module bijwerken", - "updating_script": "Script {name} bijwerken...", - "module_not_found": "Module niet gevonden", - "updated_script": "{name} bijgewerkt naar versie {version}", - "update_module_failed": "Kan de module niet updaten. Controleer de logboeken voor meer details", - "edit_module_button": "Module bewerken", - "open_module_failed": "Kan modulebestand niet openen. Controleer de logboeken voor meer details", - "clear_module_data_button": "Modulegegevens wissen", - "module_data_cleared": "Modulegegevens gewist!", - "clear_module_data_failed": "Kan modulegegevens niet wissen. Controleer de logboeken voor meer details", - "delete_module_button": "Module verwijderen", - "deleted_script": "Script {name} verwijderd!", - "delete_module_failed": "Kan module niet verwijderen. Controleer de logboeken voor meer details", - "actions_title": "Acties", - "no_description": "Geen beschrijving", - "update_available": "Update beschikbaar: {version}", - "actions_button": "Acties", - "loaded_script": "Geladen script {name}", - "unloaded_script": "Verwijderd script {name}", - "enable_script_failed": "Kan script niet inschakelen. Controleer de logboeken voor meer details", - "disable_script_failed": "Kan script niet uitschakelen. Controleer de logboeken voor meer details", - "select_scripts_folder_toast": "Selecteer uw scriptmap!", - "manage_repos_button": "Beheer repo's", - "import_from_url_button": "Importeren vanaf URL", - "open_scripts_folder_button": "Open de map Scripts", - "no_settings_for_module": "Deze module heeft geen instellingen", - "installed_scripts_tab": "Geïnstalleerde scripts", - "catalog_tab": "Catalogus", - "no_scripts_folder_selected_title": "Geen scriptmap geselecteerd", - "select_folder_button": "Selecteer map", - "no_scripts_found_title": "Geen scripts gevonden.", - "use_catalog_to_add_scripts": "Gebruik het tabblad Catalogus om scripts toe te voegen!", - "ok_button_timeout": "OK ({timeout})", - "documentation_button": "Documentatie", - "catalog": { - "script_already_installed": "Script al geïnstalleerd!", - "download_failed": "Mislukte download: {code}", - "script_downloaded": "Script gedownload!", - "could_not_create_file": "Kan bestand niet maken.", - "no_scripts_folder_selected": "Geen scriptmap geselecteerd.", - "error": "Fout: {message}", - "no_repos_added": "Geen opslagplaatsen toegevoegd.", - "repo_list_info": "Hier vindt u een lijst met repo's:", - "link_text": "Link", - "no_scripts_available": "Er zijn geen scripts beschikbaar vanuit een repository.", - "by_author": "door {author}", - "version": "Versie: {version}", - "installed_button": "Geïnstalleerd", - "download_button": "Downloaden" - }, - "repos": { - "invalid_repo_title": "Ongeldige opslagplaats", - "add_repo_button": "Voeg opslagplaats toe", - "add_repo_dialog_title": "Repository-URL toevoegen", - "repo_url_label": "Repository-URL", - "repo_added_toast": "Repository succesvol toegevoegd!", - "invalid_repo_error": "Dit lijkt geen geldige scriptrepository te zijn.", - "add_repo_failed_toast": "Kan opslagplaats niet toevoegen: {message}", - "add_button": "Toevoegen", - "no_repos_added": "Geen opslagplaatsen toegevoegd", - "remove_button": "Verwijderen", - "remove_repo_dialog_title": "Verwijder de opslagplaats", - "remove_repo_dialog_text": "Weet u zeker dat u deze opslagplaats wilt verwijderen?" - } - }, - "features": { - "config_import": { - "title": "Bevestig het importeren", - "back_button_description": "Rug", - "config_imported_toast": "Configuratie geïmporteerd!", - "confirm_button": "Bevestigen", - "expand_button_description": "Uitbreiden", - "enable_feature": "Functie inschakelen", - "enabled": "Ingeschakeld", - "disabled": "Gehandicapt" - }, - "config_export": { - "title": "Samenvatting exporteren", - "back_button_description": "Rug", - "save_button": "Redden", - "expand_button_description": "Uitbreiden", - "enable_feature": "Functie inschakelen", - "enabled": "Ingeschakeld", - "disabled": "Gehandicapt" - } - }, - "manage_repos": { - "title": "Beheer {featureName} opslagplaatsen", - "add_repo_button": "Voeg opslagplaats toe", - "add_repo_dialog_title": "Repository-URL toevoegen", - "repo_url_label": "Repository-URL", - "repo_added_successfully": "Repository succesvol toegevoegd!", - "add_repo_failed": "Kan opslagplaats niet toevoegen: {message}", - "add_button": "Toevoegen", - "no_repos_added": "Geen opslagplaatsen toegevoegd", - "remove_button": "Verwijderen" } }, "rules": { - "toasts": { - "enabled": "{ruleName} ingeschakeld", - "disabled": "{ruleName} uitgeschakeld" - }, "modes": { - "blacklist": "Zwarte lijst-modus", - "whitelist": "Witte lijst-modus" + "blacklist": "Zwarte lijst modus", + "whitelist": "Witte lijst modus" }, "properties": { "auto_download": { "name": "Automatisch downloaden", - "description": "Download automatisch Snaps wanneer je ze bekijkt", + "description": "Download Snaps automatisch tijdens het bekijken", "options": { "blacklist": "Uitsluiten van automatisch downloaden", - "whitelist": "Automatisch downloaden" + "whitelist": "Automatische download" } }, "stealth": { - "name": "Stealth-modus", - "description": "Voorkomt dat iemand weet dat je zijn of haar Snaps/Chats en gesprekken hebt geopend", + "name": "Verberg Modus", + "description": "Voorkomt dat iedereen weet dat je hun snaps/chats en gesprekken hebt geopend", "options": { - "blacklist": "Uitsluiten van de stealth-modus", - "whitelist": "Stealth-modus" + "blacklist": "Uitsluiten van Verberg Modus", + "whitelist": "Verberg modus" } }, "auto_save": { "name": "Automatisch opslaan", - "description": "Slaat chatberichten op wanneer u ze bekijkt", + "description": "Slaat chatberichten op wanneer je ze bekijkt", "options": { "blacklist": "Uitsluiten van automatisch opslaan", "whitelist": "Automatisch opslaan" } }, - "unsaveable_messages": { - "name": "Niet-op te slaan berichten", - "description": "Voorkomt dat berichten door andere mensen in de chat worden opgeslagen", - "options": { - "blacklist": "Uitsluiten van niet-op te slaan berichten", - "whitelist": "Niet-op te slaan berichten" - } - }, - "auto_open_snaps": { - "name": "Automatisch openende snaps", - "description": "Opent automatisch Snaps wanneer je ze ontvangt", - "options": { - "blacklist": "Uitsluiten van automatisch openende snaps", - "whitelist": "Automatisch openende snaps" - } - }, "hide_friend_feed": { - "name": "Verbergen in vriendenfeed" + "name": "Verbergen in Vrienden Feed" }, "e2e_encryption": { - "name": "Gebruik E2E-codering" + "name": "Gebruik E2E Encryptie" }, "pin_conversation": { "name": "Gesprek vastzetten" }, - "exclude_message_logger": { - "name": "Uitsluiten van berichtenlogger" + "unsaveable_messages": { + "name": "Berichten die niet kunnen worden opgeslagen", + "description": "Voorkomt dat berichten door andere mensen in de chat worden opgeslagen", + "options": { + "blacklist": "Sluit uit van onopslaanbare berichten", + "whitelist": "Berichten die niet kunnen worden opgeslagen" + } + }, + "auto_open_snaps": { + "name": "Snaps Automatisch Openen", + "description": "Opent Snaps automatisch bij ontvangst", + "options": { + "blacklist": "Uitsluiten van Automatisch Openen van Snaps", + "whitelist": "Snaps Automatisch Openen" + } } - } - }, - "actions": { - "clean_snapchat_cache": { - "name": "Maak de Snapchat-cache schoon", - "description": "Reinigt de Snapchat-cache" }, - "manage_friend_list": { - "name": "Beheer vriendenlijst", - "description": "Importeer/exporteer uw vriendenlijst wanneer u een back-up maakt" - }, - "export_chat_messages": { - "name": "Chatberichten exporteren", - "description": "Exporteert gespreksberichten naar een JSON/HTML/TXT-bestand" - }, - "export_memories": { - "name": "Herinneringen exporteren", - "description": "Exporteert herinneringen naar een ZIP-bestand" - }, - "bulk_messaging_action": { - "name": "Actie voor bulkberichten", - "description": "Voert bewerkingen uit zoals het verwijderen van vrienden of het massaal verwijderen van gesprekken" - }, - "regen_mappings": { - "name": "Genereer toewijzingen opnieuw", - "description": "Genereer toewijzingen handmatig opnieuw" - }, - "change_language": { - "name": "Taal wijzigen", - "description": "Verander de taal van PurrfectSnap" - }, - "file_imports": { - "name": "Bestanden importeren", - "description": "Importeer bestanden voor gebruik in Snapchat" - }, - "friend_tracker": { - "name": "Vriendentracker", - "description": "Volg je vrienden op Snapchat" - }, - "logger_history": { - "name": "Logboekgeschiedenis", - "description": "Bekijk de geschiedenis van gelogde berichten" + "toasts": { + "enabled": "{ruleName} Ingeschakeld", + "disabled": "{ruleName} uitgeschakeld" } }, "features": { "notices": { - "unstable": "⚠ Onstabiel", - "ban_risk": "⚠ Deze functie kan verbanningen veroorzaken", - "internal_behavior": "⚠ Dit kan het interne gedrag van Snapchat verstoren" + "unstable": "⚠ onstabiel", + "ban_risk": "⚠️ Deze functie kan bans veroorzaken", + "internal_behavior": "⚠️ Dit kan het interne gedrag van Snapchat breken" }, "properties": { "downloader": { "name": "Downloader", - "description": "Download Snapchat-media", "properties": { "save_folder": { - "name": "Map opslaan", - "description": "Selecteer de map waarnaar alle media moeten worden gedownload" + "name": "Opslag locatie", + "description": "Selecteer de map waar alle media naar moeten worden gedownload" }, "auto_download_sources": { - "name": "Bronnen automatisch downloaden", - "description": "Selecteer de bronnen waarvan u automatisch wilt downloaden" + "name": "Automatisch Bronnen downloaden", + "description": "Selecteer de bronnen waaruit je automatisch wilt downloaden" }, "prevent_self_auto_download": { - "name": "Voorkom zelfautomatisch downloaden", - "description": "Voorkomt dat je eigen Snaps automatisch worden gedownload" + "name": "Eigen automatische download voorkomen", + "description": "Voorkomt dat je eigen snaps automatisch worden gedownload" }, "path_format": { - "name": "Padformaat", - "description": "Geef de bestandspadindeling op" + "name": "Pad Formaat", + "description": "Geef het bestandspad formaat op" }, "allow_duplicate": { - "name": "Dubbel toestaan", - "description": "Hiermee kunnen dezelfde media meerdere keren worden gedownload" + "name": "Duplicaten toestaan", + "description": "Staat toe om meerdere keren hetzelfde media te downloaden" }, "merge_overlays": { - "name": "Overlays samenvoegen", - "description": "Combineert de tekst en de media van een Snap in één enkel bestand" + "name": "Overlays Samenvoegen", + "description": "Combineert de tekst en de media van een Snap in een enkel bestand" }, "force_image_format": { - "name": "Afbeeldingsformaat forceren", - "description": "Forceert dat afbeeldingen in een opgegeven indeling worden opgeslagen" + "name": "Forceer Afbeeldingsformaat", + "description": "Forceert dat afbeeldingen opgeslagen moeten worden in een gespecificeerd formaat" }, "force_voice_note_format": { - "name": "Formaat van spraaknotities forceren", - "description": "Forceert dat spraaknotities in een opgegeven indeling worden opgeslagen" - }, - "auto_download_voice_notes": { - "name": "Spraaknotities automatisch downloaden", - "description": "Downloadt automatisch spraaknotities tijdens het afspelen ervan" + "name": "Forceer spraaknotitie formaat", + "description": "Forceert dat spraaknotities opgeslagen moeten worden in een opgegeven formaat" }, "download_profile_pictures": { - "name": "Profielfoto's downloaden", - "description": "Hiermee kunt u profielfoto's downloaden van de profielpagina" - }, - "opera_download_button": { - "name": "Opera-downloadknop", - "description": "Voegt een downloadknop toe in de rechterbovenhoek wanneer je een Snap bekijkt.\nAls u lang op de knoppen drukt, wordt het downloaden geforceerd" - }, - "download_context_menu": { - "name": "Contextmenu downloaden", - "description": "Hiermee kunt u berichten uit een gesprek of een verhaal downloaden/bekijken via het contextmenu.\nAls u lang op de knoppen drukt, wordt het downloaden geforceerd" + "name": "Download profielfoto's", + "description": "Maakt het mogelijk om profielfoto's van de profielpagina te downloaden" }, "ffmpeg_options": { - "name": "FFmpeg-opties", - "description": "Geef aanvullende FFmpeg-opties op", + "name": "FFmpeg Opties", + "description": "Specificeer extra FFmpeg opties", "properties": { "threads": { - "name": "Draden", - "description": "Het aantal te gebruiken threads" + "name": "Threads", + "description": "Het aantal threads dat moet worden gebruikt" }, "preset": { "name": "Voorinstelling", "description": "Stel de snelheid van de conversie in" }, - "constant_rate_factor": { - "name": "Constante tarieffactor", - "description": "Stel de constante snelheidsfactor voor de video-encoder in\nVan 0 tot 51 voor libx264" - }, "video_bitrate": { "name": "Video-bitsnelheid", "description": "Stel de videobitsnelheid (kbps) in" }, "audio_bitrate": { - "name": "Audio-bitsnelheid", - "description": "Stel de audiobitsnelheid (kbps) in" + "description": "Stel de audiobitsnelheid (kbps) in", + "name": "Audio-bitsnelheid" }, "custom_video_codec": { "name": "Aangepaste videocodec", "description": "Stel een aangepaste videocodec in (bijvoorbeeld libx264)" }, + "constant_rate_factor": { + "description": "Stel de constante snelheidsfactor voor de video-encoder in\nVan 0 tot 51 voor libx264", + "name": "Constante tarieffactor" + }, "custom_audio_codec": { "name": "Aangepaste audiocodec", "description": "Stel een aangepaste audiocodec in (bijvoorbeeld AAC)" } } }, - "logging": { - "name": "Loggen", - "description": "Toont toast wanneer media worden gedownload" + "download_context_menu": { + "description": "Hiermee kunt u berichten uit een gesprek of een verhaal downloaden/bekijken via het contextmenu.\nAls u lang op de knoppen drukt, wordt het downloaden geforceerd", + "name": "Contextmenu downloaden" }, "custom_path_format": { - "name": "Aangepaste padindeling", - "description": "Geef een aangepast padformaat op voor gedownloade media\n\nBeschikbare variabelen:\n - %gebruikersnaam%\n - %bron%\n - %hash%\n - %date_time%" + "description": "Geef een aangepast padformaat op voor gedownloade media\n\nBeschikbare variabelen:\n - %username%\n - %source%\n - %hash%\n - %date_time%", + "name": "Aangepaste padindeling" + }, + "logging": { + "description": "Toont toast wanneer media worden gedownload", + "name": "Loggen" + }, + "opera_download_button": { + "name": "Opera-downloadknop", + "description": "Voegt een downloadknop toe in de rechterbovenhoek wanneer je een Snap bekijkt.\nAls u lang op de knoppen drukt, wordt het downloaden geforceerd" } - } + }, + "description": "Snapchat-media downloaden" }, "user_interface": { - "name": "Gebruikersinterface", - "description": "Verander het uiterlijk en het gevoel van Snapchat", + "description": "Verander het uiterlijk en gevoel van Snapchat", "properties": { "enable_app_appearance": { - "name": "Schakel App-weergave-instellingen in", - "description": "Schakelt de verborgen app-weergave-instelling in\nMogelijk niet vereist op nieuwere Snapchat-versies" + "name": "Activeer App Uiterlijk Instellingen", + "description": "Schakelt de verborgen App Uiterlijk Instelling in\nMogelijk niet nodig in nieuwere Snapchat versies" }, "friend_feed_message_preview": { - "name": "Voorbeeld van vriendfeedbericht", - "description": "Toont een voorbeeld van de laatste berichten in de vriendenfeed", + "name": "Voorbeeld Vrienden Feed Bericht", + "description": "Toont een voorbeeld van de laatste berichten in de Vrienden Feed", "properties": { "amount": { "name": "Hoeveelheid", - "description": "Het aantal berichten waarvan een voorbeeld kan worden bekeken" + "description": "Het aantal berichten om een voorbeeld te krijgen" } } }, - "snap_preview": { - "name": "Snapvoorbeeld", - "description": "Toont een klein voorbeeld naast onzichtbare Snaps in de chat" - }, "bootstrap_override": { - "name": "Bootstrap-overschrijving", - "description": "Overschrijft de bootstrap-instellingen van de gebruikersinterface", + "name": "Bootstrap overschrijven", + "description": "Overschrijft de gebruikersinterface bootstrap instellingen", "properties": { "app_appearance": { - "name": "App-uiterlijk", - "description": "Stelt een blijvende app-uiterlijk in" + "name": "App Uiterlijk", + "description": "Stelt een persistent App uiterlijk in" }, "home_tab": { - "name": "Tabblad Start", - "description": "Overschrijft het opstarttabblad bij het openen van Snapchat" + "name": "Startpagina tabblad", + "description": "Overschrijft het starttabblad bij het openen van Snapchat" } } }, - "force_amoled_theme": { - "name": "Amoled donkere modus", - "description": "Gebruikt een echte zwarte achtergrond voor het donkere thema" - }, "map_friend_nametags": { - "name": "Verbeterde naamplaatjes voor vriendenkaarten", - "description": "Verbetert de naamplaatjes van vrienden op de Snapmap" - }, - "prevent_message_list_auto_scroll": { - "name": "Voorkom berichtenlijst automatisch scrollen", - "description": "Voorkomt dat de berichtenlijst naar beneden schuift bij het verzenden/ontvangen van een bericht" + "name": "Verbeterde Kaart Naamtags Van Vrienden", + "description": "Verbetert de naamtags van vrienden op de Snapmap" }, "streak_expiration_info": { - "name": "Toon de vervaldatum van de streak", - "description": "Toont een Streak Expiration-timer naast de Streaks-teller" + "name": "Toon Snapreeks vervaldatum info", + "description": "Toont een Snapreeks Verlooptimer naast de Snapreeks teller" }, "hide_friend_feed_entry": { - "name": "Verberg de vermelding in de vriendenfeed", - "description": "Verbergt een specifieke vriend in de vriendenfeed\nGebruik het tabblad Sociaal om deze functie te beheren" + "name": "Verberg Vrienden Feed", + "description": "Verbergt een specifieke vriend uit de Vrienden Feed\nGebruik het sociale tabblad om deze functie te beheren" }, "hide_streak_restore": { - "name": "Verberg Streakherstel", - "description": "Verbergt de knop Herstellen in de vriendenfeed" - }, - "hide_quick_add_suggestions": { - "name": "Suggesties voor snel toevoegen verbergen", - "description": "Verwijdert suggesties voor het snel toevoegen van vrienden" - }, - "hide_story_suggestions": { - "name": "Verhaalsuggesties verbergen", - "description": "Verwijdert suggesties van de pagina Verhalen" + "name": "Snapreeksherstel verbergen", + "description": "Verbergt de Herstel knop in de vrienden feed" }, "hide_ui_components": { - "name": "UI-componenten verbergen", - "description": "Selecteer welke UI-componenten u wilt verbergen" - }, - "opera_media_quick_info": { - "name": "Opera Media Snelle informatie", - "description": "Toont nuttige informatie over media, zoals de aanmaakdatum in het contextmenu van de operaviewer" - }, - "old_bitmoji_selfie": { - "name": "Oude Bitmoji-selfie", - "description": "Brengt de Bitmoji-selfies terug van oudere Snapchat-versies" + "name": "Verberg UI Componenten", + "description": "Selecteer welke UI componenten te verbergen" }, "disable_spotlight": { - "name": "Schakel Spotlight uit", - "description": "Schakelt de Spotlight-pagina uit" - }, - "friend_feed_menu_buttons": { - "name": "Menuknoppen voor vriendenfeed", - "description": "Selecteer welke knoppen u wilt weergeven in het vriendenfeedmenu" - }, - "auto_close_friend_feed_menu": { - "name": "Automatisch vriendenfeedmenu sluiten", - "description": "Sluit automatisch het vriendenfeedmenu nadat u op een instelknop hebt gedrukt" - }, - "vertical_story_viewer": { - "name": "Verticale verhaalviewer", - "description": "Schakelt de verticale verhaalviewer in voor alle verhalen" - }, - "enable_friend_feed_menu_bar": { - "name": "Menubalk voor vriendenfeed", - "description": "Schakelt de nieuwe vriendenfeedmenubalk in" - }, - "message_indicators": { - "name": "Berichtindicatoren", - "description": "Voegt specifieke indicatorpictogrammen toe aan berichten\nOpmerking: indicatoren zijn mogelijk niet 100% nauwkeurig" - }, - "stealth_mode_indicator": { - "name": "Stealth-modusindicator", - "description": "Voegt een 👻 emoji toe naast gesprekken in stealth-modus" - }, - "edit_text_override": { - "name": "Tekstoverschrijving bewerken", - "description": "Overschrijft het gedrag van tekstvelden" - }, - "prevent_forced_keyboard": { - "name": "Voorkom geforceerd toetsenbord", - "description": "Voorkomt dat Snapchat automatisch het toetsenbord opent wanneer je een gesprek opent" - }, - "settings_menu": { - "name": "Instellingenmenu", - "description": "Verandert de manier waarop u het PurrfectSnap-menu opent", - "options": { - "default": "Standaard", - "legacy": "Nalatenschap" - } + "name": "Spotlight uitschakelen", + "description": "Schakelt de Spotlight pagina uit" } - } - }, - "messaging": { - "name": "Berichten", - "description": "Verander de manier waarop u met vrienden omgaat", - "properties": { - "bypass_screenshot_detection": { - "name": "Omzeil screenshot-detectie", - "description": "Voorkomt dat Snapchat detecteert wanneer je een screenshot maakt" - }, - "anonymous_story_viewing": { - "name": "Anoniem verhaal bekijken", - "description": "Voorkomt dat iemand weet dat je zijn of haar verhaal hebt gezien" - }, - "prevent_story_rewatch_indicator": { - "name": "Indicator voor het opnieuw bekijken van verhalen voorkomen", - "description": "Voorkomt dat iemand weet dat je zijn of haar verhaal opnieuw hebt bekeken" - }, - "hide_peek_a_peek": { - "name": "Verberg Peek-a-Peek", - "description": "Voorkomt dat er een melding wordt verzonden wanneer u half in een chat veegt" - }, - "hide_bitmoji_presence": { - "name": "Bitmoji-aanwezigheid verbergen", - "description": "Voorkomt dat uw Bitmoji opduikt terwijl u in Chat bent" - }, - "hide_typing_notifications": { - "name": "Typemeldingen verbergen", - "description": "Voorkomt dat iemand weet dat u een bericht typt" - }, - "unlimited_snap_view_time": { - "name": "Onbeperkte Snap-weergavetijd", - "description": "Verwijdert de tijdslimiet voor het bekijken van Snaps" - }, - "auto_mark_as_read": { - "name": "Automatisch markeren als gelezen", - "description": "Markeert berichten/snaps automatisch als gelezen, zelfs als de stealth-modus is ingeschakeld" - }, - "mark_snap_as_seen_button": { - "name": "Markeer de knop 'Snap als gezien'", - "description": "Voegt een knop toe om een ​​Snap te markeren zoals gezien tijdens het bekijken ervan.\nDit werkt zelfs als de Stealth-modus is ingeschakeld" - }, - "skip_when_marking_as_seen": { - "name": "Overslaan bij markeren als gezien", - "description": "Gaat automatisch naar de volgende Snap wanneer u een Snap als gezien markeert.\nGebruik in combinatie met Mark Snap as Seen-knop" - }, - "loop_media_playback": { - "name": "Loop media afspelen", - "description": "Herhaalt het afspelen van media tijdens het bekijken van Snaps/Verhalen" - }, - "disable_replay_in_ff": { - "name": "Schakel opnieuw afspelen in FF uit", - "description": "Schakelt de mogelijkheid uit om opnieuw af te spelen door lang te drukken vanuit de vriendenfeed" - }, - "half_swipe_notifier": { - "name": "Halve veegmelding", - "description": "Geeft een melding wanneer iemand half in een gesprek swipet", - "properties": { - "min_duration": { - "name": "Minimale duur", - "description": "De minimale duur van de halve veegbeweging (in seconden)" - }, - "max_duration": { - "name": "Maximale duur", - "description": "De maximale duur van de halve veegbeweging (in seconden)" - } - } - }, - "call_start_confirmation": { - "name": "Bevestiging van het starten van een gesprek", - "description": "Toont een bevestigingsvenster wanneer u een oproep start" - }, - "unlimited_conversation_pinning": { - "name": "Onbeperkt conversatie vastzetten", - "description": "Hiermee kunt u een onbeperkt aantal gesprekken lokaal vastzetten" - }, - "disable_snap_mode_restrictions": { - "name": "Schakel beperkingen in de Snap-modus uit", - "description": "Hiermee kun je zelfvernietigende Snaps zonder beperkingen bekijken" - }, - "prevent_message_sending": { - "name": "Voorkom het verzenden van berichten", - "description": "Voorkomt het verzenden van bepaalde soorten berichten" - }, - "friend_mutation_notifier": { - "name": "Kennisgever voor vriendmutaties", - "description": "Waarschuwt u wanneer er iets verandert in het profiel van een vriend" - }, - "better_notifications": { - "name": "Betere meldingen", - "description": "Voegt meer informatie toe in ontvangen meldingen", - "properties": { - "group_notifications": { - "name": "Groepsmeldingen", - "description": "Groepeer meldingen in één bericht" - }, - "chat_preview": { - "name": "Chatvoorbeeld", - "description": "Toont een voorbeeld van ontvangen berichten in de melding" - }, - "media_preview": { - "name": "Mediavoorbeeld", - "description": "Toont een voorbeeld van de geselecteerde mediatypen in de melding" - }, - "media_caption": { - "name": "Mediabijschrift", - "description": "Toont het bijgevoegde bijschrift van media in de melding" - }, - "stacked_media_messages": { - "name": "Gestapelde mediaberichten", - "description": "Combineert meerdere mediaberichten in één tekstmelding wanneer ze niet vooraf kunnen worden bekeken. Gebruik in combinatie met Chatvoorbeeld" - }, - "friend_add_source": { - "name": "Vriend Bron toevoegen", - "description": "Toont de bron van een vriendschapsverzoek in de melding" - }, - "reply_button": { - "name": "Antwoordknop", - "description": "Voegt een antwoordknop toe aan de melding" - }, - "smart_replies": { - "name": "Slimme antwoorden", - "description": "Voegt voorgestelde antwoorden toe aan meldingen (Android 10+). Gebruik in combinatie met de antwoordknop" - }, - "download_button": { - "name": "Downloadknop", - "description": "Hiermee kunt u media downloaden vanuit de melding" - }, - "mark_as_read_button": { - "name": "Markeer als leesknop", - "description": "Hiermee kunt u een bericht vanuit de melding markeren als gelezen" - }, - "mark_as_read_and_save_in_chat": { - "name": "Markeer als gelezen en sla op in de chat", - "description": "Voegt een markering als gelezen en opgeslagen in chat-knop toe aan de melding" - } - } - }, - "notification_blacklist": { - "name": "Melding zwarte lijst", - "description": "Selecteer meldingen die moeten worden geblokkeerd" - }, - "message_logger": { - "name": "Berichtenlogger", - "description": "Voorkomt dat berichten worden verwijderd", - "properties": { - "keep_my_own_messages": { - "name": "Bewaar mijn eigen berichten", - "description": "Voorkomt dat uw eigen berichten worden verwijderd" - }, - "auto_purge": { - "name": "Automatisch zuiveren", - "description": "Verwijdert automatisch berichten in de cache die ouder zijn dan de opgegeven tijdsduur" - }, - "message_filter": { - "name": "Berichtenfilter", - "description": "Selecteer welke berichten moeten worden geregistreerd (leeg voor alle berichten)" - }, - "deleted_message_color": { - "name": "Kleur verwijderd bericht", - "description": "Stelt de kleur van verwijderde berichten in" - } - } - }, - "auto_save_messages_in_conversations": { - "name": "Berichten automatisch opslaan", - "description": "Slaat automatisch elk bericht in gesprekken op" - }, - "gallery_media_send_override": { - "name": "Galerijmedia Verzenden negeren", - "description": "Spoof de mediabron bij verzending vanuit de galerij" - }, - "strip_media_metadata": { - "name": "Media-metagegevens verwijderen", - "description": "Verwijdert metagegevens van media voordat deze als bericht worden verzonden" - }, - "bypass_message_retention_policy": { - "name": "Omzeil het bewaarbeleid voor berichten", - "description": "Voorkomt dat berichten worden verwijderd nadat ze zijn bekeken" - }, - "bypass_message_action_restrictions": { - "name": "Omzeil berichtactiebeperkingen", - "description": "Hiermee kunt u reageren op een module zonder deze te openen of een bericht opslaan dat niet kan worden opgeslagen" - }, - "remove_groups_locked_status": { - "name": "Verwijder de status van vergrendelde groepen", - "description": "Hiermee kunt u groepsinformatie bekijken nadat u bent geschopt" - }, - "double_tap_chat_action": { - "name": "Dubbeltikchatactie", - "description": "Voert een aangepaste actie uit wanneer u dubbeltikt op een bericht in de chat" - }, - "double_tap_chat_action_custom_emoji": { - "name": "Dubbeltikchatactie Aangepaste Emoji-reactie", - "description": "Stelt een aangepaste emoji-reactie in voor de dubbeltikchatactie" - } - } - }, - "global": { - "name": "Globaal", - "description": "Pas de wereldwijde Snapchat-instellingen aan", - "properties": { - "better_location": { - "name": "Betere locatie", - "description": "Verbetert de Snapchat-locatie", - "properties": { - "spoof_location": { - "name": "Spoof-locatie", - "description": "Spooft uw locatie naar een opgegeven locatie" - }, - "coordinates": { - "name": "Coördinaten", - "description": "Stel de coördinaten van de vervalste locatie in" - }, - "walk_radius": { - "name": "Loop straal", - "description": "Loop willekeurig rond binnen deze straal (ft)" - }, - "always_update_location": { - "name": "Update locatie altijd", - "description": "Forceer Snapchat om de locatie bij te werken, zelfs als er geen GPS-gegevens worden ontvangen" - }, - "suspend_location_updates": { - "name": "Locatie-updates opschorten", - "description": "Voorkomt dat uw locatie wordt bijgewerkt" - }, - "spoof_battery_level": { - "name": "Spoof batterijniveau", - "description": "Spooft het batterijniveau van uw apparaat op de kaart\nDe waarde moet tussen 0 en 100 liggen" - }, - "spoof_headphones": { - "name": "Spoof-koptelefoon", - "description": "Spooft de status van het luisteren naar muziek op de kaart" - }, - "show_battery_level": { - "name": "Toon batterijniveau", - "description": "Toont het batterijniveau van je vrienden op de kaart" - } - } - }, - "snapchat_plus": { - "name": "SnapchatPlus", - "description": "Schakelt Snapchat Plus-functies in\nSommige serverzijdige functies werken mogelijk niet" - }, - "media_upload_quality": { - "name": "Kwaliteit van media-upload", - "description": "Overschrijft de kwaliteit van het uploaden van media", - "properties": { - "force_video_upload_source_quality": { - "name": "Bronkwaliteit voor video-upload forceren", - "description": "Dwingt Snapchat om de bronkwaliteit te gebruiken bij het uploaden van video's\nHoud er rekening mee dat hiermee mogelijk geen metadata van media wordt verwijderd" - }, - "disable_image_compression": { - "name": "Schakel beeldcompressie uit", - "description": "Schakelt beeldcompressie uit bij het uploaden van media" - }, - "custom_image_upload_format": { - "name": "Aangepast uploadformaat voor afbeeldingen", - "description": "Stelt een aangepast uploadformaat voor afbeeldingen in\nSelecteer een verliesvrij formaat (zoals PNG) voor de beste kwaliteit" - } - } - }, - "disable_confirmation_dialogs": { - "name": "Bevestigingsdialogen uitschakelen", - "description": "Bevestigt automatisch geselecteerde acties" - }, - "auto_updater": { - "name": "Automatische updater", - "description": "Controleert automatisch op nieuwe updates" - }, - "disable_metrics": { - "name": "Schakel statistieken uit", - "description": "Blokkeert het verzenden van specifieke analytische gegevens naar Snapchat" - }, - "disable_story_sections": { - "name": "Schakel Verhaalsecties uit", - "description": "Verwijdert secties van de pagina Verhalen\nVereist mogelijk een vernieuwing om goed te werken" - }, - "block_ads": { - "name": "Blokkeer advertenties", - "description": "Voorkomt dat advertenties worden weergegeven" - }, - "disable_custom_tabs": { - "name": "Schakel aangepaste tabbladen uit", - "description": "Opent koppelingen in ondersteunde toepassingen in plaats van in de webbrowser" - }, - "disable_permission_requests": { - "name": "Schakel toestemmingsverzoeken uit", - "description": "Voorkomt dat Snapchat om specifieke toestemmingen vraagt" - }, - "disable_memories_snap_feed": { - "name": "Schakel Herinneringen Snap Feed uit", - "description": "Voorkomt dat Snapchat recente herinneringen toont wanneer je omhoog veegt in de camera" - }, - "spotlight_comments_username": { - "name": "Spotlight Opmerkingen Gebruikersnaam", - "description": "Toont de gebruikersnaam van de auteur in Spotlight-opmerkingen" - }, - "bypass_video_length_restriction": { - "name": "Omzeil de beperkingen voor de videolengte", - "description": "Single: verzendt een enkele video\nSplitsen: video's splitsen na bewerking" - }, - "default_video_playback_rate": { - "name": "Standaard video-afspeelsnelheid", - "description": "Stelt de standaardsnelheid in voor het afspelen van video's\nDe waarde moet tussen 0,1 en 4,0 liggen" - }, - "video_playback_rate_slider": { - "name": "Schuifregelaar voor video-afspeelsnelheid", - "description": "Voegt een schuifregelaar toe in het opera-contextmenu om de afspeelsnelheid van de video te wijzigen\nOpmerking: wijzigingen zijn alleen van toepassing op volgende video's" - }, - "disable_google_play_dialogs": { - "name": "Schakel de dialoogvensters van Google Play-services uit", - "description": "Voorkom dat dialoogvensters voor beschikbaarheid van Google Play-services worden weergegeven" - }, - "default_volume_controls": { - "name": "Standaardvolumeregelaars", - "description": "Dwingt Snapchat om systeemvolumeregelaars te gebruiken" - }, - "disable_telecom_framework": { - "name": "Schakel Telecomframework uit", - "description": "Voorkomt dat Snapchat het Android Telecom-framework gebruikt\nHierdoor kun je tijdens een gesprek naar muziek luisteren" - }, - "hide_active_music": { - "name": "Actieve muziek verbergen", - "description": "Voorkomt dat Snapchat weet dat je naar muziek luistert\nHiermee kunt u foto's maken met de volumeknoppen terwijl u naar muziek luistert" - }, - "disable_snap_splitting": { - "name": "Schakel Snap-splitsing uit", - "description": "Voorkomt dat Snaps in meerdere delen worden opgesplitst\nFoto's die u verzendt, worden video's" - } - } - }, - "rules": { - "name": "Regels", - "description": "Beheer automatische functies voor individuele personen" - }, - "camera": { - "name": "Camera", - "description": "Pas de juiste instellingen aan voor de perfecte foto", - "properties": { - "disable_cameras": { - "name": "Schakel camera's uit", - "description": "Voorkomt dat Snapchat de geselecteerde camera's gebruikt" - }, - "black_photos": { - "name": "Zwarte foto's", - "description": "Vervangt gemaakte foto's door een zwarte achtergrond\nVideo's worden niet beïnvloed" - }, - "immersive_camera_preview": { - "name": "Meeslepend voorbeeld", - "description": "Voorkomt dat Snapchat het cameravoorbeeld bijsnijdt\nDit kan ertoe leiden dat de camera op sommige apparaten flikkert" - }, - "override_front_resolution": { - "name": "Resolutie voorzijde negeren", - "description": "Overschrijft de cameraresolutie voor de camera aan de voorkant" - }, - "override_back_resolution": { - "name": "Terugresolutie overschrijven", - "description": "Overschrijft de cameraresolutie voor de camera aan de achterkant" - }, - "custom_resolution": { - "name": "Aangepaste resolutie", - "description": "Stelt een aangepaste cameraresolutie in, breedte x hoogte (bijvoorbeeld 1920x1080).\nDe aangepaste resolutie moet door uw apparaat worden ondersteund" - }, - "front_custom_frame_rate": { - "name": "Aangepaste framesnelheid voorzijde", - "description": "Heft de framesnelheid van de camera aan de voorkant op" - }, - "back_custom_frame_rate": { - "name": "Terug Aangepaste framesnelheid", - "description": "Heft de framesnelheid van de camera aan de achterkant op" - }, - "force_camera_source_encoding": { - "name": "Forceer camerabroncodering", - "description": "Forceert de codering van de camerabron" - }, - "startup_default_camera": { - "name": "Standaardcamera opstarten", - "description": "Stelt de standaardcamera in bij het openen van Snapchat" - }, - "hevc_recording": { - "name": "HEVC-opname", - "description": "Maakt gebruik van HEVC (H.265)-codec voor video-opname" - } - } - }, - "streaks_reminder": { - "name": "Strepen herinnering", - "description": "Brengt u periodiek op de hoogte van uw Streaks", - "properties": { - "interval": { - "name": "Interval", - "description": "Het interval tussen elke herinnering (uren)" - }, - "remaining_hours": { - "name": "Resterende tijd", - "description": "De resterende tijd voordat de melding wordt weergegeven (uren)" - }, - "group_notifications": { - "name": "Groepsmeldingen", - "description": "Groepeer meldingen in één bericht" - } - } - }, - "experimental": { - "name": "Experimenteel", - "description": "Experimentele kenmerken", - "properties": { - "native_hooks": { - "name": "Inheemse haken", - "description": "Onveilige functies die inhaken op de eigen code van Snapchat", - "properties": { - "composer_hooks": { - "name": "Componist Haken", - "description": "Injecteert code in het platformonafhankelijke UI-framework van Composer", - "properties": { - "show_first_created_username": { - "name": "Toon eerst aangemaakte gebruikersnaam", - "description": "Toont de eerst aangemaakte gebruikersnaam naast de huidige gebruikersnaam op de profielpagina" - }, - "bypass_camera_roll_limit": { - "name": "Omzeil de camerarollimiet", - "description": "Vergroot de maximale hoeveelheid media die u vanaf de filmrol kunt verzenden" - }, - "custom_self_destruct_snap_delay": { - "name": "Aangepaste zelfvernietigingssnapvertraging", - "description": "Geeft meer opties voor de zelfvernietigingstimer bij het verzenden van een Snap" - }, - "composer_console": { - "name": "Componistenconsole", - "description": "Hiermee kunt u JavaScript-code uitvoeren in Composer (alleen arm64)" - }, - "composer_logs": { - "name": "Componistenlogboeken", - "description": "Stuurt consolelogboeken van Composer om naar PurrfectSnap" - } - } - }, - "disable_bitmoji": { - "name": "Schakel Bitmoji uit", - "description": "Schakelt Vriendenprofiel Bitmoji uit" - }, - "custom_emoji_font": { - "name": "Aangepast Emoji-lettertype", - "description": "Hiermee kunt u een aangepast emoji-lettertype gebruiken. Werkt alleen met .ttf-lettertypen" - }, - "custom_shared_library": { - "name": "Aangepaste gedeelde bibliotheek", - "description": "Laadt een aangepaste gedeelde bibliotheek in Snapchat. Deze functie is alleen bedoeld voor testdoeleinden" - } - } - }, - "spoof": { - "name": "Parodie", - "description": "Spoof verschillende informatie over u", - "properties": { - "play_store_installer_package_name": { - "name": "Play Store Installer-pakketnaam", - "description": "Overschrijft de naam van het installatiepakket naar com.android.vending" - }, - "remove_vpn_transport_flag": { - "name": "Verwijder de VPN-transportvlag", - "description": "Voorkomt dat Snapchat VPN's detecteert" - }, - "remove_mock_location_flag": { - "name": "Verwijder de neplocatievlag", - "description": "Voorkomt dat Snapchat een neplocatie detecteert" - } - } - }, - "convert_message_locally": { - "name": "Bericht lokaal converteren", - "description": "Converteert snaps om lokaal met externe media te chatten. Dit verschijnt in het chatdownloadcontextmenu" - }, - "media_file_picker": { - "name": "Mediabestandkiezer", - "description": "Hiermee kunt u elk video-/audiobestand uit de galerij kiezen" - }, - "story_logger": { - "name": "Verhaallogger", - "description": "Biedt een geschiedenis van vriendenverhalen" - }, - "call_recorder": { - "name": "Oproeprecorder", - "description": "Neemt automatisch audiogesprekken op" - }, - "account_switcher": { - "name": "Accountwisselaar", - "description": "Hiermee kunt u tussen accounts schakelen zonder uit te loggen\nDruk lang op het zoekpictogram naast uw Bitmoji-profiel om het menu te openen\nOpmerking: deze functie is experimenteel en zal waarschijnlijk in de toekomst veranderen", - "properties": { - "auto_backup_current_account": { - "name": "Automatische back-up van huidige account", - "description": "Maakt automatisch een back-up van het huidige account bij het uitloggen of wisselen van account" - } - } - }, - "better_transcript": { - "name": "Betere transcriptie", - "description": "Verbetert het transcript van de spraaknotities", - "properties": { - "force_transcription": { - "name": "Forceer transcriptie van spraaknotities", - "description": "Hiermee kunnen alle spraaknotities worden getranscribeerd" - }, - "preferred_transcription_lang": { - "name": "Voorkeur transcriptietaal", - "description": "De voorkeurstaal voor het transcript van de gesproken notitie (bijv. EN, ES, FR)" - }, - "notification_transcript": { - "name": "Meldingtranscriptie", - "description": "Transcribeert spraaknotities in meldingen\nVoor deze functie moet de functie Chatvoorbeeld zijn ingeschakeld in Betere meldingen" - } - } - }, - "voice_note_auto_play": { - "name": "Automatisch afspelen van spraaknotities", - "description": "Speelt automatisch de volgende stemnoot af nadat de huidige is afgelopen" - }, - "friend_notes": { - "name": "Vriend notities", - "description": "Hiermee kunt u notities toevoegen aan vriendenprofielen" - }, - "cof_experiments": { - "name": "COF-experimenten", - "description": "Schakelt niet-uitgebrachte/bèta-Snapchat-functies in" - }, - "context_menu_fix": { - "name": "Contextmenu opgelost", - "description": "Probeer het vriendenfeedmenu te repareren, want wanneer het apparaat offline is, kan het niet correct worden weergegeven" - }, - "app_lock": { - "name": "App-vergrendeling", - "description": "Voorkomt toegang tot Snapchat zonder toegangscode", - "properties": { - "lock_on_resume": { - "name": "Vergrendelen bij hervatten", - "description": "Vergrendelt de app wanneer deze opnieuw wordt geopend" - } - } - }, - "infinite_story_boost": { - "name": "Oneindige verhaalboost", - "description": "Omzeil de Verhaalboostlimietvertraging" - }, - "meo_passcode_bypass": { - "name": "My Eyes Only-toegangscode omzeilen", - "description": "Omzeil de My Eyes Only-toegangscode\nDit werkt alleen als de toegangscode eerder correct is ingevoerd" - }, - "no_friend_score_delay": { - "name": "Geen vertraging in de vriendenscore", - "description": "Verwijdert de vertraging bij het bekijken van een vriendenscore" - }, - "best_friend_pinning": { - "name": "Beste vriend vastzetten", - "description": "Hiermee kunt u een vriend vastzetten als uw beste vriend. Let op: alleen jij kunt je vastgezette beste vriend zien" - }, - "e2ee": { - "name": "End-to-end-codering", - "description": "Versleutelt uw berichten met AES met behulp van een gedeelde geheime sleutel\nZorg ervoor dat u uw sleutel op een veilige plek bewaart!", - "properties": { - "encrypted_message_indicator": { - "name": "Gecodeerde berichtindicator", - "description": "Voegt een 🔒 emoji toe naast gecodeerde berichten" - }, - "force_message_encryption": { - "name": "Forceer berichtcodering", - "description": "Voorkomt dat gecodeerde berichten alleen worden verzonden naar mensen voor wie E2E-codering niet is ingeschakeld als er meerdere gesprekken zijn geselecteerd" - } - } - }, - "add_friend_source_spoof": { - "name": "Voeg vriendbronspoof toe", - "description": "Spoof de bron van een vriendschapsverzoek" - }, - "hidden_snapchat_plus_features": { - "name": "Verborgen Snapchat Plus-functies", - "description": "Schakelt niet-uitgebrachte/bèta-Snapchat Plus-functies in\nWerkt mogelijk niet op oudere Snapchat-versies" - }, - "custom_streaks_expiration_format": { - "name": "Aangepast verloopformaat voor strepen", - "description": "Past het Streaks Expiration-formaat aan\n\nBeschikbare variabelen:\n - %c: aantal strepen\n - %e: Zandloper-emoji\n - %d: Dagen\n - %h: uren\n - %m: minuten\n - %s: Seconden\n - %w: resterende tijd" - }, - "prevent_forced_logout": { - "name": "Voorkom gedwongen uitloggen", - "description": "Voorkomt dat Snapchat je uitlogt wanneer je inlogt op een ander apparaat" - }, - "snapscore_changes": { - "name": "Snapscore-wijzigingen", - "description": "Houdt veranderingen bij in de Snapscore van vrienden\nGebruik deze functie alleen in nieuwere versies van Snapchat" - } - } - }, - "scripting": { - "name": "Scripten", - "description": "Voer aangepaste scripts uit om PurrfectSnap uit te breiden", - "properties": { - "developer_mode": { - "name": "Ontwikkelaarsmodus", - "description": "Toont foutopsporingsinformatie in de gebruikersinterface van Snapchat" - }, - "module_folder": { - "name": "Modulemap", - "description": "De map waarin de scripts zich bevinden" - }, - "auto_reload": { - "name": "Automatisch herladen", - "description": "Laadt automatisch scripts wanneer ze veranderen" - }, - "integrated_ui": { - "name": "Geïntegreerde gebruikersinterface", - "description": "Hiermee kunnen scripts aangepaste UI-componenten aan Snapchat toevoegen" - }, - "disable_log_anonymization": { - "name": "Schakel anonimisering van logbestanden uit", - "description": "Schakelt de anonimisering van logs uit" - }, - "disable_optimization": { - "name": "Optimalisatie uitschakelen", - "description": "Schakelt de optimalisatie van scripts uit. Dit kan prestatieproblemen veroorzaken." - } - } - }, - "friend_tracker": { - "name": "Vriendentracker", - "description": "Registreert de activiteit van een vriend op Snapchat", - "properties": { - "record_messaging_events": { - "name": "Berichtgebeurtenissen opnemen", - "description": "Registreert berichtengebeurtenissen zoals het openen van een module, het lezen van een bericht, enz." - }, - "allow_running_in_background": { - "name": "Sta uitvoeren op de achtergrond toe", - "description": "Hiermee kan de tracker op de achtergrond worden uitgevoerd. Opmerking: hierdoor wordt uw batterij aanzienlijk leeggetrokken" - }, - "auto_purge": { - "name": "Automatisch zuiveren", - "description": "Verwijdert automatisch opgeslagen gebeurtenissen die ouder zijn dan de opgegeven tijdsduur" - } - } - } - }, - "options": { - "app_appearance": { - "always_light": "Altijd licht", - "always_dark": "Altijd donker" - }, - "friend_feed_menu_buttons": { - "auto_download": "⬇️ Automatisch downloaden", - "auto_save": "💬 Berichten automatisch opslaan", - "unsaveable_messages": "⬇️ Niet-op te slaan berichten", - "auto_open_snaps": "📷 Automatisch openen van snaps", - "stealth": "👻 Stealth-modus", - "mark_snaps_as_seen": "👀 Markeer Snaps zoals gezien", - "mark_stories_as_seen_locally": "👀 Markeer Verhalen zoals lokaal gezien", - "conversation_info": "👤 Gespreksinformatie", - "e2e_encryption": "🔒 Gebruik E2E-codering" - }, - "path_format": { - "create_author_folder": "Maak een map voor elke auteur", - "create_source_folder": "Maak een map voor elk type mediabron", - "append_hash": "Voeg een unieke hash toe aan de bestandsnaam", - "append_source": "Voeg de mediabron toe aan de bestandsnaam", - "append_username": "Voeg de gebruikersnaam toe aan de bestandsnaam", - "append_date_time": "Voeg de datum en tijd toe aan de bestandsnaam" - }, - "auto_download_sources": { - "friend_snaps": "Vriendensnaps", - "friend_stories": "Vriend verhalen", - "public_stories": "Openbare verhalen", - "spotlight": "Spotlight" - }, - "logging": { - "started": "Gestart", - "success": "Succes", - "progress": "Voortgang", - "failure": "Mislukking" - }, - "notifications": { - "chat_screenshot": "Schermafbeelding", - "chat_screen_record": "Schermopname", - "snap_replay": "Snap herhaling", - "camera_roll_save": "Camerarol opslaan", - "chat": "Chatten", - "chat_reply": "Chatantwoord", - "snap": "Snap", - "typing": "Typen", - "stories": "Verhalen", - "speaking": "Spreken", - "chat_reaction": "DM-reactie", - "group_chat_reaction": "Groepsreactie", - "initiate_audio": "Inkomend audiogesprek", - "abandon_audio": "Gemist audiogesprek", - "initiate_video": "Inkomend videogesprek", - "abandon_video": "Gemist videogesprek", - "map_live_location": "Kaart live locatie" - }, - "gallery_media_send_override": { - "always_ask": "Vraag altijd", - "ORIGINAL": "Originele media", - "NOTE": "Audionoot", - "SNAP": "Snap", - "SAVEABLE_SNAP": "Bewaarbare module" - }, - "strip_media_metadata": { - "hide_caption_text": "Onderschrifttekst verbergen", - "hide_snap_filters": "Snapfilters verbergen", - "hide_extras": "Extra's verbergen (bijvoorbeeld vermeldingen)", - "remove_audio_note_duration": "Duur van audionoot verwijderen", - "remove_audio_note_transcript_capability": "Verwijder de mogelijkheid tot transcriptie van audionotities" - }, - "hide_ui_components": { - "hide_profile_call_buttons": "Verwijder profieloproepknoppen", - "hide_chat_call_buttons": "Chat-oproepknoppen verwijderen", - "hide_live_location_share_button": "Knop Live locatie delen verwijderen", - "hide_stickers_button": "Knop Stickers verwijderen", - "hide_voice_record_button": "Knop voor spraakopname verwijderen", - "hide_unread_chat_hint": "Ongelezen chathint verwijderen", - "hide_post_to_story_buttons": "Verwijder de Post-to-Story-knoppen voordat u een Snap verzendt", - "hide_billboard_prompt": "Verwijder de Billboard-prompt in de vriendenfeed", - "hide_snapchat_plus_gift_reminders": "Verwijder Snapchat Plus-cadeauherinneringen uit gesprekken", - "hide_map_reactions": "Kaartreacties verwijderen" - }, - "hide_story_suggestions": { - "hide_suggested_friend_stories": "Verberg voorgestelde vriendverhalen", - "hide_my_stories": "Verberg mijn verhalen" - }, - "home_tab": { - "map": "Kaart", - "chat": "Chatten", - "camera": "Camera", - "discover": "Ontdekken", - "spotlight": "Spotlight" - }, - "add_friend_source_spoof": { - "added_by_username": "Op gebruikersnaam", - "added_by_mention": "Door vermelding", - "added_by_group_chat": "Via groepschat", - "added_by_qr_code": "Via QR-code", - "added_by_community": "Per gemeenschap", - "added_by_quick_add": "Door Snel Toevoegen (groot risico om verbannen te worden)" - }, - "bypass_video_length_restriction": { - "single": "Enkele media", - "split": "Media splitsen" - }, - "old_bitmoji_selfie": { - "2d": "2D Bitmoji", - "3d": "3D Bitmoji" - }, - "disable_confirmation_dialogs": { - "erase_message": "Bericht wissen", - "remove_friend": "Vriend verwijderen", - "block_friend": "Vriend blokkeren", - "ignore_friend": "Negeer vriend", - "hide_friend": "Vriend verbergen", - "hide_conversation": "Gesprek verbergen", - "clear_conversation": "Wis het gesprek uit de vriendenfeed" - }, - "auto_reload": { - "snapchat_only": "Alleen Snapchat", - "all": "Alles (Snapchat + PurrfectSnap)" - }, - "edit_text_override": { - "multi_line_chat_input": "Chatinvoer met meerdere lijnen", - "bypass_text_input_limit": "Omzeil de tekstinvoerlimiet" - }, - "auto_purge": { - "never": "Nooit", - "1_hour": "1 uur", - "3_hours": "3 uur", - "6_hours": "6 uur", - "12_hours": "12 uur", - "1_day": "1 dag", - "3_days": "3 dagen", - "1_week": "1 week", - "2_weeks": "2 weken", - "1_month": "1 maand", - "3_months": "3 maanden", - "6_months": "6 maanden" - }, - "disable_story_sections": { - "friends": "Vrienden", - "suggested_stories": "Voorgestelde verhalen", - "following": "Volgende", - "discover": "Ontdekken" - }, - "disable_cameras": { - "front": "Camera aan de voorkant", - "back": "Achtercamera" - }, - "disable_permission_requests": { - "notifications": "Meldingen", - "read_media_images": "Mediabeelden lezen", - "read_media_video": "Mediavideo lezen", - "camera": "Camera", - "microphone": "Microfoon", - "location": "Locatie", - "read_contacts": "Lees Contacten", - "nearby_devices": "Apparaten in de buurt", - "phone_calls": "Telefoongesprekken" - }, - "message_indicators": { - "encryption_indicator": "Voegt een 🔒-pictogram toe naast berichten die alleen naar jou zijn verzonden", - "platform_indicator": "Voegt het platformpictogram toe waarvandaan een medium is verzonden (bijvoorbeeld Android, iOS, Web)", - "location_indicator": "Voegt een 📍-pictogram toe aan snaps wanneer deze zijn verzonden met ingeschakelde locatie", - "ovf_editor_indicator": "Geeft aan of een snap is verzonden met OVF Editor", - "director_mode_indicator": "Voegt een ✏️-pictogram toe aan snaps wanneer deze zijn verzonden via de Director-modus, die kan worden gebruikt om galerijafbeeldingen als snaps te verzenden" - }, - "auto_mark_as_read": { - "conversation_read": "Markeer het gesprek als gelezen wanneer u een bericht verzendt", - "snap_reply": "Markeer de tekst als gelezen wanneer u erop reageert", - "save_snap_in_chat": "Markeer snaps als gelezen wanneer u ze opslaat in de chat in de stealth-modus" - }, - "friend_mutation_notifier": { - "remove_friend": "Geef een melding wanneer iemand u als vriend verwijdert", - "birthday_changes": "Geef een melding wanneer iemand zijn of haar verjaardag wijzigt", - "bitmoji_selfie_changes": "Geef een melding wanneer iemand zijn Bitmoji-selfie wijzigt", - "bitmoji_avatar_changes": "Geef een melding wanneer iemand zijn Bitmoji-avatar wijzigt", - "bitmoji_background_changes": "Geef een melding wanneer iemand zijn Bitmoji-achtergrond verandert", - "bitmoji_scene_changes": "Geef een melding wanneer iemand zijn Bitmoji-scène verandert" - }, - "snapchat_plus": { - "not_subscribed": "Niet geabonneerd", - "basic": "Basis", - "ad_free": "Advertentie gratis" - }, - "double_tap_chat_action": { - "like_message": "Vind ik leuk bericht", - "copy_text": "Kopieer tekst naar klembord", - "delete_message": "Bericht verwijderen", - "mark_as_read": "Markeer als gelezen", - "custom_emoji_reaction": "Aangepaste Emoji-reactie" - }, - "startup_default_camera": { - "front": "Camera aan de voorkant", - "back": "Achtercamera" + }, + "name": "Gebruikersomgeving" } } }, - "friend_menu_option": { - "mark_snaps_as_seen": "Markeer Snaps zoals gezien", - "mark_stories_as_seen_locally": "Markeer verhalen zoals lokaal gezien", - "preview": "Voorbeeld", - "stealth_mode": "Stealth-modus", - "auto_download_blacklist": "Zwarte lijst automatisch downloaden", - "anti_auto_save": "Anti-automatisch opslaan" + "scopes": { + "friend": "Vriend", + "group": "Groep" }, - "content_type": { - "CHAT": "Chatten", - "SNAP": "Snap", - "EXTERNAL_MEDIA": "Externe media", - "NOTE": "Audionoot", - "STICKER": "Sticker", - "SHARE": "Deel", - "STATUS": "Status", - "LOCATION": "Locatie", - "STATUS_SAVE_TO_CAMERA_ROLL": "Opgeslagen op filmrol", - "STATUS_CONVERSATION_CAPTURE_SCREENSHOT": "Schermafbeelding", - "STATUS_CONVERSATION_CAPTURE_RECORD": "Schermopname", - "STATUS_CALL_MISSED_VIDEO": "Gemist videogesprek", - "STATUS_CALL_MISSED_AUDIO": "Gemist audiogesprek", - "LIVE_LOCATION_SHARE": "Live locatie delen", - "CREATIVE_TOOL_ITEM": "Creatief hulpmiddelitem", - "FAMILY_CENTER_INVITE": "Familiecentrum uitnodigen", - "FAMILY_CENTER_ACCEPT": "Familiecentrum Accepteren", - "FAMILY_CENTER_LEAVE": "Verlof gezinscentrum", - "STATUS_PLUS_GIFT": "Status Plus Cadeau", - "TINY_SNAP": "Kleine snap", - "STATUS_COUNTDOWN": "Aftellen", - "MAP_REACTION": "Kaartreactie" - }, - "media_download_source": { - "none": "Geen", - "pending": "In behandeling", - "chat_media": "Chatmedia", - "story": "Verhaal", - "public_story": "Openbaar verhaal", - "spotlight": "Spotlight", - "profile_picture": "Profielfoto", - "story_logger": "Verhaallogger", - "message_logger": "Berichtenlogger", - "merged": "Samengevoegd", - "voice_call": "Spraakoproep" - }, - "chat_action_menu": { - "preview_button": "Voorbeeld", - "download_button": "Downloaden", - "delete_logged_message_button": "Verwijder het geregistreerde bericht", - "show_chat_edit_history": "Chatbewerkingsgeschiedenis tonen", - "convert_message": "Bericht converteren" - }, - "opera_context_menu": { - "download": "Media downloaden", - "sent_at": "Verzonden op {date}", - "created_at": "Gemaakt op {date}", - "expires_at": "Verloopt op {date}", - "media_size": "Mediaformaat: {size}", - "media_duration": "Mediaduur: {duration} ms", - "show_debug_info": "Foutopsporingsinformatie weergeven" - }, - "modal_option": { - "profile_info": "Profielinformatie", - "close": "Dichtbij" - }, - "gallery_media_send_override": { - "multiple_media_toast": "U kunt slechts één medium tegelijk verzenden" - }, - "mark_as_seen": { - "no_unseen_snaps_toast": "Geen onzichtbare Snaps gevonden!", - "seen_toast": "Gemarkeerd als gezien!", - "unseen_toast": "Gemarkeerd als ongezien!", - "already_seen_toast": "Al gemarkeerd als gezien!", - "already_unseen_toast": "Al gemarkeerd als ongezien!" - }, - "conversation_preview": { - "streak_expiration": "verloopt over {day} dagen {hour} uur {minute} minuten", - "total_messages": "Totaal verzonden/ontvangen berichten: {count}", - "title": "Voorbeeld", - "unknown_user": "Onbekende gebruiker", - "no_messages": "Geen berichten gevonden!" - }, - "profile_info": { - "title": "Profielinformatie", - "first_created_username": "Eerste aangemaakte gebruikersnaam", - "mutable_username": "Veranderlijke gebruikersnaam", - "display_name": "Weergavenaam", - "added_date": "Datum toegevoegd", - "birthday": "Verjaardag: {month} {day}", - "hidden_birthday": "Verjaardag: Verborgen", - "friendship": "Vriendschap", - "add_source": "Bron toevoegen", - "snapchat_plus": "SnapchatPlus", - "snapchat_plus_state": { - "subscribed": "Geabonneerd", - "not_subscribed": "Niet geabonneerd" + "actions": { + "clean_snapchat_cache": { + "name": "Snapchat-cache opschonen", + "description": "Schoont de Snapchat-cache op" + }, + "export_chat_messages": { + "name": "Chatberichten exporteren", + "description": "Exporteert gespreksberichten naar een JSON/HTML/TXT-bestand" + }, + "manage_friend_list": { + "description": "Importeer/exporteer uw vriendenlijst bij het maken van een back-up", + "name": "Vriendenlijst beheren" + }, + "bulk_messaging_action": { + "name": "Bulkberichtactie", + "description": "Voert handelingen uit zoals het verwijderen van vrienden of het massaal verwijderen van gesprekken" + }, + "export_memories": { + "description": "Exporteert herinneringen naar een ZIP-bestand", + "name": "Herinneringen Exporteren" + }, + "change_language": { + "description": "Wijzig de taal van SnapEnhance", + "name": "Taal Wijzigen" + }, + "regen_mappings": { + "name": "Mappings Regenereren", + "description": "Mappings Handmatig Regenereren" + }, + "security_features": { + "name": "Beveiligingsfuncties" } - }, - "friendship_link_type": { - "mutual": "Wederzijds", - "outgoing": "Uitgaand", - "blocked": "Geblokkeerd", - "deleted": "Verwijderd", - "following": "Volgende", - "suggested": "Voorgesteld", - "incoming": "Inkomend", - "incoming_follower": "Inkomende volger" - }, - "bulk_messaging_action": { - "choose_action_title": "Kies een actie", - "progress_status": "Verwerking van {index} van {total}", - "selection_dialog_continue_button": "Doorgaan", - "confirmation_dialog": { - "title": "Weet je het zeker?", - "message": "Dit heeft invloed op alle geselecteerde vrienden. Deze actie kan niet ongedaan worden gemaakt." - }, - "actions": { - "remove_friends": "Vrienden verwijderen", - "clear_conversations": "Duidelijke gesprekken" - } - }, - "chat_export": { - "exporter_dialog": { - "select_conversations_title": "Selecteer Gesprekken", - "text_field_selection": "{amount} geselecteerd", - "text_field_selection_all": "Alle", - "export_file_format_title": "Bestandsformaat exporteren", - "message_type_filter_title": "Filter berichten op type", - "amount_of_messages_title": "Aantal berichten (laat dit voor iedereen leeg)", - "download_medias_title": "Media downloaden" - }, - "dialog_negative_button": "Annuleren", - "dialog_positive_button": "Exporteren", - "exported_to": "Geëxporteerd naar {path}", - "exporting_chats": "Chats exporteren...", - "processing_chats": "{amount} gesprekken verwerken...", - "export_fail": "Kan gesprek {conversation} niet exporteren", - "writing_output": "Uitvoer schrijven...", - "finished": "Klaar! U kunt dit dialoogvenster nu sluiten.", - "no_messages_found": "Geen berichten gevonden!", - "exporting_message": "{conversationName} exporteren..." - }, - "button": { - "ok": "OK", - "positive": "Ja", - "negative": "Nee", - "cancel": "Annuleren", - "open": "Open", - "download": "Downloaden", - "send": "Versturen", - "restore_original": "Origineel herstellen", - "convert_external_media": "Externe media converteren", - "save": "Redden" - }, - "tracker_events": { - "conversation_enter": "Gesprek binnenkomen", - "conversation_exit": "Gesprek verlaten", - "started_typing": "Begonnen met typen", - "stopped_typing": "Gestopt met typen", - "started_speaking": "Begon te praten", - "stopped_speaking": "Gestopt met praten", - "started_peeking": "Begonnen met gluren", - "stopped_peeking": "Gestopt met gluren", - "message_read": "Bericht gelezen", - "message_deleted": "Bericht verwijderd", - "message_saved": "Bericht opgeslagen", - "message_unsaved": "Bericht niet opgeslagen", - "message_edited": "Bericht bewerkt", - "message_reaction_add": "Bericht Reactie Toevoegen", - "message_reaction_remove": "Bericht Reactie Verwijderen", - "snap_opened": "Snap geopend", - "snap_replayed": "Snap opnieuw afgespeeld", - "snap_replayed_twice": "Snap tweemaal opnieuw afgespeeld", - "snap_screenshot": "Maak een screenshot", - "snap_screen_record": "Snap-schermopname" - }, - "tracker_actions": { - "log": "Logboek", - "in_app_notification": "In-app-melding", - "push_notification": "Pushmelding", - "custom": "Aangepast" - }, - "better_notifications": { - "button": { - "reply": "Antwoord", - "download": "Downloaden", - "mark_as_read": "Markeer als gelezen" - } - }, - "profile_picture_downloader": { - "button": "Profielfoto downloaden", - "title": "Profielfoto-downloader", - "avatar_option": "Avatar", - "background_option": "Achtergrond" - }, - "call_start_confirmation": { - "dialog_title": "Begin met bellen", - "dialog_message": "Weet u zeker dat u een gesprek wilt starten?" - }, - "half_swipe_notifier": { - "notification_channel_name": "Halve veeg", - "notification_content_dm": "{friend} is zojuist {duration} seconden half naar je chat geveegd", - "notification_content_group": "{friend} is net half naar {group} geveegd gedurende {duration} seconden" - }, - "download_processor": { - "attachment_type": { - "snap": "Snap", - "sticker": "Sticker", - "gif": "GIF", - "external_media": "Externe media", - "note": "Opmerking", - "original_story": "Origineel verhaal" - }, - "select_attachments_title": "Selecteer bijlagen", - "download_started_toast": "Het downloaden is gestart", - "unsupported_content_type_toast": "Niet-ondersteund inhoudstype!", - "failed_no_longer_available_toast": "Media niet meer beschikbaar", - "no_attachments_toast": "Geen bijlagen gevonden!", - "already_queued_toast": "Media staan ​​al in de wachtrij!", - "already_downloaded_toast": "Media al gedownload!", - "content_saved_toast": "Opgeslagen!", - "download_toast": "{friendlyName} downloaden...", - "processing_toast": "Verwerken {friendlyName}...", - "failed_generic_toast": "Kan niet downloaden", - "failed_to_create_preview_toast": "Kan voorbeeld niet maken", - "failed_processing_toast": "Mislukte verwerking {error}", - "failed_gallery_toast": "Opslaan in galerij {error} mislukt", - "dash_no_chapter": "Geen hoofdstuk gevonden", - "dash_dialog": { - "title": "Dashmedia downloaden", - "download_all": "Alles downloaden", - "segment_text": "Segment {from} - {to}" - } - }, - "streaks_reminder": { - "notification_title": "Strepen", - "notification_text": "Je verliest je Streak met {friend} over {hoursLeft} uur" - }, - "biometric_auth": { - "unlock_button": "Ontgrendelen", - "title": "Ontgrendel Snapchat", - "subtitle": "Authenticeer om Snapchat te ontgrendelen" - }, - "end_to_end_encryption": { - "toolbox": { - "no_shared_key": "Je hebt nog geen gedeeld geheim met deze vriend. Klik hieronder om een ​​nieuwe te starten.", - "shared_key_fingerprint": "Uw vingerafdruk is:\n\n{fingerprint}\n\nZorg ervoor dat u controleert of deze overeenkomt met de vingerafdruk van uw vriend!", - "initiate_exchange_button": "Start sleuteluitwisseling" - }, - "confirmation_dialogs": { - "title": "End-to-end-codering", - "confirmation_1": "WAARSCHUWING: Hierdoor wordt uw bestaande sleutel overschreven. Je verliest de toegang tot alle gecodeerde berichten van deze vriend. Weet u zeker dat u wilt doorgaan?", - "confirmation_2": "Weet u ECHT zeker dat u door wilt gaan? Dit is je laatste kans om je terug te trekken." - }, - "unencrypted_conversation_send_failure_toast": "Je kunt geen gecodeerde inhoud naar zowel gecodeerde als niet-gecodeerde gesprekken sturen!", - "native_hooks_send_failure_toast": "Kan niet verzenden! Schakel Native Hooks in de instellingen in.", - "no_participants_to_encrypt_toast": "Je hebt geen vrienden in dit gesprek waarmee je berichten kunt versleutelen!", - "encryption_failed_toast": "Kan het bericht niet coderen! Controleer logcat voor meer details.", - "accept_public_key_success_toast": "Publieke sleutel succesvol geaccepteerd!", - "accept_secret_key_success_toast": "Klaar! Je kunt nu gecodeerde berichten verzenden en ontvangen met deze vriend.", - "accept_public_key_failure_toast": "Kan de openbare sleutel niet accepteren", - "accept_secret_key_failure_toast": "Kan de geheime sleutel niet accepteren", - "accept_secret_button": "Accepteer geheim", - "accept_public_key_button": "Accepteer de openbare sleutel", - "outgoing_pk_message": "Verzoek om sleuteluitwisseling", - "outgoing_secret_message": "Reactie op sleuteluitwisseling", - "incoming_pk_message": "U heeft zojuist een verzoek om een ​​openbare sleutel ontvangen. Klik hieronder om het te accepteren.", - "incoming_secret_message": "Je vriend heeft zojuist je openbare sleutel geaccepteerd. Klik hieronder om het geheim te accepteren." - }, - "auto_open_snaps": { - "title": "Automatisch openende snaps", - "notification_content": "{count} Snaps geopend" - }, - "friend_mutation_observer": { - "notification_channel_name": "Vriendmutatiewaarnemer", - "friend_removed": "{username} heeft je als vriend verwijderd", - "birthday_removed": "{username} heeft zijn of haar verjaardag verwijderd ({birthday})", - "birthday_added": "{username} heeft zijn of haar verjaardag toegevoegd ({birthday})", - "birthday_changed": "{username} heeft zijn verjaardag gewijzigd van {oldBirthday} in {newBirthday}", - "bitmoji_selfie_changed": "{username} heeft zijn Bitmoji-selfie gewijzigd", - "bitmoji_avatar_changed": "{username} heeft zijn Bitmoji-avatar gewijzigd", - "bitmoji_background_changed": "{username} heeft de Bitmoji-achtergrond gewijzigd", - "bitmoji_scene_changed": "{username} heeft zijn/haar Bitmoji-scène gewijzigd" - }, - "material3_strings": { - "date_range_picker_start_headline": "Van", - "date_range_picker_end_headline": "Naar", - "date_range_picker_title": "Selecteer een datumbereik", - "date_picker_switch_to_calendar_mode": "Kalender", - "date_picker_switch_to_input_mode": "Invoer", - "date_range_picker_scroll_to_previous_month": "Vorige maand", - "date_range_picker_scroll_to_next_month": "Volgende maand", - "date_picker_today_description": "Vandaag", - "date_range_picker_day_in_range": "Gekozen", - "date_input_invalid_for_pattern": "Ongeldige datum", - "date_input_invalid_year_range": "Ongeldig jaar", - "date_input_invalid_not_allowed": "Ongeldige datum", - "date_range_input_invalid_range_input": "Ongeldig datumbereik" - }, - "send_override_dialog": { - "title": "Media verzenden als {type}", - "duration": "Duur: {duration}", - "saveable_snap_hint": "Maak Snap bewaarbaar in de chat", - "unlimited_duration": "Onbeperkt" - }, - "invalid_input_toast": "Ongeldige invoer! Zorg ervoor dat u een geldige waarde heeft ingevoerd." -} \ No newline at end of file + } +} diff --git a/common/src/main/assets/lang/no.json b/common/src/main/assets/lang/no.json deleted file mode 100644 index de92f117..00000000 --- a/common/src/main/assets/lang/no.json +++ /dev/null @@ -1,2022 +0,0 @@ -{ - "setup": { - "dialogs": { - "select_language": "Velg språk", - "save_folder": "PurrFectSnap krever lagringstillatelser for å laste ned og lagre medier fra Snapchat.\nVelg stedet der media skal lastes ned til.", - "select_save_folder_button": "Velg mappe" - }, - "mappings": { - "dialog": "Å generere kartlegginger, dette kan ta en stund ...", - "generate_failure_no_snapchat": "PurrFectSnap klarte ikke å oppdage Snapchat, prøv å installere Snapchat på nytt.", - "generate_failure": "En feil oppstod mens du prøver å generere kartlegginger, prøv igjen." - }, - "permissions": { - "dialog": "For å fortsette må du passe til følgende krav:", - "notification_access": "Varslingsadgang", - "battery_optimization": "Batterioptimalisering", - "display_over_other_apps": "Vis over andre apper", - "request_button": "Forespørsel" - } - }, - "scopes": { - "friend": "Venn", - "group": "Gruppe" - }, - "manager": { - "routes": { - "tasks": "Oppgaver", - "features": "Funksjoner", - "manage_rule_feature": "Administrer regelfunksjon", - "home": "Hjem", - "home_settings": "Innstillinger", - "home_logs": "Logger", - "logger_history": "Loggerhistorie", - "logged_stories": "Loggede historier", - "friend_tracker": "Friend Tracker", - "edit_rule": "Rediger regel", - "file_imports": "Filimport", - "manage_repos": "Administrer depoter", - "social": "Sosial", - "manage_scope": "Administrer omfang", - "messaging_preview": "Forhåndsvisning", - "scripts": "Skript", - "better_location": "Bedre beliggenhet" - }, - "sections": { - "home": { - "version_title": "v{versionName} · gaffel av evig", - "update_title": "PurrFectSnap -oppdatering", - "update_content": "Versjon {version} er tilgjengelig!", - "update_button": "Last ned", - "debug_build_summary_title": "Du kjører en feilsøking av purrfectsnap", - "debug_build_summary_content": "Versjon {versionName} ({versionCode})", - "debug_build_summary_date": "Bygg dato: {date} ({days} dager siden)", - "quick_actions_title": "Raske handlinger", - "download_icon_description": "Last ned", - "completed_icon_description": "Fullført", - "failed_icon_description": "Mislyktes", - "manage_quick_actions_description": "Administrer raske handlinger", - "quick_actions_icon_description": "Raske handlinger", - "add_quick_action_description": "Legg til rask handling" - }, - "home_logs": { - "no_logs_hint": "Ingen logger tilgjengelig", - "clear_logs_button": "Klare tømmerstokker", - "export_logs_button": "Eksportlogger", - "saving_logs_toast": "Lagre logger, dette kan ta en stund ...", - "saved_logs_success_toast": "Logger lagret", - "saved_logs_failure_toast": "Kunne ikke lagre logger" - }, - "home_settings": { - "actions_title": "Handlinger", - "message_logger_title": "Meldingslogger", - "debug_title": "Feilsøking", - "success_toast": "Gjort!", - "message_logger_summary": "{messageCount} meldinger\n{storyCount} Stories", - "export_button": "Eksport", - "clear_button": "Klar", - "view_logger_history_button": "Se loggerhistorikk", - "updates_title": "Oppdateringer", - "auto_update_check": "Auto Sjekk for oppdateringer", - "update_check_frequency": "Oppdater sjekkfrekvens", - "update_check_frequency_daily": "Daglig", - "update_check_frequency_weekly": "Ukentlig", - "update_check_frequency_monthly": "Månedlig", - "theme_icon_description": "Tema", - "app_theme_title": "App tema", - "theme_mode_system": "System", - "theme_mode_light": "Lys", - "theme_mode_dark": "Mørk", - "ui_settings_title": "UI -innstillinger", - "haptic_feedback_label": "Haptisk tilbakemelding", - "test_mode_label": "Testmodus (bare for feilsøking)", - "disable_feature_loading_label": "Deaktiver funksjonsbelastning", - "disable_auto_mapper_label": "Deaktiver autokart", - "disable_bypass_indicator_label": "Deaktiver bypass -statusindikator", - "update_notification_channel_name": "PurrFectSnap -oppdateringer", - "update_notification_channel_description": "Varsler for PurrfectSnap -oppdateringer", - "update_notification_title": "PurrFectSnap -oppdatering tilgjengelig", - "update_notification_text": "Versjon {version} er nå tilgjengelig.", - "export_database_failed_toast": "Kunne ikke eksportere database! {message}", - "clear_messages_failed_toast": "Kunne ikke fjerne meldinger! {message}", - "clear_file_failed_toast": "Kunne ikke fjerne filen! {message}", - "debug_file_config": "Konfigurasjon", - "debug_file_mappings": "Kartlegginger", - "debug_file_message_logger": "Meldingslogger", - "debug_file_pinned_best_friend": "Festet bestevenn", - "debug_file_native_sig_cache": "Innfødt signaturbuffer" - }, - "tasks": { - "no_tasks": "Ingen oppgaver", - "merge_button": "Fusjonere", - "failed_to_open_file": "Kunne ikke åpne filen", - "merge_files_toast": "Sammenslåing {count} filer", - "remove_selected_tasks_title": "Er du sikker på at du vil fjerne utvalgte oppgaver?", - "remove_all_tasks_title": "Er du sikker på at du vil fjerne alle oppgaver?", - "delete_files_option": "Slett også filer", - "remove_selected_tasks_confirm": "Fjern {count} oppgaver?", - "remove_all_tasks_confirm": "Fjerne alle oppgaver?", - "clear_tasks_description": "Klare oppgaver", - "file_not_found_icon_description": "Filen ikke funnet", - "image_icon_description": "Bilde", - "video_icon_description": "Video", - "audio_icon_description": "Lyd", - "file_icon_description": "Fil", - "download_icon_description": "Last ned", - "chat_action_icon_description": "Chathandling", - "cancel_icon_description": "Kansellere", - "success_icon_description": "Suksess", - "failure_icon_description": "Feil", - "cancelled_icon_description": "Kansellert", - "task_status_failure": "Feil", - "task_status_cancelled": "Kansellert" - }, - "features": { - "disabled": "Funksjonshemmet", - "export_option": "Eksport", - "import_option": "Import", - "reset_option": "Tilbakestill", - "config_export_success_toast": "Konfigurert eksportert vellykket", - "config_import_success_toast": "Konfigurert importert vellykket", - "config_import_failure_toast": "Kunne ikke importere konfigurasjon {error}", - "config_export_failure_toast": "Kunne ikke eksportere konfigurasjon {error}", - "saved_config_snackbar": "Konfigurert lagret", - "older_required": "Denne funksjonen krever Snapchat V{version} eller eldre å fungere riktig", - "newer_required": "Denne funksjonen krever Snapchat V{version} eller nyere å fungere riktig", - "search_button": "Søk" - }, - "manage_rule_feature": { - "disable_state_option": "Funksjonshemmet", - "disable_state_subtext": "Ingen venner/grupper vil bli berørt", - "whitelist_state_option": "Ingen bortsett fra ...", - "whitelist_state_subtext": "Bare {count} venner/grupper vil bli påvirket av denne regelen", - "whitelist_state_button": "Velg tillatte venner/grupper", - "blacklist_state_option": "Alle unntatt ...", - "blacklist_state_subtext": "Alle unntatt {count} venner/grupper vil bli berørt av denne regelen", - "blacklist_state_button": "Velg ekskluderte venner/grupper", - "clear_list_button": "Klare venner/grupper liste", - "dialog_clear_confirmation_text": "Er du sikker på at du vil tømme listen?" - }, - "social": { - "friends_tab": "Venner", - "groups_tab": "Grupper", - "empty_hint": "(tømme)", - "streaks_expiration_short": "{hours}h" - }, - "manage_scope": { - "logged_stories_button": "Vis loggede historier", - "e2ee_title": "Ende-til-ende kryptering", - "rules_title": "Regler", - "participants_text": "{count} Deltakere", - "not_found": "Ikke funnet", - "streaks_title": "Streker", - "streaks_length_text": "Lengde: {length}", - "streaks_expiration_text": "Utløper i {eta}", - "streaks_expiration_text_expired": "Utløpt", - "reminder_button": "Sett påminnelse", - "delete_scope_confirm_dialog_title": "Er du sikker på at du vil slette en {scope}?", - "notes_placeholder": "Klikk for å legge til et notat", - "invalid_key_size_32_bytes": "Ugyldig nøkkelstørrelse (må være 32 byte)", - "successfully_imported_key": "Vellykket importert nøkkel", - "failed_to_import_key": "Kunne ikke importere nøkkel: {message}", - "export_base64_button": "Eksportbase64", - "import_base64_button": "Importer base64" - }, - "logged_stories": { - "story_failed_to_load": "Kunne ikke laste", - "no_stories": "Ingen historier funnet", - "save_from_cache_button": "Lagre fra cache", - "downloaded_to_path": "Lastet ned til {path}", - "download_failed": "Nedlasting mislyktes: {message}", - "posted_at": "Skrevet på {date}", - "created_at": "Opprettet på {date}", - "failed_to_open_file": "Kunne ikke åpne filen. Sjekk logger for mer info", - "failed_to_get_file": "Kunne ikke få fil" - }, - "messaging_preview": { - "processed_messages_toast": "Behandlet {count} meldinger", - "processed_messages_text": "Behandlet {count} meldinger", - "close_button_description": "Lukke", - "bridge_connection_failed": "Kunne ikke koble til bro. Forsikre deg om at Snapchat kjører i bakgrunnen", - "bridge_init_failed": "Kunne ikke initialisere meldingsbroen. Forsikre deg om at Snapchat kjører i bakgrunnen", - "message_fetch_failed": "Kunne ikke hente meldinger", - "no_message_hint": "Ingen melding", - "save_selection_option": "Lagre valg", - "save_all_option": "Lagre alt", - "unsave_selection_option": "Unsave utvalg", - "unsave_all_option": "Unsav alt", - "mark_selection_as_seen_option": "Mark valgte snap som sett", - "mark_all_as_seen_option": "Merk alle snaps som sett", - "delete_selection_option": "Slett valg", - "delete_all_option": "Slett alle" - }, - "logger_history": { - "download_started_toast": "Last ned startet!", - "download_success_toast": "Lastet ned til {path}", - "download_failed_toast": "Kunne ikke laste ned {message}", - "edited_at_text": "{message} (redigert på {date})", - "download_button": "Last ned", - "select_conversation_placeholder": "Velg en samtale", - "close_button_description": "Lukke", - "search_button_description": "Søk", - "list_friend_format": "Venn {name}", - "list_group_format": "Gruppe {name}", - "no_more_messages": "Ikke flere meldinger", - "reverse_order_checkbox": "Omvendt ordre", - "chat_attachment": "Vedlegg {index}", - "empty_message": "Tom chat -melding", - "message_parse_failed": "Kunne ikke analysere melding", - "unknown_sender": "Ukjent avsender", - "download_attachment_failed_toast": "Kunne ikke laste ned vedlegg", - "log_header_format": "{username} ({type}) - {date}" - }, - "file_imports": { - "import_file_button": "Importfil", - "file_not_found": "Filen ikke funnet", - "file_import_failed": "Kunne ikke importere fil: {error}", - "file_imported": "Fil importert vellykket", - "file_delete_failed": "Kunne ikke slette filen", - "no_files_hint": "Her kan du importere filer for bruk i Snapchat. Trykk på knappen nedenfor for å importere en fil." - }, - "better_location": { - "spoofed_coordinates_title": "Lat {latitude}, lng {longitude}", - "save_coordinates_dialog_title": "Lagre koordinater", - "saved_name_dialog_hint": "Lagret navn", - "latitude_dialog_hint": "Breddegrad", - "longitude_dialog_hint": "Lengdegrad", - "save_dialog_button": "Spare", - "choose_location_button": "Velg sted", - "teleport_to_friend_button": "Teleporter til venn", - "spoof_location_toggle": "Spoof beliggenhet", - "suspend_location_updates": "Suspender beliggenhetsoppdateringer", - "saved_coordinates_title": "Lagrede koordinater", - "no_saved_coordinates_hint": "Ingen lagrede koordinater", - "delete_dialog_title": "Slett lagret koordinat", - "delete_dialog_message": "Er du sikker på at du vil slette denne lagrede koordinaten?", - "teleport_to_friend_title": "Teleporter til venn", - "search_bar": "Søk", - "no_friends_map": "Ingen venner på kartet", - "no_friends_found": "Ingen venner fant", - "edit_location_button_description": "Rediger plassering", - "add_icon_description": "Legge til", - "edit_icon_description": "Redigere", - "delete_icon_description": "Slett" - } - }, - "dialogs": { - "add_friend": { - "title": "Legg til venn eller gruppe", - "search_hint": "Søk", - "fetch_error": "Kunne ikke hente data", - "category_groups": "Grupper", - "category_friends": "Venner", - "participants_text": "{count} Deltakere", - "search_icon_description": "Søk" - }, - "scripting_warning": { - "title": "Advarsel", - "content": "PurrFectSnap inkluderer et skriptingsverktøy, slik at utførelse av brukerdefinert kode på enheten din. Bruk ekstrem forsiktighet og installer bare moduler fra kjente, pålitelige kilder. Uautoriserte eller ubekreftede moduler kan utgjøre sikkerhetsrisiko for systemet ditt." - }, - "reset_config": { - "title": "Tilbakestill konfigurasjon", - "content": "Er du sikker på at du vil tilbakestille konfigurasjonen?", - "success_toast": "Konfigurer tilbakestilling" - }, - "export_config": { - "title": "Eksportfølsomme data?", - "content": "Vil du eksportere konfigurasjonen med sensitive data? (For eksempel stedskoordinater osv.)" - }, - "messaging_action": { - "title": "Velg innholdstyper for å behandle", - "select_all_button": "Velg alt" - }, - "file_imports": { - "no_files_settings_hint": "Ingen filer funnet. Forsikre deg om at du har importert de nødvendige filene i filimportseksjonen", - "settings_select_file_hint": "Velg en importert fil" - }, - "quick_actions_dialog": { - "title": "Rediger raske handlinger", - "subtitle": "Velg og størrelse på dine raske handlinger." - } - }, - "friend_tracker": { - "rules_tab": "Regler", - "logs_tab": "Logger", - "export_dialog_title": "Eksport", - "bulk_export_button": "Bulkeksport", - "individual_export_button": "Individuell eksport", - "invalid_import_type_dialog_title": "Ugyldig importtype", - "invalid_import_type_dialog_text": "Den valgte filen er ikke kompatibel med denne importtypen. Velg riktig importtype.", - "import_dialog_title": "Import", - "bulk_import_button": "Bulkimport", - "individual_import_button": "Individuell import", - "import_button_description": "Import", - "export_button_description": "Eksport", - "export_button": "Eksport", - "delete_button_description": "Slett", - "delete_button": "Slett", - "catalog_button_description": "Katalog", - "catalog_button": "Katalog", - "add_rule_button_description": "Legg til regel", - "add_rule_button": "Legg til regel", - "no_rules_found": "Ingen regler funnet", - "empty_rule_name": "(tømme)", - "events_suffix": "hendelser", - "scopes_suffix": "omfang", - "select_rule_to_export_title": "Velg regel for å eksportere", - "deleted_logs_toast": "Slettet {count} logger", - "delete_logs_dialog_title": "Slette logger?", - "deleting_logs_dialog_text": "Slette {count} logger ...", - "delete_logs_dialog_confirm_text": "Dette vil slette logger basert på det gjeldende filteret og søket. Denne handlingen kan ikke angres.", - "exported_logs_toast": "Eksporterte tømmerstokker!", - "export_logs_failed_toast": "Kunne ikke eksportere logger. Sjekk LogCat for mer informasjon.", - "export_logs_dialog_title": "Eksportlogger?", - "exporting_logs_dialog_text": "Eksporterer logger ...", - "export_logs_dialog_confirm_text": "Dette vil eksportere logger basert på det gjeldende filteret og søket.", - "export_as_button": "Eksporter som {type}", - "filters_title": "Filtre", - "search_by_label": "Søk av", - "newest_first_label": "Nyeste først", - "since_label": "Siden", - "until_label": "Til", - "pick_a_date_button": "Velg en date", - "search_placeholder": "Søk", - "filter_button_description": "Filter", - "clear_button_description": "Klar", - "no_logs_found": "Ingen logger funnet", - "log_event_format": "{event} i {conversation}", - "condition_only_inside_conversation": "Bare når jeg er inne i samtalen", - "condition_only_outside_conversation": "Bare når jeg er utenfor samtalen", - "condition_only_when_app_active": "Bare når Snapchat er aktiv", - "condition_only_when_app_inactive": "Bare når Snapchat er inaktiv", - "condition_no_push_notification_when_app_active": "Ingen varsel når Snapchat er aktiv", - "add_event_dialog_title": "Legg til arrangement", - "event_type_label": "Hendelsestype", - "triggers_title": "Utløser", - "conditions_title": "Forhold", - "add_button": "Legge til", - "default_rule_name": "Tilpasset regel", - "discard_changes_dialog_title": "Kast endringer?", - "discard_changes_dialog_text": "Du har ufrelte endringer. Er du sikker på at du vil forkaste dem?", - "discard_button": "Kast", - "cannot_save_rule_dialog_title": "Kan ikke redde regel", - "cannot_save_rule_dialog_text": "En regel må ha minst en hendelse å spare.", - "duplicate_rule_name_dialog_title": "Dupliser regelnavn", - "duplicate_rule_name_dialog_text": "En regel med dette navnet eksisterer allerede. Velg et annet navn.", - "delete_rule_dialog_title": "Slett regel", - "delete_rule_dialog_text": "Er du sikker på at du vil slette denne regelen?", - "new_rule_title": "Ny regel", - "edit_rule_title": "Rediger regel", - "back_button_description": "Tilbake", - "save_button_description": "Spare", - "general_section_title": "General", - "rule_name_label": "Regelnavn", - "author_name_label": "Forfatternavn", - "scope_section_title": "Omfang", - "scope_all": "Alle", - "scope_whitelist": "Hviteliste", - "scope_blacklist": "Svarteliste", - "select_friends_groups_button": "Velg venner/grupper ({count})", - "events_section_title": "Hendelser", - "add_event_button": "Legg til arrangement", - "no_events_text": "Ingen hendelser" - }, - "friend_tracker_catalog": { - "download_failed": "Mislykket nedlasting: {code}", - "error": "Feil: {message}", - "no_repos_added": "Ingen depoter lagt til.", - "no_rules_available": "Ingen regler tilgjengelig fra noen repo.", - "by_author": "av {author}", - "imported_button": "Importert", - "import_button": "Import", - "title": "Friend Tracker Catalog", - "manage_repos_description": "Administrer depoter" - }, - "friend_tracker_export": { - "title": "Eksportregler", - "back_button_description": "Tilbake", - "exported_toast": "Friend Tracker regler eksportert!", - "export_failed_toast": "Kunne ikke eksportere regler: {message}", - "save_button": "Spare", - "expand_button_description": "Utvide" - }, - "friend_tracker_import": { - "title": "Importere regler", - "back_button_description": "Tilbake", - "imported_toast": "Friend Tracker regler importert!", - "import_failed_toast": "Kunne ikke importere regler: {message}", - "confirm_button": "Bekrefte", - "expand_button_description": "Utvide" - }, - "friend_tracker_repos": { - "invalid_repo_title": "Ugyldig depot", - "add_repo_button": "Legg til depot", - "add_repo_dialog_title": "Legg til depot -URL", - "repo_url_label": "URL", - "repo_added_toast": "Depot lagt til vellykket!", - "invalid_repo_error": "Dette ser ikke ut til å være et gyldig vennsporing.", - "add_repo_failed_toast": "Kunne ikke legge til depot: {message}", - "add_button": "Legge til", - "no_repos_added": "Ingen depoter lagt til", - "remove_button": "Fjerne", - "remove_repo_dialog_title": "Fjern depot", - "remove_repo_dialog_text": "Er du sikker på at du vil fjerne dette depotet?" - }, - "navigation": { - "tracker_tab_label": "Tracker", - "customize_bottom_bar_title": "Tilpass bunnstangen", - "customize_bottom_bar_subtitle": "Ombestill, legg til eller fjern faner. Maks av fem.", - "shown_tabs_title": "Viste faner", - "no_tabs_selected_text": "Ingen faner valgt", - "available_tabs_title": "Tilgjengelige faner", - "reset_button": "Tilbakestill", - "done_button": "Ferdig" - }, - "scripting": { - "script_already_installed": "Skript allerede installert!", - "downloading_script": "Last ned manus ...", - "script_downloaded": "Manus {name} lastet ned!", - "download_script_failed": "Kunne ikke laste ned skriptet. Sjekk logger for mer informasjon", - "import_script_from_url_title": "Importer skript fra URL", - "import_script_warning": "Advarsel: Importerte skript kan være skadelig for enheten din. Bare importer skript fra pålitelige kilder.", - "enter_url_label": "Skriv inn URL her:", - "script_imported": "Skript {name} Importert!", - "import_failed": "Kunne ikke importere skript. {message}. Sjekk logger for mer informasjon", - "import_button": "Import", - "update_module_button": "Oppdateringsmodul", - "updating_script": "Oppdatering av skript {name}...", - "module_not_found": "Modulen ikke funnet", - "updated_script": "Oppdatert {name} til versjon {version}", - "update_module_failed": "Kunne ikke oppdatere modulen. Sjekk logger for mer informasjon", - "edit_module_button": "Rediger modul", - "open_module_failed": "Kunne ikke åpne modulfilen. Sjekk logger for mer informasjon", - "clear_module_data_button": "Tydelig moduldata", - "module_data_cleared": "Moduldata ryddet!", - "clear_module_data_failed": "Kunne ikke fjerne moduldata. Sjekk logger for mer informasjon", - "delete_module_button": "Slett modul", - "deleted_script": "Slettet skript {name}!", - "delete_module_failed": "Kunne ikke slette modulen. Sjekk logger for mer informasjon", - "actions_title": "Handlinger", - "no_description": "Ingen beskrivelse", - "update_available": "Oppdatering tilgjengelig: {version}", - "actions_button": "Handlinger", - "loaded_script": "Lastet skript {name}", - "unloaded_script": "Lastet skript {name}", - "enable_script_failed": "Kunne ikke aktivere skript. Sjekk logger for mer informasjon", - "disable_script_failed": "Kunne ikke deaktivere skriptet. Sjekk logger for mer informasjon", - "select_scripts_folder_toast": "Velg skriptmappen!", - "manage_repos_button": "Administrer repos", - "import_from_url_button": "Import fra URL", - "open_scripts_folder_button": "Åpne skriptmappe", - "no_settings_for_module": "Denne modulen har ingen innstillinger", - "installed_scripts_tab": "Installerte skript", - "catalog_tab": "Katalog", - "no_scripts_folder_selected_title": "Ingen skriptmappe valgt", - "select_folder_button": "Velg mappe", - "no_scripts_found_title": "Ingen skript funnet.", - "use_catalog_to_add_scripts": "Bruk kategorien Katalog for å legge til skript!", - "ok_button_timeout": "Ok ({timeout})", - "documentation_button": "Dokumentasjon", - "catalog": { - "script_already_installed": "Skript allerede installert!", - "download_failed": "Mislykket nedlasting: {code}", - "script_downloaded": "Skript nedlastet!", - "could_not_create_file": "Kunne ikke opprette fil.", - "no_scripts_folder_selected": "Ingen skriptmappe valgt.", - "error": "Feil: {message}", - "no_repos_added": "Ingen depoter lagt til.", - "repo_list_info": "Her kan du finne en liste over repoer:", - "link_text": "Lenke", - "no_scripts_available": "Ingen skript tilgjengelig fra noen repo.", - "by_author": "av {author}", - "version": "Versjon: {version}", - "installed_button": "Installert", - "download_button": "Last ned" - }, - "repos": { - "invalid_repo_title": "Ugyldig depot", - "add_repo_button": "Legg til depot", - "add_repo_dialog_title": "Legg til depot -URL", - "repo_url_label": "URL", - "repo_added_toast": "Depot lagt til vellykket!", - "invalid_repo_error": "Dette ser ikke ut til å være et gyldig skriptlager.", - "add_repo_failed_toast": "Kunne ikke legge til depot: {message}", - "add_button": "Legge til", - "no_repos_added": "Ingen depoter lagt til", - "remove_button": "Fjerne", - "remove_repo_dialog_title": "Fjern depot", - "remove_repo_dialog_text": "Er du sikker på at du vil fjerne dette depotet?" - } - }, - "features": { - "config_import": { - "title": "Bekreft importen", - "back_button_description": "Tilbake", - "config_imported_toast": "Konfigurert importert!", - "confirm_button": "Bekrefte", - "expand_button_description": "Utvide", - "enable_feature": "Aktiver funksjon", - "enabled": "Aktivert", - "disabled": "Funksjonshemmet" - }, - "config_export": { - "title": "Eksportsammendrag", - "back_button_description": "Tilbake", - "save_button": "Spare", - "expand_button_description": "Utvide", - "enable_feature": "Aktiver funksjon", - "enabled": "Aktivert", - "disabled": "Funksjonshemmet" - } - }, - "manage_repos": { - "title": "Administrer {type} depoter", - "add_repo_button": "Legg til depot", - "add_repo_dialog_title": "Legg til depot -URL", - "repo_url_label": "URL", - "repo_added_successfully": "Depot lagt til vellykket!", - "add_repo_failed": "Kunne ikke legge til depot: {message}", - "add_button": "Legge til", - "no_repos_added": "Ingen depoter lagt til", - "remove_button": "Fjerne" - } - }, - "rules": { - "toasts": { - "enabled": "{ruleName} aktivert", - "disabled": "{ruleName} deaktivert" - }, - "modes": { - "blacklist": "Blacklist -modus", - "whitelist": "Hvitelistmodus" - }, - "properties": { - "auto_download": { - "name": "Auto nedlasting", - "description": "Last ned snaps automatisk når du ser på dem", - "options": { - "blacklist": "Ekskluder fra bilnedlasting", - "whitelist": "Auto nedlasting" - } - }, - "stealth": { - "name": "Stealth -modus", - "description": "Forhindrer noen i å vite at du har åpnet snaps/chatter og samtaler", - "options": { - "blacklist": "Ekskluder fra stealth -modus", - "whitelist": "Stealth -modus" - } - }, - "auto_save": { - "name": "Auto lagre", - "description": "Lagrer chatmeldinger når du ser på dem", - "options": { - "blacklist": "Ekskluder fra Auto Save", - "whitelist": "Auto lagre" - } - }, - "unsaveable_messages": { - "name": "Ugjengelige meldinger", - "description": "Forhindrer at meldinger blir lagret i chat av andre mennesker", - "options": { - "blacklist": "Ekskluder fra ugjengelige meldinger", - "whitelist": "Ugjengelige meldinger" - } - }, - "auto_open_snaps": { - "name": "Auto Open Snaps", - "description": "Åpner snaps automatisk når du mottar dem", - "options": { - "blacklist": "Ekskluder fra Auto Open Snaps", - "whitelist": "Auto Open Snaps" - } - }, - "hide_friend_feed": { - "name": "Gjemme deg for vennfôr" - }, - "e2e_encryption": { - "name": "Bruk E2E -kryptering" - }, - "pin_conversation": { - "name": "Pin samtale" - }, - "exclude_message_logger": { - "name": "Ekskluder fra meldingsloggeren" - } - } - }, - "actions": { - "clean_snapchat_cache": { - "name": "Rengjør Snapchat -cache", - "description": "Renser Snapchat -hurtigbufferen" - }, - "manage_friend_list": { - "name": "Administrer venneliste", - "description": "Importer/eksporter vennelisten din når du sikkerhetskopierer" - }, - "export_chat_messages": { - "name": "Eksporter chat -meldinger", - "description": "Eksporterer samtalemeldinger til en JSON/HTML/TXT -fil" - }, - "export_memories": { - "name": "Eksporter minner", - "description": "Eksporterer minner til en zip -fil" - }, - "bulk_messaging_action": { - "name": "Bulk -meldingshandling", - "description": "Utfører operasjoner som å slette venner eller masse sletting av samtaler" - }, - "regen_mappings": { - "name": "Regenerere kartlegginger", - "description": "Regenerere kartlegginger manuelt" - }, - "change_language": { - "name": "Endre språk", - "description": "Endre språket til PurrfectSnap" - }, - "file_imports": { - "name": "Filimport", - "description": "Importer filer for bruk i Snapchat" - }, - "friend_tracker": { - "name": "Friend Tracker", - "description": "Spor vennene dine på Snapchat" - }, - "logger_history": { - "name": "Loggerhistorie", - "description": "Se historien til loggede meldinger" - } - }, - "features": { - "notices": { - "unstable": "⚠ ustabil", - "ban_risk": "⚠ Denne funksjonen kan forårsake forbud", - "internal_behavior": "⚠ Dette kan bryte Snapchat intern oppførsel" - }, - "properties": { - "downloader": { - "name": "Nedlasting", - "description": "Last ned Snapchat Media", - "properties": { - "save_folder": { - "name": "Lagre mappen", - "description": "Velg katalogen som alle medier skal lastes ned til" - }, - "auto_download_sources": { - "name": "Auto nedlastingskilder", - "description": "Velg kildene du automatisk laster ned fra" - }, - "prevent_self_auto_download": { - "name": "Forhindre nedlasting av selv Auto", - "description": "Forhindrer at dine egne snaps blir lastet ned automatisk" - }, - "path_format": { - "name": "Stiformat", - "description": "Spesifiser filstiformatet" - }, - "allow_duplicate": { - "name": "Tillat duplikat", - "description": "Lar de samme mediene lastes ned flere ganger" - }, - "merge_overlays": { - "name": "Slå sammen overlegg", - "description": "Kombinerer teksten og media på et snap til en enkelt fil" - }, - "force_image_format": { - "name": "Forta bildeformat", - "description": "Tvinger bilder som skal lagres i et spesifisert format" - }, - "force_voice_note_format": { - "name": "Force Voice Note Format", - "description": "Forces Voice Notes som skal lagres i et spesifisert format" - }, - "auto_download_voice_notes": { - "name": "Auto nedlasting Voice Notes", - "description": "Last ned stemmenotater automatisk når du spiller dem" - }, - "download_profile_pictures": { - "name": "Last ned profilbilder", - "description": "Lar deg laste ned profilbilder fra profilsiden" - }, - "opera_download_button": { - "name": "Opera nedlastingsknapp", - "description": "Legger til en nedlastingsknapp øverst til høyre når du ser på et snap.\nLenge trykk på knappene vil tvinge nedlasting" - }, - "download_context_menu": { - "name": "Last ned kontekstmeny", - "description": "Lar deg laste ned/forhåndsvise meldinger fra en samtale eller en historie ved hjelp av hurtigmenyen.\nLenge trykk på knappene vil tvinge nedlasting" - }, - "ffmpeg_options": { - "name": "FFMPEG -alternativer", - "description": "Spesifiser flere FFMPEG -alternativer", - "properties": { - "threads": { - "name": "Tråder", - "description": "Mengden tråder som skal brukes" - }, - "preset": { - "name": "Forhåndsinnstilt", - "description": "Angi hastigheten på konverteringen" - }, - "constant_rate_factor": { - "name": "Konstant hastighetsfaktor", - "description": "Angi konstant hastighetsfaktor for videokoderen\nFra 0 til 51 for libx264" - }, - "video_bitrate": { - "name": "Video bitrate", - "description": "Sett videoen Bitrate (KBPS)" - }, - "audio_bitrate": { - "name": "Lydbitrate", - "description": "Angi lydbitraten (KBPS)" - }, - "custom_video_codec": { - "name": "Tilpasset videokodek", - "description": "Angi en tilpasset videokodek (f.eks. Libx264)" - }, - "custom_audio_codec": { - "name": "Tilpasset lydkodek", - "description": "Angi en tilpasset lydkodek (f.eks. AAC)" - } - } - }, - "logging": { - "name": "Logging", - "description": "Viser toasts når media laster ned" - }, - "custom_path_format": { - "name": "Tilpasset banformat", - "description": "Spesifiser et tilpasset banformat for nedlastede medier\n\nTilgjengelige variabler:\n - %brukernavn %\n - %kilde %\n - %hash %\n - %dato_tid %" - } - } - }, - "user_interface": { - "name": "Brukergrensesnitt", - "description": "Endre utseendet og følelsen av Snapchat", - "properties": { - "enable_app_appearance": { - "name": "Aktiver innstillinger for utseende av apper", - "description": "Aktiverer innstillingen for skjult apputseende\nKan ikke være nødvendig på nyere Snapchat -versjoner" - }, - "friend_feed_message_preview": { - "name": "Friend Melding forhåndsvisning av Feed Message", - "description": "Viser en forhåndsvisning av de siste meldingene i vennfôret", - "properties": { - "amount": { - "name": "Beløp", - "description": "Mengden meldinger som skal forhåndsvises" - } - } - }, - "snap_preview": { - "name": "SNAP -forhåndsvisning", - "description": "Viser en liten forhåndsvisning ved siden av usettede snaps i chat" - }, - "bootstrap_override": { - "name": "Bootstrap overstyring", - "description": "Overstyrer brukergrensesnittoppstillingene", - "properties": { - "app_appearance": { - "name": "Apputseende", - "description": "Angir et vedvarende apputseende" - }, - "home_tab": { - "name": "Hjem -fanen", - "description": "Overstyrer kategorien Startup når du åpner Snapchat" - } - } - }, - "force_amoled_theme": { - "name": "AMOLED Dark Mode", - "description": "Bruker en ekte svart bakgrunn for det mørke temaet" - }, - "map_friend_nametags": { - "name": "Forbedret vennekart Nametags", - "description": "Forbedrer nametagene til venner på Snapmap" - }, - "prevent_message_list_auto_scroll": { - "name": "Forhindre meldingsliste Auto Rull", - "description": "Forhindrer at meldingslisten ruller til bunnen når du sender/mottar en melding" - }, - "streak_expiration_info": { - "name": "Vis utløpsinformasjon", - "description": "Viser en strek utløpstimer ved siden av strekene telleren" - }, - "hide_friend_feed_entry": { - "name": "Skjul venn Feed Entry", - "description": "Skjuler en spesifikk venn fra vennfôret\nBruk den sosiale fanen til å administrere denne funksjonen" - }, - "hide_streak_restore": { - "name": "Skjul strek gjenoppretting", - "description": "Skjuler gjenopprettingsknappen i vennens feed" - }, - "hide_quick_add_suggestions": { - "name": "Skjul raskt legg til forslag", - "description": "Fjerner hurtig, legg til vennforslag" - }, - "hide_story_suggestions": { - "name": "Skjul historieforslag", - "description": "Fjerner forslag fra historiens side" - }, - "hide_ui_components": { - "name": "Skjul UI -komponenter", - "description": "Velg hvilke UI -komponenter du skal skjule" - }, - "opera_media_quick_info": { - "name": "Opera media rask info", - "description": "Viser nyttig informasjon om medier som opprettelsesdato i Opera Viewers kontekstmeny" - }, - "old_bitmoji_selfie": { - "name": "Gamle Bitmoji -selfie", - "description": "Bringer tilbake Bitmoji -selfiene fra eldre Snapchat -versjoner" - }, - "disable_spotlight": { - "name": "Deaktiver søkelyset", - "description": "Deaktiverer søkelyssiden" - }, - "friend_feed_menu_buttons": { - "name": "Vennfôrmeny -knapper", - "description": "Velg hvilke knapper som skal vises i vennens feed -meny" - }, - "auto_close_friend_feed_menu": { - "name": "Auto Close Friend Feed -meny", - "description": "Lukker automatisk vennemenyen for vennen etter å ha trykket på en innstillingsknapp" - }, - "vertical_story_viewer": { - "name": "Vertikal historieutsikt", - "description": "Aktiverer den vertikale historieviseren for alle historier" - }, - "enable_friend_feed_menu_bar": { - "name": "Vennfôr meny bar", - "description": "Aktiverer den nye vennens fôrmeny bar" - }, - "message_indicators": { - "name": "Meldingsindikatorer", - "description": "Legger til spesifikke indikatorikoner til meldinger\nMerk: Indikatorer er kanskje ikke 100% nøyaktige" - }, - "stealth_mode_indicator": { - "name": "Stealth Mode Indicator", - "description": "Legger til en 👻 Emoji ved siden av samtaler i stealth -modus" - }, - "edit_text_override": { - "name": "Rediger tekstoverstyring", - "description": "Overstyrer tekstfeltatferd" - }, - "prevent_forced_keyboard": { - "name": "Forhindre tvangstastatur", - "description": "Forhindrer at Snapchat automatisk dukker opp tastaturet når du åpner en samtale" - }, - "settings_menu": { - "name": "Innstillingsmenyen", - "description": "Endrer måten du åpner PurrFectSnap -menyen", - "options": { - "default": "Misligholde", - "legacy": "Arv" - } - } - } - }, - "messaging": { - "name": "Meldinger", - "description": "Endre hvordan du samhandler med venner", - "properties": { - "bypass_screenshot_detection": { - "name": "Omkjøringsskjermbilde", - "description": "Forhindrer at Snapchat oppdager når du tar et skjermbilde" - }, - "anonymous_story_viewing": { - "name": "Anonym historievisning", - "description": "Forhindrer noen i å vite at du har sett historien deres" - }, - "prevent_story_rewatch_indicator": { - "name": "Forhindrer indikator på nytt", - "description": "Forhindrer noen i å vite at du har sett på historien deres på nytt" - }, - "hide_peek_a_peek": { - "name": "Skjul Peek-a-titt", - "description": "Forhindrer at varsel blir sendt når du sveip halvparten av en prat" - }, - "hide_bitmoji_presence": { - "name": "Skjul bitmoji tilstedeværelse", - "description": "Forhindrer at bitmoji dukker opp mens du dukker opp mens du er i chat" - }, - "hide_typing_notifications": { - "name": "Skjul typingvarsler", - "description": "Forhindrer at noen vet at du skriver en melding" - }, - "unlimited_snap_view_time": { - "name": "Ubegrenset snapvisningstid", - "description": "Fjerner tidsbegrensningen for å se snaps" - }, - "auto_mark_as_read": { - "name": "Bilmerket som lest", - "description": "Merker automatisk meldinger/snaps som lest selv når stealth -modus er aktivert" - }, - "mark_snap_as_seen_button": { - "name": "Merk snap som sett knapp", - "description": "Legger til en knapp for å merke et snap som sett når du ser på den.\nDette vil fungere selv når stealth -modus er aktivert" - }, - "skip_when_marking_as_seen": { - "name": "Hopp over når du markerer som sett", - "description": "Hopper automatisk til neste snap når du markerer et snap som sett.\nBruk i kombinasjon med Mark Snap som sett -knapp" - }, - "loop_media_playback": { - "name": "Loop Media Playback", - "description": "Loops Media Playback når du ser på snaps / historier" - }, - "disable_replay_in_ff": { - "name": "Deaktiver replay i FF", - "description": "Deaktiverer muligheten til å spille igjen med en lang presse fra vennfôret" - }, - "half_swipe_notifier": { - "name": "Halv sveipvarsler", - "description": "Varsler deg når noen halvt sveiper inn i en samtale", - "properties": { - "min_duration": { - "name": "Minimum varighet", - "description": "Minimums varigheten av halv sveipen (på sekunder)" - }, - "max_duration": { - "name": "Maksimal varighet", - "description": "Maksimal varighet på halv sveipen (på sekunder)" - } - } - }, - "call_start_confirmation": { - "name": "Call Start bekreftelse", - "description": "Viser en bekreftelsesdialog når du starter en samtale" - }, - "unlimited_conversation_pinning": { - "name": "Ubegrenset samtalepinning", - "description": "Lar deg feste en ubegrenset mengde samtaler lokalt" - }, - "disable_snap_mode_restrictions": { - "name": "Deaktiver begrensninger for snap -modus", - "description": "Lar deg se selvdestruerende snaps uten begrensninger" - }, - "prevent_message_sending": { - "name": "Forhindre sending av melding", - "description": "Forhindrer å sende visse typer meldinger" - }, - "friend_mutation_notifier": { - "name": "Vennemutasjon varsler", - "description": "Varsler deg når noe endres i en venns profil" - }, - "better_notifications": { - "name": "Bedre varsler", - "description": "Legger til mer informasjon i mottatte varsler", - "properties": { - "group_notifications": { - "name": "Gruppevarsler", - "description": "Gruppevarsler til en enkelt" - }, - "chat_preview": { - "name": "Chat -forhåndsvisning", - "description": "Viser en forhåndsvisning av mottatte meldinger i varselet" - }, - "media_preview": { - "name": "Forhåndsvisning av medier", - "description": "Viser en forhåndsvisning av de valgte medietypene i varselet" - }, - "media_caption": { - "name": "Mediebilde", - "description": "Viser vedlagte medier i varselet" - }, - "stacked_media_messages": { - "name": "Stablede mediemeldinger", - "description": "Kombinerer flere mediemeldinger til en tekstvarsling når de ikke kan forhåndsvises. Bruk i kombinasjon med forhåndsvisning av chat" - }, - "friend_add_source": { - "name": "Venn legg til kilde", - "description": "Viser kilden til en venneforespørsel i varselet" - }, - "reply_button": { - "name": "Svar -knapp", - "description": "Legger til en svar -knapp til varselet" - }, - "smart_replies": { - "name": "Smarte svar", - "description": "Legger til foreslåtte svar på varsler (Android 10+). Bruk i kombinasjon med svar -knapp" - }, - "download_button": { - "name": "Last ned knappen", - "description": "Lar deg laste ned medier fra varselet" - }, - "mark_as_read_button": { - "name": "Merk som lese -knapp", - "description": "Lar deg merke en melding som lest fra varselet" - }, - "mark_as_read_and_save_in_chat": { - "name": "Merk som les og lagre i chat", - "description": "Legger til et merke som les og lagre i chat -knappen i varselet" - } - } - }, - "notification_blacklist": { - "name": "Varslingssvarteliste", - "description": "Velg varsler som skal bli blokkert" - }, - "message_logger": { - "name": "Meldingslogger", - "description": "Forhindrer at meldinger blir slettet", - "properties": { - "keep_my_own_messages": { - "name": "Behold mine egne meldinger", - "description": "Forhindrer at dine egne meldinger blir slettet" - }, - "auto_purge": { - "name": "Auto Purge", - "description": "Sletter automatisk hurtigbufrede meldinger som er eldre enn den angitte tiden" - }, - "message_filter": { - "name": "Meldingsfilter", - "description": "Velg hvilke meldinger som skal logges (tom for alle meldinger)" - }, - "deleted_message_color": { - "name": "Slettet meldingfarge", - "description": "Angir fargen på slettede meldinger" - } - } - }, - "auto_save_messages_in_conversations": { - "name": "Lagre meldinger automatisk", - "description": "Lagrer hver melding automatisk i samtaler" - }, - "gallery_media_send_override": { - "name": "Galleri media Send overstyring", - "description": "Forfalsker mediekilden når du sender fra galleriet" - }, - "strip_media_metadata": { - "name": "Strip Media -metadata", - "description": "Fjerner metadata av media før du sender som en melding" - }, - "bypass_message_retention_policy": { - "name": "Omkjøringsoppbevaringspolitikk", - "description": "Forhindrer at meldinger blir slettet etter å ha sett dem" - }, - "bypass_message_action_restrictions": { - "name": "Omkjørs meldingshandlingsbegrensninger", - "description": "Lar deg reagere på et snap uten å ha åpnet det eller lagre en ugjengelige melding" - }, - "remove_groups_locked_status": { - "name": "Fjern grupper låst status", - "description": "Lar deg se gruppeinformasjon etter å ha blitt sparket" - }, - "double_tap_chat_action": { - "name": "Dobbeltknapp chat -handling", - "description": "Utfører en tilpasset handling når du dobler en melding i chat" - }, - "double_tap_chat_action_custom_emoji": { - "name": "Dobbelt tapp chat action tilpasset emoji -reaksjon", - "description": "Angir en tilpasset emoji -reaksjon for dobbeltknappen chat -handlingen" - } - } - }, - "global": { - "name": "Global", - "description": "Tweak Global Snapchat -innstillinger", - "properties": { - "better_location": { - "name": "Bedre beliggenhet", - "description": "Forbedrer Snapchat -plasseringen", - "properties": { - "spoof_location": { - "name": "Spoof beliggenhet", - "description": "Forfalsker din beliggenhet til en spesifisert en" - }, - "coordinates": { - "name": "Koordinater", - "description": "Angi koordinatene til det forfalskede stedet" - }, - "walk_radius": { - "name": "Gå radius", - "description": "Gå tilfeldig rundt innenfor denne radius (FT)" - }, - "always_update_location": { - "name": "Oppdater alltid plasseringen", - "description": "Tvinge Snapchat til å oppdatere plassering selv om ingen GPS -data er mottatt" - }, - "suspend_location_updates": { - "name": "Suspender beliggenhetsoppdateringer", - "description": "Forhindrer at stedet ditt blir oppdatert" - }, - "spoof_battery_level": { - "name": "Spoof batterinivå", - "description": "Forfalsker batterinivået på enheten din på kart\nVerdien må være mellom 0 og 100" - }, - "spoof_headphones": { - "name": "Spoofhodetelefoner", - "description": "Forfalsker statusen til å lytte til musikk på kart" - }, - "show_battery_level": { - "name": "Vis batterinivå", - "description": "Viser batterinivået til vennene dine på kartet" - } - } - }, - "snapchat_plus": { - "name": "Snapchat Plus", - "description": "Aktiverer Snapchat Plus -funksjoner\nNoen serversidige funksjoner fungerer kanskje ikke" - }, - "media_upload_quality": { - "name": "Media laster opp kvalitet", - "description": "Overstyrer media opplastingskvalitet", - "properties": { - "force_video_upload_source_quality": { - "name": "Tving videoopplasting av kildekvalitet", - "description": "Tvinger Snapchat til å bruke kildekvaliteten når du laster opp videoer\nVær oppmerksom på at dette ikke kan fjerne metadata fra media" - }, - "disable_image_compression": { - "name": "Deaktiver bildekomprimering", - "description": "Deaktiverer bildekomprimering når du laster opp medier" - }, - "custom_image_upload_format": { - "name": "Tilpasset bildeopplastingsformat", - "description": "Angir et tilpasset bildeopplastingsformat\nVelg et tapsfritt format (som PNG) for beste kvalitet" - } - } - }, - "disable_confirmation_dialogs": { - "name": "Deaktiver bekreftelsesdialoger", - "description": "Bekrefter automatisk utvalgte handlinger" - }, - "auto_updater": { - "name": "Auto Updater", - "description": "Sjekker automatisk for nye oppdateringer" - }, - "disable_metrics": { - "name": "Deaktiver beregninger", - "description": "Blokkerer å sende spesifikke analytiske data til Snapchat" - }, - "disable_story_sections": { - "name": "Deaktiver historiedeler", - "description": "Fjerner seksjoner fra historiens side\nKan kreve en oppdatering for å fungere ordentlig" - }, - "block_ads": { - "name": "Blokkerer annonser", - "description": "Forhindrer at annonser vises" - }, - "disable_custom_tabs": { - "name": "Deaktiver tilpassede faner", - "description": "Åpner lenker i støttede applikasjoner i stedet for i nettleseren" - }, - "disable_permission_requests": { - "name": "Deaktiver tillatelsesforespørsler", - "description": "Forhindrer Snapchat fra å be om spesifikke tillatelser" - }, - "disable_memories_snap_feed": { - "name": "Deaktiver minner snap Feed", - "description": "Forhindrer at Snapchat viser nyere minner når du sveiper opp i kameraet" - }, - "spotlight_comments_username": { - "name": "Spotlight Comments Brukernavn", - "description": "Viser forfatternavn i Spotlight -kommentarer" - }, - "bypass_video_length_restriction": { - "name": "Omkjørs videolengdebegrensninger", - "description": "Singel: Sender en enkelt video\nSplit: Delte videoer etter redigering" - }, - "default_video_playback_rate": { - "name": "Standard videoavspillingskurs", - "description": "Angir standardhastigheten for avspilling av videoer\nVerdien må være mellom 0,1 og 4,0" - }, - "video_playback_rate_slider": { - "name": "Video Playback Rate glidebryter", - "description": "Legger til en glidebryter i Opera -kontekstmenyen for å endre videoavspillingsfrekvensen\nMerk: Endringer gjelder bare påfølgende videoer" - }, - "disable_google_play_dialogs": { - "name": "Deaktiver dialoger til Google Play Services", - "description": "Forhindre at dialoger til tilgjengelighet av Google Play Services blir vist" - }, - "default_volume_controls": { - "name": "Standardvolumkontroller", - "description": "Tvinger Snapchat for å bruke systemvolumkontroller" - }, - "disable_telecom_framework": { - "name": "Deaktiver telekomramme", - "description": "Forhindrer Snapchat i å bruke Android Telecom Framework\nDette lar deg lytte til musikk mens du er på en samtale" - }, - "hide_active_music": { - "name": "Skjul aktiv musikk", - "description": "Forhindrer at Snapchat vet at du lytter til musikk\nDette vil tillate deg å ta snaps ved hjelp av kontrollvolumknapper mens du lytter til musikk" - }, - "disable_snap_splitting": { - "name": "Deaktiver SNAP -splitting", - "description": "Forhindrer at snaps blir delt inn i flere deler\nBilder du sender vil bli videoer" - } - } - }, - "rules": { - "name": "Regler", - "description": "Administrer automatiske funksjoner for enkeltpersoner" - }, - "camera": { - "name": "Kamera", - "description": "Juster de riktige innstillingene for det perfekte snap", - "properties": { - "disable_cameras": { - "name": "Deaktiver kameraer", - "description": "Forhindrer at Snapchat bruker de valgte kameraene" - }, - "black_photos": { - "name": "Svarte bilder", - "description": "Erstatter fangede bilder med svart bakgrunn\nVideoer påvirkes ikke" - }, - "immersive_camera_preview": { - "name": "Oppslukende forhåndsvisning", - "description": "Forhindrer at Snapchat beskjærer kameraets forhåndsvisning\nDette kan føre til at kameraet flimrer på noen enheter" - }, - "override_front_resolution": { - "name": "Overstyr foran oppløsningen", - "description": "Overstyrer kameraoppløsningen for frontkameraet" - }, - "override_back_resolution": { - "name": "Overstyrt oppløsning", - "description": "Overstyrer kameraoppløsningen for bakkameraet" - }, - "custom_resolution": { - "name": "Tilpasset oppløsning", - "description": "Angir en tilpasset kameraoppløsning, bredde x høyde (f.eks. 1920x1080).\nDen tilpassede oppløsningen må støttes av enheten din" - }, - "front_custom_frame_rate": { - "name": "Front tilpasset bildefrekvens", - "description": "Overstyrer framkamera -rammehastigheten" - }, - "back_custom_frame_rate": { - "name": "Tilpasset tilpasset bildefrekvens", - "description": "Overstyrer rammehastigheten" - }, - "force_camera_source_encoding": { - "name": "Tvinge kamerakilde koding", - "description": "Tvinger kamerakilden som koder" - }, - "startup_default_camera": { - "name": "Oppstart standardkamera", - "description": "Angir standardkameraet når du åpner Snapchat" - }, - "hevc_recording": { - "name": "HEVC -innspilling", - "description": "Bruker HEVC (H.265) Codec for videoopptak" - } - } - }, - "streaks_reminder": { - "name": "Streaks påminnelse", - "description": "Varsler deg med jevne mellomrom om strekene dine", - "properties": { - "interval": { - "name": "Intervall", - "description": "Intervallet mellom hver påminnelse (timer)" - }, - "remaining_hours": { - "name": "Gjenværende tid", - "description": "Den gjenværende tiden før varselet vises (timer)" - }, - "group_notifications": { - "name": "Gruppevarsler", - "description": "Gruppevarsler til en enkelt" - } - } - }, - "experimental": { - "name": "Eksperimentell", - "description": "Eksperimentelle funksjoner", - "properties": { - "native_hooks": { - "name": "Innfødte kroker", - "description": "Usikre funksjoner som kobler seg til Snapchats innfødte kode", - "properties": { - "composer_hooks": { - "name": "Komponistkroker", - "description": "Injiserer koden i komponisten Cross-Platform UI Framework", - "properties": { - "show_first_created_username": { - "name": "Vis først opprettet brukernavn", - "description": "Viser det første opprettet brukernavn ved siden av gjeldende brukernavn på profilsiden" - }, - "bypass_camera_roll_limit": { - "name": "Omkjørs kamerarullgrense", - "description": "Øker den maksimale mengden medier du kan sende fra kamerarullen" - }, - "custom_self_destruct_snap_delay": { - "name": "Tilpasset selvdestruksjon SNAP -forsinkelse", - "description": "Gir flere alternativer for selvdestruksjonstimeren når du sender et snap" - }, - "composer_console": { - "name": "Komponistkonsoll", - "description": "Lar deg utføre JavaScript -kode i komponist (bare ARM64)" - }, - "composer_logs": { - "name": "Komponistlogger", - "description": "Omdirigere konsolllogger med komponist til purrfectsnap" - } - } - }, - "disable_bitmoji": { - "name": "Deaktiver Bitmoji", - "description": "Deaktiverer vennens profil bitmoji" - }, - "custom_emoji_font": { - "name": "Tilpasset emoji -font", - "description": "Lar deg bruke en tilpasset emoji -font. Fungerer bare med .ttf -skrifter" - }, - "custom_shared_library": { - "name": "Tilpasset delt bibliotek", - "description": "Laster inn et tilpasset delt bibliotek i Snapchat. Denne funksjonen er bare for testformål" - } - } - }, - "spoof": { - "name": "Spoof", - "description": "Forfalsker forskjellige informasjon om deg", - "properties": { - "play_store_installer_package_name": { - "name": "Play Store installasjonspakkenavn", - "description": "Overstyrer installasjonspakkenavnet til com.android.vending" - }, - "remove_vpn_transport_flag": { - "name": "Fjern VPN -transportflagget", - "description": "Forhindrer at Snapchat oppdager VPN -er" - }, - "remove_mock_location_flag": { - "name": "Fjern hånlig stedsflagg", - "description": "Forhindrer at Snapchat oppdager hånlig plassering" - } - } - }, - "convert_message_locally": { - "name": "Konverter meldingen lokalt", - "description": "Konverterer snaps for å chatte eksterne medier lokalt. Dette vises i chat nedlasting av kontekstmeny" - }, - "media_file_picker": { - "name": "Mediefilplukker", - "description": "Lar deg velge hvilken som helst video/lydfil fra galleriet" - }, - "story_logger": { - "name": "Story Logger", - "description": "Gir en historie med vennens historier" - }, - "call_recorder": { - "name": "Ring opptaker", - "description": "Registrerer automatisk lydanrop" - }, - "account_switcher": { - "name": "Kontobryter", - "description": "Lar deg veksle mellom kontoer uten å logge ut\nLenge trykk på søkeikonet ved siden av Bitmoji -profilen din for å åpne menyen\nMerk: Denne funksjonen er eksperimentell og vil sannsynligvis endre seg i fremtiden", - "properties": { - "auto_backup_current_account": { - "name": "Auto Backup Contrument Account", - "description": "Automatisk sikkerhetskopierer driftskontoen når du logger ut eller bytter kontoer" - } - } - }, - "better_transcript": { - "name": "Bedre transkripsjon", - "description": "Forbedrer taleanvisningsutskriften", - "properties": { - "force_transcription": { - "name": "Force Voice Note transkripsjon", - "description": "Lar alle taleanmerkninger bli transkribert" - }, - "preferred_transcription_lang": { - "name": "Foretrukket transkripsjonsspråk", - "description": "Det foretrukne språket for stemmetappingen (f.eks. En, ES, FR)" - }, - "notification_transcript": { - "name": "Varslingsutskrift", - "description": "Transkriberer taleanmerkninger i varsler\nDenne funksjonen krever at forhåndsvisningsfunksjonen for chat er aktivert i bedre varsler" - } - } - }, - "voice_note_auto_play": { - "name": "Voice Note Auto Play", - "description": "Spiller automatisk neste taleanmerkning etter at den nåværende en er ferdig" - }, - "friend_notes": { - "name": "Vennnotater", - "description": "Lar deg legge til notater til vennene" - }, - "cof_experiments": { - "name": "COF -eksperimenter", - "description": "Aktiverer uutgitte/beta Snapchat -funksjoner" - }, - "context_menu_fix": { - "name": "Kontekstmeny Fix", - "description": "Forsøk å reparere vennens fôrmeny som når enheten er frakoblet, den kan ikke vises riktig" - }, - "app_lock": { - "name": "Applås", - "description": "Forhindrer tilgang til Snapchat uten passord", - "properties": { - "lock_on_resume": { - "name": "Låse på CV", - "description": "Låser appen når den blir åpnet igjen" - } - } - }, - "infinite_story_boost": { - "name": "Uendelig historieøkning", - "description": "Omgå historien Boost Limit -forsinkelse" - }, - "meo_passcode_bypass": { - "name": "Øynene mine passerer bare omgang", - "description": "Omgå øynene mine bare passekode\nDette vil bare fungere hvis passordet er lagt inn riktig før" - }, - "no_friend_score_delay": { - "name": "Ingen vennscore forsinkelse", - "description": "Fjerner forsinkelsen når du ser på en vennescore" - }, - "best_friend_pinning": { - "name": "Bestevenninnen", - "description": "Lar deg feste en venn som din beste venn. Merk: Bare du kan se din festede beste venn" - }, - "e2ee": { - "name": "Ende-til-ende kryptering", - "description": "Krypter meldingene dine med AES ved hjelp av en delt hemmelig nøkkel\nSørg for å lagre nøkkelen et sted trygt!", - "properties": { - "encrypted_message_indicator": { - "name": "Kryptert meldingsindikator", - "description": "Legger til en 🔒 Emoji ved siden av krypterte meldinger" - }, - "force_message_encryption": { - "name": "Force Message Encryption", - "description": "Forhindrer å sende krypterte meldinger til personer som ikke har E2E -kryptering aktivert bare når flere samtaler er valgt" - } - } - }, - "add_friend_source_spoof": { - "name": "Legg til vennekilde Spoof", - "description": "Forfalsker kilden til en venneforespørsel" - }, - "hidden_snapchat_plus_features": { - "name": "Skjult Snapchat Plus -funksjoner", - "description": "Aktiverer uutgitt/beta Snapchat Plus -funksjoner\nKan ikke jobbe med eldre Snapchat -versjoner" - }, - "custom_streaks_expiration_format": { - "name": "Tilpassede streker utløpsformat", - "description": "Tilpasser strekene utløpsformat\n\nTilgjengelige variabler:\n - %C: Streker teller\n - %e: timeglassemoji\n - %D: dager\n - %H: timer\n - %m: minutter\n - %s: sekunder\n - %W: gjenværende tid" - }, - "prevent_forced_logout": { - "name": "Forhindre tvangslogging", - "description": "Forhindrer at Snapchat logger deg ut når du logger deg på en annen enhet" - }, - "snapscore_changes": { - "name": "Snapscore endringer", - "description": "Sporer endringer i venner snapscore\nBruk denne funksjonen i nyere versjoner av Snapchat" - } - } - }, - "scripting": { - "name": "Skripting", - "description": "Kjør tilpassede skript for å utvide purrfectsnap", - "properties": { - "developer_mode": { - "name": "Utviklermodus", - "description": "Viser feilsøkingsinfo på Snapchats brukergrensesnitt" - }, - "module_folder": { - "name": "Modulmappe", - "description": "Mappen der skriptene er lokalisert" - }, - "auto_reload": { - "name": "Auto Reload", - "description": "Automatisk laster inn skriptene automatisk når de endrer seg" - }, - "integrated_ui": { - "name": "Integrert brukergrensesnitt", - "description": "Lar skript legge til tilpassede brukergrensesnittkomponenter til Snapchat" - }, - "disable_log_anonymization": { - "name": "Deaktiver logganonymisering", - "description": "Deaktiverer anonymiseringen av logger" - }, - "disable_optimization": { - "name": "Deaktiver optimalisering", - "description": "Deaktiverer optimaliseringen av skript. Dette kan forårsake ytelsesproblemer." - } - } - }, - "friend_tracker": { - "name": "Friend Tracker", - "description": "Registrerer vennens aktivitet på Snapchat", - "properties": { - "record_messaging_events": { - "name": "Registrer meldingshendelser", - "description": "Registrerer meldingshendelser som å åpne et snap, lese en melding osv." - }, - "allow_running_in_background": { - "name": "Tillat løping i bakgrunnen", - "description": "Lar trackeren løpe i bakgrunnen. Merk: Dette vil tømme batteriet betydelig" - }, - "auto_purge": { - "name": "Auto Purge", - "description": "Sletter automatisk hurtigbufrede hendelser som er eldre enn den angitte tiden" - } - } - } - }, - "options": { - "app_appearance": { - "always_light": "Alltid lys", - "always_dark": "Alltid mørk" - }, - "friend_feed_menu_buttons": { - "auto_download": "⬇ Auto nedlasting", - "auto_save": "💬 Lagre meldinger automatisk", - "unsaveable_messages": "⬇ Usparte meldinger", - "auto_open_snaps": "📷 Auto Open Snaps", - "stealth": "👻 Stealth -modus", - "mark_snaps_as_seen": "👀 Mark snaps som sett", - "mark_stories_as_seen_locally": "👀 Merk historier som sett lokalt", - "conversation_info": "👤 Samtaleinfo", - "e2e_encryption": "🔒 Bruk E2E -kryptering" - }, - "path_format": { - "create_author_folder": "Lag mappe for hver forfatter", - "create_source_folder": "Lag mappe for hver mediekildetype", - "append_hash": "Legg til en unik hasj til filnavnet", - "append_source": "Legg med mediekilden i filnavnet", - "append_username": "Legg brukernavnet til filnavnet", - "append_date_time": "Legg til dato og klokkeslett til filnavnet" - }, - "auto_download_sources": { - "friend_snaps": "Venn knipser", - "friend_stories": "Vennhistorier", - "public_stories": "Offentlige historier", - "spotlight": "Spotlight" - }, - "logging": { - "started": "Startet", - "success": "Suksess", - "progress": "Framgang", - "failure": "Feil" - }, - "notifications": { - "chat_screenshot": "Skjermbilde", - "chat_screen_record": "Skjermoppføring", - "snap_replay": "Snap Replay", - "camera_roll_save": "Kamerarull lagre", - "chat": "Chat", - "chat_reply": "Chat -svar", - "snap": "Snap", - "typing": "Skrive", - "stories": "Historier", - "speaking": "Snakker", - "chat_reaction": "DM -reaksjon", - "group_chat_reaction": "Gruppereaksjon", - "initiate_audio": "Innkommende lydanrop", - "abandon_audio": "Savnet lydanrop", - "initiate_video": "Innkommende videosamtale", - "abandon_video": "Savnet videosamtale", - "map_live_location": "Kart Live Location" - }, - "gallery_media_send_override": { - "always_ask": "Spør alltid", - "ORIGINAL": "Originale medier", - "NOTE": "Lydnotat", - "SNAP": "Snap", - "SAVEABLE_SNAP": "Savbar snap" - }, - "strip_media_metadata": { - "hide_caption_text": "Skjul bildetekst", - "hide_snap_filters": "Skjul snap -filtre", - "hide_extras": "Skjul statister (f.eks. Nevn)", - "remove_audio_note_duration": "Fjern lydnotatvarigheten", - "remove_audio_note_transcript_capability": "Fjern lydnotat transkripsjonsevne" - }, - "hide_ui_components": { - "hide_profile_call_buttons": "Fjern profilanropsknapper", - "hide_chat_call_buttons": "Fjern chat -anropsknapper", - "hide_live_location_share_button": "Fjern Live Location Del -knappen", - "hide_stickers_button": "Fjern klistremerker -knappen", - "hide_voice_record_button": "Fjern stemmeknappen", - "hide_unread_chat_hint": "Fjern uleste chat -hint", - "hide_post_to_story_buttons": "Fjern innlegg til historieknapper før du sender et snap", - "hide_billboard_prompt": "Fjern Billboard -ledeteksten i Friends Feed", - "hide_snapchat_plus_gift_reminders": "Fjern Snapchat Plus -gaveminnene i samtaler", - "hide_map_reactions": "Fjern kartreaksjoner" - }, - "hide_story_suggestions": { - "hide_suggested_friend_stories": "Skjul foreslåtte vennhistorier", - "hide_my_stories": "Skjul historiene mine" - }, - "home_tab": { - "map": "Kart", - "chat": "Chat", - "camera": "Kamera", - "discover": "Oppdage", - "spotlight": "Spotlight" - }, - "add_friend_source_spoof": { - "added_by_username": "Av brukernavn", - "added_by_mention": "Ved omtale", - "added_by_group_chat": "Av gruppechat", - "added_by_qr_code": "Av QR -kode", - "added_by_community": "Av fellesskap", - "added_by_quick_add": "Ved rask tillegg (høy risiko for å bli utestengt)" - }, - "bypass_video_length_restriction": { - "single": "Enkelt media", - "split": "Delte medier" - }, - "old_bitmoji_selfie": { - "2d": "2d Bitmoji", - "3d": "3d Bitmoji" - }, - "disable_confirmation_dialogs": { - "erase_message": "Slette meldingen", - "remove_friend": "Fjern venn", - "block_friend": "Blokkerende venn", - "ignore_friend": "Ignorer venn", - "hide_friend": "Skjul venn", - "hide_conversation": "Skjul samtale", - "clear_conversation": "Klar samtale fra vennfôr" - }, - "auto_reload": { - "snapchat_only": "Bare Snapchat", - "all": "ALL (Snapchat + PurrFectSnap)" - }, - "edit_text_override": { - "multi_line_chat_input": "Multi line chat input", - "bypass_text_input_limit": "Omkjørt tekstinngangsgrense" - }, - "auto_purge": { - "never": "Aldri", - "1_hour": "1 time", - "3_hours": "3 timer", - "6_hours": "6 timer", - "12_hours": "12 timer", - "1_day": "1 dag", - "3_days": "3 dager", - "1_week": "1 uke", - "2_weeks": "2 uker", - "1_month": "1 måned", - "3_months": "3 måneder", - "6_months": "6 måneder" - }, - "disable_story_sections": { - "friends": "Venner", - "suggested_stories": "Foreslåtte historier", - "following": "Følgende", - "discover": "Oppdage" - }, - "disable_cameras": { - "front": "Frontkamera", - "back": "Ryggkamera" - }, - "disable_permission_requests": { - "notifications": "Varsler", - "read_media_images": "Les mediebilder", - "read_media_video": "Les medievideo", - "camera": "Kamera", - "microphone": "Mikrofon", - "location": "Sted", - "read_contacts": "Les kontakter", - "nearby_devices": "Nærliggende enheter", - "phone_calls": "Telefonsamtaler" - }, - "message_indicators": { - "encryption_indicator": "Legger til et 🔒 -ikon ved siden av meldinger som bare er sendt til deg", - "platform_indicator": "Legger til plattformikonet som et media ble sendt fra (f.eks. Android, iOS, nett)", - "location_indicator": "Legger til et 📍 -ikon til snaps når de er sendt med beliggenhet aktivert", - "ovf_editor_indicator": "Indikerer om et snap er blitt sendt ved hjelp av OVF -redaktøren", - "director_mode_indicator": "Legger til et ✏ -ikon til snaps når de har blitt sendt ved hjelp av direktørmodus, som kan brukes til å sende galleribilder som snaps" - }, - "auto_mark_as_read": { - "conversation_read": "Merk samtalen som lest når du sender en melding", - "snap_reply": "Mark snaps som les når du svarer på dem", - "save_snap_in_chat": "Mark snaps som les når du lagrer dem i chat mens du er i stealth -modus" - }, - "friend_mutation_notifier": { - "remove_friend": "Gi beskjed til når noen fjerner deg som en venn", - "birthday_changes": "Gi beskjed til når noen skifter bursdag", - "bitmoji_selfie_changes": "Gi beskjed til når noen endrer bitmoji -selfien", - "bitmoji_avatar_changes": "Gi beskjed til når noen endrer bitmoji -avataren sin", - "bitmoji_background_changes": "Gi beskjed til når noen endrer bitmoji -bakgrunnen", - "bitmoji_scene_changes": "Gi beskjed til når noen endrer bitmoji -scenen" - }, - "snapchat_plus": { - "not_subscribed": "Ikke abonnerte", - "basic": "Grunnleggende", - "ad_free": "Annonse gratis" - }, - "double_tap_chat_action": { - "like_message": "Som melding", - "copy_text": "Kopier tekst til utklippstavlen", - "delete_message": "Slett melding", - "mark_as_read": "Merke som lest", - "custom_emoji_reaction": "Tilpasset emoji -reaksjon" - }, - "startup_default_camera": { - "front": "Frontkamera", - "back": "Ryggkamera" - } - } - }, - "friend_menu_option": { - "mark_snaps_as_seen": "Mark Snaps som sett", - "mark_stories_as_seen_locally": "Merk historier som sett lokalt", - "preview": "Forhåndsvisning", - "stealth_mode": "Stealth -modus", - "auto_download_blacklist": "Auto Last ned svarteliste", - "anti_auto_save": "Anti Auto Save" - }, - "content_type": { - "CHAT": "Chat", - "SNAP": "Snap", - "EXTERNAL_MEDIA": "Eksterne medier", - "NOTE": "Lydnotat", - "STICKER": "Klistremerke", - "SHARE": "Dele", - "STATUS": "Status", - "LOCATION": "Sted", - "STATUS_SAVE_TO_CAMERA_ROLL": "Lagret til kamerarull", - "STATUS_CONVERSATION_CAPTURE_SCREENSHOT": "Skjermbilde", - "STATUS_CONVERSATION_CAPTURE_RECORD": "Skjermoppføring", - "STATUS_CALL_MISSED_VIDEO": "Savnet videosamtale", - "STATUS_CALL_MISSED_AUDIO": "Savnet lydanrop", - "LIVE_LOCATION_SHARE": "Live beliggenhet", - "CREATIVE_TOOL_ITEM": "Kreativt verktøy", - "FAMILY_CENTER_INVITE": "Familiesenter inviterer", - "FAMILY_CENTER_ACCEPT": "Familiesenter godtar", - "FAMILY_CENTER_LEAVE": "Familiesenterets permisjon", - "STATUS_PLUS_GIFT": "Status pluss gave", - "TINY_SNAP": "Bittesmå snap", - "STATUS_COUNTDOWN": "Nedtelling", - "MAP_REACTION": "Kartreaksjon" - }, - "media_download_source": { - "none": "Ingen", - "pending": "I påvente av", - "chat_media": "Chat media", - "story": "Historie", - "public_story": "Offentlig historie", - "spotlight": "Spotlight", - "profile_picture": "Profilbilde", - "story_logger": "Story Logger", - "message_logger": "Meldingslogger", - "merged": "Slått sammen", - "voice_call": "Taleanrop" - }, - "chat_action_menu": { - "preview_button": "Forhåndsvisning", - "download_button": "Last ned", - "delete_logged_message_button": "Slett logget melding", - "show_chat_edit_history": "Vis chat redigeringshistorikk", - "convert_message": "Konverter meldingen" - }, - "opera_context_menu": { - "download": "Last ned media", - "sent_at": "Sendt til {date}", - "created_at": "Opprettet på {date}", - "expires_at": "Utløper på {date}", - "media_size": "Mediestørrelse: {size}", - "media_duration": "Mediets varighet: {duration} MS", - "show_debug_info": "Vis feilsøkingsinfo" - }, - "modal_option": { - "profile_info": "Profilinfo", - "close": "Lukke" - }, - "gallery_media_send_override": { - "multiple_media_toast": "Du kan bare sende ett media om gangen" - }, - "mark_as_seen": { - "no_unseen_snaps_toast": "Ingen usettede snaps funnet!", - "seen_toast": "Merket som sett!", - "unseen_toast": "Merket som usett!", - "already_seen_toast": "Allerede merket som sett!", - "already_unseen_toast": "Allerede merket som usett!" - }, - "conversation_preview": { - "streak_expiration": "utløper i {day} dager {hour} timer {minute} minutter", - "total_messages": "Totalt sendt/mottatt meldinger: {count}", - "title": "Forhåndsvisning", - "unknown_user": "Ukjent bruker", - "no_messages": "Ingen meldinger funnet!" - }, - "profile_info": { - "title": "Profilinfo", - "first_created_username": "Først opprettet brukernavn", - "mutable_username": "Mutabelt brukernavn", - "display_name": "Visningsnavn", - "added_date": "Lagt til dato", - "birthday": "Bursdag: {month} {day}", - "hidden_birthday": "Bursdag: Skjult", - "friendship": "Vennskap", - "add_source": "Legg til kilde", - "snapchat_plus": "Snapchat Plus", - "snapchat_plus_state": { - "subscribed": "Abonnerer", - "not_subscribed": "Ikke abonnerte" - } - }, - "friendship_link_type": { - "mutual": "Gjensidig", - "outgoing": "Utgående", - "blocked": "Blokkert", - "deleted": "Slettet", - "following": "Følgende", - "suggested": "Foreslått", - "incoming": "Innkommende", - "incoming_follower": "Innkommende tilhenger" - }, - "bulk_messaging_action": { - "choose_action_title": "Velg en handling", - "progress_status": "Behandling {index} av {total}", - "selection_dialog_continue_button": "Fortsette", - "confirmation_dialog": { - "title": "Er du sikker?", - "message": "Dette vil påvirke alle utvalgte venner. Denne handlingen kan ikke angres." - }, - "actions": { - "remove_friends": "Fjern venner", - "clear_conversations": "Klare samtaler" - } - }, - "chat_export": { - "exporter_dialog": { - "select_conversations_title": "Velg samtaler", - "text_field_selection": "{amount} Valgt", - "text_field_selection_all": "Alle", - "export_file_format_title": "Eksporter filformat", - "message_type_filter_title": "Filtermeldinger etter type", - "amount_of_messages_title": "Mengde meldinger (la det være tomt for alle)", - "download_medias_title": "Last ned medier" - }, - "dialog_negative_button": "Kansellere", - "dialog_positive_button": "Eksport", - "exported_to": "Eksportert til {path}", - "exporting_chats": "Eksporterer chatter ...", - "processing_chats": "Behandling {amount} samtaler ...", - "export_fail": "Kunne ikke eksportere samtale {conversation}", - "writing_output": "Skrive utgang ...", - "finished": "Gjort! Du kan nå lukke denne dialogen.", - "no_messages_found": "Ingen meldinger funnet!", - "exporting_message": "Eksport {conversationName}..." - }, - "button": { - "ok": "Ok", - "positive": "Ja", - "negative": "Ingen", - "cancel": "Kansellere", - "open": "Åpne", - "download": "Last ned", - "send": "Sende", - "restore_original": "Gjenopprett original", - "convert_external_media": "Konvertere eksterne medier", - "save": "Spare" - }, - "tracker_events": { - "conversation_enter": "Samtale Enter", - "conversation_exit": "Samtaleutgang", - "started_typing": "Begynte å skrive", - "stopped_typing": "Sluttet å skrive", - "started_speaking": "Begynte å snakke", - "stopped_speaking": "Sluttet å snakke", - "started_peeking": "Begynte å kikke", - "stopped_peeking": "Sluttet å kikke", - "message_read": "Melding lest", - "message_deleted": "Meldingen slettet", - "message_saved": "Melding lagret", - "message_unsaved": "Melding ufrelst", - "message_edited": "Melding redigert", - "message_reaction_add": "Meldingsreaksjon legger til", - "message_reaction_remove": "Meldingsreaksjonen fjerner", - "snap_opened": "Snap åpnet", - "snap_replayed": "Snap replayed", - "snap_replayed_twice": "Snap spiller om to ganger", - "snap_screenshot": "Snap skjermbilde", - "snap_screen_record": "Snap Screen Record" - }, - "tracker_actions": { - "log": "Logg", - "in_app_notification": "IN-APP-varsling", - "push_notification": "Push Notification", - "custom": "Skikk" - }, - "better_notifications": { - "button": { - "reply": "Svar", - "download": "Last ned", - "mark_as_read": "Merke som lest" - } - }, - "profile_picture_downloader": { - "button": "Last ned profilbilde", - "title": "Profilbilde nedlasting", - "avatar_option": "Avatar", - "background_option": "Bakgrunn" - }, - "call_start_confirmation": { - "dialog_title": "Start samtale", - "dialog_message": "Er du sikker på at du vil starte en samtale?" - }, - "half_swipe_notifier": { - "notification_channel_name": "Halv sveip", - "notification_content_dm": "{friend} Bare halvsendt inn i chatten din for {duration} sekunder", - "notification_content_group": "{friend} Bare halvsystemet til {group} for {duration} sekunder" - }, - "download_processor": { - "attachment_type": { - "snap": "Snap", - "sticker": "Klistremerke", - "gif": "Gif", - "external_media": "Eksterne medier", - "note": "Note", - "original_story": "Original historie" - }, - "select_attachments_title": "Velg vedlegg", - "download_started_toast": "Last ned startet", - "unsupported_content_type_toast": "Ikke støttet innholdstype!", - "failed_no_longer_available_toast": "Media er ikke lenger tilgjengelig", - "no_attachments_toast": "Ingen vedlegg funnet!", - "already_queued_toast": "Media allerede i kø!", - "already_downloaded_toast": "Media allerede lastet ned!", - "content_saved_toast": "Lagret!", - "download_toast": "Last ned {friendlyName}...", - "processing_toast": "Behandling {friendlyName}...", - "failed_generic_toast": "Kunne ikke laste ned", - "failed_to_create_preview_toast": "Kunne ikke lage forhåndsvisning", - "failed_processing_toast": "Mislykket behandling {error}", - "failed_gallery_toast": "Mislykket sparing til galleri {error}", - "dash_no_chapter": "Ingen kapittel funnet", - "dash_dialog": { - "title": "Last ned Dash Media", - "download_all": "Last ned alle", - "segment_text": "Segment {from} - {to}" - } - }, - "streaks_reminder": { - "notification_title": "Streker", - "notification_text": "Du mister streken din med {friend} i {hoursLeft} timer" - }, - "biometric_auth": { - "unlock_button": "Låse opp", - "title": "Lås opp Snapchat", - "subtitle": "Vennligst autentiser for å låse opp Snapchat" - }, - "end_to_end_encryption": { - "toolbox": { - "no_shared_key": "Du har ikke en delt hemmelighet med denne vennen ennå. Klikk nedenfor for å starte en ny.", - "shared_key_fingerprint": "Fingeravtrykket ditt er:\n\n{fingerprint}\n\nSørg for å sjekke om det samsvarer med vennens fingeravtrykk!", - "initiate_exchange_button": "Start nøkkelutveksling" - }, - "confirmation_dialogs": { - "title": "Ende-til-ende kryptering", - "confirmation_1": "Advarsel: Dette vil overskrive din eksisterende nøkkel. Du mister tilgangen til alle krypterte meldinger fra denne vennen. Er du sikker på at du vil fortsette?", - "confirmation_2": "Er du helt sikker på at du vil fortsette? Dette er din siste sjanse til å gå ut igjen." - }, - "unencrypted_conversation_send_failure_toast": "Du kan ikke sende kryptert innhold til både krypterte og ukrypterte samtaler!", - "native_hooks_send_failure_toast": "Kunne ikke sende! Vennligst aktiver innfødte kroker i innstillingene.", - "no_participants_to_encrypt_toast": "Du har ingen venner i denne samtalen å kryptere meldinger med!", - "encryption_failed_toast": "Kunne ikke kryptere melding! Sjekk LogCat for mer informasjon.", - "accept_public_key_success_toast": "Offentlig nøkkel akseptert!", - "accept_secret_key_success_toast": "Gjort! Du kan nå sende og motta krypterte meldinger med denne vennen.", - "accept_public_key_failure_toast": "Kunne ikke godta offentlig nøkkel", - "accept_secret_key_failure_toast": "Kunne ikke godta hemmelig nøkkel", - "accept_secret_button": "Godta hemmelighet", - "accept_public_key_button": "Godta offentlig nøkkel", - "outgoing_pk_message": "Nøkkelutvekslingsforespørsel", - "outgoing_secret_message": "Nøkkelutvekslingsrespons", - "incoming_pk_message": "Du har nettopp mottatt en offentlig nøkkelforespørsel. Klikk nedenfor for å godta det.", - "incoming_secret_message": "Din venn godtok nettopp din offentlige nøkkel. Klikk nedenfor for å godta hemmeligheten." - }, - "auto_open_snaps": { - "title": "Auto Open Snaps", - "notification_content": "{count} Snaps åpnet" - }, - "friend_mutation_observer": { - "notification_channel_name": "Friend Mutation Observer", - "friend_removed": "{username} har fjernet deg som venn", - "birthday_removed": "{username} har fjernet bursdagen sin ({birthday})", - "birthday_added": "{username} har lagt til bursdagen sin ({birthday})", - "birthday_changed": "{username} har endret bursdagen sin fra {oldBirthday} til {newBirthday}", - "bitmoji_selfie_changed": "{username} har endret bitmoji -selfien", - "bitmoji_avatar_changed": "{username} har endret bitmoji -avataren", - "bitmoji_background_changed": "{username} har endret bitmoji -bakgrunnen", - "bitmoji_scene_changed": "{username} har endret bitmoji -scenen" - }, - "material3_strings": { - "date_range_picker_start_headline": "Fra", - "date_range_picker_end_headline": "Til", - "date_range_picker_title": "Velg datoområde", - "date_picker_switch_to_calendar_mode": "Kalender", - "date_picker_switch_to_input_mode": "Inngang", - "date_range_picker_scroll_to_previous_month": "Forrige måned", - "date_range_picker_scroll_to_next_month": "Neste måned", - "date_picker_today_description": "I dag", - "date_range_picker_day_in_range": "Valgt", - "date_input_invalid_for_pattern": "Ugyldig dato", - "date_input_invalid_year_range": "Ugyldig år", - "date_input_invalid_not_allowed": "Ugyldig dato", - "date_range_input_invalid_range_input": "Ugyldig datoområde" - }, - "send_override_dialog": { - "title": "Send media som {type}", - "duration": "Varighet: {duration}", - "saveable_snap_hint": "Gjør Snap Savable i chatten", - "unlimited_duration": "Ubegrenset" - }, - "invalid_input_toast": "Ugyldig innspill! Forsikre deg om at du har lagt inn en gyldig verdi." -} \ No newline at end of file diff --git a/common/src/main/assets/lang/or.json b/common/src/main/assets/lang/or.json deleted file mode 100644 index 1ef7d9be..00000000 --- a/common/src/main/assets/lang/or.json +++ /dev/null @@ -1,1826 +0,0 @@ -{ - "setup": { - "dialogs": { - "select_language": "ଭାଷା ଚୟନ କରନ୍ତୁ", - "save_folder": "PurrfectSnap-କୁ Snapchat-ରୁ ମିଡିଆ ଡାଉନଲୋଡ୍ ଏବଂ ସେଭ୍ କରିବା ପାଇଁ ଷ୍ଟୋରେଜ୍ ଅନୁମତି ଆବଶ୍ୟକ।\nଦୟାକରି ମିଡିଆ ଡାଉନଲୋଡ୍ କରିବା ପାଇଁ ସ୍ଥାନ ଚୟନ କରନ୍ତୁ।", - "select_save_folder_button": "ଫୋଲ୍ଡର ଚୟନ କରନ୍ତୁ" - }, - "mappings": { - "dialog": "ମ୍ୟାପିଂ ଜେନେରେଟ୍ କରାଯାଉଛି, ଏହା କିଛି ସମୟ ନେଇପାରେ...", - "generate_failure_no_snapchat": "PurrfectSnap Snapchat ଚିହ୍ନଟ କରିବାରେ ଅସମର୍ଥ, ଦୟାକରି Snapchat ପୁନଃ-ଇନଷ୍ଟଲ୍ କରିବାକୁ ଚେଷ୍ଟା କରନ୍ତୁ।", - "generate_failure": "ମ୍ୟାପିଂ ଜେନେରେଟ୍ କରିବା ସମୟରେ ଏକ ତ୍ରୁଟି ଘଟିଛି, ଦୟାକରି ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।" - }, - "permissions": { - "dialog": "ଆଗକୁ ବଢିବା ପାଇଁ, ଆପଣଙ୍କୁ ନିମ୍ନଲିଖିତ ଆବଶ୍ୟକତାଗୁଡ଼ିକ ପୂରଣ କରିବାକୁ ହେବ:", - "notification_access": "ବିଜ୍ଞପ୍ତି ଆକ୍ସେସ୍", - "battery_optimization": "ବ୍ୟାଟେରୀ ଅପ୍ଟିମାଇଜେସନ୍", - "display_over_other_apps": "ଅନ୍ୟ ଆପ୍ଲିକେସନ୍ ଉପରେ ପ୍ରଦର୍ଶନ", - "request_button": "ଅନୁରୋଧ" - } - }, - "scopes": { - "friend": "ବନ୍ଧୁ", - "group": "ଗୋଷ୍ଠୀ" - }, - "manager": { - "routes": { - "tasks": "କାର୍ଯ୍ୟ", - "features": "ବୈଶିଷ୍ଟ୍ୟ", - "manage_rule_feature": "ନିୟମ ବୈଶିଷ୍ଟ୍ୟ ପରିଚାଳନା", - "home": "ହୋମ୍", - "home_settings": "ସେଟିଂସ୍", - "home_logs": "ଲଗ୍", - "logger_history": "ଲଗର୍ ଇତିହାସ", - "logged_stories": "ଲଗ୍ ହୋଇଥିବା ଷ୍ଟୋରି", - "friend_tracker": "ବନ୍ଧୁ ଟ୍ରାକର୍", - "edit_rule": "ନିୟମ ସମ୍ପାଦନା", - "file_imports": "ଫାଇଲ୍ ଆମଦାନୀ", - "manage_repos": "ରେପୋଜିଟୋରୀ ପରିଚାଳନା", - "social": "ସାମାଜିକ", - "manage_scope": "ପରିସର ପରିଚାଳନା", - "messaging_preview": "ପୂର୍ବାବଲୋକନ", - "scripts": "ସ୍କ୍ରିପ୍ଟ", - "better_location": "ଉନ୍ନତ ଅବସ୍ଥାନ" - }, - "sections": { - "home": { - "version_title": "v{versionName} · Eternal ଦ୍ଵାରା ଫୋର୍କ୍ କରାଯାଇଛି", - "update_title": "PurrfectSnap ଅପଡେଟ୍", - "update_content": "ଭର୍ସନ୍ {version} ଉପଲବ୍ଧ!", - "update_button": "ଡାଉନଲୋଡ୍", - "debug_build_summary_title": "ଆପଣ PurrfectSnap ର ଏକ ଡିବଗ୍ ବିଲ୍ଡ ଚଲାଉଛନ୍ତି", - "debug_build_summary_content": "ଭର୍ସନ୍ {versionName} ({versionCode})", - "debug_build_summary_date": "ବିଲ୍ଡ ତାରିଖ: {date} ({days} ଦିନ ପୂର୍ବେ)", - "quick_actions_title": "ଶୀଘ୍ର କାର୍ଯ୍ୟ", - "download_icon_description": "ଡାଉନଲୋଡ୍", - "completed_icon_description": "ସମ୍ପୂର୍ଣ୍ଣ", - "failed_icon_description": "ବିଫଳ", - "manage_quick_actions_description": "ଶୀଘ୍ର କାର୍ଯ୍ୟ ପରିଚାଳନା", - "quick_actions_icon_description": "ଶୀଘ୍ର କାର୍ଯ୍ୟ", - "add_quick_action_description": "ଶୀଘ୍ର କାର୍ଯ୍ୟ ଯୋଗକରନ୍ତୁ" - }, - "home_logs": { - "no_logs_hint": "କୌଣସି ଲଗ୍ ଉପଲବ୍ଧ ନାହିଁ", - "clear_logs_button": "ଲଗ୍ ସଫା କରନ୍ତୁ", - "export_logs_button": "ଲଗ୍ ରପ୍ତାନି କରନ୍ତୁ", - "saving_logs_toast": "ଲଗ୍ ସେଭ୍ କରାଯାଉଛି, ଏହା କିଛି ସମୟ ନେଇପାରେ...", - "saved_logs_success_toast": "ଲଗ୍ ସଫଳତାର ସହିତ ସେଭ୍ ହୋଇଛି", - "saved_logs_failure_toast": "ଲଗ୍ ସେଭ୍ କରିବାରେ ବିଫଳ" - }, - "home_settings": { - "actions_title": "କାର୍ଯ୍ୟ", - "message_logger_title": "ମେସେଜ୍ ଲଗର୍", - "debug_title": "ଡିବଗ୍", - "success_toast": "ସମାପ୍ତ!", - "message_logger_summary": "{messageCount} ମେସେଜ୍\n{storyCount} ଷ୍ଟୋରି", - "export_button": "ରପ୍ତାନି", - "clear_button": "ସଫା", - "view_logger_history_button": "ଲଗର୍ ଇତିହାସ ଦେଖନ୍ତୁ", - "updates_title": "ଅପଡେଟ୍", - "auto_update_check": "ଅପଡେଟ୍ ପାଇଁ ଅଟୋମେଟିକ୍ ଯାଞ୍ଚ", - "update_check_frequency": "ଅପଡେଟ୍ ଯାଞ୍ଚ ଫ୍ରିକ୍ୱେନ୍ସି", - "update_check_frequency_daily": "ଦୈନିକ", - "update_check_frequency_weekly": "ସାପ୍ତାହିକ", - "update_check_frequency_monthly": "ମାସିକ", - "theme_icon_description": "ଥିମ୍", - "app_theme_title": "ଆପ୍ ଥିମ୍", - "theme_mode_system": "ସିଷ୍ଟମ୍", - "theme_mode_light": "ଆଲୋକ", - "theme_mode_dark": "ଅନ୍ଧାର", - "ui_settings_title": "UI ସେଟିଂସ୍", - "haptic_feedback_label": "ହାପ୍ଟିକ୍ ଫିଡବ୍ୟାକ୍", - "test_mode_label": "ଟେଷ୍ଟ ମୋଡ୍ (କେବଳ ଡିବଗିଂ ପାଇଁ)", - "disable_feature_loading_label": "ବୈଶିଷ୍ଟ୍ୟ ଲୋଡିଂ ଅକ୍ଷମ କରନ୍ତୁ", - "disable_auto_mapper_label": "ଅଟୋ ମ୍ୟାପର୍ ଅକ୍ଷମ କରନ୍ତୁ", - "disable_bypass_indicator_label": "ବାଇପାସ୍ ସ୍ଥିତି ସୂଚକ ଅକ୍ଷମ କରନ୍ତୁ", - "update_notification_channel_name": "PurrfectSnap ଅପଡେଟ୍", - "update_notification_channel_description": "PurrfectSnap ଅପଡେଟ୍ ପାଇଁ ବିଜ୍ଞପ୍ତି", - "update_notification_title": "PurrfectSnap ଅପଡେଟ୍ ଉପଲବ୍ଧ", - "update_notification_text": "ଭର୍ସନ୍ {version} ଏବେ ଉପଲବ୍ଧ।", - "export_database_failed_toast": "ଡାଟାବେସ୍ ରପ୍ତାନି କରିବାରେ ବିଫଳ! {message}", - "clear_messages_failed_toast": "ମେସେଜ୍ ସଫା କରିବାରେ ବିଫଳ! {message}", - "clear_file_failed_toast": "ଫାଇଲ୍ ସଫା କରିବାରେ ବିଫଳ! {message}", - "debug_file_config": "କନଫିଗୁରେସନ୍", - "debug_file_mappings": "ମ୍ୟାପିଂ", - "debug_file_message_logger": "ମେସେଜ୍ ଲଗର୍", - "debug_file_pinned_best_friend": "ପିନ୍ ହୋଇଥିବା ଶ୍ରେଷ୍ଠ ବନ୍ଧୁ", - "debug_file_native_sig_cache": "ନେଟିଭ୍ ସିଗ୍ନେଚର୍ କ୍ୟାଶ୍" - }, - "tasks": { - "no_tasks": "କୌଣସି କାର୍ଯ୍ୟ ନାହିଁ", - "merge_button": "ମିଶ୍ରଣ", - "failed_to_open_file": "ଫାଇଲ୍ ଖୋଲିବାରେ ବିଫଳ", - "merge_files_toast": "{count} ଫାଇଲ୍ ମିଶ୍ରଣ କରାଯାଉଛି", - "remove_selected_tasks_title": "ଆପଣ ନିଶ୍ଚିତ କି ଆପଣ ଚୟନିତ କାର୍ଯ୍ୟଗୁଡ଼ିକୁ ଅପସାରଣ କରିବାକୁ ଚାହୁଁଛନ୍ତି?", - "remove_all_tasks_title": "ଆପଣ ନିଶ୍ଚିତ କି ଆପଣ ସମସ୍ତ କାର୍ଯ୍ୟ ଅପସାରଣ କରିବାକୁ ଚାହୁଁଛନ୍ତି?", - "delete_files_option": "ଫାଇଲଗୁଡ଼ିକୁ ମଧ୍ୟ ଡିଲିଟ୍ କରନ୍ତୁ", - "remove_selected_tasks_confirm": "{count} କାର୍ଯ୍ୟ ଅପସାରଣ କରିବେ?", - "remove_all_tasks_confirm": "ସମସ୍ତ କାର୍ଯ୍ୟ ଅପସାରଣ କରିବେ?", - "clear_tasks_description": "କାର୍ଯ୍ୟ ସଫା କରନ୍ତୁ", - "file_not_found_icon_description": "ଫାଇଲ୍ ମିଳିଲା ନାହିଁ", - "image_icon_description": "ପ୍ରତିଛବି", - "video_icon_description": "ଭିଡିଓ", - "audio_icon_description": "ଅଡିଓ", - "file_icon_description": "ଫାଇଲ୍", - "download_icon_description": "ଡାଉନଲୋଡ୍", - "chat_action_icon_description": "ଚାଟ୍ କାର୍ଯ୍ୟ", - "cancel_icon_description": "ବାତିଲ୍", - "success_icon_description": "ସଫଳତା", - "failure_icon_description": "ବିଫଳତା", - "cancelled_icon_description": "ବାତିଲ୍", - "task_status_failure": "ବିଫଳତା", - "task_status_cancelled": "ବାତିଲ୍" - }, - "features": { - "disabled": "ଅକ୍ଷମ", - "export_option": "ରପ୍ତାନି", - "import_option": "ଆମଦାନୀ", - "reset_option": "ପୁନଃସେଟ୍", - "config_export_success_toast": "କନଫିଗୁରେସନ୍ ସଫଳତାର ସହିତ ରପ୍ତାନି ହୋଇଛି", - "config_import_success_toast": "କନଫିଗୁରେସନ୍ ସଫଳତାର ସହିତ ଆମଦାନୀ ହୋଇଛି", - "config_import_failure_toast": "କନଫିଗୁରେସନ୍ ଆମଦାନି କରିବାରେ ବିଫଳ: {error}", - "config_export_failure_toast": "କନଫିଗୁରେସନ୍ ରପ୍ତାନି କରିବାରେ ବିଫଳ: {error}", - "saved_config_snackbar": "କନଫିଗୁରେସନ୍ ସେଭ୍ ହୋଇଛି", - "older_required": "ଏହି ବୈଶିଷ୍ଟ୍ୟକୁ ସଠିକ୍ ଭାବରେ କାମ କରିବାକୁ Snapchat v{version} କିମ୍ବା ପୁରୁଣା ସଂସ୍କରଣ ଆବଶ୍ୟକ।", - "newer_required": "ଏହି ବୈଶିଷ୍ଟ୍ୟକୁ ସଠିକ୍ ଭାବରେ କାମ କରିବାକୁ Snapchat v{version} କିମ୍ବା ନୂତନ ସଂସ୍କରଣ ଆବଶ୍ୟକ।", - "search_button": "ସନ୍ଧାନ" - }, - "manage_rule_feature": { - "disable_state_option": "ଅକ୍ଷମ", - "disable_state_subtext": "କୌଣସି ବନ୍ଧୁ/ଗୋଷ୍ଠୀ ପ୍ରଭାବିତ ହେବେ ନାହିଁ", - "whitelist_state_option": "କେହି ନୁହେଁ କେବଳ...", - "whitelist_state_subtext": "କେବଳ {count} ବନ୍ଧୁ/ଗୋଷ୍ଠୀ ଏହି ନିୟମ ଦ୍ୱାରା ପ୍ରଭାବିତ ହେବେ", - "whitelist_state_button": "ଅନୁମୋଦିତ ବନ୍ଧୁ/ଗୋଷ୍ଠୀ ଚୟନ କରନ୍ତୁ", - "blacklist_state_option": "ସମସ୍ତେ କେବଳ...", - "blacklist_state_subtext": "ସମସ୍ତେ କେବଳ {count} ବନ୍ଧୁ/ଗୋଷ୍ଠୀ ଏହି ନିୟମ ଦ୍ୱାରା ପ୍ରଭାବିତ ହେବେ", - "blacklist_state_button": "ବାଦ ପଡ଼ିଥିବା ବନ୍ଧୁ/ଗୋଷ୍ଠୀ ଚୟନ କରନ୍ତୁ", - "clear_list_button": "ବନ୍ଧୁ/ଗୋଷ୍ଠୀ ତାଲିକା ସଫା କରନ୍ତୁ", - "dialog_clear_confirmation_text": "ଆପଣ ନିଶ୍ଚିତ କି ଆପଣ ତାଲିକା ସଫା କରିବାକୁ ଚାହୁଁଛନ୍ତି?" - }, - "social": { - "friends_tab": "ବନ୍ଧୁ", - "groups_tab": "ଗୋଷ୍ଠୀ", - "empty_hint": "(ଖାଲି)", - "streaks_expiration_short": "{hours}ଘ" - }, - "manage_scope": { - "logged_stories_button": "ଲଗ୍ ହୋଇଥିବା ଷ୍ଟୋରି ଦେଖାନ୍ତୁ", - "e2ee_title": "ଏଣ୍ଡ-ଟୁ-ଏଣ୍ଡ ଏନକ୍ରିପ୍ସନ୍", - "rules_title": "ନିୟମ", - "participants_text": "{count} ଅଂଶଗ୍ରହଣକାରୀ", - "not_found": "ମିଳିଲା ନାହିଁ", - "streaks_title": "ଷ୍ଟ୍ରିକ୍", - "streaks_length_text": "ଲମ୍ବ: {length}", - "streaks_expiration_text": "{eta} ରେ ସମାପ୍ତ ହେବ", - "streaks_expiration_text_expired": "ସମାପ୍ତ", - "reminder_button": "ରିମାଇଣ୍ଡର୍ ସେଟ୍ କରନ୍ତୁ", - "delete_scope_confirm_dialog_title": "ଆପଣ ନିଶ୍ଚିତ କି ଆପଣ {scope} ଡିଲିଟ୍ କରିବାକୁ ଚାହୁଁଛନ୍ତି?", - "notes_placeholder": "ଏକ ନୋଟ୍ ଯୋଡିବାକୁ କ୍ଲିକ୍ କରନ୍ତୁ", - "invalid_key_size_32_bytes": "ଅବୈଧ କି' ଆକାର (32 ବାଇଟ୍ ହେବା ଆବଶ୍ୟକ)", - "successfully_imported_key": "କି' ସଫଳତାର ସହିତ ଆମଦାନୀ ହୋଇଛି", - "failed_to_import_key": "କି' ଆମଦାନି କରିବାରେ ବିଫଳ: {message}", - "export_base64_button": "Base64 ରପ୍ତାନି କରନ୍ତୁ", - "import_base64_button": "Base64 ଆମଦାନୀ କରନ୍ତୁ" - }, - "logged_stories": { - "story_failed_to_load": "ଲୋଡ୍ କରିବାରେ ବିଫଳ", - "no_stories": "କୌଣସି ଷ୍ଟୋରି ମିଳିଲା ନାହିଁ", - "save_from_cache_button": "କ୍ୟାଶରୁ ସେଭ୍ କରନ୍ତୁ", - "downloaded_to_path": "{path} କୁ ଡାଉନଲୋଡ୍ ହୋଇଛି", - "download_failed": "ଡାଉନଲୋଡ୍ ବିଫଳ: {message}", - "posted_at": "{date} ରେ ପୋଷ୍ଟ କରାଯାଇଛି", - "created_at": "{date} ରେ ସୃଷ୍ଟି କରାଯାଇଛି", - "failed_to_open_file": "ଫାଇଲ୍ ଖୋଲିବାରେ ବିଫଳ। ଅଧିକ ସୂଚନା ପାଇଁ ଲଗ୍ ଯାଞ୍ଚ କରନ୍ତୁ", - "failed_to_get_file": "ଫାଇଲ୍ ପାଇବାରେ ବିଫଳ" - }, - "messaging_preview": { - "processed_messages_toast": "{count} ମେସେଜ୍ ପ୍ରକ୍ରିୟାକୃତ ହୋଇଛି", - "processed_messages_text": "{count} ମେସେଜ୍ ପ୍ରକ୍ରିୟାକୃତ ହୋଇଛି", - "close_button_description": "ବନ୍ଦ", - "bridge_connection_failed": "ବ୍ରିଜ୍ ସହିତ ସଂଯୋଗ କରିବାରେ ବିଫଳ। ନିଶ୍ଚିତ କରନ୍ତୁ ଯେ Snapchat ପୃଷ୍ଠଭୂମିରେ ଚାଲୁଛି", - "bridge_init_failed": "ମେସେଜିଂ ବ୍ରିଜ୍ ଆରମ୍ଭ କରିବାରେ ବିଫଳ। ନିଶ୍ଚିତ କରନ୍ତୁ ଯେ Snapchat ପୃଷ୍ଠଭୂମିରେ ଚାଲୁଛି", - "message_fetch_failed": "ମେସେଜ୍ ଆଣିବାରେ ବିଫଳ", - "no_message_hint": "କୌଣସି ମେସେଜ୍ ନାହିଁ", - "save_selection_option": "ଚୟନ ସେଭ୍ କରନ୍ତୁ", - "save_all_option": "ସବୁ ସେଭ୍ କରନ୍ତୁ", - "unsave_selection_option": "ଚୟନ ଅନସେଭ୍ କରନ୍ତୁ", - "unsave_all_option": "ସବୁ ଅନସେଭ୍ କରନ୍ତୁ", - "mark_selection_as_seen_option": "ଚୟନିତ ସ୍ନାପକୁ ଦେଖାଯାଇଥିବା ଭାବରେ ଚିହ୍ନିତ କରନ୍ତୁ", - "mark_all_as_seen_option": "ସମସ୍ତ ସ୍ନାପକୁ ଦେଖାଯାଇଥିବା ଭାବରେ ଚିହ୍ନିତ କରନ୍ତୁ", - "delete_selection_option": "ଚୟନ ଡିଲିଟ୍ କରନ୍ତୁ", - "delete_all_option": "ସବୁ ଡିଲିଟ୍ କରନ୍ତୁ" - }, - "logger_history": { - "download_started_toast": "ଡାଉନଲୋଡ୍ ଆରମ୍ଭ ହେଲା!", - "download_success_toast": "{path} କୁ ଡାଉନଲୋଡ୍ ହୋଇଛି", - "download_failed_toast": "{message} ଡାଉନଲୋଡ୍ କରିବାରେ ବିଫଳ", - "edited_at_text": "{message} ({date} ରେ ସମ୍ପାଦିତ)", - "download_button": "ଡାଉନଲୋଡ୍", - "select_conversation_placeholder": "ଏକ ବାର୍ତ୍ତାଳାପ ଚୟନ କରନ୍ତୁ", - "close_button_description": "ବନ୍ଦ", - "search_button_description": "ସନ୍ଧାନ", - "list_friend_format": "ବନ୍ଧୁ {name}", - "list_group_format": "ଗୋଷ୍ଠୀ {name}", - "no_more_messages": "ଆଉ ମେସେଜ୍ ନାହିଁ", - "reverse_order_checkbox": "ଓଲଟା କ୍ରମ", - "chat_attachment": "ଆଟାଚମେଣ୍ଟ {index}", - "empty_message": "ଖାଲି ଚାଟ୍ ମେସେଜ୍", - "message_parse_failed": "ମେସେଜ୍ ପାର୍ସ୍ କରିବାରେ ବିଫଳ", - "unknown_sender": "ଅଜ୍ଞାତ ପ୍ରେରକ", - "download_attachment_failed_toast": "ଆଟାଚମେଣ୍ଟ ଡାଉନଲୋଡ୍ କରିବାରେ ବିଫଳ", - "log_header_format": "{username} ({type}) - {date}" - }, - "file_imports": { - "import_file_button": "ଫାଇଲ୍ ଆମଦାନୀ କରନ୍ତୁ", - "file_not_found": "ଫାଇଲ୍ ମିଳିଲା ନାହିଁ", - "file_import_failed": "ଫାଇଲ୍ ଆମଦାନି କରିବାରେ ବିଫଳ: {error}", - "file_imported": "ଫାଇଲ୍ ସଫଳତାର ସହିତ ଆମଦାନୀ ହୋଇଛି", - "file_delete_failed": "ଫାଇଲ୍ ଡିଲିଟ୍ କରିବାରେ ବିଫଳ", - "no_files_hint": "ଏଠାରେ ଆପଣ Snapchat ରେ ବ୍ୟବହାର ପାଇଁ ଫାଇଲ୍ ଆମଦାନୀ କରିପାରିବେ। ଏକ ଫାଇଲ୍ ଆମଦାନୀ କରିବାକୁ ନିମ୍ନରେ ଥିବା ବଟନ୍ ଦବାନ୍ତୁ।" - }, - "better_location": { - "spoofed_coordinates_title": "Lat {latitude}, Lng {longitude}", - "save_coordinates_dialog_title": "କୋର୍ଡିନେଟ୍ ସେଭ୍ କରନ୍ତୁ", - "saved_name_dialog_hint": "ସେଭ୍ ହୋଇଥିବା ନାମ", - "latitude_dialog_hint": "ଅକ୍ଷାଂଶ", - "longitude_dialog_hint": "ଦ୍ରାଘିମା", - "save_dialog_button": "ସେଭ୍", - "choose_location_button": "ଅବସ୍ଥାନ ଚୟନ କରନ୍ତୁ", - "teleport_to_friend_button": "ବନ୍ଧୁଙ୍କୁ ଟେଲିପୋର୍ଟ କରନ୍ତୁ", - "spoof_location_toggle": "ସ୍ପୁଫ୍ ଅବସ୍ଥାନ", - "suspend_location_updates": "ଅବସ୍ଥାନ ଅପଡେଟ୍ ସ୍ଥଗିତ କରନ୍ତୁ", - "saved_coordinates_title": "ସେଭ୍ ହୋଇଥିବା କୋର୍ଡିନେଟ୍", - "no_saved_coordinates_hint": "କୌଣସି ସେଭ୍ ହୋଇଥିବା କୋର୍ଡିନେଟ୍ ନାହିଁ", - "delete_dialog_title": "ସେଭ୍ ହୋଇଥିବା କୋର୍ଡିନେଟ୍ ଡିଲିଟ୍ କରନ୍ତୁ", - "delete_dialog_message": "ଆପଣ ନିଶ୍ଚିତ କି ଆପଣ ଏହି ସେଭ୍ ହୋଇଥିବା କୋର୍ଡିନେଟ୍ ଡିଲିଟ୍ କରିବାକୁ ଚାହୁଁଛନ୍ତି?", - "teleport_to_friend_title": "ବନ୍ଧୁଙ୍କୁ ଟେଲିପୋର୍ଟ କରନ୍ତୁ", - "search_bar": "ସନ୍ଧାନ", - "no_friends_map": "ମାନଚିତ୍ରରେ କୌଣସି ବନ୍ଧୁ ନାହାଁନ୍ତି", - "no_friends_found": "କୌଣସି ବନ୍ଧୁ ମିଳିଲେ ନାହିଁ", - "edit_location_button_description": "ଅବସ୍ଥାନ ସମ୍ପାଦନା", - "add_icon_description": "ଯୋଗକରନ୍ତୁ", - "edit_icon_description": "ସମ୍ପାଦନା", - "delete_icon_description": "ଡିଲିଟ୍" - } - }, - "dialogs": { - "add_friend": { - "title": "ବନ୍ଧୁ କିମ୍ବା ଗୋଷ୍ଠୀ ଯୋଗକରନ୍ତୁ", - "search_hint": "ସନ୍ଧାନ", - "fetch_error": "ତଥ୍ୟ ଆଣିବାରେ ବିଫଳ", - "category_groups": "ଗୋଷ୍ଠୀ", - "category_friends": "ବନ୍ଧୁ", - "participants_text": "{count} ଅଂଶଗ୍ରହଣକାରୀ", - "search_icon_description": "ସନ୍ଧାନ" - }, - "scripting_warning": { - "title": "ଚେତାବନୀ", - "content": "PurrfectSnap ରେ ଏକ ସ୍କ୍ରିପ୍ଟିଂ ଉପକରଣ ଅଛି, ଯାହା ଆପଣଙ୍କ ଡିଭାଇସରେ ଉପଭୋକ୍ତା-ପରିଭାଷିତ କୋଡ୍ ଚଲାଇବାକୁ ଅନୁମତି ଦିଏ। ଅତ୍ୟନ୍ତ ସାବଧାନତା ଅବଲମ୍ବନ କରନ୍ତୁ ଏବଂ କେବଳ ଜଣାଶୁଣା, ବିଶ୍ୱସ୍ତ ଉତ୍ସରୁ ମଡ୍ୟୁଲ୍ ଇନଷ୍ଟଲ୍ କରନ୍ତୁ। ଅନଧିକୃତ କିମ୍ବା ଅପ୍ରମାଣିତ ମଡ୍ୟୁଲ୍ ଆପଣଙ୍କ ସିଷ୍ଟମ ପାଇଁ ସୁରକ୍ଷା ବିପଦ ସୃଷ୍ଟି କରିପାରେ।" - }, - "reset_config": { - "title": "କନଫିଗୁରେସନ୍ ପୁନଃସେଟ୍ କରନ୍ତୁ", - "content": "ଆପଣ ନିଶ୍ଚିତ କି ଆପଣ କନଫିଗୁରେସନ୍ ପୁନଃସେଟ୍ କରିବାକୁ ଚାହୁଁଛନ୍ତି?", - "success_toast": "କନଫିଗୁରେସନ୍ ସଫଳତାର ସହିତ ପୁନଃସେଟ୍ ହୋଇଛି" - }, - "export_config": { - "title": "ସମ୍ବେଦନଶୀଳ ତଥ୍ୟ ରପ୍ତାନି କରିବେ?", - "content": "ଆପଣ ସମ୍ବେଦନଶୀଳ ତଥ୍ୟ (ଯେପରିକି ଅବସ୍ଥାନ କୋର୍ଡିନେଟ୍, ଇତ୍ୟାଦି) ସହିତ କନଫିଗୁରେସନ୍ ରପ୍ତାନି କରିବାକୁ ଚାହୁଁଛନ୍ତି କି?" - }, - "messaging_action": { - "title": "ପ୍ରକ୍ରିୟାକରଣ ପାଇଁ ବିଷୟବସ୍ତୁ ପ୍ରକାର ଚୟନ କରନ୍ତୁ", - "select_all_button": "ସବୁ ଚୟନ କରନ୍ତୁ" - }, - "file_imports": { - "no_files_settings_hint": "କୌଣସି ଫାଇଲ୍ ମିଳିଲା ନାହିଁ। ନିଶ୍ଚିତ କରନ୍ତୁ ଯେ ଆପଣ ଫାଇଲ୍ ଆମଦାନୀ ବିଭାଗରେ ଆବଶ୍ୟକ ଫାଇଲ୍ ଆମଦାନୀ କରିଛନ୍ତି", - "settings_select_file_hint": "ଏକ ଆମଦାନୀ ହୋଇଥିବା ଫାଇଲ୍ ଚୟନ କରନ୍ତୁ" - }, - "quick_actions_dialog": { - "title": "ଶୀଘ୍ର କାର୍ଯ୍ୟ ସମ୍ପାଦନା କରନ୍ତୁ", - "subtitle": "ଆପଣଙ୍କ ଶୀଘ୍ର କାର୍ଯ୍ୟଗୁଡ଼ିକୁ ଚୟନ କରନ୍ତୁ ଏବଂ ଆକାର ଦିଅନ୍ତୁ।" - } - }, - "friend_tracker": { - "rules_tab": "ନିୟମ", - "logs_tab": "ଲଗ୍", - "export_dialog_title": "ରପ୍ତାନି", - "bulk_export_button": "ବହୁଳ ରପ୍ତାନି", - "individual_export_button": "ବ୍ୟକ୍ତିଗତ ରପ୍ତାନି", - "invalid_import_type_dialog_title": "ଅବୈଧ ଆମଦାନୀ ପ୍ରକାର", - "invalid_import_type_dialog_text": "ଚୟନିତ ଫାଇଲ୍ ଏହି ଆମଦାନୀ ପ୍ରକାର ସହିତ ସୁସଙ୍ଗତ ନୁହେଁ। ଦୟାକରି ସଠିକ୍ ଆମଦାନୀ ପ୍ରକାର ଚୟନ କରନ୍ତୁ।", - "import_dialog_title": "ଆମଦାନୀ", - "bulk_import_button": "ବହୁଳ ଆମଦାନୀ", - "individual_import_button": "ବ୍ୟକ୍ତିଗତ ଆମଦାନୀ", - "import_button_description": "ଆମଦାନୀ", - "export_button_description": "ରପ୍ତାନି", - "export_button": "ରପ୍ତାନି", - "delete_button_description": "ଡିଲିଟ୍", - "delete_button": "ଡିଲିଟ୍", - "catalog_button_description": "କାଟାଲଗ୍", - "catalog_button": "କାଟାଲଗ୍", - "add_rule_button_description": "ନିୟମ ଯୋଗକରନ୍ତୁ", - "add_rule_button": "ନିୟମ ଯୋଗକରନ୍ତୁ", - "no_rules_found": "କୌଣସି ନିୟମ ମିଳିଲା ନାହିଁ", - "empty_rule_name": "(ଖାଲି)", - "events_suffix": "ଇଭେଣ୍ଟ", - "scopes_suffix": "ପରିସର", - "select_rule_to_export_title": "ରପ୍ତାନି କରିବାକୁ ନିୟମ ଚୟନ କରନ୍ତୁ", - "deleted_logs_toast": "{count} ଲଗ୍ ଡିଲିଟ୍ ହୋଇଛି", - "delete_logs_dialog_title": "ଲଗ୍ ଡିଲିଟ୍ କରିବେ?", - "deleting_logs_dialog_text": "{count} ଲଗ୍ ଡିଲିଟ୍ କରାଯାଉଛି...", - "delete_logs_dialog_confirm_text": "ଏହା ସାମ୍ପ୍ରତିକ ଫିଲ୍ଟର୍ ଏବଂ ସନ୍ଧାନ କ୍ୱେରୀ ଉପରେ ଆଧାର କରି ଲଗ୍ ଡିଲିଟ୍ କରିବ। ଏହି କାର୍ଯ୍ୟକୁ ପୂର୍ବବତ୍ କରାଯାଇପାରିବ ନାହିଁ।", - "exported_logs_toast": "ଲଗ୍ ରପ୍ତାନି ହୋଇଛି!", - "export_logs_failed_toast": "ଲଗ୍ ରପ୍ତାନି କରିବାରେ ବିଫଳ। ଅଧିକ ବିବରଣୀ ପାଇଁ LogCat ଯାଞ୍ଚ କରନ୍ତୁ।", - "export_logs_dialog_title": "ଲଗ୍ ରପ୍ତାନି କରିବେ?", - "exporting_logs_dialog_text": "ଲଗ୍ ରପ୍ତାନି କରାଯାଉଛି...", - "export_logs_dialog_confirm_text": "ଏହା ସାମ୍ପ୍ରତିକ ଫିଲ୍ଟର୍ ଏବଂ ସନ୍ଧାନ କ୍ୱେରୀ ଉପରେ ଆଧାର କରି ଲଗ୍ ରପ୍ତାନି କରିବ।", - "export_as_button": "{type} ଭାବରେ ରପ୍ତାନି କରନ୍ତୁ", - "filters_title": "ଫିଲ୍ଟର୍", - "search_by_label": "ଦ୍ୱାରା ସନ୍ଧାନ", - "newest_first_label": "ନୂତନତମ ପ୍ରଥମେ", - "since_label": "ଠାରୁ", - "until_label": "ପର୍ଯ୍ୟନ୍ତ", - "pick_a_date_button": "ଏକ ତାରିଖ ଚୟନ କରନ୍ତୁ", - "search_placeholder": "ସନ୍ଧାନ", - "filter_button_description": "ଫିଲ୍ଟର୍", - "clear_button_description": "ସଫା", - "no_logs_found": "କୌଣସି ଲଗ୍ ମିଳିଲା ନାହିଁ", - "log_event_format": "{conversation} ରେ {event}", - "condition_only_inside_conversation": "କେବଳ ଯେତେବେଳେ ମୁଁ ବାର୍ତ୍ତାଳାପରେ ଅଛି", - "condition_only_outside_conversation": "କେବଳ ଯେତେବେଳେ ମୁଁ ବାର୍ତ୍ତାଳାପ ବାହାରେ ଅଛି", - "condition_only_when_app_active": "କେବଳ ଯେତେବେଳେ Snapchat ସକ୍ରିୟ ଥାଏ", - "condition_only_when_app_inactive": "କେବଳ ଯେତେବେଳେ Snapchat ନିଷ୍କ୍ରିୟ ଥାଏ", - "condition_no_push_notification_when_app_active": "Snapchat ସକ୍ରିୟ ଥିବାବେଳେ କୌଣସି ପୁଶ୍ ବିଜ୍ଞପ୍ତି ନାହିଁ", - "add_event_dialog_title": "ଇଭେଣ୍ଟ ଯୋଗକରନ୍ତୁ", - "event_type_label": "ଇଭେଣ୍ଟ ପ୍ରକାର", - "triggers_title": "ଟ୍ରିଗର୍", - "conditions_title": "ସର୍ତ୍ତ", - "add_button": "ଯୋଗକରନ୍ତୁ", - "default_rule_name": "କଷ୍ଟମ୍ ନିୟମ", - "discard_changes_dialog_title": "ପରିବର୍ତ୍ତନଗୁଡ଼ିକୁ ବାତିଲ୍ କରିବେ?", - "discard_changes_dialog_text": "ଆପଣଙ୍କର ଅସେଭ୍ ହୋଇଥିବା ପରିବର୍ତ୍ତନ ଅଛି। ଆପଣ ନିଶ୍ଚିତ କି ଆପଣ ସେଗୁଡ଼ିକୁ ବାତିଲ୍ କରିବାକୁ ଚାହୁଁଛନ୍ତି?", - "discard_button": "ବାତିଲ୍", - "cannot_save_rule_dialog_title": "ନିୟମ ସେଭ୍ କରିହେବ ନାହିଁ", - "cannot_save_rule_dialog_text": "ଏକ ନିୟମ ସେଭ୍ କରିବାକୁ ଅତିକମରେ ଗୋଟିଏ ଇଭେଣ୍ଟ ଥିବା ଆବଶ୍ୟକ।", - "duplicate_rule_name_dialog_title": "ନକଲ ନିୟମ ନାମ", - "duplicate_rule_name_dialog_text": "ଏହି ନାମ ସହିତ ଏକ ନିୟମ ପୂର୍ବରୁ ଅଛି। ଦୟାକରି ଏକ ଭିନ୍ନ ନାମ ଚୟନ କରନ୍ତୁ।", - "delete_rule_dialog_title": "ନିୟମ ଡିଲିଟ୍ କରନ୍ତୁ", - "delete_rule_dialog_text": "ଆପଣ ନିଶ୍ଚିତ କି ଆପଣ ଏହି ନିୟମ ଡିଲିଟ୍ କରିବାକୁ ଚାହୁଁଛନ୍ତି?", - "new_rule_title": "ନୂଆ ନିୟମ", - "edit_rule_title": "ନିୟମ ସମ୍ପାଦନା", - "back_button_description": "ପଛକୁ", - "save_button_description": "ସେଭ୍", - "general_section_title": "ସାଧାରଣ", - "rule_name_label": "ନିୟମ ନାମ", - "author_name_label": "ଲେଖକ ନାମ", - "scope_section_title": "ପରିସର", - "scope_all": "ସମସ୍ତ", - "scope_whitelist": "ହ୍ୱାଇଟଲିଷ୍ଟ", - "scope_blacklist": "ବ୍ଲାକଲିଷ୍ଟ", - "select_friends_groups_button": "ବନ୍ଧୁ/ଗୋଷ୍ଠୀ ଚୟନ କରନ୍ତୁ ({count})", - "events_section_title": "ଇଭେଣ୍ଟ", - "add_event_button": "ଇଭେଣ୍ଟ ଯୋଗକରନ୍ତୁ", - "no_events_text": "କୌଣସି ଇଭେଣ୍ଟ ନାହିଁ" - }, - "friend_tracker_catalog": { - "download_failed": "ଡାଉନଲୋଡ୍ ବିଫଳ: {code}", - "error": "ତ୍ରୁଟି: {message}", - "no_repos_added": "କୌଣସି ରେପୋଜିଟୋରୀ ଯୋଗ କରାଯାଇ ନାହିଁ।", - "no_rules_available": "କୌଣସି ରେପୋରୁ କୌଣସି ନିୟମ ଉପଲବ୍ଧ ନାହିଁ।", - "by_author": "{author} ଦ୍ୱାରା", - "imported_button": "ଆମଦାନୀ ହୋଇଛି", - "import_button": "ଆମଦାନୀ", - "title": "ବନ୍ଧୁ ଟ୍ରାକର୍ କାଟାଲଗ୍", - "manage_repos_description": "ରେପୋଜିଟୋରୀ ପରିଚାଳନା" - }, - "friend_tracker_export": { - "title": "ନିୟମ ରପ୍ତାନି", - "back_button_description": "ପଛକୁ", - "exported_toast": "ବନ୍ଧୁ ଟ୍ରାକର୍ ନିୟମ ରପ୍ତାନି ହୋଇଛି!", - "export_failed_toast": "ନିୟମ ରପ୍ତାନି କରିବାରେ ବିଫଳ: {message}", - "save_button": "ସେଭ୍", - "expand_button_description": "ବିସ୍ତାର" - }, - "friend_tracker_import": { - "title": "ନିୟମ ଆମଦାନୀ", - "back_button_description": "ପଛକୁ", - "imported_toast": "ବନ୍ଧୁ ଟ୍ରାକର୍ ନିୟମ ଆମଦାନୀ ହୋଇଛି!", - "import_failed_toast": "ନିୟମ ଆମଦାନୀ କରିବାରେ ବିଫଳ: {message}", - "confirm_button": "ନିଶ୍ଚିତ", - "expand_button_description": "ବିସ୍ତାର" - }, - "friend_tracker_repos": { - "invalid_repo_title": "ଅବୈଧ ରେପୋଜିଟୋରୀ", - "add_repo_button": "ରେପୋଜିଟୋରୀ ଯୋଗକରନ୍ତୁ", - "add_repo_dialog_title": "ରେପୋଜିଟୋରୀ URL ଯୋଗକରନ୍ତୁ", - "repo_url_label": "ରେପୋଜିଟୋରୀ URL", - "repo_added_toast": "ରେପୋଜିଟୋରୀ ସଫଳତାର ସହିତ ଯୋଗ କରାଯାଇଛି!", - "invalid_repo_error": "ଏହା ଏକ ବୈଧ ବନ୍ଧୁ ଟ୍ରାକର୍ ରେପୋଜିଟୋରୀ ପରି ଦେଖାଯାଉ ନାହିଁ।", - "add_repo_failed_toast": "ରେପୋଜିଟୋରୀ ଯୋଗ କରିବାରେ ବିଫଳ: {message}", - "add_button": "ଯୋଗକରନ୍ତୁ", - "no_repos_added": "କୌଣସି ରେପୋଜିଟୋରୀ ଯୋଗ କରାଯାଇ ନାହିଁ", - "remove_button": "ଅପସାରଣ", - "remove_repo_dialog_title": "ରେପୋଜିଟୋରୀ ଅପସାରଣ କରନ୍ତୁ", - "remove_repo_dialog_text": "ଆପଣ ନିଶ୍ଚିତ କି ଆପଣ ଏହି ରେପୋଜିଟୋରୀ ଅପସାରଣ କରିବାକୁ ଚାହୁଁଛନ୍ତି?" - }, - "navigation": { - "tracker_tab_label": "ଟ୍ରାକର୍", - "customize_bottom_bar_title": "ତଳ ବାର୍ କଷ୍ଟମାଇଜ୍ କରନ୍ତୁ", - "customize_bottom_bar_subtitle": "ଟ୍ୟାବ୍ ପୁନଃକ୍ରମ, ଯୋଗ କିମ୍ବା ଅପସାରଣ କରନ୍ତୁ। ସର୍ବାଧିକ ପାଞ୍ଚଟି।", - "shown_tabs_title": "ଦେଖାଯାଇଥିବା ଟ୍ୟାବ୍", - "no_tabs_selected_text": "କୌଣସି ଟ୍ୟାବ୍ ଚୟନ କରାଯାଇ ନାହିଁ", - "available_tabs_title": "ଉପଲବ୍ଧ ଟ୍ୟାବ୍", - "reset_button": "ପୁନଃସେଟ୍", - "done_button": "ସମାପ୍ତ" - }, - "scripting": { - "script_already_installed": "ସ୍କ୍ରିପ୍ଟ ପୂର୍ବରୁ ଇନଷ୍ଟଲ୍ ହୋଇଛି!", - "downloading_script": "ସ୍କ୍ରିପ୍ଟ ଡାଉନଲୋଡ୍ କରାଯାଉଛି...", - "script_downloaded": "ସ୍କ୍ରିପ୍ଟ {name} ଡାଉନଲୋଡ୍ ହୋଇଛି!", - "download_script_failed": "ସ୍କ୍ରିପ୍ଟ ଡାଉନଲୋଡ୍ କରିବାରେ ବିଫଳ। ଅଧିକ ବିବରଣୀ ପାଇଁ ଲଗ୍ ଯାଞ୍ଚ କରନ୍ତୁ", - "import_script_from_url_title": "URL ରୁ ସ୍କ୍ରିପ୍ଟ ଆମଦାନୀ କରନ୍ତୁ", - "import_script_warning": "ଚେତାବନୀ: ଆମଦାନୀ ହୋଇଥିବା ସ୍କ୍ରିପ୍ଟ ଆପଣଙ୍କ ଡିଭାଇସରେ କ୍ଷତିକାରକ ହୋଇପାରେ। କେବଳ ବିଶ୍ୱସ୍ତ ଉତ୍ସରୁ ସ୍କ୍ରିପ୍ଟ ଆମଦାନୀ କରନ୍ତୁ।", - "enter_url_label": "ଏଠାରେ URL ପ୍ରବେଶ କରନ୍ତୁ:", - "script_imported": "ସ୍କ୍ରିପ୍ଟ {name} ଆମଦାନୀ ହୋଇଛି!", - "import_failed": "ସ୍କ୍ରିପ୍ଟ ଆମଦାନୀ କରିବାରେ ବିଫଳ। {message}। ଅଧିକ ବିବରଣୀ ପାଇଁ ଲଗ୍ ଯାଞ୍ଚ କରନ୍ତୁ", - "import_button": "ଆମଦାନୀ", - "update_module_button": "ମଡ୍ୟୁଲ୍ ଅପଡେଟ୍ କରନ୍ତୁ", - "updating_script": "{name} ସ୍କ୍ରିପ୍ଟ ଅପଡେଟ୍ କରାଯାଉଛି...", - "module_not_found": "ମଡ୍ୟୁଲ୍ ମିଳିଲା ନାହିଁ", - "updated_script": "{name} କୁ {version} ଭର୍ସନରେ ଅପଡେଟ୍ କରାଯାଇଛି", - "update_module_failed": "ମଡ୍ୟୁଲ୍ ଅପଡେଟ୍ କରିବାରେ ବିଫଳ। ଅଧିକ ବିବରଣୀ ପାଇଁ ଲଗ୍ ଯାଞ୍ଚ କରନ୍ତୁ", - "edit_module_button": "ମଡ୍ୟୁଲ୍ ସମ୍ପାଦନା", - "open_module_failed": "ମଡ୍ୟୁଲ୍ ଫାଇଲ୍ ଖୋଲିବାରେ ବିଫଳ। ଅଧିକ ବିବରଣୀ ପାଇଁ ଲଗ୍ ଯାଞ୍ଚ କରନ୍ତୁ", - "clear_module_data_button": "ମଡ୍ୟୁଲ୍ ଡାଟା ସଫା କରନ୍ତୁ", - "module_data_cleared": "ମଡ୍ୟୁଲ୍ ଡାଟା ସଫା ହୋଇଛି!", - "clear_module_data_failed": "ମଡ୍ୟୁଲ୍ ଡାଟା ସଫା କରିବାରେ ବିଫଳ। ଅଧିକ ବିବରଣୀ ପାଇଁ ଲଗ୍ ଯାଞ୍ଚ କରନ୍ତୁ", - "delete_module_button": "ମଡ୍ୟୁଲ୍ ଡିଲିଟ୍ କରନ୍ତୁ", - "deleted_script": "{name} ସ୍କ୍ରିପ୍ଟ ଡିଲିଟ୍ ହୋଇଛି!", - "delete_module_failed": "ମଡ୍ୟୁଲ୍ ଡିଲିଟ୍ କରିବାରେ ବିଫଳ। ଅଧିକ ବିବରଣୀ ପାଇଁ ଲଗ୍ ଯାଞ୍ଚ କରନ୍ତୁ", - "actions_title": "କାର୍ଯ୍ୟ", - "no_description": "କୌଣସି ବର୍ଣ୍ଣନା ନାହିଁ", - "update_available": "ଅପଡେଟ୍ ଉପଲବ୍ଧ: {version}", - "actions_button": "କାର୍ଯ୍ୟ", - "loaded_script": "ଲୋଡ୍ ହୋଇଥିବା ସ୍କ୍ରିପ୍ଟ {name}", - "unloaded_script": "ଅନଲୋଡ୍ ହୋଇଥିବା ସ୍କ୍ରିପ୍ଟ {name}", - "enable_script_failed": "ସ୍କ୍ରିପ୍ଟ ସକ୍ଷମ କରିବାରେ ବିଫଳ। ଅଧିକ ବିବରଣୀ ପାଇଁ ଲଗ୍ ଯାଞ୍ଚ କରନ୍ତୁ", - "disable_script_failed": "ସ୍କ୍ରିପ୍ଟ ଅକ୍ଷମ କରିବାରେ ବିଫଳ। ଅଧିକ ବିବରଣୀ ପାଇଁ ଲଗ୍ ଯାଞ୍ଚ କରନ୍ତୁ", - "select_scripts_folder_toast": "ଦୟାକରି ଆପଣଙ୍କ ସ୍କ୍ରିପ୍ଟ ଫୋଲ୍ଡର ଚୟନ କରନ୍ତୁ!", - "manage_repos_button": "ରେପୋଜିଟୋରୀ ପରିଚାଳନା", - "import_from_url_button": "URL ରୁ ଆମଦାନୀ", - "open_scripts_folder_button": "ସ୍କ୍ରିପ୍ଟ ଫୋଲ୍ଡର ଖୋଲନ୍ତୁ", - "no_settings_for_module": "ଏହି ମଡ୍ୟୁଲର କୌଣସି ସେଟିଂସ୍ ନାହିଁ", - "installed_scripts_tab": "ଇନଷ୍ଟଲ୍ ହୋଇଥିବା ସ୍କ୍ରିପ୍ଟ", - "catalog_tab": "କାଟାଲଗ୍", - "no_scripts_folder_selected_title": "କୌଣସି ସ୍କ୍ରିପ୍ଟ ଫୋଲ୍ଡର ଚୟନ କରାଯାଇ ନାହିଁ", - "select_folder_button": "ଫୋଲ୍ଡର ଚୟନ କରନ୍ତୁ", - "no_scripts_found_title": "କୌଣସି ସ୍କ୍ରିପ୍ଟ ମିଳିଲା ନାହିଁ।", - "use_catalog_to_add_scripts": "ସ୍କ୍ରିପ୍ଟ ଯୋଗ କରିବା ପାଇଁ କାଟାଲଗ୍ ଟ୍ୟାବ୍ ବ୍ୟବହାର କରନ୍ତୁ!", - "ok_button_timeout": "ଠିକ୍ ({timeout})", - "documentation_button": "ଡକ୍ୟୁମେଣ୍ଟେସନ୍", - "catalog": { - "script_already_installed": "ସ୍କ୍ରିପ୍ଟ ପୂର୍ବରୁ ଇନଷ୍ଟଲ୍ ହୋଇଛି!", - "download_failed": "ଡାଉନଲୋଡ୍ ବିଫଳ: {code}", - "script_downloaded": "ସ୍କ୍ରିପ୍ଟ ଡାଉନଲୋଡ୍ ହୋଇଛି!", - "could_not_create_file": "ଫାଇଲ୍ ସୃଷ୍ଟି କରିହେଲା ନାହିଁ।", - "no_scripts_folder_selected": "କୌଣସି ସ୍କ୍ରିପ୍ଟ ଫୋଲ୍ଡର ଚୟନ କରାଯାଇ ନାହିଁ।", - "error": "ତ୍ରୁଟି: {message}", - "no_repos_added": "କୌଣସି ରେପୋଜିଟୋରୀ ଯୋଗ କରାଯାଇ ନାହିଁ।", - "repo_list_info": "ଏଠାରେ ଆପଣ ରେପୋଜିଟୋରୀର ଏକ ତାଲିକା ପାଇପାରିବେ:", - "link_text": "ଲିଙ୍କ୍", - "no_scripts_available": "କୌଣସି ରେପୋରୁ କୌଣସି ସ୍କ୍ରିପ୍ଟ ଉପଲବ୍ଧ ନାହିଁ।", - "by_author": "{author} ଦ୍ୱାରା", - "version": "ଭର୍ସନ୍: {version}", - "installed_button": "ଇନଷ୍ଟଲ୍ ହୋଇଛି", - "download_button": "ଡାଉନଲୋଡ୍" - }, - "repos": { - "invalid_repo_title": "ଅବୈଧ ରେପୋଜିଟୋରୀ", - "add_repo_button": "ରେପୋଜିଟୋରୀ ଯୋଗକରନ୍ତୁ", - "add_repo_dialog_title": "ରେପୋଜିଟୋରୀ URL ଯୋଗକରନ୍ତୁ", - "repo_url_label": "ରେପୋଜିଟୋରୀ URL", - "repo_added_toast": "ରେପୋଜିଟୋରୀ ସଫଳତାର ସହିତ ଯୋଗ କରାଯାଇଛି!", - "invalid_repo_error": "ଏହା ଏକ ବୈଧ ସ୍କ୍ରିପ୍ଟ ରେପୋଜିଟୋରୀ ପରି ଦେଖାଯାଉ ନାହିଁ।", - "add_repo_failed_toast": "ରେପୋଜିଟୋରୀ ଯୋଗ କରିବାରେ ବିଫଳ: {message}", - "add_button": "ଯୋଗକରନ୍ତୁ", - "no_repos_added": "କୌଣସି ରେପୋଜିଟୋରୀ ଯୋଗ କରାଯାଇ ନାହିଁ", - "remove_button": "ଅପସାରଣ", - "remove_repo_dialog_title": "ରେପୋଜିଟୋରୀ ଅପସାରଣ କରନ୍ତୁ", - "remove_repo_dialog_text": "ଆପଣ ନିଶ୍ଚିତ କି ଆପଣ ଏହି ରେପୋଜିଟୋରୀ ଅପସାରଣ କରିବାକୁ ଚାହୁଁଛନ୍ତି?" - } - }, - "features": { - "config_import": { - "title": "ଆମଦାନୀ ନିଶ୍ଚିତ କରନ୍ତୁ", - "back_button_description": "ପଛକୁ", - "config_imported_toast": "କନଫିଗୁରେସନ୍ ଆମଦାନୀ ହୋଇଛି!", - "confirm_button": "ନିଶ୍ଚିତ", - "expand_button_description": "ବିସ୍ତାର", - "enable_feature": "ବୈଶିଷ୍ଟ୍ୟ ସକ୍ଷମ କରନ୍ତୁ", - "enabled": "ସକ୍ଷମ", - "disabled": "ଅକ୍ଷମ" - }, - "config_export": { - "title": "ରପ୍ତାନି ସାରାଂଶ", - "back_button_description": "ପଛକୁ", - "save_button": "ସେଭ୍", - "expand_button_description": "ବିସ୍ତାର", - "enable_feature": "ବୈଶିଷ୍ଟ୍ୟ ସକ୍ଷମ କରନ୍ତୁ", - "enabled": "ସକ୍ଷମ", - "disabled": "ଅକ୍ଷମ" - } - }, - "manage_repos": { - "title": "{featureName} ରେପୋଜିଟୋରୀ ପରିଚାଳନା କରନ୍ତୁ", - "add_repo_button": "ରେପୋଜିଟୋରୀ ଯୋଗକରନ୍ତୁ", - "add_repo_dialog_title": "ରେପୋଜିଟୋରୀ URL ଯୋଗକରନ୍ତୁ", - "repo_url_label": "ରେପୋଜିଟୋରୀ URL", - "repo_added_successfully": "ରେପୋଜିଟୋରୀ ସଫଳତାର ସହିତ ଯୋଗ କରାଯାଇଛି!", - "add_repo_failed": "ରେପୋଜିଟୋରୀ ଯୋଗ କରିବାରେ ବିଫଳ: {message}", - "add_button": "ଯୋଗକରନ୍ତୁ", - "no_repos_added": "କୌଣସି ରେପୋଜିଟୋରୀ ଯୋଗ କରାଯାଇ ନାହିଁ", - "remove_button": "ଅପସାରଣ" - } - }, - "rules": { - "toasts": { - "enabled": "{ruleName} ସକ୍ଷମ ହୋଇଛି", - "disabled": "{ruleName} ଅକ୍ଷମ ହୋଇଛି" - }, - "modes": { - "blacklist": "ବ୍ଲାକଲିଷ୍ଟ ମୋଡ୍", - "whitelist": "ହ୍ୱାଇଟଲିଷ୍ଟ ମୋଡ୍" - }, - "properties": { - "auto_download": { - "name": "ଅଟୋ ଡାଉନଲୋଡ୍", - "description": "ସ୍ନାପ୍ ଦେଖିବା ସମୟରେ ସ୍ୱୟଂଚାଳିତ ଭାବରେ ଡାଉନଲୋଡ୍ କରନ୍ତୁ", - "options": { - "blacklist": "ଅଟୋ ଡାଉନଲୋଡରୁ ବାଦ ଦିଅନ୍ତୁ", - "whitelist": "ଅଟୋ ଡାଉନଲୋଡ୍" - } - }, - "stealth": { - "name": "ଷ୍ଟିଲଥ୍ ମୋଡ୍", - "description": "ଆପଣ ସେମାନଙ୍କ ସ୍ନାପ୍/ଚାଟ୍ ଏବଂ ବାର୍ତ୍ତାଳାପ ଖୋଲିଛନ୍ତି ବୋଲି କାହାକୁ ଜାଣିବାକୁ ଦିଏ ନାହିଁ", - "options": { - "blacklist": "ଷ୍ଟିଲଥ୍ ମୋଡରୁ ବାଦ ଦିଅନ୍ତୁ", - "whitelist": "ଷ୍ଟିଲଥ୍ ମୋଡ୍" - } - }, - "auto_save": { - "name": "ଅଟୋ ସେଭ୍", - "description": "ଚାଟ୍ ମେସେଜ୍ ଦେଖିବା ସମୟରେ ସେଭ୍ କରେ", - "options": { - "blacklist": "ଅଟୋ ସେଭରୁ ବାଦ ଦିଅନ୍ତୁ", - "whitelist": "ଅଟୋ ସେଭ୍" - } - }, - "unsaveable_messages": { - "name": "ଅସେଭ୍ ହୋଇପାରୁନଥିବା ମେସେଜ୍", - "description": "ଅନ୍ୟ ଲୋକଙ୍କ ଦ୍ୱାରା ଚାଟରେ ମେସେଜ୍ ସେଭ୍ ହେବାରୁ ରୋକିଥାଏ", - "options": { - "blacklist": "ଅସେଭ୍ ହୋଇପାରୁନଥିବା ମେସେଜରୁ ବାଦ ଦିଅନ୍ତୁ", - "whitelist": "ଅସେଭ୍ ହୋଇପାରୁନଥିବା ମେସେଜ୍" - } - }, - "auto_open_snaps": { - "name": "ଅଟୋ ଓପନ୍ ସ୍ନାପ୍", - "description": "ସ୍ନାପ୍ ଗ୍ରହଣ କରିବା ସମୟରେ ସ୍ୱୟଂଚାଳିତ ଭାବରେ ଖୋଲିଥାଏ", - "options": { - "blacklist": "ଅଟୋ ଓପନ୍ ସ୍ନାପରୁ ବାଦ ଦିଅନ୍ତୁ", - "whitelist": "ଅଟୋ ଓପନ୍ ସ୍ନାପ୍" - } - }, - "hide_friend_feed": { - "name": "ବନ୍ଧୁ ଫିଡରୁ ଲୁଚାନ୍ତୁ" - }, - "e2e_encryption": { - "name": "E2E ଏନକ୍ରିପ୍ସନ୍ ବ୍ୟବହାର କରନ୍ତୁ" - }, - "pin_conversation": { - "name": "ବାର୍ତ୍ତାଳାପ ପିନ୍ କରନ୍ତୁ" - }, - "exclude_message_logger": { - "name": "ମେସେଜ୍ ଲଗରରୁ ବାଦ ଦିଅନ୍ତୁ" - } - } - }, - "actions": { - "clean_snapchat_cache": { - "name": "Snapchat କ୍ୟାଶ୍ ସଫା କରନ୍ତୁ", - "description": "Snapchat କ୍ୟାଶ୍ ସଫା କରେ" - }, - "manage_friend_list": { - "name": "ବନ୍ଧୁ ତାଲିକା ପରିଚାଳନା", - "description": "ବ୍ୟାକଅପ୍ କରିବା ସମୟରେ ଆପଣଙ୍କ ବନ୍ଧୁ ତାଲିକା ଆମଦାନୀ/ରପ୍ତାନି କରନ୍ତୁ" - }, - "export_chat_messages": { - "name": "ଚାଟ୍ ମେସେଜ୍ ରପ୍ତାନି କରନ୍ତୁ", - "description": "ବାର୍ତ୍ତାଳାପ ମେସେଜଗୁଡ଼ିକୁ ଏକ JSON/HTML/TXT ଫାଇଲରେ ରପ୍ତାନି କରେ" - }, - "export_memories": { - "name": "ସ୍ମୃତି ରପ୍ତାନି କରନ୍ତୁ", - "description": "ସ୍ମୃତିଗୁଡ଼ିକୁ ଏକ ZIP ଫାଇଲରେ ରପ୍ତାନି କରେ" - }, - "bulk_messaging_action": { - "name": "ବହୁଳ ମେସେଜିଂ କାର୍ଯ୍ୟ", - "description": "ବନ୍ଧୁ ଡିଲିଟ୍ କରିବା କିମ୍ବା ବାର୍ତ୍ତାଳାପ ବହୁଳ ଭାବରେ ଡିଲିଟ୍ କରିବା ଭଳି କାର୍ଯ୍ୟ ସମ୍ପାଦନ କରେ" - }, - "regen_mappings": { - "name": "ମ୍ୟାପିଂ ପୁନଃ-ଜେନେରେଟ୍ କରନ୍ତୁ", - "description": "ମାନୁଆଲି ମ୍ୟାପିଂ ପୁନଃ-ଜେନେରେଟ୍ କରନ୍ତୁ" - }, - "change_language": { - "name": "ଭାଷା ପରିବର୍ତ୍ତନ କରନ୍ତୁ", - "description": "PurrfectSnap ର ଭାଷା ପରିବର୍ତ୍ତନ କରନ୍ତୁ" - }, - "file_imports": { - "name": "ଫାଇଲ୍ ଆମଦାନୀ", - "description": "Snapchat ରେ ବ୍ୟବହାର ପାଇଁ ଫାଇଲ୍ ଆମଦାନୀ କରନ୍ତୁ" - }, - "friend_tracker": { - "name": "ବନ୍ଧୁ ଟ୍ରାକର୍", - "description": "Snapchat ରେ ଆପଣଙ୍କ ବନ୍ଧୁମାନଙ୍କୁ ଟ୍ରାକ୍ କରନ୍ତୁ" - }, - "logger_history": { - "name": "ଲଗର୍ ଇତିହାସ", - "description": "ଲଗ୍ ହୋଇଥିବା ମେସେଜର ଇତିହାସ ଦେଖନ୍ତୁ" - } - }, - "features": { - "notices": { - "unstable": "⚠ ଅସ୍ଥିର", - "ban_risk": "⚠ ଏହି ବୈଶିଷ୍ଟ୍ୟ ବ୍ୟାନ୍ କରାଇପାରେ", - "internal_behavior": "⚠ ଏହା Snapchat-ର ଆଭ୍ୟନ୍ତରୀଣ ଆଚରଣକୁ ଭଙ୍ଗ କରିପାରେ" - }, - "properties": { - "downloader": { - "name": "ଡାଉନଲୋଡର୍", - "description": "Snapchat ମିଡିଆ ଡାଉନଲୋଡ୍ କରନ୍ତୁ", - "properties": { - "save_folder": { - "name": "ଫୋଲ୍ଡର ସେଭ୍ କରନ୍ତୁ", - "description": "ସମସ୍ତ ମିଡିଆ ଡାଉନଲୋଡ୍ କରିବାକୁ ଥିବା ଡିରେକ୍ଟୋରୀ ଚୟନ କରନ୍ତୁ" - }, - "auto_download_sources": { - "name": "ଅଟୋ ଡାଉନଲୋଡ୍ ଉତ୍ସ", - "description": "ସ୍ୱୟଂଚାଳିତ ଭାବରେ ଡାଉନଲୋଡ୍ କରିବାକୁ ଉତ୍ସ ଚୟନ କରନ୍ତୁ" - }, - "prevent_self_auto_download": { - "name": "ନିଜର ଅଟୋ ଡାଉନଲୋଡ୍ ରୋକନ୍ତୁ", - "description": "ନିଜର ସ୍ନାପଗୁଡ଼ିକୁ ସ୍ୱୟଂଚାଳିତ ଭାବରେ ଡାଉନଲୋଡ୍ ହେବାରୁ ରୋକିଥାଏ" - }, - "path_format": { - "name": "ପଥ ଫର୍ମାଟ୍", - "description": "ଫାଇଲ୍ ପଥ ଫର୍ମାଟ୍ ନିର୍ଦ୍ଦିଷ୍ଟ କରନ୍ତୁ" - }, - "allow_duplicate": { - "name": "ନକଲ ଅନୁମତି ଦିଅନ୍ତୁ", - "description": "ସମାନ ମିଡିଆକୁ ଏକାଧିକ ଥର ଡାଉନଲୋଡ୍ କରିବାକୁ ଅନୁମତି ଦିଏ" - }, - "merge_overlays": { - "name": "ଓଭରଲେ ମିଶ୍ରଣ କରନ୍ତୁ", - "description": "ଏକ ସ୍ନାପର ଟେକ୍ସଟ୍ ଏବଂ ମିଡିଆକୁ ଗୋଟିଏ ଫାଇଲରେ ମିଶ୍ରଣ କରେ" - }, - "force_image_format": { - "name": "ପ୍ରତିଛବି ଫର୍ମାଟ୍ ବାଧ୍ୟ କରନ୍ତୁ", - "description": "ପ୍ରତିଛବିଗୁଡ଼ିକୁ ଏକ ନିର୍ଦ୍ଦିଷ୍ଟ ଫର୍ମାଟରେ ସେଭ୍ କରିବାକୁ ବାଧ୍ୟ କରେ" - }, - "force_voice_note_format": { - "name": "ଭଏସ୍ ନୋଟ୍ ଫର୍ମାଟ୍ ବାଧ୍ୟ କରନ୍ତୁ", - "description": "ଭଏସ୍ ନୋଟଗୁଡ଼ିକୁ ଏକ ନିର୍ଦ୍ଦିଷ୍ଟ ଫର୍ମାଟରେ ସେଭ୍ କରିବାକୁ ବାଧ୍ୟ କରେ" - }, - "auto_download_voice_notes": { - "name": "ଭଏସ୍ ନୋଟ୍ ଅଟୋ ଡାଉନଲୋଡ୍ କରନ୍ତୁ", - "description": "ଭଏସ୍ ନୋଟ୍ ପ୍ଲେ କରିବା ସମୟରେ ସ୍ୱୟଂଚାଳିତ ଭାବରେ ଡାଉନଲୋଡ୍ କରେ" - }, - "download_profile_pictures": { - "name": "ପ୍ରୋଫାଇଲ୍ ଚିତ୍ର ଡାଉନଲୋଡ୍ କରନ୍ତୁ", - "description": "ପ୍ରୋଫାଇଲ୍ ପୃଷ୍ଠାରୁ ପ୍ରୋଫାଇଲ୍ ଚିତ୍ର ଡାଉନଲୋଡ୍ କରିବାକୁ ଅନୁମତି ଦିଏ" - }, - "opera_download_button": { - "name": "ଅପେରା ଡାଉନଲୋଡ୍ ବଟନ୍", - "description": "ଏକ ସ୍ନାପ୍ ଦେଖିବାବେଳେ ଉପର-ଡାହାଣ କୋଣରେ ଏକ ଡାଉନଲୋଡ୍ ବଟନ୍ ଯୋଗ କରେ।\nବଟନ୍ ଉପରେ ଲମ୍ବା ପ୍ରେସ୍ ଡାଉନଲୋଡ୍ ବାଧ୍ୟ କରିବ" - }, - "download_context_menu": { - "name": "ପ୍ରସଙ୍ଗ ମେନୁ ଡାଉନଲୋଡ୍ କରନ୍ତୁ", - "description": "ପ୍ରସଙ୍ଗ ମେନୁ ବ୍ୟବହାର କରି ବାର୍ତ୍ତାଳାପ କିମ୍ବା ଷ୍ଟୋରିରୁ ମେସେଜ୍ ଡାଉନଲୋଡ୍/ପୂର୍ବାବଲୋକନ କରିବାକୁ ଅନୁମତି ଦିଏ।\nବଟନ୍ ଉପରେ ଲମ୍ବା ପ୍ରେସ୍ ଡାଉନଲୋଡ୍ ବାଧ୍ୟ କରିବ" - }, - "ffmpeg_options": { - "name": "FFmpeg ବିକଳ୍ପ", - "description": "ଅତିରିକ୍ତ FFmpeg ବିକଳ୍ପ ନିର୍ଦ୍ଦିଷ୍ଟ କରନ୍ତୁ", - "properties": { - "threads": { - "name": "ଥ୍ରେଡ୍", - "description": "ବ୍ୟବହାର କରିବାକୁ ଥିବା ଥ୍ରେଡ୍ ସଂଖ୍ୟା" - }, - "preset": { - "name": "ପ୍ରିସେଟ୍", - "description": "ରୂପାନ୍ତର ଗତି ସେଟ୍ କରନ୍ତୁ" - }, - "constant_rate_factor": { - "name": "ସ୍ଥିର ହାର ଫ୍ୟାକ୍ଟର୍", - "description": "ଭିଡିଓ ଏନକୋଡର୍ ପାଇଁ ସ୍ଥିର ହାର ଫ୍ୟାକ୍ଟର୍ ସେଟ୍ କରନ୍ତୁ\nlibx264 ପାଇଁ 0 ରୁ 51" - }, - "video_bitrate": { - "name": "ଭିଡିଓ ବିଟ୍ରେଟ୍", - "description": "ଭିଡିଓ ବିଟ୍ରେଟ୍ (kbps) ସେଟ୍ କରନ୍ତୁ" - }, - "audio_bitrate": { - "name": "ଅଡିଓ ବିଟ୍ରେଟ୍", - "description": "ଅଡିଓ ବିଟ୍ରେଟ୍ (kbps) ସେଟ୍ କରନ୍ତୁ" - }, - "custom_video_codec": { - "name": "କଷ୍ଟମ୍ ଭିଡିଓ କୋଡେକ୍", - "description": "ଏକ କଷ୍ଟମ୍ ଭିଡିଓ କୋଡେକ୍ ସେଟ୍ କରନ୍ତୁ (ଯଥା libx264)" - }, - "custom_audio_codec": { - "name": "କଷ୍ଟମ୍ ଅଡିଓ କୋଡେକ୍", - "description": "ଏକ କଷ୍ଟମ୍ ଅଡିଓ କୋଡେକ୍ ସେଟ୍ କରନ୍ତୁ (ଯଥା aac)" - } - } - }, - "logging": { - "name": "ଲଗିଂ", - "description": "ମିଡିଆ ଡାଉନଲୋଡ୍ ହେବା ସମୟରେ ଟୋଷ୍ଟ ଦେଖାଏ" - }, - "custom_path_format": { - "name": "କଷ୍ଟମ୍ ପଥ ଫର୍ମାଟ୍", - "description": "ଡାଉନଲୋଡ୍ ହୋଇଥିବା ମିଡିଆ ପାଇଁ ଏକ କଷ୍ଟମ୍ ପଥ ଫର୍ମାଟ୍ ନିର୍ଦ୍ଦିଷ୍ଟ କରନ୍ତୁ\n\nଉପଲବ୍ଧ ଭେରିଏବଲ୍:\n - %username%\n - %source%\n - %hash%\n - %date_time%" - } - } - }, - "user_interface": { - "name": "ଉପଭୋକ୍ତା ଇଣ୍ଟରଫେସ୍", - "description": "Snapchat ର ରୂପ ଏବଂ ଅନୁଭବ ପରିବର୍ତ୍ତନ କରନ୍ତୁ", - "properties": { - "enable_app_appearance": { - "name": "ଆପ୍ ଦୃଶ୍ୟ ସେଟିଂସ୍ ସକ୍ଷମ କରନ୍ତୁ", - "description": "ଲୁକ୍କାୟିତ ଆପ୍ ଦୃଶ୍ୟ ସେଟିଂ ସକ୍ଷମ କରେ।\nନୂତନ Snapchat ସଂସ୍କରଣରେ ଆବଶ୍ୟକ ହୋଇନପାରେ।" - }, - "friend_feed_message_preview": { - "name": "ବନ୍ଧୁ ଫିଡ୍ ମେସେଜ୍ ପୂର୍ବାବଲୋକନ", - "description": "ବନ୍ଧୁ ଫିଡରେ ଶେଷ ମେସେଜଗୁଡ଼ିକର ଏକ ପୂର୍ବାବଲୋକନ ଦେଖାଏ", - "properties": { - "amount": { - "name": "ପରିମାଣ", - "description": "ପୂର୍ବାବଲୋକନ କରିବାକୁ ଥିବା ମେସେଜର ପରିମାଣ" - } - } - }, - "snap_preview": { - "name": "ସ୍ନାପ୍ ପୂର୍ବାବଲୋକନ", - "description": "ଚାଟରେ ଅଦୃଶ୍ୟ ସ୍ନାପ୍ ପାଖରେ ଏକ ଛୋଟ ପୂର୍ବାବଲୋକନ ପ୍ରଦର୍ଶନ କରେ" - }, - "bootstrap_override": { - "name": "ବୁଟଷ୍ଟ୍ରାପ୍ ଓଭରରାଇଡ୍", - "description": "ଉପଭୋକ୍ତା ଇଣ୍ଟରଫେସ୍ ବୁଟଷ୍ଟ୍ରାପ୍ ସେଟିଂସକୁ ଓଭରରାଇଡ୍ କରେ", - "properties": { - "app_appearance": { - "name": "ଆପ୍ ଦୃଶ୍ୟ", - "description": "ଏକ ସ୍ଥାୟୀ ଆପ୍ ଦୃଶ୍ୟ ସେଟ୍ କରେ" - }, - "home_tab": { - "name": "ହୋମ୍ ଟ୍ୟାବ୍", - "description": "Snapchat ଖୋଲିବା ସମୟରେ ଷ୍ଟାର୍ଟଅପ୍ ଟ୍ୟାବକୁ ଓଭରରାଇଡ୍ କରେ" - } - } - }, - "force_amoled_theme": { - "name": "AMOLED ଡାର୍କ ମୋଡ୍", - "description": "ଡାର୍କ ଥିମ୍ ପାଇଁ ଏକ ପ୍ରକୃତ କଳା ପୃଷ୍ଠଭୂମି ବ୍ୟବହାର କରେ" - }, - "map_friend_nametags": { - "name": "ଉନ୍ନତ ବନ୍ଧୁ ମାନଚିତ୍ର ନାମଟ୍ୟାଗ୍", - "description": "Snapmap ରେ ବନ୍ଧୁମାନଙ୍କ ନାମଟ୍ୟାଗ୍ ଉନ୍ନତ କରେ" - }, - "prevent_message_list_auto_scroll": { - "name": "ମେସେଜ୍ ତାଲିକା ଅଟୋ ସ୍କ୍ରୋଲ୍ ରୋକନ୍ତୁ", - "description": "ମେସେଜ୍ ପଠାଇବା/ଗ୍ରହଣ କରିବା ସମୟରେ ମେସେଜ୍ ତାଲିକାକୁ ତଳକୁ ସ୍କ୍ରୋଲ୍ କରିବାରୁ ରୋକିଥାଏ" - }, - "streak_expiration_info": { - "name": "ଷ୍ଟ୍ରିକ୍ ସମାପ୍ତି ସୂଚନା ଦେଖାନ୍ତୁ", - "description": "ଷ୍ଟ୍ରିକ୍ କାଉଣ୍ଟର୍ ପାଖରେ ଏକ ଷ୍ଟ୍ରିକ୍ ସମାପ୍ତି ଟାଇମର୍ ଦେଖାଏ" - }, - "hide_friend_feed_entry": { - "name": "ବନ୍ଧୁ ଫିଡ୍ ଏଣ୍ଟ୍ରି ଲୁଚାନ୍ତୁ", - "description": "ବନ୍ଧୁ ଫିଡରୁ ଏକ ନିର୍ଦ୍ଦିଷ୍ଟ ବନ୍ଧୁଙ୍କୁ ଲୁଚାଏ।\nଏହି ବୈଶିଷ୍ଟ୍ୟ ପରିଚାଳନା କରିବାକୁ ସାମାଜିକ ଟ୍ୟାବ୍ ବ୍ୟବହାର କରନ୍ତୁ" - }, - "hide_streak_restore": { - "name": "ଷ୍ଟ୍ରିକ୍ ପୁନରୁଦ୍ଧାର ଲୁଚାନ୍ତୁ", - "description": "ବନ୍ଧୁ ଫିଡରେ ପୁନରୁଦ୍ଧାର ବଟନ୍ ଲୁଚାଏ" - }, - "hide_quick_add_suggestions": { - "name": "ଶୀଘ୍ର ଯୋଗ ପରାମର୍ଶ ଲୁଚାନ୍ତୁ", - "description": "ଶୀଘ୍ର ବନ୍ଧୁ ଯୋଗ ପରାମର୍ଶ ଅପସାରଣ କରେ" - }, - "hide_story_suggestions": { - "name": "ଷ୍ଟୋରି ପରାମର୍ଶ ଲୁଚାନ୍ତୁ", - "description": "ଷ୍ଟୋରି ପୃଷ୍ଠାରୁ ପରାମର୍ଶ ଅପସାରଣ କରେ" - }, - "hide_ui_components": { - "name": "UI ଉପାଦାନ ଲୁଚାନ୍ତୁ", - "description": "କେଉଁ UI ଉପାଦାନ ଲୁଚାଇବାକୁ ଚୟନ କରନ୍ତୁ" - }, - "opera_media_quick_info": { - "name": "ଅପେରା ମିଡିଆ ଶୀଘ୍ର ସୂଚନା", - "description": "ଅପେରା ଭିଉଅର୍ ପ୍ରସଙ୍ଗ ମେନୁରେ ସୃଷ୍ଟି ତାରିଖ ଭଳି ଉପଯୋଗୀ ମିଡିଆ ସୂଚନା ଦେଖାଏ" - }, - "old_bitmoji_selfie": { - "name": "ପୁରୁଣା Bitmoji ସେଲ୍ଫି", - "description": "ପୁରୁଣା Snapchat ସଂସ୍କରଣରୁ Bitmoji ସେଲ୍ଫି ଫେରାଇ ଆଣେ" - }, - "disable_spotlight": { - "name": "ସ୍ପଟଲାଇଟ୍ ଅକ୍ଷମ କରନ୍ତୁ", - "description": "ସ୍ପଟଲାଇଟ୍ ପୃଷ୍ଠା ଅକ୍ଷମ କରେ" - }, - "friend_feed_menu_buttons": { - "name": "ବନ୍ଧୁ ଫିଡ୍ ମେନୁ ବଟନ୍", - "description": "ବନ୍ଧୁ ଫିଡ୍ ମେନୁରେ କେଉଁ ବଟନ୍ ଦେଖାଇବାକୁ ଚୟନ କରନ୍ତୁ" - }, - "auto_close_friend_feed_menu": { - "name": "ଅଟୋ କ୍ଲୋଜ୍ ବନ୍ଧୁ ଫିଡ୍ ମେନୁ", - "description": "ଏକ ସେଟିଂ ବଟନ୍ ଦବାଇବା ପରେ ସ୍ୱୟଂଚାଳିତ ଭାବରେ ବନ୍ଧୁ ଫିଡ୍ ମେନୁ ବନ୍ଦ କରେ" - }, - "vertical_story_viewer": { - "name": "ଭର୍ଟିକାଲ୍ ଷ୍ଟୋରି ଭିଉଅର୍", - "description": "ସମସ୍ତ ଷ୍ଟୋରି ପାଇଁ ଭର୍ଟିକାଲ୍ ଷ୍ଟୋରି ଭିଉଅର୍ ସକ୍ଷମ କରେ" - }, - "enable_friend_feed_menu_bar": { - "name": "ବନ୍ଧୁ ଫିଡ୍ ମେନୁ ବାର୍ ସକ୍ଷମ କରନ୍ତୁ", - "description": "ନୂଆ ବନ୍ଧୁ ଫିଡ୍ ମେନୁ ବାର୍ ସକ୍ଷମ କରେ" - }, - "message_indicators": { - "name": "ମେସେଜ୍ ସୂଚକ", - "description": "ମେସେଜଗୁଡ଼ିକରେ ନିର୍ଦ୍ଦିଷ୍ଟ ସୂଚକ ଆଇକନ୍ ଯୋଗ କରେ।\nଟିପ୍ପଣୀ: ସୂଚକ 100% ସଠିକ୍ ହୋଇନପାରେ" - }, - "stealth_mode_indicator": { - "name": "ଷ୍ଟିଲଥ୍ ମୋଡ୍ ସୂଚକ", - "description": "ଷ୍ଟିଲଥ୍ ମୋଡରେ ଥିବା ବାର୍ତ୍ତାଳାପ ପାଖରେ ଏକ 👻 ଇମୋଜି ଯୋଗ କରେ" - }, - "edit_text_override": { - "name": "ଟେକ୍ସଟ୍ ଓଭରରାଇଡ୍ ସମ୍ପାଦନା", - "description": "ଟେକ୍ସଟ୍ ଫିଲ୍ଡ ଆଚରଣକୁ ଓଭରରାଇଡ୍ କରେ" - }, - "prevent_forced_keyboard": { - "name": "ବାଧ୍ୟତାମୂଳକ କିବୋର୍ଡ ରୋକନ୍ତୁ", - "description": "ଆପଣ ଏକ ବାର୍ତ୍ତାଳାପ ଖୋଲିବାବେଳେ Snapchat କୁ ସ୍ୱୟଂଚାଳିତ ଭାବରେ କିବୋର୍ଡ ଦେଖାଇବାରୁ ରୋକିଥାଏ" - }, - "settings_menu": { - "name": "ସେଟିଂସ୍ ମେନୁ", - "description": "ଆପଣ PurrfectSnap ମେନୁ ଖୋଲିବାର ଉପାୟ ପରିବର୍ତ୍ତନ କରେ", - "options": { - "default": "ଡିଫଲ୍ଟ", - "legacy": "ପୁରୁଣା" - } - } - } - }, - "global": { - "name": "ବିଶ୍ୱସ୍ତରୀୟ", - "description": "ବିଶ୍ୱସ୍ତରୀୟ Snapchat ସେଟିଂସ୍ ଟ୍ୱିକ୍ କରନ୍ତୁ", - "properties": { - "better_location": { - "name": "ଉନ୍ନତ ଅବସ୍ଥାନ", - "description": "Snapchat ଅବସ୍ଥାନକୁ ଉନ୍ନତ କରେ", - "properties": { - "spoof_location": { - "name": "ସ୍ପୁଫ୍ ଅବସ୍ଥାନ", - "description": "ଆପଣଙ୍କ ଅବସ୍ଥାନକୁ ଏକ ନିର୍ଦ୍ଦିଷ୍ଟ ସ୍ଥାନକୁ ସ୍ପୁଫ୍ କରେ" - }, - "coordinates": { - "name": "କୋର୍ଡିନେଟ୍", - "description": "ସ୍ପୁଫ୍ ହୋଇଥିବା ଅବସ୍ଥାନର କୋର୍ଡିନେଟ୍ ସେଟ୍ କରନ୍ତୁ" - }, - "walk_radius": { - "name": "ଚାଲିବା ରେଡିୟସ୍", - "description": "ଏହି ରେଡିୟସ୍ (ଫୁଟ) ମଧ୍ୟରେ ଅନିୟମିତ ଭାବରେ ଚାଲନ୍ତୁ" - }, - "always_update_location": { - "name": "ସର୍ବଦା ଅବସ୍ଥାନ ଅପଡେଟ୍ କରନ୍ତୁ", - "description": "କୌଣସି GPS ଡାଟା ଗ୍ରହଣ କରାଯାଇନଥିଲେ ମଧ୍ୟ Snapchat କୁ ଅବସ୍ଥାନ ଅପଡେଟ୍ କରିବାକୁ ବାଧ୍ୟ କରେ" - }, - "suspend_location_updates": { - "name": "ଅବସ୍ଥାନ ଅପଡେଟ୍ ସ୍ଥଗିତ କରନ୍ତୁ", - "description": "ଆପଣଙ୍କ ଅବସ୍ଥାନ ଅପଡେଟ୍ ହେବାରୁ ରୋକିଥାଏ" - }, - "spoof_battery_level": { - "name": "ବ୍ୟାଟେରୀ ସ୍ତର ସ୍ପୁଫ୍", - "description": "ମାନଚିତ୍ରରେ ଆପଣଙ୍କ ଡିଭାଇସର ବ୍ୟାଟେରୀ ସ୍ତରକୁ ସ୍ପୁଫ୍ କରେ।\nମୂଲ୍ୟ 0 ରୁ 100 ମଧ୍ୟରେ ହେବା ଆବଶ୍ୟକ" - }, - "spoof_headphones": { - "name": "ହେଡଫୋନ୍ ସ୍ପୁଫ୍", - "description": "ମାନଚିତ୍ରରେ ସଙ୍ଗୀତ ଶୁଣିବାର ସ୍ଥିତିକୁ ସ୍ପୁଫ୍ କରେ" - }, - "show_battery_level": { - "name": "ବ୍ୟାଟେରୀ ସ୍ତର ଦେଖାନ୍ତୁ", - "description": "ମାନଚିତ୍ରରେ ଆପଣଙ୍କ ବନ୍ଧୁମାନଙ୍କ ବ୍ୟାଟେରୀ ସ୍ତର ଦେଖାଏ" - } - } - }, - "snapchat_plus": { - "name": "Snapchat+", - "description": "Snapchat+ ବୈଶିଷ୍ଟ୍ୟ ସକ୍ଷମ କରେ।\nକିଛି ସର୍ଭର-ପାର୍ଶ୍ୱ ବୈଶିଷ୍ଟ୍ୟ କାମ କରିନପାରେ।" - }, - "media_upload_quality": { - "name": "ମିଡିଆ ଅପଲୋଡ୍ ଗୁଣବତ୍ତା", - "description": "ମିଡିଆ ଅପଲୋଡ୍ ଗୁଣବତ୍ତାକୁ ଓଭରରାଇଡ୍ କରେ", - "properties": { - "force_video_upload_source_quality": { - "name": "ଭିଡିଓ ଅପଲୋଡ୍ ଉତ୍ସ ଗୁଣବତ୍ତା ବାଧ୍ୟ କରନ୍ତୁ", - "description": "ଭିଡିଓ ଅପଲୋଡ୍ କରିବା ସମୟରେ ଉତ୍ସ ଗୁଣବତ୍ତା ବ୍ୟବହାର କରିବାକୁ Snapchat କୁ ବାଧ୍ୟ କରେ।\nଦୟାକରି ଧ୍ୟାନ ଦିଅନ୍ତୁ ଯେ ଏହା ମିଡିଆରୁ ମେଟାଡାଟା ଅପସାରଣ କରିନପାରେ" - }, - "disable_image_compression": { - "name": "ପ୍ରତିଛବି ସଙ୍କୋଚନ ଅକ୍ଷମ କରନ୍ତୁ", - "description": "ମିଡିଆ ଅପଲୋଡ୍ କରିବା ସମୟରେ ପ୍ରତିଛବି ସଙ୍କୋଚନ ଅକ୍ଷମ କରେ" - }, - "custom_image_upload_format": { - "name": "କଷ୍ଟମ୍ ପ୍ରତିଛବି ଅପଲୋଡ୍ ଫର୍ମାଟ୍", - "description": "ଏକ କଷ୍ଟମ୍ ପ୍ରତିଛବି ଅପଲୋଡ୍ ଫର୍ମାଟ୍ ସେଟ୍ କରେ।\nଶ୍ରେଷ୍ଠ ଗୁଣବତ୍ତା ପାଇଁ ଏକ କ୍ଷତିହୀନ ଫର୍ମାଟ୍ (ଯେପରିକି PNG) ଚୟନ କରନ୍ତୁ" - } - } - }, - "disable_confirmation_dialogs": { - "name": "ନିଶ୍ଚିତକରଣ ଡାୟଲଗ୍ ଅକ୍ଷମ କରନ୍ତୁ", - "description": "ଚୟନିତ କାର୍ଯ୍ୟଗୁଡ଼ିକୁ ସ୍ୱୟଂଚାଳିତ ଭାବରେ ନିଶ୍ଚିତ କରେ" - }, - "auto_updater": { - "name": "ଅଟୋ ଅପଡେଟର୍", - "description": "ନୂଆ ଅପଡେଟ୍ ପାଇଁ ସ୍ୱୟଂଚାଳିତ ଭାବରେ ଯାଞ୍ଚ କରେ" - }, - "disable_metrics": { - "name": "ମେଟ୍ରିକ୍ସ ଅକ୍ଷମ କରନ୍ତୁ", - "description": "Snapchat କୁ ନିର୍ଦ୍ଦିଷ୍ଟ ଆନାଲିଟିକ୍ସ ଡାଟା ପଠାଇବା ବନ୍ଦ କରେ" - }, - "disable_story_sections": { - "name": "ଷ୍ଟୋରି ବିଭାଗ ଅକ୍ଷମ କରନ୍ତୁ", - "description": "ଷ୍ଟୋରି ପୃଷ୍ଠାରୁ ବିଭାଗ ଅପସାରଣ କରେ।\nସଠିକ୍ ଭାବରେ କାମ କରିବା ପାଇଁ ଏକ ରିଫ୍ରେଶ୍ ଆବଶ୍ୟକ ହୋଇପାରେ" - }, - "block_ads": { - "name": "ବିଜ୍ଞାପନ ବ୍ଲକ୍ କରନ୍ତୁ", - "description": "ବିଜ୍ଞାପନ ପ୍ରଦର୍ଶିତ ହେବାରୁ ରୋକିଥାଏ" - }, - "disable_custom_tabs": { - "name": "କଷ୍ଟମ୍ ଟ୍ୟାବ୍ ଅକ୍ଷମ କରନ୍ତୁ", - "description": "ୱେବ୍ ବ୍ରାଉଜର ବଦଳରେ ସମର୍ଥିତ ଆପ୍ଲିକେସନରେ ଲିଙ୍କ୍ ଖୋଲିଥାଏ" - }, - "disable_permission_requests": { - "name": "ଅନୁମତି ଅନୁରୋଧ ଅକ୍ଷମ କରନ୍ତୁ", - "description": "Snapchat କୁ ନିର୍ଦ୍ଦିଷ୍ଟ ଅନୁମତି ମାଗିବାରୁ ରୋକିଥାଏ" - }, - "disable_memories_snap_feed": { - "name": "ସ୍ମୃତି ସ୍ନାପ୍ ଫିଡ୍ ଅକ୍ଷମ କରନ୍ତୁ", - "description": "କ୍ୟାମେରାରେ ଉପରକୁ ସ୍ୱାଇପ୍ କରିବାବେଳେ Snapchat କୁ ସାମ୍ପ୍ରତିକ ସ୍ମୃତି ଦେଖାଇବାରୁ ରୋକିଥାଏ" - }, - "spotlight_comments_username": { - "name": "ସ୍ପଟଲାଇଟ୍ ମନ୍ତବ୍ୟ ଉପଭୋକ୍ତା ନାମ", - "description": "ସ୍ପଟଲାଇଟ୍ ମନ୍ତବ୍ୟରେ ଲେଖକଙ୍କ ଉପଭୋକ୍ତା ନାମ ଦେଖାଏ" - }, - "bypass_video_length_restriction": { - "name": "ଭିଡିଓ ଲମ୍ବ ପ୍ରତିବନ୍ଧକ ବାଇପାସ୍", - "description": "ଏକକ: ଏକକ ଭିଡିଓ ପଠାଏ।\nବିଭାଜନ: ସମ୍ପାଦନା ପରେ ଭିଡିଓକୁ ବିଭାଜନ କରେ" - }, - "default_video_playback_rate": { - "name": "ଡିଫଲ୍ଟ ଭିଡିଓ ପ୍ଲେବ୍ୟାକ୍ ହାର", - "description": "ଭିଡିଓ ପ୍ଲେବ୍ୟାକ୍ ପାଇଁ ଡିଫଲ୍ଟ ଗତି ସେଟ୍ କରେ।\nମୂଲ୍ୟ 0.1 ଏବଂ 4.0 ମଧ୍ୟରେ ହେବା ଆବଶ୍ୟକ" - }, - "video_playback_rate_slider": { - "name": "ଭିଡିଓ ପ୍ଲେବ୍ୟାକ୍ ହାର ସ୍ଲାଇଡର୍", - "description": "ଭିଡିଓ ପ୍ଲେବ୍ୟାକ୍ ହାର ପରିବର୍ତ୍ତନ କରିବା ପାଇଁ ଅପେରା ପ୍ରସଙ୍ଗ ମେନୁରେ ଏକ ସ୍ଲାଇଡର୍ ଯୋଗ କରେ।\nଟିପ୍ପଣୀ: ପରିବର୍ତ୍ତନଗୁଡ଼ିକ କେବଳ ପରବର୍ତ୍ତୀ ଭିଡିଓଗୁଡ଼ିକରେ ପ୍ରଯୁଜ୍ୟ" - }, - "disable_google_play_dialogs": { - "name": "ଗୁଗୁଲ୍ ପ୍ଲେ ସେବା ଡାୟଲଗ୍ ଅକ୍ଷମ କରନ୍ତୁ", - "description": "ଗୁଗୁଲ୍ ପ୍ଲେ ସେବା ଉପଲବ୍ଧତା ଡାୟଲଗ୍ ଦେଖାଯିବାରୁ ରୋକନ୍ତୁ" - }, - "default_volume_controls": { - "name": "ଡିଫଲ୍ଟ ଭଲ୍ୟୁମ୍ ନିୟନ୍ତ୍ରଣ", - "description": "Snapchat କୁ ସିଷ୍ଟମ୍ ଭଲ୍ୟୁମ୍ ନିୟନ୍ତ୍ରଣ ବ୍ୟବହାର କରିବାକୁ ବାଧ୍ୟ କରେ" - }, - "disable_telecom_framework": { - "name": "ଟେଲିକମ୍ ଫ୍ରେମୱାର୍କ ଅକ୍ଷମ କରନ୍ତୁ", - "description": "Snapchat କୁ Android ଟେଲିକମ୍ ଫ୍ରେମୱାର୍କ ବ୍ୟବହାର କରିବାରୁ ରୋକିଥାଏ।\nଏହା ଆପଣଙ୍କୁ କଲରେ ଥିବାବେଳେ ସଙ୍ଗୀତ ଶୁଣିବାକୁ ଅନୁମତି ଦିଏ" - }, - "hide_active_music": { - "name": "ସକ୍ରିୟ ସଙ୍ଗୀତ ଲୁଚାନ୍ତୁ", - "description": "ଆପଣ ସଙ୍ଗୀତ ଶୁଣୁଛନ୍ତି ବୋଲି Snapchat କୁ ଜାଣିବାରୁ ରୋକିଥାଏ।\nଏହା ଆପଣଙ୍କୁ ସଙ୍ଗୀତ ଶୁଣିବା ସମୟରେ ଭଲ୍ୟୁମ୍ ନିୟନ୍ତ୍ରଣ ବଟନ୍ ବ୍ୟବହାର କରି ସ୍ନାପ୍ ନେବାକୁ ଅନୁମତି ଦେବ" - }, - "disable_snap_splitting": { - "name": "ସ୍ନାପ୍ ବିଭାଜନ ଅକ୍ଷମ କରନ୍ତୁ", - "description": "ସ୍ନାପଗୁଡ଼ିକୁ ଏକାଧିକ ଭାଗରେ ବିଭାଜିତ ହେବାରୁ ରୋକିଥାଏ।\nଆପଣ ପଠାଉଥିବା ଚିତ୍ରଗୁଡ଼ିକ ଭିଡିଓ ହୋଇଯିବ" - } - } - }, - "rules": { - "name": "ନିୟମ", - "description": "ବ୍ୟକ୍ତିଗତ ଲୋକଙ୍କ ପାଇଁ ସ୍ୱୟଂଚାଳିତ ବ features ଶିଷ୍ଟ୍ୟଗୁଡିକ ପରିଚାଳନା କରନ୍ତୁ |" - }, - "camera": { - "name": "କ୍ୟାମେରା", - "description": "ପରଫେକ୍ଟ ସ୍ନାପ୍ ପାଇଁ ସଠିକ୍ ସେଟିଙ୍ଗ୍ ଆଡଜଷ୍ଟ କରନ୍ତୁ |", - "properties": { - "disable_cameras": { - "name": "କ୍ୟାମେରା ଅକ୍ଷମ କରନ୍ତୁ |", - "description": "ସିଲେକ୍ଟ ହୋଇଥିବା କ୍ୟାମେରା ବ୍ୟବହାରରୁ ସ୍ନାପଚାଟକୁ ପ୍ରତିରୋଧ କରେ |" - }, - "black_photos": { - "name": "କଳା ଫଟୋ", - "description": "ଏକ କଳା ପୃଷ୍ଠଭୂମି ସହିତ ଧରାଯାଇଥିବା ଫଟୋକୁ ବଦଳାଇଲା |\nଭିଡିଓଗୁଡିକ ପ୍ରଭାବିତ ହୁଏ ନାହିଁ |" - }, - "immersive_camera_preview": { - "name": "ଅମରାତ୍ମକ ପୂର୍ବାବଲୋକନ |", - "description": "କ୍ୟାମେରା ପୂର୍ବାବଲୋକନ କ୍ରପ୍ ରୁ ସ୍ନାପଚାଟକୁ ପ୍ରତିରୋଧ କରେ |\nଏହା ହୁଏତ କ୍ୟାମେରାକୁ କିଛି ଡିଭାଇସରେ ଫ୍ଲିକର୍ କରିପାରେ |" - }, - "override_front_resolution": { - "name": "ଆଗ ରିଜୋଲ୍ୟୁସନ୍ କୁ ନବଲିଖନ କରନ୍ତୁ |", - "description": "ଆଗ କ୍ୟାମେରା ପାଇଁ କ୍ୟାମେରା ରିଜୋଲ୍ୟୁସନ୍ କୁ ନବଲିଖନ କରେ |" - }, - "override_back_resolution": { - "name": "ପଛ ରେଜୋଲୁସନକୁ ନବଲିଖନ କରନ୍ତୁ |", - "description": "ପଛ କ୍ୟାମେରା ପାଇଁ କ୍ୟାମେରା ରିଜୋଲ୍ୟୁସନ୍ କୁ ନବଲିଖନ କରେ |" - }, - "custom_resolution": { - "name": "କଷ୍ଟମ୍ ରେଜୋଲୁସନ", - "description": "ଏକ କଷ୍ଟମ୍ କ୍ୟାମେରା ରେଜୋଲୁସନ, ମୋଟେଇ ଏକ୍ସ ଉଚ୍ଚତା (ଯଥା 1920x1080) |\nକଷ୍ଟମ୍ ରେଜୋଲୁସନ ଆପଣଙ୍କ ଡିଭାଇସ୍ ଦ୍ୱାରା ସମର୍ଥିତ ହେବା ଜରୁରୀ |" - }, - "front_custom_frame_rate": { - "name": "ଆଗ କଷ୍ଟମ୍ ଫ୍ରେମ୍ ହାର |", - "description": "ଆଗ କ୍ୟାମେରା ଫ୍ରେମ୍ ହାର ହାରକୁ ନବଲିଖନ କରେ |" - }, - "back_custom_frame_rate": { - "name": "କଷ୍ଟମ୍ ଫ୍ରେମ୍ ହାର |", - "description": "ପଛ କ୍ୟାମେରା ଫ୍ରେମ୍ ହାର ହାରକୁ ନବଲିଖନ କରେ |" - }, - "force_camera_source_encoding": { - "name": "କ୍ୟାମେରା ଉତ୍ସ ଏନକୋଡିଂକୁ ବାଧ୍ୟ କରନ୍ତୁ |", - "description": "କ୍ୟାମେରା ଉତ୍ସ ଏନକୋଡିଂକୁ ବାଧ୍ୟ କରିଥାଏ |" - }, - "startup_default_camera": { - "name": "ଡିଫଲ୍ଟ କ୍ୟାମେରା ଆରମ୍ଭ କରନ୍ତୁ |", - "description": "ସ୍ନାପଚାଟ ଖୋଲିବା ସମୟରେ ଡିଫଲ୍ଟ କ୍ୟାମେରା ସେଟ୍ କରେ |" - }, - "hevc_recording": { - "name": "HEVC ରେକର୍ଡିଂ |", - "description": "ଭିଡିଓ ରେକର୍ଡିଂ ପାଇଁ HEVC (H.265) କୋଡେକ୍ ବ୍ୟବହାର କରେ |" - } - } - }, - "streaks_reminder": { - "name": "ଷ୍ଟ୍ରିକ୍ସ ସ୍ମାରକପତ୍ର |", - "description": "ପର୍ଯ୍ୟାୟକ୍ରମେ ତୁମର ଷ୍ଟ୍ରିକ୍ସ ବିଷୟରେ ସୂଚିତ କରେ |", - "properties": { - "interval": { - "name": "ବ୍ୟବଧାନ", - "description": "ପ୍ରତ୍ୟେକ ସ୍ମାରକପତ୍ର (ଘଣ୍ଟା) ମଧ୍ୟରେ ବ୍ୟବଧାନ |" - }, - "remaining_hours": { - "name": "ଅବଶିଷ୍ଟ ସମୟ", - "description": "ବିଜ୍ଞପ୍ତି (ଘଣ୍ଟା) ଦେଖାଯିବା ପୂର୍ବରୁ ଅବଶିଷ୍ଟ ସମୟ |" - }, - "group_notifications": { - "name": "ଗୋଷ୍ଠୀ ବିଜ୍ଞପ୍ତିଗୁଡିକ", - "description": "ଏକକକୁ ଗୋଷ୍ଠୀ ବିଜ୍ଞପ୍ତି |" - } - } - }, - "experimental": { - "name": "ପରୀକ୍ଷାମୂଳକ |", - "description": "ପରୀକ୍ଷାମୂଳକ ବ features ଶିଷ୍ଟ୍ୟଗୁଡିକ |", - "properties": { - "native_hooks": { - "name": "ଦେଶୀ ହୁକ୍ |", - "description": "ଅସୁରକ୍ଷିତ ବ features ଶିଷ୍ଟ୍ୟଗୁଡିକ ସ୍ନାପଚାଟକର ଦେଶୀ କୋଡ଼ରେ ହୁକ୍ |", - "properties": { - "composer_hooks": { - "name": "ରଚନା ହୁକ୍", - "description": "ରଚନା କ୍ରସ୍ ପ୍ଲାଟଫର୍ମ UI framework ାଞ୍ଚାରେ କୋଡ୍ ଇଞ୍ଜେକ୍ସନ କରେ |", - "properties": { - "show_first_created_username": { - "name": "ପ୍ରଥମ ବ୍ୟବହାର ଉପଯୋଗକର୍ତ୍ତା ନାମ ଦେଖାନ୍ତୁ |", - "description": "ପ୍ରୋଫାଇଲ୍ ପୃଷ୍ଠାରେ ସାମ୍ପ୍ରତିକ ଉପଯୋଗକର୍ତ୍ତା ନାମର ପ୍ରଥମ ନିର୍ଦ୍ଦେଶିତ ଉପଯୋଗକର୍ତ୍ତା ନାମ ଦର୍ଶାଏ |" - }, - "bypass_camera_roll_limit": { - "name": "କ୍ୟାମେରା ରୋଲ୍ ସୀମା ବାଇପାସ୍ କରନ୍ତୁ |", - "description": "ଆପଣ କ୍ୟାମେରା ରୋଲରୁ ପ୍ୟାକେଜ୍ ପଠାଉଥିବା ମିଡିଆକୁ ବ increases ାଇଥାଏ |" - }, - "custom_self_destruct_snap_delay": { - "name": "କଷ୍ଟମ୍ ସ୍ sun ତୁକିଆନ ସ୍ନାପ୍ ବିଳମ୍ବ |", - "description": "ଏକ ସ୍ନାପ୍ ପଠାଇବାବେଳେ ଆତ୍ମ-ବିନାଶ ଟାଇମର୍ ପାଇଁ ଅଧିକ ବିକଳ୍ପ ଦେଇଥାଏ |" - }, - "composer_console": { - "name": "ରଚନା କନସୋଲ୍ |", - "description": "ଆପଣଙ୍କୁ ରଚନା (କେବଳ ବାହୁବଳୀ) ରେ ଜାଭାସ୍କ୍ରିପ୍ଟ କୋଡ୍ ଏକଜେକ୍ୟୁଟ୍ କରିବାକୁ ଅନୁମତି ଦିଏ |" - }, - "composer_logs": { - "name": "ରଚନା ଲଗ୍", - "description": "Purrfectsnap କୁ ରଚନାଗୁଡ଼ିକର କୋନସୋଲ ଲଗଗୁଡ଼ିକର ପୁନ ir ନିର୍ଦ୍ଦେଶ କରେ |" - } - } - }, - "disable_bitmoji": { - "name": "ବିଟମୋଜୀକୁ ଅକ୍ଷମ କରନ୍ତୁ |", - "description": "ବନ୍ଧୁ ପ୍ରୋଫାଇଲ୍ ବିଟମୋଜୀକୁ ଅକ୍ଷମ କରିଥାଏ |" - }, - "custom_emoji_font": { - "name": "କଷ୍ଟମ୍ ଇମୋଜି ଫଣ୍ଟ |", - "description": "ଆପଣଙ୍କୁ ଏକ କଷ୍ଟମ୍ ଇମୋଜି ଫଣ୍ଟ ବ୍ୟବହାର କରିବାକୁ ଅନୁମତି ଦିଏ | କେବଳ .ttef ଫଣ୍ଟ ସହିତ କାମ କରେ |" - }, - "custom_shared_library": { - "name": "କଷ୍ଟମ୍ ଅଂଶୀଦାର ଲାଇବ୍ରେରୀ |", - "description": "ସ୍ନାପଚାଟରେ ଏକ କଷ୍ଟମ୍ ଅଂଶୀଦାର ଲାଇବ୍ରେରୀ ଲୋଡ୍ କରେ | ଏହି ବ feature ଶିଷ୍ଟ୍ୟ କେବଳ ପରୀକ୍ଷା ଉଦ୍ଦେଶ୍ୟରେ |" - } - } - }, - "spoof": { - "name": "Spof", - "description": "ଆପଣଙ୍କ ବିଷୟରେ ବିଭିନ୍ନ ସୂଚନା ସ୍ପଫ୍ କରନ୍ତୁ |", - "properties": { - "play_store_installer_package_name": { - "name": "ଷ୍ଟୋର ସଂସ୍ଥାପକ ପ୍ୟାକେଜ୍ ନାମ ଖେଳନ୍ତୁ |", - "description": "Am.ndarid.vend କୁ ସଂସ୍ଥାପକ ପ୍ୟାକେଜ୍ ନାମକୁ ନବଲିଖନ କରେ |" - }, - "remove_vpn_transport_flag": { - "name": "VPN ପରିବହନ ପତାକା ହଟାନ୍ତୁ |", - "description": "Vprind ଚିହ୍ନଟ କରିବାରେ ସ୍ନାପଚାଟକୁ ପ୍ରତିରୋଧ କରେ |" - }, - "remove_mock_location_flag": { - "name": "ପରିସଂଖ୍ୟାନ ଅବସ୍ଥାନ ଫ୍ଲାଗ୍ ଅପସାରଣ କରନ୍ତୁ |", - "description": "ମକ୍ ଅବସ୍ଥାନ ଚିହ୍ନଟ କରିବାରେ ସ୍ନାପଚାଟକୁ ପ୍ରତିରୋଧ କରେ |" - } - } - }, - "convert_message_locally": { - "name": "ସ୍ଥାନୀୟ ଭାବରେ ସନ୍ଦେଶକୁ ରୂପାନ୍ତର କରନ୍ତୁ |", - "description": "ସ୍ନାପ୍ସକୁ ସ୍ଥାନୀୟ ଭାବରେ ବାହ୍ୟ ମିଡିଆ ଚାଟ୍ କରିବାକୁ ରୂପାନ୍ତର କରେ | ଏହା ଚାଟ୍ ଡାଉନଲୋଡ୍ ପ୍ରସଙ୍ଗ ମେନୁରେ ଦେଖାଯାଏ |" - }, - "media_file_picker": { - "name": "ମିଡିଆ ଫାଇଲ୍ ପିକର୍ |", - "description": "ଗ୍ୟାଲେରୀରୁ ଆପଣଙ୍କୁ କ vail ଣସି ଭିଡିଓ / ଅଡିଓ ଫାଇଲ୍ ବାଛିବାକୁ ଅନୁମତି ଦିଏ |" - }, - "story_logger": { - "name": "କାହାଣୀ ଲଗର |", - "description": "ସାଙ୍ଗମାନଙ୍କ କାହାଣୀର ଏକ ଇତିହାସ ପ୍ରଦାନ କରେ |" - }, - "call_recorder": { - "name": "କଲ୍ ରେକର୍ଡର୍ |", - "description": "ସ୍ୱୟଂଚାଳିତ ଭାବରେ ଅଡିଓ କଲ୍ ରେକର୍ଡ କରେ |" - }, - "account_switcher": { - "name": "ଆକାଉଣ୍ଟ୍ ସୁଇଚର୍ |", - "description": "ଲଗ୍ ଆଉଟ୍ ନକରି ଆକାଉଣ୍ଟ୍ ମଧ୍ୟରେ ସୁଇଚ୍ କରିବାକୁ ଅନୁମତି ଦିଏ |\nମେନୁ ଖୋଲିବା ପାଇଁ ଆପଣଙ୍କ ବିଟମୋଜି ପ୍ରୋଫାଇଲରେ ସର୍ଚ୍ଚ ଆଇକନ୍ ଉପରେ ଲଙ୍ଗ୍ ଦବାନ୍ତୁ |\nଟିପନ୍ତୁ: ଏହି ବ feature ଶିଷ୍ଟ୍ୟ ପରୀକ୍ଷାମୂଳକ ଏବଂ ଭବିଷ୍ୟତରେ ବୋଧହୁଏ ପରିବର୍ତ୍ତନ ହେବ |", - "properties": { - "auto_backup_current_account": { - "name": "ଅଟୋ ବ୍ୟାକଅପ୍ ସାମ୍ପ୍ରତିକ ଆକାଉଣ୍ଟ୍ |", - "description": "ଲଗ୍ ଆଉଟ୍ କିମ୍ବା ସୁଇଚ୍ କରିବା ସମୟରେ ସାମ୍ପ୍ରତିକ ଆକାଉଣ୍ଟ୍ ସ୍ୱୟଂଚାଳିତ ଭାବରେ ବ୍ୟାକଅପ୍ କରେ |" - } - } - }, - "better_transcript": { - "name": "ଉତ୍ତମ ଟ୍ରାନ୍ସକ୍ରିପ୍ଟ |", - "description": "ଭଏସ୍ ନୋଟ୍ ଟ୍ରାନ୍ସକ୍ରିପ୍ଟକୁ ଉନ୍ନତ କରେ |", - "properties": { - "force_transcription": { - "name": "ଫୋର୍ସ ଭଏସ୍ ନୋଟ୍ ଟ୍ରାନ୍ସକ୍ରିପସନ୍ |", - "description": "ସମସ୍ତ ଭଏସ୍ ନୋଟ୍ ଗୁଡିକ ଟ୍ରାନ୍ସକ୍ରିପଡ୍ କରିବାକୁ ଅନୁମତି ଦିଏ |" - }, - "preferred_transcription_lang": { - "name": "ପସନ୍ଦିତ ଟ୍ରାନ୍ସକ୍ରିପସନ୍ ଭାଷା |", - "description": "ଭଏସ୍ ନୋଟ୍ ଟ୍ରାନ୍ସକ୍ରିପ୍ଟ ପାଇଁ ପସନ୍ଦିତ ଭାଷା (ଯଥା EN, ES)" - }, - "notification_transcript": { - "name": "ବିଜ୍ଞପ୍ତି ଟ୍ରାନ୍ସକ୍ରିପ୍ |", - "description": "ବିଜ୍ଞପ୍ତିରେ ଭଏସ୍ ନୋଟ୍ ଗୁଡିକୁ ଟ୍ରାନ୍ସକ୍ରିପସନ୍ କରନ୍ତୁ |\nଏହି ବ feature ଶିଷ୍ଟ୍ୟ ଭଲ ବିଜ୍ଞପ୍ତିରେ ସକ୍ଷମ ହେବାକୁ ଥିବା ଚାଟ୍ ପୂର୍ବାବଲୋକନ ବ feature ଶିଷ୍ଟ୍ୟ ଆବଶ୍ୟକ କରେ |" - } - } - }, - "voice_note_auto_play": { - "name": "ଭଏସ୍ ନୋଟ୍ ଅଟୋ ପ୍ଲେ |", - "description": "ସାମ୍ପ୍ରତିକ ଗୋଟିଏ ସମାପ୍ତ ହେବା ପରେ ସ୍ୱୟଂଚାଳିତ ଭାବରେ ପରବର୍ତ୍ତୀ ଭଏସ୍ ନୋଟ୍ ଗୁଡିକୁ ବାଦ ଦେଇଥାଏ |" - }, - "friend_notes": { - "name": "ସାଙ୍ଗ ନୋଟ୍", - "description": "ସାଙ୍ଗମାନଙ୍କୁ ବନ୍ଧୁ ପ୍ରୋଫାଇଲରେ ନୋଟ୍ ଯୋଡିବାକୁ ଅନୁମତି ଦିଏ |" - }, - "cof_experiments": { - "name": "Cof ପରୀକ୍ଷଣ |", - "description": "ଅବିଭକ୍ତ / ବିଟା ସ୍ନାପଚ୍ ବ features ଶିଷ୍ଟ୍ୟଗୁଡିକ ସକ୍ଷମ କରେ |" - }, - "context_menu_fix": { - "name": "ପ୍ରସଙ୍ଗ ତାଲିକା ଠିକ ଅଛି |", - "description": "ଯେତେବେଳେ ଡିଭାଇସ୍ ଅଫଲାଇନ୍ ଯେତେବେଳେ ଡିଭାଇସ୍ ଅଫଲାଇନ୍ ହୁଏ ଏହା ସଠିକ୍ ଭାବରେ ପ୍ରଦର୍ଶିତ ହୋଇପାରିବ ନାହିଁ |" - }, - "app_lock": { - "name": "ଆପ୍ ଲକ୍ |", - "description": "ପାସକୋଡ୍ ବିନା ସ୍ନାପଚ୍ କୁ ପ୍ରବେଶକୁ ରୋକିଥାଏ |", - "properties": { - "lock_on_resume": { - "name": "ରିଜ୍ୟୁମ୍ ଉପରେ ଲକ୍ କରନ୍ତୁ |", - "description": "ଯେତେବେଳେ ଏହା ଖୋଲାଯାଏ ଆପ୍କୁ ଲକ୍ କରେ |" - } - } - }, - "infinite_story_boost": { - "name": "ଅସୀମ କାହାଣୀ ବୃଦ୍ଧି |", - "description": "କାହାଣୀକୁ ବହିଷ୍କାର ସୀମିତତା ବିଲୋପ କରନ୍ତୁ |" - }, - "meo_passcode_bypass": { - "name": "ମୋର ଆଖି କେବଳ ପାସକୋଡ୍ ବାଇପାସ୍ |", - "description": "ମୋ ଆଖିକୁ ବାଇସୋଜ୍ କେବଳ ପାସକୋଡ୍ |\nଯଦି ପାସକୋଡ୍ ସଠିକ୍ ଭାବରେ ପ୍ରବେଶ କରାଯାଏ ତେବେ ଏହା କେବଳ କାମ କରିବ |" - }, - "no_friend_score_delay": { - "name": "କ friend ଣସି ବନ୍ଧୁ ସ୍କୋର ବିଳମ୍ବ ନାହିଁ |", - "description": "ଏକ ସାଙ୍ଗମାନଙ୍କ ସ୍କୋର ଦେଖିବାରେ ବିଳମ୍ବକୁ ଅପସାରଣ କରେ |" - }, - "best_friend_pinning": { - "name": "ସର୍ବୋତ୍ତମ ବନ୍ଧୁ ପିନ୍ |", - "description": "ତୁମ ନମ୍ବରକୁ ତୁମର ନମ୍ବର ଭାବରେ ଜଣେ ବନ୍ଧୁଙ୍କୁ ପିନ୍ କରିବାକୁ ଅନୁମତି ଦିଏ | ଟିପନ୍ତୁ: କେବଳ ଆପଣ ଆପଣଙ୍କର ପିନ୍ ହୋଇଥିବା ସର୍ବୋତ୍ତମ ବନ୍ଧୁଙ୍କୁ ଦେଖିପାରିବେ |" - }, - "e2ee": { - "name": "ଶେଷ-ଏଣ୍ଡ ଏନକ୍ରିପସନ୍ |", - "description": "ଏକ ଅଂଶୀଦାର ଗୁପ୍ତ ଚାବି ବ୍ୟବହାର କରି AES ସହିତ ଆପଣଙ୍କର ସନ୍ଦେଶଗୁଡ଼ିକୁ ଏନକ୍ରିପ୍ଟ କରେ |\nତୁମର ଚାବିକୁ ସୁରକ୍ଷିତ ସ୍ଥାନକୁ ସେଭ୍ କରିବାକୁ ନିଶ୍ଚିତ କର!", - "properties": { - "encrypted_message_indicator": { - "name": "ଏନକ୍ରିପ୍ଟ ହୋଇଥିବା ସନ୍ଦେଶ ସୂଚକ |", - "description": "ଏନକ୍ରିପ୍ଟ ହୋଇଥିବା ସନ୍ଦେଶଗୁଡ଼ିକ ପାଖରେ ଏକ 🔒 ଇମୋଜି ଯୋଗ କରେ |" - }, - "force_message_encryption": { - "name": "ବାର୍ତ୍ତା ଏନକ୍ରିପସନ୍ ବେକ କରନ୍ତୁ |", - "description": "ଯେଉଁ ଲୋକମାନଙ୍କୁ ଏନକ୍ରିପ୍ଟ ହୋଇଥିବା ବାର୍ତ୍ତା ପଠାଇବାକୁ ପ୍ରତିରୋଧ କରେ ଯେଉଁମାନଙ୍କ ପାଖରେ E2E ଏନକ୍ରିପସନ୍ ନାହିଁ ଯେତେବେଳେ ଏକାଧିକ ବାର୍ତ୍ତାଳାପ ଚୟନ ହୁଏ |" - } - } - }, - "add_friend_source_spoof": { - "name": "ବନ୍ଧୁ ଉତ୍ସ ସ୍ପୋଫ୍ ଯୋଡନ୍ତୁ |", - "description": "ଏକ ବନ୍ଧୁ ଅନୁରୋଧର ଉତ୍ସର ସ୍ପୋଫ୍ |" - }, - "hidden_snapchat_plus_features": { - "name": "ଲୁକ୍କାୟିତ SCAPCHAT ପ୍ଲସ୍ ବ features ଶିଷ୍ଟ୍ୟ |", - "description": "ଅବିଭକ୍ତ / ବିଟା ସ୍ନାପଚ୍ ପ୍ଲସ୍ ବ features ଶିଷ୍ଟ୍ୟଗୁଡିକ ସକ୍ଷମ କରେ |\nପୁରୁଣା ସ୍ନାପଚାଟ ସଂସ୍କରଣରେ କାମ କରିନପାରେ |" - }, - "custom_streaks_expiration_format": { - "name": "କଷ୍ଟମ୍ ଷ୍ଟ୍ରକ୍ ମିଆଦ ପୂର୍ଣ୍ଣ ଫର୍ମାଟ୍ |", - "description": "ଷ୍ଟ୍ରକ୍ସର ସମାପ୍ତି ଫର୍ମାଟ୍ କୁ କଷ୍ଟମାଇଜ୍ କରେ |\n\nଉପଲବ୍ଧ ଭେରିଏବଲ୍:\n -% C: ଷ୍ଟ୍ରିକ୍ସ ଗଣନା |\n -% ଇ: ହୋମ୍ଲାସସ୍ ଇମୋଜି |\n -% D: ଦିନ |\n -% h: ଘଣ୍ଟା |\n -% m: ମିନିଟ୍ |\n -% S: ସେକେଣ୍ଡ୍ |\n -% W: ଅବଶିଷ୍ଟ ସମୟ |" - }, - "prevent_forced_logout": { - "name": "ବାଧ୍ୟତାମୂଳକ ଲଗଆଉଟ୍ କୁ ରୋକନ୍ତୁ |", - "description": "ଯେତେବେଳେ ଆପଣ ଅନ୍ୟ ଡିଭାଇସରେ ଲଗ୍ଇନ୍ କରନ୍ତି, ତୁମକୁ ଲଗ୍ ଆଉଟ୍ କରିବାକୁ ବାରଣ କରେ |" - }, - "snapscore_changes": { - "name": "ସ୍ନାପସସ୍କୋର ପରିବର୍ତ୍ତନ |", - "description": "ସାଙ୍ଗମାନଙ୍କ ସ୍ନାପସସ୍କୋରରେ ପରିବର୍ତ୍ତନଗୁଡିକ |\nକେବଳ ସ୍ନାପଚାଟର ନୂତନ ସଂସ୍କରଣରେ ଏହି ବ feature ଶିଷ୍ଟ୍ୟ ବ୍ୟବହାର କରନ୍ତୁ |" - } - } - }, - "scripting": { - "name": "ସ୍କ୍ରିପ୍ଟିଂ", - "description": "Purrfectsnap ବିସ୍ତାର କରିବାକୁ କଷ୍ଟମ୍ ସ୍କ୍ରିପ୍ଟଗୁଡିକ ଚଲାନ୍ତୁ |", - "properties": { - "developer_mode": { - "name": "ଡେଭଲପର୍ ମୋଡ୍ |", - "description": "ସ୍ନାପଚାଟଙ୍କ UI ଉପରେ ଡିବଗ୍ ସୂଚନା ଦେଖାଏ |" - }, - "module_folder": { - "name": "ମଡ୍ୟୁଲ୍ ଫୋଲ୍ଡର |", - "description": "ଯେଉଁଠାରେ ସ୍କ୍ରିପ୍ଟଗୁଡ଼ିକ ଅବସ୍ଥିତ ତାହା ଫୋଲ୍ଡର୍ |" - }, - "auto_reload": { - "name": "ଅଟୋ ପୁନ elo ଲୋଡ୍ |", - "description": "ଯେତେବେଳେ ସେମାନେ ପରିବର୍ତ୍ତନ କରନ୍ତି ତେବେ ସ୍କ୍ରିପ୍ଟଗୁଡ଼ିକୁ ପୁନ elo ଲୋଡ୍ କରନ୍ତୁ |" - }, - "integrated_ui": { - "name": "ଇଣ୍ଟିଗ୍ରେଟେଡ୍ UI |", - "description": "ସ୍ନାପଚାଟରେ କଷ୍ଟମ୍ UI ଉପାଦାନଗୁଡିକ ଯୋଡିବାକୁ ସ୍କ୍ରିପ୍ଟଗୁଡ଼ିକୁ ଅନୁମତି କରିବାକୁ ଅନୁମତି ଦିଏ |" - }, - "disable_log_anonymization": { - "name": "ଲଗ୍ ଅଜ୍ଞାତକରଣକୁ ଅକ୍ଷମ କରନ୍ତୁ |", - "description": "ଲଗର ଅଜ୍ଞାତତାକୁ ଅକ୍ଷମ କରିଥାଏ |" - }, - "disable_optimization": { - "name": "ଅପ୍ଟିମାଇଜେସନ୍ ଅକ୍ଷମ କରନ୍ତୁ |", - "description": "ସ୍କ୍ରିପ୍ଟଗୁଡ଼ିକର ଅପ୍ଟିମାଇଜେସନ୍ ଅକ୍ଷମ କରେ | ଏହା କାର୍ଯ୍ୟଦକ୍ଷତା ସମସ୍ୟା ସୃଷ୍ଟି କରିପାରେ |" - } - } - }, - "friend_tracker": { - "name": "ବନ୍ଧୁ ଟ୍ରାକର", - "description": "ସ୍ନାପଚାଟରେ ବନ୍ଧୁଙ୍କ କାର୍ଯ୍ୟକଳାପ ରେକର୍ଡ କରେ |", - "properties": { - "record_messaging_events": { - "name": "ମେସେଜିଂ ଇଭେଣ୍ଟଗୁଡିକ ରେକର୍ଡ କରନ୍ତୁ |", - "description": "ମେସେଜ୍ ଖୋଲିବା ପରି ମେସେଜିଂ ଇଭେଣ୍ଟଗୁଡିକ ରେକର୍ଡ କରେ, ଏକ ବାର୍ତ୍ତା ପ reading ିବା ଇତ୍ୟାଦି |" - }, - "allow_running_in_background": { - "name": "ପୃଷ୍ଠଭୂମିରେ ଚାଲିବାକୁ ଅନୁମତି ଦିଅନ୍ତୁ |", - "description": "ଟ୍ରାକରକୁ ପୃଷ୍ଠଭୂମିରେ ଚାଲିବାକୁ ଅନୁମତି ଦିଏ | ଟିପନ୍ତୁ: ଏହା ଆପଣଙ୍କ ବ୍ୟାଟେରୀକୁ ଯଥେଷ୍ଟ ନିଷ୍କାସନ କରିବ |" - }, - "auto_purge": { - "name": "ଅଟୋ ଶୁଦ୍ଧ", - "description": "ନିର୍ଦ୍ଦିଷ୍ଟ ସମୟଠାରୁ ପୁରୁଣା ଷ୍ଟାଚ୍ ଇଭେଣ୍ଟଗୁଡିକ ସ୍ୱୟଂଚାଳିତ ଭାବରେ ଡିଲିଟ୍ କରେ |" - } - } - } - }, - "options": { - "app_appearance": { - "always_light": "ସର୍ବଦା ଆଲୋକ |", - "always_dark": "ସବୁବେଳେ ଅନ୍ଧକାର |" - }, - "friend_feed_menu_buttons": { - "auto_download": "⬇️ ଅଟୋ ଡାଉନଲୋଡ୍ |", - "auto_save": "💬 ଅଟୋ ଫାଇଲ୍ ସେଭ୍ କରନ୍ତୁ |", - "unsaveable_messages": "⬇️ ସଂପୂର୍ଣ୍ଣ ଯୋଗ୍ୟ ବାର୍ତ୍ତା |", - "auto_open_snaps": "📷 ଅଟୋ ଓପନ୍ ସ୍ଫାପ୍ |", - "stealth": "👻 ଚୋରି ମୋଡ୍ |", - "mark_snaps_as_seen": "ଦେଖାଯାଇଥିବା ପରି ସ୍ନାପ୍ଗୁଡ଼ିକୁ ଚିହ୍ନିତ କରେ |", - "mark_stories_as_seen_locally": "ସ୍ଥାନୀୟ ଭାବରେ ଦେଖାଯାଉଥିବା ପରି କାହାଣୀକୁ ଚିହ୍ନିତ କରେ |", - "conversation_info": "👤 ବାର୍ତ୍ତାଳାପ ସୂଚନା |", - "e2e_encryption": "E2e ଏନକ୍ରିପସନ୍ ବ୍ୟବହାର କରନ୍ତୁ |" - }, - "path_format": { - "create_author_folder": "ପ୍ରତ୍ୟେକ ଲେଖକଙ୍କ ପାଇଁ ଫୋଲ୍ଡର ସୃଷ୍ଟି କରନ୍ତୁ |", - "create_source_folder": "ପ୍ରତ୍ୟେକ ମିଡିଆ ଉତ୍ସ ପ୍ରକାର ପାଇଁ ଫୋଲ୍ଡର ସୃଷ୍ଟି କରନ୍ତୁ |", - "append_hash": "ଫାଇଲ୍ ନାମ ସହିତ ଏକ ଅନନ୍ୟ ହ୍ୟାସ୍ ଯୋଡନ୍ତୁ |", - "append_source": "ଫାଇଲ୍ ନାମକୁ ମିଡିଆ ଉତ୍ସ ଯୋଡନ୍ତୁ |", - "append_username": "ଫାଇଲ୍ ନାମ ସହିତ ଉପଯୋଗକର୍ତ୍ତା ନାମ ଯୋଡନ୍ତୁ |", - "append_date_time": "ଫାଇଲ୍ ନାମକୁ ତାରିଖ ଏବଂ ସମୟ ଯୋଡନ୍ତୁ |" - }, - "auto_download_sources": { - "friend_snaps": "ବନ୍ଧୁ ସ୍ନାପ୍ |", - "friend_stories": "ବନ୍ଧୁ କାହାଣୀ", - "public_stories": "ସର୍ବସାଧାରଣ କାହାଣୀ |", - "spotlight": "ସ୍ପଟ୍ ଲାଇଟ୍ |" - }, - "logging": { - "started": "ଆରମ୍ଭ କରିବା", - "success": "ସଫଳତା", - "progress": "ପ୍ରଗତି", - "failure": "ବିଫଳତା" - }, - "notifications": { - "chat_screenshot": "ସ୍କ୍ରିନସଟ୍ |", - "chat_screen_record": "ସ୍କ୍ରିନ୍ ରେକର୍ଡ |", - "snap_replay": "ସ୍ନାପ୍ ରିପ୍ଲେ |", - "camera_roll_save": "କ୍ୟାମେରା ରୋଲ୍ ସେଭ୍ |", - "chat": "ଚାଟ୍ କରନ୍ତୁ |", - "chat_reply": "ଚାଟ୍ ଉତ୍ତର ଦିଅ |", - "snap": "ସ୍ନାପ୍", - "typing": "ଟାଇପ୍ କରିବା", - "stories": "କାହାଣୀଗୁଡ଼ିକ", - "speaking": "କହିବା", - "chat_reaction": "DM ପ୍ରତିକ୍ରିୟା", - "group_chat_reaction": "ଗ୍ରୁପ୍ ପ୍ରତିକ୍ରିୟା", - "initiate_audio": "ଆସୁଥିବା ଅଡିଓ କଲ୍ |", - "abandon_audio": "ଅଡିଓ କଲ୍ ମିସ୍ |", - "initiate_video": "ଆସୁଥିବା ଭିଡିଓ କଲ୍ |", - "abandon_video": "ଭିଡିଓ କଲ୍ ମିସ୍ କରନ୍ତୁ |", - "map_live_location": "ମାନଚିତ୍ର ଲାଇଭ୍ ଅବସ୍ଥାନ |" - }, - "gallery_media_send_override": { - "always_ask": "ସର୍ବଦା ପଚାର |", - "ORIGINAL": "ମୂଳ ମିଡିଆ |", - "NOTE": "ଅଡିଓ ନୋଟ୍ |", - "SNAP": "ସ୍ନାପ୍", - "SAVEABLE_SNAP": "ସେଭ୍ ଯୋଗ୍ୟ ସ୍ନାପ୍ |" - }, - "strip_media_metadata": { - "hide_caption_text": "କ୍ୟାପସନ୍ ପାଠ୍ୟ ଲୁଚାନ୍ତୁ |", - "hide_snap_filters": "ସ୍ନାପ୍ ଫିଲ୍ଟରଗୁଡିକ ଲୁଚାନ୍ତୁ |", - "hide_extras": "ଅତିରିକ୍ତ ଲୁଚାନ୍ତୁ (ଯଥା)", - "remove_audio_note_duration": "ଅଡିଓ ନୋଟ୍ ଅବଧି ଅପସାରଣ କରନ୍ତୁ |", - "remove_audio_note_transcript_capability": "ଅଡିଓ ନୋଟ୍ ଟ୍ରାନ୍ସକ୍ରିପ୍ଟ କ୍ଷମତା ଅପସାରଣ କରନ୍ତୁ |" - }, - "hide_ui_components": { - "hide_profile_call_buttons": "ପ୍ରୋଫାଇଲ୍ କଲ୍ ବଟନ୍ ହଟାନ୍ତୁ |", - "hide_chat_call_buttons": "ଚାଟ୍ କଲ୍ ବଟନ୍ ଅପସାରଣ କରନ୍ତୁ |", - "hide_live_location_share_button": "ଲାଇଭ୍ ଅବସ୍ଥାନ ଅଂଶୀଦାର ବଟନ୍ ଅପସାରଣ କରନ୍ତୁ |", - "hide_stickers_button": "ଷ୍ଟିକର ବଟନ୍ ଅପସାରଣ କରନ୍ତୁ |", - "hide_voice_record_button": "ଭଏସ୍ ରେକର୍ଡ ବଟନ୍ ଅପସାରଣ କରନ୍ତୁ |", - "hide_unread_chat_hint": "ପ read ଼ା ଚାଟ୍ ଇଙ୍ଗିତ ହଟାନ୍ତୁ |", - "hide_post_to_story_buttons": "ସ୍ନାପ୍ ପଠାଇବା ପୂର୍ବରୁ କାହାଣୀ ବଟନ୍ କୁ ହଟାନ୍ତୁ |", - "hide_billboard_prompt": "ସାଙ୍ଗମାନଙ୍କୁ ଫିଡ୍ ରେ ବିଲବୋର୍ଡ ପ୍ରମ୍ପ୍ଟ୍ ଅପସାରଣ କରନ୍ତୁ |", - "hide_snapchat_plus_gift_reminders": "ବାର୍ତ୍ତାଳାପରେ ସ୍ନାପଚାଟ ପ୍ଲସ୍ ରାଇଜ୍ ରିମାଇଜ୍ ଅପସାରଣ କରନ୍ତୁ |", - "hide_map_reactions": "ମାନଚିତ୍ର ପ୍ରତିକ୍ରିୟା ଅପସାରଣ କରନ୍ତୁ |" - }, - "hide_story_suggestions": { - "hide_suggested_friend_stories": "ପରାମର୍ଶିତ ବନ୍ଧୁ କାହାଣୀ ଲୁଚାନ୍ତୁ |", - "hide_my_stories": "ମୋର କାହାଣୀ ଲୁଚାନ୍ତୁ |" - }, - "home_tab": { - "map": "ମାନଚିତ୍ର", - "chat": "ଚାଟ୍ କରନ୍ତୁ |", - "camera": "କ୍ୟାମେରା", - "discover": "ଆବିଷ୍କାର କରନ୍ତୁ |", - "spotlight": "ସ୍ପଟ୍ ଲାଇଟ୍ |" - }, - "add_friend_source_spoof": { - "added_by_username": "ଉପଯୋଗକର୍ତ୍ତା ନାମ ଦ୍ୱାରା |", - "added_by_mention": "ଉଲ୍ଲେଖ କରି", - "added_by_group_chat": "ଗ୍ରୁପ୍ ଚାଟ୍ ଦ୍ୱାରା |", - "added_by_qr_code": "QR କୋଡ୍ ଦ୍ୱାରା |", - "added_by_community": "ସମ୍ପ୍ରଦାୟ ଦ୍ୱାରା", - "added_by_quick_add": "ଶୀଘ୍ର ଯୋଡିବା ଦ୍ୱାରା (ନିଷେଧ ହେବାର ଅଧିକ ବିପଦ)" - }, - "bypass_video_length_restriction": { - "single": "ଏକକ ମିଡିଆ |", - "split": "ମିଡିଆ ବିଭାଜିତ କରନ୍ତୁ |" - }, - "old_bitmoji_selfie": { - "2d": "2D Bitmoji |", - "3d": "3D ବିଟମୋଜୀ |" - }, - "disable_confirmation_dialogs": { - "erase_message": "ବାର୍ତ୍ତା ଲିଭାନ୍ତୁ |", - "remove_friend": "ସାଙ୍ଗକୁ ହଟାନ୍ତୁ |", - "block_friend": "ସାଙ୍ଗରେ ଅବରୋଧ", - "ignore_friend": "ବନ୍ଧୁକୁ ଅଣଦେଖା କରନ୍ତୁ |", - "hide_friend": "ସାଙ୍ଗକୁ ଲୁଚାନ୍ତୁ |", - "hide_conversation": "ବାର୍ତ୍ତାଳାପକୁ ଲୁଚାନ୍ତୁ |", - "clear_conversation": "ବନ୍ଧୁ ଫିଡ୍ ରୁ ବାର୍ତ୍ତାଳାପ ବନ୍ଦ |" - }, - "auto_reload": { - "snapchat_only": "କେବଳ ସ୍ନାପଚ୍", - "all": "ସମସ୍ତ (ସ୍ନାପଚ୍ + purrfrufsnap)" - }, - "edit_text_override": { - "multi_line_chat_input": "ମଲ୍ଟି ଲାଇନ୍ ଚାଟ୍ ଇନପୁଟ୍ |", - "bypass_text_input_limit": "ପାଠ୍ୟ ଇନପୁଟ୍ ସୀମା ବାଇପାସ୍ କରନ୍ତୁ |" - }, - "auto_purge": { - "never": "କେବେ ନୁହେଁ", - "1_hour": "1 ଘଣ୍ଟା", - "3_hours": "3 ଘଣ୍ଟା", - "6_hours": "6 ଘଣ୍ଟା", - "12_hours": "12 ଘଣ୍ଟା", - "1_day": "1 ଦିନ", - "3_days": "3 ଦିନ", - "1_week": "1 ସପ୍ତାହ", - "2_weeks": "2 ସପ୍ତାହ", - "1_month": "1 ମାସ", - "3_months": "3 ମାସ", - "6_months": "6 ମାସ" - }, - "disable_story_sections": { - "friends": "ସାଙ୍ଗଗଣ", - "suggested_stories": "ପ୍ରସ୍ତାବିତ କାହାଣୀ |", - "following": "ନିମ୍ନଲିଖିତ", - "discover": "ଆବିଷ୍କାର କରନ୍ତୁ |" - }, - "disable_cameras": { - "front": "ଆଗ କ୍ୟାମେରା |", - "back": "ପଛ କାଷ୍ଟର" - }, - "disable_permission_requests": { - "notifications": "ବିଜ୍ଞପ୍ତିଗୁଡିକ", - "read_media_images": "ମିଡିଆ ଚିତ୍ର ପ Read ନ୍ତୁ |", - "read_media_video": "ମିଡିଆ ଭିଡିଓ ପ Read ନ୍ତୁ |", - "camera": "କ୍ୟାମେରା", - "microphone": "ମାଇକ୍ରୋଫୋନ୍ |", - "location": "ଅବସ୍ଥାନ", - "read_contacts": "ସମ୍ପର୍କଗୁଡିକ ପ Read ଼ନ୍ତୁ |", - "nearby_devices": "ନିକଟ ଡିଭାଇସ୍ |", - "phone_calls": "ଫୋନ୍ କଲ୍ |" - }, - "message_indicators": { - "encryption_indicator": "ବାର୍ତ୍ତାଗୁଡ଼ିକ ପାଖରେ ଏକ 🔒 ଆଇକନ୍ ଯୋଗ କରେ ଯାହା କେବଳ ତୁମକୁ ପଠାଯାଇଛି |", - "platform_indicator": "ଯେଉଁଥିରୁ ଏକ ମିଡିଆ ପଠାଯାଇଥିଲା, (ଯଥା ଆଣ୍ଡ୍ରଏଡ୍, ଆଇଓ, ୱେବ୍)", - "location_indicator": "ଅବସ୍ଥାନ ସକ୍ଷମ ହେବା ସହିତ ପଠାଯିବାବେଳେ ସ୍ନାପ୍ କରିବାକୁ ଏକ 📍 ଆଇକନ୍ ଯୋଡନ୍ତି |", - "ovf_editor_indicator": "OVF ସମ୍ପାଦକ ବ୍ୟବହାର କରି ଏକ ସ୍ନାପ୍ ପଠାଯାଇଛି କି ନାହିଁ ସୂଚାଇଥାଏ |", - "director_mode_indicator": "ଡାଇର୍ ମୋଡ୍ ବ୍ୟବହାର କରି ପଠାଇବାକୁ ଥିବା ଏକ ✏️ ଆଇକନ୍ କୁ ଯୋଡିବା, ଯାହା ସ୍ନାପ୍ ଭାବରେ ଗ୍ୟାଲେରୀ ପ୍ରତିଛବି ପଠାଇବା ପାଇଁ ବ୍ୟବହୃତ ହୋଇପାରିବ |" - }, - "auto_mark_as_read": { - "conversation_read": "ଏକ ବାର୍ତ୍ତା ପଠାଇବା ସମୟରେ ପ read ଼ିବା ଭାବରେ ବାର୍ତ୍ତାଳାପକୁ ଚିହ୍ନିତ କରନ୍ତୁ |", - "snap_reply": "ସେମାନଙ୍କୁ ଉତ୍ତର ଦେବାବେଳେ ପ read ଼ିବା ପରି ଚିହ୍ନିତ ହୁଏ |", - "save_snap_in_chat": "ଚୋରି ମୋଡରେ ସେମାନଙ୍କୁ ଚାଟ୍ ରେ ସେଭ୍ କରିବା ସମୟରେ ସେମାନଙ୍କୁ ପ read ଼ିବା ପରି ଚିହ୍ନିତ କରେ |" - }, - "friend_mutation_notifier": { - "remove_friend": "ଯେତେବେଳେ କେହି ଆପଣଙ୍କୁ ଜଣେ ବନ୍ଧୁ ଭାବରେ ଅପସାରଣ କରନ୍ତି ସୂଚିତ କରନ୍ତୁ |", - "birthday_changes": "ଯେତେବେଳେ କେହି ଜନ୍ମଦିନ ପରିବର୍ତ୍ତନ କରନ୍ତି ତାହା ସୂଚିତ କରନ୍ତୁ |", - "bitmoji_selfie_changes": "ଯେତେବେଳେ କେହି ସେମାନଙ୍କର ବିଟମୋଜି ଆତ୍ମ ପରିବର୍ତ୍ତନ କରନ୍ତି:", - "bitmoji_avatar_changes": "ଯେତେବେଳେ କେହି ସେମାନଙ୍କର ବିଟମୋଜି ଅବତାର ପରିବର୍ତ୍ତନ କରନ୍ତି ତାହା ସୂଚିତ କରନ୍ତୁ |", - "bitmoji_background_changes": "ଯେତେବେଳେ କେହି ସେମାନଙ୍କର ବିଟମୋଜୀ ପୃଷ୍ଠଭୂମି ପରିବର୍ତ୍ତନ କରନ୍ତି ତାହା ସୂଚିତ କରନ୍ତୁ |", - "bitmoji_scene_changes": "ଯେତେବେଳେ କେହି ସେମାନଙ୍କର ବିଟମୋଜି ଦୃଶ୍ୟ ପରିବର୍ତ୍ତନ କରନ୍ତି ତାହା ସୂଚିତ କର |" - }, - "snapchat_plus": { - "not_subscribed": "ଗ୍ରହୀତା ନୁହେଁ |", - "basic": "ମ basic ଳିକ", - "ad_free": "ଖରାପ ମାଗଣା |" - }, - "double_tap_chat_action": { - "like_message": "ବାର୍ତ୍ତା ପରି |", - "copy_text": "କ୍ଲିପବୋର୍ଡରେ ଟେକ୍ସଟ୍ କପି କରନ୍ତୁ |", - "delete_message": "ବାର୍ତ୍ତା ବିଲୋପ କରନ୍ତୁ |", - "mark_as_read": "ପ read ାଯାଇଥିବା ପରି ଚିହ୍ନ |", - "custom_emoji_reaction": "କଷ୍ଟମ୍ ଇମୋଜି ପ୍ରତିକ୍ରିୟା |" - }, - "startup_default_camera": { - "front": "ଆଗ କ୍ୟାମେରା |", - "back": "ପଛ କାଷ୍ଟର" - } - } - }, - "friend_menu_option": { - "mark_snaps_as_seen": "ଦେଖାଯାଇଥିବା ପରି ଚିହ୍ନିତ |", - "mark_stories_as_seen_locally": "ସ୍ଥାନୀୟ ଭାବରେ ଦେଖାଯାଉଥିବା କାହାଣୀଗୁଡିକ ଚିହ୍ନିତ କରନ୍ତୁ |", - "preview": "ପୂର୍ବାବଲୋକନ", - "stealth_mode": "ଚୋରି ମୋଡ୍", - "auto_download_blacklist": "ଅଟୋ ଡାଉନଲୋଡ୍ ବ୍ଲାକଲିଷ୍ଟ |", - "anti_auto_save": "ଆଣ୍ଟି ଅଟୋ ସେଭ୍ |" - }, - "content_type": { - "CHAT": "ଚାଟ୍ କରନ୍ତୁ |", - "SNAP": "ସ୍ନାପ୍", - "EXTERNAL_MEDIA": "ବାହ୍ୟ ମିଡିଆ |", - "NOTE": "ଅଡିଓ ନୋଟ୍ |", - "STICKER": "ଷ୍ଟିକର |", - "SHARE": "ଅଂଶୀଦାର କରନ୍ତୁ |", - "STATUS": "ସ୍ଥିତି", - "LOCATION": "ଅବସ୍ଥାନ", - "STATUS_SAVE_TO_CAMERA_ROLL": "କ୍ୟାମେରା ରୋଲରେ ସଞ୍ଚୟ |", - "STATUS_CONVERSATION_CAPTURE_SCREENSHOT": "ସ୍କ୍ରିନସଟ୍ |", - "STATUS_CONVERSATION_CAPTURE_RECORD": "ସ୍କ୍ରିନ୍ ରେକର୍ଡ |", - "STATUS_CALL_MISSED_VIDEO": "ଭିଡିଓ କଲ୍ ମିସ୍ କରନ୍ତୁ |", - "STATUS_CALL_MISSED_AUDIO": "ଅଡିଓ କଲ୍ ମିସ୍ |", - "LIVE_LOCATION_SHARE": "ଲାଇଭ୍ ଅବସ୍ଥାନ ଅଂଶୀଦାର |", - "CREATIVE_TOOL_ITEM": "କ୍ରିଏଟିଭ୍ ଟୁଲ୍ ଆଇଟମ୍ |", - "FAMILY_CENTER_INVITE": "ପାରିବାରିକ କେନ୍ଦ୍ର ଆମନ୍ତ୍ରଣ |", - "FAMILY_CENTER_ACCEPT": "ପାରିବାରିକ କେନ୍ଦ୍ର ଗ୍ରହଣ କରେ |", - "FAMILY_CENTER_LEAVE": "ପାରିବାରିକ କେନ୍ଦ୍ର ଛୁଟି |", - "STATUS_PLUS_GIFT": "ସ୍ଥିତି ପ୍ଲସ୍ ଉପହାର |", - "TINY_SNAP": "ଛୋଟ ସ୍ନାପ୍ |", - "STATUS_COUNTDOWN": "କାଉଣ୍ଟଡାଉନ୍", - "MAP_REACTION": "ମାନଚିତ୍ର ପ୍ରତିକ୍ରିୟା" - }, - "media_download_source": { - "none": "କିଛି ନୁହେଁ |", - "pending": "ବିଚାରାଧୀନ ଅଛି", - "chat_media": "ଚାଟ୍ ମିଡିଆ |", - "story": "କାହାଣୀ", - "public_story": "ସର୍ବସାଧାରଣ କାହାଣୀ |", - "spotlight": "ସ୍ପଟ୍ ଲାଇଟ୍ |", - "profile_picture": "ପ୍ରୋଫାଇଲ୍ ଛବି", - "story_logger": "କାହାଣୀ ଲଗର |", - "message_logger": "ବାର୍ତ୍ତା ଲଗର୍ |", - "merged": "ମିଶ୍ରଣ", - "voice_call": "ଭଏସ୍ କଲ୍" - }, - "chat_action_menu": { - "preview_button": "ପୂର୍ବାବଲୋକନ", - "download_button": "ଡାଉନଲୋଡ୍ କରନ୍ତୁ |", - "delete_logged_message_button": "ଲଗ୍ ହୋଇଥିବା ବାର୍ତ୍ତା ବିଲୋପ କରନ୍ତୁ |", - "show_chat_edit_history": "ଚାଟ୍ ଏଡିଟ୍ ଇତିହାସ ଦେଖାନ୍ତୁ |", - "convert_message": "ସନ୍ଦେଶକୁ ରୂପାନ୍ତର କରନ୍ତୁ |" - }, - "opera_context_menu": { - "download": "ମିଡିଆ ଡାଉନଲୋଡ୍ କରନ୍ତୁ", - "sent_at": "{date} କୁ ପଠାଯାଇଛି", - "created_at": "{date} ରେ ସୃଷ୍ଟି", - "expires_at": "{date} ରେ ସମାପ୍ତ ହେବ", - "media_size": "ମିଡିଆ ଆକାର: {size}", - "media_duration": "ଗଣମାଧ୍ୟମ ଅବଧି: {duration} ms", - "show_debug_info": "ଡିବଗ୍ ସୂଚନା ଦେଖାନ୍ତୁ" - }, - "modal_option": { - "profile_info": "ପ୍ରୋଫାଇଲ୍ ସୂଚନା", - "close": "ବନ୍ଦ" - }, - "gallery_media_send_override": { - "multiple_media_toast": "ଆପଣ କେବଳ ଗୋଟିଏ ସମୟରେ ଗୋଟିଏ ମିଡିଆ ପଠାଇ ପାରିବେ |" - }, - "mark_as_seen": { - "no_unseen_snaps_toast": "କ un ଣସି ଅଦୃଶ୍ୟ ସ୍ନାପ୍ସ ମିଳିଲା ନାହିଁ!", - "seen_toast": "ଦେଖାଯାଇଥିବା ପରି ଚିହ୍ନିତ!", - "unseen_toast": "ଅଦୃଶ୍ୟ ଭାବରେ ଚିହ୍ନିତ!", - "already_seen_toast": "ଦେଖାଯାଇଥିବା ପରି ଚିହ୍ନିତ ହୋଇସାରିଛି!", - "already_unseen_toast": "ଅଦୃଶ୍ୟ ଭାବରେ ପୂର୍ବରୁ ଚିହ୍ନିତ ହୋଇସାରିଛି!" - }, - "conversation_preview": { - "streak_expiration": "{days} ଦିନ {hours} ଘଣ୍ଟା {minutes} ମିନିଟ୍", - "total_messages": "ସମୁଦାୟ ପଠାଯାଇଥିବା / ଗ୍ରହଣ କରାଯାଇଥିବା ବାର୍ତ୍ତା: {count}", - "title": "ପୂର୍ବାବଲୋକନ", - "unknown_user": "ଅଜ୍ଞାତ ଉପଭୋକ୍ତା", - "no_messages": "କୌଣସି ମେସେଜ୍ ମିଳିଲା ନାହିଁ!" - }, - "profile_info": { - "title": "ପ୍ରୋଫାଇଲ୍ ସୂଚନା", - "first_created_username": "ପ୍ରଥମ ବ୍ୟବହାରକାରୀ ନାମ", - "mutable_username": "ପରିବର୍ତ୍ତନୀୟ ଉପଭୋକ୍ତା ନାମ", - "display_name": "ପ୍ରଦର୍ଶନ ନାମ", - "added_date": "ଯୋଗ କରାଯାଇଥିବା ତାରିଖ", - "birthday": "ଜନ୍ମଦିନ: {month} {day}", - "hidden_birthday": "ଜନ୍ମଦିନ: ଲୁକ୍କାୟିତ", - "friendship": "ବନ୍ଧୁତା", - "add_source": "ଉତ୍ସ ଯୋଗକରନ୍ତୁ", - "snapchat_plus": "Snapchat+", - "snapchat_plus_state": { - "subscribed": "ଗ୍ରହୀତା", - "not_subscribed": "ଗ୍ରହୀତା ନୁହେଁ" - } - }, - "friendship_link_type": { - "mutual": "ପାରସ୍ପରିକ", - "outgoing": "ଯିବେଳୟ", - "blocked": "ବନ୍ଧାକ", - "deleted": "ବିଲୋପ", - "following": "ନିମ୍ନଲିଖିତ", - "suggested": "ପରାମର୍ଶ ଦିଆଯାଇଛି |", - "incoming": "ଆସୁଥିବା", - "incoming_follower": "ଆସୁଥିବା ଅନୁଗାମୀ |" - }, - "bulk_messaging_action": { - "choose_action_title": "ଏକ କାର୍ଯ୍ୟ ବାଛନ୍ତୁ", - "progress_status": "ପ୍ରକ୍ରିୟାକରଣ {text}", - "selection_dialog_continue_button": "ଜାରି ରଖନ୍ତୁ", - "confirmation_dialog": { - "title": "ଆପଣ ନିଶ୍ଚିତ କି?", - "message": "ଏହା ସମସ୍ତ ମନୋନୀତ ବନ୍ଧୁମାନଙ୍କୁ ପ୍ରଭାବିତ କରିବ। ଏହି କାର୍ଯ୍ୟକୁ ପୂର୍ବବତ୍ କରାଯାଇପାରିବ ନାହିଁ।" - }, - "actions": { - "remove_friends": "ବନ୍ଧୁମାନଙ୍କୁ ଅପସାରଣ କରନ୍ତୁ", - "clear_conversations": "ବାର୍ତ୍ତାଳାପ ସଫା କରନ୍ତୁ" - } - }, - "chat_export": { - "exporter_dialog": { - "select_conversations_title": "ବାର୍ତ୍ତାଳାପ ଚୟନ କରନ୍ତୁ", - "text_field_selection": "{count} ଚୟନିତ", - "text_field_selection_all": "ସମସ୍ତ", - "export_file_format_title": "ଫାଇଲ୍ ଫର୍ମାଟ୍ ରପ୍ତାନି କରନ୍ତୁ", - "message_type_filter_title": "ପ୍ରକାର ଅନୁଯାୟୀ ମେସେଜ୍ ଫିଲ୍ଟର୍ କରନ୍ତୁ", - "amount_of_messages_title": "ମେସେଜ୍ ପରିମାଣ (ସମସ୍ତଙ୍କ ପାଇଁ ଖାଲି ଛାଡି ଦିଅନ୍ତୁ)", - "download_medias_title": "ମିଡିଆ ଡାଉନଲୋଡ୍ କରନ୍ତୁ" - }, - "dialog_negative_button": "ବାତିଲ୍", - "dialog_positive_button": "ରପ୍ତାନି", - "exported_to": "{path} କୁ ରପ୍ତାନି ହୋଇଛି", - "exporting_chats": "ଚାଟ୍ ରପ୍ତାନି କରାଯାଉଛି...", - "processing_chats": "{count} ବାର୍ତ୍ତାଳାପ ପ୍ରକ୍ରିୟାକରଣ କରାଯାଉଛି...", - "export_fail": "{name} ବାର୍ତ୍ତାଳାପ ରପ୍ତାନି କରିବାରେ ବିଫଳ", - "writing_output": "ଆଉଟପୁଟ୍ ଲେଖାଯାଉଛି...", - "finished": "ସମାପ୍ତ! ଆପଣ ବର୍ତ୍ତମାନ ଏହି ଡାୟଲଗ୍ ବନ୍ଦ କରିପାରିବେ।", - "no_messages_found": "କୌଣସି ମେସେଜ୍ ମିଳିଲା ନାହିଁ!", - "exporting_message": "{id} ମେସେଜ୍ ରପ୍ତାନି କରାଯାଉଛି..." - }, - "button": { - "ok": "ଠିକ୍ ଅଛି", - "positive": "ହଁ", - "negative": "ନା", - "cancel": "ବାତିଲ୍ କରନ୍ତୁ |", - "open": "ଖୋଲ |", - "download": "ଡାଉନଲୋଡ୍ କରନ୍ତୁ |", - "send": "ପଠାନ୍ତୁ", - "restore_original": "ମୂଳ ପୁନରୁଦ୍ଧାର କରନ୍ତୁ |", - "convert_external_media": "ବାହ୍ୟ ମିଡିଆକୁ ରୂପାନ୍ତର କରନ୍ତୁ |", - "save": "ସଞ୍ଚୟ କରନ୍ତୁ |" - }, - "tracker_events": { - "conversation_enter": "ବାର୍ତ୍ତାଳାପ ଏଣ୍ଟର୍", - "conversation_exit": "ବାର୍ତ୍ତାଳାପ ପ୍ରସ୍ଥାନ", - "started_typing": "ଟାଇପ୍ କରିବା ଆରମ୍ଭ କଲା |", - "stopped_typing": "ଟାଇପ୍ କରିବା ବନ୍ଦ କରିଦେଲା |", - "started_speaking": "କହିବା ଆରମ୍ଭ କଲା |", - "stopped_speaking": "କହିବା ବନ୍ଦ କରିଦେଲା |", - "started_peeking": "ଖାଇବା ଆରମ୍ଭ କଲା |", - "stopped_peeking": "କଦଳୀ ବନ୍ଦ କରିଦେଲା |", - "message_read": "ବାର୍ତ୍ତା ପ read ଼ନ୍ତୁ |", - "message_deleted": "ବାର୍ତ୍ତା ବିଲୋପ ହୋଇଛି |", - "message_saved": "ବାର୍ତ୍ତା ସଞ୍ଚୟ ହୋଇଛି |", - "message_unsaved": "ବାର୍ତ୍ତା ସଂଶୋଧିତ |", - "message_edited": "ବାର୍ତ୍ତା ସମ୍ପାଦିତ |", - "message_reaction_add": "ବାର୍ତ୍ତା ପ୍ରତିକ୍ରିୟା ଆଡ୍ |", - "message_reaction_remove": "ବାର୍ତ୍ତା ପ୍ରତିକ୍ରିୟା ଅପସାରଣ କରନ୍ତୁ |", - "snap_opened": "ସ୍ନାପ୍ ଖୋଲିଲା |", - "snap_replayed": "ସ୍ନାପ୍ ରିପ୍ଲେଡ୍ ହୋଇଛି |", - "snap_replayed_twice": "ସ୍ନାପ୍ ଦୁଇଥର ବଦଳାଇଲା |", - "snap_screenshot": "ସ୍ନାପ୍ ସ୍କ୍ରିନସଟ୍ |", - "snap_screen_record": "ସ୍ନାପ୍ ସ୍କ୍ରିନ୍ ରେକର୍ଡ |" - }, - "tracker_actions": { - "log": "ଲଗ୍", - "in_app_notification": "ଇନ୍-ଆପ୍ ବିଜ୍ଞପ୍ତି |", - "push_notification": "ପୁସ୍ ବିଜ୍ଞପ୍ତି |", - "custom": "କଷ୍ଟମ୍" - }, - "better_notifications": { - "button": { - "reply": "ଉତ୍ତର ଦିଅ", - "download": "ଡାଉନଲୋଡ୍ କରନ୍ତୁ |", - "mark_as_read": "ପ read ାଯାଇଥିବା ପରି ଚିହ୍ନ |" - } - }, - "profile_picture_downloader": { - "button": "ପ୍ରୋଫାଇଲ୍ ଛବି ଡାଉନଲୋଡ୍ କରନ୍ତୁ |", - "title": "ପ୍ରୋଫାଇଲ୍ ଚିତ୍ର ଡାଉନଲୋଡର୍ |", - "avatar_option": "ଅବତାର", - "background_option": "ପୃଷ୍ଠଭୂମି" - }, - "call_start_confirmation": { - "dialog_title": "କଲ୍ ଆରମ୍ଭ କରନ୍ତୁ |", - "dialog_message": "ଆପଣ ନିଶ୍ଚିତ କି ଆପଣ ଏକ କଲ୍ ଆରମ୍ଭ କରିବାକୁ ଚାହୁଁଛନ୍ତି କି?" - }, - "half_swipe_notifier": { - "notification_channel_name": "ଅଧା ସ୍ୱାଇପ୍", - "notification_content_dm": "{user} କେବଳ ତୁମ ଚାଟରେ ଅଧା-ସ୍ୱାଇପ୍ କରିଛନ୍ତି", - "notification_content_group": "{user} {conversation} ରେ {duration} ସେକେଣ୍ଡ ପାଇଁ ଅଧା-ସ୍ୱାଇପ୍ କରିଛନ୍ତି" - }, - "download_processor": { - "attachment_type": { - "snap": "ସ୍ନାପ୍", - "sticker": "ଷ୍ଟିକର୍", - "gif": "Gif", - "external_media": "ବାହ୍ୟ ମିଡିଆ", - "note": "ନୋଟ୍", - "original_story": "ମୂଳ ଷ୍ଟୋରି" - }, - "select_attachments_title": "ଆଟାଚମେଣ୍ଟ ଚୟନ କରନ୍ତୁ", - "download_started_toast": "ଡାଉନଲୋଡ୍ ଆରମ୍ଭ ହେଲା", - "unsupported_content_type_toast": "ଅସମର୍ଥିତ ବିଷୟବସ୍ତୁ ପ୍ରକାର!", - "failed_no_longer_available_toast": "ମିଡିଆ ଆଉ ଉପଲବ୍ଧ ନାହିଁ", - "no_attachments_toast": "କୌଣସି ଆଟାଚମେଣ୍ଟ ମିଳିଲା ନାହିଁ!", - "already_queued_toast": "ମିଡିଆ ପୂର୍ବରୁ ଧାଡିରେ ଅଛି!", - "already_downloaded_toast": "ମିଡିଆ ପୂର୍ବରୁ ଡାଉନଲୋଡ୍ ହୋଇଛି!", - "content_saved_toast": "ବିଷୟବସ୍ତୁ ସେଭ୍ ହୋଇଛି!", - "download_toast": "{name} ଡାଉନଲୋଡ୍ କରାଯାଉଛି", - "processing_toast": "{name} ପ୍ରକ୍ରିୟାକରଣ କରାଯାଉଛି...", - "failed_generic_toast": "ଡାଉନଲୋଡ୍ କରିବାରେ ବିଫଳ", - "failed_to_create_preview_toast": "ପୂର୍ବାବଲୋକନ ସୃଷ୍ଟି କରିବାରେ ବିଫଳ", - "failed_processing_toast": "{name} ପ୍ରକ୍ରିୟାକରଣରେ ବିଫଳ", - "failed_gallery_toast": "{name} କୁ ଗ୍ୟାଲେରୀରେ ସେଭ୍ କରିବାରେ ବିଫଳ", - "dash_no_chapter": "କୌଣସି ଅଧ୍ୟାୟ ମିଳିଲା ନାହିଁ", - "dash_dialog": { - "title": "ଡ୍ୟାସ୍ ମିଡିଆ ଡାଉନଲୋଡ୍ କରନ୍ତୁ", - "download_all": "ସମସ୍ତ ଡାଉନଲୋଡ୍ କରନ୍ତୁ", - "segment_text": "ବିଭାଗ {start} - {end}" - } - }, - "streaks_reminder": { - "notification_title": "ଷ୍ଟ୍ରିକ୍", - "notification_text": "ଆପଣ {time} ରେ ଆପଣଙ୍କର ଷ୍ଟ୍ରିକ୍ ହରାଇବେ" - }, - "biometric_auth": { - "unlock_button": "ଅନଲକ୍", - "title": "Snapchat ଅନଲକ୍ କରନ୍ତୁ", - "subtitle": "Snapchat ଅନଲକ୍ କରିବାକୁ ଦୟାକରି ପ୍ରାମାଣିକରଣ କରନ୍ତୁ" - }, - "end_to_end_encryption": { - "toolbox": { - "no_shared_key": "ତୁମର ଏପର୍ଯ୍ୟନ୍ତ ଏହି ବନ୍ଧୁଙ୍କ ସହିତ ଏକ ଅଂଶୀଦାର ରହସ୍ୟ ନାହିଁ। ଏକ ନୂଆ ଆରମ୍ଭ କରିବାକୁ ନିମ୍ନରେ କ୍ଲିକ୍ କରନ୍ତୁ।", - "shared_key_fingerprint": "ତୁମର ଫିଙ୍ଗର ପ୍ରିଣ୍ଟ ହେଉଛି:\n\n{fingerprint}\n\nଏହା ଆପଣଙ୍କ ବନ୍ଧୁଙ୍କ ଫିଙ୍ଗର ପ୍ରିଣ୍ଟ ସହିତ ମେଳ ଖାଉଛି କି ନାହିଁ ଯାଞ୍ଚ କରିବାକୁ!", - "initiate_exchange_button": "କି' ବିନିମୟ ଆରମ୍ଭ କରନ୍ତୁ" - }, - "confirmation_dialogs": { - "title": "ଏଣ୍ଡ-ଟୁ-ଏଣ୍ଡ ଏନକ୍ରିପ୍ସନ୍", - "confirmation_1": "ଚେତାବନୀ: ଏହା ଆପଣଙ୍କର ବିଦ୍ୟମାନ କି'କୁ ଓଭରରାଇଟ୍ କରିବ। ଏହି ବନ୍ଧୁଙ୍କଠାରୁ ସମସ୍ତ ଏନକ୍ରିପ୍ଟ ହୋଇଥିବା ମେସେଜଗୁଡ଼ିକୁ ଆପଣ ଆଉ ଆକ୍ସେସ୍ କରିପାରିବେ ନାହିଁ। ଆପଣ ଜାରି ରଖିବାକୁ ଚାହୁଁଛନ୍ତି କି?", - "confirmation_2": "ଆପଣ ପ୍ରକୃତରେ ନିଶ୍ଚିତ କି ଆପଣ ଜାରି ରଖିବାକୁ ଚାହୁଁଛନ୍ତି? ପଛକୁ ଫେରିବା ପାଇଁ ଏହା ଆପଣଙ୍କର ଶେଷ ସୁଯୋଗ।" - }, - "unencrypted_conversation_send_failure_toast": "ଆପଣ ଉଭୟ ଏନକ୍ରିପ୍ଟ ହୋଇଥିବା ଏବଂ ଅଣ-ଏନକ୍ରିପ୍ଟ ହୋଇଥିବା ବାର୍ତ୍ତାଳାପରେ ଏନକ୍ରିପ୍ଟ ହୋଇଥିବା ବିଷୟବସ୍ତୁ ପଠାଇ ପାରିବେ ନାହିଁ!", - "native_hooks_send_failure_toast": "ପଠାଇବାରେ ବିଫଳ! ଦୟାକରି ସେଟିଂସରେ ନେଟିଭ୍ ହୁକ୍ ସକ୍ଷମ କରନ୍ତୁ।", - "no_participants_to_encrypt_toast": "ମେସେଜ୍ ଏନକ୍ରିପ୍ଟ କରିବା ପାଇଁ ଆପଣଙ୍କର ଏହି ବାର୍ତ୍ତାଳାପରେ କୌଣସି ବନ୍ଧୁ ନାହାଁନ୍ତି!", - "encryption_failed_toast": "ମେସେଜ୍ ଏନକ୍ରିପ୍ଟ କରିବାରେ ବିଫଳ! ଅଧିକ ବିବରଣୀ ପାଇଁ LogCat ଯାଞ୍ଚ କରନ୍ତୁ।", - "accept_public_key_success_toast": "ସାର୍ବଜନୀନ କି' ସଫଳତାର ସହିତ ଗ୍ରହଣ କରାଯାଇଛି!", - "accept_secret_key_success_toast": "ସମାପ୍ତ! ଆପଣ ବର୍ତ୍ତମାନ ଏହି ବନ୍ଧୁଙ୍କ ସହିତ ଏନକ୍ରିପ୍ଟ ହୋଇଥିବା ମେସେଜ୍ ପଠାଇ ପାରିବେ।", - "accept_public_key_failure_toast": "ସାର୍ବଜନୀନ କି' ଗ୍ରହଣ କରିବାରେ ବିଫଳ।", - "accept_secret_key_failure_toast": "ଗୁପ୍ତ କି' ଗ୍ରହଣ କରିବାରେ ବିଫଳ।", - "accept_secret_button": "ଗୁପ୍ତ ଗ୍ରହଣ କରନ୍ତୁ", - "accept_public_key_button": "ସାର୍ବଜନୀନ କି' ଗ୍ରହଣ କରନ୍ତୁ", - "outgoing_pk_message": "କି' ବିନିମୟ ଅନୁରୋଧ", - "outgoing_secret_message": "କି' ବିନିମୟ ପ୍ରତିକ୍ରିୟା", - "incoming_pk_message": "ଆପଣ ଏକ ସାର୍ବଜନୀନ କି' ଅନୁରୋଧ ଗ୍ରହଣ କରିଛନ୍ତି। ଏହାକୁ ଗ୍ରହଣ କରିବାକୁ ନିମ୍ନରେ କ୍ଲିକ୍ କରନ୍ତୁ।", - "incoming_secret_message": "ଆପଣଙ୍କ ବନ୍ଧୁ ଆପଣଙ୍କ ସାର୍ବଜନୀନ କି' ଗ୍ରହଣ କରିଛନ୍ତି। ଗୁପ୍ତ ଗ୍ରହଣ କରିବାକୁ ନିମ୍ନରେ କ୍ଲିକ୍ କରନ୍ତୁ।" - }, - "auto_open_snaps": { - "title": "ଅଟୋ ଓପନ୍ ସ୍ନାପ୍", - "notification_content": "{count} ସ୍ନାପ୍ ଖୋଲିଲା" - }, - "friend_mutation_observer": { - "notification_channel_name": "ବନ୍ଧୁ ମ୍ୟୁଟେସନ୍ ପର୍ଯ୍ୟବେକ୍ଷକ", - "friend_removed": "{name} ତୁମକୁ ଜଣେ ବନ୍ଧୁ ଭାବରେ ଅପସାରଣ କରିଛି", - "birthday_removed": "{name} ସେମାନଙ୍କର ଜନ୍ମଦିନ ହଟାଇଛନ୍ତି ({birthday})", - "birthday_added": "{name} ସେମାନଙ୍କର ଜନ୍ମଦିନ ଯୋଡିଛି ({birthday})", - "birthday_changed": "{name} ସେମାନଙ୍କର ଜନ୍ମଦିନକୁ {old_birthday} ରୁ {new_birthday} କୁ ପରିବର୍ତ୍ତନ କରିଛି", - "bitmoji_selfie_changed": "{name} ସେମାନଙ୍କର ବିଟମୋଜି ସେଲ୍ଫି ବଦଳାଇଛି", - "bitmoji_avatar_changed": "{name} ସେମାନଙ୍କର ବିଟମୋଜି ଅବତାର ପରିବର୍ତ୍ତନ କରିଛି", - "bitmoji_background_changed": "{name} ସେମାନଙ୍କର ବିଟମୋଜୀ ପୃଷ୍ଠଭୂମି ପରିବର୍ତ୍ତନ କରିଛି", - "bitmoji_scene_changed": "{name} ସେମାନଙ୍କର ବିଟମୋଜି ଦୃଶ୍ୟ ବଦଳାଇଛି" - }, - "material3_strings": { - "date_range_picker_start_headline": "ଆରମ୍ଭ ତାରିଖ", - "date_range_picker_end_headline": "ଶେଷ ତାରିଖ", - "date_range_picker_title": "ତାରିଖ ପରିସର ଚୟନ କରନ୍ତୁ", - "date_picker_switch_to_calendar_mode": "କ୍ୟାଲେଣ୍ଡର ମୋଡକୁ ସୁଇଚ୍ କରନ୍ତୁ", - "date_picker_switch_to_input_mode": "ଇନପୁଟ୍ ମୋଡକୁ ସୁଇଚ୍ କରନ୍ତୁ", - "date_range_picker_scroll_to_previous_month": "ପୂର୍ବ ମାସକୁ ସ୍କ୍ରୋଲ୍ କରନ୍ତୁ", - "date_range_picker_scroll_to_next_month": "ପରବର୍ତ୍ତୀ ମାସକୁ ସ୍କ୍ରୋଲ୍ କରନ୍ତୁ", - "date_picker_today_description": "ଆଜି", - "date_range_picker_day_in_range": "ପରିସରରେ ଥିବା ଦିନ", - "date_input_invalid_for_pattern": "ପ୍ୟାଟର୍ନ ପାଇଁ ଅବୈଧ ତାରିଖ", - "date_input_invalid_year_range": "ଅବୈଧ ବର୍ଷ ପରିସର", - "date_input_invalid_not_allowed": "ଅନୁମତି ନଥିବା ଅବୈଧ ତାରିଖ", - "date_range_input_invalid_range_input": "ଅବୈଧ ତାରିଖ ପରିସର ଇନପୁଟ୍" - }, - "send_override_dialog": { - "title": "{type} ଭାବରେ ମିଡିଆ ପଠାନ୍ତୁ", - "duration": "ଅବଧି: {duration}", - "saveable_snap_hint": "ଚାଟରେ ସ୍ନାପ୍ ସେଭ୍ କରନ୍ତୁ", - "unlimited_duration": "ଅସୀମିତ" - }, - "invalid_input_toast": "ଅବୈଧ ଇନପୁଟ୍! ନିଶ୍ଚିତ କରନ୍ତୁ ଯେ ଆପଣ ଏକ ବୈଧ ମୂଲ୍ୟ ପ୍ରବେଶ କରିଛନ୍ତି।" -} \ No newline at end of file diff --git a/common/src/main/assets/lang/pa.json b/common/src/main/assets/lang/pa.json deleted file mode 100644 index 6477dcc6..00000000 --- a/common/src/main/assets/lang/pa.json +++ /dev/null @@ -1,2016 +0,0 @@ -{ - "setup": { - "dialogs": { - "select_language": "ਭਾਸ਼ਾ ਚੁਣੋ", - "save_folder": "PurrfectSnap ਨੂੰ Snapchat ਤੋਂ ਮੀਡੀਆ ਡਾਊਨਲੋਡ ਕਰਨ ਅਤੇ ਸੇਵ ਕਰਨ ਲਈ ਸਟੋਰੇਜ ਅਨੁਮਤੀ ਦੀ ਲੋੜ ਹੈ।\nਕਿਰਪਾ ਕਰਕੇ ਉਹ ਥਾਂ ਚੁਣੋ ਜਿੱਥੇ ਮੀਡੀਆ ਨੂੰ ਡਾਊਨਲੋਡ ਕੀਤਾ ਜਾਣਾ ਚਾਹੀਦਾ ਹੈ।", - "select_save_folder_button": "ਫੋਲਡਰ ਚੁਣੋ" - }, - "mappings": { - "dialog": "ਮੈਪਿੰਗ ਤਿਆਰ ਕੀਤੀ ਜਾ ਰਹੀ ਹੈ, ਇਸ ਵਿੱਚ ਕੁਝ ਸਮਾਂ ਲੱਗ ਸਕਦਾ ਹੈ...", - "generate_failure_no_snapchat": "PurrfectSnap Snapchat ਦਾ ਪਤਾ ਲਗਾਉਣ ਵਿੱਚ ਅਸਮਰੱਥ ਸੀ, ਕਿਰਪਾ ਕਰਕੇ Snapchat ਨੂੰ ਮੁੜ-ਇੰਸਟਾਲ ਕਰਨ ਦੀ ਕੋਸ਼ਿਸ਼ ਕਰੋ।", - "generate_failure": "ਮੈਪਿੰਗ ਤਿਆਰ ਕਰਨ ਦੀ ਕੋਸ਼ਿਸ਼ ਕਰਦੇ ਹੋਏ ਇੱਕ ਗਲਤੀ ਆਈ, ਕਿਰਪਾ ਕਰਕੇ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।" - }, - "permissions": { - "dialog": "ਜਾਰੀ ਰੱਖਣ ਲਈ, ਤੁਹਾਨੂੰ ਹੇਠ ਲਿਖੀਆਂ ਲੋੜਾਂ ਪੂਰੀਆਂ ਕਰਨੀਆਂ ਪੈਣਗੀਆਂ:", - "notification_access": "ਸੂਚਨਾ ਪਹੁੰਚ", - "battery_optimization": "ਬੈਟਰੀ ਅਨੁਕੂਲਨ", - "display_over_other_apps": "ਹੋਰ ਐਪਾਂ 'ਤੇ ਡਿਸਪਲੇ ਕਰੋ", - "request_button": "ਬੇਨਤੀ" - } - }, - "scopes": { - "friend": "ਦੋਸਤ", - "group": "ਸਮੂਹ" - }, - "manager": { - "routes": { - "tasks": "ਕਾਰਜ", - "features": "ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ", - "manage_rule_feature": "ਨਿਯਮ ਵਿਸ਼ੇਸ਼ਤਾ ਦਾ ਪ੍ਰਬੰਧਨ ਕਰੋ", - "home": "ਘਰ", - "home_settings": "ਸੈਟਿੰਗਾਂ", - "home_logs": "ਲੌਗਸ", - "logger_history": "ਲੌਗਰ ਇਤਿਹਾਸ", - "logged_stories": "ਲੌਗ ਕੀਤੀਆਂ ਕਹਾਣੀਆਂ", - "friend_tracker": "ਦੋਸਤ ਟਰੈਕਰ", - "edit_rule": "ਨਿਯਮ ਸੰਪਾਦਿਤ ਕਰੋ", - "file_imports": "ਫਾਈਲ ਆਯਾਤ", - "manage_repos": "ਰਿਪੋਜ਼ਟਰੀਆਂ ਦਾ ਪ੍ਰਬੰਧਨ ਕਰੋ", - "social": "ਸਮਾਜਿਕ", - "manage_scope": "ਸਕੋਪ ਦਾ ਪ੍ਰਬੰਧਨ ਕਰੋ", - "messaging_preview": "ਪੂਰਵਦਰਸ਼ਨ", - "scripts": "ਸਕ੍ਰਿਪਟਾਂ", - "better_location": "ਬਿਹਤਰ ਸਥਾਨ" - }, - "sections": { - "home": { - "version_title": "v{versionName} · Eternal ਦੁਆਰਾ ਫੋਰਕ ਕੀਤਾ ਗਿਆ", - "update_title": "PurrfectSnap ਅੱਪਡੇਟ", - "update_content": "ਸੰਸਕਰਣ {version} ਉਪਲਬਧ ਹੈ!", - "update_button": "ਡਾਊਨਲੋਡ ਕਰੋ", - "debug_build_summary_title": "ਤੁਸੀਂ PurrfectSnap ਦਾ ਇੱਕ ਡੀਬੱਗ ਬਿਲਡ ਚਲਾ ਰਹੇ ਹੋ", - "debug_build_summary_content": "ਸੰਸਕਰਣ {versionName} ({versionCode})", - "debug_build_summary_date": "ਬਿਲਡ ਮਿਤੀ: {date} ({days} ਦਿਨ ਪਹਿਲਾਂ)", - "quick_actions_title": "ਤੁਰੰਤ ਕਾਰਵਾਈਆਂ", - "download_icon_description": "ਡਾਊਨਲੋਡ ਕਰੋ", - "completed_icon_description": "ਪੂਰਾ ਹੋਇਆ", - "failed_icon_description": "ਅਸਫਲ", - "manage_quick_actions_description": "ਤੁਰੰਤ ਕਾਰਵਾਈਆਂ ਦਾ ਪ੍ਰਬੰਧਨ ਕਰੋ", - "quick_actions_icon_description": "ਤੁਰੰਤ ਕਾਰਵਾਈਆਂ", - "add_quick_action_description": "ਤੁਰੰਤ ਕਾਰਵਾਈ ਸ਼ਾਮਲ ਕਰੋ" - }, - "home_logs": { - "no_logs_hint": "ਕੋਈ ਲੌਗ ਉਪਲਬਧ ਨਹੀਂ ਹਨ", - "clear_logs_button": "ਲੌਗ ਸਾਫ਼ ਕਰੋ", - "export_logs_button": "ਲੌਗ ਨਿਰਯਾਤ ਕਰੋ", - "saving_logs_toast": "ਲੌਗ ਸੇਵ ਕੀਤੇ ਜਾ ਰਹੇ ਹਨ, ਇਸ ਵਿੱਚ ਕੁਝ ਸਮਾਂ ਲੱਗ ਸਕਦਾ ਹੈ...", - "saved_logs_success_toast": "ਲੌਗ ਸਫਲਤਾਪੂਰਵਕ ਸੇਵ ਕੀਤੇ ਗਏ", - "saved_logs_failure_toast": "ਲੌਗ ਸੇਵ ਕਰਨ ਵਿੱਚ ਅਸਫਲ" - }, - "home_settings": { - "actions_title": "ਕਾਰਵਾਈਆਂ", - "message_logger_title": "ਸੁਨੇਹਾ ਲੌਗਰ", - "debug_title": "ਡੀਬੱਗ", - "success_toast": "ਹੋ ਗਿਆ!", - "message_logger_summary": "{messageCount} ਸੁਨੇਹੇ\n{storyCount} ਕਹਾਣੀਆਂ", - "export_button": "ਨਿਰਯਾਤ", - "clear_button": "ਸਾਫ਼ ਕਰੋ", - "view_logger_history_button": "ਲੌਗਰ ਇਤਿਹਾਸ ਵੇਖੋ", - "updates_title": "ਅੱਪਡੇਟ", - "auto_update_check": "ਅੱਪਡੇਟ ਲਈ ਆਟੋਮੈਟਿਕ ਜਾਂਚ", - "update_check_frequency": "ਅੱਪਡੇਟ ਜਾਂਚ ਬਾਰੰਬਾਰਤਾ", - "update_check_frequency_daily": "ਰੋਜ਼ਾਨਾ", - "update_check_frequency_weekly": "ਹਫਤਾਵਾਰੀ", - "update_check_frequency_monthly": "ਮਹੀਨਾਵਾਰ", - "theme_icon_description": "ਥੀਮ", - "app_theme_title": "ਐਪ ਥੀਮ", - "theme_mode_system": "ਸਿਸਟਮ", - "theme_mode_light": "ਹਲਕਾ", - "theme_mode_dark": "ਗੂੜ੍ਹਾ", - "ui_settings_title": "UI ਸੈਟਿੰਗਾਂ", - "haptic_feedback_label": "ਹੈਪਟਿਕ ਫੀਡਬੈਕ", - "test_mode_label": "ਟੈਸਟ ਮੋਡ (ਸਿਰਫ਼ ਡੀਬੱਗਿੰਗ ਲਈ)", - "disable_feature_loading_label": "ਵਿਸ਼ੇਸ਼ਤਾ ਲੋਡਿੰਗ ਨੂੰ ਅਯੋਗ ਕਰੋ", - "disable_auto_mapper_label": "ਆਟੋ ਮੈਪਰ ਨੂੰ ਅਯੋਗ ਕਰੋ", - "disable_bypass_indicator_label": "ਬਾਈਪਾਸ ਸਥਿਤੀ ਸੂਚਕ ਨੂੰ ਅਯੋਗ ਕਰੋ", - "update_notification_channel_name": "PurrfectSnap ਅੱਪਡੇਟ", - "update_notification_channel_description": "PurrfectSnap ਅੱਪਡੇਟ ਲਈ ਸੂਚਨਾਵਾਂ", - "update_notification_title": "PurrfectSnap ਅੱਪਡੇਟ ਉਪਲਬਧ ਹੈ", - "update_notification_text": "ਸੰਸਕਰਣ {version} ਹੁਣ ਉਪਲਬਧ ਹੈ।", - "export_database_failed_toast": "ਡਾਟਾਬੇਸ ਨਿਰਯਾਤ ਕਰਨ ਵਿੱਚ ਅਸਫਲ! {message}", - "clear_messages_failed_toast": "ਸੁਨੇਹੇ ਸਾਫ਼ ਕਰਨ ਵਿੱਚ ਅਸਫਲ! {message}", - "clear_file_failed_toast": "ਫਾਈਲ ਸਾਫ਼ ਕਰਨ ਵਿੱਚ ਅਸਫਲ! {message}", - "debug_file_config": "ਸੰਰਚਨਾ", - "debug_file_mappings": "ਮੈਪਿੰਗ", - "debug_file_message_logger": "ਸੁਨੇਹਾ ਲੌਗਰ", - "debug_file_pinned_best_friend": "ਪਿੰਨ ਕੀਤਾ ਸਭ ਤੋਂ ਵਧੀਆ ਦੋਸਤ", - "debug_file_native_sig_cache": "ਨੇਟਿਵ ਦਸਤਖਤ ਕੈਸ਼" - }, - "tasks": { - "no_tasks": "ਕੋਈ ਕਾਰਜ ਨਹੀਂ", - "merge_button": "ਮਿਲਾਓ", - "failed_to_open_file": "ਫਾਈਲ ਖੋਲ੍ਹਣ ਵਿੱਚ ਅਸਫਲ", - "merge_files_toast": "{count} ਫਾਈਲਾਂ ਨੂੰ ਮਿਲਾਇਆ ਜਾ ਰਿਹਾ ਹੈ", - "remove_selected_tasks_title": "ਕੀ ਤੁਸੀਂ ਯਕੀਨੀ ਹੋ ਕਿ ਤੁਸੀਂ ਚੁਣੇ ਹੋਏ ਕਾਰਜਾਂ ਨੂੰ ਹਟਾਉਣਾ ਚਾਹੁੰਦੇ ਹੋ?", - "remove_all_tasks_title": "ਕੀ ਤੁਸੀਂ ਯਕੀਨੀ ਹੋ ਕਿ ਤੁਸੀਂ ਸਾਰੇ ਕਾਰਜਾਂ ਨੂੰ ਹਟਾਉਣਾ ਚਾਹੁੰਦੇ ਹੋ?", - "delete_files_option": "ਫਾਈਲਾਂ ਨੂੰ ਵੀ ਮਿਟਾਓ", - "remove_selected_tasks_confirm": "{count} ਕਾਰਜ ਹਟਾਓ?", - "remove_all_tasks_confirm": "ਸਾਰੇ ਕਾਰਜ ਹਟਾਓ?", - "clear_tasks_description": "ਕਾਰਜ ਸਾਫ਼ ਕਰੋ", - "file_not_found_icon_description": "ਫਾਈਲ ਨਹੀਂ ਮਿਲੀ", - "image_icon_description": "ਚਿੱਤਰ", - "video_icon_description": "ਵੀਡੀਓ", - "audio_icon_description": "ਆਡੀਓ", - "file_icon_description": "ਫਾਈਲ", - "download_icon_description": "ਡਾਊਨਲੋਡ ਕਰੋ", - "chat_action_icon_description": "ਗੱਲਬਾਤ ਦੀ ਕਾਰਵਾਈ", - "cancel_icon_description": "ਰੱਦ ਕਰੋ", - "success_icon_description": "ਸਫਲਤਾ", - "failure_icon_description": "ਅਸਫਲਤਾ", - "cancelled_icon_description": "ਰੱਦ ਕੀਤਾ ਗਿਆ", - "task_status_failure": "ਅਸਫਲਤਾ", - "task_status_cancelled": "ਰੱਦ ਕੀਤਾ ਗਿਆ" - }, - "features": { - "disabled": "ਅਯੋਗ", - "export_option": "ਨਿਰਯਾਤ", - "import_option": "ਆਯਾਤ", - "reset_option": "ਰੀਸੈਟ", - "config_export_success_toast": "ਸੰਰਚਨਾ ਸਫਲਤਾਪੂਰਵਕ ਨਿਰਯਾਤ ਕੀਤੀ ਗਈ", - "config_import_success_toast": "ਸੰਰਚਨਾ ਸਫਲਤਾਪੂਰਵਕ ਆਯਾਤ ਕੀਤੀ ਗਈ", - "config_import_failure_toast": "ਸੰਰਚਨਾ ਆਯਾਤ ਕਰਨ ਵਿੱਚ ਅਸਫਲ: {error}", - "config_export_failure_toast": "ਸੰਰਚਨਾ ਨਿਰਯਾਤ ਕਰਨ ਵਿੱਚ ਅਸਫਲ: {error}", - "saved_config_snackbar": "ਸੰਰਚਨਾ ਸੇਵ ਕੀਤੀ ਗਈ", - "older_required": "ਇਸ ਵਿਸ਼ੇਸ਼ਤਾ ਨੂੰ ਸਹੀ ਢੰਗ ਨਾਲ ਕੰਮ ਕਰਨ ਲਈ Snapchat v{version} ਜਾਂ ਪੁਰਾਣੇ ਦੀ ਲੋੜ ਹੈ।", - "newer_required": "ਇਸ ਵਿਸ਼ੇਸ਼ਤਾ ਨੂੰ ਸਹੀ ਢੰਗ ਨਾਲ ਕੰਮ ਕਰਨ ਲਈ Snapchat v{version} ਜਾਂ ਨਵੇਂ ਦੀ ਲੋੜ ਹੈ।", - "search_button": "ਖੋਜ" - }, - "manage_rule_feature": { - "disable_state_option": "ਅਯੋਗ", - "disable_state_subtext": "ਕੋਈ ਦੋਸਤ/ਸਮੂਹ ਪ੍ਰਭਾਵਿਤ ਨਹੀਂ ਹੋਵੇਗਾ", - "whitelist_state_option": "ਕੋਈ ਨਹੀਂ ਸਿਵਾਏ...", - "whitelist_state_subtext": "ਸਿਰਫ਼ {count} ਦੋਸਤ/ਸਮੂਹ ਇਸ ਨਿਯਮ ਦੁਆਰਾ ਪ੍ਰਭਾਵਿਤ ਹੋਣਗੇ", - "whitelist_state_button": "ਇਜਾਜ਼ਤ ਵਾਲੇ ਦੋਸਤ/ਸਮੂਹ ਚੁਣੋ", - "blacklist_state_option": "ਹਰ ਕੋਈ ਸਿਵਾਏ...", - "blacklist_state_subtext": "ਹਰ ਕੋਈ {count} ਦੋਸਤਾਂ/ਸਮੂਹਾਂ ਨੂੰ ਛੱਡ ਕੇ ਇਸ ਨਿਯਮ ਦੁਆਰਾ ਪ੍ਰਭਾਵਿਤ ਹੋਵੇਗਾ", - "blacklist_state_button": "ਬਾਹਰ ਕੀਤੇ ਦੋਸਤ/ਸਮੂਹ ਚੁਣੋ", - "clear_list_button": "ਦੋਸਤ/ਸਮੂਹ ਸੂਚੀ ਸਾਫ਼ ਕਰੋ", - "dialog_clear_confirmation_text": "ਕੀ ਤੁਸੀਂ ਯਕੀਨੀ ਹੋ ਕਿ ਤੁਸੀਂ ਇਸ ਸੂਚੀ ਨੂੰ ਸਾਫ਼ ਕਰਨਾ ਚਾਹੁੰਦੇ ਹੋ?" - }, - "social": { - "friends_tab": "ਦੋਸਤ", - "groups_tab": "ਸਮੂਹ", - "empty_hint": "(ਖਾਲੀ)", - "streaks_expiration_short": "{hours} ਘੰਟੇ" - }, - "manage_scope": { - "logged_stories_button": "ਲੌਗ ਕੀਤੀਆਂ ਕਹਾਣੀਆਂ ਦਿਖਾਓ", - "e2ee_title": "ਐਂਡ-ਟੂ-ਐਂਡ ਇਨਕ੍ਰਿਪਸ਼ਨ", - "rules_title": "ਨਿਯਮ", - "participants_text": "{count} ਭਾਗੀਦਾਰ", - "not_found": "ਨਹੀਂ ਮਿਲਿਆ", - "streaks_title": "ਸਟ੍ਰੀਕਸ", - "streaks_length_text": "ਲੰਬਾਈ: {length}", - "streaks_expiration_text": "{eta} 'ਤੇ ਮਿਆਦ ਪੁੱਗ ਰਹੀ ਹੈ", - "streaks_expiration_text_expired": "ਮਿਆਦ ਪੁੱਗ ਗਈ", - "reminder_button": "ਰੀਮਾਈਂਡਰ ਸੈੱਟ ਕਰੋ", - "delete_scope_confirm_dialog_title": "ਕੀ ਤੁਸੀਂ ਯਕੀਨੀ ਹੋ ਕਿ ਤੁਸੀਂ {scope} ਨੂੰ ਮਿਟਾਉਣਾ ਚਾਹੁੰਦੇ ਹੋ?", - "notes_placeholder": "ਇੱਕ ਨੋਟ ਜੋੜਨ ਲਈ ਕਲਿੱਕ ਕਰੋ", - "invalid_key_size_32_bytes": "ਅਵੈਧ ਕੁੰਜੀ ਆਕਾਰ (32 ਬਾਈਟ ਹੋਣਾ ਚਾਹੀਦਾ ਹੈ)", - "successfully_imported_key": "ਕੁੰਜੀ ਸਫਲਤਾਪੂਰਵਕ ਆਯਾਤ ਕੀਤੀ ਗਈ", - "failed_to_import_key": "ਕੁੰਜੀ ਆਯਾਤ ਕਰਨ ਵਿੱਚ ਅਸਫਲ: {message}", - "export_base64_button": "Base64 ਨਿਰਯਾਤ ਕਰੋ", - "import_base64_button": "Base64 ਆਯਾਤ ਕਰੋ" - }, - "logged_stories": { - "story_failed_to_load": "ਲੋਡ ਕਰਨ ਵਿੱਚ ਅਸਫਲ", - "no_stories": "ਕੋਈ ਕਹਾਣੀਆਂ ਨਹੀਂ ਮਿਲੀਆਂ", - "save_from_cache_button": "ਕੈਸ਼ ਤੋਂ ਸੇਵ ਕਰੋ", - "downloaded_to_path": "{path} 'ਤੇ ਡਾਊਨਲੋਡ ਕੀਤਾ ਗਿਆ", - "download_failed": "ਡਾਊਨਲੋਡ ਅਸਫਲ: {message}", - "posted_at": "{date} 'ਤੇ ਪੋਸਟ ਕੀਤਾ ਗਿਆ", - "created_at": "{date} 'ਤੇ ਬਣਾਇਆ ਗਿਆ", - "failed_to_open_file": "ਫਾਈਲ ਖੋਲ੍ਹਣ ਵਿੱਚ ਅਸਫਲ। ਹੋਰ ਜਾਣਕਾਰੀ ਲਈ ਲੌਗਸ ਦੀ ਜਾਂਚ ਕਰੋ", - "failed_to_get_file": "ਫਾਈਲ ਪ੍ਰਾਪਤ ਕਰਨ ਵਿੱਚ ਅਸਫਲ" - }, - "messaging_preview": { - "processed_messages_toast": "{count} ਸੁਨੇਹੇ ਪ੍ਰੋਸੈਸ ਕੀਤੇ ਗਏ", - "processed_messages_text": "{count} ਸੁਨੇਹੇ ਪ੍ਰੋਸੈਸ ਕੀਤੇ ਗਏ", - "close_button_description": "ਬੰਦ ਕਰੋ", - "bridge_connection_failed": "ਬ੍ਰਿਜ ਨਾਲ ਕਨੈਕਟ ਕਰਨ ਵਿੱਚ ਅਸਫਲ। ਯਕੀਨੀ ਬਣਾਓ ਕਿ Snapchat ਬੈਕਗ੍ਰਾਉਂਡ ਵਿੱਚ ਚੱਲ ਰਿਹਾ ਹੈ", - "bridge_init_failed": "ਮੈਸੇਜਿੰਗ ਬ੍ਰਿਜ ਨੂੰ ਸ਼ੁਰੂ ਕਰਨ ਵਿੱਚ ਅਸਫਲ। ਯਕੀਨੀ ਬਣਾਓ ਕਿ Snapchat ਬੈਕਗ੍ਰਾਉਂਡ ਵਿੱਚ ਚੱਲ ਰਿਹਾ ਹੈ", - "message_fetch_failed": "ਸੁਨੇਹੇ ਪ੍ਰਾਪਤ ਕਰਨ ਵਿੱਚ ਅਸਫਲ", - "no_message_hint": "ਕੋਈ ਸੁਨੇਹਾ ਨਹੀਂ", - "save_selection_option": "ਚੋਣ ਸੇਵ ਕਰੋ", - "save_all_option": "ਸਭ ਸੇਵ ਕਰੋ", - "unsave_selection_option": "ਚੋਣ ਨੂੰ ਅਣ-ਸੇਵ ਕਰੋ", - "unsave_all_option": "ਸਭ ਨੂੰ ਅਣ-ਸੇਵ ਕਰੋ", - "mark_selection_as_seen_option": "ਚੁਣੇ ਹੋਏ ਸਨੈਪ ਨੂੰ ਦੇਖੇ ਗਏ ਵਜੋਂ ਮਾਰਕ ਕਰੋ", - "mark_all_as_seen_option": "ਸਾਰੇ ਸਨੈਪਸ ਨੂੰ ਦੇਖੇ ਗਏ ਵਜੋਂ ਮਾਰਕ ਕਰੋ", - "delete_selection_option": "ਚੋਣ ਮਿਟਾਓ", - "delete_all_option": "ਸਭ ਮਿਟਾਓ" - }, - "logger_history": { - "download_started_toast": "ਡਾਊਨਲੋਡ ਸ਼ੁਰੂ ਹੋਇਆ!", - "download_success_toast": "{path} 'ਤੇ ਡਾਊਨਲੋਡ ਕੀਤਾ ਗਿਆ", - "download_failed_toast": "{message} ਨੂੰ ਡਾਊਨਲੋਡ ਕਰਨ ਵਿੱਚ ਅਸਫਲ", - "edited_at_text": "{message} ({date} 'ਤੇ ਸੰਪਾਦਿਤ)", - "download_button": "ਡਾਊਨਲੋਡ ਕਰੋ", - "select_conversation_placeholder": "ਇੱਕ ਗੱਲਬਾਤ ਚੁਣੋ", - "close_button_description": "ਬੰਦ ਕਰੋ", - "search_button_description": "ਖੋਜ", - "list_friend_format": "ਦੋਸਤ {name}", - "list_group_format": "ਸਮੂਹ {name}", - "no_more_messages": "ਕੋਈ ਹੋਰ ਸੁਨੇਹੇ ਨਹੀਂ", - "reverse_order_checkbox": "ਉਲਟਾ ਕ੍ਰਮ", - "chat_attachment": "ਅਟੈਚਮੈਂਟ {index}", - "empty_message": "ਖਾਲੀ ਗੱਲਬਾਤ ਸੁਨੇਹਾ", - "message_parse_failed": "ਸੁਨੇਹਾ ਪਾਰਸ ਕਰਨ ਵਿੱਚ ਅਸਫਲ", - "unknown_sender": "ਅਣਜਾਣ ਭੇਜਣ ਵਾਲਾ", - "download_attachment_failed_toast": "ਅਟੈਚਮੈਂਟ ਡਾਊਨਲੋਡ ਕਰਨ ਵਿੱਚ ਅਸਫਲ", - "log_header_format": "{username} ({type}) - {date}" - }, - "file_imports": { - "import_file_button": "ਫਾਈਲ ਆਯਾਤ ਕਰੋ", - "file_not_found": "ਫਾਈਲ ਨਹੀਂ ਮਿਲੀ", - "file_import_failed": "ਫਾਈਲ ਆਯਾਤ ਕਰਨ ਵਿੱਚ ਅਸਫਲ: {error}", - "file_imported": "ਫਾਈਲ ਸਫਲਤਾਪੂਰਵਕ ਆਯਾਤ ਕੀਤੀ ਗਈ", - "file_delete_failed": "ਫਾਈਲ ਮਿਟਾਉਣ ਵਿੱਚ ਅਸਫਲ", - "no_files_hint": "ਇੱਥੇ ਤੁਸੀਂ Snapchat ਵਿੱਚ ਵਰਤੋਂ ਲਈ ਫਾਈਲਾਂ ਆਯਾਤ ਕਰ ਸਕਦੇ ਹੋ। ਇੱਕ ਫਾਈਲ ਆਯਾਤ ਕਰਨ ਲਈ ਹੇਠਾਂ ਦਿੱਤੇ ਬਟਨ ਨੂੰ ਦਬਾਓ।" - }, - "better_location": { - "spoofed_coordinates_title": "Lat {latitude}, Lng {longitude}", - "save_coordinates_dialog_title": "ਕੋਆਰਡੀਨੇਟ ਸੇਵ ਕਰੋ", - "saved_name_dialog_hint": "ਸੇਵ ਕੀਤਾ ਨਾਮ", - "latitude_dialog_hint": "ਅਕਸ਼ਾਂਸ਼", - "longitude_dialog_hint": "ਲੰਬਕਾਰ", - "save_dialog_button": "ਸੇਵ", - "choose_location_button": "ਸਥਾਨ ਚੁਣੋ", - "teleport_to_friend_button": "ਦੋਸਤ ਨੂੰ ਟੈਲੀਪੋਰਟ ਕਰੋ", - "spoof_location_toggle": "ਸਥਾਨ ਸਪੂਫ ਕਰੋ", - "suspend_location_updates": "ਸਥਾਨ ਅੱਪਡੇਟ ਨੂੰ ਮੁਅੱਤਲ ਕਰੋ", - "saved_coordinates_title": "ਸੇਵ ਕੀਤੇ ਕੋਆਰਡੀਨੇਟ", - "no_saved_coordinates_hint": "ਕੋਈ ਸੇਵ ਕੀਤੇ ਕੋਆਰਡੀਨੇਟ ਨਹੀਂ", - "delete_dialog_title": "ਸੇਵ ਕੀਤੇ ਕੋਆਰਡੀਨੇਟ ਮਿਟਾਓ", - "delete_dialog_message": "ਕੀ ਤੁਸੀਂ ਯਕੀਨੀ ਹੋ ਕਿ ਤੁਸੀਂ ਇਸ ਸੇਵ ਕੀਤੇ ਕੋਆਰਡੀਨੇਟ ਨੂੰ ਮਿਟਾਉਣਾ ਚਾਹੁੰਦੇ ਹੋ?", - "teleport_to_friend_title": "ਦੋਸਤ ਨੂੰ ਟੈਲੀਪੋਰਟ ਕਰੋ", - "search_bar": "ਖੋਜ", - "no_friends_map": "ਨਕਸ਼ੇ 'ਤੇ ਕੋਈ ਦੋਸਤ ਨਹੀਂ", - "no_friends_found": "ਕੋਈ ਦੋਸਤ ਨਹੀਂ ਮਿਲਿਆ", - "edit_location_button_description": "ਸਥਾਨ ਸੰਪਾਦਿਤ ਕਰੋ", - "add_icon_description": "ਸ਼ਾਮਲ ਕਰੋ", - "edit_icon_description": "ਸੰਪਾਦਿਤ ਕਰੋ", - "delete_icon_description": "ਮਿਟਾਓ" - } - }, - "dialogs": { - "add_friend": { - "title": "ਦੋਸਤ ਜਾਂ ਸਮੂਹ ਸ਼ਾਮਲ ਕਰੋ", - "search_hint": "ਖੋਜ", - "fetch_error": "ਡਾਟਾ ਪ੍ਰਾਪਤ ਕਰਨ ਵਿੱਚ ਅਸਫਲ", - "category_groups": "ਸਮੂਹ", - "category_friends": "ਦੋਸਤ", - "participants_text": "{count} ਭਾਗੀਦਾਰ", - "search_icon_description": "ਖੋਜ" - }, - "scripting_warning": { - "title": "ਚੇਤਾਵਨੀ", - "content": "PurrfectSnap ਵਿੱਚ ਇੱਕ ਸਕ੍ਰਿਪਟਿੰਗ ਟੂਲ ਸ਼ਾਮਲ ਹੈ, ਜੋ ਤੁਹਾਡੀ ਡਿਵਾਈਸ 'ਤੇ ਉਪਭੋਗਤਾ-ਪ੍ਰਭਾਸ਼ਿਤ ਕੋਡ ਨੂੰ ਚਲਾਉਣ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ। ਬਹੁਤ ਜ਼ਿਆਦਾ ਸਾਵਧਾਨੀ ਵਰਤੋ ਅਤੇ ਸਿਰਫ਼ ਜਾਣੇ-ਪਛਾਣੇ, ਭਰੋਸੇਯੋਗ ਸਰੋਤਾਂ ਤੋਂ ਮਾਡਿਊਲ ਇੰਸਟਾਲ ਕਰੋ। ਅਣਅਧਿਕਾਰਤ ਜਾਂ ਗੈਰ-ਪ੍ਰਮਾਣਿਤ ਮਾਡਿਊਲ ਤੁਹਾਡੇ ਸਿਸਟਮ ਲਈ ਸੁਰੱਖਿਆ ਖਤਰੇ ਪੈਦਾ ਕਰ ਸਕਦੇ ਹਨ।" - }, - "reset_config": { - "title": "ਸੰਰਚਨਾ ਰੀਸੈਟ ਕਰੋ", - "content": "ਕੀ ਤੁਸੀਂ ਯਕੀਨੀ ਹੋ ਕਿ ਤੁਸੀਂ ਸੰਰਚਨਾ ਨੂੰ ਰੀਸੈਟ ਕਰਨਾ ਚਾਹੁੰਦੇ ਹੋ?", - "success_toast": "ਸੰਰਚਨਾ ਸਫਲਤਾਪੂਰਵਕ ਰੀਸੈਟ ਕੀਤੀ ਗਈ" - }, - "export_config": { - "title": "ਸੰਵੇਦਨਸ਼ੀਲ ਡਾਟਾ ਨਿਰਯਾਤ ਕਰੀਏ?", - "content": "ਕੀ ਤੁਸੀਂ ਸੰਵੇਦਨਸ਼ੀਲ ਡਾਟਾ (ਜਿਵੇਂ ਕਿ ਸਥਾਨ ਕੋਆਰਡੀਨੇਟ, ਆਦਿ) ਨਾਲ ਸੰਰਚਨਾ ਨਿਰਯਾਤ ਕਰਨਾ ਚਾਹੁੰਦੇ ਹੋ?" - }, - "messaging_action": { - "title": "ਪ੍ਰੋਸੈਸ ਕਰਨ ਲਈ ਸਮੱਗਰੀ ਦੀਆਂ ਕਿਸਮਾਂ ਚੁਣੋ", - "select_all_button": "ਸਭ ਚੁਣੋ" - }, - "file_imports": { - "no_files_settings_hint": "ਕੋਈ ਫਾਈਲਾਂ ਨਹੀਂ ਮਿਲੀਆਂ। ਯਕੀਨੀ ਬਣਾਓ ਕਿ ਤੁਸੀਂ ਫਾਈਲ ਆਯਾਤ ਸੈਕਸ਼ਨ ਵਿੱਚ ਲੋੜੀਂਦੀਆਂ ਫਾਈਲਾਂ ਆਯਾਤ ਕੀਤੀਆਂ ਹਨ", - "settings_select_file_hint": "ਇੱਕ ਆਯਾਤ ਕੀਤੀ ਫਾਈਲ ਚੁਣੋ" - }, - "quick_actions_dialog": { - "title": "ਤੁਰੰਤ ਕਾਰਵਾਈਆਂ ਨੂੰ ਸੋਧੋ", - "subtitle": "ਆਪਣੀਆਂ ਤੁਰੰਤ ਕਾਰਵਾਈਆਂ ਚੁਣੋ ਅਤੇ ਮੁੜ-ਆਕਾਰ ਦਿਓ।" - } - }, - "friend_tracker": { - "rules_tab": "ਨਿਯਮ", - "logs_tab": "ਲੌਗਸ", - "export_dialog_title": "ਨਿਰਯਾਤ", - "bulk_export_button": "ਬਲਕ ਨਿਰਯਾਤ", - "individual_export_button": "ਵਿਅਕਤੀਗਤ ਨਿਰਯਾਤ", - "invalid_import_type_dialog_title": "ਅਵੈਧ ਆਯਾਤ ਕਿਸਮ", - "invalid_import_type_dialog_text": "ਚੁਣੀ ਗਈ ਫਾਈਲ ਇਸ ਆਯਾਤ ਕਿਸਮ ਦੇ ਅਨੁਕੂਲ ਨਹੀਂ ਹੈ। ਕਿਰਪਾ ਕਰਕੇ ਸਹੀ ਆਯਾਤ ਕਿਸਮ ਚੁਣੋ।", - "import_dialog_title": "ਆਯਾਤ", - "bulk_import_button": "ਬਲਕ ਆਯਾਤ", - "individual_import_button": "ਵਿਅਕਤੀਗਤ ਆਯਾਤ", - "import_button_description": "ਆਯਾਤ", - "export_button_description": "ਨਿਰਯਾਤ", - "export_button": "ਨਿਰਯਾਤ", - "delete_button_description": "ਮਿਟਾਓ", - "delete_button": "ਮਿਟਾਓ", - "catalog_button_description": "ਕੈਟਾਲਾਗ", - "catalog_button": "ਕੈਟਾਲਾਗ", - "add_rule_button_description": "ਨਿਯਮ ਸ਼ਾਮਲ ਕਰੋ", - "add_rule_button": "ਨਿਯਮ ਸ਼ਾਮਲ ਕਰੋ", - "no_rules_found": "ਕੋਈ ਨਿਯਮ ਨਹੀਂ ਮਿਲਿਆ", - "empty_rule_name": "(ਖਾਲੀ)", - "events_suffix": "ਸਮਾਗਮਾਂ", - "scopes_suffix": "ਸਕੋਪ", - "select_rule_to_export_title": "ਨਿਰਯਾਤ ਕਰਨ ਲਈ ਨਿਯਮ ਚੁਣੋ", - "deleted_logs_toast": "{count} ਲੌਗ ਮਿਟਾਏ ਗਏ", - "delete_logs_dialog_title": "ਲੌਗ ਮਿਟਾਓ?", - "deleting_logs_dialog_text": "{count} ਲੌਗ ਮਿਟਾਏ ਜਾ ਰਹੇ ਹਨ...", - "delete_logs_dialog_confirm_text": "ਇਹ ਮੌਜੂਦਾ ਫਿਲਟਰ ਅਤੇ ਖੋਜ ਪੁੱਛਗਿੱਛ ਦੇ ਆਧਾਰ 'ਤੇ ਲੌਗਸ ਨੂੰ ਮਿਟਾ ਦੇਵੇਗਾ। ਇਸ ਕਾਰਵਾਈ ਨੂੰ ਵਾਪਸ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਦਾ।", - "exported_logs_toast": "ਲੌਗ ਨਿਰਯਾਤ ਕੀਤੇ ਗਏ!", - "export_logs_failed_toast": "ਲੌਗ ਨਿਰਯਾਤ ਕਰਨ ਵਿੱਚ ਅਸਫਲ। ਹੋਰ ਵੇਰਵਿਆਂ ਲਈ LogCat ਦੀ ਜਾਂਚ ਕਰੋ।", - "export_logs_dialog_title": "ਲੌਗ ਨਿਰਯਾਤ ਕਰੋ?", - "exporting_logs_dialog_text": "ਲੌਗ ਨਿਰਯਾਤ ਕੀਤੇ ਜਾ ਰਹੇ ਹਨ...", - "export_logs_dialog_confirm_text": "ਇਹ ਮੌਜੂਦਾ ਫਿਲਟਰ ਅਤੇ ਖੋਜ ਪੁੱਛਗਿੱਛ ਦੇ ਆਧਾਰ 'ਤੇ ਲੌਗਸ ਨੂੰ ਨਿਰਯਾਤ ਕਰੇਗਾ।", - "export_as_button": "{type} ਵਜੋਂ ਨਿਰਯਾਤ ਕਰੋ", - "filters_title": "ਫਿਲਟਰ", - "search_by_label": "ਦੁਆਰਾ ਖੋਜ ਕਰੋ", - "newest_first_label": "ਸਭ ਤੋਂ ਨਵਾਂ ਪਹਿਲਾਂ", - "since_label": "ਤੋਂ", - "until_label": "ਤੱਕ", - "pick_a_date_button": "ਇੱਕ ਮਿਤੀ ਚੁਣੋ", - "search_placeholder": "ਖੋਜ", - "filter_button_description": "ਫਿਲਟਰ", - "clear_button_description": "ਸਾਫ਼ ਕਰੋ", - "no_logs_found": "ਕੋਈ ਲੌਗ ਨਹੀਂ ਮਿਲਿਆ", - "log_event_format": "{conversation} ਵਿੱਚ {event}", - "condition_only_inside_conversation": "ਸਿਰਫ਼ ਜਦੋਂ ਮੈਂ ਗੱਲਬਾਤ ਵਿੱਚ ਹੋਵਾਂ", - "condition_only_outside_conversation": "ਸਿਰਫ਼ ਜਦੋਂ ਮੈਂ ਗੱਲਬਾਤ ਤੋਂ ਬਾਹਰ ਹੋਵਾਂ", - "condition_only_when_app_active": "ਸਿਰਫ਼ ਜਦੋਂ Snapchat ਕਿਰਿਆਸ਼ੀਲ ਹੋਵੇ", - "condition_only_when_app_inactive": "ਸਿਰਫ਼ ਜਦੋਂ Snapchat ਨਿਸ਼ਕਿਰਿਆ ਹੋਵੇ", - "condition_no_push_notification_when_app_active": "ਜਦੋਂ Snapchat ਕਿਰਿਆਸ਼ੀਲ ਹੋਵੇ ਤਾਂ ਕੋਈ ਪੁਸ਼ ਸੂਚਨਾ ਨਹੀਂ", - "add_event_dialog_title": "ਸਮਾਗਮ ਸ਼ਾਮਲ ਕਰੋ", - "event_type_label": "ਸਮਾਗਮ ਦੀ ਕਿਸਮ", - "triggers_title": "ਟਰਿੱਗਰ", - "conditions_title": "ਸ਼ਰਤਾਂ", - "add_button": "ਸ਼ਾਮਲ ਕਰੋ", - "default_rule_name": "ਕਸਟਮ ਨਿਯਮ", - "discard_changes_dialog_title": "ਤਬਦੀਲੀਆਂ ਰੱਦ ਕਰੋ?", - "discard_changes_dialog_text": "ਤੁਹਾਡੇ ਕੋਲ ਅਣਸੇਵ ਕੀਤੀਆਂ ਤਬਦੀਲੀਆਂ ਹਨ। ਕੀ ਤੁਸੀਂ ਯਕੀਨੀ ਹੋ ਕਿ ਤੁਸੀਂ ਉਨ੍ਹਾਂ ਨੂੰ ਰੱਦ ਕਰਨਾ ਚਾਹੁੰਦੇ ਹੋ?", - "discard_button": "ਰੱਦ ਕਰੋ", - "cannot_save_rule_dialog_title": "ਨਿਯਮ ਸੇਵ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਦਾ", - "cannot_save_rule_dialog_text": "ਇੱਕ ਨਿਯਮ ਨੂੰ ਸੇਵ ਕਰਨ ਲਈ ਘੱਟੋ-ਘੱਟ ਇੱਕ ਸਮਾਗਮ ਹੋਣਾ ਚਾਹੀਦਾ ਹੈ।", - "duplicate_rule_name_dialog_title": "ਡੁਪਲੀਕੇਟ ਨਿਯਮ ਨਾਮ", - "duplicate_rule_name_dialog_text": "ਇਸ ਨਾਮ ਨਾਲ ਇੱਕ ਨਿਯਮ ਪਹਿਲਾਂ ਤੋਂ ਮੌਜੂਦ ਹੈ। ਕਿਰਪਾ ਕਰਕੇ ਇੱਕ ਵੱਖਰਾ ਨਾਮ ਚੁਣੋ।", - "delete_rule_dialog_title": "ਨਿਯਮ ਮਿਟਾਓ", - "delete_rule_dialog_text": "ਕੀ ਤੁਸੀਂ ਯਕੀਨੀ ਹੋ ਕਿ ਤੁਸੀਂ ਇਸ ਨਿਯਮ ਨੂੰ ਮਿਟਾਉਣਾ ਚਾਹੁੰਦੇ ਹੋ?", - "new_rule_title": "ਨਵਾਂ ਨਿਯਮ", - "edit_rule_title": "ਨਿਯਮ ਸੰਪਾਦਿਤ ਕਰੋ", - "back_button_description": "ਪਿੱਛੇ", - "save_button_description": "ਸੇਵ", - "general_section_title": "ਆਮ", - "rule_name_label": "ਨਿਯਮ ਦਾ ਨਾਮ", - "author_name_label": "ਲੇਖਕ ਦਾ ਨਾਮ", - "scope_section_title": "ਸਕੋਪ", - "scope_all": "ਸਾਰੇ", - "scope_whitelist": "ਵ੍ਹਾਈਟਲਿਸਟ", - "scope_blacklist": "ਬਲੈਕਲਿਸਟ", - "select_friends_groups_button": "ਦੋਸਤ/ਸਮੂਹ ਚੁਣੋ ({count})", - "events_section_title": "ਸਮਾਗਮ", - "add_event_button": "ਸਮਾਗਮ ਸ਼ਾਮਲ ਕਰੋ", - "no_events_text": "ਕੋਈ ਸਮਾਗਮ ਨਹੀਂ" - }, - "friend_tracker_catalog": { - "download_failed": "ਡਾਊਨਲੋਡ ਅਸਫਲ: {code}", - "error": "ਗਲਤੀ: {message}", - "no_repos_added": "ਕੋਈ ਰਿਪੋਜ਼ਟਰੀਆਂ ਸ਼ਾਮਲ ਨਹੀਂ ਕੀਤੀਆਂ ਗਈਆਂ।", - "no_rules_available": "ਕਿਸੇ ਵੀ ਰਿਪੋਜ਼ਟਰੀ ਤੋਂ ਕੋਈ ਨਿਯਮ ਉਪਲਬਧ ਨਹੀਂ ਹੈ।", - "by_author": "{author} ਦੁਆਰਾ", - "imported_button": "ਆਯਾਤ ਕੀਤਾ ਗਿਆ", - "import_button": "ਆਯਾਤ", - "title": "ਦੋਸਤ ਟਰੈਕਰ ਕੈਟਾਲਾਗ", - "manage_repos_description": "ਰਿਪੋਜ਼ਟਰੀਆਂ ਦਾ ਪ੍ਰਬੰਧਨ ਕਰੋ" - }, - "friend_tracker_export": { - "title": "ਨਿਯਮ ਨਿਰਯਾਤ ਕਰੋ", - "back_button_description": "ਪਿੱਛੇ", - "exported_toast": "ਦੋਸਤ ਟਰੈਕਰ ਨਿਯਮ ਨਿਰਯਾਤ ਕੀਤੇ ਗਏ!", - "export_failed_toast": "ਨਿਯਮ ਨਿਰਯਾਤ ਕਰਨ ਵਿੱਚ ਅਸਫਲ: {message}", - "save_button": "ਸੇਵ", - "expand_button_description": "ਫੈਲਾਓ" - }, - "friend_tracker_import": { - "title": "ਨਿਯਮ ਆਯਾਤ ਕਰੋ", - "back_button_description": "ਪਿੱਛੇ", - "imported_toast": "ਦੋਸਤ ਟਰੈਕਰ ਨਿਯਮ ਆਯਾਤ ਕੀਤੇ ਗਏ!", - "import_failed_toast": "ਨਿਯਮ ਆਯਾਤ ਕਰਨ ਵਿੱਚ ਅਸਫਲ: {message}", - "confirm_button": "ਪੁਸ਼ਟੀ ਕਰੋ", - "expand_button_description": "ਫੈਲਾਓ" - }, - "friend_tracker_repos": { - "invalid_repo_title": "ਅਵੈਧ ਰਿਪੋਜ਼ਟਰੀ", - "add_repo_button": "ਰਿਪੋਜ਼ਟਰੀ ਸ਼ਾਮਲ ਕਰੋ", - "add_repo_dialog_title": "ਰਿਪੋਜ਼ਟਰੀ URL ਸ਼ਾਮਲ ਕਰੋ", - "repo_url_label": "ਰਿਪੋਜ਼ਟਰੀ URL", - "repo_added_toast": "ਰਿਪੋਜ਼ਟਰੀ ਸਫਲਤਾਪੂਰਵਕ ਸ਼ਾਮਲ ਕੀਤੀ ਗਈ!", - "invalid_repo_error": "ਇਹ ਇੱਕ ਵੈਧ ਦੋਸਤ ਟਰੈਕਰ ਰਿਪੋਜ਼ਟਰੀ ਨਹੀਂ ਜਾਪਦੀ।", - "add_repo_failed_toast": "ਰਿਪੋਜ਼ਟਰੀ ਸ਼ਾਮਲ ਕਰਨ ਵਿੱਚ ਅਸਫਲ: {message}", - "add_button": "ਸ਼ਾਮਲ ਕਰੋ", - "no_repos_added": "ਕੋਈ ਰਿਪੋਜ਼ਟਰੀਆਂ ਸ਼ਾਮਲ ਨਹੀਂ ਕੀਤੀਆਂ ਗਈਆਂ", - "remove_button": "ਹਟਾਓ", - "remove_repo_dialog_title": "ਰਿਪੋਜ਼ਟਰੀ ਹਟਾਓ", - "remove_repo_dialog_text": "ਕੀ ਤੁਸੀਂ ਯਕੀਨੀ ਹੋ ਕਿ ਤੁਸੀਂ ਇਸ ਰਿਪੋਜ਼ਟਰੀ ਨੂੰ ਹਟਾਉਣਾ ਚਾਹੁੰਦੇ ਹੋ?" - }, - "navigation": { - "tracker_tab_label": "ਟਰੈਕਰ", - "customize_bottom_bar_title": "ਹੇਠਲੀ ਬਾਰ ਨੂੰ ਅਨੁਕੂਲਿਤ ਕਰੋ", - "customize_bottom_bar_subtitle": "ਟੈਬਾਂ ਨੂੰ ਮੁੜ-ਕ੍ਰਮਬੱਧ ਕਰੋ, ਸ਼ਾਮਲ ਕਰੋ ਜਾਂ ਹਟਾਓ। ਵੱਧ ਤੋਂ ਵੱਧ ਪੰਜ।", - "shown_tabs_title": "ਦਿਖਾਈਆਂ ਗਈਆਂ ਟੈਬਾਂ", - "no_tabs_selected_text": "ਕੋਈ ਟੈਬ ਨਹੀਂ ਚੁਣੀ ਗਈ", - "available_tabs_title": "ਉਪਲਬਧ ਟੈਬਾਂ", - "reset_button": "ਰੀਸੈਟ", - "done_button": "ਹੋ ਗਿਆ" - }, - "scripting": { - "script_already_installed": "ਸਕ੍ਰਿਪਟ ਪਹਿਲਾਂ ਹੀ ਇੰਸਟਾਲ ਹੈ!", - "downloading_script": "ਸਕ੍ਰਿਪਟ ਡਾਊਨਲੋਡ ਕੀਤੀ ਜਾ ਰਹੀ ਹੈ...", - "script_downloaded": "ਸਕ੍ਰਿਪਟ {name} ਡਾਊਨਲੋਡ ਕੀਤੀ ਗਈ!", - "download_script_failed": "ਸਕ੍ਰਿਪਟ ਡਾਊਨਲੋਡ ਕਰਨ ਵਿੱਚ ਅਸਫਲ। ਹੋਰ ਵੇਰਵਿਆਂ ਲਈ ਲੌਗਸ ਦੀ ਜਾਂਚ ਕਰੋ", - "import_script_from_url_title": "URL ਤੋਂ ਸਕ੍ਰਿਪਟ ਆਯਾਤ ਕਰੋ", - "import_script_warning": "ਚੇਤਾਵਨੀ: ਆਯਾਤ ਕੀਤੀਆਂ ਸਕ੍ਰਿਪਟਾਂ ਤੁਹਾਡੀ ਡਿਵਾਈਸ ਲਈ ਨੁਕਸਾਨਦੇਹ ਹੋ ਸਕਦੀਆਂ ਹਨ। ਸਿਰਫ਼ ਭਰੋਸੇਯੋਗ ਸਰੋਤਾਂ ਤੋਂ ਸਕ੍ਰਿਪਟਾਂ ਆਯਾਤ ਕਰੋ।", - "enter_url_label": "ਇੱਥੇ URL ਦਾਖਲ ਕਰੋ:", - "script_imported": "ਸਕ੍ਰਿਪਟ {name} ਆਯਾਤ ਕੀਤੀ ਗਈ!", - "import_failed": "ਸਕ੍ਰਿਪਟ ਆਯਾਤ ਕਰਨ ਵਿੱਚ ਅਸਫਲ। {message}। ਹੋਰ ਵੇਰਵਿਆਂ ਲਈ ਲੌਗਸ ਦੀ ਜਾਂਚ ਕਰੋ", - "import_button": "ਆਯਾਤ", - "update_module_button": "ਮਾਡਿਊਲ ਅੱਪਡੇਟ ਕਰੋ", - "updating_script": "ਸਕ੍ਰਿਪਟ {name} ਨੂੰ ਅੱਪਡੇਟ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ...", - "module_not_found": "ਮਾਡਿਊਲ ਨਹੀਂ ਮਿਲਿਆ", - "updated_script": "{name} ਨੂੰ ਸੰਸਕਰਣ {version} 'ਤੇ ਅੱਪਡੇਟ ਕੀਤਾ ਗਿਆ", - "update_module_failed": "ਮਾਡਿਊਲ ਅੱਪਡੇਟ ਕਰਨ ਵਿੱਚ ਅਸਫਲ। ਹੋਰ ਵੇਰਵਿਆਂ ਲਈ ਲੌਗਸ ਦੀ ਜਾਂਚ ਕਰੋ", - "edit_module_button": "ਮਾਡਿਊਲ ਸੰਪਾਦਿਤ ਕਰੋ", - "open_module_failed": "ਮਾਡਿਊਲ ਫਾਈਲ ਖੋਲ੍ਹਣ ਵਿੱਚ ਅਸਫਲ। ਹੋਰ ਵੇਰਵਿਆਂ ਲਈ ਲੌਗਸ ਦੀ ਜਾਂਚ ਕਰੋ", - "clear_module_data_button": "ਮਾਡਿਊਲ ਡਾਟਾ ਸਾਫ਼ ਕਰੋ", - "module_data_cleared": "ਮਾਡਿਊਲ ਡਾਟਾ ਸਾਫ਼ ਹੋ ਗਿਆ!", - "clear_module_data_failed": "ਮਾਡਿਊਲ ਡਾਟਾ ਸਾਫ਼ ਕਰਨ ਵਿੱਚ ਅਸਫਲ। ਹੋਰ ਵੇਰਵਿਆਂ ਲਈ ਲੌਗਸ ਦੀ ਜਾਂਚ ਕਰੋ", - "delete_module_button": "ਮਾਡਿਊਲ ਮਿਟਾਓ", - "deleted_script": "ਸਕ੍ਰਿਪਟ {name} ਮਿਟਾ ਦਿੱਤੀ ਗਈ!", - "delete_module_failed": "ਮਾਡਿਊਲ ਮਿਟਾਉਣ ਵਿੱਚ ਅਸਫਲ। ਹੋਰ ਵੇਰਵਿਆਂ ਲਈ ਲੌਗਸ ਦੀ ਜਾਂਚ ਕਰੋ", - "actions_title": "ਕਾਰਵਾਈਆਂ", - "no_description": "ਕੋਈ ਵੇਰਵਾ ਨਹੀਂ", - "update_available": "ਅੱਪਡੇਟ ਉਪਲਬਧ: {version}", - "actions_button": "ਕਾਰਵਾਈਆਂ", - "loaded_script": "ਲੋਡ ਕੀਤੀ ਸਕ੍ਰਿਪਟ {name}", - "unloaded_script": "ਅਣਲੋਡ ਕੀਤੀ ਸਕ੍ਰਿਪਟ {name}", - "enable_script_failed": "ਸਕ੍ਰਿਪਟ ਨੂੰ ਸਮਰੱਥ ਕਰਨ ਵਿੱਚ ਅਸਫਲ। ਹੋਰ ਵੇਰਵਿਆਂ ਲਈ ਲੌਗਸ ਦੀ ਜਾਂਚ ਕਰੋ", - "disable_script_failed": "ਸਕ੍ਰਿਪਟ ਨੂੰ ਅਯੋਗ ਕਰਨ ਵਿੱਚ ਅਸਫਲ। ਹੋਰ ਵੇਰਵਿਆਂ ਲਈ ਲੌਗਸ ਦੀ ਜਾਂਚ ਕਰੋ", - "select_scripts_folder_toast": "ਕਿਰਪਾ ਕਰਕੇ ਆਪਣਾ ਸਕ੍ਰਿਪਟਾਂ ਫੋਲਡਰ ਚੁਣੋ!", - "manage_repos_button": "ਰਿਪੋਜ਼ਟਰੀਆਂ ਦਾ ਪ੍ਰਬੰਧਨ ਕਰੋ", - "import_from_url_button": "URL ਤੋਂ ਆਯਾਤ ਕਰੋ", - "open_scripts_folder_button": "ਸਕ੍ਰਿਪਟਾਂ ਫੋਲਡਰ ਖੋਲ੍ਹੋ", - "no_settings_for_module": "ਇਸ ਮਾਡਿਊਲ ਲਈ ਕੋਈ ਸੈਟਿੰਗਾਂ ਨਹੀਂ ਹਨ", - "installed_scripts_tab": "ਇੰਸਟਾਲ ਕੀਤੀਆਂ ਸਕ੍ਰਿਪਟਾਂ", - "catalog_tab": "ਕੈਟਾਲਾਗ", - "no_scripts_folder_selected_title": "ਕੋਈ ਸਕ੍ਰਿਪਟਾਂ ਫੋਲਡਰ ਨਹੀਂ ਚੁਣਿਆ ਗਿਆ", - "select_folder_button": "ਫੋਲਡਰ ਚੁਣੋ", - "no_scripts_found_title": "ਕੋਈ ਸਕ੍ਰਿਪਟਾਂ ਨਹੀਂ ਮਿਲੀਆਂ।", - "use_catalog_to_add_scripts": "ਸਕ੍ਰਿਪਟਾਂ ਸ਼ਾਮਲ ਕਰਨ ਲਈ ਕੈਟਾਲਾਗ ਟੈਬ ਦੀ ਵਰਤੋਂ ਕਰੋ!", - "ok_button_timeout": "ਠੀਕ ਹੈ ({timeout})", - "documentation_button": "ਦਸਤਾਵੇਜ਼", - "catalog": { - "script_already_installed": "ਸਕ੍ਰਿਪਟ ਪਹਿਲਾਂ ਹੀ ਇੰਸਟਾਲ ਹੈ!", - "download_failed": "ਡਾਊਨਲੋਡ ਅਸਫਲ: {code}", - "script_downloaded": "ਸਕ੍ਰਿਪਟ ਡਾਊਨਲੋਡ ਕੀਤੀ ਗਈ!", - "could_not_create_file": "ਫਾਈਲ ਨਹੀਂ ਬਣਾਈ ਜਾ ਸਕੀ।", - "no_scripts_folder_selected": "ਕੋਈ ਸਕ੍ਰਿਪਟਾਂ ਫੋਲਡਰ ਨਹੀਂ ਚੁਣਿਆ ਗਿਆ।", - "error": "ਗਲਤੀ: {message}", - "no_repos_added": "ਕੋਈ ਰਿਪੋਜ਼ਟਰੀਆਂ ਸ਼ਾਮਲ ਨਹੀਂ ਕੀਤੀਆਂ ਗਈਆਂ।", - "repo_list_info": "ਇੱਥੇ ਤੁਸੀਂ ਰਿਪੋਜ਼ਟਰੀਆਂ ਦੀ ਸੂਚੀ ਲੱਭ ਸਕਦੇ ਹੋ:", - "link_text": "ਲਿੰਕ", - "no_scripts_available": "ਕਿਸੇ ਵੀ ਰਿਪੋਜ਼ਟਰੀ ਤੋਂ ਕੋਈ ਸਕ੍ਰਿਪਟਾਂ ਉਪਲਬਧ ਨਹੀਂ ਹਨ।", - "by_author": "{author} ਦੁਆਰਾ", - "version": "ਸੰਸਕਰਣ: {version}", - "installed_button": "ਇੰਸਟਾਲ ਕੀਤਾ ਗਿਆ", - "download_button": "ਡਾਊਨਲੋਡ ਕਰੋ" - }, - "repos": { - "invalid_repo_title": "ਅਵੈਧ ਰਿਪੋਜ਼ਟਰੀ", - "add_repo_button": "ਰਿਪੋਜ਼ਟਰੀ ਸ਼ਾਮਲ ਕਰੋ", - "add_repo_dialog_title": "ਰਿਪੋਜ਼ਟਰੀ URL ਸ਼ਾਮਲ ਕਰੋ", - "repo_url_label": "ਰਿਪੋਜ਼ਟਰੀ URL", - "repo_added_toast": "ਰਿਪੋਜ਼ਟਰੀ ਸਫਲਤਾਪੂਰਵਕ ਸ਼ਾਮਲ ਕੀਤੀ ਗਈ!", - "invalid_repo_error": "ਇਹ ਇੱਕ ਵੈਧ ਸਕ੍ਰਿਪਟ ਰਿਪੋਜ਼ਟਰੀ ਨਹੀਂ ਜਾਪਦੀ।", - "add_repo_failed_toast": "ਰਿਪੋਜ਼ਟਰੀ ਸ਼ਾਮਲ ਕਰਨ ਵਿੱਚ ਅਸਫਲ: {message}", - "add_button": "ਸ਼ਾਮਲ ਕਰੋ", - "no_repos_added": "ਕੋਈ ਰਿਪੋਜ਼ਟਰੀਆਂ ਸ਼ਾਮਲ ਨਹੀਂ ਕੀਤੀਆਂ ਗਈਆਂ", - "remove_button": "ਹਟਾਓ", - "remove_repo_dialog_title": "ਰਿਪੋਜ਼ਟਰੀ ਹਟਾਓ", - "remove_repo_dialog_text": "ਕੀ ਤੁਸੀਂ ਯਕੀਨੀ ਹੋ ਕਿ ਤੁਸੀਂ ਇਸ ਰਿਪੋਜ਼ਟਰੀ ਨੂੰ ਹਟਾਉਣਾ ਚਾਹੁੰਦੇ ਹੋ?" - } - }, - "features": { - "config_import": { - "title": "ਆਯਾਤ ਦੀ ਪੁਸ਼ਟੀ ਕਰੋ", - "back_button_description": "ਪਿੱਛੇ", - "config_imported_toast": "ਸੰਰਚਨਾ ਆਯਾਤ ਕੀਤੀ ਗਈ!", - "confirm_button": "ਪੁਸ਼ਟੀ ਕਰੋ", - "expand_button_description": "ਫੈਲਾਓ", - "enable_feature": "ਵਿਸ਼ੇਸ਼ਤਾ ਨੂੰ ਸਮਰੱਥ ਕਰੋ", - "enabled": "ਸਮਰਥਿਤ", - "disabled": "ਅਯੋਗ" - }, - "config_export": { - "title": "ਨਿਰਯਾਤ ਸੰਖੇਪ", - "back_button_description": "ਪਿੱਛੇ", - "save_button": "ਸੇਵ", - "expand_button_description": "ਫੈਲਾਓ", - "enable_feature": "ਵਿਸ਼ੇਸ਼ਤਾ ਨੂੰ ਸਮਰੱਥ ਕਰੋ", - "enabled": "ਸਮਰਥਿਤ", - "disabled": "ਅਯੋਗ" - } - }, - "manage_repos": { - "title": "{featureName} ਰਿਪੋਜ਼ਟਰੀਆਂ ਦਾ ਪ੍ਰਬੰਧਨ ਕਰੋ", - "add_repo_button": "ਰਿਪੋਜ਼ਟਰੀ ਸ਼ਾਮਲ ਕਰੋ", - "add_repo_dialog_title": "ਰਿਪੋਜ਼ਟਰੀ URL ਸ਼ਾਮਲ ਕਰੋ", - "repo_url_label": "ਰਿਪੋਜ਼ਟਰੀ URL", - "repo_added_successfully": "ਰਿਪੋਜ਼ਟਰੀ ਸਫਲਤਾਪੂਰਵਕ ਸ਼ਾਮਲ ਕੀਤੀ ਗਈ!", - "add_repo_failed": "ਰਿਪੋਜ਼ਟਰੀ ਸ਼ਾਮਲ ਕਰਨ ਵਿੱਚ ਅਸਫਲ: {message}", - "add_button": "ਸ਼ਾਮਲ ਕਰੋ", - "no_repos_added": "ਕੋਈ ਰਿਪੋਜ਼ਟਰੀਆਂ ਸ਼ਾਮਲ ਨਹੀਂ ਕੀਤੀਆਂ ਗਈਆਂ", - "remove_button": "ਹਟਾਓ" - } - }, - "rules": { - "toasts": { - "enabled": "{ruleName} ਸਮਰਥਿਤ", - "disabled": "{ruleName} ਅਯੋਗ" - }, - "modes": { - "blacklist": "ਬਲੈਕਲਿਸਟ ਮੋਡ", - "whitelist": "ਵ੍ਹਾਈਟਲਿਸਟ ਮੋਡ" - }, - "properties": { - "auto_download": { - "name": "ਆਟੋ ਡਾਊਨਲੋਡ", - "description": "ਸਨੈਪ ਦੇਖਣ ਵੇਲੇ ਆਪਣੇ ਆਪ ਡਾਊਨਲੋਡ ਕਰੋ", - "options": { - "blacklist": "ਆਟੋ ਡਾਊਨਲੋਡ ਤੋਂ ਬਾਹਰ ਕੱਢੋ", - "whitelist": "ਆਟੋ ਡਾਊਨਲੋਡ" - } - }, - "stealth": { - "name": "ਸਟੀਲਥ ਮੋਡ", - "description": "ਕਿਸੇ ਨੂੰ ਇਹ ਜਾਣਨ ਤੋਂ ਰੋਕਦਾ ਹੈ ਕਿ ਤੁਸੀਂ ਉਨ੍ਹਾਂ ਦੇ ਸਨੈਪ/ਚੈਟ ਅਤੇ ਗੱਲਬਾਤ ਖੋਲ੍ਹ ਦਿੱਤੀ ਹੈ", - "options": { - "blacklist": "ਸਟੀਲਥ ਮੋਡ ਤੋਂ ਬਾਹਰ ਕੱਢੋ", - "whitelist": "ਸਟੀਲਥ ਮੋਡ" - } - }, - "auto_save": { - "name": "ਆਟੋ ਸੇਵ", - "description": "ਚੈਟ ਸੁਨੇਹੇ ਦੇਖਣ ਵੇਲੇ ਸੇਵ ਕਰਦਾ ਹੈ", - "options": { - "blacklist": "ਆਟੋ ਸੇਵ ਤੋਂ ਬਾਹਰ ਕੱਢੋ", - "whitelist": "ਆਟੋ ਸੇਵ" - } - }, - "unsaveable_messages": { - "name": "ਅਣ-ਸੇਵ ਕਰਨ ਯੋਗ ਸੁਨੇਹੇ", - "description": "ਦੂਜੇ ਲੋਕਾਂ ਦੁਆਰਾ ਚੈਟ ਵਿੱਚ ਸੁਨੇਹਿਆਂ ਨੂੰ ਸੇਵ ਹੋਣ ਤੋਂ ਰੋਕਦਾ ਹੈ", - "options": { - "blacklist": "ਅਣ-ਸੇਵ ਕਰਨ ਯੋਗ ਸੁਨੇਹਿਆਂ ਤੋਂ ਬਾਹਰ ਕੱਢੋ", - "whitelist": "ਅਣ-ਸੇਵ ਕਰਨ ਯੋਗ ਸੁਨੇਹੇ" - } - }, - "auto_open_snaps": { - "name": "ਆਟੋ ਓਪਨ ਸਨੈਪਸ", - "description": "ਜਦੋਂ ਉਨ੍ਹਾਂ ਨੂੰ ਪ੍ਰਾਪਤ ਕੀਤਾ ਜਾਂਦਾ ਹੈ ਤਾਂ ਸਨੈਪਸ ਨੂੰ ਆਪਣੇ ਆਪ ਖੋਲ੍ਹਦਾ ਹੈ", - "options": { - "blacklist": "ਆਟੋ ਓਪਨ ਸਨੈਪਸ ਤੋਂ ਬਾਹਰ ਕੱਢੋ", - "whitelist": "ਆਟੋ ਓਪਨ ਸਨੈਪਸ" - } - }, - "hide_friend_feed": { - "name": "ਦੋਸਤ ਫੀਡ ਤੋਂ ਲੁਕਾਓ" - }, - "e2e_encryption": { - "name": "E2E ਇਨਕ੍ਰਿਪਸ਼ਨ ਦੀ ਵਰਤੋਂ ਕਰੋ" - }, - "pin_conversation": { - "name": "ਗੱਲਬਾਤ ਪਿੰਨ ਕਰੋ" - }, - "exclude_message_logger": { - "name": "ਸੁਨੇਹਾ ਲੌਗਰ ਤੋਂ ਬਾਹਰ ਕੱਢੋ" - } - } - }, - "actions": { - "clean_snapchat_cache": { - "name": "Snapchat ਕੈਸ਼ ਸਾਫ਼ ਕਰੋ", - "description": "Snapchat ਕੈਸ਼ ਨੂੰ ਸਾਫ਼ ਕਰਦਾ ਹੈ" - }, - "manage_friend_list": { - "name": "ਦੋਸਤ ਸੂਚੀ ਦਾ ਪ੍ਰਬੰਧਨ ਕਰੋ", - "description": "ਬੈਕਅੱਪ ਲੈਣ ਵੇਲੇ ਆਪਣੀ ਦੋਸਤ ਸੂਚੀ ਨੂੰ ਆਯਾਤ/ਨਿਰਯਾਤ ਕਰੋ" - }, - "export_chat_messages": { - "name": "ਚੈਟ ਸੁਨੇਹੇ ਨਿਰਯਾਤ ਕਰੋ", - "description": "ਗੱਲਬਾਤ ਦੇ ਸੁਨੇਹਿਆਂ ਨੂੰ ਇੱਕ JSON/HTML/TXT ਫਾਈਲ ਵਿੱਚ ਨਿਰਯਾਤ ਕਰਦਾ ਹੈ" - }, - "export_memories": { - "name": "ਯਾਦਾਂ ਨਿਰਯਾਤ ਕਰੋ", - "description": "ਯਾਦਾਂ ਨੂੰ ਇੱਕ ZIP ਫਾਈਲ ਵਿੱਚ ਨਿਰਯਾਤ ਕਰਦਾ ਹੈ" - }, - "bulk_messaging_action": { - "name": "ਬਲਕ ਮੈਸੇਜਿੰਗ ਕਾਰਵਾਈ", - "description": "ਦੋਸਤਾਂ ਨੂੰ ਹਟਾਉਣ ਜਾਂ ਗੱਲਬਾਤ ਨੂੰ ਵੱਡੀ ਗਿਣਤੀ ਵਿੱਚ ਮਿਟਾਉਣ ਵਰਗੇ ਕੰਮ ਕਰਦਾ ਹੈ" - }, - "regen_mappings": { - "name": "ਮੈਪਿੰਗ ਮੁੜ-ਤਿਆਰ ਕਰੋ", - "description": "ਮੈਪਿੰਗ ਨੂੰ ਹੱਥੀਂ ਮੁੜ-ਤਿਆਰ ਕਰੋ" - }, - "change_language": { - "name": "ਭਾਸ਼ਾ ਬਦਲੋ", - "description": "PurrfectSnap ਦੀ ਭਾਸ਼ਾ ਬਦਲੋ" - }, - "file_imports": { - "name": "ਫਾਈਲ ਆਯਾਤ", - "description": "Snapchat ਵਿੱਚ ਵਰਤੋਂ ਲਈ ਫਾਈਲਾਂ ਆਯਾਤ ਕਰੋ" - }, - "friend_tracker": { - "name": "ਦੋਸਤ ਟਰੈਕਰ", - "description": "Snapchat 'ਤੇ ਆਪਣੇ ਦੋਸਤਾਂ ਨੂੰ ਟਰੈਕ ਕਰੋ" - }, - "logger_history": { - "name": "ਲੌਗਰ ਇਤਿਹਾਸ", - "description": "ਲੌਗ ਕੀਤੇ ਸੁਨੇਹਿਆਂ ਦਾ ਇਤਿਹਾਸ ਵੇਖੋ" - } - }, - "features": { - "notices": { - "unstable": "⚠ ਅਸਥਿਰ", - "ban_risk": "⚠ ਇਹ ਵਿਸ਼ੇਸ਼ਤਾ ਪਾਬੰਦੀ ਦਾ ਕਾਰਨ ਬਣ ਸਕਦੀ ਹੈ", - "internal_behavior": "⚠ ਇਹ Snapchat ਦੇ ਅੰਦਰੂਨੀ ਵਿਵਹਾਰ ਨੂੰ ਤੋੜ ਸਕਦਾ ਹੈ" - }, - "properties": { - "downloader": { - "name": "ਡਾਊਨਲੋਡਰ", - "description": "Snapchat ਮੀਡੀਆ ਡਾਊਨਲੋਡ ਕਰੋ", - "properties": { - "save_folder": { - "name": "ਫੋਲਡਰ ਸੇਵ ਕਰੋ", - "description": "ਉਹ ਡਾਇਰੈਕਟਰੀ ਚੁਣੋ ਜਿੱਥੇ ਸਾਰਾ ਮੀਡੀਆ ਡਾਊਨਲੋਡ ਕੀਤਾ ਜਾਣਾ ਚਾਹੀਦਾ ਹੈ" - }, - "auto_download_sources": { - "name": "ਆਟੋ ਡਾਊਨਲੋਡ ਸਰੋਤ", - "description": "ਆਪਣੇ ਆਪ ਡਾਊਨਲੋਡ ਕਰਨ ਲਈ ਸਰੋਤ ਚੁਣੋ" - }, - "prevent_self_auto_download": { - "name": "ਸਵੈ-ਆਟੋ ਡਾਊਨਲੋਡ ਨੂੰ ਰੋਕੋ", - "description": "ਤੁਹਾਡੇ ਆਪਣੇ ਸਨੈਪਸ ਨੂੰ ਆਪਣੇ ਆਪ ਡਾਊਨਲੋਡ ਹੋਣ ਤੋਂ ਰੋਕਦਾ ਹੈ" - }, - "path_format": { - "name": "ਮਾਰਗ ਫਾਰਮੈਟ", - "description": "ਫਾਈਲ ਮਾਰਗ ਫਾਰਮੈਟ ਦਿਓ" - }, - "allow_duplicate": { - "name": "ਡੁਪਲੀਕੇਟ ਦੀ ਆਗਿਆ ਦਿਓ", - "description": "ਇੱਕੋ ਮੀਡੀਆ ਨੂੰ ਕਈ ਵਾਰ ਡਾਊਨਲੋਡ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ" - }, - "merge_overlays": { - "name": "ਓਵਰਲੇ ਮਿਲਾਓ", - "description": "ਇੱਕ ਸਨੈਪ ਦੇ ਟੈਕਸਟ ਅਤੇ ਮੀਡੀਆ ਨੂੰ ਇੱਕ ਫਾਈਲ ਵਿੱਚ ਮਿਲਾਉਂਦਾ ਹੈ" - }, - "force_image_format": { - "name": "ਚਿੱਤਰ ਫਾਰਮੈਟ ਨੂੰ ਮਜਬੂਰ ਕਰੋ", - "description": "ਚਿੱਤਰਾਂ ਨੂੰ ਇੱਕ ਖਾਸ ਫਾਰਮੈਟ ਵਿੱਚ ਸੇਵ ਕਰਨ ਲਈ ਮਜਬੂਰ ਕਰਦਾ ਹੈ" - }, - "force_voice_note_format": { - "name": "ਵੌਇਸ ਨੋਟ ਫਾਰਮੈਟ ਨੂੰ ਮਜਬੂਰ ਕਰੋ", - "description": "ਵੌਇਸ ਨੋਟਸ ਨੂੰ ਇੱਕ ਖਾਸ ਫਾਰਮੈਟ ਵਿੱਚ ਸੇਵ ਕਰਨ ਲਈ ਮਜਬੂਰ ਕਰਦਾ ਹੈ" - }, - "auto_download_voice_notes": { - "name": "ਆਟੋ ਡਾਊਨਲੋਡ ਵੌਇਸ ਨੋਟਸ", - "description": "ਜਦੋਂ ਤੁਸੀਂ ਉਨ੍ਹਾਂ ਨੂੰ ਚਲਾਉਂਦੇ ਹੋ ਤਾਂ ਵੌਇਸ ਨੋਟਸ ਨੂੰ ਆਪਣੇ ਆਪ ਡਾਊਨਲੋਡ ਕਰਦਾ ਹੈ" - }, - "download_profile_pictures": { - "name": "ਪ੍ਰੋਫਾਈਲ ਤਸਵੀਰਾਂ ਡਾਊਨਲੋਡ ਕਰੋ", - "description": "ਤੁਹਾਨੂੰ ਪ੍ਰੋਫਾਈਲ ਪੰਨੇ ਤੋਂ ਪ੍ਰੋਫਾਈਲ ਤਸਵੀਰਾਂ ਡਾਊਨਲੋਡ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ" - }, - "opera_download_button": { - "name": "ਓਪੇਰਾ ਡਾਊਨਲੋਡ ਬਟਨ", - "description": "ਇੱਕ ਸਨੈਪ ਦੇਖਣ ਵੇਲੇ ਉੱਪਰ-ਸੱਜੇ ਕੋਨੇ ਵਿੱਚ ਇੱਕ ਡਾਊਨਲੋਡ ਬਟਨ ਜੋੜਦਾ ਹੈ।\nਬਟਨ 'ਤੇ ਲੰਮਾ ਦਬਾਓ ਡਾਊਨਲੋਡ ਨੂੰ ਮਜਬੂਰ ਕਰੇਗਾ" - }, - "download_context_menu": { - "name": "ਪ੍ਰਸੰਗ ਮੀਨੂ ਡਾਊਨਲੋਡ ਕਰੋ", - "description": "ਤੁਹਾਨੂੰ ਪ੍ਰਸੰਗ ਮੀਨੂ ਦੀ ਵਰਤੋਂ ਕਰਕੇ ਗੱਲਬਾਤ ਜਾਂ ਕਹਾਣੀ ਤੋਂ ਸੁਨੇਹੇ ਡਾਊਨਲੋਡ/ਪੂਰਵਦਰਸ਼ਨ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।\nਬਟਨ 'ਤੇ ਲੰਮਾ ਦਬਾਓ ਡਾਊਨਲੋਡ ਨੂੰ ਮਜਬੂਰ ਕਰੇਗਾ" - }, - "ffmpeg_options": { - "name": "FFmpeg ਵਿਕਲਪ", - "description": "ਵਾਧੂ FFmpeg ਵਿਕਲਪ ਦਿਓ", - "properties": { - "threads": { - "name": "ਥਰਿੱਡ", - "description": "ਵਰਤਣ ਲਈ ਥਰਿੱਡਾਂ ਦੀ ਗਿਣਤੀ" - }, - "preset": { - "name": "ਪ੍ਰੀਸੈੱਟ", - "description": "ਪਰਿਵਰਤਨ ਦੀ ਗਤੀ ਸੈੱਟ ਕਰੋ" - }, - "constant_rate_factor": { - "name": "ਸਥਿਰ ਦਰ ਕਾਰਕ", - "description": "ਵੀਡੀਓ ਏਨਕੋਡਰ ਲਈ ਸਥਿਰ ਦਰ ਕਾਰਕ ਸੈੱਟ ਕਰੋ\nlibx264 ਲਈ 0 ਤੋਂ 51" - }, - "video_bitrate": { - "name": "ਵੀਡੀਓ ਬਿਟਰੇਟ", - "description": "ਵੀਡੀਓ ਬਿਟਰੇਟ (kbps) ਸੈੱਟ ਕਰੋ" - }, - "audio_bitrate": { - "name": "ਆਡੀਓ ਬਿਟਰੇਟ", - "description": "ਆਡੀਓ ਬਿਟਰੇਟ (kbps) ਸੈੱਟ ਕਰੋ" - }, - "custom_video_codec": { - "name": "ਕਸਟਮ ਵੀਡੀਓ ਕੋਡੇਕ", - "description": "ਇੱਕ ਕਸਟਮ ਵੀਡੀਓ ਕੋਡੇਕ ਸੈੱਟ ਕਰੋ (ਜਿਵੇਂ ਕਿ libx264)" - }, - "custom_audio_codec": { - "name": "ਕਸਟਮ ਆਡੀਓ ਕੋਡੇਕ", - "description": "ਇੱਕ ਕਸਟਮ ਆਡੀਓ ਕੋਡੇਕ ਸੈੱਟ ਕਰੋ (ਜਿਵੇਂ ਕਿ aac)" - } - } - }, - "logging": { - "name": "ਲੌਗਿੰਗ", - "description": "ਮੀਡੀਆ ਡਾਊਨਲੋਡ ਹੋਣ ਵੇਲੇ ਟੋਸਟ ਦਿਖਾਉਂਦਾ ਹੈ" - }, - "custom_path_format": { - "name": "ਕਸਟਮ ਮਾਰਗ ਫਾਰਮੈਟ", - "description": "ਡਾਊਨਲੋਡ ਕੀਤੇ ਮੀਡੀਆ ਲਈ ਇੱਕ ਕਸਟਮ ਮਾਰਗ ਫਾਰਮੈਟ ਦਿਓ\n\nਉਪਲਬਧ ਵੇਰੀਏਬਲ:\n - %username%\n - %source%\n - %hash%\n - %date_time%" - } - } - }, - "user_interface": { - "name": "ਯੂਜ਼ਰ ਇੰਟਰਫੇਸ", - "description": "Snapchat ਦੀ ਦਿੱਖ ਅਤੇ ਅਨੁਭਵ ਬਦਲੋ", - "properties": { - "enable_app_appearance": { - "name": "ਐਪ ਦਿੱਖ ਸੈਟਿੰਗਾਂ ਨੂੰ ਸਮਰੱਥ ਕਰੋ", - "description": "ਲੁਕਵੀਂ ਐਪ ਦਿੱਖ ਸੈਟਿੰਗ ਨੂੰ ਸਮਰੱਥ ਬਣਾਉਂਦਾ ਹੈ।\nਨਵੇਂ Snapchat ਸੰਸਕਰਣਾਂ 'ਤੇ ਲੋੜੀਂਦਾ ਨਹੀਂ ਹੋ ਸਕਦਾ।" - }, - "friend_feed_message_preview": { - "name": "ਦੋਸਤ ਫੀਡ ਸੁਨੇਹਾ ਪੂਰਵਦਰਸ਼ਨ", - "description": "ਦੋਸਤ ਫੀਡ ਵਿੱਚ ਆਖਰੀ ਸੁਨੇਹਿਆਂ ਦਾ ਪੂਰਵਦਰਸ਼ਨ ਦਿਖਾਉਂਦਾ ਹੈ", - "properties": { - "amount": { - "name": "ਰਕਮ", - "description": "ਪੂਰਵਦਰਸ਼ਨ ਲਈ ਸੁਨੇਹਿਆਂ ਦੀ ਗਿਣਤੀ" - } - } - }, - "snap_preview": { - "name": "ਸਨੈਪ ਪੂਰਵਦਰਸ਼ਨ", - "description": "ਚੈਟ ਵਿੱਚ ਅਣਦੇਖੇ ਸਨੈਪ ਦੇ ਅੱਗੇ ਇੱਕ ਛੋਟਾ ਪੂਰਵਦਰਸ਼ਨ ਪ੍ਰਦਰਸ਼ਿਤ ਕਰਦਾ ਹੈ" - }, - "bootstrap_override": { - "name": "ਬੂਟਸਟਰੈਪ ਓਵਰਰਾਈਡ", - "description": "ਯੂਜ਼ਰ ਇੰਟਰਫੇਸ ਬੂਟਸਟਰੈਪ ਸੈਟਿੰਗਾਂ ਨੂੰ ਓਵਰਰਾਈਡ ਕਰਦਾ ਹੈ", - "properties": { - "app_appearance": { - "name": "ਐਪ ਦਿੱਖ", - "description": "ਇੱਕ ਸਥਾਈ ਐਪ ਦਿੱਖ ਸੈੱਟ ਕਰਦਾ ਹੈ" - }, - "home_tab": { - "name": "ਹੋਮ ਟੈਬ", - "description": "Snapchat ਖੋਲ੍ਹਣ ਵੇਲੇ ਸ਼ੁਰੂਆਤੀ ਟੈਬ ਨੂੰ ਓਵਰਰਾਈਡ ਕਰਦਾ ਹੈ" - } - } - }, - "force_amoled_theme": { - "name": "AMOLED ਗੂੜ੍ਹਾ ਮੋਡ", - "description": "ਗੂੜ੍ਹੇ ਥੀਮ ਲਈ ਇੱਕ ਸੱਚਾ ਕਾਲਾ ਪਿਛੋਕੜ ਵਰਤਦਾ ਹੈ" - }, - "map_friend_nametags": { - "name": "ਵਧੇ ਹੋਏ ਦੋਸਤ ਨਕਸ਼ੇ ਨਾਮਟੈਗ", - "description": "Snapmap 'ਤੇ ਦੋਸਤਾਂ ਦੇ ਨਾਮਟੈਗ ਨੂੰ ਸੁਧਾਰਦਾ ਹੈ" - }, - "prevent_message_list_auto_scroll": { - "name": "ਸੁਨੇਹਾ ਸੂਚੀ ਆਟੋ-ਸਕ੍ਰੌਲ ਨੂੰ ਰੋਕੋ", - "description": "ਇੱਕ ਸੁਨੇਹਾ ਭੇਜਣ/ਪ੍ਰਾਪਤ ਕਰਨ ਵੇਲੇ ਸੁਨੇਹਾ ਸੂਚੀ ਨੂੰ ਹੇਠਾਂ ਸਕ੍ਰੌਲ ਕਰਨ ਤੋਂ ਰੋਕਦਾ ਹੈ" - }, - "streak_expiration_info": { - "name": "ਸਟ੍ਰੀਕ ਮਿਆਦ ਪੁੱਗਣ ਦੀ ਜਾਣਕਾਰੀ ਦਿਖਾਓ", - "description": "ਸਟ੍ਰੀਕ ਕਾਊਂਟਰ ਦੇ ਅੱਗੇ ਇੱਕ ਸਟ੍ਰੀਕ ਮਿਆਦ ਪੁੱਗਣ ਦਾ ਟਾਈਮਰ ਦਿਖਾਉਂਦਾ ਹੈ" - }, - "hide_friend_feed_entry": { - "name": "ਦੋਸਤ ਫੀਡ ਐਂਟਰੀ ਲੁਕਾਓ", - "description": "ਇੱਕ ਖਾਸ ਦੋਸਤ ਨੂੰ ਦੋਸਤ ਫੀਡ ਤੋਂ ਲੁਕਾਉਂਦਾ ਹੈ।\nਇਸ ਵਿਸ਼ੇਸ਼ਤਾ ਦਾ ਪ੍ਰਬੰਧਨ ਕਰਨ ਲਈ ਸੋਸ਼ਲ ਟੈਬ ਦੀ ਵਰਤੋਂ ਕਰੋ" - }, - "hide_streak_restore": { - "name": "ਸਟ੍ਰੀਕ ਰੀਸਟੋਰ ਲੁਕਾਓ", - "description": "ਦੋਸਤ ਫੀਡ ਵਿੱਚ ਰੀਸਟੋਰ ਬਟਨ ਨੂੰ ਲੁਕਾਉਂਦਾ ਹੈ" - }, - "hide_quick_add_suggestions": { - "name": "ਤੁਰੰਤ ਸ਼ਾਮਲ ਸੁਝਾਅ ਲੁਕਾਓ", - "description": "ਤੁਰੰਤ ਸ਼ਾਮਲ ਦੋਸਤ ਸੁਝਾਵਾਂ ਨੂੰ ਹਟਾਉਂਦਾ ਹੈ" - }, - "hide_story_suggestions": { - "name": "ਕਹਾਣੀ ਸੁਝਾਅ ਲੁਕਾਓ", - "description": "ਕਹਾਣੀਆਂ ਪੰਨੇ ਤੋਂ ਸੁਝਾਵਾਂ ਨੂੰ ਹਟਾਉਂਦਾ ਹੈ" - }, - "hide_ui_components": { - "name": "UI ਕੰਪੋਨੈਂਟਸ ਲੁਕਾਓ", - "description": "ਚੁਣੋ ਕਿ ਕਿਹੜੇ UI ਕੰਪੋਨੈਂਟਸ ਨੂੰ ਲੁਕਾਉਣਾ ਹੈ" - }, - "opera_media_quick_info": { - "name": "ਓਪੇਰਾ ਮੀਡੀਆ ਤੇਜ਼ ਜਾਣਕਾਰੀ", - "description": "ਓਪੇਰਾ ਦਰਸ਼ਕ ਪ੍ਰਸੰਗ ਮੀਨੂ ਵਿੱਚ ਉਪਯੋਗੀ ਮੀਡੀਆ ਜਾਣਕਾਰੀ ਜਿਵੇਂ ਕਿ ਬਣਾਉਣ ਦੀ ਮਿਤੀ ਦਿਖਾਉਂਦਾ ਹੈ" - }, - "old_bitmoji_selfie": { - "name": "ਪੁਰਾਣੀ Bitmoji ਸੈਲਫੀ", - "description": "ਪੁਰਾਣੇ Snapchat ਸੰਸਕਰਣਾਂ ਤੋਂ Bitmoji ਸੈਲਫੀ ਵਾਪਸ ਲਿਆਉਂਦਾ ਹੈ" - }, - "disable_spotlight": { - "name": "ਸਪੌਟਲਾਈਟ ਨੂੰ ਅਯੋਗ ਕਰੋ", - "description": "ਸਪੌਟਲਾਈਟ ਪੰਨੇ ਨੂੰ ਅਯੋਗ ਕਰਦਾ ਹੈ" - }, - "friend_feed_menu_buttons": { - "name": "ਦੋਸਤ ਫੀਡ ਮੀਨੂ ਬਟਨ", - "description": "ਚੁਣੋ ਕਿ ਦੋਸਤ ਫੀਡ ਮੀਨੂ ਵਿੱਚ ਕਿਹੜੇ ਬਟਨ ਦਿਖਾਉਣੇ ਹਨ" - }, - "auto_close_friend_feed_menu": { - "name": "ਆਟੋ-ਬੰਦ ਦੋਸਤ ਫੀਡ ਮੀਨੂ", - "description": "ਇੱਕ ਸੈਟਿੰਗ ਬਟਨ ਦਬਾਉਣ ਤੋਂ ਬਾਅਦ ਦੋਸਤ ਫੀਡ ਮੀਨੂ ਨੂੰ ਆਪਣੇ ਆਪ ਬੰਦ ਕਰ ਦਿੰਦਾ ਹੈ" - }, - "vertical_story_viewer": { - "name": "ਲੰਬਕਾਰੀ ਕਹਾਣੀ ਦਰਸ਼ਕ", - "description": "ਸਾਰੀਆਂ ਕਹਾਣੀਆਂ ਲਈ ਲੰਬਕਾਰੀ ਕਹਾਣੀ ਦਰਸ਼ਕ ਨੂੰ ਸਮਰੱਥ ਬਣਾਉਂਦਾ ਹੈ" - }, - "enable_friend_feed_menu_bar": { - "name": "ਦੋਸਤ ਫੀਡ ਮੀਨੂ ਬਾਰ ਨੂੰ ਸਮਰੱਥ ਕਰੋ", - "description": "ਨਵਾਂ ਦੋਸਤ ਫੀਡ ਮੀਨੂ ਬਾਰ ਨੂੰ ਸਮਰੱਥ ਬਣਾਉਂਦਾ ਹੈ" - }, - "message_indicators": { - "name": "ਸੁਨੇਹਾ ਸੂਚਕ", - "description": "ਸੁਨੇਹਿਆਂ ਵਿੱਚ ਖਾਸ ਸੂਚਕ ਆਈਕਨ ਜੋੜਦਾ ਹੈ।\nਨੋਟ: ਸੂਚਕ 100% ਸਹੀ ਨਹੀਂ ਹੋ ਸਕਦੇ" - }, - "stealth_mode_indicator": { - "name": "ਸਟੀਲਥ ਮੋਡ ਸੂਚਕ", - "description": "ਸਟੀਲਥ ਮੋਡ ਵਿੱਚ ਗੱਲਬਾਤ ਦੇ ਅੱਗੇ ਇੱਕ 👻 ਇਮੋਜੀ ਜੋੜਦਾ ਹੈ" - }, - "edit_text_override": { - "name": "ਟੈਕਸਟ ਓਵਰਰਾਈਡ ਸੰਪਾਦਿਤ ਕਰੋ", - "description": "ਟੈਕਸਟ ਫੀਲਡ ਵਿਵਹਾਰ ਨੂੰ ਓਵਰਰਾਈਡ ਕਰਦਾ ਹੈ" - }, - "prevent_forced_keyboard": { - "name": "ਜਬਰੀ ਕੀਬੋਰਡ ਨੂੰ ਰੋਕੋ", - "description": "ਜਦੋਂ ਤੁਸੀਂ ਇੱਕ ਗੱਲਬਾਤ ਖੋਲ੍ਹਦੇ ਹੋ ਤਾਂ Snapchat ਨੂੰ ਆਪਣੇ ਆਪ ਕੀਬੋਰਡ ਦਿਖਾਉਣ ਤੋਂ ਰੋਕਦਾ ਹੈ" - }, - "settings_menu": { - "name": "ਸੈਟਿੰਗਾਂ ਮੀਨੂ", - "description": "ਤੁਹਾਡੇ ਦੁਆਰਾ PurrfectSnap ਮੀਨੂ ਖੋਲ੍ਹਣ ਦਾ ਤਰੀਕਾ ਬਦਲਦਾ ਹੈ", - "options": { - "default": "ਡਿਫੌਲਟ", - "legacy": "ਪੁਰਾਣਾ" - } - } - } - }, - "messaging": { - "name": "ਮੈਸੇਜਿੰਗ", - "description": "ਬਦਲੋ ਤੁਸੀਂ ਦੋਸਤਾਂ ਨਾਲ ਕਿਵੇਂ ਗੱਲਬਾਤ ਕਰਦੇ ਹੋ", - "properties": { - "bypass_screenshot_detection": { - "name": "ਬਾਈਪਾਸ ਸਕਰੀਨਸ਼ਾਟ ਖੋਜ", - "description": "ਜਦੋਂ ਤੁਸੀਂ ਸਕ੍ਰੀਨਸ਼ਾਟ ਲੈਂਦੇ ਹੋ ਤਾਂ ਸੂਚੀ ਭਰਨ ਤੋਂ ਸਨੈਪਚੈਟ ਨੂੰ ਰੋਕਦਾ ਹੈ" - }, - "anonymous_story_viewing": { - "name": "ਅਗਿਆਤ ਕਹਾਣੀ ਦੇਖ ਰਹੀ ਹੈ", - "description": "ਕਿਸੇ ਨੂੰ ਜਾਣਨ ਤੋਂ ਰੋਕਦਾ ਹੈ ਕਿ ਤੁਸੀਂ ਉਨ੍ਹਾਂ ਦੀ ਕਹਾਣੀ ਵੇਖੀ ਹੈ" - }, - "prevent_story_rewatch_indicator": { - "name": "ਕਹਾਣੀ ਰੀਵਚ ਸੂਚਕ ਨੂੰ ਰੋਕੋ", - "description": "ਕਿਸੇ ਨੂੰ ਜਾਣਨ ਤੋਂ ਰੋਕਦਾ ਹੈ ਕਿ ਤੁਸੀਂ ਉਨ੍ਹਾਂ ਦੀ ਕਹਾਣੀ ਨੂੰ ਦੁਬਾਰਾ ਛਾਪੇ" - }, - "hide_peek_a_peek": { - "name": "ਪੀਕ-ਏ-ਪੇਕ ਨੂੰ ਓਹਲੇ ਕਰੋ", - "description": "ਜਦੋਂ ਤੁਸੀਂ ਅੱਧੀ ਸਵਾਈਪ ਕੀਤੀ ਜਾਂਦੀ ਹੈ ਤਾਂ ਨੋਟੀਫਿਕੇਸ਼ਨ ਨੋਟੀਫਿਕੇਸ਼ਨ ਤੋਂ ਰੋਕਦਾ ਹੈ" - }, - "hide_bitmoji_presence": { - "name": "ਬਿੱਟਮੋਜੀ ਮੌਜੂਦਗੀ ਨੂੰ ਲੁਕਾਓ", - "description": "ਤੁਹਾਡੇ ਬਿੱਟਮੁਜੀ ਨੂੰ ਚੈਟ ਕਰਨ ਵੇਲੇ ਭਟਕਣ ਤੋਂ ਰੋਕਦਾ ਹੈ" - }, - "hide_typing_notifications": { - "name": "ਟਾਈਪਿੰਗ ਸੂਚਨਾਵਾਂ ਲੁਕਾਓ", - "description": "ਕਿਸੇ ਨੂੰ ਵੀ ਇਹ ਜਾਣਨ ਤੋਂ ਰੋਕਦਾ ਹੈ ਕਿ ਤੁਸੀਂ ਕੋਈ ਸੁਨੇਹਾ ਟਾਈਪ ਕਰ ਰਹੇ ਹੋ" - }, - "unlimited_snap_view_time": { - "name": "ਅਸੀਮਤ ਸਨੈਪ ਵੇਖੋ", - "description": "ਤਸਵੀਰਾਂ ਦੇਖਣ ਲਈ ਸਮਾਂ ਸੀਮਾ ਨੂੰ ਦੂਰ ਕਰਦਾ ਹੈ" - }, - "auto_mark_as_read": { - "name": "ਪੜ੍ਹਨ ਦੇ ਤੌਰ ਤੇ ਆਟੋ ਮਾਰਕ", - "description": "ਆਪਣੇ ਆਪ ਸੁਨੇਹੇ / ਸਨੈਪਾਂ ਨੂੰ ਉਦੋਂ ਦੇ ਰੂਪ ਵਿੱਚ ਮਾਰਦਾ ਹੈ ਜਦੋਂ ਕਿ ਸਥਾਪਨਾ ਮੋਡ ਯੋਗ ਹੁੰਦਾ ਹੈ" - }, - "mark_snap_as_seen_button": { - "name": "ਨਿਸ਼ਾਨ ਦੇ ਤੌਰ ਤੇ ਨਿਸ਼ਾਨ ਸਨੈਪ", - "description": "ਜਦੋਂ ਇਹ ਦੇਖਣ ਵੇਲੇ ਵੇਖੇ ਗਏ ਸਨੈਪ ਨੂੰ ਮਾਰਕ ਕਰਨ ਲਈ ਇੱਕ ਬਟਨ ਸ਼ਾਮਲ ਕਰਦਾ ਹੈ.\nਇਹ ਉਦੋਂ ਵੀ ਕੰਮ ਕਰੇਗਾ ਜਦੋਂ ਬਣਾਉਦੀ ਮੋਡ ਸਮਰੱਥ ਹੁੰਦਾ ਹੈ" - }, - "skip_when_marking_as_seen": { - "name": "ਜਦੋਂ ਕਿ ਵੇਖਿਆ ਗਿਆ ਹੋਵੇ ਤਾਂ ਛੱਡੋ", - "description": "ਜਦੋਂ ਕਿ ਵੇਖਿਆ ਗਿਆ ਤਾਂ ਸੂਚਿਆਂ ਦੀ ਨਿਸ਼ਾਨਦੇਹੀ ਕਰਦੇ ਸਮੇਂ ਆਪਣੇ ਆਪ ਹੀ ਅਗਲੇ ਸਨੈਪ ਤੇ ਜਾਓ.\nਡਾਰਕ ਸਨੈਪ ਦੇ ਨਾਲ ਮਿਲਾਪ ਬਟਨ ਦੇ ਨਾਲ ਜੋੜੋ" - }, - "loop_media_playback": { - "name": "ਲੂਪ ਮੀਡੀਆ ਪਲੇਅਬੈਕ", - "description": "SAPS / ਕਹਾਣੀਆਂ ਵੇਖਣ ਵੇਲੇ ਲੂਪਸ ਮੀਡੀਆ ਪਲੇਅਬੈਕ" - }, - "disable_replay_in_ff": { - "name": "ਐੱਫ ਐੱਫ ਵਿੱਚ ਰੀਪਲੇਅ ਨੂੰ ਅਯੋਗ ਕਰੋ", - "description": "ਮਿੱਤਰ ਫੀਡ ਤੋਂ ਲੰਬੇ ਪ੍ਰੈਸ ਨਾਲ ਦੁਬਾਰਾ ਪ੍ਰੈਸ ਚਲਾਉਣ ਦੀ ਯੋਗਤਾ ਨੂੰ ਅਯੋਗ ਕਰਦਾ ਹੈ" - }, - "half_swipe_notifier": { - "name": "ਅੱਧਾ ਸਵਾਈਪ ਨਾਨਫਾਇਰ", - "description": "ਤੁਹਾਨੂੰ ਸੂਚਿਤ ਕਰੋ ਜਦੋਂ ਕੋਈ ਕਿਸੇ ਗੱਲਬਾਤ ਵਿੱਚ ਹੈ", - "properties": { - "min_duration": { - "name": "ਘੱਟੋ ਘੱਟ ਅਵਧੀ", - "description": "ਅੱਧੇ ਸਵਾਈਪ ਦਾ ਘੱਟੋ ਘੱਟ ਅੰਤਰਾਲ (ਸਕਿੰਟਾਂ ਵਿੱਚ)" - }, - "max_duration": { - "name": "ਵੱਧ ਤੋਂ ਵੱਧ ਅਵਧੀ", - "description": "ਅੱਧੇ ਸਵਾਈਪ ਦਾ ਵੱਧ ਤੋਂ ਵੱਧ ਅੰਤਰਾਲ (ਸਕਿੰਟਾਂ ਵਿੱਚ)" - } - } - }, - "call_start_confirmation": { - "name": "ਕਾਲ ਸ਼ੁਰੂ ਪੁਸ਼ਟੀਕਰਣ", - "description": "ਕਾਲ ਸ਼ੁਰੂ ਕਰਨ ਵੇਲੇ ਇੱਕ ਪੁਸ਼ਟੀਕਰਣ ਡਾਇਲਾਗ ਦਿਖਾਉਂਦਾ ਹੈ" - }, - "unlimited_conversation_pinning": { - "name": "ਅਸੀਮਤ ਗੱਲਬਾਤ ਪਿੰਨਿੰਗ", - "description": "ਤੁਹਾਨੂੰ ਸਥਾਨਕ ਤੌਰ 'ਤੇ ਅਸੀਮਿਤ ਗੱਲਬਾਤ ਨੂੰ ਜਾਰੀ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ" - }, - "disable_snap_mode_restrictions": { - "name": "ਸਨੈਪ ਮੋਡ ਪਾਬੰਦੀਆਂ ਨੂੰ ਅਸਮਰੱਥ ਬਣਾਓ", - "description": "ਤੁਹਾਨੂੰ ਪਾਬੰਦੀਆਂ ਤੋਂ ਬਿਨਾਂ ਸਵੈ-ਵਿਨਾਸ਼ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ" - }, - "prevent_message_sending": { - "name": "ਸੁਨੇਹਾ ਭੇਜਣ ਤੋਂ ਰੋਕੋ", - "description": "ਕੁਝ ਕਿਸਮਾਂ ਦੇ ਸੰਦੇਸ਼ ਭੇਜਣ ਤੋਂ ਰੋਕਦਾ ਹੈ" - }, - "friend_mutation_notifier": { - "name": "ਮਿੱਤਰ ਪਰਿਵਰਤਨ ਨੋਟੀਫਾਇਰ", - "description": "ਤੁਹਾਨੂੰ ਸੂਚਿਤ ਕਰਦਾ ਹੈ ਜਦੋਂ ਕਿਸੇ ਦੋਸਤ ਦੇ ਪ੍ਰੋਫਾਈਲ ਵਿੱਚ ਕੁਝ ਬਦਲਦਾ ਹੈ" - }, - "better_notifications": { - "name": "ਬਿਹਤਰ ਸੂਚਨਾਵਾਂ", - "description": "ਪ੍ਰਾਪਤ ਹੋਈਆਂ ਸੂਚਨਾਵਾਂ ਵਿੱਚ ਵਧੇਰੇ ਜਾਣਕਾਰੀ ਸ਼ਾਮਲ ਕਰਦਾ ਹੈ", - "properties": { - "group_notifications": { - "name": "ਸਮੂਹ ਦੀਆਂ ਸੂਚਨਾਵਾਂ", - "description": "ਇੱਕ ਸਿੰਗਲ ਵਿੱਚ ਸਮੂਹ ਦੀਆਂ ਸੂਚਨਾਵਾਂ" - }, - "chat_preview": { - "name": "ਚੈਟ ਸਫ਼ਾ", - "description": "ਨੋਟੀਫਿਕੇਸ਼ਨ ਵਿੱਚ ਪ੍ਰਾਪਤ ਕੀਤੇ ਸੰਦੇਸ਼ਾਂ ਦਾ ਪੂਰਵਦਰਸ਼ਨ ਦਰਸਾਉਂਦਾ ਹੈ" - }, - "media_preview": { - "name": "ਮੀਡੀਆ ਪੂਰਵਦਰਸ਼ਨ", - "description": "ਨੋਟੀਫਿਕੇਸ਼ਨ ਵਿੱਚ ਚੁਣੀਆਂ ਗਈਆਂ ਮੀਡੀਆ ਕਿਸਮਾਂ ਦਾ ਪੂਰਵ ਦਰਸ਼ਨ ਦਰਸਾਉਂਦਾ ਹੈ" - }, - "media_caption": { - "name": "ਮੀਡੀਆ ਸੁਰਖੀ", - "description": "ਨੋਟੀਫਿਕੇਸ਼ਨ ਵਿੱਚ ਮੀਡੀਆ ਦੀ ਨਾਲ ਜੁੜਿਆ ਕੈਪਸ਼ਨ ਨੂੰ ਦਰਸਾਉਂਦਾ ਹੈ" - }, - "stacked_media_messages": { - "name": "ਸਟੈਕਡ ਮੀਡੀਆ ਸੁਨੇਹੇ", - "description": "ਮਲਟੀਪਲ ਮੀਡੀਆ ਸੁਨੇਹਿਆਂ ਨੂੰ ਇੱਕ ਟੈਕਸਟ ਸੂਚਨਾ ਵਿੱਚ ਜੋੜਦਾ ਹੈ ਜਦੋਂ ਉਹਨਾਂ ਦਾ ਪੂਰਵਦਰਸ਼ਨ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਦਾ. ਚੈਟ ਪੂਰਵ ਦਰਸ਼ਨ ਦੇ ਨਾਲ ਜੋੜ ਕੇ ਵਰਤੋ" - }, - "friend_add_source": { - "name": "ਦੋਸਤੋ ਸਰੋਤ ਸ਼ਾਮਲ ਕਰੋ", - "description": "ਨੋਟੀਫਿਕੇਸ਼ਨ ਵਿੱਚ ਇੱਕ ਦੋਸਤ ਬੇਨਤੀ ਦਾ ਸਰੋਤ ਦਰਸਾਉਂਦਾ ਹੈ" - }, - "reply_button": { - "name": "ਜਵਾਬ ਬਟਨ", - "description": "ਨੋਟੀਫਿਕੇਸ਼ਨ ਲਈ ਜਵਾਬ ਬਟਨ ਸ਼ਾਮਲ ਕਰਦਾ ਹੈ" - }, - "smart_replies": { - "name": "ਸਮਾਰਟ ਜਵਾਬ", - "description": "ਸੂਚਨਾਵਾਂ (ਐਂਡਰਾਇਡ 10+) ਨੂੰ ਸੁਝਾਏ ਜਵਾਬ ਜੋੜਦਾ ਹੈ. ਜਵਾਬ ਬਟਨ ਦੇ ਨਾਲ ਜੋੜ ਕੇ ਵਰਤੋ" - }, - "download_button": { - "name": "ਡਾਉਨਲੋਡ ਬਟਨ", - "description": "ਤੁਹਾਨੂੰ ਨੋਟੀਫਿਕੇਸ਼ਨ ਤੋਂ ਮੀਡੀਆ ਨੂੰ ਡਾ download ਨਲੋਡ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ" - }, - "mark_as_read_button": { - "name": "ਪੜ੍ਹਨ ਵਾਲੇ ਬਟਨ ਵਜੋਂ ਮਾਰਕ ਕਰੋ", - "description": "ਤੁਹਾਨੂੰ ਨੋਟੀਫਿਕੇਸ਼ਨ ਤੋਂ ਪੜ੍ਹਨ ਦੇ ਰੂਪ ਵਿੱਚ ਇੱਕ ਸੁਨੇਹਾ ਮਾਰਕ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ" - }, - "mark_as_read_and_save_in_chat": { - "name": "ਪੜ੍ਹੋ ਅਤੇ ਗੱਲਬਾਤ ਵਿੱਚ ਸੇਵ ਕਰੋ", - "description": "ਨੋਟੀਫਿਕੇਸ਼ਨ ਵਿੱਚ ਚੈਟ ਬਟਨ ਨੂੰ ਪੜ੍ਹਨ ਅਤੇ ਬਚਾਉਣ ਦੇ ਤੌਰ ਤੇ ਮਾਰਕ ਸ਼ਾਮਲ ਕਰਦਾ ਹੈ" - } - } - }, - "notification_blacklist": { - "name": "ਸੂਚਨਾ ਬਲੈਕਲਿਸਟ", - "description": "ਨੋਟੀਫਿਕੇਸ਼ਨ ਚੁਣੋ ਜੋ ਬਲੌਕ ਹੋ ਜਾਣ" - }, - "message_logger": { - "name": "ਸੁਨੇਹਾ ਲਾਗਰ", - "description": "ਸੁਨੇਹੇ ਨੂੰ ਮਿਟਾਉਣ ਤੋਂ ਰੋਕਦਾ ਹੈ", - "properties": { - "keep_my_own_messages": { - "name": "ਮੇਰੇ ਆਪਣੇ ਸੁਨੇਹੇ ਰੱਖੋ", - "description": "ਤੁਹਾਡੇ ਆਪਣੇ ਸੰਦੇਸ਼ਾਂ ਨੂੰ ਮਿਟਾਉਣ ਤੋਂ ਰੋਕਦਾ ਹੈ" - }, - "auto_purge": { - "name": "ਆਟੋ ਸ਼ੁੱਧ", - "description": "ਆਪਣੇ ਆਪ ਹੀ ਕੈਸ਼ ਕੀਤੇ ਸੰਦੇਸ਼ਾਂ ਨੂੰ ਮਿਟਾਉਂਦਾ ਹੈ ਜੋ ਨਿਰਧਾਰਤ ਸਮੇਂ ਤੋਂ ਪੁਰਾਣੇ ਹਨ" - }, - "message_filter": { - "name": "ਸੁਨੇਹਾ ਫਿਲਟਰ", - "description": "ਚੁਣੋ ਕਿ ਕਿਹੜੇ ਸੁਨੇਹਿਆਂ ਨੂੰ ਲੌਗਇਨ ਹੋਣਾ ਚਾਹੀਦਾ ਹੈ (ਸਾਰੇ ਸੁਨੇਹਿਆਂ ਲਈ ਖਾਲੀ)" - }, - "deleted_message_color": { - "name": "ਮਿਟਾ ਦਿੱਤਾ ਸੁਨੇਹਾ ਰੰਗ", - "description": "ਮਿਟਾਏ ਗਏ ਸੁਨੇਹਿਆਂ ਦਾ ਰੰਗ ਨਿਰਧਾਰਤ ਕਰਦਾ ਹੈ" - } - } - }, - "auto_save_messages_in_conversations": { - "name": "ਆਟੋ ਸੇਵ ਸੁਨੇਹੇ", - "description": "ਹਰ ਸੁਨੇਹੇ ਨੂੰ ਗੱਲਬਾਤ ਵਿੱਚ ਆਪਣੇ ਆਪ ਬਚ ਜਾਂਦਾ ਹੈ" - }, - "gallery_media_send_override": { - "name": "ਗੈਲਰੀ ਮੀਡੀਆ ਓਵਰਰਾਈਡ ਭੇਜਦਾ ਹੈ", - "description": "ਗੈਲਰੀ ਤੋਂ ਭੇਜਣ ਵੇਲੇ ਮੀਡੀਆ ਸਰੋਤ ਨੂੰ ਸਪੋਰਟ ਕਰਦਾ ਹੈ" - }, - "strip_media_metadata": { - "name": "ਸਟ੍ਰਿਪ ਮੀਡੀਆ ਮੈਟਾਡਾਟਾ", - "description": "ਇੱਕ ਸੁਨੇਹਾ ਭੇਜਣ ਤੋਂ ਪਹਿਲਾਂ ਮੀਡੀਆ ਦਾ ਮੈਟਾਡੇਟਾ ਹਟਾਓ" - }, - "bypass_message_retention_policy": { - "name": "ਬਾਈਪਾਸ ਸੁਨੇਹਾ ਧਾਰਨ ਨੀਤੀ", - "description": "ਸੰਦੇਸ਼ਾਂ ਨੂੰ ਵੇਖਣ ਤੋਂ ਬਾਅਦ ਸੁਨੇਹੇ ਨੂੰ ਮਿਟਾਉਣ ਤੋਂ ਰੋਕਦਾ ਹੈ" - }, - "bypass_message_action_restrictions": { - "name": "ਬਾਈਪਾਸ ਮੈਸੇਜ ਐਕਸ਼ਨ ਪਾਬੰਦੀਆਂ", - "description": "ਤੁਹਾਨੂੰ ਇਸ ਨੂੰ ਖੋਲ੍ਹਿਆ ਜਾਂ ਬੇਲੋੜੀ ਸੰਦੇਸ਼ ਨੂੰ ਬਚਾਉਣ ਤੋਂ ਬਿਨਾਂ ਤੁਹਾਨੂੰ ਇੱਕ ਸਨੈਪ ਤੇ ਪ੍ਰਤੀਕ੍ਰਿਆ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ" - }, - "remove_groups_locked_status": { - "name": "ਸਮੂਹਾਂ ਨੂੰ ਬੰਦ ਸਥਿਤੀ ਹਟਾਓ", - "description": "ਤੁਹਾਨੂੰ ਲੱਤ ਮਾਰਨ ਤੋਂ ਬਾਅਦ ਸਮੂਹ ਜਾਣਕਾਰੀ ਨੂੰ ਵੇਖਣ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ" - }, - "double_tap_chat_action": { - "name": "ਟੈਪ ਚੈਟ ਕਾਰਵਾਈ", - "description": "ਜਦੋਂ ਗੱਲਬਾਤ ਵਿੱਚ ਸੁਨੇਹਾ ਭੇਜਦਾ ਹੈ ਤਾਂ ਇੱਕ ਕਸਟਮ ਕਾਰਵਾਈ ਕਰਦਾ ਹੈ" - }, - "double_tap_chat_action_custom_emoji": { - "name": "ਟੈਪ ਚੈਟ ਐਕਸ਼ਨ ਕਸਟਮ ਇਮੋਜੀ ਪ੍ਰਤੀਕ੍ਰਿਆ", - "description": "ਡਬਲ ਟੈਪ ਚੈਟ ਕਾਰਵਾਈ ਲਈ ਇੱਕ ਕਸਟਮ ਇਮੋਜੀ ਪ੍ਰਤੀਕ੍ਰਿਆ ਨਿਰਧਾਰਤ ਕਰਦਾ ਹੈ" - } - } - }, - "global": { - "name": "ਗਲੋਬਲ", - "description": "ਗਲੋਬਲ Snapchat ਸੈਟਿੰਗਾਂ ਨੂੰ ਟਵੀਕ ਕਰੋ", - "properties": { - "better_location": { - "name": "ਬਿਹਤਰ ਸਥਾਨ", - "description": "Snapchat ਦੀ ਸਥਿਤੀ ਨੂੰ ਵਧਾਉਂਦਾ ਹੈ", - "properties": { - "spoof_location": { - "name": "ਸਥਾਨ ਸਪੂਫ ਕਰੋ", - "description": "ਤੁਹਾਡੀ ਸਥਿਤੀ ਨੂੰ ਇੱਕ ਨਿਸ਼ਚਿਤ ਸਥਾਨ 'ਤੇ ਸਪੂਫ ਕਰਦਾ ਹੈ" - }, - "coordinates": { - "name": "ਕੋਆਰਡੀਨੇਟ", - "description": "ਸਪੂਫ ਕੀਤੇ ਸਥਾਨ ਦੇ ਕੋਆਰਡੀਨੇਟ ਸੈੱਟ ਕਰੋ" - }, - "walk_radius": { - "name": "ਵਾਕ ਰੇਡੀਅਸ", - "description": "ਇਸ ਰੇਡੀਅਸ (ਫੁੱਟ) ਦੇ ਅੰਦਰ ਬੇਤਰਤੀਬੇ ਘੁੰਮੋ" - }, - "always_update_location": { - "name": "ਹਮੇਸ਼ਾ ਸਥਾਨ ਅੱਪਡੇਟ ਕਰੋ", - "description": "Snapchat ਨੂੰ ਸਥਾਨ ਅੱਪਡੇਟ ਕਰਨ ਲਈ ਮਜਬੂਰ ਕਰੋ ਭਾਵੇਂ ਕੋਈ GPS ਡਾਟਾ ਪ੍ਰਾਪਤ ਨਾ ਹੋਵੇ" - }, - "suspend_location_updates": { - "name": "ਸਥਾਨ ਅੱਪਡੇਟ ਨੂੰ ਮੁਅੱਤਲ ਕਰੋ", - "description": "ਤੁਹਾਡੀ ਸਥਿਤੀ ਨੂੰ ਅੱਪਡੇਟ ਹੋਣ ਤੋਂ ਰੋਕਦਾ ਹੈ" - }, - "spoof_battery_level": { - "name": "ਬੈਟਰੀ ਪੱਧਰ ਸਪੂਫ ਕਰੋ", - "description": "ਨਕਸ਼ੇ 'ਤੇ ਤੁਹਾਡੀ ਡਿਵਾਈਸ ਦੇ ਬੈਟਰੀ ਪੱਧਰ ਨੂੰ ਸਪੂਫ ਕਰਦਾ ਹੈ।\nਮੁੱਲ 0 ਅਤੇ 100 ਦੇ ਵਿਚਕਾਰ ਹੋਣਾ ਚਾਹੀਦਾ ਹੈ" - }, - "spoof_headphones": { - "name": "ਹੈੱਡਫੋਨ ਸਪੂਫ ਕਰੋ", - "description": "ਨਕਸ਼ੇ 'ਤੇ ਸੰਗੀਤ ਸੁਣਨ ਦੀ ਸਥਿਤੀ ਨੂੰ ਸਪੂਫ ਕਰਦਾ ਹੈ" - }, - "show_battery_level": { - "name": "ਬੈਟਰੀ ਪੱਧਰ ਦਿਖਾਓ", - "description": "ਨਕਸ਼ੇ 'ਤੇ ਤੁਹਾਡੇ ਦੋਸਤਾਂ ਦਾ ਬੈਟਰੀ ਪੱਧਰ ਦਿਖਾਉਂਦਾ ਹੈ" - } - } - }, - "snapchat_plus": { - "name": "Snapchat+", - "description": "Snapchat+ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਨੂੰ ਸਮਰੱਥ ਬਣਾਉਂਦਾ ਹੈ।\nਕੁਝ ਸਰਵਰ-ਸਾਈਡ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਕੰਮ ਨਹੀਂ ਕਰ ਸਕਦੀਆਂ" - }, - "media_upload_quality": { - "name": "ਮੀਡੀਆ ਅੱਪਲੋਡ ਗੁਣਵੱਤਾ", - "description": "ਮੀਡੀਆ ਅੱਪਲੋਡ ਗੁਣਵੱਤਾ ਨੂੰ ਓਵਰਰਾਈਡ ਕਰਦਾ ਹੈ", - "properties": { - "force_video_upload_source_quality": { - "name": "ਵੀਡੀਓ ਅੱਪਲੋਡ ਸਰੋਤ ਗੁਣਵੱਤਾ ਨੂੰ ਮਜਬੂਰ ਕਰੋ", - "description": "ਵੀਡੀਓ ਅੱਪਲੋਡ ਕਰਨ ਵੇਲੇ ਸਰੋਤ ਗੁਣਵੱਤਾ ਦੀ ਵਰਤੋਂ ਕਰਨ ਲਈ Snapchat ਨੂੰ ਮਜਬੂਰ ਕਰਦਾ ਹੈ।\nਕਿਰਪਾ ਕਰਕੇ ਨੋਟ ਕਰੋ ਕਿ ਇਹ ਮੀਡੀਆ ਤੋਂ ਮੈਟਾਡੇਟਾ ਨਹੀਂ ਹਟਾ ਸਕਦਾ" - }, - "disable_image_compression": { - "name": "ਚਿੱਤਰ ਕੰਪਰੈਸ਼ਨ ਨੂੰ ਅਯੋਗ ਕਰੋ", - "description": "ਮੀਡੀਆ ਅੱਪਲੋਡ ਕਰਨ ਵੇਲੇ ਚਿੱਤਰ ਕੰਪਰੈਸ਼ਨ ਨੂੰ ਅਯੋਗ ਕਰਦਾ ਹੈ" - }, - "custom_image_upload_format": { - "name": "ਕਸਟਮ ਚਿੱਤਰ ਅੱਪਲੋਡ ਫਾਰਮੈਟ", - "description": "ਇੱਕ ਕਸਟਮ ਚਿੱਤਰ ਅੱਪਲੋਡ ਫਾਰਮੈਟ ਸੈੱਟ ਕਰਦਾ ਹੈ।\nਵਧੀਆ ਗੁਣਵੱਤਾ ਲਈ ਇੱਕ ਨੁਕਸਾਨ ਰਹਿਤ ਫਾਰਮੈਟ (ਜਿਵੇਂ ਕਿ PNG) ਚੁਣੋ" - } - } - }, - "disable_confirmation_dialogs": { - "name": "ਪੁਸ਼ਟੀਕਰਨ ਡਾਇਲਾਗ ਨੂੰ ਅਯੋਗ ਕਰੋ", - "description": "ਚੁਣੀਆਂ ਗਈਆਂ ਕਾਰਵਾਈਆਂ ਦੀ ਆਪਣੇ ਆਪ ਪੁਸ਼ਟੀ ਕਰਦਾ ਹੈ" - }, - "auto_updater": { - "name": "ਆਟੋ ਅੱਪਡੇਟਰ", - "description": "ਨਵੇਂ ਅੱਪਡੇਟ ਲਈ ਆਪਣੇ ਆਪ ਜਾਂਚ ਕਰਦਾ ਹੈ" - }, - "disable_metrics": { - "name": "ਮੀਟ੍ਰਿਕਸ ਨੂੰ ਅਯੋਗ ਕਰੋ", - "description": "Snapchat ਨੂੰ ਖਾਸ ਵਿਸ਼ਲੇਸ਼ਣ ਡਾਟਾ ਭੇਜਣ ਤੋਂ ਰੋਕਦਾ ਹੈ" - }, - "disable_story_sections": { - "name": "ਕਹਾਣੀ ਭਾਗਾਂ ਨੂੰ ਅਯੋਗ ਕਰੋ", - "description": "ਕਹਾਣੀਆਂ ਪੰਨੇ ਤੋਂ ਭਾਗਾਂ ਨੂੰ ਹਟਾਉਂਦਾ ਹੈ।\nਸਹੀ ਢੰਗ ਨਾਲ ਕੰਮ ਕਰਨ ਲਈ ਇੱਕ ਤਾਜ਼ਗੀ ਦੀ ਲੋੜ ਹੋ ਸਕਦੀ ਹੈ" - }, - "block_ads": { - "name": "ਇਸ਼ਤਿਹਾਰਾਂ ਨੂੰ ਬਲੌਕ ਕਰੋ", - "description": "ਇਸ਼ਤਿਹਾਰਾਂ ਨੂੰ ਪ੍ਰਦਰਸ਼ਿਤ ਹੋਣ ਤੋਂ ਰੋਕਦਾ ਹੈ" - }, - "disable_custom_tabs": { - "name": "ਕਸਟਮ ਟੈਬਾਂ ਨੂੰ ਅਯੋਗ ਕਰੋ", - "description": "ਵੈੱਬ ਬ੍ਰਾਊਜ਼ਰ ਦੀ ਬਜਾਏ ਸਮਰਥਿਤ ਐਪਲੀਕੇਸ਼ਨਾਂ ਵਿੱਚ ਲਿੰਕ ਖੋਲ੍ਹਦਾ ਹੈ" - }, - "disable_permission_requests": { - "name": "ਇਜਾਜ਼ਤ ਬੇਨਤੀਆਂ ਨੂੰ ਅਯੋਗ ਕਰੋ", - "description": "Snapchat ਨੂੰ ਖਾਸ ਇਜਾਜ਼ਤਾਂ ਮੰਗਣ ਤੋਂ ਰੋਕਦਾ ਹੈ" - }, - "disable_memories_snap_feed": { - "name": "ਯਾਦਾਂ ਸਨੈਪ ਫੀਡ ਨੂੰ ਅਯੋਗ ਕਰੋ", - "description": "ਜਦੋਂ ਤੁਸੀਂ ਕੈਮਰੇ ਵਿੱਚ ਸਵਾਈਪ ਕਰਦੇ ਹੋ ਤਾਂ Snapchat ਨੂੰ ਹਾਲੀਆ ਯਾਦਾਂ ਦਿਖਾਉਣ ਤੋਂ ਰੋਕਦਾ ਹੈ" - }, - "spotlight_comments_username": { - "name": "ਸਪੌਟਲਾਈਟ ਟਿੱਪਣੀਆਂ ਉਪਭੋਗਤਾ ਨਾਮ", - "description": "ਸਪੌਟਲਾਈਟ ਟਿੱਪਣੀਆਂ ਵਿੱਚ ਲੇਖਕ ਦਾ ਉਪਭੋਗਤਾ ਨਾਮ ਦਿਖਾਉਂਦਾ ਹੈ" - }, - "bypass_video_length_restriction": { - "name": "ਵੀਡੀਓ ਲੰਬਾਈ ਪਾਬੰਦੀ ਨੂੰ ਬਾਈਪਾਸ ਕਰੋ", - "description": "ਸਿੰਗਲ: ਇੱਕ ਵੀਡੀਓ ਭੇਜਦਾ ਹੈ।\nਸਪਲਿਟ: ਸੰਪਾਦਨ ਤੋਂ ਬਾਅਦ ਵੀਡੀਓ ਨੂੰ ਵੰਡਦਾ ਹੈ" - }, - "default_video_playback_rate": { - "name": "ਡਿਫੌਲਟ ਵੀਡੀਓ ਪਲੇਬੈਕ ਦਰ", - "description": "ਵੀਡੀਓ ਪਲੇਬੈਕ ਲਈ ਡਿਫੌਲਟ ਗਤੀ ਸੈੱਟ ਕਰਦਾ ਹੈ।\nਮੁੱਲ 0.1 ਅਤੇ 4.0 ਦੇ ਵਿਚਕਾਰ ਹੋਣਾ ਚਾਹੀਦਾ ਹੈ" - }, - "video_playback_rate_slider": { - "name": "ਵੀਡੀਓ ਪਲੇਬੈਕ ਦਰ ਸਲਾਈਡਰ", - "description": "ਵੀਡੀਓ ਪਲੇਬੈਕ ਦਰ ਨੂੰ ਬਦਲਣ ਲਈ ਓਪੇਰਾ ਪ੍ਰਸੰਗ ਮੀਨੂ ਵਿੱਚ ਇੱਕ ਸਲਾਈਡਰ ਜੋੜਦਾ ਹੈ।\nਨੋਟ: ਤਬਦੀਲੀਆਂ ਸਿਰਫ਼ ਬਾਅਦ ਦੀਆਂ ਵੀਡੀਓਜ਼ 'ਤੇ ਲਾਗੂ ਹੁੰਦੀਆਂ ਹਨ" - }, - "disable_google_play_dialogs": { - "name": "ਗੂਗਲ ਪਲੇ ਸੇਵਾਵਾਂ ਡਾਇਲਾਗ ਨੂੰ ਅਯੋਗ ਕਰੋ", - "description": "ਗੂਗਲ ਪਲੇ ਸੇਵਾਵਾਂ ਦੀ ਉਪਲਬਧਤਾ ਡਾਇਲਾਗ ਨੂੰ ਦਿਖਾਈ ਦੇਣ ਤੋਂ ਰੋਕੋ" - }, - "default_volume_controls": { - "name": "ਡਿਫੌਲਟ ਵਾਲੀਅਮ ਕੰਟਰੋਲ", - "description": "Snapchat ਨੂੰ ਸਿਸਟਮ ਵਾਲੀਅਮ ਕੰਟਰੋਲ ਦੀ ਵਰਤੋਂ ਕਰਨ ਲਈ ਮਜਬੂਰ ਕਰਦਾ ਹੈ" - }, - "disable_telecom_framework": { - "name": "ਟੈਲੀਕਾਮ ਫਰੇਮਵਰਕ ਨੂੰ ਅਯੋਗ ਕਰੋ", - "description": "Snapchat ਨੂੰ ਐਂਡਰਾਇਡ ਟੈਲੀਕਾਮ ਫਰੇਮਵਰਕ ਦੀ ਵਰਤੋਂ ਕਰਨ ਤੋਂ ਰੋਕਦਾ ਹੈ।\nਇਹ ਤੁਹਾਨੂੰ ਇੱਕ ਕਾਲ 'ਤੇ ਹੋਣ ਵੇਲੇ ਸੰਗੀਤ ਸੁਣਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ" - }, - "hide_active_music": { - "name": "ਕਿਰਿਆਸ਼ੀਲ ਸੰਗੀਤ ਲੁਕਾਓ", - "description": "Snapchat ਨੂੰ ਇਹ ਜਾਣਨ ਤੋਂ ਰੋਕਦਾ ਹੈ ਕਿ ਤੁਸੀਂ ਸੰਗੀਤ ਸੁਣ ਰਹੇ ਹੋ।\nਇਹ ਤੁਹਾਨੂੰ ਸੰਗੀਤ ਸੁਣਨ ਵੇਲੇ ਵਾਲੀਅਮ ਕੰਟਰੋਲ ਬਟਨਾਂ ਦੀ ਵਰਤੋਂ ਕਰਕੇ ਸਨੈਪ ਲੈਣ ਦੇਵੇਗਾ" - }, - "disable_snap_splitting": { - "name": "ਸਨੈਪ ਸਪਲਿਟਿੰਗ ਨੂੰ ਅਯੋਗ ਕਰੋ", - "description": "ਸਨੈਪਸ ਨੂੰ ਕਈ ਹਿੱਸਿਆਂ ਵਿੱਚ ਵੰਡਣ ਤੋਂ ਰੋਕਦਾ ਹੈ।\nਜੋ ਤਸਵੀਰਾਂ ਤੁਸੀਂ ਭੇਜਦੇ ਹੋ ਉਹ ਵੀਡੀਓ ਵਿੱਚ ਬਦਲ ਜਾਣਗੀਆਂ" - } - } - }, - "rules": { - "name": "ਨਿਯਮ", - "description": "ਵਿਅਕਤੀਗਤ ਲੋਕਾਂ ਲਈ ਸਵੈਚਲਿਤ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਦਾ ਪ੍ਰਬੰਧਨ ਕਰੋ" - }, - "camera": { - "name": "ਕੈਮਰਾ", - "description": "ਸੰਪੂਰਨ ਸਨੈਪ ਲਈ ਸਹੀ ਸੈਟਿੰਗਾਂ ਨੂੰ ਵਿਵਸਥਿਤ ਕਰੋ", - "properties": { - "disable_cameras": { - "name": "ਕੈਮਰੇ ਅਯੋਗ ਕਰੋ", - "description": "ਚੁਣੇ ਗਏ ਕੈਮਰੇ ਦੀ ਵਰਤੋਂ ਕਰਨ ਤੋਂ Snapchat ਨੂੰ ਰੋਕਦਾ ਹੈ" - }, - "black_photos": { - "name": "ਕਾਲੀਆਂ ਫੋਟੋਆਂ", - "description": "ਕੈਪਚਰ ਕੀਤੀਆਂ ਫੋਟੋਆਂ ਨੂੰ ਕਾਲੇ ਪਿਛੋਕੜ ਨਾਲ ਬਦਲ ਦਿੰਦਾ ਹੈ।\nਵੀਡੀਓ ਪ੍ਰਭਾਵਿਤ ਨਹੀਂ ਹੁੰਦੇ" - }, - "immersive_camera_preview": { - "name": "ਇਮਰਸਿਵ ਕੈਮਰਾ ਪੂਰਵਦਰਸ਼ਨ", - "description": "ਕੈਮਰਾ ਪੂਰਵਦਰਸ਼ਨ ਨੂੰ ਕੱਟਣ ਤੋਂ Snapchat ਨੂੰ ਰੋਕਦਾ ਹੈ।\nਇਹ ਕੁਝ ਡਿਵਾਈਸਾਂ 'ਤੇ ਕੈਮਰੇ ਨੂੰ ਫਲਿੱਕਰ ਕਰ ਸਕਦਾ ਹੈ" - }, - "override_front_resolution": { - "name": "ਫਰੰਟ ਰੈਜ਼ੋਲਿਊਸ਼ਨ ਨੂੰ ਓਵਰਰਾਈਡ ਕਰੋ", - "description": "ਫਰੰਟ ਕੈਮਰੇ ਲਈ ਕੈਮਰਾ ਰੈਜ਼ੋਲਿਊਸ਼ਨ ਨੂੰ ਓਵਰਰਾਈਡ ਕਰਦਾ ਹੈ" - }, - "override_back_resolution": { - "name": "ਬੈਕ ਰੈਜ਼ੋਲਿਊਸ਼ਨ ਨੂੰ ਓਵਰਰਾਈਡ ਕਰੋ", - "description": "ਬੈਕ ਕੈਮਰੇ ਲਈ ਕੈਮਰਾ ਰੈਜ਼ੋਲਿਊਸ਼ਨ ਨੂੰ ਓਵਰਰਾਈਡ ਕਰਦਾ ਹੈ" - }, - "custom_resolution": { - "name": "ਕਸਟਮ ਰੈਜ਼ੋਲਿਊਸ਼ਨ", - "description": "ਇੱਕ ਕਸਟਮ ਕੈਮਰਾ ਰੈਜ਼ੋਲਿਊਸ਼ਨ, ਚੌੜਾਈ x ਉਚਾਈ (ਜਿਵੇਂ 1920x1080) ਨਿਸ਼ਚਿਤ ਕਰਦਾ ਹੈ।\nਕਸਟਮ ਰੈਜ਼ੋਲਿਊਸ਼ਨ ਤੁਹਾਡੀ ਡਿਵਾਈਸ ਦੁਆਰਾ ਸਮਰਥਿਤ ਹੋਣਾ ਚਾਹੀਦਾ ਹੈ" - }, - "front_custom_frame_rate": { - "name": "ਫਰੰਟ ਕਸਟਮ ਫਰੇਮ ਦਰ", - "description": "ਫਰੰਟ ਕੈਮਰਾ ਫਰੇਮ ਦਰ ਨੂੰ ਓਵਰਰਾਈਡ ਕਰਦਾ ਹੈ" - }, - "back_custom_frame_rate": { - "name": "ਬੈਕ ਕਸਟਮ ਫਰੇਮ ਦਰ", - "description": "ਬੈਕ ਕੈਮਰਾ ਫਰੇਮ ਦਰ ਨੂੰ ਓਵਰਰਾਈਡ ਕਰਦਾ ਹੈ" - }, - "force_camera_source_encoding": { - "name": "ਕੈਮਰਾ ਸਰੋਤ ਏਨਕੋਡਿੰਗ ਨੂੰ ਮਜਬੂਰ ਕਰੋ", - "description": "ਕੈਮਰਾ ਸਰੋਤ ਏਨਕੋਡਿੰਗ ਨੂੰ ਮਜਬੂਰ ਕਰਦਾ ਹੈ" - }, - "startup_default_camera": { - "name": "ਸ਼ੁਰੂਆਤੀ ਡਿਫੌਲਟ ਕੈਮਰਾ", - "description": "Snapchat ਖੋਲ੍ਹਣ ਵੇਲੇ ਡਿਫੌਲਟ ਕੈਮਰਾ ਸੈੱਟ ਕਰਦਾ ਹੈ" - }, - "hevc_recording": { - "name": "HEVC ਰਿਕਾਰਡਿੰਗ", - "description": "ਵੀਡੀਓ ਰਿਕਾਰਡਿੰਗ ਲਈ HEVC (H.265) ਕੋਡੇਕ ਦੀ ਵਰਤੋਂ ਕਰਦਾ ਹੈ" - } - } - }, - "streaks_reminder": { - "name": "ਸਟ੍ਰੀਕਸ ਰੀਮਾਈਂਡਰ", - "description": "ਸਮੇਂ-ਸਮੇਂ 'ਤੇ ਤੁਹਾਨੂੰ ਤੁਹਾਡੀਆਂ ਸਟ੍ਰੀਕਸ ਬਾਰੇ ਸੂਚਿਤ ਕਰਦਾ ਹੈ", - "properties": { - "interval": { - "name": "ਅੰਤਰਾਲ", - "description": "ਹਰੇਕ ਰੀਮਾਈਂਡਰ (ਘੰਟਿਆਂ ਵਿੱਚ) ਵਿਚਕਾਰ ਅੰਤਰਾਲ" - }, - "remaining_hours": { - "name": "ਬਾਕੀ ਘੰਟੇ", - "description": "ਸੂਚਨਾ ਦਿਖਾਏ ਜਾਣ ਤੋਂ ਪਹਿਲਾਂ ਬਾਕੀ ਘੰਟੇ" - }, - "group_notifications": { - "name": "ਸਮੂਹ ਸੂਚਨਾਵਾਂ", - "description": "ਸਮੂਹ ਸੂਚਨਾਵਾਂ ਨੂੰ ਇੱਕ ਵਿੱਚ" - } - } - }, - "experimental": { - "name": "ਪ੍ਰਯੋਗਾਤਮਕ", - "description": "ਪ੍ਰਯੋਗਾਤਮਕ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ", - "properties": { - "native_hooks": { - "name": "ਨੇਟਿਵ ਹੁੱਕ", - "description": "ਅਸੁਰੱਖਿਅਤ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਜੋ Snapchat ਦੇ ਨੇਟਿਵ ਕੋਡ ਵਿੱਚ ਹੁੱਕ ਕਰਦੀਆਂ ਹਨ", - "properties": { - "composer_hooks": { - "name": "ਕੰਪੋਜ਼ਰ ਹੁੱਕ", - "description": "ਕੰਪੋਜ਼ਰ ਕ੍ਰਾਸ-ਪਲੇਟਫਾਰਮ UI ਫਰੇਮਵਰਕ ਵਿੱਚ ਕੋਡ ਇੰਜੈਕਟ ਕਰਦਾ ਹੈ", - "properties": { - "show_first_created_username": { - "name": "ਪਹਿਲਾਂ ਬਣਾਇਆ ਗਿਆ ਉਪਭੋਗਤਾ ਨਾਮ ਦਿਖਾਓ", - "description": "ਪ੍ਰੋਫਾਈਲ ਪੰਨੇ ਵਿੱਚ ਮੌਜੂਦਾ ਉਪਭੋਗਤਾ ਨਾਮ ਦੇ ਅੱਗੇ ਪਹਿਲਾਂ ਬਣਾਇਆ ਗਿਆ ਉਪਭੋਗਤਾ ਨਾਮ ਦਿਖਾਉਂਦਾ ਹੈ" - }, - "bypass_camera_roll_limit": { - "name": "ਕੈਮਰਾ ਰੋਲ ਸੀਮਾ ਨੂੰ ਬਾਈਪਾਸ ਕਰੋ", - "description": "ਤੁਹਾਡੇ ਦੁਆਰਾ ਕੈਮਰਾ ਰੋਲ ਤੋਂ ਭੇਜੇ ਜਾ ਸਕਣ ਵਾਲੇ ਮੀਡੀਆ ਦੀ ਵੱਧ ਤੋਂ ਵੱਧ ਮਾਤਰਾ ਨੂੰ ਵਧਾਉਂਦਾ ਹੈ" - }, - "custom_self_destruct_snap_delay": { - "name": "ਕਸਟਮ ਸਵੈ-ਵਿਨਾਸ਼ ਸਨੈਪ ਦੇਰੀ", - "description": "ਇੱਕ ਸਨੈਪ ਭੇਜਣ ਵੇਲੇ ਸਵੈ-ਵਿਨਾਸ਼ ਟਾਈਮਰ ਲਈ ਹੋਰ ਵਿਕਲਪ ਦਿੰਦਾ ਹੈ" - }, - "composer_console": { - "name": "ਕੰਪੋਜ਼ਰ ਕੰਸੋਲ", - "description": "ਤੁਹਾਨੂੰ ਕੰਪੋਜ਼ਰ ਵਿੱਚ JavaScript ਕੋਡ ਚਲਾਉਣ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ (ਸਿਰਫ਼ arm64)" - }, - "composer_logs": { - "name": "ਕੰਪੋਜ਼ਰ ਲੌਗਸ", - "description": "ਕੰਪੋਜ਼ਰ ਦੇ ਕੰਸੋਲ ਲੌਗਸ ਨੂੰ PurrfectSnap 'ਤੇ ਰੀਡਾਇਰੈਕਟ ਕਰਦਾ ਹੈ" - } - } - }, - "disable_bitmoji": { - "name": "Bitmoji ਨੂੰ ਅਯੋਗ ਕਰੋ", - "description": "ਦੋਸਤ ਪ੍ਰੋਫਾਈਲ Bitmoji ਨੂੰ ਅਯੋਗ ਕਰਦਾ ਹੈ" - }, - "custom_emoji_font": { - "name": "ਕਸਟਮ ਇਮੋਜੀ ਫੌਂਟ", - "description": "ਤੁਹਾਨੂੰ ਇੱਕ ਕਸਟਮ ਇਮੋਜੀ ਫੌਂਟ ਵਰਤਣ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ। ਸਿਰਫ਼ .ttf ਫੌਂਟਾਂ ਨਾਲ ਕੰਮ ਕਰਦਾ ਹੈ" - }, - "custom_shared_library": { - "name": "ਕਸਟਮ ਸ਼ੇਅਰਡ ਲਾਇਬ੍ਰੇਰੀ", - "description": "Snapchat ਵਿੱਚ ਇੱਕ ਕਸਟਮ ਸ਼ੇਅਰਡ ਲਾਇਬ੍ਰੇਰੀ ਲੋਡ ਕਰਦਾ ਹੈ। ਇਹ ਵਿਸ਼ੇਸ਼ਤਾ ਸਿਰਫ਼ ਟੈਸਟਿੰਗ ਦੇ ਉਦੇਸ਼ਾਂ ਲਈ ਹੈ" - } - } - }, - "spoof": { - "name": "ਸਪੂਫ", - "description": "ਤੁਹਾਡੇ ਬਾਰੇ ਵੱਖ-ਵੱਖ ਜਾਣਕਾਰੀ ਨੂੰ ਸਪੂਫ ਕਰੋ", - "properties": { - "play_store_installer_package_name": { - "name": "ਪਲੇ ਸਟੋਰ ਇੰਸਟਾਲਰ ਪੈਕੇਜ ਨਾਮ", - "description": "ਇੰਸਟਾਲਰ ਪੈਕੇਜ ਨਾਮ ਨੂੰ com.android.vending 'ਤੇ ਓਵਰਰਾਈਡ ਕਰਦਾ ਹੈ" - }, - "remove_vpn_transport_flag": { - "name": "VPN ਟ੍ਰਾਂਸਪੋਰਟ ਫਲੈਗ ਹਟਾਓ", - "description": "Snapchat ਨੂੰ VPN ਦਾ ਪਤਾ ਲਗਾਉਣ ਤੋਂ ਰੋਕਦਾ ਹੈ" - }, - "remove_mock_location_flag": { - "name": "ਮੌਕ ਸਥਾਨ ਫਲੈਗ ਹਟਾਓ", - "description": "Snapchat ਨੂੰ ਮੌਕ ਸਥਾਨ ਦਾ ਪਤਾ ਲਗਾਉਣ ਤੋਂ ਰੋਕਦਾ ਹੈ" - } - } - }, - "convert_message_locally": { - "name": "ਸੁਨੇਹੇ ਨੂੰ ਸਥਾਨਕ ਤੌਰ 'ਤੇ ਬਦਲੋ", - "description": "ਸਨੈਪਸ ਨੂੰ ਸਥਾਨਕ ਤੌਰ 'ਤੇ ਬਾਹਰੀ ਮੀਡੀਆ ਚੈਟ ਵਿੱਚ ਬਦਲਦਾ ਹੈ। ਇਹ ਚੈਟ ਡਾਊਨਲੋਡ ਪ੍ਰਸੰਗ ਮੀਨੂ ਵਿੱਚ ਦਿਖਾਈ ਦਿੰਦਾ ਹੈ" - }, - "media_file_picker": { - "name": "ਮੀਡੀਆ ਫਾਈਲ ਪਿਕਰ", - "description": "ਤੁਹਾਨੂੰ ਗੈਲਰੀ ਤੋਂ ਕੋਈ ਵੀ ਵੀਡੀਓ/ਆਡੀਓ ਫਾਈਲ ਚੁਣਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ" - }, - "story_logger": { - "name": "ਕਹਾਣੀ ਲੌਗਰ", - "description": "ਦੋਸਤਾਂ ਦੀਆਂ ਕਹਾਣੀਆਂ ਦਾ ਇਤਿਹਾਸ ਪ੍ਰਦਾਨ ਕਰਦਾ ਹੈ" - }, - "call_recorder": { - "name": "ਕਾਲ ਰਿਕਾਰਡਰ", - "description": "ਆਡੀਓ ਕਾਲਾਂ ਨੂੰ ਆਪਣੇ ਆਪ ਰਿਕਾਰਡ ਕਰਦਾ ਹੈ" - }, - "account_switcher": { - "name": "ਖਾਤਾ ਸਵਿੱਚਰ", - "description": "ਤੁਹਾਨੂੰ ਲੌਗ ਆਊਟ ਕੀਤੇ ਬਿਨਾਂ ਖਾਤਿਆਂ ਵਿਚਕਾਰ ਸਵਿੱਚ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।\nਮੀਨੂ ਖੋਲ੍ਹਣ ਲਈ ਆਪਣੇ Bitmoji ਪ੍ਰੋਫਾਈਲ ਦੇ ਅੱਗੇ ਖੋਜ ਆਈਕਨ 'ਤੇ ਲੰਮਾ ਦਬਾਓ।\nਨੋਟ: ਇਹ ਵਿਸ਼ੇਸ਼ਤਾ ਪ੍ਰਯੋਗਾਤਮਕ ਹੈ ਅਤੇ ਭਵਿੱਖ ਵਿੱਚ ਬਦਲ ਸਕਦੀ ਹੈ" - }, - "better_transcript": { - "name": "ਬਿਹਤਰ ਟ੍ਰਾਂਸਕ੍ਰਿਪਟ", - "description": "ਵੌਇਸ ਨੋਟ ਟ੍ਰਾਂਸਕ੍ਰਿਪਟ ਨੂੰ ਸੁਧਾਰਦਾ ਹੈ", - "properties": { - "force_transcription": { - "name": "ਵੌਇਸ ਨੋਟ ਟ੍ਰਾਂਸਕ੍ਰਿਪਸ਼ਨ ਨੂੰ ਮਜਬੂਰ ਕਰੋ", - "description": "ਸਾਰੇ ਵੌਇਸ ਨੋਟਸ ਨੂੰ ਟ੍ਰਾਂਸਕ੍ਰਾਈਬ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ" - }, - "preferred_transcription_lang": { - "name": "ਪਸੰਦੀਦਾ ਟ੍ਰਾਂਸਕ੍ਰਿਪਸ਼ਨ ਭਾਸ਼ਾ", - "description": "ਵੌਇਸ ਨੋਟ ਟ੍ਰਾਂਸਕ੍ਰਿਪਟ ਲਈ ਤਰਜੀਹੀ ਭਾਸ਼ਾ (ਜਿਵੇਂ EN, ES, FR)" - }, - "notification_transcript": { - "name": "ਸੂਚਨਾ ਟ੍ਰਾਂਸਕ੍ਰਿਪਟ", - "description": "ਸੂਚਨਾਵਾਂ ਵਿੱਚ ਵੌਇਸ ਨੋਟਸ ਨੂੰ ਟ੍ਰਾਂਸਕ੍ਰਾਈਬ ਕਰਦਾ ਹੈ।\nਇਸ ਵਿਸ਼ੇਸ਼ਤਾ ਲਈ ਬਿਹਤਰ ਸੂਚਨਾਵਾਂ ਵਿੱਚ ਚੈਟ ਪੂਰਵਦਰਸ਼ਨ ਵਿਸ਼ੇਸ਼ਤਾ ਨੂੰ ਸਮਰੱਥ ਕਰਨ ਦੀ ਲੋੜ ਹੈ" - } - } - }, - "voice_note_auto_play": { - "name": "ਵੌਇਸ ਨੋਟ ਆਟੋ ਪਲੇ", - "description": "ਮੌਜੂਦਾ ਇੱਕ ਦੇ ਖਤਮ ਹੋਣ ਤੋਂ ਬਾਅਦ ਅਗਲੇ ਵੌਇਸ ਨੋਟ ਨੂੰ ਆਪਣੇ ਆਪ ਚਲਾਉਂਦਾ ਹੈ" - }, - "friend_notes": { - "name": "ਦੋਸਤ ਨੋਟਸ", - "description": "ਤੁਹਾਨੂੰ ਦੋਸਤ ਪ੍ਰੋਫਾਈਲਾਂ ਵਿੱਚ ਨੋਟ ਜੋੜਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ" - }, - "cof_experiments": { - "name": "COF ਪ੍ਰਯੋਗ", - "description": "ਅਣ-ਰਿਲੀਜ਼/ਬੀਟਾ Snapchat ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਨੂੰ ਸਮਰੱਥ ਬਣਾਉਂਦਾ ਹੈ" - }, - "context_menu_fix": { - "name": "ਪ੍ਰਸੰਗ ਮੀਨੂ ਫਿਕਸ", - "description": "ਦੋਸਤ ਫੀਡ ਮੀਨੂ ਨੂੰ ਠੀਕ ਕਰਦਾ ਹੈ, ਜੋ ਡਿਵਾਈਸ ਔਫਲਾਈਨ ਹੋਣ 'ਤੇ ਸਹੀ ਢੰਗ ਨਾਲ ਪ੍ਰਦਰਸ਼ਿਤ ਨਹੀਂ ਹੋ ਸਕਦਾ" - }, - "app_lock": { - "name": "ਐਪ ਲੌਕ", - "description": "ਪਾਸਕੋਡ ਤੋਂ ਬਿਨਾਂ Snapchat ਤੱਕ ਪਹੁੰਚ ਨੂੰ ਰੋਕਦਾ ਹੈ", - "properties": { - "lock_on_resume": { - "name": "ਮੁੜ ਸ਼ੁਰੂ ਕਰਨ 'ਤੇ ਲੌਕ ਕਰੋ", - "description": "ਐਪ ਨੂੰ ਦੁਬਾਰਾ ਖੋਲ੍ਹਣ 'ਤੇ ਲੌਕ ਕਰਦਾ ਹੈ" - } - } - }, - "infinite_story_boost": { - "name": "ਅਨੰਤ ਕਹਾਣੀ ਬੂਸਟ", - "description": "ਕਹਾਣੀ ਬੂਸਟ ਸੀਮਾ ਨੂੰ ਬਾਈਪਾਸ ਕਰੋ" - }, - "meo_passcode_bypass": { - "name": "ਮੇਰੀਆਂ ਅੱਖਾਂ ਸਿਰਫ਼ ਪਾਸਕੋਡ ਬਾਈਪਾਸ", - "description": "ਮੇਰੀਆਂ ਅੱਖਾਂ ਸਿਰਫ਼ ਪਾਸਕੋਡ ਨੂੰ ਬਾਈਪਾਸ ਕਰੋ।\nਇਹ ਸਿਰਫ਼ ਤਾਂ ਹੀ ਕੰਮ ਕਰੇਗਾ ਜੇਕਰ ਪਾਸਕੋਡ ਪਹਿਲਾਂ ਸਹੀ ਢੰਗ ਨਾਲ ਦਾਖਲ ਕੀਤਾ ਗਿਆ ਹੋਵੇ" - }, - "no_friend_score_delay": { - "name": "ਕੋਈ ਦੋਸਤ ਸਕੋਰ ਦੇਰੀ ਨਹੀਂ", - "description": "ਇੱਕ ਦੋਸਤ ਦੇ ਸਕੋਰ ਨੂੰ ਦੇਖਣ ਵੇਲੇ ਦੇਰੀ ਨੂੰ ਹਟਾਉਂਦਾ ਹੈ" - }, - "best_friend_pinning": { - "name": "ਸਭ ਤੋਂ ਵਧੀਆ ਦੋਸਤ ਪਿੰਨਿੰਗ", - "description": "ਤੁਹਾਨੂੰ ਇੱਕ ਦੋਸਤ ਨੂੰ ਆਪਣੇ ਨੰਬਰ ਇੱਕ ਸਭ ਤੋਂ ਵਧੀਆ ਦੋਸਤ ਵਜੋਂ ਪਿੰਨ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ। ਨੋਟ: ਸਿਰਫ਼ ਤੁਸੀਂ ਆਪਣੇ ਪਿੰਨ ਕੀਤੇ ਸਭ ਤੋਂ ਵਧੀਆ ਦੋਸਤ ਨੂੰ ਦੇਖ ਸਕਦੇ ਹੋ" - }, - "e2ee": { - "name": "ਐਂਡ-ਟੂ-ਐਂਡ ਇਨਕ੍ਰਿਪਸ਼ਨ", - "description": "ਇੱਕ ਸਾਂਝੀ ਗੁਪਤ ਕੁੰਜੀ ਦੀ ਵਰਤੋਂ ਕਰਕੇ ਤੁਹਾਡੇ ਸੁਨੇਹਿਆਂ ਨੂੰ AES ਨਾਲ ਇਨਕ੍ਰਿਪਟ ਕਰਦਾ ਹੈ।\nਆਪਣੀ ਕੁੰਜੀ ਨੂੰ ਕਿਤੇ ਸੁਰੱਖਿਅਤ ਸੇਵ ਕਰਨਾ ਯਕੀਨੀ ਬਣਾਓ!", - "properties": { - "encrypted_message_indicator": { - "name": "ਇਨਕ੍ਰਿਪਟਡ ਸੁਨੇਹਾ ਸੂਚਕ", - "description": "ਇਨਕ੍ਰਿਪਟਡ ਸੁਨੇਹਿਆਂ ਦੇ ਅੱਗੇ ਇੱਕ 🔒 ਇਮੋਜੀ ਜੋੜਦਾ ਹੈ" - }, - "force_message_encryption": { - "name": "ਸੁਨੇਹਾ ਇਨਕ੍ਰਿਪਸ਼ਨ ਨੂੰ ਮਜਬੂਰ ਕਰੋ", - "description": "ਉਨ੍ਹਾਂ ਲੋਕਾਂ ਨੂੰ ਇਨਕ੍ਰਿਪਟਡ ਸੁਨੇਹੇ ਭੇਜਣ ਤੋਂ ਰੋਕਦਾ ਹੈ ਜਿਨ੍ਹਾਂ ਕੋਲ E2E ਇਨਕ੍ਰਿਪਸ਼ਨ ਸਮਰੱਥ ਨਹੀਂ ਹੈ ਜਦੋਂ ਕਈ ਗੱਲਬਾਤਾਂ ਚੁਣੀਆਂ ਜਾਂਦੀਆਂ ਹਨ" - } - } - }, - "add_friend_source_spoof": { - "name": "ਦੋਸਤ ਸਰੋਤ ਸਪੂਫ ਸ਼ਾਮਲ ਕਰੋ", - "description": "ਇੱਕ ਦੋਸਤ ਬੇਨਤੀ ਦੇ ਸਰੋਤ ਨੂੰ ਸਪੂਫ ਕਰਦਾ ਹੈ" - }, - "hidden_snapchat_plus_features": { - "name": "ਲੁਕਵੇਂ Snapchat+ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ", - "description": "ਅਣ-ਰਿਲੀਜ਼/ਬੀਟਾ Snapchat+ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਨੂੰ ਸਮਰੱਥ ਬਣਾਉਂਦਾ ਹੈ।\nਪੁਰਾਣੇ Snapchat ਸੰਸਕਰਣਾਂ 'ਤੇ ਕੰਮ ਨਹੀਂ ਕਰ ਸਕਦਾ" - }, - "custom_streaks_expiration_format": { - "name": "ਕਸਟਮ ਸਟ੍ਰੀਕਸ ਮਿਆਦ ਪੁੱਗਣ ਦਾ ਫਾਰਮੈਟ", - "description": "ਸਟ੍ਰੀਕਸ ਮਿਆਦ ਪੁੱਗਣ ਦੇ ਫਾਰਮੈਟ ਨੂੰ ਅਨੁਕੂਲਿਤ ਕਰਦਾ ਹੈ।\n\nਉਪਲਬਧ ਵੇਰੀਏਬਲ:\n - %c: ਸਟ੍ਰੀਕਸ ਗਿਣਤੀ\n - %e: ਘੰਟਾ ਗਲਾਸ ਇਮੋਜੀ\n - %d: ਦਿਨ\n - %h: ਘੰਟੇ\n - %m: ਮਿੰਟ\n - %s: ਸਕਿੰਟ\n - %w: ਬਾਕੀ ਸਮਾਂ" - }, - "prevent_forced_logout": { - "name": "ਜਬਰੀ ਲੌਗਆਊਟ ਨੂੰ ਰੋਕੋ", - "description": "ਜਦੋਂ ਤੁਸੀਂ ਕਿਸੇ ਹੋਰ ਡਿਵਾਈਸ 'ਤੇ ਲੌਗਇਨ ਕਰਦੇ ਹੋ ਤਾਂ Snapchat ਨੂੰ ਤੁਹਾਨੂੰ ਲੌਗ ਆਊਟ ਕਰਨ ਤੋਂ ਰੋਕਦਾ ਹੈ" - }, - "snapscore_changes": { - "name": "ਸਨੈਪਸਕੋਰ ਤਬਦੀਲੀਆਂ", - "description": "ਦੋਸਤਾਂ ਦੇ ਸਨੈਪਸਕੋਰ ਵਿੱਚ ਤਬਦੀਲੀਆਂ ਨੂੰ ਟਰੈਕ ਕਰਦਾ ਹੈ।\nਇਸ ਵਿਸ਼ੇਸ਼ਤਾ ਦੀ ਵਰਤੋਂ ਸਿਰਫ਼ Snapchat ਦੇ ਨਵੇਂ ਸੰਸਕਰਣਾਂ 'ਤੇ ਕਰੋ" - } - } - }, - "scripting": { - "name": "ਸਕ੍ਰਿਪਟਿੰਗ", - "description": "PurrfectSnap ਨੂੰ ਵਧਾਉਣ ਲਈ ਕਸਟਮ ਸਕ੍ਰਿਪਟਾਂ ਚਲਾਓ", - "properties": { - "developer_mode": { - "name": "ਡਿਵੈਲਪਰ ਮੋਡ", - "description": "Snapchat ਦੇ UI 'ਤੇ ਡੀਬੱਗ ਜਾਣਕਾਰੀ ਦਿਖਾਉਂਦਾ ਹੈ" - }, - "module_folder": { - "name": "ਮਾਡਿਊਲ ਫੋਲਡਰ", - "description": "ਉਹ ਫੋਲਡਰ ਜਿੱਥੇ ਸਕ੍ਰਿਪਟਾਂ ਸਥਿਤ ਹਨ" - }, - "auto_reload": { - "name": "ਆਟੋ ਰੀਲੋਡ", - "description": "ਜਦੋਂ ਉਹ ਬਦਲਦੇ ਹਨ ਤਾਂ ਸਕ੍ਰਿਪਟਾਂ ਨੂੰ ਆਪਣੇ ਆਪ ਰੀਲੋਡ ਕਰੋ" - }, - "integrated_ui": { - "name": "ਏਕੀਕ੍ਰਿਤ UI", - "description": "ਸਕ੍ਰਿਪਟਾਂ ਨੂੰ Snapchat ਵਿੱਚ ਕਸਟਮ UI ਕੰਪੋਨੈਂਟਸ ਜੋੜਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ" - }, - "disable_log_anonymization": { - "name": "ਲੌਗ ਗੁਮਨਾਮਤਾ ਨੂੰ ਅਯੋਗ ਕਰੋ", - "description": "ਲੌਗ ਦੀ ਗੁਮਨਾਮਤਾ ਨੂੰ ਅਯੋਗ ਕਰਦਾ ਹੈ" - }, - "disable_optimization": { - "name": "ਅਨੁਕੂਲਨ ਨੂੰ ਅਯੋਗ ਕਰੋ", - "description": "ਸਕ੍ਰਿਪਟਾਂ ਦੇ ਅਨੁਕੂਲਨ ਨੂੰ ਅਯੋਗ ਕਰਦਾ ਹੈ। ਇਹ ਪ੍ਰਦਰਸ਼ਨ ਸਮੱਸਿਆਵਾਂ ਦਾ ਕਾਰਨ ਬਣ ਸਕਦਾ ਹੈ।" - } - } - }, - "friend_tracker": { - "name": "ਦੋਸਤ ਟਰੈਕਰ", - "description": "Snapchat 'ਤੇ ਦੋਸਤ ਦੀ ਗਤੀਵਿਧੀ ਨੂੰ ਰਿਕਾਰਡ ਕਰਦਾ ਹੈ", - "properties": { - "record_messaging_events": { - "name": "ਮੈਸੇਜਿੰਗ ਸਮਾਗਮਾਂ ਨੂੰ ਰਿਕਾਰਡ ਕਰੋ", - "description": "ਮੈਸੇਜਿੰਗ ਸਮਾਗਮਾਂ ਨੂੰ ਰਿਕਾਰਡ ਕਰਦਾ ਹੈ ਜਿਵੇਂ ਕਿ ਇੱਕ ਸਨੈਪ ਖੋਲ੍ਹਣਾ, ਇੱਕ ਸੁਨੇਹਾ ਪੜ੍ਹਨਾ, ਆਦਿ।" - }, - "allow_running_in_background": { - "name": "ਬੈਕਗ੍ਰਾਉਂਡ ਵਿੱਚ ਚੱਲਣ ਦੀ ਆਗਿਆ ਦਿਓ", - "description": "ਟਰੈਕਰ ਨੂੰ ਬੈਕਗ੍ਰਾਉਂਡ ਵਿੱਚ ਚੱਲਣ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ। ਨੋਟ: ਇਹ ਤੁਹਾਡੀ ਬੈਟਰੀ ਨੂੰ ਕਾਫ਼ੀ ਹੱਦ ਤੱਕ ਖਤਮ ਕਰ ਦੇਵੇਗਾ" - }, - "auto_purge": { - "name": "ਆਟੋ ਸ਼ੁੱਧ", - "description": "ਨਿਰਧਾਰਤ ਸਮੇਂ ਤੋਂ ਪੁਰਾਣੇ ਕੈਸ਼ ਕੀਤੇ ਸਮਾਗਮਾਂ ਨੂੰ ਆਪਣੇ ਆਪ ਮਿਟਾਉਂਦਾ ਹੈ" - } - } - } - }, - "options": { - "app_appearance": { - "always_light": "ਹਮੇਸ਼ਾ ਹਲਕਾ", - "always_dark": "ਹਮੇਸ਼ਾ ਗੂੜ੍ਹਾ" - }, - "friend_feed_menu_buttons": { - "auto_download": "⬇️ ਆਟੋ ਡਾਊਨਲੋਡ", - "auto_save": "💬 ਆਟੋ ਸੇਵ ਸੁਨੇਹੇ", - "unsaveable_messages": "⬇️ ਅਣ-ਸੇਵ ਕਰਨ ਯੋਗ ਸੁਨੇਹੇ", - "auto_open_snaps": "📷 ਆਟੋ ਓਪਨ ਸਨੈਪਸ", - "stealth": "👻 ਸਟੀਲਥ ਮੋਡ", - "mark_snaps_as_seen": "ਸਨੈਪਸ ਨੂੰ ਦੇਖੇ ਗਏ ਵਜੋਂ ਮਾਰਕ ਕਰੋ", - "mark_stories_as_seen_locally": "ਕਹਾਣੀਆਂ ਨੂੰ ਸਥਾਨਕ ਤੌਰ 'ਤੇ ਦੇਖੇ ਗਏ ਵਜੋਂ ਮਾਰਕ ਕਰੋ", - "conversation_info": "👤 ਗੱਲਬਾਤ ਦੀ ਜਾਣਕਾਰੀ", - "e2e_encryption": "🔒 E2E ਇਨਕ੍ਰਿਪਸ਼ਨ ਦੀ ਵਰਤੋਂ ਕਰੋ" - }, - "path_format": { - "create_author_folder": "ਹਰੇਕ ਲੇਖਕ ਲਈ ਫੋਲਡਰ ਬਣਾਓ", - "create_source_folder": "ਹਰੇਕ ਮੀਡੀਆ ਸਰੋਤ ਕਿਸਮ ਲਈ ਫੋਲਡਰ ਬਣਾਓ", - "append_hash": "ਫਾਈਲ ਨਾਮ ਵਿੱਚ ਇੱਕ ਵਿਲੱਖਣ ਹੈਸ਼ ਸ਼ਾਮਲ ਕਰੋ", - "append_source": "ਫਾਈਲ ਨਾਮ ਵਿੱਚ ਮੀਡੀਆ ਸਰੋਤ ਸ਼ਾਮਲ ਕਰੋ", - "append_username": "ਫਾਈਲ ਨਾਮ ਵਿੱਚ ਉਪਭੋਗਤਾ ਨਾਮ ਸ਼ਾਮਲ ਕਰੋ", - "append_date_time": "ਫਾਈਲ ਨਾਮ ਵਿੱਚ ਮਿਤੀ ਅਤੇ ਸਮਾਂ ਸ਼ਾਮਲ ਕਰੋ" - }, - "auto_download_sources": { - "friend_snaps": "ਦੋਸਤ ਸਨੈਪਸ", - "friend_stories": "ਦੋਸਤ ਕਹਾਣੀਆਂ", - "public_stories": "ਜਨਤਕ ਕਹਾਣੀਆਂ", - "spotlight": "ਸਪੌਟਲਾਈਟ" - }, - "logging": { - "started": "ਸ਼ੁਰੂ ਹੋਇਆ", - "success": "ਸਫਲਤਾ", - "progress": "ਪ੍ਰਗਤੀ", - "failure": "ਅਸਫਲਤਾ" - }, - "notifications": { - "chat_screenshot": "ਚੈਟ ਸਕ੍ਰੀਨਸ਼ਾਟ", - "chat_screen_record": "ਚੈਟ ਸਕ੍ਰੀਨ ਰਿਕਾਰਡ", - "snap_replay": "ਸਨੈਪ ਰੀਪਲੇ", - "camera_roll_save": "ਕੈਮਰਾ ਰੋਲ ਸੇਵ", - "chat": "ਚੈਟ", - "chat_reply": "ਚੈਟ ਜਵਾਬ", - "snap": "ਸਨੈਪ", - "typing": "ਟਾਈਪਿੰਗ", - "stories": "ਕਹਾਣੀਆਂ", - "speaking": "ਬੋਲ ਰਿਹਾ ਹੈ", - "chat_reaction": "DM ਪ੍ਰਤੀਕਿਰਿਆ", - "group_chat_reaction": "ਸਮੂਹ ਪ੍ਰਤੀਕਿਰਿਆ", - "initiate_audio": "ਆਉਣ ਵਾਲੀ ਆਡੀਓ ਕਾਲ", - "abandon_audio": "ਮਿਸਡ ਆਡੀਓ ਕਾਲ", - "initiate_video": "ਆਉਣ ਵਾਲੀ ਵੀਡੀਓ ਕਾਲ", - "abandon_video": "ਮਿਸਡ ਵੀਡੀਓ ਕਾਲ", - "map_live_location": "ਲਾਈਵ ਸਥਾਨ" - }, - "gallery_media_send_override": { - "always_ask": "ਹਮੇਸ਼ਾ ਪੁੱਛੋ", - "ORIGINAL": "ਅਸਲ ਮੀਡੀਆ", - "NOTE": "ਆਡੀਓ ਨੋਟ", - "SNAP": "ਸਨੈਪ", - "SAVEABLE_SNAP": "ਸੇਵ ਕਰਨ ਯੋਗ ਸਨੈਪ" - }, - "strip_media_metadata": { - "hide_caption_text": "ਕੈਪਸ਼ਨ ਟੈਕਸਟ ਲੁਕਾਓ", - "hide_snap_filters": "ਸਨੈਪ ਫਿਲਟਰ ਲੁਕਾਓ", - "hide_extras": "ਵਾਧੂ ਲੁਕਾਓ (ਜਿਵੇਂ ਕਿ ਜ਼ਿਕਰ)", - "remove_audio_note_duration": "ਆਡੀਓ ਨੋਟ ਦੀ ਮਿਆਦ ਹਟਾਓ", - "remove_audio_note_transcript_capability": "ਆਡੀਓ ਨੋਟ ਟ੍ਰਾਂਸਕ੍ਰਿਪਟ ਸਮਰੱਥਾ ਨੂੰ ਹਟਾਓ" - }, - "hide_ui_components": { - "hide_profile_call_buttons": "ਪ੍ਰੋਫਾਈਲ ਕਾਲ ਬਟਨ ਹਟਾਓ", - "hide_chat_call_buttons": "ਚੈਟ ਕਾਲ ਬਟਨ ਹਟਾਓ", - "hide_live_location_share_button": "ਲਾਈਵ ਸਥਾਨ ਸ਼ੇਅਰ ਬਟਨ ਹਟਾਓ", - "hide_stickers_button": "ਸਟਿੱਕਰ ਬਟਨ ਹਟਾਓ", - "hide_voice_record_button": "ਵੌਇਸ ਰਿਕਾਰਡ ਬਟਨ ਹਟਾਓ", - "hide_unread_chat_hint": "ਅਣ-ਪੜ੍ਹੇ ਚੈਟ ਸੰਕੇਤ ਨੂੰ ਹਟਾਓ", - "hide_post_to_story_buttons": "ਇੱਕ ਸਨੈਪ ਭੇਜਣ ਤੋਂ ਪਹਿਲਾਂ ਕਹਾਣੀ ਬਟਨਾਂ 'ਤੇ ਪੋਸਟ ਹਟਾਓ", - "hide_billboard_prompt": "ਦੋਸਤ ਫੀਡ ਵਿੱਚ ਬਿਲਬੋਰਡ ਪ੍ਰੋਂਪਟ ਹਟਾਓ", - "hide_snapchat_plus_gift_reminders": "ਗੱਲਬਾਤ ਵਿੱਚ Snapchat+ ਤੋਹਫ਼ੇ ਰੀਮਾਈਂਡਰ ਹਟਾਓ", - "hide_map_reactions": "ਨਕਸ਼ਾ ਪ੍ਰਤੀਕਿਰਿਆਵਾਂ ਹਟਾਓ" - }, - "hide_story_suggestions": { - "hide_suggested_friend_stories": "ਸੁਝਾਏ ਗਏ ਦੋਸਤ ਕਹਾਣੀਆਂ ਲੁਕਾਓ", - "hide_my_stories": "ਮੇਰੀਆਂ ਕਹਾਣੀਆਂ ਲੁਕਾਓ" - }, - "home_tab": { - "map": "ਨਕਸ਼ਾ", - "chat": "ਚੈਟ", - "camera": "ਕੈਮਰਾ", - "discover": "ਖੋਜੋ", - "spotlight": "ਸਪੌਟਲਾਈਟ" - }, - "add_friend_source_spoof": { - "added_by_username": "ਉਪਭੋਗਤਾ ਨਾਮ ਦੁਆਰਾ", - "added_by_mention": "ਜ਼ਿਕਰ ਦੁਆਰਾ", - "added_by_group_chat": "ਸਮੂਹ ਗੱਲਬਾਤ ਦੁਆਰਾ", - "added_by_qr_code": "QR ਕੋਡ ਦੁਆਰਾ", - "added_by_community": "ਕਮਿਊਨਿਟੀ ਦੁਆਰਾ", - "added_by_quick_add": "ਤੁਰੰਤ ਸ਼ਾਮਲ ਦੁਆਰਾ (ਪਾਬੰਦੀ ਲੱਗਣ ਦਾ ਵੱਧ ਖਤਰਾ)" - }, - "bypass_video_length_restriction": { - "single": "ਇੱਕ ਮੀਡੀਆ", - "split": "ਮੀਡੀਆ ਵੰਡੋ" - }, - "old_bitmoji_selfie": { - "2d": "2D Bitmoji", - "3d": "3D Bitmoji" - }, - "disable_confirmation_dialogs": { - "erase_message": "ਸੁਨੇਹਾ ਮਿਟਾਓ", - "remove_friend": "ਦੋਸਤ ਹਟਾਓ", - "block_friend": "ਦੋਸਤ ਬਲੌਕ ਕਰੋ", - "ignore_friend": "ਦੋਸਤ ਨੂੰ ਨਜ਼ਰਅੰਦਾਜ਼ ਕਰੋ", - "hide_friend": "ਦੋਸਤ ਲੁਕਾਓ", - "hide_conversation": "ਗੱਲਬਾਤ ਲੁਕਾਓ", - "clear_conversation": "ਦੋਸਤ ਫੀਡ ਤੋਂ ਗੱਲਬਾਤ ਸਾਫ਼ ਕਰੋ" - }, - "auto_reload": { - "snapchat_only": "ਸਿਰਫ਼ Snapchat", - "all": "ਸਾਰੇ (Snapchat + PurrfectSnap)" - }, - "edit_text_override": { - "multi_line_chat_input": "ਮਲਟੀ-ਲਾਈਨ ਚੈਟ ਇਨਪੁਟ", - "bypass_text_input_limit": "ਟੈਕਸਟ ਇਨਪੁਟ ਸੀਮਾ ਨੂੰ ਬਾਈਪਾਸ ਕਰੋ" - }, - "auto_purge": { - "never": "ਕਦੇ ਨਹੀਂ", - "1_hour": "1 ਘੰਟਾ", - "3_hours": "3 ਘੰਟੇ", - "6_hours": "6 ਘੰਟੇ", - "12_hours": "12 ਘੰਟੇ", - "1_day": "1 ਦਿਨ", - "3_days": "3 ਦਿਨ", - "1_week": "1 ਹਫ਼ਤਾ", - "2_weeks": "2 ਹਫ਼ਤੇ", - "1_month": "1 ਮਹੀਨਾ", - "3_months": "3 ਮਹੀਨੇ", - "6_months": "6 ਮਹੀਨੇ" - }, - "disable_story_sections": { - "friends": "ਦੋਸਤ", - "suggested_stories": "ਸੁਝਾਈਆਂ ਕਹਾਣੀਆਂ", - "following": "ਅਨੁਸਰਣ ਕਰ ਰਹੇ ਹਨ", - "discover": "ਖੋਜੋ" - }, - "disable_cameras": { - "front": "ਫਰੰਟ ਕੈਮਰਾ", - "back": "ਬੈਕ ਕੈਮਰਾ" - }, - "disable_permission_requests": { - "notifications": "ਸੂਚਨਾਵਾਂ", - "read_media_images": "ਮੀਡੀਆ ਚਿੱਤਰ ਪੜ੍ਹੋ", - "read_media_video": "ਮੀਡੀਆ ਵੀਡੀਓ ਪੜ੍ਹੋ", - "camera": "ਕੈਮਰਾ", - "microphone": "ਮਾਈਕ੍ਰੋਫੋਨ", - "location": "ਸਥਾਨ", - "read_contacts": "ਸੰਪਰਕ ਪੜ੍ਹੋ", - "nearby_devices": "ਨੇੜਲੇ ਡਿਵਾਈਸਾਂ", - "phone_calls": "ਫੋਨ ਕਾਲਾਂ" - }, - "message_indicators": { - "encryption_indicator": "ਸਿਰਫ਼ ਤੁਹਾਡੇ ਲਈ ਭੇਜੇ ਗਏ ਸੁਨੇਹਿਆਂ ਦੇ ਅੱਗੇ ਇੱਕ 🔒 ਆਈਕਨ ਜੋੜਦਾ ਹੈ", - "platform_indicator": "ਉਸ ਪਲੇਟਫਾਰਮ ਦਾ ਆਈਕਨ ਜੋੜਦਾ ਹੈ ਜਿੱਥੋਂ ਇੱਕ ਮੀਡੀਆ ਭੇਜਿਆ ਗਿਆ ਸੀ (ਜਿਵੇਂ ਕਿ Android, iOS, Web)", - "location_indicator": "ਸਨੈਪਸ ਦੇ ਅੱਗੇ ਇੱਕ 📍 ਆਈਕਨ ਜੋੜਦਾ ਹੈ ਜਦੋਂ ਉਹ ਸਥਾਨ ਸਮਰਥਿਤ ਨਾਲ ਭੇਜੇ ਜਾਂਦੇ ਹਨ", - "ovf_editor_indicator": "ਇਹ ਦਰਸਾਉਂਦਾ ਹੈ ਕਿ ਕੀ ਇੱਕ ਸਨੈਪ OVF ਸੰਪਾਦਕ ਦੀ ਵਰਤੋਂ ਕਰਕੇ ਭੇਜਿਆ ਗਿਆ ਹੈ", - "director_mode_indicator": "ਸਨੈਪਸ ਦੇ ਅੱਗੇ ਇੱਕ 🎬 ਆਈਕਨ ਜੋੜਦਾ ਹੈ ਜਦੋਂ ਉਹ ਡਾਇਰੈਕਟਰ ਮੋਡ ਦੀ ਵਰਤੋਂ ਕਰਕੇ ਭੇਜੇ ਜਾਂਦੇ ਹਨ, ਜਿਸਦੀ ਵਰਤੋਂ ਗੈਲਰੀ ਚਿੱਤਰਾਂ ਨੂੰ ਸਨੈਪਸ ਵਜੋਂ ਭੇਜਣ ਲਈ ਕੀਤੀ ਜਾ ਸਕਦੀ ਹੈ" - }, - "auto_mark_as_read": { - "conversation_read": "ਇੱਕ ਸੁਨੇਹਾ ਭੇਜਣ ਵੇਲੇ ਗੱਲਬਾਤ ਨੂੰ ਪੜ੍ਹੇ ਗਏ ਵਜੋਂ ਮਾਰਕ ਕਰੋ", - "snap_reply": "ਜਵਾਬ ਦੇਣ ਵੇਲੇ ਸਨੈਪਸ ਨੂੰ ਪੜ੍ਹੇ ਗਏ ਵਜੋਂ ਮਾਰਕ ਕਰੋ", - "save_snap_in_chat": "ਸਟੀਲਥ ਮੋਡ ਵਿੱਚ ਹੋਣ 'ਤੇ ਚੈਟ ਵਿੱਚ ਸੇਵ ਕਰਨ ਵੇਲੇ ਸਨੈਪਸ ਨੂੰ ਪੜ੍ਹੇ ਗਏ ਵਜੋਂ ਮਾਰਕ ਕਰੋ" - }, - "friend_mutation_notifier": { - "remove_friend": "ਜਦੋਂ ਕੋਈ ਤੁਹਾਨੂੰ ਦੋਸਤ ਵਜੋਂ ਹਟਾਉਂਦਾ ਹੈ ਤਾਂ ਸੂਚਿਤ ਕਰੋ", - "birthday_changes": "ਜਦੋਂ ਕੋਈ ਆਪਣਾ ਜਨਮਦਿਨ ਬਦਲਦਾ ਹੈ ਤਾਂ ਸੂਚਿਤ ਕਰੋ", - "bitmoji_selfie_changes": "ਜਦੋਂ ਕੋਈ ਆਪਣੀ Bitmoji ਸੈਲਫੀ ਬਦਲਦਾ ਹੈ ਤਾਂ ਸੂਚਿਤ ਕਰੋ", - "bitmoji_avatar_changes": "ਜਦੋਂ ਕੋਈ ਆਪਣਾ Bitmoji ਅਵਤਾਰ ਬਦਲਦਾ ਹੈ ਤਾਂ ਸੂਚਿਤ ਕਰੋ", - "bitmoji_background_changes": "ਜਦੋਂ ਕੋਈ ਆਪਣਾ Bitmoji ਪਿਛੋਕੜ ਬਦਲਦਾ ਹੈ ਤਾਂ ਸੂਚਿਤ ਕਰੋ", - "bitmoji_scene_changes": "ਜਦੋਂ ਕੋਈ ਆਪਣਾ Bitmoji ਦ੍ਰਿਸ਼ ਬਦਲਦਾ ਹੈ ਤਾਂ ਸੂਚਿਤ ਕਰੋ" - }, - "snapchat_plus": { - "not_subscribed": "ਸਬਸਕ੍ਰਾਈਬ ਨਹੀਂ ਕੀਤਾ", - "basic": "ਮੁਢਲਾ", - "ad_free": "ਵਿਗਿਆਪਨ-ਮੁਕਤ" - }, - "double_tap_chat_action": { - "like_message": "ਸੁਨੇਹਾ ਪਸੰਦ ਕਰੋ", - "copy_text": "ਕਲਿੱਪਬੋਰਡ 'ਤੇ ਟੈਕਸਟ ਕਾਪੀ ਕਰੋ", - "delete_message": "ਸੁਨੇਹਾ ਮਿਟਾਓ", - "mark_as_read": "ਪੜ੍ਹੇ ਗਏ ਵਜੋਂ ਮਾਰਕ ਕਰੋ", - "custom_emoji_reaction": "ਕਸਟਮ ਇਮੋਜੀ ਪ੍ਰਤੀਕਿਰਿਆ" - }, - "startup_default_camera": { - "front": "ਫਰੰਟ ਕੈਮਰਾ", - "back": "ਬੈਕ ਕੈਮਰਾ" - } - } - }, - "friend_menu_option": { - "mark_snaps_as_seen": "ਸਨੈਪਸ ਨੂੰ ਦੇਖੇ ਗਏ ਵਜੋਂ ਮਾਰਕ ਕਰੋ", - "mark_stories_as_seen_locally": "ਕਹਾਣੀਆਂ ਨੂੰ ਸਥਾਨਕ ਤੌਰ 'ਤੇ ਦੇਖੇ ਗਏ ਵਜੋਂ ਮਾਰਕ ਕਰੋ", - "preview": "ਪੂਰਵਦਰਸ਼ਨ", - "stealth_mode": "ਸਟੀਲਥ ਮੋਡ", - "auto_download_blacklist": "ਆਟੋ ਡਾਊਨਲੋਡ ਬਲੈਕਲਿਸਟ", - "anti_auto_save": "ਐਂਟੀ ਆਟੋ ਸੇਵ" - }, - "content_type": { - "CHAT": "ਚੈਟ", - "SNAP": "ਸਨੈਪ", - "EXTERNAL_MEDIA": "ਬਾਹਰੀ ਮੀਡੀਆ", - "NOTE": "ਆਡੀਓ ਨੋਟ", - "STICKER": "ਸਟਿੱਕਰ", - "SHARE": "ਸ਼ੇਅਰ ਕਰੋ", - "STATUS": "ਸਥਿਤੀ", - "LOCATION": "ਸਥਾਨ", - "STATUS_SAVE_TO_CAMERA_ROLL": "ਕੈਮਰਾ ਰੋਲ ਵਿੱਚ ਸੇਵ ਕੀਤਾ ਗਿਆ", - "STATUS_CONVERSATION_CAPTURE_SCREENSHOT": "ਸਕ੍ਰੀਨਸ਼ਾਟ", - "STATUS_CONVERSATION_CAPTURE_RECORD": "ਸਕ੍ਰੀਨ ਰਿਕਾਰਡ", - "STATUS_CALL_MISSED_VIDEO": "ਮਿਸਡ ਵੀਡੀਓ ਕਾਲ", - "STATUS_CALL_MISSED_AUDIO": "ਮਿਸਡ ਆਡੀਓ ਕਾਲ", - "LIVE_LOCATION_SHARE": "ਲਾਈਵ ਸਥਾਨ ਸ਼ੇਅਰ", - "CREATIVE_TOOL_ITEM": "ਰਚਨਾਤਮਕ ਟੂਲ ਆਈਟਮ", - "FAMILY_CENTER_INVITE": "ਪਰਿਵਾਰ ਕੇਂਦਰ ਸੱਦਾ", - "FAMILY_CENTER_ACCEPT": "ਪਰਿਵਾਰ ਕੇਂਦਰ ਸਵੀਕਾਰ ਕਰਦਾ ਹੈ", - "FAMILY_CENTER_LEAVE": "ਪਰਿਵਾਰ ਕੇਂਦਰ ਛੱਡੋ", - "STATUS_PLUS_GIFT": "ਸਥਿਤੀ ਪਲੱਸ ਤੋਹਫ਼ਾ", - "TINY_SNAP": "ਛੋਟਾ ਸਨੈਪ", - "STATUS_COUNTDOWN": "ਕਾਊਂਟਡਾਊਨ", - "MAP_REACTION": "ਨਕਸ਼ਾ ਪ੍ਰਤੀਕਿਰਿਆ" - }, - "media_download_source": { - "none": "ਕੋਈ ਨਹੀਂ", - "pending": "ਬਕਾਇਆ", - "chat_media": "ਚੈਟ ਮੀਡੀਆ", - "story": "ਕਹਾਣੀ", - "public_story": "ਜਨਤਕ ਕਹਾਣੀ", - "spotlight": "ਸਪੌਟਲਾਈਟ", - "profile_picture": "ਪ੍ਰੋਫਾਈਲ ਤਸਵੀਰ", - "story_logger": "ਕਹਾਣੀ ਲੌਗਰ", - "message_logger": "ਸੁਨੇਹਾ ਲੌਗਰ", - "merged": "ਮਿਲਾਇਆ ਗਿਆ", - "voice_call": "ਵੌਇਸ ਕਾਲ" - }, - "chat_action_menu": { - "preview_button": "ਪੂਰਵਦਰਸ਼ਨ", - "download_button": "ਡਾਊਨਲੋਡ ਕਰੋ", - "delete_logged_message_button": "ਲੌਗ ਕੀਤੇ ਸੁਨੇਹੇ ਨੂੰ ਮਿਟਾਓ", - "show_chat_edit_history": "ਚੈਟ ਸੰਪਾਦਨ ਇਤਿਹਾਸ ਦਿਖਾਓ", - "convert_message": "ਸੁਨੇਹਾ ਬਦਲੋ" - }, - "opera_context_menu": { - "download": "ਮੀਡੀਆ ਡਾਊਨਲੋਡ ਕਰੋ", - "sent_at": "{date} 'ਤੇ ਭੇਜਿਆ ਗਿਆ", - "created_at": "{date} 'ਤੇ ਬਣਾਇਆ ਗਿਆ", - "expires_at": "{date} 'ਤੇ ਮਿਆਦ ਪੁੱਗ ਗਈ", - "media_size": "ਮੀਡੀਆ ਆਕਾਰ: {size}", - "media_duration": "ਮੀਡੀਆ ਦੀ ਮਿਆਦ: {duration} ms", - "show_debug_info": "ਡੀਬੱਗ ਜਾਣਕਾਰੀ ਦਿਖਾਓ" - }, - "modal_option": { - "profile_info": "ਪ੍ਰੋਫਾਈਲ ਜਾਣਕਾਰੀ", - "close": "ਬੰਦ ਕਰੋ" - }, - "gallery_media_send_override": { - "multiple_media_toast": "ਤੁਸੀਂ ਇੱਕ ਵਾਰ ਵਿੱਚ ਸਿਰਫ਼ ਇੱਕ ਮੀਡੀਆ ਭੇਜ ਸਕਦੇ ਹੋ" - }, - "mark_as_seen": { - "no_unseen_snaps_toast": "ਕੋਈ ਅਣਦੇਖੇ ਸਨੈਪ ਨਹੀਂ ਮਿਲੇ!", - "seen_toast": "ਦੇਖੇ ਗਏ ਵਜੋਂ ਮਾਰਕ ਕੀਤਾ ਗਿਆ!", - "unseen_toast": "ਅਣਦੇਖੇ ਵਜੋਂ ਮਾਰਕ ਕੀਤਾ ਗਿਆ!", - "already_seen_toast": "ਪਹਿਲਾਂ ਹੀ ਦੇਖੇ ਗਏ ਵਜੋਂ ਮਾਰਕ ਕੀਤਾ ਗਿਆ!", - "already_unseen_toast": "ਪਹਿਲਾਂ ਹੀ ਅਣਦੇਖੇ ਵਜੋਂ ਮਾਰਕ ਕੀਤਾ ਗਿਆ!" - }, - "conversation_preview": { - "streak_expiration": "{days} ਦਿਨ {hours} ਘੰਟੇ {minutes} ਮਿੰਟ ਵਿੱਚ ਮਿਆਦ ਪੁੱਗਦੀ ਹੈ", - "total_messages": "ਕੁੱਲ ਭੇਜੇ/ਪ੍ਰਾਪਤ ਕੀਤੇ ਸੁਨੇਹੇ: {count}", - "title": "ਪੂਰਵਦਰਸ਼ਨ", - "unknown_user": "ਅਣਜਾਣ ਉਪਭੋਗਤਾ", - "no_messages": "ਕੋਈ ਸੁਨੇਹੇ ਨਹੀਂ ਮਿਲੇ!" - }, - "profile_info": { - "title": "ਪ੍ਰੋਫਾਈਲ ਜਾਣਕਾਰੀ", - "first_created_username": "ਪਹਿਲਾਂ ਬਣਾਇਆ ਗਿਆ ਉਪਭੋਗਤਾ ਨਾਮ", - "mutable_username": "ਬਦਲਣਯੋਗ ਉਪਭੋਗਤਾ ਨਾਮ", - "display_name": "ਡਿਸਪਲੇ ਨਾਮ", - "added_date": "ਸ਼ਾਮਲ ਕੀਤੀ ਮਿਤੀ", - "birthday": "ਜਨਮਦਿਨ: {month} {day}", - "hidden_birthday": "ਜਨਮਦਿਨ: ਲੁਕਿਆ ਹੋਇਆ", - "friendship": "ਦੋਸਤੀ", - "add_source": "ਸਰੋਤ ਸ਼ਾਮਲ ਕਰੋ", - "snapchat_plus": "Snapchat+", - "snapchat_plus_state": { - "subscribed": "ਸਬਸਕ੍ਰਾਈਬ ਕੀਤਾ", - "not_subscribed": "ਸਬਸਕ੍ਰਾਈਬ ਨਹੀਂ ਕੀਤਾ" - } - }, - "friendship_link_type": { - "mutual": "ਆਪਸੀ", - "outgoing": "ਬਾਹਰ ਜਾਣ ਵਾਲਾ", - "blocked": "ਬਲੌਕ ਕੀਤਾ", - "deleted": "ਮਿਟਾਇਆ ਗਿਆ", - "following": "ਅਨੁਸਰਣ ਕਰ ਰਹੇ ਹਨ", - "suggested": "ਸੁਝਾਇਆ ਗਿਆ", - "incoming": "ਆਉਣ ਵਾਲਾ", - "incoming_follower": "ਆਉਣ ਵਾਲਾ ਅਨੁਯਾਈ" - }, - "bulk_messaging_action": { - "choose_action_title": "ਇੱਕ ਕਾਰਵਾਈ ਚੁਣੋ", - "progress_status": "ਪ੍ਰੋਸੈਸਿੰਗ {text}", - "selection_dialog_continue_button": "ਜਾਰੀ ਰੱਖੋ", - "confirmation_dialog": { - "title": "ਕੀ ਤੁਸੀਂ ਯਕੀਨੀ ਹੋ?", - "message": "ਇਹ ਸਾਰੇ ਚੁਣੇ ਹੋਏ ਦੋਸਤਾਂ ਨੂੰ ਪ੍ਰਭਾਵਿਤ ਕਰੇਗਾ। ਇਸ ਕਾਰਵਾਈ ਨੂੰ ਵਾਪਸ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਦਾ।" - }, - "actions": { - "remove_friends": "ਦੋਸਤ ਹਟਾਓ", - "clear_conversations": "ਗੱਲਬਾਤ ਸਾਫ਼ ਕਰੋ" - } - }, - "chat_export": { - "exporter_dialog": { - "select_conversations_title": "ਗੱਲਬਾਤ ਚੁਣੋ", - "text_field_selection": "{count} ਚੁਣੇ ਗਏ", - "text_field_selection_all": "ਸਾਰੇ", - "export_file_format_title": "ਫਾਈਲ ਫਾਰਮੈਟ ਨਿਰਯਾਤ ਕਰੋ", - "message_type_filter_title": "ਕਿਸਮ ਦੁਆਰਾ ਸੁਨੇਹੇ ਫਿਲਟਰ ਕਰੋ", - "amount_of_messages_title": "ਸੁਨੇਹਿਆਂ ਦੀ ਗਿਣਤੀ (ਸਭ ਲਈ ਖਾਲੀ ਛੱਡੋ)", - "download_medias_title": "ਮੀਡੀਆ ਡਾਊਨਲੋਡ ਕਰੋ" - }, - "dialog_negative_button": "ਰੱਦ ਕਰੋ", - "dialog_positive_button": "ਨਿਰਯਾਤ", - "exported_to": "{path} 'ਤੇ ਨਿਰਯਾਤ ਕੀਤਾ ਗਿਆ", - "exporting_chats": "ਗੱਲਬਾਤ ਨਿਰਯਾਤ ਕੀਤੀ ਜਾ ਰਹੀ ਹੈ...", - "processing_chats": "{count} ਗੱਲਬਾਤਾਂ ਦੀ ਪ੍ਰੋਸੈਸਿੰਗ ਹੋ ਰਹੀ ਹੈ...", - "export_fail": "{name} ਗੱਲਬਾਤ ਨੂੰ ਨਿਰਯਾਤ ਕਰਨ ਵਿੱਚ ਅਸਫਲ", - "writing_output": "ਆਉਟਪੁੱਟ ਲਿਖੀ ਜਾ ਰਹੀ ਹੈ...", - "finished": "ਹੋ ਗਿਆ! ਤੁਸੀਂ ਹੁਣ ਇਸ ਡਾਇਲਾਗ ਨੂੰ ਬੰਦ ਕਰ ਸਕਦੇ ਹੋ।", - "no_messages_found": "ਕੋਈ ਸੁਨੇਹੇ ਨਹੀਂ ਮਿਲੇ!", - "exporting_message": "ਸੁਨੇਹਾ {id} ਨਿਰਯਾਤ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ..." - }, - "button": { - "ok": "ਠੀਕ ਹੈ", - "positive": "ਹਾਂ", - "negative": "ਨਹੀਂ", - "cancel": "ਰੱਦ ਕਰੋ", - "open": "ਖੋਲ੍ਹੋ", - "download": "ਡਾਊਨਲੋਡ ਕਰੋ", - "send": "ਭੇਜੋ", - "restore_original": "ਅਸਲ ਨੂੰ ਰੀਸਟੋਰ ਕਰੋ", - "convert_external_media": "ਬਾਹਰੀ ਮੀਡੀਆ ਨੂੰ ਬਦਲੋ", - "save": "ਸੇਵ" - }, - "tracker_events": { - "conversation_enter": "ਗੱਲਬਾਤ ਦਰਜ ਕਰੋ", - "conversation_exit": "ਗੱਲਬਾਤ ਬਾਹਰ ਜਾਣ", - "started_typing": "ਟਾਈਪਿੰਗ ਸ਼ੁਰੂ ਕੀਤਾ", - "stopped_typing": "ਟਾਈਪਿੰਗ ਬੰਦ ਕਰ ਦਿੱਤਾ", - "started_speaking": "ਬੋਲਣਾ ਸ਼ੁਰੂ ਕੀਤਾ", - "stopped_speaking": "ਬੋਲਣਾ ਬੰਦ ਕਰ ਦਿੱਤਾ", - "started_peeking": "ਪੇਸਿੰਗ ਸ਼ੁਰੂ ਕੀਤੀ", - "stopped_peeking": "ਪੇਸਿੰਗ ਬੰਦ ਕਰ ਦਿੱਤੀ", - "message_read": "ਸੁਨੇਹਾ ਪੜ੍ਹੋ", - "message_deleted": "ਸੁਨੇਹਾ ਮਿਟਾ ਦਿੱਤਾ ਗਿਆ", - "message_saved": "ਸੁਨੇਹਾ ਬਚਾਇਆ", - "message_unsaved": "ਸੁਨੇਹਾ ਅਸੁਰੱਖਿਅਤ", - "message_edited": "ਸੁਨੇਹਾ ਸੰਪਾਦਿਤ", - "message_reaction_add": "ਸੁਨੇਹਾ ਪ੍ਰਤੀਕਰਮ ਸ਼ਾਮਲ ਕਰੋ", - "message_reaction_remove": "ਸੁਨੇਹਾ ਪ੍ਰਤੀਕਰਮ ਹਟਾਓ", - "snap_opened": "ਸਨੈਪ ਖੁੱਲ੍ਹ ਗਈ", - "snap_replayed": "ਸਨੈਪ ਰੀਡੈਂਟੀਡ", - "snap_replayed_twice": "ਪਈਆਂ ਸਨੈਪ ਨੂੰ ਦੋ ਵਾਰ", - "snap_screenshot": "ਸਕਰੀਨ ਸ਼ਾਟ", - "snap_screen_record": "ਸਨੈਪ ਸਕਰੀਨ ਰਿਕਾਰਡ" - }, - "tracker_actions": { - "log": "ਲਾਗ", - "in_app_notification": "ਇਨ-ਐਪ ਨੋਟੀਫਿਕੇਸ਼ਨ", - "push_notification": "ਪੁਸ਼ ਨੋਟੀਫਿਕੇਸ਼ਨ", - "custom": "ਕਸਟਮ" - }, - "better_notifications": { - "button": { - "reply": "ਜਵਾਬ", - "download": "ਡਾਉਨਲੋਡ ਕਰੋ", - "mark_as_read": "ਪੜ੍ਹਨ ਦੇ ਤੌਰ ਤੇ ਮਾਰਕ" - } - }, - "profile_picture_downloader": { - "button": "ਪ੍ਰੋਫਾਈਲ ਤਸਵੀਰ ਡਾਉਨਲੋਡ ਕਰੋ", - "title": "ਪ੍ਰੋਫਾਈਲ ਤਸਵੀਰ ਡਾ er ਡਰਰ", - "avatar_option": "ਅਵਤਾਰ", - "background_option": "ਪਿਛੋਕੜ" - }, - "call_start_confirmation": { - "dialog_title": "ਕਾਲ ਸ਼ੁਰੂ ਕਰੋ", - "dialog_message": "ਕੀ ਤੁਸੀਂ ਯਕੀਨਨ ਕਾਲ ਸ਼ੁਰੂ ਕਰਨਾ ਚਾਹੁੰਦੇ ਹੋ?" - }, - "half_swipe_notifier": { - "notification_channel_name": "ਅੱਧੀ ਸਵਾਈਪ", - "notification_content_dm": "__ ਪਲੇਸਧਾਰਕ_ 13 ਸਕਿੰਟਾਂ ਲਈ ਤੁਹਾਡੀ ਚੈਟ ਵਿੱਚ ਅੱਧਾ ਸਜਾਇਆ", - "notification_content_group": "__ ਪਲੇਸਡੋਲਡਰ_0 __ ਪਲੇਸਹੋਲਡਰ_1__ ਸਕਿੰਟ ਲਈ __ ਪਲੇਸੋਲਡਰ_1__ ਤੇ" - }, - "download_processor": { - "attachment_type": { - "snap": "ਸਨੈਪ", - "sticker": "ਸਟਿੱਕਰ", - "gif": "Gif", - "external_media": "ਬਾਹਰੀ ਮੀਡੀਆ", - "note": "ਨੋਟ", - "original_story": "ਅਸਲ ਕਹਾਣੀ" - }, - "select_attachments_title": "ਨੱਥੀ ਚੁਣੋ", - "download_started_toast": "ਡਾ Download ਨਲੋਡ ਸ਼ੁਰੂ", - "unsupported_content_type_toast": "ਅਸਮਰਥਿਤ ਸਮਗਰੀ ਦੀ ਕਿਸਮ!", - "failed_no_longer_available_toast": "ਮੀਡੀਆ ਹੁਣ ਉਪਲਬਧ ਨਹੀਂ ਹੈ", - "no_attachments_toast": "ਕੋਈ ਅਟੈਚਮੈਂਟ ਨਹੀਂ ਮਿਲਿਆ!", - "already_queued_toast": "ਮੀਡੀਆ ਪਹਿਲਾਂ ਹੀ ਕਤਾਰ ਵਿੱਚ ਹੈ!", - "already_downloaded_toast": "ਮੀਡੀਆ ਪਹਿਲਾਂ ਹੀ ਡਾ ed ਨਲੋਡ ਕੀਤਾ ਗਿਆ ਹੈ!", - "content_saved_toast": "ਬਚਾਇਆ!", - "download_toast": "ਡਾਉਨਲੋਡ ਕਰਨਾ __ ਪਲੇਸੋਲਡਰ_0 __...", - "processing_toast": "ਪ੍ਰੋਸੈਸਿੰਗ __ ਪਲੇਸੋਲਡਰ_0 __...", - "failed_generic_toast": "ਡਾ download ਨਲੋਡ ਕਰਨ ਵਿੱਚ ਅਸਫਲ", - "failed_to_create_preview_toast": "ਝਲਕ ਬਣਾਉਣ ਵਿੱਚ ਅਸਫਲ", - "failed_processing_toast": "ਅਸਫਲ ਪ੍ਰੋਸੈਸਿੰਗ __ ਪਲੇਸੋਲਡਰ_0__", - "failed_gallery_toast": "ਗੈਲਰੀ ਨੂੰ ਬਚਾਉਣ ਵਿੱਚ ਅਸਫਲ __ ਪਲੇਸੋਲਡਰ_0____", - "dash_no_chapter": "ਕੋਈ ਵੀ ਅਧਿਆਇ ਨਹੀਂ ਮਿਲਿਆ", - "dash_dialog": { - "title": "ਡਸ਼ ਮੀਡੀਆ ਨੂੰ ਡਾ Download ਨਲੋਡ ਕਰੋ", - "download_all": "ਸਾਰੇ ਡਾ Download ਨਲੋਡ ਕਰੋ", - "segment_text": "ਖੰਡ __ ਪਲੇਸੋਲਡਰ_0__ - __ ਪਲੇਸਡੋਲਡਰ_1____" - } - }, - "streaks_reminder": { - "notification_title": "ਸਟ੍ਰੀਕਸ", - "notification_text": "__ ਪਲੇਸਧਾਰਕ_0_1__ ਸਾਲਾਂ ਵਿੱਚ ਤੁਹਾਡੀ ਲੜੀ ਨੂੰ __ ਪਲੇਸੋਲਡਰ_0__ ਦੇ ਨਾਲ ਆਪਣੀ ਲੜੀ ਗੁਆ ਲਓਗੇ" - }, - "biometric_auth": { - "unlock_button": "ਅਨਲੌਕ", - "title": "ਅਨਲੌਕ ਸਨਲੌਕ", - "subtitle": "ਸਕੈਚੈਟ ਨੂੰ ਅਨਲੌਕ ਕਰਨ ਲਈ ਪ੍ਰਮਾਣਿਤ ਕਰੋ" - }, - "end_to_end_encryption": { - "toolbox": { - "no_shared_key": "ਤੁਹਾਡੇ ਕੋਲ ਅਜੇ ਇਸ ਦੋਸਤ ਨਾਲ ਸਾਂਝਾ ਰਾਜ਼ ਨਹੀਂ ਹੈ. ਇੱਕ ਨਵਾਂ ਆਰੰਭ ਕਰਨ ਲਈ ਹੇਠਾਂ ਕਲਿੱਕ ਕਰੋ.", - "shared_key_fingerprint": "ਤੁਹਾਡਾ ਫਿੰਗਰਪ੍ਰਿੰਟ ਇਹ ਹੈ:\n\n__ ਪਲੇਸੋਲਡਰ_0____\n\nਇਹ ਯਕੀਨੀ ਬਣਾਓ ਕਿ ਕੀ ਇਹ ਤੁਹਾਡੇ ਦੋਸਤ ਦੇ ਫਿੰਗਰਪ੍ਰਿੰਟ ਨਾਲ ਮੇਲ ਖਾਂਦਾ ਹੈ!", - "initiate_exchange_button": "ਕੁੰਜੀ ਐਕਸਚੇਂਜ ਦੀ ਸ਼ੁਰੂਆਤ ਕਰੋ" - }, - "confirmation_dialogs": { - "title": "ਅੰਤ ਤੋਂ-ਅੰਤ ਇਨਕ੍ਰਿਪਸ਼ਨ", - "confirmation_1": "ਚੇਤਾਵਨੀ: ਇਹ ਤੁਹਾਡੀ ਮੌਜੂਦਾ ਕੁੰਜੀ ਨੂੰ ਮੁੜ ਲਿਖ ਦੇਵੇਗਾ. ਤੁਸੀਂ ਇਸ ਦੋਸਤ ਦੇ ਸਾਰੇ ਇਨਕ੍ਰਿਪਟਡ ਸੁਨੇਹਿਆਂ ਦੀ ਪਹੁੰਚ loose ਿੱਲੀ ਕਰੋਗੇ. ਕੀ ਤੁਸੀਂ ਯਕੀਨਨ ਜਾਰੀ ਰੱਖਣਾ ਚਾਹੁੰਦੇ ਹੋ?", - "confirmation_2": "ਕੀ ਤੁਸੀਂ ਸੱਚਮੁੱਚ ਯਕੀਨਨ ਜਾਰੀ ਰੱਖਣਾ ਚਾਹੁੰਦੇ ਹੋ? ਇਹ ਵਾਪਸ ਆਉਣ ਦਾ ਆਖਰੀ ਮੌਕਾ ਹੈ." - }, - "unencrypted_conversation_send_failure_toast": "ਤੁਸੀਂ ਐਨਕ੍ਰਿਪਟਡ ਸਮੱਗਰੀ ਨੂੰ ਐਨਕ੍ਰਿਪਟਡ ਅਤੇ ਨਾ-ਕ੍ਰਿਕਟਡ ਗੱਲਬਾਤ ਵਿੱਚ ਭੇਜ ਨਹੀਂ ਸਕਦੇ!", - "native_hooks_send_failure_toast": "ਭੇਜਣ ਵਿੱਚ ਅਸਫਲ! ਕਿਰਪਾ ਕਰਕੇ ਸੈਟਿੰਗਾਂ ਵਿੱਚ ਦੇਸੀ ਹੁੱਕਾਂ ਨੂੰ ਸਮਰੱਥ ਕਰੋ.", - "no_participants_to_encrypt_toast": "ਇਸ ਨਾਲ ਸੰਦੇਸ਼ਾਂ ਨੂੰ ਇਨਕ੍ਰਿਪਟ ਕਰਨ ਲਈ ਤੁਹਾਡੇ ਕੋਈ ਦੋਸਤ ਨਹੀਂ ਹਨ!", - "encryption_failed_toast": "ਸੁਨੇਹੇ ਨੂੰ ਇੰਕ੍ਰਿਪਟ ਕਰਨ ਵਿੱਚ ਅਸਫਲ! ਵਧੇਰੇ ਜਾਣਕਾਰੀ ਲਈ ਲੌਗਕੈਟ ਦੀ ਜਾਂਚ ਕਰੋ.", - "accept_public_key_success_toast": "ਪਬਲਿਕ ਕੁੰਜੀ ਸਫਲਤਾਪੂਰਵਕ ਸਵੀਕਾਰ ਕਰ ਲਈ ਗਈ!", - "accept_secret_key_success_toast": "ਕੀਤਾ! ਤੁਸੀਂ ਹੁਣ ਇਸ ਦੋਸਤ ਨਾਲ ਇਨਕ੍ਰਿਪਟਡ ਸੁਨੇਹੇ ਭੇਜ ਅਤੇ ਪ੍ਰਾਪਤ ਕਰ ਸਕਦੇ ਹੋ.", - "accept_public_key_failure_toast": "ਜਨਤਕ ਕੁੰਜੀ ਨੂੰ ਸਵੀਕਾਰ ਕਰਨ ਵਿੱਚ ਅਸਫਲ", - "accept_secret_key_failure_toast": "ਗੁਪਤ ਕੁੰਜੀ ਨੂੰ ਸਵੀਕਾਰ ਕਰਨ ਵਿੱਚ ਅਸਫਲ", - "accept_secret_button": "ਗੁਪਤ ਸਵੀਕਾਰ ਕਰੋ", - "accept_public_key_button": "ਜਨਤਕ ਕੁੰਜੀ ਨੂੰ ਸਵੀਕਾਰ ਕਰੋ", - "outgoing_pk_message": "ਕੁੰਜੀ ਐਕਸਚੇਂਜ ਦੀ ਬੇਨਤੀ", - "outgoing_secret_message": "ਕੁੰਜੀ ਐਕਸਚੇਂਜ ਜਵਾਬ", - "incoming_pk_message": "ਤੁਹਾਨੂੰ ਹੁਣੇ ਹੀ ਜਨਤਕ ਕੁੰਜੀ ਬੇਨਤੀ ਮਿਲੀ ਹੈ. ਇਸ ਨੂੰ ਸਵੀਕਾਰ ਕਰਨ ਲਈ ਹੇਠਾਂ ਕਲਿੱਕ ਕਰੋ.", - "incoming_secret_message": "ਤੁਹਾਡੇ ਦੋਸਤ ਨੇ ਹੁਣੇ ਆਪਣੀ ਜਨਤਕ ਕੁੰਜੀ ਨੂੰ ਸਵੀਕਾਰ ਕਰ ਲਿਆ. ਗੁਪਤ ਸਵੀਕਾਰ ਕਰਨ ਲਈ ਹੇਠਾਂ ਕਲਿੱਕ ਕਰੋ." - }, - "auto_open_snaps": { - "title": "ਆਟੋ ਓਪਨ ਸਨੈਪਸ", - "notification_content": "__ ਪਲੇਸਡੋਲਡਰ_0 __ ਤੇ ਜਾਓ" - }, - "friend_mutation_observer": { - "notification_channel_name": "ਮਿੱਤਰ ਪਰਿਵਰਤਨ ਆਬਜ਼ਰਵਰ", - "friend_removed": "__ ਪਲੇਸੋਲਡਰ_0__ ਤੁਹਾਡੇ ਨੂੰ ਇੱਕ ਦੋਸਤ ਵਜੋਂ ਹਟਾ ਦਿੱਤਾ ਹੈ", - "birthday_removed": "__ ਪਲੇਸਹੋਲਡਰ_0__ ਨੇ ਆਪਣਾ ਜਨਮਦਿਨ ਹਟਾ ਦਿੱਤਾ ਹੈ (__ ਪਲੇਸਡੋਲਡਰ_1____)", - "birthday_added": "__ ਪਲੇਸੋਲਡਰ_0__ ਨੇ ਉਨ੍ਹਾਂ ਦੇ ਜਨਮਦਿਨ ਨੂੰ ਜੋੜਿਆ (__ ਪਲੇਸਡੋਲਡਰ_1____)", - "birthday_changed": "__ ਪਲੇਸਹੋਲਡਰ_0____ ਆਪਣੇ ਜਨਮਦਿਨ ਨੂੰ __ ਪਲੇਸਧਾਰਕ_1__ ਤੋਂ __ ਪਲੇਸਹੋਲਡਰ_2 ਤੋਂ ਬਦਲਿਆ ਹੈ", - "bitmoji_selfie_changed": "__ ਪਲੇਸਹੋਲਡਰ_0__ ਨੇ ਆਪਣੇ ਬਿੱਟਮੋਜੀ ਸੈਲਫੀ ਨੂੰ ਬਦਲਿਆ ਹੈ", - "bitmoji_avatar_changed": "__ ਪਲੇਸੋਲਡਰ_0__ ਨੇ ਆਪਣੇ ਬਿੱਟਮੋਜੀ ਅਵਤਾਰ ਨੂੰ ਬਦਲਿਆ ਹੈ", - "bitmoji_background_changed": "__ ਪਲੇਸਹੋਲਡਰ_0__ ਨੇ ਆਪਣਾ ਬਿੱਟਮੋਜੀ ਪਿਛੋਕੜ ਬਦਲਿਆ ਹੈ", - "bitmoji_scene_changed": "__ ਪਲੇਸੋਲਡਰ_0____ ਨੇ ਆਪਣੇ ਬਿੱਟਮਜੀ ਦ੍ਰਿਸ਼ ਨੂੰ ਬਦਲਿਆ ਹੈ" - }, - "material3_strings": { - "date_range_picker_start_headline": "ਤੋਂ", - "date_range_picker_end_headline": "ਨੂੰ", - "date_range_picker_title": "ਤਾਰੀਖ ਦੀ ਸੀਮਾ ਚੁਣੋ", - "date_picker_switch_to_calendar_mode": "ਕੈਲੰਡਰ", - "date_picker_switch_to_input_mode": "ਇੰਪੁੱਟ", - "date_range_picker_scroll_to_previous_month": "ਪਿਛਲੇ ਮਹੀਨੇ", - "date_range_picker_scroll_to_next_month": "ਅਗਲੇ ਮਹੀਨੇ", - "date_picker_today_description": "ਅੱਜ", - "date_range_picker_day_in_range": "ਚੁਣਿਆ", - "date_input_invalid_for_pattern": "ਗਲਤ ਤਾਰੀਖ", - "date_input_invalid_year_range": "ਅਵੈਧ ਸਾਲ", - "date_input_invalid_not_allowed": "ਗਲਤ ਤਾਰੀਖ", - "date_range_input_invalid_range_input": "ਗਲਤ ਮਿਤੀ ਸੀਮਾ" - }, - "send_override_dialog": { - "title": "ਮੀਡੀਆ ਨੂੰ __ ਪਲੇਸੋਲਡਰ_0__ ਦੇ ਤੌਰ ਤੇ ਭੇਜੋ", - "duration": "ਅਵਧੀ: __ ਪਲੇਸੋਲਡਰ_0____", - "saveable_snap_hint": "ਗੱਲਬਾਤ ਵਿੱਚ ਸੇਵ ਹੋਣ ਯੋਗ ਬਣਾਓ", - "unlimited_duration": "ਅਸੀਮਤ" - }, - "invalid_input_toast": "ਗਲਤ ਇਨਪੁਟ! ਇਹ ਸੁਨਿਸ਼ਚਿਤ ਕਰੋ ਕਿ ਤੁਸੀਂ ਇੱਕ ਵੈਧ ਮੁੱਲ ਦਾਖਲ ਕੀਤਾ ਹੈ." -} \ No newline at end of file diff --git a/common/src/main/assets/lang/pl.json b/common/src/main/assets/lang/pl.json index 2e852196..3638c585 100644 --- a/common/src/main/assets/lang/pl.json +++ b/common/src/main/assets/lang/pl.json @@ -1,614 +1,234 @@ { "setup": { "dialogs": { - "select_language": "Wybierz Język", - "save_folder": "PurrfectSnap wymaga uprawnień do przechowywania, aby pobierać i zapisywać multimedia ze Snapchata.\nWybierz lokalizację, do której mają zostać pobrane multimedia.", + "select_language": "Wybierz język", + "save_folder": "SnapEnhance wymaga uprawnień do przechowywania danych w celu pobierania i zapisywania mediów z Snapchat.\nProszę wybrać lokalizację, do której media powinny być pobierane.", "select_save_folder_button": "Wybierz Folder" }, "mappings": { - "dialog": "Generowanie mapowań może chwilę potrwać...", - "generate_failure_no_snapchat": "PurrfectSnap nie mógł wykryć Snapchata. Spróbuj ponownie zainstalować Snapchata.", - "generate_failure": "Wystąpił błąd podczas próby wygenerowania mapowań. Spróbuj ponownie." + "dialog": "Aby dynamicznie obsługiwać szeroki zakres wersji Snapchat, konieczne są mapowania, aby SnapEnhance działał poprawnie. To nie powinno zająć więcej niż 5 sekund.", + "generate_failure_no_snapchat": "SnapEnhance nie było w stanie wykryć Snapchata, spróbuj ponownie zainstalować Snapchat.", + "generate_failure": "Wystąpił błąd podczas próby generowania mapowań, spróbuj ponownie." }, "permissions": { - "dialog": "Aby kontynuować, musisz spełnić następujące wymagania:", + "dialog": "Aby kontynuować, musisz spełnić poniższe wymagania:", "notification_access": "Dostęp do powiadomień", "battery_optimization": "Optymalizacja baterii", - "display_over_other_apps": "Wyświetlaj nad innymi aplikacjami", - "request_button": "Wniosek" + "display_over_other_apps": "Wyświetlanie nad innymi aplikacjami", + "request_button": "Wymagania" } }, + "manager": { + "routes": { + "features": "Cechy", + "home": "Strona główna", + "home_settings": "Ustawienia", + "home_logs": "Logi", + "social": "Społeczność", + "scripts": "Skrypty", + "messaging_preview": "Podgląd", + "tasks": "Zadania" + }, + "sections": { + "features": { + "disabled": "Wyłączony" + }, + "home": { + "update_title": "Aktualizacja SnapEnchance", + "update_content": "Wersja {version} jest dostępna!", + "update_button": "Pobierz" + }, + "home_logs": { + "no_logs_hint": "Brak Dostępnych Logów", + "clear_logs_button": "Wyczyść Logi", + "export_logs_button": "Eksportuj Logi", + "saved_logs_success_toast": "Logi Zapisane Pomyślnie", + "saved_logs_failure_toast": "Nie udało zapisać sie logów", + "saving_logs_toast": "Zapisywanie logów, To może chwile potrwać ..." + }, + "home_settings": { + "message_logger_summary": "{messageCount} Wiadomości\n{storyCount} Story", + "success_toast": "Gotowe!", + "export_button": "Eksport", + "actions_title": "Akcja", + "clear_button": "Czysto" + } + }, + "dialogs": { + "export_config": { + "title": "Eksportować wrażliwe dane?", + "content": "Czy chcesz wyeksportować konfigurację z wrażliwymi danymi? (Takie jak współrzędne lokalizacji itp.)" + }, + "file_imports": { + "settings_select_file_hint": "Wybierz zaimportowany plik", + "no_files_settings_hint": "Nie znaleziono plików. Upewnij się, że zaimportowałeś wymagane pliki w sekcji \"Importy plików\"" + }, + "scripting_warning": { + "title": "Ostrzeżenie", + "content": "SnapEnhance zawiera narzędzie skryptowe, umożliwiające wykonanie zdefiniowanego przez użytkownika kodu na Twoim urządzeniu. Używaj z szczególną ostrożnością i instaluj moduły z znanego, wiarygodnego źródła. Nieautoryzowane lub niezweryfikowane moduły mogą stwarzać zagrożenie dla twojego systemu." + }, + "reset_config": { + "success_toast": "Konfiguracja została pomyślnie zresetowana", + "title": "Uruchom ponownie konfigurację", + "content": "Czy na pewno chcesz zresetować konfigurację?" + }, + "messaging_action": { + "select_all_button": "Zaznacz wszystko", + "title": "Wybierz typy treści do przetworzenia" + } + } + }, + "friend_menu_option": { + "preview": "Podgląd", + "stealth_mode": "Tryb Stealth", + "auto_download_blacklist": "Automatyczne pobieranie czarnej listy", + "anti_auto_save": "Anty-automatyczne zapisywanie" + }, + "chat_action_menu": { + "preview_button": "Podgląd", + "download_button": "Pobierz", + "delete_logged_message_button": "Usuń zarejestrowaną wiadomość" + }, + "opera_context_menu": { + "download": "Pobierz media" + }, + "modal_option": { + "profile_info": "Info o profilu", + "close": "Zamknij" + }, + "gallery_media_send_override": { + "multiple_media_toast": "Możesz wysłać tylko jeden nośnik na raz" + }, + "conversation_preview": { + "streak_expiration": "wygasa za {day} dni {hour} godziny {minute} minuty", + "total_messages": "Łączna liczba wysłanych/odebranych wiadomości: {count}", + "title": "Podgląd", + "unknown_user": "Nieznany użytkownik" + }, + "profile_info": { + "title": "Info o profilu", + "display_name": "Wyświetl nazwę", + "added_date": "Dodaj datę", + "birthday": "Urodziny : {month} {day}" + }, + "chat_export": { + "dialog_negative_button": "Anuluj", + "dialog_positive_button": "Eksportuj", + "exported_to": "Wyeksportowano do {path}", + "exporting_chats": "Eksportowanie czatów...", + "processing_chats": "Przetwarzanie rozmów {amount}...", + "export_fail": "Nie udało się wyeksportować rozmowy {conversation}", + "writing_output": "Zapisywanie danych...", + "finished": "Gotowe! Teraz możesz zamknąć to okno.", + "no_messages_found": "Nie znaleziono wiadomości!", + "exporting_message": "Eksportowanie {conversation}..." + }, + "button": { + "ok": "Ok", + "positive": "Tak", + "negative": "Nie", + "cancel": "Anuluj", + "open": "Otwórz" + }, + "download_processor": { + "download_started_toast": "Rozpoczęto pobieranie", + "unsupported_content_type_toast": "Nieobsługiwany typ treści!", + "failed_no_longer_available_toast": "Media już niedostępne", + "already_queued_toast": "Media są już w kolejce!", + "already_downloaded_toast": "Media już pobrane!", + "download_toast": "Pobieranie {path}...", + "processing_toast": "Przetwarzanie {path}...", + "failed_generic_toast": "Pobieranie nie powiodło się", + "failed_to_create_preview_toast": "Nie można wczytać podglądu" + }, "scopes": { "friend": "Przyjaciel", "group": "Grupa" }, - "manager": { - "routes": { - "tasks": "Zadania", - "features": "Cechy", - "manage_rule_feature": "Zarządzaj funkcją reguły", - "home": "Dom", - "home_settings": "Ustawienia", - "home_logs": "Dzienniki", - "logger_history": "Historia rejestratora", - "logged_stories": "Zarejestrowane historie", - "friend_tracker": "Śledzenie znajomych", - "edit_rule": "Edytuj regułę", - "file_imports": "Import plików", - "manage_repos": "Zarządzaj repozytoriami", - "social": "Społeczny", - "manage_scope": "Zarządzaj zakresem", - "messaging_preview": "Zapowiedź", - "scripts": "Skrypty", - "better_location": "Lepsza lokalizacja" - }, - "sections": { - "home": { - "version_title": "v{versionName} · rozwidlony przez Eternal", - "update_title": "Aktualizacja PurrfectSnap", - "update_content": "Wersja {version} jest dostępna!", - "update_button": "Pobierać", - "debug_build_summary_title": "Używasz kompilacji debugowania PurrfectSnap", - "debug_build_summary_content": "Wersja {versionName} ({versionCode})", - "debug_build_summary_date": "Data kompilacji: {date} ({days} dni temu)", - "quick_actions_title": "Szybkie działania", - "download_icon_description": "Pobierać", - "completed_icon_description": "Zakończony", - "failed_icon_description": "Przegrany", - "manage_quick_actions_description": "Zarządzaj szybkimi akcjami", - "quick_actions_icon_description": "Szybkie działania", - "add_quick_action_description": "Dodaj szybką akcję" - }, - "home_logs": { - "no_logs_hint": "Brak dostępnych logów", - "clear_logs_button": "Wyczyść dzienniki", - "export_logs_button": "Eksportuj dzienniki", - "saving_logs_toast": "Zapisywanie logów może chwilę potrwać...", - "saved_logs_success_toast": "Logi zostały zapisane pomyślnie", - "saved_logs_failure_toast": "Nie udało się zapisać logów" - }, - "home_settings": { - "actions_title": "Działania", - "message_logger_title": "Rejestrator wiadomości", - "debug_title": "Odpluskwić", - "success_toast": "Zrobione!", - "message_logger_summary": "{messageCount} wiadomości\n{storyCount} historie", - "export_button": "Eksport", - "clear_button": "Jasne", - "view_logger_history_button": "Wyświetl historię rejestratora", - "updates_title": "Aktualizacje", - "auto_update_check": "Automatyczne sprawdzanie dostępności aktualizacji", - "update_check_frequency": "Aktualizuj częstotliwość sprawdzania", - "update_check_frequency_daily": "Codziennie", - "update_check_frequency_weekly": "Tygodnik", - "update_check_frequency_monthly": "Miesięczny", - "theme_icon_description": "Temat", - "app_theme_title": "Motyw aplikacji", - "theme_mode_system": "System", - "theme_mode_light": "Światło", - "theme_mode_dark": "Ciemny", - "ui_settings_title": "Ustawienia interfejsu użytkownika", - "haptic_feedback_label": "Informacje zwrotne dotykowe", - "test_mode_label": "Tryb testowy (TYLKO DO DEBUGOWANIA)", - "disable_feature_loading_label": "Wyłącz ładowanie funkcji", - "disable_auto_mapper_label": "Wyłącz funkcję automatycznego mapowania", - "disable_bypass_indicator_label": "Wyłącz wskaźnik stanu obejścia", - "update_notification_channel_name": "Aktualizacje PurrfectSnap", - "update_notification_channel_description": "Powiadomienia o aktualizacjach PurrfectSnap", - "update_notification_title": "Dostępna aktualizacja PurrfectSnap", - "update_notification_text": "Wersja %s jest już dostępna.", - "export_database_failed_toast": "Nie udało się wyeksportować bazy danych! __ symbol zastępczy_0__", - "clear_messages_failed_toast": "Nie udało się usunąć wiadomości! __ symbol zastępczy_0__", - "clear_file_failed_toast": "Nie udało się wyczyścić pliku! __ symbol zastępczy_0__", - "debug_file_config": "Konfiguracja", - "debug_file_mappings": "Mapowania", - "debug_file_message_logger": "Rejestrator wiadomości", - "debug_file_pinned_best_friend": "Przypięty najlepszy przyjaciel", - "debug_file_native_sig_cache": "Natywna pamięć podręczna podpisów" - }, - "tasks": { - "no_tasks": "Brak zadań", - "merge_button": "Łączyć", - "failed_to_open_file": "Nie udało się otworzyć pliku", - "merge_files_toast": "Łączenie plików {count}", - "remove_selected_tasks_title": "Czy na pewno chcesz usunąć wybrane zadania?", - "remove_all_tasks_title": "Czy na pewno chcesz usunąć wszystkie zadania?", - "delete_files_option": "Usuń także pliki", - "remove_selected_tasks_confirm": "Usunąć zadania {count}?", - "remove_all_tasks_confirm": "Usunąć wszystkie zadania?", - "clear_tasks_description": "Wyczyść zadania", - "file_not_found_icon_description": "Nie znaleziono pliku", - "image_icon_description": "Obraz", - "video_icon_description": "Wideo", - "audio_icon_description": "Audio", - "file_icon_description": "Plik", - "download_icon_description": "Pobierać", - "chat_action_icon_description": "Akcja na czacie", - "cancel_icon_description": "Anulować", - "success_icon_description": "Sukces", - "failure_icon_description": "Awaria", - "cancelled_icon_description": "Odwołany", - "task_status_failure": "Awaria", - "task_status_cancelled": "Odwołany" - }, - "features": { - "disabled": "Wyłączony", - "export_option": "Eksport", - "import_option": "Import", - "reset_option": "Nastawić", - "config_export_success_toast": "Konfiguracja została pomyślnie wyeksportowana", - "config_import_success_toast": "Konfiguracja została zaimportowana pomyślnie", - "config_import_failure_toast": "Nie udało się zaimportować konfiguracji {error}", - "config_export_failure_toast": "Nie udało się wyeksportować konfiguracji {error}", - "saved_config_snackbar": "Konfiguracja zapisana", - "older_required": "Ta funkcja wymaga do prawidłowego działania aplikacji Snapchat w wersji v{version} lub starszej", - "newer_required": "Ta funkcja wymaga do prawidłowego działania aplikacji Snapchat w wersji v{version} lub nowszej", - "search_button": "Szukaj" - }, - "manage_rule_feature": { - "disable_state_option": "Wyłączony", - "disable_state_subtext": "Nie będzie to miało wpływu na żadnych znajomych/grupy", - "whitelist_state_option": "Nikt oprócz...", - "whitelist_state_subtext": "Ta reguła będzie miała wpływ tylko na {count} znajomych/grupy", - "whitelist_state_button": "Wybierz dozwolonych znajomych/grupy", - "blacklist_state_option": "Wszyscy oprócz...", - "blacklist_state_subtext": "Ta reguła będzie dotyczyć wszystkich oprócz {count} znajomych/grup", - "blacklist_state_button": "Wybierz wykluczonych znajomych/grupy", - "clear_list_button": "Wyczyść listę znajomych/grup", - "dialog_clear_confirmation_text": "Czy na pewno chcesz wyczyścić listę?" - }, - "social": { - "friends_tab": "Przyjaciele", - "groups_tab": "Grupy", - "empty_hint": "(pusty)", - "streaks_expiration_short": "{hours}h" - }, - "manage_scope": { - "logged_stories_button": "Pokaż zarejestrowane historie", - "e2ee_title": "Szyfrowanie typu end-to-end", - "rules_title": "Zasady", - "participants_text": "{count} uczestników", - "not_found": "Nie znaleziono", - "streaks_title": "Pasemko", - "streaks_length_text": "Długość: {length}", - "streaks_expiration_text": "Wygasa za {eta}", - "streaks_expiration_text_expired": "Wygasły", - "reminder_button": "Ustaw przypomnienie", - "delete_scope_confirm_dialog_title": "Czy na pewno chcesz usunąć {scope}?", - "notes_placeholder": "Kliknij, aby dodać notatkę", - "invalid_key_size_32_bytes": "Nieprawidłowy rozmiar klucza (musi mieć 32 bajty)", - "successfully_imported_key": "Pomyślnie zaimportowano klucz", - "failed_to_import_key": "Nie udało się zaimportować klucza: {message}", - "export_base64_button": "Eksportuj Base64", - "import_base64_button": "Importuj Base64" - }, - "logged_stories": { - "story_failed_to_load": "Nie udało się załadować", - "no_stories": "Nie znaleziono żadnych historii", - "save_from_cache_button": "Zapisz z pamięci podręcznej", - "downloaded_to_path": "Pobrano do {path}", - "download_failed": "Pobieranie nie powiodło się: {message}", - "posted_at": "Opublikowano w {date}", - "created_at": "Utworzono w {date}", - "failed_to_open_file": "Nie udało się otworzyć pliku. Sprawdź dzienniki, aby uzyskać więcej informacji", - "failed_to_get_file": "Nie udało się pobrać pliku" - }, - "messaging_preview": { - "processed_messages_toast": "Przetworzone wiadomości {count}", - "processed_messages_text": "Przetworzone wiadomości {count}", - "close_button_description": "Zamknąć", - "bridge_connection_failed": "Nie udało się połączyć z mostem. Upewnij się, że Snapchat działa w tle", - "bridge_init_failed": "Nie udało się zainicjować mostu komunikacyjnego. Upewnij się, że Snapchat działa w tle", - "message_fetch_failed": "Nie udało się pobrać wiadomości", - "no_message_hint": "Brak wiadomości", - "save_selection_option": "Zapisz wybór", - "save_all_option": "Zapisz wszystko", - "unsave_selection_option": "Anuluj zapisanie wyboru", - "unsave_all_option": "Usuń zapisywanie wszystkich", - "mark_selection_as_seen_option": "Oznacz wybrany Snap jako widoczny", - "mark_all_as_seen_option": "Oznacz wszystkie Snapy jako widoczne", - "delete_selection_option": "Usuń zaznaczenie", - "delete_all_option": "Usuń wszystko" - }, - "logger_history": { - "download_started_toast": "Pobieranie rozpoczęte!", - "download_success_toast": "Pobrano do {path}", - "download_failed_toast": "Nie udało się pobrać {message}", - "edited_at_text": "{message} (edytowano w {date})", - "download_button": "Pobierać", - "select_conversation_placeholder": "Wybierz rozmowę", - "close_button_description": "Zamknąć", - "search_button_description": "Szukaj", - "list_friend_format": "Przyjaciel {name}", - "list_group_format": "Grupa {name}", - "no_more_messages": "Żadnych więcej wiadomości", - "reverse_order_checkbox": "Odwrotna kolejność", - "chat_attachment": "Załącznik {index}", - "empty_message": "Pusta wiadomość czatu", - "message_parse_failed": "Nie udało się przeanalizować wiadomości", - "unknown_sender": "Nieznany nadawca", - "download_attachment_failed_toast": "Nie udało się pobrać załącznika", - "log_header_format": "{username} ({type}) - {date}" - }, - "file_imports": { - "import_file_button": "Importuj plik", - "file_not_found": "Nie znaleziono pliku", - "file_import_failed": "Nie udało się zaimportować pliku: {error}", - "file_imported": "Plik zaimportowano pomyślnie", - "file_delete_failed": "Nie udało się usunąć pliku", - "no_files_hint": "Tutaj możesz importować pliki do użytku w Snapchacie. Naciśnij przycisk poniżej, aby zaimportować plik." - }, - "better_location": { - "spoofed_coordinates_title": "Lat {latitude}, Lng {longitude}", - "save_coordinates_dialog_title": "Zapisz współrzędne", - "saved_name_dialog_hint": "Zapisana nazwa", - "latitude_dialog_hint": "Szerokość", - "longitude_dialog_hint": "Długość geograficzna", - "save_dialog_button": "Ratować", - "choose_location_button": "Wybierz lokalizację", - "teleport_to_friend_button": "Teleportuj się do znajomego", - "spoof_location_toggle": "Fałszywa lokalizacja", - "suspend_location_updates": "Zawieś aktualizacje lokalizacji", - "saved_coordinates_title": "Zapisane współrzędne", - "no_saved_coordinates_hint": "Brak zapisanych współrzędnych", - "delete_dialog_title": "Usuń zapisaną współrzędną", - "delete_dialog_message": "Czy na pewno chcesz usunąć tę zapisaną współrzędną?", - "teleport_to_friend_title": "Teleportuj się do znajomego", - "search_bar": "Szukaj", - "no_friends_map": "Brak znajomych na mapie", - "no_friends_found": "Nie znaleziono znajomych", - "edit_location_button_description": "Edytuj lokalizację", - "add_icon_description": "Dodać", - "edit_icon_description": "Redagować", - "delete_icon_description": "Usuwać" - } - }, - "dialogs": { - "add_friend": { - "title": "Dodaj znajomego lub grupę", - "search_hint": "Szukaj", - "fetch_error": "Nie udało się pobrać danych", - "category_groups": "Grupy", - "category_friends": "Przyjaciele", - "participants_text": "{count} uczestników", - "search_icon_description": "Szukaj" - }, - "scripting_warning": { - "title": "Ostrzeżenie", - "content": "PurrfectSnap zawiera narzędzie skryptowe, umożliwiające wykonanie kodu zdefiniowanego przez użytkownika na Twoim urządzeniu. Zachowaj szczególną ostrożność i instaluj moduły wyłącznie ze znanych, niezawodnych źródeł. Nieautoryzowane lub niezweryfikowane moduły mogą stwarzać zagrożenie bezpieczeństwa Twojego systemu." - }, - "reset_config": { - "title": "Zresetuj konfigurację", - "content": "Czy na pewno chcesz zresetować konfigurację?", - "success_toast": "Konfiguracja została pomyślnie zresetowana" - }, - "export_config": { - "title": "Eksportować wrażliwe dane?", - "content": "Czy chcesz wyeksportować konfigurację z wrażliwymi danymi? (Takie jak współrzędne lokalizacji itp.)" - }, - "messaging_action": { - "title": "Wybierz typy treści do przetworzenia", - "select_all_button": "Wybierz wszystko" - }, - "file_imports": { - "no_files_settings_hint": "Nie znaleziono plików. Upewnij się, że zaimportowałeś wymagane pliki w sekcji Importy plików", - "settings_select_file_hint": "Wybierz zaimportowany plik" - }, - "quick_actions_dialog": { - "title": "Edytuj szybkie akcje", - "subtitle": "Wybierz i dostosuj swoje szybkie działania." - } - }, - "friend_tracker": { - "rules_tab": "Zasady", - "logs_tab": "Dzienniki", - "export_dialog_title": "Eksport", - "bulk_export_button": "Eksport zbiorczy", - "individual_export_button": "Eksport indywidualny", - "invalid_import_type_dialog_title": "Nieprawidłowy typ importu", - "invalid_import_type_dialog_text": "Wybrany plik nie jest zgodny z tym typem importu. Wybierz właściwy typ importu.", - "import_dialog_title": "Import", - "bulk_import_button": "Import zbiorczy", - "individual_import_button": "Import indywidualny", - "import_button_description": "Import", - "export_button_description": "Eksport", - "export_button": "Eksport", - "delete_button_description": "Usuwać", - "delete_button": "Usuwać", - "catalog_button_description": "Katalog", - "catalog_button": "Katalog", - "add_rule_button_description": "Dodaj regułę", - "add_rule_button": "Dodaj regułę", - "no_rules_found": "Nie znaleziono żadnych reguł", - "empty_rule_name": "(pusty)", - "events_suffix": "wydarzenia", - "scopes_suffix": "zakresy", - "select_rule_to_export_title": "Wybierz regułę do eksportu", - "deleted_logs_toast": "Usunięto dzienniki {count}", - "delete_logs_dialog_title": "Usunąć logi?", - "deleting_logs_dialog_text": "Usuwanie dzienników {count}...", - "delete_logs_dialog_confirm_text": "Spowoduje to usunięcie dzienników na podstawie bieżącego filtra i zapytania. Tej akcji nie można cofnąć.", - "exported_logs_toast": "Wyeksportowane logi!", - "export_logs_failed_toast": "Nie udało się wyeksportować dzienników. Sprawdź logcat, aby uzyskać więcej szczegółów.", - "export_logs_dialog_title": "Eksportować logi?", - "exporting_logs_dialog_text": "Eksportowanie dzienników...", - "export_logs_dialog_confirm_text": "Spowoduje to wyeksportowanie dzienników na podstawie bieżącego filtra i zapytania.", - "export_as_button": "Eksportuj jako {type}", - "filters_title": "Filtry", - "search_by_label": "Wyszukaj według", - "newest_first_label": "Najpierw najnowsze", - "since_label": "Od", - "until_label": "Dopóki", - "pick_a_date_button": "Wybierz datę", - "search_placeholder": "Szukaj", - "filter_button_description": "Filtr", - "clear_button_description": "Jasne", - "no_logs_found": "Nie znaleziono dzienników", - "log_event_format": "{event} w {conversation}", - "condition_only_inside_conversation": "Tylko wtedy, gdy prowadzę rozmowę", - "condition_only_outside_conversation": "Tylko gdy jestem poza rozmową", - "condition_only_when_app_active": "Tylko wtedy, gdy Snapchat jest aktywny", - "condition_only_when_app_inactive": "Tylko wtedy, gdy Snapchat jest nieaktywny", - "condition_no_push_notification_when_app_active": "Brak powiadomienia, gdy Snapchat jest aktywny", - "add_event_dialog_title": "Dodaj wydarzenie", - "event_type_label": "Typ zdarzenia", - "triggers_title": "Wyzwalacze", - "conditions_title": "Warunki", - "add_button": "Dodać", - "default_rule_name": "Reguła niestandardowa", - "discard_changes_dialog_title": "Odrzucić zmiany?", - "discard_changes_dialog_text": "Masz niezapisane zmiany. Czy na pewno chcesz je odrzucić?", - "discard_button": "Wyrzucać", - "cannot_save_rule_dialog_title": "Nie można zapisać reguły", - "cannot_save_rule_dialog_text": "Reguła musi mieć co najmniej jedno zdarzenie do zapisania.", - "duplicate_rule_name_dialog_title": "Zduplikowana nazwa reguły", - "duplicate_rule_name_dialog_text": "Reguła o tej nazwie już istnieje. Proszę wybrać inną nazwę.", - "delete_rule_dialog_title": "Usuń regułę", - "delete_rule_dialog_text": "Czy na pewno chcesz usunąć tę regułę?", - "new_rule_title": "Nowa zasada", - "edit_rule_title": "Edytuj regułę", - "back_button_description": "Z powrotem", - "save_button_description": "Ratować", - "general_section_title": "Ogólny", - "rule_name_label": "Nazwa reguły", - "author_name_label": "Imię autora", - "scope_section_title": "Zakres", - "scope_all": "Wszystko", - "scope_whitelist": "Biała lista", - "scope_blacklist": "Czarna lista", - "select_friends_groups_button": "Wybierz znajomych/grupy ({count})", - "events_section_title": "Wydarzenia", - "add_event_button": "Dodaj wydarzenie", - "no_events_text": "Brak wydarzeń" - }, - "friend_tracker_catalog": { - "download_failed": "Nie udało się pobrać: {code}", - "error": "Błąd: {message}", - "no_repos_added": "Nie dodano żadnych repozytoriów.", - "no_rules_available": "Żadne reguły nie są dostępne w żadnym repozytorium.", - "by_author": "przez {author}", - "imported_button": "Importowany", - "import_button": "Import", - "title": "Katalog śledzenia znajomych", - "manage_repos_description": "Zarządzaj repozytoriami" - }, - "friend_tracker_export": { - "title": "Reguły eksportu", - "back_button_description": "Z powrotem", - "exported_toast": "Wyeksportowano reguły śledzenia znajomych!", - "export_failed_toast": "Nie udało się wyeksportować reguł: {message}", - "save_button": "Ratować", - "expand_button_description": "Zwiększać" - }, - "friend_tracker_import": { - "title": "Reguły importu", - "back_button_description": "Z powrotem", - "imported_toast": "Zaimportowano reguły śledzenia znajomych!", - "import_failed_toast": "Nie udało się zaimportować reguł: {message}", - "confirm_button": "Potwierdzać", - "expand_button_description": "Zwiększać" - }, - "friend_tracker_repos": { - "invalid_repo_title": "Nieprawidłowe repozytorium", - "add_repo_button": "Dodaj repozytorium", - "add_repo_dialog_title": "Dodaj adres URL repozytorium", - "repo_url_label": "Adres URL repozytorium", - "repo_added_toast": "Repozytorium dodano pomyślnie!", - "invalid_repo_error": "To nie wygląda na prawidłowe repozytorium narzędzia do śledzenia znajomych.", - "add_repo_failed_toast": "Nie udało się dodać repozytorium: {message}", - "add_button": "Dodać", - "no_repos_added": "Nie dodano żadnych repozytoriów", - "remove_button": "Usunąć", - "remove_repo_dialog_title": "Usuń repozytorium", - "remove_repo_dialog_text": "Czy na pewno chcesz usunąć to repozytorium?" - }, - "navigation": { - "tracker_tab_label": "Abstrakt", - "customize_bottom_bar_title": "Dostosuj dolny pasek", - "customize_bottom_bar_subtitle": "Zmień kolejność, dodaj lub usuń karty. Maksymalnie pięć.", - "shown_tabs_title": "Pokazane zakładki", - "no_tabs_selected_text": "Nie wybrano żadnych kart", - "available_tabs_title": "Dostępne zakładki", - "reset_button": "Nastawić", - "done_button": "Zrobione" - }, - "scripting": { - "script_already_installed": "Skrypt już zainstalowany!", - "downloading_script": "Pobieram skrypt...", - "script_downloaded": "Skrypt {name} pobrany!", - "download_script_failed": "Nie udało się pobrać skryptu. Sprawdź dzienniki, aby uzyskać więcej szczegółów", - "import_script_from_url_title": "Importuj skrypt z adresu URL", - "import_script_warning": "Ostrzeżenie: zaimportowane skrypty mogą być szkodliwe dla Twojego urządzenia. Importuj skrypty tylko z zaufanych źródeł.", - "enter_url_label": "Wpisz adres URL tutaj:", - "script_imported": "Skrypt {name} zaimportowany!", - "import_failed": "Nie udało się zaimportować skryptu. __element zastępczy_0__. Sprawdź dzienniki, aby uzyskać więcej szczegółów", - "import_button": "Import", - "update_module_button": "Aktualizuj moduł", - "updating_script": "Aktualizowanie skryptu {name}...", - "module_not_found": "Nie znaleziono modułu", - "updated_script": "Zaktualizowano {name} do wersji {version}", - "update_module_failed": "Nie udało się zaktualizować modułu. Sprawdź dzienniki, aby uzyskać więcej szczegółów", - "edit_module_button": "Edytuj moduł", - "open_module_failed": "Nie udało się otworzyć pliku modułu. Sprawdź dzienniki, aby uzyskać więcej szczegółów", - "clear_module_data_button": "Wyczyść dane modułu", - "module_data_cleared": "Dane modułu zostały usunięte!", - "clear_module_data_failed": "Nie udało się wyczyścić danych modułu. Sprawdź dzienniki, aby uzyskać więcej szczegółów", - "delete_module_button": "Usuń moduł", - "deleted_script": "Usunięto skrypt {name}!", - "delete_module_failed": "Nie udało się usunąć modułu. Sprawdź dzienniki, aby uzyskać więcej szczegółów", - "actions_title": "Działania", - "no_description": "Brak opisu", - "update_available": "Dostępna aktualizacja: {version}", - "actions_button": "Działania", - "loaded_script": "Załadowany skrypt {name}", - "unloaded_script": "Wyładowany skrypt {name}", - "enable_script_failed": "Nie udało się włączyć skryptu. Sprawdź dzienniki, aby uzyskać więcej szczegółów", - "disable_script_failed": "Nie udało się wyłączyć skryptu. Sprawdź dzienniki, aby uzyskać więcej szczegółów", - "select_scripts_folder_toast": "Proszę wybrać folder ze skryptami!", - "manage_repos_button": "Zarządzaj repozytoriami", - "import_from_url_button": "Importuj z adresu URL", - "open_scripts_folder_button": "Otwórz folder skryptów", - "no_settings_for_module": "Moduł ten nie posiada żadnych ustawień", - "installed_scripts_tab": "Zainstalowane skrypty", - "catalog_tab": "Katalog", - "no_scripts_folder_selected_title": "Nie wybrano folderu skryptów", - "select_folder_button": "Wybierz folder", - "no_scripts_found_title": "Nie znaleziono skryptów.", - "use_catalog_to_add_scripts": "Skorzystaj z zakładki Katalog, aby dodać skrypty!", - "ok_button_timeout": "OK ({timeout})", - "documentation_button": "Dokumentacja", - "catalog": { - "script_already_installed": "Skrypt już zainstalowany!", - "download_failed": "Nie udało się pobrać: {code}", - "script_downloaded": "Skrypt pobrany!", - "could_not_create_file": "Nie można utworzyć pliku.", - "no_scripts_folder_selected": "Nie wybrano folderu skryptów.", - "error": "Błąd: {message}", - "no_repos_added": "Nie dodano żadnych repozytoriów.", - "repo_list_info": "Tutaj znajdziesz listę repozytoriów:", - "link_text": "Połączyć", - "no_scripts_available": "Żadne skrypty nie są dostępne w żadnym repozytorium.", - "by_author": "przez {author}", - "version": "Wersja: {version}", - "installed_button": "Zainstalowany", - "download_button": "Pobierać" - }, - "repos": { - "invalid_repo_title": "Nieprawidłowe repozytorium", - "add_repo_button": "Dodaj repozytorium", - "add_repo_dialog_title": "Dodaj adres URL repozytorium", - "repo_url_label": "Adres URL repozytorium", - "repo_added_toast": "Repozytorium dodano pomyślnie!", - "invalid_repo_error": "To nie wygląda na prawidłowe repozytorium skryptów.", - "add_repo_failed_toast": "Nie udało się dodać repozytorium: {message}", - "add_button": "Dodać", - "no_repos_added": "Nie dodano żadnych repozytoriów", - "remove_button": "Usunąć", - "remove_repo_dialog_title": "Usuń repozytorium", - "remove_repo_dialog_text": "Czy na pewno chcesz usunąć to repozytorium?" - } - }, - "features": { - "config_import": { - "title": "Potwierdź import", - "back_button_description": "Z powrotem", - "config_imported_toast": "Konfiguracja zaimportowana!", - "confirm_button": "Potwierdzać", - "expand_button_description": "Zwiększać", - "enable_feature": "Włącz funkcję", - "enabled": "Włączony", - "disabled": "Wyłączony" - }, - "config_export": { - "title": "Podsumowanie eksportu", - "back_button_description": "Z powrotem", - "save_button": "Ratować", - "expand_button_description": "Zwiększać", - "enable_feature": "Włącz funkcję", - "enabled": "Włączony", - "disabled": "Wyłączony" - } - }, - "manage_repos": { - "title": "Zarządzaj repozytoriami {type}", - "add_repo_button": "Dodaj repozytorium", - "add_repo_dialog_title": "Dodaj adres URL repozytorium", - "repo_url_label": "Adres URL repozytorium", - "repo_added_successfully": "Repozytorium dodano pomyślnie!", - "add_repo_failed": "Nie udało się dodać repozytorium: {message}", - "add_button": "Dodać", - "no_repos_added": "Nie dodano żadnych repozytoriów", - "remove_button": "Usunąć" - } - }, "rules": { - "toasts": { - "enabled": "{ruleName} włączone", - "disabled": "{ruleName} wyłączony" - }, "modes": { "blacklist": "Tryb czarnej listy", "whitelist": "Tryb białej listy" }, "properties": { - "auto_download": { - "name": "Automatyczne pobieranie", - "description": "Automatycznie pobieraj Snapy podczas ich przeglądania", - "options": { - "blacklist": "Wyklucz z automatycznego pobierania", - "whitelist": "Automatyczne pobieranie" - } - }, "stealth": { - "name": "Tryb ukrycia", - "description": "Uniemożliwia innym dowiedzenie się, że otworzyłeś ich Snapy/czaty i rozmowy", "options": { - "blacklist": "Wyklucz z trybu ukrytego", - "whitelist": "Tryb ukrycia" - } + "whitelist": "Tryb ukrycia", + "blacklist": "Wyklucz z trybu ukrytego" + }, + "name": "Tryb ukrycia", + "description": "Uniemożliwia innym dowiedzenie się, że otworzyłeś ich Snapy/czaty oraz rozmowy" }, "auto_save": { "name": "Automatyczne zapisywanie", - "description": "Zapisuje wiadomości czatu podczas ich przeglądania", "options": { - "blacklist": "Wyklucz z automatycznego zapisywania", - "whitelist": "Automatyczne zapisywanie" - } + "whitelist": "Automatyczne zapisywanie", + "blacklist": "Wyklucz z automatycznego zapisywania" + }, + "description": "Zapisuje wiadomości czatu podczas ich przeglądania" + }, + "auto_download": { + "options": { + "whitelist": "Automatyczne pobieranie", + "blacklist": "Wyklucz z automatycznego pobierania" + }, + "name": "Automatyczne pobieranie", + "description": "Automatycznie pobieraj snapy, gdy je wyswietlasz" + }, + "auto_open_snaps": { + "options": { + "whitelist": "Automatyczne Otwieranie Snapów", + "blacklist": "Wyklucz z automatycznie otwieranych Snapów" + }, + "description": "Automatycznie otwiera Snapy po ich otrzymaniu" + }, + "pin_conversation": { + "name": "Przypnij konwersacje" + }, + "hide_friend_feed": { + "name": "Ukryj z Kanału znajomych" }, "unsaveable_messages": { "name": "Wiadomości, których nie można zapisać", - "description": "Zapobiega zapisywaniu wiadomości na czacie przez inne osoby", "options": { - "blacklist": "Wyklucz z wiadomości, których nie można zapisać", + "blacklist": "Wyklucz osoby z wiadomości, których nie można zapisać", "whitelist": "Wiadomości, których nie można zapisać" - } - }, - "auto_open_snaps": { - "name": "Automatyczne otwieranie zatrzasków", - "description": "Automatycznie otwiera Snapy po ich otrzymaniu", - "options": { - "blacklist": "Wyklucz z zatrzasków automatycznego otwierania", - "whitelist": "Automatyczne otwieranie zatrzasków" - } - }, - "hide_friend_feed": { - "name": "Ukryj w Aktualnościach znajomych" + }, + "description": "Uniemożliwia zapisywanie wiadomości na czacie przez inne osoby" }, "e2e_encryption": { "name": "Użyj szyfrowania E2E" - }, - "pin_conversation": { - "name": "Przypnij rozmowę" - }, - "exclude_message_logger": { - "name": "Wyklucz z rejestratora wiadomości" } + }, + "toasts": { + "enabled": "{ruleName} włączony", + "disabled": "{ruleName} wyłączony" } }, "actions": { + "regen_mappings": { + "description": "Ręcznie wygeneruj ponownie mapowania", + "name": "Regeneruj mapowania" + }, + "change_language": { + "name": "Zmień język", + "description": "Zmień język SnapEnhance'a" + }, + "friend_tracker": { + "name": "Śledzenie znajomych", + "description": "Śledź swoich znajomych na Snapchacie" + }, + "file_imports": { + "name": "Import plików", + "description": "Importuj pliki do użytku w Snapchacie" + }, + "logger_history": { + "name": "Historia rejestratora", + "description": "Przeglądaj historię zarejestrowanych wiadomości" + }, "clean_snapchat_cache": { - "name": "Wyczyść pamięć podręczną Snapchata", - "description": "Czyści pamięć podręczną Snapchata" + "description": "Czyści pamięć podręczną Snapchata", + "name": "Wyczyść pamięć podręczną Snapchata" }, "manage_friend_list": { "name": "Zarządzaj listą znajomych", @@ -619,1404 +239,18 @@ "description": "Eksportuje wiadomości konwersacji do pliku JSON/HTML/TXT" }, "export_memories": { - "name": "Eksportuj wspomnienia", - "description": "Eksportuje wspomnienia do pliku ZIP" + "description": "Eksportuje wspomnienia do pliku ZIP", + "name": "Eksportuj wspomnienia" }, "bulk_messaging_action": { - "name": "Akcja przesyłania wiadomości zbiorczych", - "description": "Wykonuje operacje takie jak usuwanie znajomych czy masowe usuwanie rozmów" - }, - "regen_mappings": { - "name": "Regeneruj mapowania", - "description": "Ręcznie wygeneruj ponownie mapowania" - }, - "change_language": { - "name": "Zmień język", - "description": "Zmień język PurrfectSnap" - }, - "file_imports": { - "name": "Import plików", - "description": "Importuj pliki do użytku w Snapchacie" - }, - "friend_tracker": { - "name": "Śledzenie znajomych", - "description": "Śledź swoich znajomych na Snapchacie" - }, - "logger_history": { - "name": "Historia rejestratora", - "description": "Przeglądaj historię zarejestrowanych wiadomości" + "description": "Wykonuje operacje takie jak usuwanie znajomych czy masowe usuwanie rozmów", + "name": "Akcja przesyłania wiadomości zbiorczych" } }, "features": { "notices": { "unstable": "⚠ Niestabilny", - "ban_risk": "⚠ Ta funkcja może powodować bany", - "internal_behavior": "⚠ Może to złamać wewnętrzne zachowanie Snapchata" - }, - "properties": { - "downloader": { - "name": "Pobieracz", - "description": "Pobierz Snapchat Media", - "properties": { - "save_folder": { - "name": "Zapisz folder", - "description": "Wybierz katalog, do którego mają zostać pobrane wszystkie multimedia" - }, - "auto_download_sources": { - "name": "Źródła automatycznego pobierania", - "description": "Wybierz źródła, z których chcesz automatycznie pobierać pliki" - }, - "prevent_self_auto_download": { - "name": "Zapobiegaj automatycznemu pobieraniu", - "description": "Zapobiega automatycznemu pobieraniu własnych Snapów" - }, - "path_format": { - "name": "Format ścieżki", - "description": "Określ format ścieżki pliku" - }, - "allow_duplicate": { - "name": "Zezwalaj na duplikację", - "description": "Umożliwia wielokrotne pobieranie tych samych multimediów" - }, - "merge_overlays": { - "name": "Połącz nakładki", - "description": "Łączy tekst i multimedia Snapu w jeden plik" - }, - "force_image_format": { - "name": "Wymuś format obrazu", - "description": "Wymusza zapisywanie obrazów w określonym formacie" - }, - "force_voice_note_format": { - "name": "Wymuś format notatki głosowej", - "description": "Wymusza zapisywanie notatek głosowych w określonym formacie" - }, - "auto_download_voice_notes": { - "name": "Automatyczne pobieranie notatek głosowych", - "description": "Automatycznie pobiera notatki głosowe podczas ich odtwarzania" - }, - "download_profile_pictures": { - "name": "Pobierz zdjęcia profilowe", - "description": "Umożliwia pobranie zdjęć profilowych ze strony profilowej" - }, - "opera_download_button": { - "name": "Przycisk pobierania Opery", - "description": "Dodaje przycisk pobierania w prawym górnym rogu podczas przeglądania Snapu.\nDługie naciśnięcie przycisków wymusi pobranie" - }, - "download_context_menu": { - "name": "Pobierz menu kontekstowe", - "description": "Umożliwia pobieranie/przeglądanie wiadomości z rozmowy lub historii za pomocą menu kontekstowego.\nDługie naciśnięcie przycisków wymusi pobranie" - }, - "ffmpeg_options": { - "name": "Opcje FFmpeg", - "description": "Określ dodatkowe opcje FFmpeg", - "properties": { - "threads": { - "name": "Wątki", - "description": "Liczba wątków do wykorzystania" - }, - "preset": { - "name": "Wstępnie ustawione", - "description": "Ustaw szybkość konwersji" - }, - "constant_rate_factor": { - "name": "Stały współczynnik szybkości", - "description": "Ustaw stały współczynnik szybkości dla kodera wideo\nOd 0 do 51 dla libx264" - }, - "video_bitrate": { - "name": "Szybkość transmisji wideo", - "description": "Ustaw szybkość transmisji wideo (kb/s)" - }, - "audio_bitrate": { - "name": "Szybkość transmisji dźwięku", - "description": "Ustaw szybkość transmisji audio (kb/s)" - }, - "custom_video_codec": { - "name": "Niestandardowy kodek wideo", - "description": "Ustaw niestandardowy kodek wideo (np. libx264)" - }, - "custom_audio_codec": { - "name": "Niestandardowy kodek audio", - "description": "Ustaw niestandardowy kodek audio (np. AAC)" - } - } - }, - "logging": { - "name": "Wycięcie lasu", - "description": "Pokazuje toasty podczas pobierania multimediów" - }, - "custom_path_format": { - "name": "Niestandardowy format ścieżki", - "description": "Określ niestandardowy format ścieżki dla pobranych multimediów\n\nDostępne zmienne:\n - %nazwa użytkownika%\n - %źródło%\n -%hash%\n -%data_godzina%" - } - } - }, - "user_interface": { - "name": "Interfejs użytkownika", - "description": "Zmień wygląd i działanie Snapchata", - "properties": { - "enable_app_appearance": { - "name": "Włącz ustawienia wyglądu aplikacji", - "description": "Włącza ukryte ustawienie wyglądu aplikacji\nMoże nie być wymagane w nowszych wersjach Snapchata" - }, - "friend_feed_message_preview": { - "name": "Podgląd wiadomości w kanale znajomych", - "description": "Pokazuje podgląd ostatnich wiadomości w Aktualnościach znajomych", - "properties": { - "amount": { - "name": "Kwota", - "description": "Liczba wiadomości, które mają zostać wyświetlone" - } - } - }, - "snap_preview": { - "name": "Podgląd przyciągania", - "description": "Wyświetla mały podgląd obok niewidocznych Snapów na czacie" - }, - "bootstrap_override": { - "name": "Zastąpienie Bootstrapa", - "description": "Zastępuje ustawienia ładowania początkowego interfejsu użytkownika", - "properties": { - "app_appearance": { - "name": "Wygląd aplikacji", - "description": "Ustawia trwały wygląd aplikacji" - }, - "home_tab": { - "name": "Karta Strona główna", - "description": "Zastępuje kartę startową podczas otwierania Snapchata" - } - } - }, - "force_amoled_theme": { - "name": "Amoledowy tryb ciemny", - "description": "Używa prawdziwego czarnego tła dla ciemnego motywu" - }, - "map_friend_nametags": { - "name": "Ulepszone plakietki z nazwami map znajomych", - "description": "Poprawia plakietki znajomych na Snapmapie" - }, - "prevent_message_list_auto_scroll": { - "name": "Zapobiegaj automatycznemu przewijaniu listy wiadomości", - "description": "Zapobiega przewijaniu listy wiadomości w dół podczas wysyłania/odbierania wiadomości" - }, - "streak_expiration_info": { - "name": "Pokaż informacje o wygaśnięciu serii", - "description": "Wyświetla licznik czasu wygaśnięcia serii obok licznika serii" - }, - "hide_friend_feed_entry": { - "name": "Ukryj wpis w kanale znajomych", - "description": "Ukrywa określonego znajomego w Aktualnościach znajomych\nAby zarządzać tą funkcją, użyj karty społecznościowej" - }, - "hide_streak_restore": { - "name": "Ukryj przywracanie serii", - "description": "Ukrywa przycisk Przywróć w aktualnościach znajomych" - }, - "hide_quick_add_suggestions": { - "name": "Ukryj sugestie szybkiego dodawania", - "description": "Usuwa sugestie szybkiego dodawania znajomych" - }, - "hide_story_suggestions": { - "name": "Ukryj sugestie dotyczące historii", - "description": "Usuwa sugestie ze strony Historie" - }, - "hide_ui_components": { - "name": "Ukryj komponenty interfejsu użytkownika", - "description": "Wybierz, które komponenty interfejsu użytkownika mają zostać ukryte" - }, - "opera_media_quick_info": { - "name": "Szybkie informacje dotyczące Opery Media", - "description": "Pokazuje przydatne informacje o mediach, takie jak data utworzenia, w menu kontekstowym przeglądarki Opera" - }, - "old_bitmoji_selfie": { - "name": "Stare selfie Bitmoji", - "description": "Przywraca selfie Bitmoji ze starszych wersji Snapchata" - }, - "disable_spotlight": { - "name": "Wyłącz Spotlight", - "description": "Wyłącza stronę Spotlight" - }, - "friend_feed_menu_buttons": { - "name": "Przyciski menu kanału znajomych", - "description": "Wybierz, które przyciski mają być wyświetlane w menu Kanał znajomych" - }, - "auto_close_friend_feed_menu": { - "name": "Automatyczne zamykanie menu kanałów znajomych", - "description": "Automatycznie zamyka menu kanałów znajomych po naciśnięciu przycisku ustawień" - }, - "vertical_story_viewer": { - "name": "Pionowa przeglądarka historii", - "description": "Włącza pionową przeglądarkę historii dla wszystkich historii" - }, - "enable_friend_feed_menu_bar": { - "name": "Pasek menu kanału znajomych", - "description": "Włącza nowy pasek menu kanału znajomych" - }, - "message_indicators": { - "name": "Wskaźniki wiadomości", - "description": "Dodaje określone ikony wskaźników do wiadomości\nUwaga: wskaźniki mogą nie być w 100% dokładne" - }, - "stealth_mode_indicator": { - "name": "Wskaźnik trybu ukrytego", - "description": "Dodaje emoji 👻 obok rozmów w trybie ukrytym" - }, - "edit_text_override": { - "name": "Edytuj zastąpienie tekstu", - "description": "Zastępuje zachowanie pola tekstowego" - }, - "prevent_forced_keyboard": { - "name": "Zapobiegaj wymuszonej klawiaturze", - "description": "Zapobiega automatycznemu wyświetlaniu klawiatury przez Snapchat po otwarciu rozmowy" - }, - "settings_menu": { - "name": "Menu ustawień", - "description": "Zmienia sposób otwierania menu PurrfectSnap", - "options": { - "default": "Domyślny", - "legacy": "Dziedzictwo" - } - } - } - }, - "messaging": { - "name": "Wiadomości", - "description": "Zmień sposób interakcji ze znajomymi", - "properties": { - "bypass_screenshot_detection": { - "name": "Pomiń wykrywanie zrzutów ekranu", - "description": "Uniemożliwia Snapchatowi wykrycie, kiedy robisz zrzut ekranu" - }, - "anonymous_story_viewing": { - "name": "Anonimowe oglądanie historii", - "description": "Uniemożliwia komukolwiek dowiedzenie się, że widziałeś ich historię" - }, - "prevent_story_rewatch_indicator": { - "name": "Zapobiegaj wskaźnikowi ponownego oglądania historii", - "description": "Uniemożliwia innym dowiedzenie się, że ponownie obejrzałeś ich historię" - }, - "hide_peek_a_peek": { - "name": "Ukryj podgląd", - "description": "Zapobiega wysyłaniu powiadomień, gdy przesuniesz palcem do połowy na czacie" - }, - "hide_bitmoji_presence": { - "name": "Ukryj obecność Bitmoji", - "description": "Zapobiega pojawianiu się Bitmoji podczas czatu" - }, - "hide_typing_notifications": { - "name": "Ukryj powiadomienia o pisaniu", - "description": "Uniemożliwia innym zorientowanie się, że piszesz wiadomość" - }, - "unlimited_snap_view_time": { - "name": "Nieograniczony czas przeglądania Snap", - "description": "Usuwa limit czasu na oglądanie Snapów" - }, - "auto_mark_as_read": { - "name": "Automatyczne oznaczenie jako przeczytane", - "description": "Automatycznie oznacza wiadomości/snapy jako przeczytane, nawet gdy włączony jest tryb ukryty" - }, - "mark_snap_as_seen_button": { - "name": "Przycisk Zaznacz przyciąganie jako widoczne", - "description": "Dodaje przycisk umożliwiający oznaczenie Snap jako widocznego podczas jego oglądania.\nBędzie to działać nawet wtedy, gdy włączony jest tryb ukryty" - }, - "skip_when_marking_as_seen": { - "name": "Pomiń podczas oznaczania jako widziane", - "description": "Automatycznie przechodzi do następnego przyciągania podczas oznaczania przyciągania jako widocznego.\nUżywaj w połączeniu z przyciskiem Zaznacz przyciąganie jako widoczne" - }, - "loop_media_playback": { - "name": "Odtwarzanie multimediów w pętli", - "description": "Zapętla odtwarzanie multimediów podczas przeglądania Snapów / Historii" - }, - "disable_replay_in_ff": { - "name": "Wyłącz powtórkę w FF", - "description": "Wyłącza możliwość ponownego odtwarzania po długim naciśnięciu w kanale znajomych" - }, - "half_swipe_notifier": { - "name": "Powiadomienie o połowie machnięcia", - "description": "Powiadamia Cię, gdy ktoś do połowy włączy się do rozmowy", - "properties": { - "min_duration": { - "name": "Minimalny czas trwania", - "description": "Minimalny czas trwania półprzesunięcia (w sekundach)" - }, - "max_duration": { - "name": "Maksymalny czas trwania", - "description": "Maksymalny czas trwania półprzesunięcia (w sekundach)" - } - } - }, - "call_start_confirmation": { - "name": "Potwierdzenie rozpoczęcia połączenia", - "description": "Wyświetla okno dialogowe potwierdzenia podczas rozpoczynania połączenia" - }, - "unlimited_conversation_pinning": { - "name": "Nieograniczone przypinanie rozmów", - "description": "Pozwala przypiąć lokalnie nieograniczoną liczbę rozmów" - }, - "disable_snap_mode_restrictions": { - "name": "Wyłącz ograniczenia trybu przyciągania", - "description": "Umożliwia oglądanie samoniszczących Snapów bez ograniczeń" - }, - "prevent_message_sending": { - "name": "Zapobiegaj wysyłaniu wiadomości", - "description": "Uniemożliwia wysyłanie niektórych typów wiadomości" - }, - "friend_mutation_notifier": { - "name": "Powiadomienie o mutacjach znajomych", - "description": "Powiadamia Cię, gdy coś zmieni się w profilu znajomego" - }, - "better_notifications": { - "name": "Lepsze powiadomienia", - "description": "Dodaje więcej informacji w otrzymanych powiadomieniach", - "properties": { - "group_notifications": { - "name": "Powiadomienia grupowe", - "description": "Grupuj powiadomienia w jedno" - }, - "chat_preview": { - "name": "Podgląd czatu", - "description": "Wyświetla podgląd odebranych wiadomości w powiadomieniu" - }, - "media_preview": { - "name": "Podgląd multimediów", - "description": "Wyświetla podgląd wybranych typów multimediów w powiadomieniu" - }, - "media_caption": { - "name": "Podpis multimedialny", - "description": "Wyświetla załączony podpis multimediów w powiadomieniu" - }, - "stacked_media_messages": { - "name": "Skumulowane wiadomości multimedialne", - "description": "Łączy wiele wiadomości multimedialnych w jedno powiadomienie tekstowe, gdy nie można ich wyświetlić. Używaj w połączeniu z podglądem czatu" - }, - "friend_add_source": { - "name": "Przyjaciel Dodaj źródło", - "description": "Pokazuje w powiadomieniu źródło zaproszenia do grona znajomych" - }, - "reply_button": { - "name": "Przycisk odpowiedzi", - "description": "Dodaje przycisk odpowiedzi do powiadomienia" - }, - "smart_replies": { - "name": "Inteligentne odpowiedzi", - "description": "Dodaje sugerowane odpowiedzi na powiadomienia (Android 10+). Używaj w połączeniu z przyciskiem odpowiedzi" - }, - "download_button": { - "name": "Pobierz przycisk", - "description": "Umożliwia pobranie multimediów z powiadomienia" - }, - "mark_as_read_button": { - "name": "Przycisk Oznacz jako przeczytane", - "description": "Umożliwia oznaczenie wiadomości jako przeczytanej w powiadomieniu" - }, - "mark_as_read_and_save_in_chat": { - "name": "Oznacz jako przeczytane i zapisz na czacie", - "description": "Dodaje do powiadomienia oznaczenie jako przeczytane i zapisane na czacie" - } - } - }, - "notification_blacklist": { - "name": "Czarna lista powiadomień", - "description": "Wybierz powiadomienia, które mają być blokowane" - }, - "message_logger": { - "name": "Rejestrator wiadomości", - "description": "Zapobiega usuwaniu wiadomości", - "properties": { - "keep_my_own_messages": { - "name": "Zachowaj moje własne wiadomości", - "description": "Zapobiega usuwaniu własnych wiadomości" - }, - "auto_purge": { - "name": "Automatyczne oczyszczanie", - "description": "Automatycznie usuwa wiadomości z pamięci podręcznej, które są starsze niż określony czas" - }, - "message_filter": { - "name": "Filtr wiadomości", - "description": "Wybierz, które wiadomości mają być rejestrowane (puste dla wszystkich wiadomości)" - }, - "deleted_message_color": { - "name": "Kolor usuniętej wiadomości", - "description": "Ustawia kolor usuniętych wiadomości" - } - } - }, - "auto_save_messages_in_conversations": { - "name": "Automatyczne zapisywanie wiadomości", - "description": "Automatycznie zapisuje każdą wiadomość w rozmowach" - }, - "gallery_media_send_override": { - "name": "Zastąpienie wysyłania multimediów z galerii", - "description": "Fałszywie źródło multimediów podczas wysyłania z Galerii" - }, - "strip_media_metadata": { - "name": "Usuń metadane multimediów", - "description": "Usuwa metadane multimediów przed wysłaniem jako wiadomość" - }, - "bypass_message_retention_policy": { - "name": "Pomiń zasady przechowywania wiadomości", - "description": "Zapobiega usuwaniu wiadomości po ich przejrzeniu" - }, - "bypass_message_action_restrictions": { - "name": "Pomiń ograniczenia akcji związanych z wiadomościami", - "description": "Umożliwia reakcję na snap bez otwierania go lub zapisanie wiadomości, której nie można zapisać" - }, - "remove_groups_locked_status": { - "name": "Usuń status zablokowania grup", - "description": "Umożliwia przeglądanie informacji o grupie po wyrzuceniu" - }, - "double_tap_chat_action": { - "name": "Dwukrotne dotknięcie akcji na czacie", - "description": "Wykonuje niestandardową akcję po dwukrotnym dotknięciu wiadomości na czacie" - }, - "double_tap_chat_action_custom_emoji": { - "name": "Dwukrotne dotknięcie akcji na czacie Niestandardowa reakcja emoji", - "description": "Ustawia niestandardową reakcję emoji dla akcji czatu dwukrotnego dotknięcia" - } - } - }, - "global": { - "name": "Światowy", - "description": "Dostosuj globalne ustawienia Snapchata", - "properties": { - "better_location": { - "name": "Lepsza lokalizacja", - "description": "Poprawia lokalizację Snapchata", - "properties": { - "spoof_location": { - "name": "Fałszywa lokalizacja", - "description": "Podrabia Twoją lokalizację na określoną" - }, - "coordinates": { - "name": "Współrzędne", - "description": "Ustaw współrzędne fałszywej lokalizacji" - }, - "walk_radius": { - "name": "Promień spaceru", - "description": "Losowo spaceruj w obrębie tego promienia (w stopach)" - }, - "always_update_location": { - "name": "Zawsze aktualizuj lokalizację", - "description": "Wymuś aktualizację lokalizacji przez Snapchata, nawet jeśli nie zostaną odebrane żadne dane GPS" - }, - "suspend_location_updates": { - "name": "Zawieś aktualizacje lokalizacji", - "description": "Uniemożliwia aktualizację Twojej lokalizacji" - }, - "spoof_battery_level": { - "name": "Fałszywy poziom naładowania baterii", - "description": "Podrabia poziom baterii urządzenia na mapie\nWartość musi mieścić się w przedziale od 0 do 100" - }, - "spoof_headphones": { - "name": "Fałszywe słuchawki", - "description": "Fałszywie status słuchania muzyki na mapie" - }, - "show_battery_level": { - "name": "Pokaż poziom baterii", - "description": "Pokazuje poziom naładowania baterii Twoich znajomych na mapie" - } - } - }, - "snapchat_plus": { - "name": "Snapchata Plusa", - "description": "Włącza funkcje Snapchat Plus\nNiektóre funkcje po stronie serwera mogą nie działać" - }, - "media_upload_quality": { - "name": "Jakość przesyłania multimediów", - "description": "Zastępuje jakość przesyłanych multimediów", - "properties": { - "force_video_upload_source_quality": { - "name": "Wymuś jakość źródła przesyłania wideo", - "description": "Zmusza Snapchata do korzystania z jakości źródłowej podczas przesyłania filmów\nNależy pamiętać, że może to nie spowodować usunięcia metadanych z multimediów" - }, - "disable_image_compression": { - "name": "Wyłącz kompresję obrazu", - "description": "Wyłącza kompresję obrazu podczas przesyłania multimediów" - }, - "custom_image_upload_format": { - "name": "Niestandardowy format przesyłania obrazu", - "description": "Ustawia niestandardowy format przesyłania obrazu\nAby uzyskać najlepszą jakość, wybierz format bezstratny (np. PNG)." - } - } - }, - "disable_confirmation_dialogs": { - "name": "Wyłącz okna dialogowe potwierdzenia", - "description": "Automatycznie potwierdza wybrane działania" - }, - "auto_updater": { - "name": "Automatyczna aktualizacja", - "description": "Automatycznie sprawdza dostępność nowych aktualizacji" - }, - "disable_metrics": { - "name": "Wyłącz metryki", - "description": "Blokuje wysyłanie określonych danych analitycznych do Snapchata" - }, - "disable_story_sections": { - "name": "Wyłącz sekcje historii", - "description": "Usuwa sekcje ze strony Historie\nMoże wymagać odświeżenia, aby działać prawidłowo" - }, - "block_ads": { - "name": "Blokuj reklamy", - "description": "Uniemożliwia wyświetlanie reklam" - }, - "disable_custom_tabs": { - "name": "Wyłącz karty niestandardowe", - "description": "Otwiera łącza w obsługiwanych aplikacjach, a nie w przeglądarce internetowej" - }, - "disable_permission_requests": { - "name": "Wyłącz żądania uprawnień", - "description": "Uniemożliwia Snapchatowi proszenie o określone uprawnienia" - }, - "disable_memories_snap_feed": { - "name": "Wyłącz funkcję Snap Snap Feed", - "description": "Uniemożliwia Snapchatowi pokazywanie ostatnich wspomnień po przesunięciu palcem w górę w aparacie" - }, - "spotlight_comments_username": { - "name": "Komentarze w centrum uwagi Nazwa użytkownika", - "description": "Pokazuje nazwę użytkownika autora w komentarzach Spotlight" - }, - "bypass_video_length_restriction": { - "name": "Omiń ograniczenia długości wideo", - "description": "Pojedynczy: wysyła pojedynczy film\nPodziel: podziel filmy po edycji" - }, - "default_video_playback_rate": { - "name": "Domyślna szybkość odtwarzania wideo", - "description": "Ustawia domyślną prędkość odtwarzania filmów\nWartość musi mieścić się w przedziale od 0,1 do 4,0" - }, - "video_playback_rate_slider": { - "name": "Suwak szybkości odtwarzania wideo", - "description": "Dodaje suwak w menu kontekstowym Opery, aby zmienić szybkość odtwarzania wideo\nUwaga: zmiany dotyczą tylko kolejnych filmów" - }, - "disable_google_play_dialogs": { - "name": "Wyłącz okna dialogowe usług Google Play", - "description": "Zapobiegaj wyświetlaniu okien dialogowych dostępności Usług Google Play" - }, - "default_volume_controls": { - "name": "Domyślne regulatory głośności", - "description": "Zmusza Snapchata do korzystania z systemowej regulacji głośności" - }, - "disable_telecom_framework": { - "name": "Wyłącz strukturę telekomunikacyjną", - "description": "Uniemożliwia Snapchatowi korzystanie z platformy Android Telecom\nDzięki temu możesz słuchać muzyki podczas rozmowy" - }, - "hide_active_music": { - "name": "Ukryj aktywną muzykę", - "description": "Uniemożliwia Snapchatowi poznanie, że słuchasz muzyki\nUmożliwi to robienie zdjęć za pomocą przycisków regulacji głośności podczas słuchania muzyki" - }, - "disable_snap_splitting": { - "name": "Wyłącz dzielenie przez przyciąganie", - "description": "Zapobiega dzieleniu przyciągań na wiele części\nZdjęcia, które prześlesz, zamienią się w filmy" - } - } - }, - "rules": { - "name": "Zasady", - "description": "Zarządzaj funkcjami automatycznymi dla poszczególnych osób" - }, - "camera": { - "name": "Kamera", - "description": "Dostosuj odpowiednie ustawienia, aby uzyskać idealne ujęcie", - "properties": { - "disable_cameras": { - "name": "Wyłącz kamery", - "description": "Uniemożliwia Snapchatowi korzystanie z wybranych kamer" - }, - "black_photos": { - "name": "Czarne Zdjęcia", - "description": "Zastępuje zrobione zdjęcia czarnym tłem\nNie ma to wpływu na filmy" - }, - "immersive_camera_preview": { - "name": "Wciągający podgląd", - "description": "Zapobiega przycinaniu podglądu kamery przez Snapchat\nMoże to powodować migotanie aparatu w niektórych urządzeniach" - }, - "override_front_resolution": { - "name": "Zastąp rozdzielczość przednią", - "description": "Zastępuje rozdzielczość aparatu przedniego" - }, - "override_back_resolution": { - "name": "Zastąp rozdzielczość wsteczną", - "description": "Zastępuje rozdzielczość kamery tylnej" - }, - "custom_resolution": { - "name": "Niestandardowa rozdzielczość", - "description": "Ustawia niestandardową rozdzielczość kamery, szerokość x wysokość (np. 1920x1080).\nNiestandardowa rozdzielczość musi być obsługiwana przez Twoje urządzenie" - }, - "front_custom_frame_rate": { - "name": "Przednia niestandardowa liczba klatek na sekundę", - "description": "Zastępuje częstotliwość klatek przedniego aparatu" - }, - "back_custom_frame_rate": { - "name": "Wstecz Niestandardowa liczba klatek na sekundę", - "description": "Zastępuje częstotliwość klatek tylnej kamery" - }, - "force_camera_source_encoding": { - "name": "Wymuś kodowanie źródła kamery", - "description": "Wymusza kodowanie źródła kamery" - }, - "startup_default_camera": { - "name": "Domyślna kamera startowa", - "description": "Ustawia domyślną kamerę podczas otwierania Snapchata" - }, - "hevc_recording": { - "name": "Nagranie HEVC", - "description": "Do nagrywania wideo wykorzystuje kodek HEVC (H.265)." - } - } - }, - "streaks_reminder": { - "name": "Przypomnienie o smugach", - "description": "Okresowo powiadamia Cię o Twoich seriach", - "properties": { - "interval": { - "name": "Interwał", - "description": "Odstęp pomiędzy każdym przypomnieniem (godziny)" - }, - "remaining_hours": { - "name": "Pozostały czas", - "description": "Pozostały czas do wyświetlenia powiadomienia (godziny)" - }, - "group_notifications": { - "name": "Powiadomienia grupowe", - "description": "Grupuj powiadomienia w jedno" - } - } - }, - "experimental": { - "name": "Eksperymentalny", - "description": "Funkcje eksperymentalne", - "properties": { - "native_hooks": { - "name": "Rodzime hooki", - "description": "Niebezpieczne funkcje, które łączą się z natywnym kodem Snapchata", - "properties": { - "composer_hooks": { - "name": "Haki kompozytorskie", - "description": "Wstrzykuje kod do wieloplatformowego interfejsu użytkownika Composer", - "properties": { - "show_first_created_username": { - "name": "Pokaż pierwszą utworzoną nazwę użytkownika", - "description": "Pokazuje pierwszą utworzoną nazwę użytkownika obok bieżącej nazwy użytkownika na stronie profilu" - }, - "bypass_camera_roll_limit": { - "name": "Obejście limitu rolki aparatu", - "description": "Zwiększa maksymalną ilość multimediów, które można wysłać z rolki aparatu" - }, - "custom_self_destruct_snap_delay": { - "name": "Niestandardowe opóźnienie przyciągania samozniszczenia", - "description": "Daje więcej opcji licznika czasu samozniszczenia podczas wysyłania Snapu" - }, - "composer_console": { - "name": "Konsola kompozytora", - "description": "Umożliwia wykonanie kodu JavaScript w Composer (tylko arm64)" - }, - "composer_logs": { - "name": "Dzienniki kompozytora", - "description": "Przekierowuje logi konsoli Composer do PurrfectSnap" - } - } - }, - "disable_bitmoji": { - "name": "Wyłącz Bitmoji", - "description": "Wyłącza profil znajomych Bitmoji" - }, - "custom_emoji_font": { - "name": "Niestandardowa czcionka emoji", - "description": "Umożliwia użycie niestandardowej czcionki emoji. Działa tylko z czcionkami .ttf" - }, - "custom_shared_library": { - "name": "Niestandardowa biblioteka współdzielona", - "description": "Ładuje niestandardową bibliotekę współdzieloną do Snapchata. Ta funkcja służy wyłącznie do celów testowych" - } - } - }, - "spoof": { - "name": "Naciąganie", - "description": "Fałszuj różne informacje o Tobie", - "properties": { - "play_store_installer_package_name": { - "name": "Nazwa pakietu instalatora Sklepu Play", - "description": "Zastępuje nazwę pakietu instalacyjnego na com.android.vending" - }, - "remove_vpn_transport_flag": { - "name": "Usuń flagę transportu VPN", - "description": "Uniemożliwia Snapchatowi wykrywanie sieci VPN" - }, - "remove_mock_location_flag": { - "name": "Usuń flagę fałszywej lokalizacji", - "description": "Uniemożliwia Snapchatowi wykrywanie fałszywej lokalizacji" - } - } - }, - "convert_message_locally": { - "name": "Konwertuj wiadomość lokalnie", - "description": "Konwertuje snapy, aby lokalnie rozmawiać z mediami zewnętrznymi. Pojawia się w menu kontekstowym pobierania czatu" - }, - "media_file_picker": { - "name": "Selektor plików multimedialnych", - "description": "Umożliwia wybranie dowolnego pliku wideo/audio z galerii" - }, - "story_logger": { - "name": "Rejestrator historii", - "description": "Zawiera historię historii znajomych" - }, - "call_recorder": { - "name": "Rejestrator rozmów", - "description": "Automatycznie nagrywa rozmowy audio" - }, - "account_switcher": { - "name": "Zmiana konta", - "description": "Umożliwia przełączanie pomiędzy kontami bez konieczności wylogowywania się\nNaciśnij długo ikonę wyszukiwania obok profilu Bitmoji, aby otworzyć menu\nUwaga: ta funkcja ma charakter eksperymentalny i prawdopodobnie ulegnie zmianie w przyszłości", - "properties": { - "auto_backup_current_account": { - "name": "Automatyczna kopia zapasowa konta bieżącego", - "description": "Automatycznie tworzy kopię zapasową bieżącego konta podczas wylogowywania się lub przełączania kont" - } - } - }, - "better_transcript": { - "name": "Lepsza transkrypcja", - "description": "Poprawia transkrypcję notatek głosowych", - "properties": { - "force_transcription": { - "name": "Wymuś transkrypcję notatki głosowej", - "description": "Umożliwia transkrypcję wszystkich notatek głosowych" - }, - "preferred_transcription_lang": { - "name": "Preferowany język transkrypcji", - "description": "Preferowany język transkrypcji notatki głosowej (np. EN, ES, FR)" - }, - "notification_transcript": { - "name": "Transkrypcja powiadomienia", - "description": "Transkrypcja notatek głosowych w powiadomieniach\nTa funkcja wymaga włączenia funkcji Podgląd czatu w Lepszych powiadomieniach" - } - } - }, - "voice_note_auto_play": { - "name": "Automatyczne odtwarzanie notatki głosowej", - "description": "Automatycznie odtwarza następną notatkę głosową po zakończeniu bieżącej" - }, - "friend_notes": { - "name": "Notatki znajomych", - "description": "Umożliwia dodawanie notatek do profili znajomych" - }, - "cof_experiments": { - "name": "Eksperymenty COF", - "description": "Włącza niewydane/beta funkcje Snapchata" - }, - "context_menu_fix": { - "name": "Poprawka menu kontekstowego", - "description": "Spróbuj naprawić menu kanału znajomych, ponieważ gdy urządzenie jest w trybie offline, nie może być poprawnie wyświetlane" - }, - "app_lock": { - "name": "Blokada aplikacji", - "description": "Uniemożliwia dostęp do Snapchata bez hasła", - "properties": { - "lock_on_resume": { - "name": "Zablokuj CV", - "description": "Blokuje aplikację po jej ponownym otwarciu" - } - } - }, - "infinite_story_boost": { - "name": "Nieskończone wzmocnienie historii", - "description": "Omiń opóźnienie limitu wzmocnienia historii" - }, - "meo_passcode_bypass": { - "name": "Obejście kodu dostępu My Eyes Only", - "description": "Omiń hasło My Eyes Only\nTo zadziała tylko wtedy, gdy hasło zostało wcześniej wprowadzone poprawnie" - }, - "no_friend_score_delay": { - "name": "Brak opóźnienia w zdobywaniu punktów znajomych", - "description": "Usuwa opóźnienie podczas przeglądania wyniku znajomych" - }, - "best_friend_pinning": { - "name": "Przypinanie najlepszego przyjaciela", - "description": "Umożliwia przypięcie znajomego jako najlepszego przyjaciela numer jeden. Uwaga: tylko Ty możesz zobaczyć swojego przypiętego najlepszego przyjaciela" - }, - "e2ee": { - "name": "Szyfrowanie typu end-to-end", - "description": "Szyfruje wiadomości za pomocą AES przy użyciu wspólnego tajnego klucza\nPamiętaj, aby zapisać swój klucz w bezpiecznym miejscu!", - "properties": { - "encrypted_message_indicator": { - "name": "Wskaźnik zaszyfrowanej wiadomości", - "description": "Dodaje emoji 🔒 obok zaszyfrowanych wiadomości" - }, - "force_message_encryption": { - "name": "Wymuś szyfrowanie wiadomości", - "description": "Zapobiega wysyłaniu zaszyfrowanych wiadomości do osób, które nie mają włączonego szyfrowania E2E, tylko w przypadku wybrania wielu rozmów" - } - } - }, - "add_friend_source_spoof": { - "name": "Dodaj parodię źródła znajomego", - "description": "Fałszywie źródło zaproszenia do znajomych" - }, - "hidden_snapchat_plus_features": { - "name": "Ukryte funkcje Snapchata Plus", - "description": "Włącza niewydane/beta funkcje Snapchat Plus\nMoże nie działać na starszych wersjach Snapchata" - }, - "custom_streaks_expiration_format": { - "name": "Niestandardowy format ważności serii", - "description": "Dostosowuje format wygaśnięcia serii\n\nDostępne zmienne:\n - %c: Liczba smug\n - %e: Emoji klepsydry\n - %d: dni\n - %h: godziny\n -%m: minuty\n - %s: sekundy\n -%w: Pozostały czas" - }, - "prevent_forced_logout": { - "name": "Zapobiegaj wymuszonemu wylogowaniu", - "description": "Uniemożliwia Snapchatowi wylogowanie Cię, gdy logujesz się na innym urządzeniu" - }, - "snapscore_changes": { - "name": "Zmiany w Snapscore'ie", - "description": "Śledzi zmiany w Snapscore znajomych\nUżywaj tej funkcji tylko w nowszych wersjach Snapchata" - } - } - }, - "scripting": { - "name": "Skrypty", - "description": "Uruchamiaj niestandardowe skrypty, aby rozszerzyć PurrfectSnap", - "properties": { - "developer_mode": { - "name": "Tryb programisty", - "description": "Pokazuje informacje debugowania w interfejsie użytkownika Snapchata" - }, - "module_folder": { - "name": "Folder modułu", - "description": "Folder, w którym znajdują się skrypty" - }, - "auto_reload": { - "name": "Automatyczne przeładowanie", - "description": "Automatycznie przeładowuje skrypty po ich zmianie" - }, - "integrated_ui": { - "name": "Zintegrowany interfejs użytkownika", - "description": "Umożliwia skryptom dodawanie niestandardowych komponentów interfejsu użytkownika do Snapchata" - }, - "disable_log_anonymization": { - "name": "Wyłącz anonimizację logów", - "description": "Wyłącza anonimizację logów" - }, - "disable_optimization": { - "name": "Wyłącz optymalizację", - "description": "Wyłącza optymalizację skryptów. Może to powodować problemy z wydajnością." - } - } - }, - "friend_tracker": { - "name": "Śledzenie znajomych", - "description": "Rejestruje aktywność znajomego na Snapchacie", - "properties": { - "record_messaging_events": { - "name": "Nagrywaj zdarzenia związane z przesyłaniem wiadomości", - "description": "Rejestruje zdarzenia związane z przesyłaniem wiadomości, takie jak otwarcie przystawki, przeczytanie wiadomości itp." - }, - "allow_running_in_background": { - "name": "Zezwalaj na działanie w tle", - "description": "Umożliwia działanie modułu śledzącego w tle. Uwaga: spowoduje to znaczne wyczerpanie baterii" - }, - "auto_purge": { - "name": "Automatyczne oczyszczanie", - "description": "Automatycznie usuwa buforowane zdarzenia, które są starsze niż określony czas" - } - } - } - }, - "options": { - "app_appearance": { - "always_light": "Zawsze lekko", - "always_dark": "Zawsze Ciemno" - }, - "friend_feed_menu_buttons": { - "auto_download": "⬇️ Automatyczne pobieranie", - "auto_save": "💬 Automatyczne zapisywanie wiadomości", - "unsaveable_messages": "⬇️ Wiadomości, których nie można zapisać", - "auto_open_snaps": "📷 Automatyczne otwieranie zatrzasków", - "stealth": "👻 Tryb ukrycia", - "mark_snaps_as_seen": "👀 Oznacz Snapy jako widoczne", - "mark_stories_as_seen_locally": "👀 Oznacz Historie jako widziane lokalnie", - "conversation_info": "👤 Informacje o rozmowie", - "e2e_encryption": "🔒 Użyj szyfrowania E2E" - }, - "path_format": { - "create_author_folder": "Utwórz folder dla każdego autora", - "create_source_folder": "Utwórz folder dla każdego typu źródła multimediów", - "append_hash": "Dodaj unikalny skrót do nazwy pliku", - "append_source": "Dodaj źródło multimediów do nazwy pliku", - "append_username": "Dodaj nazwę użytkownika do nazwy pliku", - "append_date_time": "Dodaj datę i godzinę do nazwy pliku" - }, - "auto_download_sources": { - "friend_snaps": "Snapy znajomych", - "friend_stories": "Historie przyjaciół", - "public_stories": "Historie publiczne", - "spotlight": "Reflektor" - }, - "logging": { - "started": "Rozpoczęło się", - "success": "Sukces", - "progress": "Postęp", - "failure": "Awaria" - }, - "notifications": { - "chat_screenshot": "Zrzut ekranu", - "chat_screen_record": "Nagranie ekranu", - "snap_replay": "Powtórka Snapu", - "camera_roll_save": "Zapisz rolkę z aparatu", - "chat": "Pogawędzić", - "chat_reply": "Odpowiedź na czacie", - "snap": "Pstryknąć", - "typing": "Pisanie na maszynie", - "stories": "Historie", - "speaking": "Mówienie", - "chat_reaction": "Reakcja DM", - "group_chat_reaction": "Reakcja grupowa", - "initiate_audio": "Przychodzące połączenie audio", - "abandon_audio": "Nieodebrane połączenie audio", - "initiate_video": "Przychodzące połączenie wideo", - "abandon_video": "Nieodebrane połączenie wideo", - "map_live_location": "Mapa lokalizacji na żywo" - }, - "gallery_media_send_override": { - "always_ask": "Zawsze pytaj", - "ORIGINAL": "Oryginalne media", - "NOTE": "Notatka dźwiękowa", - "SNAP": "Pstryknąć", - "SAVEABLE_SNAP": "Możliwość zapisania Snapu" - }, - "strip_media_metadata": { - "hide_caption_text": "Ukryj tekst podpisu", - "hide_snap_filters": "Ukryj filtry przyciągania", - "hide_extras": "Ukryj dodatki (np. wzmianki)", - "remove_audio_note_duration": "Usuń czas trwania notatki dźwiękowej", - "remove_audio_note_transcript_capability": "Usuń możliwość transkrypcji notatek audio" - }, - "hide_ui_components": { - "hide_profile_call_buttons": "Usuń przyciski połączeń profilowych", - "hide_chat_call_buttons": "Usuń przyciski rozmów na czacie", - "hide_live_location_share_button": "Usuń przycisk udostępniania lokalizacji na żywo", - "hide_stickers_button": "Przycisk Usuń naklejki", - "hide_voice_record_button": "Usuń przycisk nagrywania głosu", - "hide_unread_chat_hint": "Usuń nieprzeczytaną wskazówkę dotyczącą czatu", - "hide_post_to_story_buttons": "Usuń przyciski Opublikuj w relacji przed wysłaniem Snapa", - "hide_billboard_prompt": "Usuń monit na billboardzie w kanale znajomych", - "hide_snapchat_plus_gift_reminders": "Usuń przypomnienia o prezentach Snapchat Plus w rozmowach", - "hide_map_reactions": "Usuń reakcje mapy" - }, - "hide_story_suggestions": { - "hide_suggested_friend_stories": "Ukryj sugerowane historie znajomych", - "hide_my_stories": "Ukryj moje historie" - }, - "home_tab": { - "map": "Mapa", - "chat": "Pogawędzić", - "camera": "Kamera", - "discover": "Odkryć", - "spotlight": "Reflektor" - }, - "add_friend_source_spoof": { - "added_by_username": "Według nazwy użytkownika", - "added_by_mention": "Przez wzmiankę", - "added_by_group_chat": "Przez czat grupowy", - "added_by_qr_code": "Za pomocą kodu QR", - "added_by_community": "Przez społeczność", - "added_by_quick_add": "Przez Szybkie dodawanie (wysokie ryzyko bycia zbanowanym)" - }, - "bypass_video_length_restriction": { - "single": "Pojedyncze media", - "split": "Podziel multimedia" - }, - "old_bitmoji_selfie": { - "2d": "Bitmoji 2D", - "3d": "Bitmoji 3D" - }, - "disable_confirmation_dialogs": { - "erase_message": "Usuń wiadomość", - "remove_friend": "Usuń znajomego", - "block_friend": "Zablokuj przyjaciela", - "ignore_friend": "Ignoruj ​​Przyjaciela", - "hide_friend": "Ukryj przyjaciela", - "hide_conversation": "Ukryj rozmowę", - "clear_conversation": "Usuń rozmowę z kanału znajomych" - }, - "auto_reload": { - "snapchat_only": "Tylko Snapchat", - "all": "Wszystko (Snapchat + PurrfectSnap)" - }, - "edit_text_override": { - "multi_line_chat_input": "Wejście na czacie wieloliniowym", - "bypass_text_input_limit": "Pomiń limit wprowadzania tekstu" - }, - "auto_purge": { - "never": "Nigdy", - "1_hour": "1 godzina", - "3_hours": "3 godziny", - "6_hours": "6 godzin", - "12_hours": "12 godzin", - "1_day": "1 dzień", - "3_days": "3 dni", - "1_week": "1 tydzień", - "2_weeks": "2 tygodnie", - "1_month": "1 miesiąc", - "3_months": "3 miesiące", - "6_months": "6 miesięcy" - }, - "disable_story_sections": { - "friends": "Przyjaciele", - "suggested_stories": "Sugerowane historie", - "following": "Następny", - "discover": "Odkryć" - }, - "disable_cameras": { - "front": "Kamera przednia", - "back": "Kamera tylna" - }, - "disable_permission_requests": { - "notifications": "Powiadomienia", - "read_media_images": "Przeczytaj obrazy multimedialne", - "read_media_video": "Przeczytaj wideo multimedialne", - "camera": "Kamera", - "microphone": "Mikrofon", - "location": "Lokalizacja", - "read_contacts": "Przeczytaj Kontakty", - "nearby_devices": "Urządzenia w pobliżu", - "phone_calls": "Rozmowy telefoniczne" - }, - "message_indicators": { - "encryption_indicator": "Dodaje ikonę 🔒 obok wiadomości wysłanych tylko do Ciebie", - "platform_indicator": "Dodaje ikonę platformy, z której wysłano multimedia (np. Android, iOS, Web)", - "location_indicator": "Dodaje ikonę 📍 do snapów, które zostały wysłane z włączoną lokalizacją", - "ovf_editor_indicator": "Wskazuje, czy snap został wysłany za pomocą Edytora OVF", - "director_mode_indicator": "Dodaje ikonę ✏️ do snapów wysłanych w trybie reżyserskim, którego można używać do wysyłania zdjęć z galerii jako snapów" - }, - "auto_mark_as_read": { - "conversation_read": "Oznacz rozmowę jako przeczytaną podczas wysyłania wiadomości", - "snap_reply": "Odpowiadając na nie, oznaczaj je jako przeczytane", - "save_snap_in_chat": "Oznacz zdjęcia jako przeczytane podczas zapisywania ich na czacie w trybie ukrytym" - }, - "friend_mutation_notifier": { - "remove_friend": "Powiadamiaj, gdy ktoś usunie Cię ze znajomych", - "birthday_changes": "Powiadamiaj, gdy ktoś zmieni datę urodzenia", - "bitmoji_selfie_changes": "Powiadamiaj, gdy ktoś zmieni swoje selfie Bitmoji", - "bitmoji_avatar_changes": "Powiadamiaj, gdy ktoś zmieni swój awatar Bitmoji", - "bitmoji_background_changes": "Powiadamiaj, gdy ktoś zmieni tło Bitmoji", - "bitmoji_scene_changes": "Powiadamiaj, gdy ktoś zmieni scenę Bitmoji" - }, - "snapchat_plus": { - "not_subscribed": "Brak subskrypcji", - "basic": "Podstawowy", - "ad_free": "Bez reklam" - }, - "double_tap_chat_action": { - "like_message": "Lubię wiadomość", - "copy_text": "Skopiuj tekst do schowka", - "delete_message": "Usuń wiadomość", - "mark_as_read": "Oznacz jako przeczytane", - "custom_emoji_reaction": "Niestandardowa reakcja emoji" - }, - "startup_default_camera": { - "front": "Kamera przednia", - "back": "Kamera tylna" - } + "ban_risk": "⚠ Ta funkcja może powodować bany" } - }, - "friend_menu_option": { - "mark_snaps_as_seen": "Oznacz Snapsa tak, jak widać", - "mark_stories_as_seen_locally": "Oznacz historie jako widziane lokalnie", - "preview": "Zapowiedź", - "stealth_mode": "Tryb ukrycia", - "auto_download_blacklist": "Automatyczne pobieranie czarnej listy", - "anti_auto_save": "Blokada automatycznego zapisywania" - }, - "content_type": { - "CHAT": "Pogawędzić", - "SNAP": "Pstryknąć", - "EXTERNAL_MEDIA": "Media zewnętrzne", - "NOTE": "Notatka dźwiękowa", - "STICKER": "Naklejka", - "SHARE": "Udział", - "STATUS": "Status", - "LOCATION": "Lokalizacja", - "STATUS_SAVE_TO_CAMERA_ROLL": "Zapisano w Rolce z aparatu", - "STATUS_CONVERSATION_CAPTURE_SCREENSHOT": "Zrzut ekranu", - "STATUS_CONVERSATION_CAPTURE_RECORD": "Nagranie ekranu", - "STATUS_CALL_MISSED_VIDEO": "Nieodebrane połączenie wideo", - "STATUS_CALL_MISSED_AUDIO": "Nieodebrane połączenie audio", - "LIVE_LOCATION_SHARE": "Udostępnianie lokalizacji na żywo", - "CREATIVE_TOOL_ITEM": "Element narzędzia kreatywnego", - "FAMILY_CENTER_INVITE": "Zaproszenie do Centrum Rodzinnego", - "FAMILY_CENTER_ACCEPT": "Centrum rodzinne Akceptuję", - "FAMILY_CENTER_LEAVE": "Urlop w Centrum Rodzinnym", - "STATUS_PLUS_GIFT": "Status Plus Prezent", - "TINY_SNAP": "Mały Snap", - "STATUS_COUNTDOWN": "Odliczanie", - "MAP_REACTION": "Reakcja mapy" - }, - "media_download_source": { - "none": "Nic", - "pending": "Aż do", - "chat_media": "Czat z multimediami", - "story": "Historia", - "public_story": "Historia publiczna", - "spotlight": "Reflektor", - "profile_picture": "Zdjęcie profilowe", - "story_logger": "Rejestrator historii", - "message_logger": "Rejestrator wiadomości", - "merged": "Połączone", - "voice_call": "Połączenie głosowe" - }, - "chat_action_menu": { - "preview_button": "Zapowiedź", - "download_button": "Pobierać", - "delete_logged_message_button": "Usuń zarejestrowaną wiadomość", - "show_chat_edit_history": "Pokaż historię edycji czatu", - "convert_message": "Konwertuj wiadomość" - }, - "opera_context_menu": { - "download": "Pobierz multimedia", - "sent_at": "Wysłano o {date}", - "created_at": "Utworzono w {date}", - "expires_at": "Wygasa o {date}", - "media_size": "Rozmiar nośnika: {size}", - "media_duration": "Czas trwania multimediów: {duration} ms", - "show_debug_info": "Pokaż informacje o debugowaniu" - }, - "modal_option": { - "profile_info": "Informacje o profilu", - "close": "Zamknąć" - }, - "gallery_media_send_override": { - "multiple_media_toast": "Jednocześnie możesz wysłać tylko jedno multimedia" - }, - "mark_as_seen": { - "no_unseen_snaps_toast": "Nie znaleziono niewidzianych Snapów!", - "seen_toast": "Oznaczono jako widziane!", - "unseen_toast": "Oznaczono jako niewidoczne!", - "already_seen_toast": "Już oznaczone jako widoczne!", - "already_unseen_toast": "Już oznaczono jako niewidoczne!" - }, - "conversation_preview": { - "streak_expiration": "wygasa za {day} dni {hour} godzin {minute} minut", - "total_messages": "Całkowita liczba wysłanych/odebranych wiadomości: {count}", - "title": "Zapowiedź", - "unknown_user": "Nieznany użytkownik", - "no_messages": "Nie znaleziono żadnych wiadomości!" - }, - "profile_info": { - "title": "Informacje o profilu", - "first_created_username": "Pierwsza utworzona nazwa użytkownika", - "mutable_username": "Zmienna nazwa użytkownika", - "display_name": "Nazwa wyświetlana", - "added_date": "Dodano datę", - "birthday": "Urodziny: {month} {day}", - "hidden_birthday": "Urodziny: Ukryte", - "friendship": "Przyjaźń", - "add_source": "Dodaj źródło", - "snapchat_plus": "Snapchata Plusa", - "snapchat_plus_state": { - "subscribed": "Zasubskrybowano", - "not_subscribed": "Brak subskrypcji" - } - }, - "friendship_link_type": { - "mutual": "Wzajemne", - "outgoing": "Towarzyski", - "blocked": "Zablokowany", - "deleted": "Usunięto", - "following": "Następny", - "suggested": "Sugerowane", - "incoming": "Przybywający", - "incoming_follower": "Przychodzący obserwujący" - }, - "bulk_messaging_action": { - "choose_action_title": "Wybierz akcję", - "progress_status": "Przetwarzanie {index} z {total}", - "selection_dialog_continue_button": "Kontynuować", - "confirmation_dialog": { - "title": "Czy jesteś pewien?", - "message": "Będzie to miało wpływ na wszystkich wybranych znajomych. Tej akcji nie można cofnąć." - }, - "actions": { - "remove_friends": "Usuń znajomych", - "clear_conversations": "Wyczyść rozmowy" - } - }, - "chat_export": { - "exporter_dialog": { - "select_conversations_title": "Wybierz opcję Rozmowy", - "text_field_selection": "Wybrano {amount}", - "text_field_selection_all": "Wszystko", - "export_file_format_title": "Eksportuj format pliku", - "message_type_filter_title": "Filtruj wiadomości według typu", - "amount_of_messages_title": "Ilość wiadomości (pozostaw puste dla wszystkich)", - "download_medias_title": "Pobierz Media" - }, - "dialog_negative_button": "Anulować", - "dialog_positive_button": "Eksport", - "exported_to": "Wyeksportowano do {path}", - "exporting_chats": "Eksportowanie czatów...", - "processing_chats": "Przetwarzam rozmowy {amount}...", - "export_fail": "Nie udało się wyeksportować rozmowy {conversation}", - "writing_output": "Zapisywanie wyników...", - "finished": "Zrobione! Możesz teraz zamknąć to okno dialogowe.", - "no_messages_found": "Nie znaleziono żadnych wiadomości!", - "exporting_message": "Eksportowanie {conversation}..." - }, - "button": { - "ok": "OK", - "positive": "Tak", - "negative": "NIE", - "cancel": "Anulować", - "open": "Otwarte", - "download": "Pobierać", - "send": "Wysłać", - "restore_original": "Przywróć oryginał", - "convert_external_media": "Konwertuj media zewnętrzne", - "save": "Ratować" - }, - "tracker_events": { - "conversation_enter": "Rozmowa Wejdź", - "conversation_exit": "Wyjście z rozmowy", - "started_typing": "Zaczął pisać", - "stopped_typing": "Przestał pisać", - "started_speaking": "Zaczął mówić", - "stopped_speaking": "Przestał mówić", - "started_peeking": "Zacząłem podglądać", - "stopped_peeking": "Przestałem podglądać", - "message_read": "Wiadomość przeczytana", - "message_deleted": "Wiadomość usunięta", - "message_saved": "Wiadomość zapisana", - "message_unsaved": "Wiadomość niezapisana", - "message_edited": "Wiadomość edytowana", - "message_reaction_add": "Wiadomość Reakcja Dodaj", - "message_reaction_remove": "Wiadomość Reakcja Usuń", - "snap_opened": "Przystawka otwarta", - "snap_replayed": "Ponowne odtworzenie Snapu", - "snap_replayed_twice": "Snap powtórzony dwa razy", - "snap_screenshot": "Zrób zrzut ekranu", - "snap_screen_record": "Nagrywanie ekranu Snap" - }, - "tracker_actions": { - "log": "Dziennik", - "in_app_notification": "Powiadomienie w aplikacji", - "push_notification": "Powiadomienie push", - "custom": "Zwyczaj" - }, - "better_notifications": { - "button": { - "reply": "Odpowiedź", - "download": "Pobierać", - "mark_as_read": "Oznacz jako przeczytane" - } - }, - "profile_picture_downloader": { - "button": "Pobierz zdjęcie profilowe", - "title": "Narzędzie do pobierania zdjęć profilowych", - "avatar_option": "Awatara", - "background_option": "Tło" - }, - "call_start_confirmation": { - "dialog_title": "Rozpocznij połączenie", - "dialog_message": "Czy na pewno chcesz rozpocząć połączenie?" - }, - "half_swipe_notifier": { - "notification_channel_name": "Pół przesunięcia", - "notification_content_dm": "{friend} właśnie wsunął się do połowy na Twój czat na {duration} sekund", - "notification_content_group": "{friend} przesunięty do połowy do {group} na {duration} sekund" - }, - "download_processor": { - "attachment_type": { - "snap": "Pstryknąć", - "sticker": "Naklejka", - "gif": "GIF-y", - "external_media": "Media zewnętrzne", - "note": "Notatka", - "original_story": "Oryginalna historia" - }, - "select_attachments_title": "Wybierz załączniki", - "download_started_toast": "Pobieranie rozpoczęte", - "unsupported_content_type_toast": "Nieobsługiwany typ zawartości!", - "failed_no_longer_available_toast": "Media już niedostępne", - "no_attachments_toast": "Nie znaleziono załączników!", - "already_queued_toast": "Media już w kolejce!", - "already_downloaded_toast": "Multimedia już pobrane!", - "content_saved_toast": "Zapisano!", - "download_toast": "Pobieranie {path}...", - "processing_toast": "Przetwarzanie {path}...", - "failed_generic_toast": "Nie udało się pobrać", - "failed_to_create_preview_toast": "Nie udało się utworzyć podglądu", - "failed_processing_toast": "Nie udało się przetworzyć {error}", - "failed_gallery_toast": "Nie udało się zapisać w galerii {error}", - "dash_no_chapter": "Nie znaleziono rozdziału", - "dash_dialog": { - "title": "Pobierz multimedia w formacie dash", - "download_all": "Pobierz wszystko", - "segment_text": "Segment {from} - {to}" - } - }, - "streaks_reminder": { - "notification_title": "Pasemko", - "notification_text": "Stracisz swoją passę z {friend} za {hoursLeft} godzin" - }, - "biometric_auth": { - "unlock_button": "Odblokować", - "title": "Odblokuj Snapchata", - "subtitle": "Uwierzytelnij się, aby odblokować Snapchata" - }, - "end_to_end_encryption": { - "toolbox": { - "no_shared_key": "Nie masz jeszcze wspólnego sekretu z tym znajomym. Kliknij poniżej, aby rozpocząć nowe.", - "shared_key_fingerprint": "Twój odcisk palca to:\n\n__ symbol zastępczy_0__\n\nKoniecznie sprawdź, czy pasuje do odcisku palca Twojego znajomego!", - "initiate_exchange_button": "Rozpocznij wymianę kluczy" - }, - "confirmation_dialogs": { - "title": "Szyfrowanie typu end-to-end", - "confirmation_1": "OSTRZEŻENIE: Spowoduje to zastąpienie istniejącego klucza. Stracisz dostęp do wszystkich zaszyfrowanych wiadomości od tego znajomego. Czy na pewno chcesz kontynuować?", - "confirmation_2": "Czy NAPRAWDĘ jesteś pewien, że chcesz kontynuować? To twoja ostatnia szansa, żeby się wycofać." - }, - "unencrypted_conversation_send_failure_toast": "Nie możesz wysyłać zaszyfrowanych treści zarówno do rozmów zaszyfrowanych, jak i niezaszyfrowanych!", - "native_hooks_send_failure_toast": "Nie udało się wysłać! Proszę włączyć Native Hooki w ustawieniach.", - "no_participants_to_encrypt_toast": "Nie masz w tej rozmowie żadnych znajomych, z którymi mógłbyś szyfrować wiadomości!", - "encryption_failed_toast": "Nie udało się zaszyfrować wiadomości! Sprawdź logcat, aby uzyskać więcej szczegółów.", - "accept_public_key_success_toast": "Klucz publiczny został pomyślnie zaakceptowany!", - "accept_secret_key_success_toast": "Zrobione! Możesz teraz wysyłać i odbierać zaszyfrowane wiadomości z tym znajomym.", - "accept_public_key_failure_toast": "Nie udało się zaakceptować klucza publicznego", - "accept_secret_key_failure_toast": "Nie udało się zaakceptować tajnego klucza", - "accept_secret_button": "Zaakceptuj tajemnicę", - "accept_public_key_button": "Zaakceptuj klucz publiczny", - "outgoing_pk_message": "Prośba o wymianę klucza", - "outgoing_secret_message": "Odpowiedź na wymianę klucza", - "incoming_pk_message": "Właśnie otrzymałeś prośbę o klucz publiczny. Kliknij poniżej, aby to zaakceptować.", - "incoming_secret_message": "Twój znajomy właśnie zaakceptował Twój klucz publiczny. Kliknij poniżej, aby zaakceptować sekret." - }, - "auto_open_snaps": { - "title": "Automatyczne otwieranie zatrzasków", - "notification_content": "{count} Otwarte zatrzaski" - }, - "friend_mutation_observer": { - "notification_channel_name": "Przyjaciel Obserwator Mutacji", - "friend_removed": "{username} usunął Cię jako znajomego", - "birthday_removed": "{username} usunął swoją datę urodzenia ({birthday})", - "birthday_added": "{username} dodał swoje urodziny ({birthday})", - "birthday_changed": "{username} zmienił swoją datę urodzenia z {oldBirthday} na {newBirthday}", - "bitmoji_selfie_changed": "{username} zmienił swoje selfie Bitmoji", - "bitmoji_avatar_changed": "{username} zmienił swój awatar Bitmoji", - "bitmoji_background_changed": "{username} zmienił tło Bitmoji", - "bitmoji_scene_changed": "{username} zmienił swoją scenę Bitmoji" - }, - "material3_strings": { - "date_range_picker_start_headline": "Z", - "date_range_picker_end_headline": "Do", - "date_range_picker_title": "Wybierz zakres dat", - "date_picker_switch_to_calendar_mode": "Kalendarz", - "date_picker_switch_to_input_mode": "Wejście", - "date_range_picker_scroll_to_previous_month": "Poprzedni miesiąc", - "date_range_picker_scroll_to_next_month": "Przyszły miesiąc", - "date_picker_today_description": "Dzisiaj", - "date_range_picker_day_in_range": "Wybrany", - "date_input_invalid_for_pattern": "Nieprawidłowa data", - "date_input_invalid_year_range": "Nieprawidłowy rok", - "date_input_invalid_not_allowed": "Nieprawidłowa data", - "date_range_input_invalid_range_input": "Nieprawidłowy zakres dat" - }, - "send_override_dialog": { - "title": "Wyślij multimedia jako {type}", - "duration": "Czas trwania: {duration}", - "saveable_snap_hint": "Udostępnij Snap do zapisania na czacie", - "unlimited_duration": "Nieograniczony" - }, - "invalid_input_toast": "Nieprawidłowe dane wejściowe! Upewnij się, że wpisałeś prawidłową wartość." -} \ No newline at end of file + } +} diff --git a/common/src/main/assets/lang/pt.json b/common/src/main/assets/lang/pt.json index ff770dde..460992c1 100644 --- a/common/src/main/assets/lang/pt.json +++ b/common/src/main/assets/lang/pt.json @@ -1,2022 +1,49 @@ { - "setup": { - "dialogs": { - "select_language": "Selecione o idioma", - "save_folder": "PurrfectSnap requer permissões de armazenamento para baixar e salvar mídia do Snapchat.\nEscolha o local para onde a mídia deve ser baixada.", - "select_save_folder_button": "Selecione a pasta" - }, - "mappings": { - "dialog": "Gerando Mapeamentos, isso pode demorar um pouco...", - "generate_failure_no_snapchat": "O PurrfectSnap não conseguiu detectar o Snapchat, tente reinstalar o Snapchat.", - "generate_failure": "Ocorreu um erro ao tentar gerar mapeamentos. Tente novamente." - }, - "permissions": { - "dialog": "Para continuar você precisa atender aos seguintes requisitos:", - "notification_access": "Acesso à notificação", - "battery_optimization": "Otimização da bateria", - "display_over_other_apps": "Exibir em outros aplicativos", - "request_button": "Solicitar" - } - }, - "scopes": { - "friend": "Amigo", - "group": "Grupo" - }, - "manager": { - "routes": { - "tasks": "Tarefas", - "features": "Características", - "manage_rule_feature": "Gerenciar recurso de regra", - "home": "Lar", - "home_settings": "Configurações", - "home_logs": "Registros", - "logger_history": "Histórico do registrador", - "logged_stories": "Histórias registradas", - "friend_tracker": "Rastreador de amigos", - "edit_rule": "Editar regra", - "file_imports": "Importações de arquivos", - "manage_repos": "Gerenciar repositórios", - "social": "Social", - "manage_scope": "Gerenciar escopo", - "messaging_preview": "Visualização", - "scripts": "Roteiros", - "better_location": "Melhor localização" - }, - "sections": { - "home": { - "version_title": "v{versionName} · bifurcado por Eternal", - "update_title": "Atualização do PurrfectSnap", - "update_content": "A versão {version} está disponível!", - "update_button": "Download", - "debug_build_summary_title": "Você está executando uma compilação de depuração do PurrfectSnap", - "debug_build_summary_content": "Versão {versionName} ({versionCode})", - "debug_build_summary_date": "Data de construção: {date} ({days} dias atrás)", - "quick_actions_title": "Ações rápidas", - "download_icon_description": "Download", - "completed_icon_description": "Concluído", - "failed_icon_description": "Fracassado", - "manage_quick_actions_description": "Gerenciar ações rápidas", - "quick_actions_icon_description": "Ações rápidas", - "add_quick_action_description": "Adicionar ação rápida" - }, - "home_logs": { - "no_logs_hint": "Nenhum registro disponível", - "clear_logs_button": "Limpar registros", - "export_logs_button": "Exportar registros", - "saving_logs_toast": "Salvando registros, isso pode demorar um pouco...", - "saved_logs_success_toast": "Registros salvos com sucesso", - "saved_logs_failure_toast": "Falha ao salvar registros" - }, - "home_settings": { - "actions_title": "Ações", - "message_logger_title": "Registrador de mensagens", - "debug_title": "Depurar", - "success_toast": "Feito!", - "message_logger_summary": "{messageCount} mensagens\n{storyCount} histórias", - "export_button": "Exportar", - "clear_button": "Claro", - "view_logger_history_button": "Ver histórico do registrador", - "updates_title": "Atualizações", - "auto_update_check": "Verificação automática de atualizações", - "update_check_frequency": "Frequência de verificação de atualização", - "update_check_frequency_daily": "Diário", - "update_check_frequency_weekly": "Semanalmente", - "update_check_frequency_monthly": "Mensal", - "theme_icon_description": "Tema", - "app_theme_title": "Tema do aplicativo", - "theme_mode_system": "Sistema", - "theme_mode_light": "Luz", - "theme_mode_dark": "Escuro", - "ui_settings_title": "Configurações da IU", - "haptic_feedback_label": "Feedback tátil", - "test_mode_label": "Modo de teste (SOMENTE PARA DEPURAÇÃO)", - "disable_feature_loading_label": "Desativar carregamento de recursos", - "disable_auto_mapper_label": "Desativar Mapeador Automático", - "disable_bypass_indicator_label": "Desativar indicador de status de desvio", - "update_notification_channel_name": "Atualizações do PurrfectSnap", - "update_notification_channel_description": "Notificações para atualizações do PurrfectSnap", - "update_notification_title": "Atualização PurrfectSnap disponível", - "update_notification_text": "A versão %s já está disponível.", - "export_database_failed_toast": "Falha ao exportar banco de dados! __espaço reservado_0__", - "clear_messages_failed_toast": "Falha ao limpar mensagens! __espaço reservado_0__", - "clear_file_failed_toast": "Falha ao limpar o arquivo! __espaço reservado_0__", - "debug_file_config": "Configuração", - "debug_file_mappings": "Mapeamentos", - "debug_file_message_logger": "Registrador de mensagens", - "debug_file_pinned_best_friend": "Melhor amigo fixado", - "debug_file_native_sig_cache": "Cache de assinatura nativo" - }, - "tasks": { - "no_tasks": "Nenhuma tarefa", - "merge_button": "Mesclar", - "failed_to_open_file": "Falha ao abrir o arquivo", - "merge_files_toast": "Mesclando arquivos {count}", - "remove_selected_tasks_title": "Tem certeza de que deseja remover as tarefas selecionadas?", - "remove_all_tasks_title": "Tem certeza de que deseja remover todas as tarefas?", - "delete_files_option": "Exclua também arquivos", - "remove_selected_tasks_confirm": "Remover tarefas {count}?", - "remove_all_tasks_confirm": "Remover todas as tarefas?", - "clear_tasks_description": "Limpar tarefas", - "file_not_found_icon_description": "Arquivo não encontrado", - "image_icon_description": "Imagem", - "video_icon_description": "Vídeo", - "audio_icon_description": "Áudio", - "file_icon_description": "Arquivo", - "download_icon_description": "Download", - "chat_action_icon_description": "Ação de bate-papo", - "cancel_icon_description": "Cancelar", - "success_icon_description": "Sucesso", - "failure_icon_description": "Falha", - "cancelled_icon_description": "Cancelado", - "task_status_failure": "Falha", - "task_status_cancelled": "Cancelado" - }, - "features": { - "disabled": "Desabilitado", - "export_option": "Exportar", - "import_option": "Importar", - "reset_option": "Reiniciar", - "config_export_success_toast": "Configuração exportada com sucesso", - "config_import_success_toast": "Configuração importada com sucesso", - "config_import_failure_toast": "Falha ao importar configuração {error}", - "config_export_failure_toast": "Falha ao exportar configuração {error}", - "saved_config_snackbar": "Configuração salva", - "older_required": "Este recurso requer Snapchat v{version} ou anterior para funcionar corretamente", - "newer_required": "Este recurso requer Snapchat v{version} ou mais recente para funcionar corretamente", - "search_button": "Procurar" - }, - "manage_rule_feature": { - "disable_state_option": "Desabilitado", - "disable_state_subtext": "Nenhum amigo/grupo será afetado", - "whitelist_state_option": "Ninguém exceto...", - "whitelist_state_subtext": "Apenas {count} amigos/grupos serão afetados por esta regra", - "whitelist_state_button": "Selecione amigos/grupos permitidos", - "blacklist_state_option": "Todos, exceto...", - "blacklist_state_subtext": "Todos, exceto {count} amigos/grupos, serão afetados por esta regra", - "blacklist_state_button": "Selecione amigos/grupos excluídos", - "clear_list_button": "Limpar lista de amigos/grupos", - "dialog_clear_confirmation_text": "Tem certeza de que deseja limpar a lista?" - }, - "social": { - "friends_tab": "Amigos", - "groups_tab": "Grupos", - "empty_hint": "(vazio)", - "streaks_expiration_short": "__espaço reservado_0__h" - }, - "manage_scope": { - "logged_stories_button": "Mostrar histórias registradas", - "e2ee_title": "Criptografia ponta a ponta", - "rules_title": "Regras", - "participants_text": "{count} participantes", - "not_found": "Não encontrado", - "streaks_title": "Ondas", - "streaks_length_text": "Comprimento: __espaço reservado_0__", - "streaks_expiration_text": "Expira em {eta}", - "streaks_expiration_text_expired": "Expirado", - "reminder_button": "Definir lembrete", - "delete_scope_confirm_dialog_title": "Tem certeza de que deseja excluir um {scope}?", - "notes_placeholder": "Clique para adicionar uma nota", - "invalid_key_size_32_bytes": "Tamanho de chave inválido (deve ter 32 bytes)", - "successfully_imported_key": "Chave importada com sucesso", - "failed_to_import_key": "Falha ao importar chave: {message}", - "export_base64_button": "Exportar Base64", - "import_base64_button": "Importar Base64" - }, - "logged_stories": { - "story_failed_to_load": "Falha ao carregar", - "no_stories": "Nenhuma história encontrada", - "save_from_cache_button": "Salvar do cache", - "downloaded_to_path": "Baixado em {path}", - "download_failed": "Falha no download: {message}", - "posted_at": "Postado em {date}", - "created_at": "Criado em {date}", - "failed_to_open_file": "Falha ao abrir o arquivo. Verifique os registros para obter mais informações", - "failed_to_get_file": "Falha ao obter arquivo" - }, - "messaging_preview": { - "processed_messages_toast": "Mensagens {count} processadas", - "processed_messages_text": "Mensagens {count} processadas", - "close_button_description": "Fechar", - "bridge_connection_failed": "Falha ao conectar à ponte. Certifique-se de que o Snapchat esteja sendo executado em segundo plano", - "bridge_init_failed": "Falha ao inicializar a ponte de mensagens. Certifique-se de que o Snapchat esteja sendo executado em segundo plano", - "message_fetch_failed": "Falha ao buscar mensagens", - "no_message_hint": "Nenhuma mensagem", - "save_selection_option": "Salvar seleção", - "save_all_option": "Salvar tudo", - "unsave_selection_option": "Seleção não salva", - "unsave_all_option": "Cancelar salvamento de tudo", - "mark_selection_as_seen_option": "Marcar o Snap selecionado como visto", - "mark_all_as_seen_option": "Marcar todos os Snaps como vistos", - "delete_selection_option": "Excluir seleção", - "delete_all_option": "Excluir tudo" - }, - "logger_history": { - "download_started_toast": "Download iniciado!", - "download_success_toast": "Baixado em {path}", - "download_failed_toast": "Falha ao baixar {message}", - "edited_at_text": "{message} (editado em {date})", - "download_button": "Download", - "select_conversation_placeholder": "Selecione uma conversa", - "close_button_description": "Fechar", - "search_button_description": "Procurar", - "list_friend_format": "Amigo {name}", - "list_group_format": "Grupo __espaço reservado_0__", - "no_more_messages": "Não há mais mensagens", - "reverse_order_checkbox": "Ordem inversa", - "chat_attachment": "Anexo {index}", - "empty_message": "Mensagem de bate-papo vazia", - "message_parse_failed": "Falha ao analisar a mensagem", - "unknown_sender": "Remetente desconhecido", - "download_attachment_failed_toast": "Falha ao baixar o anexo", - "log_header_format": "{username} ({type}) - {date}" - }, - "file_imports": { - "import_file_button": "Importar arquivo", - "file_not_found": "Arquivo não encontrado", - "file_import_failed": "Falha ao importar arquivo: {error}", - "file_imported": "Arquivo importado com sucesso", - "file_delete_failed": "Falha ao excluir o arquivo", - "no_files_hint": "Aqui você pode importar arquivos para usar no Snapchat. Pressione o botão abaixo para importar um arquivo." - }, - "better_location": { - "spoofed_coordinates_title": "Lat {latitude}, Lng {longitude}", - "save_coordinates_dialog_title": "Salvar coordenadas", - "saved_name_dialog_hint": "Nome salvo", - "latitude_dialog_hint": "Latitude", - "longitude_dialog_hint": "Longitude", - "save_dialog_button": "Salvar", - "choose_location_button": "Escolha o local", - "teleport_to_friend_button": "Teleporte para amigo", - "spoof_location_toggle": "Localização falsa", - "suspend_location_updates": "Suspender atualizações de localização", - "saved_coordinates_title": "Coordenadas salvas", - "no_saved_coordinates_hint": "Nenhuma coordenada salva", - "delete_dialog_title": "Excluir coordenada salva", - "delete_dialog_message": "Tem certeza de que deseja excluir esta coordenada salva?", - "teleport_to_friend_title": "Teleporte para amigo", - "search_bar": "Procurar", - "no_friends_map": "Nenhum amigo no mapa", - "no_friends_found": "Nenhum amigo encontrado", - "edit_location_button_description": "Editar local", - "add_icon_description": "Adicionar", - "edit_icon_description": "Editar", - "delete_icon_description": "Excluir" - } - }, - "dialogs": { - "add_friend": { - "title": "Adicionar amigo ou grupo", - "search_hint": "Procurar", - "fetch_error": "Falha ao buscar dados", - "category_groups": "Grupos", - "category_friends": "Amigos", - "participants_text": "{count} participantes", - "search_icon_description": "Procurar" - }, - "scripting_warning": { - "title": "Aviso", - "content": "PurrfectSnap inclui uma ferramenta de script, permitindo a execução de código definido pelo usuário em seu dispositivo. Tenha extremo cuidado e instale apenas módulos de fontes conhecidas e confiáveis. Módulos não autorizados ou não verificados podem representar riscos de segurança para o seu sistema." - }, - "reset_config": { - "title": "Redefinir configuração", - "content": "Tem certeza de que deseja redefinir a configuração?", - "success_toast": "Configuração redefinida com sucesso" - }, - "export_config": { - "title": "Exportar dados confidenciais?", - "content": "Quer exportar a configuração com dados confidenciais? (Como coordenadas de localização, etc.)" - }, - "messaging_action": { - "title": "Escolha os tipos de conteúdo para processar", - "select_all_button": "Selecionar tudo" - }, - "file_imports": { - "no_files_settings_hint": "Nenhum arquivo encontrado. Certifique-se de ter importado os arquivos necessários na seção Importações de arquivos", - "settings_select_file_hint": "Selecione um arquivo importado" - }, - "quick_actions_dialog": { - "title": "Editar ações rápidas", - "subtitle": "Selecione e dimensione suas ações rápidas." - } - }, - "friend_tracker": { - "rules_tab": "Regras", - "logs_tab": "Registros", - "export_dialog_title": "Exportar", - "bulk_export_button": "Exportação em massa", - "individual_export_button": "Exportação individual", - "invalid_import_type_dialog_title": "Tipo de importação inválido", - "invalid_import_type_dialog_text": "O arquivo selecionado não é compatível com este tipo de importação. Selecione o tipo de importação correto.", - "import_dialog_title": "Importar", - "bulk_import_button": "Importação em massa", - "individual_import_button": "Importação individual", - "import_button_description": "Importar", - "export_button_description": "Exportar", - "export_button": "Exportar", - "delete_button_description": "Excluir", - "delete_button": "Excluir", - "catalog_button_description": "Catálogo", - "catalog_button": "Catálogo", - "add_rule_button_description": "Adicionar regra", - "add_rule_button": "Adicionar regra", - "no_rules_found": "Nenhuma regra encontrada", - "empty_rule_name": "(vazio)", - "events_suffix": "eventos", - "scopes_suffix": "escopos", - "select_rule_to_export_title": "Selecione a regra para exportar", - "deleted_logs_toast": "Registros {count} excluídos", - "delete_logs_dialog_title": "Excluir registros?", - "deleting_logs_dialog_text": "Excluindo registros de {count}...", - "delete_logs_dialog_confirm_text": "Isso excluirá os logs com base no filtro atual e na consulta de pesquisa. Esta ação não pode ser desfeita.", - "exported_logs_toast": "Registros exportados!", - "export_logs_failed_toast": "Falha ao exportar registros. Verifique o logcat para mais detalhes.", - "export_logs_dialog_title": "Exportar registros?", - "exporting_logs_dialog_text": "Exportando registros...", - "export_logs_dialog_confirm_text": "Isso exportará os logs com base no filtro atual e na consulta de pesquisa.", - "export_as_button": "Exportar como {type}", - "filters_title": "Filtros", - "search_by_label": "Pesquisar por", - "newest_first_label": "O mais novo primeiro", - "since_label": "Desde", - "until_label": "Até", - "pick_a_date_button": "Escolha uma data", - "search_placeholder": "Procurar", - "filter_button_description": "Filtro", - "clear_button_description": "Claro", - "no_logs_found": "Nenhum registro encontrado", - "log_event_format": "{event} em {conversation}", - "condition_only_inside_conversation": "Só quando estou dentro de uma conversa", - "condition_only_outside_conversation": "Somente quando estou fora da conversa", - "condition_only_when_app_active": "Somente quando o Snapchat está ativo", - "condition_only_when_app_inactive": "Somente quando o Snapchat está inativo", - "condition_no_push_notification_when_app_active": "Nenhuma notificação quando o Snapchat está ativo", - "add_event_dialog_title": "Adicionar Evento", - "event_type_label": "Tipo de evento", - "triggers_title": "Gatilhos", - "conditions_title": "Condições", - "add_button": "Adicionar", - "default_rule_name": "Regra personalizada", - "discard_changes_dialog_title": "Descartar alterações?", - "discard_changes_dialog_text": "Você tem alterações não salvas. Tem certeza de que deseja descartá-los?", - "discard_button": "Descartar", - "cannot_save_rule_dialog_title": "Não é possível salvar a regra", - "cannot_save_rule_dialog_text": "Uma regra deve ter pelo menos um evento para salvar.", - "duplicate_rule_name_dialog_title": "Nome de regra duplicado", - "duplicate_rule_name_dialog_text": "Já existe uma regra com este nome. Escolha um nome diferente.", - "delete_rule_dialog_title": "Excluir regra", - "delete_rule_dialog_text": "Tem certeza de que deseja excluir esta regra?", - "new_rule_title": "Nova regra", - "edit_rule_title": "Editar regra", - "back_button_description": "Voltar", - "save_button_description": "Salvar", - "general_section_title": "Em geral", - "rule_name_label": "Nome da regra", - "author_name_label": "Nome do autor", - "scope_section_title": "Escopo", - "scope_all": "Todos", - "scope_whitelist": "Lista de permissões", - "scope_blacklist": "Lista negra", - "select_friends_groups_button": "Selecione Amigos/Grupos ({count})", - "events_section_title": "Eventos", - "add_event_button": "Adicionar Evento", - "no_events_text": "Nenhum evento" - }, - "friend_tracker_catalog": { - "download_failed": "Falha no download: {code}", - "error": "Erro: {message}", - "no_repos_added": "Nenhum repositório adicionado.", - "no_rules_available": "Nenhuma regra disponível em nenhum repositório.", - "by_author": "por {author}", - "imported_button": "Importado", - "import_button": "Importar", - "title": "Catálogo Rastreador de Amigos", - "manage_repos_description": "Gerenciar repositórios" - }, - "friend_tracker_export": { - "title": "Regras de exportação", - "back_button_description": "Voltar", - "exported_toast": "Regras do rastreador de amigos exportadas!", - "export_failed_toast": "Falha ao exportar regras: {message}", - "save_button": "Salvar", - "expand_button_description": "Expandir" - }, - "friend_tracker_import": { - "title": "Regras de importação", - "back_button_description": "Voltar", - "imported_toast": "Regras do rastreador de amigos importadas!", - "import_failed_toast": "Falha ao importar regras: {message}", - "confirm_button": "Confirmar", - "expand_button_description": "Expandir" - }, - "friend_tracker_repos": { - "invalid_repo_title": "Repositório inválido", - "add_repo_button": "Adicionar repositório", - "add_repo_dialog_title": "Adicionar URL do repositório", - "repo_url_label": "URL do repositório", - "repo_added_toast": "Repositório adicionado com sucesso!", - "invalid_repo_error": "Este não parece ser um repositório válido do Friend Tracker.", - "add_repo_failed_toast": "Falha ao adicionar repositório: {message}", - "add_button": "Adicionar", - "no_repos_added": "Nenhum repositório adicionado", - "remove_button": "Remover", - "remove_repo_dialog_title": "Remover repositório", - "remove_repo_dialog_text": "Tem certeza de que deseja remover este repositório?" - }, - "navigation": { - "tracker_tab_label": "Rastreador", - "customize_bottom_bar_title": "Personalizar barra inferior", - "customize_bottom_bar_subtitle": "Reordene, adicione ou remova guias. Máximo de cinco.", - "shown_tabs_title": "Guias mostradas", - "no_tabs_selected_text": "Nenhuma guia selecionada", - "available_tabs_title": "Guias disponíveis", - "reset_button": "Reiniciar", - "done_button": "Feito" - }, - "scripting": { - "script_already_installed": "Script já instalado!", - "downloading_script": "Baixando roteiro...", - "script_downloaded": "Script {name} baixado!", - "download_script_failed": "Falha ao baixar o script. Verifique os registros para obter mais detalhes", - "import_script_from_url_title": "Importar script do URL", - "import_script_warning": "Aviso: scripts importados podem ser prejudiciais ao seu dispositivo. Importe scripts apenas de fontes confiáveis.", - "enter_url_label": "Insira o URL aqui:", - "script_imported": "Script {name} importado!", - "import_failed": "Falha ao importar script. __espaço reservado_0__. Verifique os registros para obter mais detalhes", - "import_button": "Importar", - "update_module_button": "Módulo de atualização", - "updating_script": "Atualizando script {name}...", - "module_not_found": "Módulo não encontrado", - "updated_script": "{name} atualizado para a versão {version}", - "update_module_failed": "Falha ao atualizar o módulo. Verifique os registros para obter mais detalhes", - "edit_module_button": "Editar Módulo", - "open_module_failed": "Falha ao abrir o arquivo do módulo. Verifique os registros para obter mais detalhes", - "clear_module_data_button": "Limpar dados do módulo", - "module_data_cleared": "Dados do módulo apagados!", - "clear_module_data_failed": "Falha ao limpar os dados do módulo. Verifique os registros para obter mais detalhes", - "delete_module_button": "Excluir módulo", - "deleted_script": "Script excluído {name}!", - "delete_module_failed": "Falha ao excluir o módulo. Verifique os registros para obter mais detalhes", - "actions_title": "Ações", - "no_description": "Sem descrição", - "update_available": "Atualização disponível: {version}", - "actions_button": "Ações", - "loaded_script": "Script carregado {name}", - "unloaded_script": "Script descarregado {name}", - "enable_script_failed": "Falha ao ativar o script. Verifique os registros para obter mais detalhes", - "disable_script_failed": "Falha ao desativar o script. Verifique os registros para obter mais detalhes", - "select_scripts_folder_toast": "Por favor selecione sua pasta de scripts!", - "manage_repos_button": "Gerenciar repositórios", - "import_from_url_button": "Importar do URL", - "open_scripts_folder_button": "Abrir pasta de scripts", - "no_settings_for_module": "Este módulo não possui nenhuma configuração", - "installed_scripts_tab": "Scripts instalados", - "catalog_tab": "Catálogo", - "no_scripts_folder_selected_title": "Nenhuma pasta de scripts selecionada", - "select_folder_button": "Selecione a pasta", - "no_scripts_found_title": "Nenhum script encontrado.", - "use_catalog_to_add_scripts": "Use a guia do catálogo para adicionar scripts!", - "ok_button_timeout": "OK (__espaço reservado_0__)", - "documentation_button": "Documentação", - "catalog": { - "script_already_installed": "Script já instalado!", - "download_failed": "Falha no download: {code}", - "script_downloaded": "Script baixado!", - "could_not_create_file": "Não foi possível criar o arquivo.", - "no_scripts_folder_selected": "Nenhuma pasta de scripts selecionada.", - "error": "Erro: {message}", - "no_repos_added": "Nenhum repositório adicionado.", - "repo_list_info": "Aqui você pode encontrar uma lista de repositórios:", - "link_text": "Link", - "no_scripts_available": "Nenhum script disponível em nenhum repositório.", - "by_author": "por {author}", - "version": "Versão: {version}", - "installed_button": "Instalado", - "download_button": "Download" - }, - "repos": { - "invalid_repo_title": "Repositório inválido", - "add_repo_button": "Adicionar repositório", - "add_repo_dialog_title": "Adicionar URL do repositório", - "repo_url_label": "URL do repositório", - "repo_added_toast": "Repositório adicionado com sucesso!", - "invalid_repo_error": "Este não parece ser um repositório de script válido.", - "add_repo_failed_toast": "Falha ao adicionar repositório: {message}", - "add_button": "Adicionar", - "no_repos_added": "Nenhum repositório adicionado", - "remove_button": "Remover", - "remove_repo_dialog_title": "Remover repositório", - "remove_repo_dialog_text": "Tem certeza de que deseja remover este repositório?" - } - }, - "features": { - "config_import": { - "title": "Confirmar importação", - "back_button_description": "Voltar", - "config_imported_toast": "Configuração importada!", - "confirm_button": "Confirmar", - "expand_button_description": "Expandir", - "enable_feature": "Habilitar recurso", - "enabled": "Habilitado", - "disabled": "Desabilitado" - }, - "config_export": { - "title": "Resumo de exportação", - "back_button_description": "Voltar", - "save_button": "Salvar", - "expand_button_description": "Expandir", - "enable_feature": "Habilitar recurso", - "enabled": "Habilitado", - "disabled": "Desabilitado" - } - }, - "manage_repos": { - "title": "Gerenciar repositórios {type}", - "add_repo_button": "Adicionar repositório", - "add_repo_dialog_title": "Adicionar URL do repositório", - "repo_url_label": "URL do repositório", - "repo_added_successfully": "Repositório adicionado com sucesso!", - "add_repo_failed": "Falha ao adicionar repositório: {message}", - "add_button": "Adicionar", - "no_repos_added": "Nenhum repositório adicionado", - "remove_button": "Remover" - } - }, - "rules": { - "toasts": { - "enabled": "{ruleName} ativado", - "disabled": "{ruleName} desativado" - }, - "modes": { - "blacklist": "Modo lista negra", - "whitelist": "Modo de lista de permissões" - }, - "properties": { - "auto_download": { - "name": "Download automático", - "description": "Baixe Snaps automaticamente ao visualizá-los", - "options": { - "blacklist": "Excluir do download automático", - "whitelist": "Download automático" - } - }, - "stealth": { - "name": "Modo furtivo", - "description": "Impede que alguém saiba que você abriu seus Snaps/Bate-papos e conversas", - "options": { - "blacklist": "Excluir do modo furtivo", - "whitelist": "Modo furtivo" - } - }, - "auto_save": { - "name": "Salvamento automático", - "description": "Salva mensagens de bate-papo ao visualizá-las", - "options": { - "blacklist": "Excluir do salvamento automático", - "whitelist": "Salvamento automático" - } - }, - "unsaveable_messages": { - "name": "Mensagens não salváveis", - "description": "Impede que mensagens sejam salvas no chat por outras pessoas", - "options": { - "blacklist": "Excluir de mensagens que não podem ser salvas", - "whitelist": "Mensagens não salváveis" - } - }, - "auto_open_snaps": { - "name": "Snaps de abertura automática", - "description": "Abre Snaps automaticamente ao recebê-los", - "options": { - "blacklist": "Excluir dos snaps de abertura automática", - "whitelist": "Snaps de abertura automática" - } - }, - "hide_friend_feed": { - "name": "Ocultar do feed de amigos" - }, - "e2e_encryption": { - "name": "Use criptografia E2E" - }, - "pin_conversation": { - "name": "Fixar conversa" - }, - "exclude_message_logger": { - "name": "Excluir do registrador de mensagens" - } - } - }, - "actions": { - "clean_snapchat_cache": { - "name": "Limpe o cache do Snapchat", - "description": "Limpa o cache do Snapchat" - }, - "manage_friend_list": { - "name": "Gerenciar lista de amigos", - "description": "Importe/exporte sua lista de amigos ao fazer backup" - }, - "export_chat_messages": { - "name": "Exportar mensagens de bate-papo", - "description": "Exporta mensagens de conversa para um arquivo JSON/HTML/TXT" - }, - "export_memories": { - "name": "Exportar memórias", - "description": "Exporta memórias para um arquivo ZIP" - }, - "bulk_messaging_action": { - "name": "Ação de mensagens em massa", - "description": "Executa operações como exclusão de amigos ou exclusão em massa de conversas" - }, - "regen_mappings": { - "name": "Regenerar mapeamentos", - "description": "Regenerar mapeamentos manualmente" - }, - "change_language": { - "name": "Alterar idioma", - "description": "Alterar o idioma do PurrfectSnap" - }, - "file_imports": { - "name": "Importações de arquivos", - "description": "Importe arquivos para uso no Snapchat" - }, - "friend_tracker": { - "name": "Rastreador de amigos", - "description": "Acompanhe seus amigos no Snapchat" - }, - "logger_history": { - "name": "Histórico do registrador", - "description": "Ver o histórico de mensagens registradas" - } - }, - "features": { - "notices": { - "unstable": "⚠ Instável", - "ban_risk": "⚠ Este recurso pode causar banimentos", - "internal_behavior": "⚠ Isso pode prejudicar o comportamento interno do Snapchat" - }, - "properties": { - "downloader": { - "name": "Baixador", - "description": "Baixar mídia Snapchat", - "properties": { - "save_folder": { - "name": "Salvar pasta", - "description": "Selecione o diretório para o qual todas as mídias devem ser baixadas" - }, - "auto_download_sources": { - "name": "Fontes de download automático", - "description": "Selecione as fontes para download automático" - }, - "prevent_self_auto_download": { - "name": "Impedir download automático", - "description": "Impede que seus próprios Snaps sejam baixados automaticamente" - }, - "path_format": { - "name": "Formato do caminho", - "description": "Especifique o formato do caminho do arquivo" - }, - "allow_duplicate": { - "name": "Permitir duplicado", - "description": "Permite que a mesma mídia seja baixada várias vezes" - }, - "merge_overlays": { - "name": "Mesclar sobreposições", - "description": "Combina o texto e a mídia de um Snap em um único arquivo" - }, - "force_image_format": { - "name": "Forçar formato de imagem", - "description": "Força as imagens a serem salvas em um formato especificado" - }, - "force_voice_note_format": { - "name": "Forçar formato de nota de voz", - "description": "Força que as notas de voz sejam salvas em um formato especificado" - }, - "auto_download_voice_notes": { - "name": "Download automático de notas de voz", - "description": "Baixa automaticamente notas de voz ao reproduzi-las" - }, - "download_profile_pictures": { - "name": "Baixar fotos de perfil", - "description": "Permite que você baixe fotos de perfil da página de perfil" - }, - "opera_download_button": { - "name": "Botão de download do Opera", - "description": "Adiciona um botão de download no canto superior direito ao visualizar um Snap.\nManter os botões pressionados forçará o download" - }, - "download_context_menu": { - "name": "Baixar menu de contexto", - "description": "Permite baixar/visualizar mensagens de uma conversa ou história usando o menu de contexto.\nManter os botões pressionados forçará o download" - }, - "ffmpeg_options": { - "name": "Opções FFmpeg", - "description": "Especifique opções adicionais do FFmpeg", - "properties": { - "threads": { - "name": "Tópicos", - "description": "A quantidade de threads a serem usados" - }, - "preset": { - "name": "Predefinido", - "description": "Defina a velocidade da conversão" - }, - "constant_rate_factor": { - "name": "Fator de taxa constante", - "description": "Defina o fator de taxa constante para o codificador de vídeo\nDe 0 a 51 para libx264" - }, - "video_bitrate": { - "name": "Taxa de bits de vídeo", - "description": "Defina a taxa de bits do vídeo (kbps)" - }, - "audio_bitrate": { - "name": "Taxa de bits de áudio", - "description": "Defina a taxa de bits do áudio (kbps)" - }, - "custom_video_codec": { - "name": "Codec de vídeo personalizado", - "description": "Defina um codec de vídeo personalizado (por exemplo, libx264)" - }, - "custom_audio_codec": { - "name": "Codec de áudio personalizado", - "description": "Defina um codec de áudio personalizado (por exemplo, AAC)" - } - } - }, - "logging": { - "name": "Registro", - "description": "Mostra brindes quando a mídia está sendo baixada" - }, - "custom_path_format": { - "name": "Formato de caminho personalizado", - "description": "Especifique um formato de caminho personalizado para mídia baixada\n\nVariáveis ​​disponíveis:\n - %nome de usuário%\n - %fonte%\n -% hash%\n -%data_hora%" - } - } - }, - "user_interface": { - "name": "Interface do usuário", - "description": "Mude a aparência do Snapchat", - "properties": { - "enable_app_appearance": { - "name": "Habilitar configurações de aparência do aplicativo", - "description": "Ativa a configuração oculta de aparência do aplicativo\nPode não ser necessário em versões mais recentes do Snapchat" - }, - "friend_feed_message_preview": { - "name": "Visualização da mensagem do feed de amigos", - "description": "Mostra uma prévia das últimas mensagens no Friend Feed", - "properties": { - "amount": { - "name": "Quantia", - "description": "A quantidade de mensagens a serem visualizadas" - } - } - }, - "snap_preview": { - "name": "Visualização instantânea", - "description": "Exibe uma pequena prévia ao lado dos Snaps não vistos no bate-papo" - }, - "bootstrap_override": { - "name": "Substituição de inicialização", - "description": "Substitui as configurações de inicialização da interface do usuário", - "properties": { - "app_appearance": { - "name": "Aparência do aplicativo", - "description": "Define uma aparência de aplicativo persistente" - }, - "home_tab": { - "name": "Guia inicial", - "description": "Substitui a guia de inicialização ao abrir o Snapchat" - } - } - }, - "force_amoled_theme": { - "name": "Modo escuro Amolado", - "description": "Usa um fundo preto verdadeiro para o tema escuro" - }, - "map_friend_nametags": { - "name": "Nomes de mapa de amigos aprimorados", - "description": "Melhora os Nametags dos amigos no Snapmap" - }, - "prevent_message_list_auto_scroll": { - "name": "Impedir a rolagem automática da lista de mensagens", - "description": "Impede que a lista de mensagens role para baixo ao enviar/receber uma mensagem" - }, - "streak_expiration_info": { - "name": "Mostrar informações de expiração de sequência", - "description": "Mostra um cronômetro de expiração de sequência próximo ao contador de sequências" - }, - "hide_friend_feed_entry": { - "name": "Ocultar entrada de feed de amigo", - "description": "Oculta um amigo específico do Friend Feed\nUse a guia social para gerenciar esse recurso" - }, - "hide_streak_restore": { - "name": "Ocultar restauração de sequência", - "description": "Oculta o botão Restaurar no feed do amigo" - }, - "hide_quick_add_suggestions": { - "name": "Ocultar sugestões de adição rápida", - "description": "Remove sugestões de adição rápida de amigos" - }, - "hide_story_suggestions": { - "name": "Ocultar sugestões de histórias", - "description": "Remove sugestões da página Histórias" - }, - "hide_ui_components": { - "name": "Ocultar componentes da UI", - "description": "Selecione quais componentes da UI serão ocultados" - }, - "opera_media_quick_info": { - "name": "Informações rápidas sobre mídia Opera", - "description": "Mostra informações úteis da mídia, como data de criação no menu de contexto do Opera Viewer" - }, - "old_bitmoji_selfie": { - "name": "Selfie Bitmoji Antiga", - "description": "Traz de volta as selfies Bitmoji de versões mais antigas do Snapchat" - }, - "disable_spotlight": { - "name": "Desativar destaque", - "description": "Desativa a página Spotlight" - }, - "friend_feed_menu_buttons": { - "name": "Botões do menu de feed de amigos", - "description": "Selecione quais botões serão exibidos no menu Friend Feed" - }, - "auto_close_friend_feed_menu": { - "name": "Menu de feed de amigo para fechamento automático", - "description": "Fecha automaticamente o menu Friend Feed após pressionar um botão de configuração" - }, - "vertical_story_viewer": { - "name": "Visualizador vertical de histórias", - "description": "Ativa o visualizador vertical de histórias para todas as histórias" - }, - "enable_friend_feed_menu_bar": { - "name": "Barra de menu do feed de amigos", - "description": "Ativa a nova barra de menu do feed de amigos" - }, - "message_indicators": { - "name": "Indicadores de mensagens", - "description": "Adiciona ícones de indicadores específicos às mensagens\nObservação: os indicadores podem não ser 100% precisos" - }, - "stealth_mode_indicator": { - "name": "Indicador de modo furtivo", - "description": "Adiciona um emoji 👻 próximo às conversas em modo furtivo" - }, - "edit_text_override": { - "name": "Editar substituição de texto", - "description": "Substitui o comportamento do campo de texto" - }, - "prevent_forced_keyboard": { - "name": "Impedir teclado forçado", - "description": "Impede que o Snapchat abra automaticamente o teclado quando você abre uma conversa" - }, - "settings_menu": { - "name": "Menu Configurações", - "description": "Muda a maneira como você abre o menu PurrfectSnap", - "options": { - "default": "Padrão", - "legacy": "Legado" - } - } - } - }, - "messaging": { - "name": "Mensagens", - "description": "Mude a forma como você interage com os amigos", - "properties": { - "bypass_screenshot_detection": { - "name": "Ignorar detecção de captura de tela", - "description": "Impede que o Snapchat detecte quando você faz uma captura de tela" - }, - "anonymous_story_viewing": { - "name": "Visualização anônima de histórias", - "description": "Impede que alguém saiba que você viu a história deles" - }, - "prevent_story_rewatch_indicator": { - "name": "Evitar indicador de repetição de história", - "description": "Impede que alguém saiba que você assistiu novamente a história deles" - }, - "hide_peek_a_peek": { - "name": "Ocultar espiada", - "description": "Impede que notificações sejam enviadas quando você desliza pela metade para entrar em um bate-papo" - }, - "hide_bitmoji_presence": { - "name": "Ocultar presença de Bitmoji", - "description": "Impede que seu Bitmoji apareça durante o bate-papo" - }, - "hide_typing_notifications": { - "name": "Ocultar notificações de digitação", - "description": "Impede que alguém saiba que você está digitando uma mensagem" - }, - "unlimited_snap_view_time": { - "name": "Tempo ilimitado de visualização instantânea", - "description": "Remove o limite de tempo para visualização de Snaps" - }, - "auto_mark_as_read": { - "name": "Marcação automática como lida", - "description": "Marca automaticamente mensagens/snaps como lidas mesmo quando o modo Stealth está ativado" - }, - "mark_snap_as_seen_button": { - "name": "Botão Marcar Snap como Visto", - "description": "Adiciona um botão para marcar um Snap como visto ao visualizá-lo.\nIsso funcionará mesmo quando o modo Stealth estiver ativado" - }, - "skip_when_marking_as_seen": { - "name": "Pular ao marcar como visto", - "description": "Pula automaticamente para o próximo Snap ao marcar um Snap como visto.\nUse em combinação com o botão Marcar Snap como Visto" - }, - "loop_media_playback": { - "name": "Reprodução de mídia em loop", - "description": "Faz um loop na reprodução de mídia ao visualizar Snaps/Histórias" - }, - "disable_replay_in_ff": { - "name": "Desativar repetição em FF", - "description": "Desativa a capacidade de reproduzir com um toque longo no Friend Feed" - }, - "half_swipe_notifier": { - "name": "Notificador de meio furto", - "description": "Notifica você quando alguém desliza parcialmente para uma conversa", - "properties": { - "min_duration": { - "name": "Duração Mínima", - "description": "A duração mínima do meio furto (em segundos)" - }, - "max_duration": { - "name": "Duração Máxima", - "description": "A duração máxima do meio furto (em segundos)" - } - } - }, - "call_start_confirmation": { - "name": "Confirmação de início de chamada", - "description": "Mostra uma caixa de diálogo de confirmação ao iniciar uma chamada" - }, - "unlimited_conversation_pinning": { - "name": "Fixação ilimitada de conversas", - "description": "Permite fixar uma quantidade ilimitada de conversas localmente" - }, - "disable_snap_mode_restrictions": { - "name": "Desativar restrições do modo Snap", - "description": "Permite que você visualize Snaps autodestrutivos sem restrições" - }, - "prevent_message_sending": { - "name": "Impedir o envio de mensagens", - "description": "Impede o envio de certos tipos de mensagens" - }, - "friend_mutation_notifier": { - "name": "Notificador de mutação de amigo", - "description": "Notifica você quando algo muda no perfil de um amigo" - }, - "better_notifications": { - "name": "Melhores notificações", - "description": "Adiciona mais informações nas notificações recebidas", - "properties": { - "group_notifications": { - "name": "Notificações de grupo", - "description": "Agrupe notificações em uma única" - }, - "chat_preview": { - "name": "Visualização do bate-papo", - "description": "Mostra uma prévia das mensagens recebidas na notificação" - }, - "media_preview": { - "name": "Visualização de mídia", - "description": "Mostra uma prévia dos tipos de mídia selecionados na notificação" - }, - "media_caption": { - "name": "Legenda de mídia", - "description": "Mostra a legenda anexada da mídia na notificação" - }, - "stacked_media_messages": { - "name": "Mensagens de mídia empilhadas", - "description": "Combina várias mensagens de mídia em uma notificação de texto quando elas não podem ser visualizadas. Use em combinação com a visualização do bate-papo" - }, - "friend_add_source": { - "name": "Fonte de adição de amigo", - "description": "Mostra a origem de um pedido de amizade na notificação" - }, - "reply_button": { - "name": "Botão Responder", - "description": "Adiciona um botão de resposta à notificação" - }, - "smart_replies": { - "name": "Respostas inteligentes", - "description": "Adiciona respostas sugeridas às notificações (Android 10+). Use em combinação com o botão Responder" - }, - "download_button": { - "name": "Botão de download", - "description": "Permite que você baixe mídia da notificação" - }, - "mark_as_read_button": { - "name": "Botão Marcar como lido", - "description": "Permite marcar uma mensagem como lida na notificação" - }, - "mark_as_read_and_save_in_chat": { - "name": "Marcar como lido e salvar no bate-papo", - "description": "Adiciona uma marca como lida e salva no botão de bate-papo à notificação" - } - } - }, - "notification_blacklist": { - "name": "Lista negra de notificações", - "description": "Selecione notificações que devem ser bloqueadas" - }, - "message_logger": { - "name": "Registrador de mensagens", - "description": "Impede que mensagens sejam excluídas", - "properties": { - "keep_my_own_messages": { - "name": "Manter minhas próprias mensagens", - "description": "Impede que suas próprias mensagens sejam excluídas" - }, - "auto_purge": { - "name": "Purga automática", - "description": "Exclui automaticamente mensagens em cache mais antigas que o período de tempo especificado" - }, - "message_filter": { - "name": "Filtro de mensagens", - "description": "Selecione quais mensagens devem ser registradas (vazio para todas as mensagens)" - }, - "deleted_message_color": { - "name": "Cor da mensagem excluída", - "description": "Define a cor das mensagens excluídas" - } - } - }, - "auto_save_messages_in_conversations": { - "name": "Salvar mensagens automaticamente", - "description": "Salva automaticamente todas as mensagens nas conversas" - }, - "gallery_media_send_override": { - "name": "Substituição de envio de mídia da galeria", - "description": "Falsifica a fonte de mídia ao enviar da Galeria" - }, - "strip_media_metadata": { - "name": "Remover metadados de mídia", - "description": "Remove metadados de mídia antes de enviar como mensagem" - }, - "bypass_message_retention_policy": { - "name": "Ignorar política de retenção de mensagens", - "description": "Impede que as mensagens sejam excluídas após visualizá-las" - }, - "bypass_message_action_restrictions": { - "name": "Ignorar restrições de ação de mensagem", - "description": "Permite que você reaja a um instantâneo sem abri-lo ou salve uma mensagem que não pode ser salva" - }, - "remove_groups_locked_status": { - "name": "Remover status de grupos bloqueados", - "description": "Permite que você visualize informações do grupo após ser expulso" - }, - "double_tap_chat_action": { - "name": "Ação de bate-papo com toque duplo", - "description": "Executa uma ação personalizada ao tocar duas vezes em uma mensagem no bate-papo" - }, - "double_tap_chat_action_custom_emoji": { - "name": "Toque duplo em ação de bate-papo, reação de emoji personalizado", - "description": "Define uma reação emoji personalizada para a ação de bate-papo com toque duplo" - } - } - }, - "global": { - "name": "Global", - "description": "Ajustar configurações globais do Snapchat", - "properties": { - "better_location": { - "name": "Melhor localização", - "description": "Melhora a localização do Snapchat", - "properties": { - "spoof_location": { - "name": "Localização falsa", - "description": "Falsifica sua localização para uma localização específica" - }, - "coordinates": { - "name": "Coordenadas", - "description": "Defina as coordenadas do local falsificado" - }, - "walk_radius": { - "name": "Raio de caminhada", - "description": "Ande aleatoriamente dentro deste raio (pés)" - }, - "always_update_location": { - "name": "Sempre atualizar o local", - "description": "Forçar o Snapchat a atualizar a localização mesmo que nenhum dado de GPS seja recebido" - }, - "suspend_location_updates": { - "name": "Suspender atualizações de localização", - "description": "Impede que sua localização seja atualizada" - }, - "spoof_battery_level": { - "name": "Nível de bateria falso", - "description": "Falsifica o nível da bateria do seu dispositivo no mapa\nO valor deve estar entre 0 e 100" - }, - "spoof_headphones": { - "name": "Fones de ouvido falsos", - "description": "Falsifica o status de ouvir música no mapa" - }, - "show_battery_level": { - "name": "Mostrar nível da bateria", - "description": "Mostra o nível da bateria dos seus amigos no mapa" - } - } - }, - "snapchat_plus": { - "name": "Snapchat Plus", - "description": "Habilita recursos do Snapchat Plus\nAlguns recursos do lado do servidor podem não funcionar" - }, - "media_upload_quality": { - "name": "Qualidade de upload de mídia", - "description": "Substitui a qualidade do upload de mídia", - "properties": { - "force_video_upload_source_quality": { - "name": "Forçar qualidade da fonte de upload de vídeo", - "description": "Força o Snapchat a usar a qualidade da fonte ao enviar vídeos\nObserve que isso pode não remover metadados da mídia" - }, - "disable_image_compression": { - "name": "Desativar compactação de imagem", - "description": "Desativa a compactação de imagem ao fazer upload de mídia" - }, - "custom_image_upload_format": { - "name": "Formato de upload de imagem personalizado", - "description": "Define um formato de upload de imagem personalizado\nSelecione um formato sem perdas (como PNG) para obter a melhor qualidade" - } - } - }, - "disable_confirmation_dialogs": { - "name": "Desativar caixas de diálogo de confirmação", - "description": "Confirma automaticamente as ações selecionadas" - }, - "auto_updater": { - "name": "Atualizador automático", - "description": "Verifica automaticamente se há novas atualizações" - }, - "disable_metrics": { - "name": "Desabilitar métricas", - "description": "Bloqueia o envio de dados analíticos específicos para o Snapchat" - }, - "disable_story_sections": { - "name": "Desativar seções da história", - "description": "Remove seções da página Histórias\nPode exigir uma atualização para funcionar corretamente" - }, - "block_ads": { - "name": "Bloquear anúncios", - "description": "Impede que anúncios sejam exibidos" - }, - "disable_custom_tabs": { - "name": "Desativar guias personalizadas", - "description": "Abre links em aplicativos suportados em vez de no navegador da Web" - }, - "disable_permission_requests": { - "name": "Desabilitar solicitações de permissão", - "description": "Impede que o Snapchat solicite permissões específicas" - }, - "disable_memories_snap_feed": { - "name": "Desativar feed instantâneo de memórias", - "description": "Impede que o Snapchat mostre memórias recentes quando você desliza a câmera para cima" - }, - "spotlight_comments_username": { - "name": "Nome de usuário dos comentários do Spotlight", - "description": "Mostra o nome de usuário do autor nos comentários do Spotlight" - }, - "bypass_video_length_restriction": { - "name": "Ignorar restrições de duração de vídeo", - "description": "Único: envia um único vídeo\nDividir: divida os vídeos após a edição" - }, - "default_video_playback_rate": { - "name": "Taxa de reprodução de vídeo padrão", - "description": "Define a velocidade padrão para reprodução de vídeos\nO valor deve estar entre 0,1 e 4,0" - }, - "video_playback_rate_slider": { - "name": "Controle deslizante de taxa de reprodução de vídeo", - "description": "Adiciona um controle deslizante no menu de contexto do Opera para alterar a taxa de reprodução do vídeo\nObservação: as alterações se aplicam apenas aos vídeos subsequentes" - }, - "disable_google_play_dialogs": { - "name": "Desativar caixas de diálogo do Google Play Services", - "description": "Impedir que as caixas de diálogo de disponibilidade do Google Play Services sejam exibidas" - }, - "default_volume_controls": { - "name": "Controles de volume padrão", - "description": "Força o Snapchat a usar controles de volume do sistema" - }, - "disable_telecom_framework": { - "name": "Desativar estrutura de telecomunicações", - "description": "Impede que o Snapchat use o framework Android Telecom\nIsso permite que você ouça música durante uma chamada" - }, - "hide_active_music": { - "name": "Ocultar música ativa", - "description": "Impede que o Snapchat saiba que você está ouvindo música\nIsso permitirá que você tire fotos usando os botões de controle de volume enquanto ouve música" - }, - "disable_snap_splitting": { - "name": "Desativar divisão instantânea", - "description": "Impede que os Snaps sejam divididos em várias partes\nAs fotos que você enviar se transformarão em vídeos" - } - } - }, - "rules": { - "name": "Regras", - "description": "Gerenciar recursos automáticos para pessoas individuais" - }, - "camera": { - "name": "Câmera", - "description": "Ajuste as configurações corretas para o snap perfeito", - "properties": { - "disable_cameras": { - "name": "Desativar câmeras", - "description": "Impede que o Snapchat use as câmeras selecionadas" - }, - "black_photos": { - "name": "Fotos pretas", - "description": "Substitui as fotos capturadas por um fundo preto\nOs vídeos não são afetados" - }, - "immersive_camera_preview": { - "name": "Pré-visualização imersiva", - "description": "Impede que o Snapchat corte a visualização da câmera\nIsso pode fazer com que a câmera pisque em alguns dispositivos" - }, - "override_front_resolution": { - "name": "Substituir resolução frontal", - "description": "Substitui a resolução da câmera frontal" - }, - "override_back_resolution": { - "name": "Substituir resolução anterior", - "description": "Substitui a resolução da câmera traseira" - }, - "custom_resolution": { - "name": "Resolução personalizada", - "description": "Define uma resolução de câmera personalizada, largura x altura (por exemplo, 1920x1080).\nA resolução personalizada deve ser suportada pelo seu dispositivo" - }, - "front_custom_frame_rate": { - "name": "Taxa de quadros frontal personalizada", - "description": "Substitui a taxa de quadros da câmera frontal" - }, - "back_custom_frame_rate": { - "name": "Voltar Taxa de quadros personalizada", - "description": "Substitui a taxa de quadros da câmera traseira" - }, - "force_camera_source_encoding": { - "name": "Forçar codificação da fonte da câmera", - "description": "Força a codificação da fonte da câmera" - }, - "startup_default_camera": { - "name": "Câmera padrão de inicialização", - "description": "Define a câmera padrão ao abrir o Snapchat" - }, - "hevc_recording": { - "name": "Gravação HEVC", - "description": "Usa codec HEVC (H.265) para gravação de vídeo" - } - } - }, - "streaks_reminder": { - "name": "Lembrete de sequências", - "description": "Notifica você periodicamente sobre suas Streaks", - "properties": { - "interval": { - "name": "Intervalo", - "description": "O intervalo entre cada lembrete (horas)" - }, - "remaining_hours": { - "name": "Tempo restante", - "description": "O tempo restante antes que a notificação seja exibida (horas)" - }, - "group_notifications": { - "name": "Notificações de grupo", - "description": "Agrupe notificações em uma única" - } - } - }, - "experimental": { - "name": "Experimental", - "description": "Recursos experimentais", - "properties": { - "native_hooks": { - "name": "Ganchos nativos", - "description": "Recursos inseguros que se conectam ao código nativo do Snapchat", - "properties": { - "composer_hooks": { - "name": "Ganchos de Compositor", - "description": "Injeta código na estrutura de UI multiplataforma do Composer", - "properties": { - "show_first_created_username": { - "name": "Mostrar primeiro nome de usuário criado", - "description": "Mostra o primeiro nome de usuário criado próximo ao nome de usuário atual na página de perfil" - }, - "bypass_camera_roll_limit": { - "name": "Ignorar limite de rolagem da câmera", - "description": "Aumenta a quantidade máxima de mídia que você pode enviar do rolo da câmera" - }, - "custom_self_destruct_snap_delay": { - "name": "Atraso de snap de autodestruição personalizado", - "description": "Oferece mais opções para o temporizador de autodestruição ao enviar um Snap" - }, - "composer_console": { - "name": "Console do Compositor", - "description": "Permite executar código JavaScript no Composer (somente arm64)" - }, - "composer_logs": { - "name": "Registros do compositor", - "description": "Redireciona logs do console do Composer para PurrfectSnap" - } - } - }, - "disable_bitmoji": { - "name": "Desativar Bitmoji", - "description": "Desativa o Bitmoji do perfil de amigos" - }, - "custom_emoji_font": { - "name": "Fonte Emoji Personalizada", - "description": "Permite que você use uma fonte emoji personalizada. Funciona apenas com fontes .ttf" - }, - "custom_shared_library": { - "name": "Biblioteca compartilhada personalizada", - "description": "Carrega uma biblioteca compartilhada personalizada no Snapchat. Este recurso é apenas para fins de teste" - } - } - }, - "spoof": { - "name": "Paródia", - "description": "Falsificar várias informações sobre você", - "properties": { - "play_store_installer_package_name": { - "name": "Nome do pacote do instalador da Play Store", - "description": "Substitui o nome do pacote do instalador por com.android.vending" - }, - "remove_vpn_transport_flag": { - "name": "Remover sinalizador de transporte VPN", - "description": "Impede que o Snapchat detecte VPNs" - }, - "remove_mock_location_flag": { - "name": "Remover sinalizador de localização simulada", - "description": "Impede que o Snapchat detecte localização simulada" - } - } - }, - "convert_message_locally": { - "name": "Converter mensagem localmente", - "description": "Converte instantâneos para conversar com mídia externa localmente. Isso aparece no menu de contexto de download do chat" - }, - "media_file_picker": { - "name": "Seletor de arquivos de mídia", - "description": "Permite que você escolha qualquer arquivo de vídeo/áudio da galeria" - }, - "story_logger": { - "name": "Registrador de histórias", - "description": "Fornece um histórico de histórias de amigos" - }, - "call_recorder": { - "name": "Gravador de chamadas", - "description": "Grava automaticamente chamadas de áudio" - }, - "account_switcher": { - "name": "Alternador de conta", - "description": "Permite que você alterne entre contas sem sair\nMantenha pressionado o ícone de pesquisa próximo ao seu perfil Bitmoji para abrir o menu\nObservação: esse recurso é experimental e provavelmente mudará no futuro", - "properties": { - "auto_backup_current_account": { - "name": "Conta corrente de backup automático", - "description": "Faz backup automático da conta atual ao sair ou trocar de conta" - } - } - }, - "better_transcript": { - "name": "Melhor transcrição", - "description": "Melhora a transcrição da nota de voz", - "properties": { - "force_transcription": { - "name": "Forçar transcrição de nota de voz", - "description": "Permite que todas as notas de voz sejam transcritas" - }, - "preferred_transcription_lang": { - "name": "Idioma de transcrição preferido", - "description": "O idioma preferido para a transcrição da nota de voz (por exemplo, EN, ES, FR)" - }, - "notification_transcript": { - "name": "Transcrição da Notificação", - "description": "Transcreve notas de voz em notificações\nEste recurso requer que o recurso de visualização de bate-papo esteja ativado no Better Notifications" - } - } - }, - "voice_note_auto_play": { - "name": "Reprodução automática de nota de voz", - "description": "Reproduz automaticamente a próxima nota de voz após o término da atual" - }, - "friend_notes": { - "name": "Notas de amigos", - "description": "Permite adicionar notas aos perfis de amigos" - }, - "cof_experiments": { - "name": "Experimentos COF", - "description": "Habilita recursos não lançados/beta do Snapchat" - }, - "context_menu_fix": { - "name": "Correção do menu de contexto", - "description": "Tente reparar o menu Friend Feed, pois quando o dispositivo está off-line ele não pode ser exibido corretamente" - }, - "app_lock": { - "name": "Bloqueio de aplicativo", - "description": "Impede o acesso ao Snapchat sem senha", - "properties": { - "lock_on_resume": { - "name": "Bloquear no currículo", - "description": "Bloqueia o aplicativo quando ele é reaberto" - } - } - }, - "infinite_story_boost": { - "name": "Impulso de história infinita", - "description": "Ignore o atraso do Story Boost Limit" - }, - "meo_passcode_bypass": { - "name": "Desvio de senha somente para meus olhos", - "description": "Ignorar a senha My Eyes Only\nIsso só funcionará se a senha tiver sido digitada corretamente antes" - }, - "no_friend_score_delay": { - "name": "Sem atraso na pontuação do amigo", - "description": "Remove o atraso ao visualizar uma pontuação de amigos" - }, - "best_friend_pinning": { - "name": "Fixação de melhor amigo", - "description": "Permite que você fixe um amigo como seu melhor amigo número um. Observação: só você pode ver seu melhor amigo fixado" - }, - "e2ee": { - "name": "Criptografia ponta a ponta", - "description": "Criptografa suas mensagens com AES usando uma chave secreta compartilhada\nCertifique-se de salvar sua chave em um lugar seguro!", - "properties": { - "encrypted_message_indicator": { - "name": "Indicador de mensagem criptografada", - "description": "Adiciona um 🔒 emoji ao lado das mensagens criptografadas" - }, - "force_message_encryption": { - "name": "Forçar criptografia de mensagens", - "description": "Impede o envio de mensagens criptografadas para pessoas que não tenham a criptografia E2E ativada somente quando várias conversas forem selecionadas" - } - } - }, - "add_friend_source_spoof": { - "name": "Adicionar falsificação de fonte de amigo", - "description": "Falsifica a origem de um pedido de amizade" - }, - "hidden_snapchat_plus_features": { - "name": "Recursos ocultos do Snapchat Plus", - "description": "Habilita recursos não lançados/beta do Snapchat Plus\nPode não funcionar em versões mais antigas do Snapchat" - }, - "custom_streaks_expiration_format": { - "name": "Formato de expiração de sequências personalizadas", - "description": "Personaliza o formato de expiração de Streaks\n\nVariáveis ​​disponíveis:\n - %c: Contagem de sequências\n - %e: Emoji de ampulheta\n - %d: Dias\n - %h: Horas\n - %m: Minutos\n - %s: segundos\n - %w: Tempo restante" - }, - "prevent_forced_logout": { - "name": "Impedir logout forçado", - "description": "Impede que o Snapchat desconecte você quando você fizer login em outro dispositivo" - }, - "snapscore_changes": { - "name": "Mudanças no Snapscore", - "description": "Rastreia alterações no Snapscore de amigos\nUse este recurso apenas em versões mais recentes do Snapchat" - } - } - }, - "scripting": { - "name": "Scripts", - "description": "Execute scripts personalizados para estender o PurrfectSnap", - "properties": { - "developer_mode": { - "name": "Modo de desenvolvedor", - "description": "Mostra informações de depuração na interface do Snapchat" - }, - "module_folder": { - "name": "Pasta do Módulo", - "description": "A pasta onde os scripts estão localizados" - }, - "auto_reload": { - "name": "Recarga automática", - "description": "Recarrega scripts automaticamente quando eles mudam" - }, - "integrated_ui": { - "name": "UI integrada", - "description": "Permite que scripts adicionem componentes de UI personalizados ao Snapchat" - }, - "disable_log_anonymization": { - "name": "Desativar anonimato de log", - "description": "Desativa o anonimato dos logs" - }, - "disable_optimization": { - "name": "Desativar otimização", - "description": "Desativa a otimização de scripts. Isso pode causar problemas de desempenho." - } - } - }, - "friend_tracker": { - "name": "Rastreador de amigos", - "description": "Registra a atividade de um amigo no Snapchat", - "properties": { - "record_messaging_events": { - "name": "Gravar eventos de mensagens", - "description": "Registra eventos de mensagens, como abrir um snap, ler uma mensagem, etc." - }, - "allow_running_in_background": { - "name": "Permitir execução em segundo plano", - "description": "Permite que o rastreador seja executado em segundo plano. Nota: Isso irá descarregar significativamente sua bateria" - }, - "auto_purge": { - "name": "Purga automática", - "description": "Exclui automaticamente eventos em cache mais antigos que o período de tempo especificado" - } - } - } - }, - "options": { - "app_appearance": { - "always_light": "Sempre leve", - "always_dark": "Sempre escuro" - }, - "friend_feed_menu_buttons": { - "auto_download": "⬇️ Download automático", - "auto_save": "💬 Salvar mensagens automaticamente", - "unsaveable_messages": "⬇️ Mensagens que não podem ser salvas", - "auto_open_snaps": "📷 Snaps de abertura automática", - "stealth": "👻 Modo furtivo", - "mark_snaps_as_seen": "👀 Marcar Snaps como vistos", - "mark_stories_as_seen_locally": "👀 Marcar histórias como vistas localmente", - "conversation_info": "👤 Informações da conversa", - "e2e_encryption": "🔒 Use criptografia E2E" - }, - "path_format": { - "create_author_folder": "Crie uma pasta para cada autor", - "create_source_folder": "Crie uma pasta para cada tipo de fonte de mídia", - "append_hash": "Adicione um hash exclusivo ao nome do arquivo", - "append_source": "Adicione a fonte de mídia ao nome do arquivo", - "append_username": "Adicione o nome de usuário ao nome do arquivo", - "append_date_time": "Adicione a data e hora ao nome do arquivo" - }, - "auto_download_sources": { - "friend_snaps": "Fotos de amigos", - "friend_stories": "Histórias de amigos", - "public_stories": "Histórias Públicas", - "spotlight": "Destaque" - }, - "logging": { - "started": "Iniciado", - "success": "Sucesso", - "progress": "Progresso", - "failure": "Falha" - }, - "notifications": { - "chat_screenshot": "Captura de tela", - "chat_screen_record": "Gravação de tela", - "snap_replay": "Repetição instantânea", - "camera_roll_save": "Salvar rolo da câmera", - "chat": "Bater papo", - "chat_reply": "Resposta de bate-papo", - "snap": "Foto", - "typing": "Digitando", - "stories": "Histórias", - "speaking": "Falando", - "chat_reaction": "Reação DM", - "group_chat_reaction": "Reação do Grupo", - "initiate_audio": "Chamada de áudio recebida", - "abandon_audio": "Chamada de áudio perdida", - "initiate_video": "Chamada de vídeo recebida", - "abandon_video": "Videochamada perdida", - "map_live_location": "Mapa de localização ao vivo" - }, - "gallery_media_send_override": { - "always_ask": "Sempre pergunte", - "ORIGINAL": "Mídia Original", - "NOTE": "Nota de áudio", - "SNAP": "Foto", - "SAVEABLE_SNAP": "Snap Salvável" - }, - "strip_media_metadata": { - "hide_caption_text": "Ocultar texto da legenda", - "hide_snap_filters": "Ocultar filtros instantâneos", - "hide_extras": "Ocultar extras (por exemplo, menções)", - "remove_audio_note_duration": "Remover duração da nota de áudio", - "remove_audio_note_transcript_capability": "Remover capacidade de transcrição de notas de áudio" - }, - "hide_ui_components": { - "hide_profile_call_buttons": "Remover botões de chamada de perfil", - "hide_chat_call_buttons": "Remover botões de chamada de bate-papo", - "hide_live_location_share_button": "Remover botão de compartilhamento de localização ao vivo", - "hide_stickers_button": "Botão Remover Adesivos", - "hide_voice_record_button": "Remover botão de gravação de voz", - "hide_unread_chat_hint": "Remover dica de bate-papo não lido", - "hide_post_to_story_buttons": "Remova os botões Postar na história antes de enviar um Snap", - "hide_billboard_prompt": "Remover aviso de outdoor no feed de amigos", - "hide_snapchat_plus_gift_reminders": "Remova lembretes de presentes do Snapchat Plus em conversas", - "hide_map_reactions": "Remover reações do mapa" - }, - "hide_story_suggestions": { - "hide_suggested_friend_stories": "Ocultar histórias de amigos sugeridas", - "hide_my_stories": "Ocultar minhas histórias" - }, - "home_tab": { - "map": "Mapa", - "chat": "Bater papo", - "camera": "Câmera", - "discover": "Descobrir", - "spotlight": "Destaque" - }, - "add_friend_source_spoof": { - "added_by_username": "Por nome de usuário", - "added_by_mention": "Por Menção", - "added_by_group_chat": "Por bate-papo em grupo", - "added_by_qr_code": "Por código QR", - "added_by_community": "Por comunidade", - "added_by_quick_add": "Por Quick Add (alto risco de ser banido)" - }, - "bypass_video_length_restriction": { - "single": "Mídia única", - "split": "Dividir mídia" - }, - "old_bitmoji_selfie": { - "2d": "Bitmoji 2D", - "3d": "Bitmoji 3D" - }, - "disable_confirmation_dialogs": { - "erase_message": "Apagar mensagem", - "remove_friend": "Remover amigo", - "block_friend": "Bloquear amigo", - "ignore_friend": "Ignorar amigo", - "hide_friend": "Ocultar amigo", - "hide_conversation": "Ocultar conversa", - "clear_conversation": "Limpar conversa do feed de amigos" - }, - "auto_reload": { - "snapchat_only": "Apenas Snapchat", - "all": "Todos (Snapchat + PurrfectSnap)" - }, - "edit_text_override": { - "multi_line_chat_input": "Entrada de bate-papo multilinha", - "bypass_text_input_limit": "Ignorar limite de entrada de texto" - }, - "auto_purge": { - "never": "Nunca", - "1_hour": "1 hora", - "3_hours": "3 horas", - "6_hours": "6 horas", - "12_hours": "12 horas", - "1_day": "1 dia", - "3_days": "3 dias", - "1_week": "1 semana", - "2_weeks": "2 semanas", - "1_month": "1 mês", - "3_months": "3 meses", - "6_months": "6 meses" - }, - "disable_story_sections": { - "friends": "Amigos", - "suggested_stories": "Histórias sugeridas", - "following": "Seguindo", - "discover": "Descobrir" - }, - "disable_cameras": { - "front": "Câmera frontal", - "back": "Câmera traseira" - }, - "disable_permission_requests": { - "notifications": "Notificações", - "read_media_images": "Leia imagens de mídia", - "read_media_video": "Leia o vídeo da mídia", - "camera": "Câmera", - "microphone": "Microfone", - "location": "Localização", - "read_contacts": "Ler contatos", - "nearby_devices": "Dispositivos próximos", - "phone_calls": "Chamadas telefônicas" - }, - "message_indicators": { - "encryption_indicator": "Adiciona um ícone 🔒 ao lado das mensagens que foram enviadas apenas para você", - "platform_indicator": "Adiciona o ícone da plataforma da qual a mídia foi enviada (por exemplo, Android, iOS, Web)", - "location_indicator": "Adiciona um ícone 📍 aos instantâneos quando eles são enviados com localização ativada", - "ovf_editor_indicator": "Indica se um snap foi enviado usando o Editor OVF", - "director_mode_indicator": "Adiciona um ícone ✏️ aos instantâneos quando eles são enviados usando o Modo Diretor, que pode ser usado para enviar imagens da galeria como instantâneos" - }, - "auto_mark_as_read": { - "conversation_read": "Marcar conversa como lida ao enviar uma mensagem", - "snap_reply": "Marcar os snaps como lidos ao respondê-los", - "save_snap_in_chat": "Marcar snaps como lidos ao salvá-los no bate-papo no modo furtivo" - }, - "friend_mutation_notifier": { - "remove_friend": "Notificar quando alguém remover você como amigo", - "birthday_changes": "Notificar quando alguém mudar de aniversário", - "bitmoji_selfie_changes": "Notificar quando alguém alterar sua selfie Bitmoji", - "bitmoji_avatar_changes": "Notificar quando alguém alterar seu avatar Bitmoji", - "bitmoji_background_changes": "Notificar quando alguém alterar o plano de fundo do Bitmoji", - "bitmoji_scene_changes": "Notificar quando alguém mudar sua cena de Bitmoji" - }, - "snapchat_plus": { - "not_subscribed": "Não inscrito", - "basic": "Básico", - "ad_free": "Anúncio grátis" - }, - "double_tap_chat_action": { - "like_message": "Curtir mensagem", - "copy_text": "Copiar texto para a área de transferência", - "delete_message": "Excluir mensagem", - "mark_as_read": "Marcar como lido", - "custom_emoji_reaction": "Reação de Emoji Personalizado" - }, - "startup_default_camera": { - "front": "Câmera frontal", - "back": "Câmera traseira" - } - } - }, - "friend_menu_option": { - "mark_snaps_as_seen": "Marcar Snaps como vistos", - "mark_stories_as_seen_locally": "Marcar histórias como vistas localmente", - "preview": "Visualização", - "stealth_mode": "Modo furtivo", - "auto_download_blacklist": "Lista negra de download automático", - "anti_auto_save": "Anti-salvamento automático" - }, - "content_type": { - "CHAT": "Bater papo", - "SNAP": "Foto", - "EXTERNAL_MEDIA": "Mídia Externa", - "NOTE": "Nota de áudio", - "STICKER": "Adesivo", - "SHARE": "Compartilhar", - "STATUS": "Status", - "LOCATION": "Localização", - "STATUS_SAVE_TO_CAMERA_ROLL": "Salvo no rolo da câmera", - "STATUS_CONVERSATION_CAPTURE_SCREENSHOT": "Captura de tela", - "STATUS_CONVERSATION_CAPTURE_RECORD": "Gravação de tela", - "STATUS_CALL_MISSED_VIDEO": "Videochamada perdida", - "STATUS_CALL_MISSED_AUDIO": "Chamada de áudio perdida", - "LIVE_LOCATION_SHARE": "Compartilhamento de localização ao vivo", - "CREATIVE_TOOL_ITEM": "Item de ferramenta criativa", - "FAMILY_CENTER_INVITE": "Convite para Centro Familiar", - "FAMILY_CENTER_ACCEPT": "Centro Familiar Aceitar", - "FAMILY_CENTER_LEAVE": "Licença do Centro Familiar", - "STATUS_PLUS_GIFT": "Presente Status Plus", - "TINY_SNAP": "Pequeno estalo", - "STATUS_COUNTDOWN": "Contagem regressiva", - "MAP_REACTION": "Reação do mapa" - }, - "media_download_source": { - "none": "Nenhum", - "pending": "Pendente", - "chat_media": "Mídia de bate-papo", - "story": "História", - "public_story": "História Pública", - "spotlight": "Destaque", - "profile_picture": "Foto do perfil", - "story_logger": "Registrador de histórias", - "message_logger": "Registrador de mensagens", - "merged": "Mesclado", - "voice_call": "Chamada de voz" - }, "chat_action_menu": { - "preview_button": "Visualização", - "download_button": "Download", - "delete_logged_message_button": "Excluir mensagem registrada", - "show_chat_edit_history": "Mostrar histórico de edições do bate-papo", - "convert_message": "Converter mensagem" - }, - "opera_context_menu": { - "download": "Baixar mídia", - "sent_at": "Enviado em {date}", - "created_at": "Criado em {date}", - "expires_at": "Expira em {date}", - "media_size": "Tamanho da mídia: {size}", - "media_duration": "Duração da mídia: {duration} ms", - "show_debug_info": "Mostrar informações de depuração" + "preview_button": "Pré-visualização", + "download_button": "Descarregar" }, "modal_option": { - "profile_info": "Informações do perfil", + "profile_info": "Informações do Perfil", "close": "Fechar" }, - "gallery_media_send_override": { - "multiple_media_toast": "Você só pode enviar uma mídia por vez" - }, - "mark_as_seen": { - "no_unseen_snaps_toast": "Nenhum Snap invisível encontrado!", - "seen_toast": "Marcado como visto!", - "unseen_toast": "Marcado como invisível!", - "already_seen_toast": "Já marcado como visto!", - "already_unseen_toast": "Já marcado como invisível!" - }, "conversation_preview": { "streak_expiration": "expira em {day} dias {hour} horas {minute} minutos", - "total_messages": "Total de mensagens enviadas/recebidas: {count}", - "title": "Visualização", - "unknown_user": "Usuário desconhecido", - "no_messages": "Nenhuma mensagem encontrada!" + "title": "Pré-visualização", + "unknown_user": "Usuário Desconhecido" }, "profile_info": { - "title": "Informações do perfil", - "first_created_username": "Primeiro nome de usuário criado", - "mutable_username": "Nome de usuário mutável", - "display_name": "Nome de exibição", - "added_date": "Data adicionada", - "birthday": "Aniversário: {month} {day}", - "hidden_birthday": "Aniversário: Oculto", - "friendship": "Amizade", - "add_source": "Adicionar fonte", - "snapchat_plus": "Snapchat Plus", - "snapchat_plus_state": { - "subscribed": "Inscrito", - "not_subscribed": "Não inscrito" - } - }, - "friendship_link_type": { - "mutual": "Mútuo", - "outgoing": "Extrovertido", - "blocked": "Bloqueado", - "deleted": "Excluído", - "following": "Seguindo", - "suggested": "Sugerido", - "incoming": "Entrada", - "incoming_follower": "Seguidor de entrada" - }, - "bulk_messaging_action": { - "choose_action_title": "Escolha uma ação", - "progress_status": "Processando {index} de {total}", - "selection_dialog_continue_button": "Continuar", - "confirmation_dialog": { - "title": "Tem certeza?", - "message": "Isso afetará todos os amigos selecionados. Esta ação não pode ser desfeita." - }, - "actions": { - "remove_friends": "Remover amigos", - "clear_conversations": "Limpar conversas" - } + "title": "Informações do Perfil", + "display_name": "Nome de Exibição", + "birthday": "Aniversário: {month} {day}" }, "chat_export": { - "exporter_dialog": { - "select_conversations_title": "Selecione Conversas", - "text_field_selection": "{amount} selecionado", - "text_field_selection_all": "Todos", - "export_file_format_title": "Exportar formato de arquivo", - "message_type_filter_title": "Filtrar mensagens por tipo", - "amount_of_messages_title": "Quantidade de Mensagens (deixe em branco para todas)", - "download_medias_title": "Baixar mídias" - }, "dialog_negative_button": "Cancelar", "dialog_positive_button": "Exportar", "exported_to": "Exportado para {path}", - "exporting_chats": "Exportando bate-papos...", - "processing_chats": "Processando {amount} conversas...", + "exporting_chats": "A Exportar Conversas...", + "processing_chats": "A Processar {amount} conversas...", "export_fail": "Falha ao exportar a conversa {conversation}", - "writing_output": "Escrevendo saída...", - "finished": "Feito! Agora você pode fechar esta caixa de diálogo.", - "no_messages_found": "Nenhuma mensagem encontrada!", - "exporting_message": "Exportando {conversation}..." + "finished": "Pronto! Já pode fechar este diálogo.", + "no_messages_found": "Nenhuma mensagem foi encontrada!", + "exporting_message": "A Exportar {conversation}..." }, "button": { - "ok": "OK", + "ok": "Aceitar", "positive": "Sim", "negative": "Não", "cancel": "Cancelar", - "open": "Abrir", - "download": "Download", - "send": "Enviar", - "restore_original": "Restaurar Original", - "convert_external_media": "Converter mídia externa", - "save": "Salvar" + "open": "Abrir" }, - "tracker_events": { - "conversation_enter": "Entrar na conversa", - "conversation_exit": "Saída de conversa", - "started_typing": "Comecei a digitar", - "stopped_typing": "Parou de digitar", - "started_speaking": "Comecei a falar", - "stopped_speaking": "Parou de falar", - "started_peeking": "Comecei a espiar", - "stopped_peeking": "Parou de espiar", - "message_read": "Mensagem lida", - "message_deleted": "Mensagem excluída", - "message_saved": "Mensagem salva", - "message_unsaved": "Mensagem não salva", - "message_edited": "Mensagem editada", - "message_reaction_add": "Adicionar reação à mensagem", - "message_reaction_remove": "Reação de mensagem removida", - "snap_opened": "Snap aberto", - "snap_replayed": "Snap repetido", - "snap_replayed_twice": "Snap repetido duas vezes", - "snap_screenshot": "Captura de tela instantânea", - "snap_screen_record": "Registro instantâneo de tela" - }, - "tracker_actions": { - "log": "Registro", - "in_app_notification": "Notificação no aplicativo", - "push_notification": "Notificação push", - "custom": "Personalizado" - }, - "better_notifications": { - "button": { - "reply": "Responder", - "download": "Download", - "mark_as_read": "Marcar como lido" + "setup": { + "dialogs": { + "select_save_folder_button": "Selecione a pasta", + "select_language": "Selecione o idioma", + "save_folder": "SnapEnhance requer permissões de armazenamento para baixar e salvar mídia do Snapchat.\nEscolha o local para onde a mídia deve ser baixada." + }, + "mappings": { + "dialog": "Para suportar dinamicamente uma ampla variedade de versões do Snapchat, os mapeamentos são necessários para que o SnapEnhance funcione corretamente. Isso não deve levar mais de 5 segundos.", + "generate_failure_no_snapchat": "O SnapEnhance não conseguiu detectar o Snapchat. Tente reinstalar o Snapchat." } - }, - "profile_picture_downloader": { - "button": "Baixar foto do perfil", - "title": "Downloader de imagem de perfil", - "avatar_option": "avatar", - "background_option": "Fundo" - }, - "call_start_confirmation": { - "dialog_title": "Iniciar chamada", - "dialog_message": "Tem certeza de que deseja iniciar uma chamada?" - }, - "half_swipe_notifier": { - "notification_channel_name": "Meio golpe", - "notification_content_dm": "{friend} apenas deslizou até a metade no seu bate-papo por {duration} segundos", - "notification_content_group": "{friend} apenas deslizou até a metade em {group} por {duration} segundos" - }, - "download_processor": { - "attachment_type": { - "snap": "Foto", - "sticker": "Adesivo", - "gif": "GIFs", - "external_media": "Mídia Externa", - "note": "Observação", - "original_story": "História original" - }, - "select_attachments_title": "Selecione anexos", - "download_started_toast": "Download iniciado", - "unsupported_content_type_toast": "Tipo de conteúdo não suportado!", - "failed_no_longer_available_toast": "A mídia não está mais disponível", - "no_attachments_toast": "Nenhum anexo encontrado!", - "already_queued_toast": "Mídia já na fila!", - "already_downloaded_toast": "Mídia já baixada!", - "content_saved_toast": "Salvo!", - "download_toast": "Baixando {path}...", - "processing_toast": "Processando {path}...", - "failed_generic_toast": "Falha ao baixar", - "failed_to_create_preview_toast": "Falha ao criar visualização", - "failed_processing_toast": "Falha no processamento {error}", - "failed_gallery_toast": "Falha ao salvar na galeria {error}", - "dash_no_chapter": "Nenhum capítulo encontrado", - "dash_dialog": { - "title": "Baixar mídia do painel", - "download_all": "Baixar tudo", - "segment_text": "Segmento {from} - {to}" - } - }, - "streaks_reminder": { - "notification_title": "Ondas", - "notification_text": "Você perderá sua sequência com {friend} em {hoursLeft} horas" - }, - "biometric_auth": { - "unlock_button": "Desbloquear", - "title": "Desbloquear Snapchat", - "subtitle": "Autentique-se para desbloquear o Snapchat" - }, - "end_to_end_encryption": { - "toolbox": { - "no_shared_key": "Você ainda não tem um segredo compartilhado com este amigo. Clique abaixo para iniciar um novo.", - "shared_key_fingerprint": "Sua impressão digital é:\n\n__espaço reservado_0__\n\nCertifique-se de verificar se corresponde à impressão digital do seu amigo!", - "initiate_exchange_button": "Iniciar troca de chaves" - }, - "confirmation_dialogs": { - "title": "Criptografia ponta a ponta", - "confirmation_1": "AVISO: Isso substituirá sua chave existente. Você perderá o acesso a todas as mensagens criptografadas deste amigo. Tem certeza de que deseja continuar?", - "confirmation_2": "Você tem REALMENTE certeza de que deseja continuar? Esta é sua última chance de desistir." - }, - "unencrypted_conversation_send_failure_toast": "Você não pode enviar conteúdo criptografado para conversas criptografadas e não criptografadas!", - "native_hooks_send_failure_toast": "Falha ao enviar! Por favor, habilite Native Hooks nas configurações.", - "no_participants_to_encrypt_toast": "Você não tem nenhum amigo nesta conversa com quem criptografar mensagens!", - "encryption_failed_toast": "Falha ao criptografar a mensagem! Verifique o logcat para mais detalhes.", - "accept_public_key_success_toast": "Chave pública aceita com sucesso!", - "accept_secret_key_success_toast": "Feito! Agora você pode enviar e receber mensagens criptografadas com este amigo.", - "accept_public_key_failure_toast": "Falha ao aceitar a chave pública", - "accept_secret_key_failure_toast": "Falha ao aceitar a chave secreta", - "accept_secret_button": "Aceitar segredo", - "accept_public_key_button": "Aceitar chave pública", - "outgoing_pk_message": "Solicitação de troca de chaves", - "outgoing_secret_message": "Resposta de troca de chave", - "incoming_pk_message": "Você acabou de receber uma solicitação de chave pública. Clique abaixo para aceitá-lo.", - "incoming_secret_message": "Seu amigo acabou de aceitar sua chave pública. Clique abaixo para aceitar o segredo." - }, - "auto_open_snaps": { - "title": "Snaps de abertura automática", - "notification_content": "{count} Snaps abertos" - }, - "friend_mutation_observer": { - "notification_channel_name": "Observador de Mutação de Amigo", - "friend_removed": "{username} removeu você como amigo", - "birthday_removed": "{username} removeu a data de nascimento ({birthday})", - "birthday_added": "{username} adicionou seu aniversário ({birthday})", - "birthday_changed": "{username} mudou sua data de nascimento de {oldBirthday} para {newBirthday}", - "bitmoji_selfie_changed": "{username} mudou sua selfie Bitmoji", - "bitmoji_avatar_changed": "{username} mudou seu avatar Bitmoji", - "bitmoji_background_changed": "{username} mudou o plano de fundo do Bitmoji", - "bitmoji_scene_changed": "{username} mudou sua cena Bitmoji" - }, - "material3_strings": { - "date_range_picker_start_headline": "De", - "date_range_picker_end_headline": "Para", - "date_range_picker_title": "Selecione o período", - "date_picker_switch_to_calendar_mode": "Calendário", - "date_picker_switch_to_input_mode": "Entrada", - "date_range_picker_scroll_to_previous_month": "Mês anterior", - "date_range_picker_scroll_to_next_month": "Próximo mês", - "date_picker_today_description": "Hoje", - "date_range_picker_day_in_range": "Selecionado", - "date_input_invalid_for_pattern": "Data inválida", - "date_input_invalid_year_range": "Ano inválido", - "date_input_invalid_not_allowed": "Data inválida", - "date_range_input_invalid_range_input": "Período inválido" - }, - "send_override_dialog": { - "title": "Enviar mídia como {type}", - "duration": "Duração: {duration}", - "saveable_snap_hint": "Torne o Snap salvável no chat", - "unlimited_duration": "Ilimitado" - }, - "invalid_input_toast": "Entrada inválida! Certifique-se de inserir um valor válido." -} \ No newline at end of file + } +} diff --git a/common/src/main/assets/lang/ro.json b/common/src/main/assets/lang/ro.json index 166cc737..d68241e3 100644 --- a/common/src/main/assets/lang/ro.json +++ b/common/src/main/assets/lang/ro.json @@ -1,2022 +1,1349 @@ { - "setup": { - "dialogs": { - "select_language": "Selectați limba", - "save_folder": "PurrfectsNap necesită permisiuni de stocare pentru a descărca și salva suportul de la Snapchat.\nVă rugăm să alegeți locația în care trebuie descărcată media.", - "select_save_folder_button": "Selectați folder" + "friend_menu_option": { + "preview": "Previzualizare", + "stealth_mode": "Modul Mascare", + "anti_auto_save": "Anti Salvare Automată", + "auto_download_blacklist": "Descărcare automată Lista neagră", + "mark_snaps_as_seen": "Marchează Snap-urile ca fiind văzute", + "mark_stories_as_seen_locally": "Marcați poveștile așa cum sunt văzute la nivel local" + }, + "modal_option": { + "profile_info": "Informații Profil", + "close": "Închide" + }, + "gallery_media_send_override": { + "multiple_media_toast": "Puteți trimite un singur fișier media la un moment dat" + }, + "conversation_preview": { + "streak_expiration": "expiră în {day} zile {hour} ore {minute} minute", + "total_messages": "Total mesaje trimise/primite: {count}", + "title": "Previzualizare", + "unknown_user": "Utilizator Necunoscut" + }, + "profile_info": { + "display_name": "Nume afișat", + "friendship": "Prietenie", + "title": "Informații profil", + "first_created_username": "Primul nume de utilizator creat", + "mutable_username": "Nume de utilizator modificabil", + "snapchat_plus_state": { + "not_subscribed": "Neabonat", + "subscribed": "Abonat" }, + "added_date": "Data adăugată", + "birthday": "Zi de naștere: {month} {day}", + "hidden_birthday": "Zi de naștere: Ascuns", + "add_source": "Sursa adăugării", + "snapchat_plus": "Snapchat Plus" + }, + "chat_export": { + "dialog_negative_button": "Anulare", + "exported_to": "Exportat către {path}", + "exporting_chats": "Se exportă conversațiile...", + "processing_chats": "Se procesează {amount} de conversații...", + "export_fail": "Nu s-a putut exporta conversația {conversation}", + "writing_output": "Se scrie rezultatul...", + "finished": "Gata! Acum puteți să închideți acest dialog.", + "no_messages_found": "Niciun mesaj găsit!", + "exporting_message": "Se exportă {conversation}...", + "exporter_dialog": { + "text_field_selection": "{cantitatea} selectată", + "select_conversations_title": "Selectați Conversațiile", + "text_field_selection_all": "Toate", + "export_file_format_title": "Formatul fișierului de export", + "message_type_filter_title": "Filtrați mesajele după tip", + "amount_of_messages_title": "Cantitatea de mesaje (lăsați necompletat pentru toate)", + "download_medias_title": "Descărcare fișierele Media" + }, + "dialog_positive_button": "Exportă" + }, + "button": { + "ok": "OK", + "positive": "Da", + "negative": "Nu", + "cancel": "Anulare", + "open": "Deschide", + "download": "Descarcă" + }, + "download_processor": { + "download_started_toast": "Descărcarea a început", + "unsupported_content_type_toast": "Tip de conținut nesuportat!", + "failed_no_longer_available_toast": "Media nu mai e valabilă", + "already_queued_toast": "Media este deja în așteptare!", + "already_downloaded_toast": "Media deja descărcată!", + "download_toast": "Se descarcă {path}...", + "processing_toast": "Se procesează {path}...", + "failed_generic_toast": "Descărcarea a eșuat", + "failed_to_create_preview_toast": "Nu a reușit să se creeze previzualizarea", + "attachment_type": { + "external_media": "Media extern", + "note": "Notă", + "original_story": "Povestea originală", + "sticker": "Autocolant", + "snap": "Snap" + }, + "select_attachments_title": "Selectați atașamentele de descărcat", + "failed_gallery_toast": "Nu s-a salvat în galerie {error}", + "dash_dialog": { + "title": "Descărcare media dash", + "segment_text": "Segmentul {from} - {to}", + "download_all": "Descarcă toate" + }, + "no_attachments_toast": "Nu s-au găsit atașamente!", + "failed_processing_toast": "Procesarea eșuată {error}", + "dash_no_chapter": "Nu a fost găsit niciun capitol" + }, + "setup": { "mappings": { - "dialog": "Generarea mapării, acest lucru poate dura ceva timp ...", - "generate_failure_no_snapchat": "Purrfectsnap nu a putut detecta Snapchat, vă rugăm să încercați să reinstalați Snapchat.", - "generate_failure": "A apărut o eroare în timpul încercării de a genera mapări, vă rugăm să încercați din nou." + "generate_failure_no_snapchat": "SnapEnhance nu a putut detecta Snapchat, încercați să reinstalați Snapchat.", + "dialog": "Pentru a suporta dinamic o mai multe versiuni de Snapchat, mapările sunt necesare pentru SnapEnhance pentru a funcționa corect, nu ar trebui să dureze mai mult de 5 secunde.", + "generate_failure": "A apărut o eroare în timpul generării mapărilor, te rog încearcă din nou." }, "permissions": { - "dialog": "Pentru a continua, trebuie să vă potriviți următoarele cerințe:", - "notification_access": "Acces la notificare", - "battery_optimization": "Optimizarea bateriei", - "display_over_other_apps": "Afișați alte aplicații", + "dialog": "Pentru a continua trebuie să îndeplinești următoarele condiții:", + "notification_access": "Acces Notificări", + "battery_optimization": "Optimizare Baterie", + "display_over_other_apps": "Afișează Peste Alte Aplicații", "request_button": "Cerere" + }, + "dialogs": { + "select_language": "Selectează Limba", + "save_folder": "SnapEnhance necesită acces la Stocare pentru a descărca si salva media din Snapchat.\nTe rog selectează locația unde ar trebui să fie descărcate.", + "select_save_folder_button": "Alege Dosarul" } }, - "scopes": { - "friend": "Prieten", - "group": "Grup" - }, "manager": { "routes": { + "home": "Acasă", + "logger_history": "Istoric Log-uri", + "scripts": "Șcenarii", + "home_settings": "Setări", "tasks": "Sarcini", "features": "Caracteristici", - "manage_rule_feature": "Gestionați funcția de regulă", - "home": "Acasă", - "home_settings": "Setări", - "home_logs": "Jurnale", - "logger_history": "Istoricul loggerului", - "logged_stories": "Povești înregistrate", - "friend_tracker": "Prieten tracker", - "edit_rule": "Regula de editare", - "file_imports": "Importuri de fișiere", - "manage_repos": "Gestionați depozitele", + "home_logs": "Log-uri", "social": "Social", - "manage_scope": "Gestionează domeniul de aplicare", - "messaging_preview": "Previzualizare", - "scripts": "Scripturi", - "better_location": "Locație mai bună" + "manage_scope": "Gestionează Scopul", + "messaging_preview": "Previzualizează", + "logged_stories": "Povești înregistrate" }, "sections": { - "home": { - "version_title": "v{versionName} · furcat de Eternal", - "update_title": "Actualizare PurrfectSnap", - "update_content": "Versiunea {version} este disponibilă!", - "update_button": "Descarca", - "debug_build_summary_title": "Rulați o versiune de depanare a PurrfectSnap", - "debug_build_summary_content": "Versiunea {versionName} ({versionCode})", - "debug_build_summary_date": "Data compilării: {date} (acum {days} zile)", - "quick_actions_title": "Acțiuni rapide", - "download_icon_description": "Descarca", - "completed_icon_description": "Finalizat", - "failed_icon_description": "A eșuat", - "manage_quick_actions_description": "Gestionați acțiunile rapide", - "quick_actions_icon_description": "Acțiuni rapide", - "add_quick_action_description": "Adăugați o acțiune rapidă" - }, - "home_logs": { - "no_logs_hint": "Nu sunt disponibile jurnale", - "clear_logs_button": "Șterge jurnalele", - "export_logs_button": "Exportă jurnalele", - "saving_logs_toast": "Se salvează jurnalele, acest lucru poate dura ceva timp...", - "saved_logs_success_toast": "Jurnalele au fost salvate cu succes", - "saved_logs_failure_toast": "Salvarea jurnalelor a eșuat" - }, - "home_settings": { - "actions_title": "Acțiuni", - "message_logger_title": "Jurnal de mesaje", - "debug_title": "Depanare", - "success_toast": "Terminat!", - "message_logger_summary": "{messageCount} mesaje\n{storyCount} povești", - "export_button": "Exportă", - "clear_button": "Șterge", - "view_logger_history_button": "Vezi istoricul jurnalului", - "updates_title": "Actualizări", - "auto_update_check": "Verifică automat actualizările", - "update_check_frequency": "Frecvența verificării actualizărilor", - "update_check_frequency_daily": "Zilnic", - "update_check_frequency_weekly": "Săptămânal", - "update_check_frequency_monthly": "Lunar", - "theme_icon_description": "Temă", - "app_theme_title": "Tema aplicației", - "theme_mode_system": "Sistem", - "theme_mode_light": "Luminos", - "theme_mode_dark": "Întunecat", - "ui_settings_title": "Setări UI", - "haptic_feedback_label": "Feedback haptic", - "test_mode_label": "Mod de testare (DOAR PENTRU DEPANARE)", - "disable_feature_loading_label": "Dezactivează încărcarea funcțiilor", - "disable_auto_mapper_label": "Dezactivează maparea automată", - "disable_bypass_indicator_label": "Dezactivează indicatorul de stare a bypass-ului", - "update_notification_channel_name": "Actualizări PurrfectSnap", - "update_notification_channel_description": "Notificări pentru actualizările PurrfectSnap", - "update_notification_title": "Actualizare PurrfectSnap disponibilă", - "update_notification_text": "Versiunea {version} este acum disponibilă.", - "export_database_failed_toast": "Exportul bazei de date a eșuat! {message}", - "clear_messages_failed_toast": "Ștergerea mesajelor a eșuat! {message}", - "clear_file_failed_toast": "Ștergerea fișierului a eșuat! {message}", - "debug_file_config": "Configurație", - "debug_file_mappings": "Mapări", - "debug_file_message_logger": "Jurnal de mesaje", - "debug_file_pinned_best_friend": "Cel mai bun prieten fixat", - "debug_file_native_sig_cache": "Cache de semnături native" + "social": { + "streaks_expiration_short": "{hours}h", + "friends_tab": "Prieteni", + "groups_tab": "Grupuri", + "empty_hint": "(gol)" }, "tasks": { - "no_tasks": "Nicio sarcină", - "merge_button": "Îmbină", - "failed_to_open_file": "Deschiderea fișierului a eșuat", - "merge_files_toast": "Se îmbină {count} fișiere", - "remove_selected_tasks_title": "Sigur doriți să eliminați sarcinile selectate?", - "remove_all_tasks_title": "Sigur doriți să eliminați toate sarcinile?", - "delete_files_option": "Ștergeți și fișierele", + "no_tasks": "Fără actiuni", + "merge_files_toast": "Îmbinând {count} fișiere", + "remove_selected_tasks_title": "Ești sigur că vrei sa ștergi actiunile selectate?", + "delete_files_option": "De asemenea șterge fișierele", "remove_selected_tasks_confirm": "Eliminați {count} sarcini?", "remove_all_tasks_confirm": "Eliminați toate sarcinile?", - "clear_tasks_description": "Șterge sarcinile", - "file_not_found_icon_description": "Fișierul nu a fost găsit", - "image_icon_description": "Imagine", - "video_icon_description": "Video", - "audio_icon_description": "Audio", - "file_icon_description": "Fișier", - "download_icon_description": "Descarcă", - "chat_action_icon_description": "Acțiune de chat", - "cancel_icon_description": "Anulează", - "success_icon_description": "Succes", - "failure_icon_description": "Eșec", - "cancelled_icon_description": "Anulat", - "task_status_failure": "Eșec", - "task_status_cancelled": "Anulat" + "remove_all_tasks_title": "Sigur doriți să eliminați toate sarcinile?" }, "features": { "disabled": "Dezactivat", + "config_import_success_toast": "Configurația a fost importată cu succes", "export_option": "Exportă", "import_option": "Importă", "reset_option": "Resetează", "config_export_success_toast": "Configurația a fost exportată cu succes", - "config_import_success_toast": "Configurația a fost importată cu succes", - "config_import_failure_toast": "Importul configurației a eșuat: {error}", - "config_export_failure_toast": "Exportul configurației a eșuat: {error}", - "saved_config_snackbar": "Configurație salvată", - "older_required": "Această funcție necesită Snapchat v{version} sau o versiune mai veche pentru a funcționa corect.", - "newer_required": "Această funcție necesită Snapchat v{version} sau o versiune mai nouă pentru a funcționa corect.", - "search_button": "Caută" + "saved_config_snackbar": "Configurația a fost salvată", + "config_import_failure_toast": "Nu s-a putut importa configurația {error}" }, - "manage_rule_feature": { - "disable_state_option": "Dezactivat", - "disable_state_subtext": "Niciun prieten/grup nu va fi afectat", - "whitelist_state_option": "Nimeni în afară de...", - "whitelist_state_subtext": "Doar {count} prieteni/grupuri vor fi afectați de această regulă", - "whitelist_state_button": "Selectează prietenii/grupurile permise", - "blacklist_state_option": "Toți, cu excepția...", - "blacklist_state_subtext": "Toți, cu excepția a {count} prieteni/grupuri, vor fi afectați de această regulă", - "blacklist_state_button": "Selectează prietenii/grupurile excluse", - "clear_list_button": "Șterge lista de prieteni/grupuri", - "dialog_clear_confirmation_text": "Sigur doriți să ștergeți lista?" + "logger_history": { + "list_group_format": "Grup {name}", + "list_friend_format": "Prieten {name}", + "no_more_messages": "Nu mai sunt mesaje", + "reverse_order_checkbox": "Inversează ordinea", + "chat_attachment": "Atașament {index}", + "empty_message": "Mesaj de chat gol", + "message_parse_failed": "Nu s-a putut analiza mesajul", + "unknown_sender": "Expeditor necunoscut", + "download_attachment_failed_toast": "Atașamentul nu a putut fi descărcat" }, - "social": { - "friends_tab": "Prieteni", - "groups_tab": "Grupuri", - "empty_hint": "(gol)", - "streaks_expiration_short": "{hours}h" + "home_settings": { + "export_button": "Exportă", + "actions_title": "Acțiuni", + "debug_title": "Depanare", + "success_toast": "Gata!", + "message_logger_summary": "{messageCount} mesaje\n{storyCount} povești", + "message_logger_title": "Salvator de mesaje", + "view_logger_history_button": "Vedeți istoricul înregistratorului", + "clear_button": "Curăță" + }, + "home": { + "update_content": "Versiunea {version} este disponibilă!", + "update_button": "Descarcă", + "update_title": "Actualizare SnapEnhance" + }, + "messaging_preview": { + "bridge_init_failed": "Nu s-a inițializat puntea de mesagerie", + "bridge_connection_failed": "Nu s-a putut conecta la Snapchat prin serviciul punte", + "message_fetch_failed": "Nu s-au putut prelua mesajele", + "no_message_hint": "Niciun mesaj", + "save_selection_option": "Salvați selecția", + "save_all_option": "Salvează tot", + "unsave_selection_option": "Anulați salvarea selecției", + "unsave_all_option": "Anulați salvarea tuturor", + "mark_selection_as_seen_option": "Marcați Snapul selectat ca văzut", + "mark_all_as_seen_option": "Marcați ca văzut toate Snapurile", + "delete_all_option": "Sterge tot", + "delete_selection_option": "Șterge selecția" + }, + "home_logs": { + "no_logs_hint": "Nu există jurnalele disponibile", + "clear_logs_button": "Ștergeți jurnalele", + "export_logs_button": "Exportă jurnalele", + "saving_logs_toast": "Se salvează jurnalele, poate dura ceva timp...", + "saved_logs_failure_toast": "Salvarea jurnalelor a eșuat", + "saved_logs_success_toast": "Jurnalele au fost salvate cu succes" }, "manage_scope": { - "logged_stories_button": "Afișează poveștile înregistrate", "e2ee_title": "Criptare end-to-end", "rules_title": "Reguli", "participants_text": "{count} participanți", "not_found": "Nu a fost găsit", - "streaks_title": "Serii", + "streaks_title": "Linii", "streaks_length_text": "Lungime: {length}", + "logged_stories_button": "Afișați poveștile înregistrate", "streaks_expiration_text": "Expiră în {eta}", "streaks_expiration_text_expired": "Expirat", - "reminder_button": "Setează memento", - "delete_scope_confirm_dialog_title": "Sigur doriți să ștergeți {scope}?", - "notes_placeholder": "Faceți clic pentru a adăuga o notă", - "invalid_key_size_32_bytes": "Dimensiune cheie nevalidă (trebuie să fie de 32 de octeți)", - "successfully_imported_key": "Cheia a fost importată cu succes", - "failed_to_import_key": "Importul cheii a eșuat: {message}", - "export_base64_button": "Exportă Base64", - "import_base64_button": "Importă Base64" + "reminder_button": "Setați memento", + "delete_scope_confirm_dialog_title": "Sigur doriți să ștergeți un {scope}?" }, "logged_stories": { "story_failed_to_load": "Încărcarea a eșuat", "no_stories": "Nu s-au găsit povești", - "save_from_cache_button": "Salvează din cache", - "downloaded_to_path": "Descărcat la {path}", - "download_failed": "Descărcarea a eșuat: {message}", - "posted_at": "Postat la {date}", - "created_at": "Creat la {date}", - "failed_to_open_file": "Deschiderea fișierului a eșuat. Verificați jurnalele pentru mai multe informații", - "failed_to_get_file": "Preluarea fișierului a eșuat" - }, - "messaging_preview": { - "processed_messages_toast": "{count} mesaje procesate", - "processed_messages_text": "{count} mesaje procesate", - "close_button_description": "Închide", - "bridge_connection_failed": "Conectarea la punte a eșuat. Asigurați-vă că Snapchat rulează în fundal", - "bridge_init_failed": "Inițializarea punții de mesagerie a eșuat. Asigurați-vă că Snapchat rulează în fundal", - "message_fetch_failed": "Preluarea mesajelor a eșuat", - "no_message_hint": "Niciun mesaj", - "save_selection_option": "Salvează selecția", - "save_all_option": "Salvează tot", - "unsave_selection_option": "Anulează salvarea selecției", - "unsave_all_option": "Anulează salvarea tuturor", - "mark_selection_as_seen_option": "Marchează Snap-ul selectat ca văzut", - "mark_all_as_seen_option": "Marchează toate Snap-urile ca văzute", - "delete_selection_option": "Șterge selecția", - "delete_all_option": "Șterge tot" - }, - "logger_history": { - "download_started_toast": "Descărcarea a început!", - "download_success_toast": "Descărcat la {path}", - "download_failed_toast": "Descărcarea {message} a eșuat", - "edited_at_text": "{message} (editat la {date})", - "download_button": "Descarcă", - "select_conversation_placeholder": "Selectează o conversație", - "close_button_description": "Închide", - "search_button_description": "Caută", - "list_friend_format": "Prieten {name}", - "list_group_format": "Grup {name}", - "no_more_messages": "Nu mai sunt mesaje", - "reverse_order_checkbox": "Ordine inversă", - "chat_attachment": "Atașament {index}", - "empty_message": "Mesaj de chat gol", - "message_parse_failed": "Analiza mesajului a eșuat", - "unknown_sender": "Expeditor necunoscut", - "download_attachment_failed_toast": "Descărcarea atașamentului a eșuat", - "log_header_format": "{username} ({type}) - {date}" - }, - "file_imports": { - "import_file_button": "Importă fișier", - "file_not_found": "Fișierul nu a fost găsit", - "file_import_failed": "Importul fișierului a eșuat: {error}", - "file_imported": "Fișierul a fost importat cu succes", - "file_delete_failed": "Ștergerea fișierului a eșuat", - "no_files_hint": "Aici puteți importa fișiere pentru a le utiliza în Snapchat. Apăsați butonul de mai jos pentru a importa un fișier." - }, - "better_location": { - "spoofed_coordinates_title": "Lat {latitude}, Lng {longitude}", - "save_coordinates_dialog_title": "Salvează coordonatele", - "saved_name_dialog_hint": "Nume salvat", - "latitude_dialog_hint": "Latitudine", - "longitude_dialog_hint": "Longitudine", - "save_dialog_button": "Salvează", - "choose_location_button": "Alege locația", - "teleport_to_friend_button": "Teleportează-te la un prieten", - "spoof_location_toggle": "Falsifică locația", - "suspend_location_updates": "Suspendă actualizările de locație", - "saved_coordinates_title": "Coordonate salvate", - "no_saved_coordinates_hint": "Nicio coordonată salvată", - "delete_dialog_title": "Șterge coordonatele salvate", - "delete_dialog_message": "Sigur doriți să ștergeți aceste coordonate salvate?", - "teleport_to_friend_title": "Teleportează-te la un prieten", - "search_bar": "Caută", - "no_friends_map": "Niciun prieten pe hartă", - "no_friends_found": "Nu s-au găsit prieteni", - "edit_location_button_description": "Editează locația", - "add_icon_description": "Adaugă", - "edit_icon_description": "Editează", - "delete_icon_description": "Șterge" + "save_from_cache_button": "Salvați din Cache(memoria temporară)" } }, "dialogs": { + "scripting_warning": { + "title": "Atenție", + "content": "SnapEnhance include un instrument de scriere, care permite executarea codului definit de utilizator pe dispozitivul dumneavoastră. Fiți extrem de precauți și instalați numai module din surse cunoscute și de încredere. Modulele neautorizate sau neverificate pot prezenta riscuri de securitate pentru sistemul dumneavoastră." + }, "add_friend": { - "title": "Adaugă un prieten sau un grup", + "title": "Adaugă un Prieten sau un Grup", "search_hint": "Caută", "fetch_error": "Preluarea datelor a eșuat", "category_groups": "Grupuri", - "category_friends": "Prieteni", - "participants_text": "{count} participanți", - "search_icon_description": "Caută" - }, - "scripting_warning": { - "title": "Avertisment", - "content": "PurrfectSnap include un instrument de scriptare, permițând executarea codului definit de utilizator pe dispozitivul dvs. Fiți extrem de precaut și instalați module doar din surse cunoscute și de încredere. Modulele neautorizate sau neverificate pot prezenta riscuri de securitate pentru sistemul dvs." + "category_friends": "Prieteni" }, "reset_config": { - "title": "Resetează configurația", - "content": "Sigur doriți să resetați configurația?", - "success_toast": "Configurația a fost resetată cu succes" - }, - "export_config": { - "title": "Exportați date sensibile?", - "content": "Doriți să exportați configurația cu date sensibile? (cum ar fi coordonatele de locație etc.)" + "title": "Resetare configurări", + "success_toast": "Resetarea configurării cu succes", + "content": "Sigur doriți să resetați configurația?" }, "messaging_action": { "title": "Alegeți tipurile de conținut de procesat", "select_all_button": "Selectează tot" - }, - "file_imports": { - "no_files_settings_hint": "Nu s-au găsit fișiere. Asigurați-vă că ați importat fișierele necesare în secțiunea Importuri de fișiere", - "settings_select_file_hint": "Selectează un fișier importat" - }, - "quick_actions_dialog": { - "title": "Editează acțiunile rapide", - "subtitle": "Selectați și redimensionați acțiunile rapide." } - }, - "friend_tracker": { - "rules_tab": "Reguli", - "logs_tab": "Jurnale", - "export_dialog_title": "Exportă", - "bulk_export_button": "Export în bloc", - "individual_export_button": "Export individual", - "invalid_import_type_dialog_title": "Tip de import nevalid", - "invalid_import_type_dialog_text": "Fișierul selectat nu este compatibil cu acest tip de import. Vă rugăm să selectați tipul de import corect.", - "import_dialog_title": "Importă", - "bulk_import_button": "Import în bloc", - "individual_import_button": "Import individual", - "import_button_description": "Importă", - "export_button_description": "Exportă", - "export_button": "Exportă", - "delete_button_description": "Șterge", - "delete_button": "Șterge", - "catalog_button_description": "Catalog", - "catalog_button": "Catalog", - "add_rule_button_description": "Adaugă regulă", - "add_rule_button": "Adaugă regulă", - "no_rules_found": "Nu s-au găsit reguli", - "empty_rule_name": "(gol)", - "events_suffix": "evenimente", - "scopes_suffix": "scopuri", - "select_rule_to_export_title": "Selectează regula de exportat", - "deleted_logs_toast": "{count} jurnale șterse", - "delete_logs_dialog_title": "Ștergeți jurnalele?", - "deleting_logs_dialog_text": "Se șterg {count} jurnale...", - "delete_logs_dialog_confirm_text": "Aceasta va șterge jurnalele pe baza filtrului și interogării de căutare curente. Această acțiune nu poate fi anulată.", - "exported_logs_toast": "Jurnale exportate!", - "export_logs_failed_toast": "Exportul jurnalelor a eșuat. Verificați LogCat pentru mai multe detalii.", - "export_logs_dialog_title": "Exportați jurnalele?", - "exporting_logs_dialog_text": "Se exportă jurnalele...", - "export_logs_dialog_confirm_text": "Aceasta va exporta jurnalele pe baza filtrului și interogării de căutare curente.", - "export_as_button": "Exportă ca {type}", - "filters_title": "Filtre", - "search_by_label": "Caută după", - "newest_first_label": "Cel mai nou primul", - "since_label": "Din", - "until_label": "Până la", - "pick_a_date_button": "Alege o dată", - "search_placeholder": "Caută", - "filter_button_description": "Filtru", - "clear_button_description": "Șterge", - "no_logs_found": "Nu s-au găsit jurnale", - "log_event_format": "{event} în {conversation}", - "condition_only_inside_conversation": "Doar când sunt într-o conversație", - "condition_only_outside_conversation": "Doar când sunt în afara conversației", - "condition_only_when_app_active": "Doar când Snapchat este activ", - "condition_only_when_app_inactive": "Doar când Snapchat este inactiv", - "condition_no_push_notification_when_app_active": "Nicio notificare push când Snapchat este activ", - "add_event_dialog_title": "Adaugă eveniment", - "event_type_label": "Tipul evenimentului", - "triggers_title": "Declanșatoare", - "conditions_title": "Condiții", - "add_button": "Adaugă", - "default_rule_name": "Regulă personalizată", - "discard_changes_dialog_title": "Renunțați la modificări?", - "discard_changes_dialog_text": "Aveți modificări nesalvate. Sigur doriți să le renunțați?", - "discard_button": "Renunță", - "cannot_save_rule_dialog_title": "Nu se poate salva regula", - "cannot_save_rule_dialog_text": "O regulă trebuie să aibă cel puțin un eveniment pentru a fi salvată.", - "duplicate_rule_name_dialog_title": "Nume de regulă duplicat", - "duplicate_rule_name_dialog_text": "Există deja o regulă cu acest nume. Vă rugăm să alegeți un alt nume.", - "delete_rule_dialog_title": "Șterge regula", - "delete_rule_dialog_text": "Sigur doriți să ștergeți această regulă?", - "new_rule_title": "Regulă nouă", - "edit_rule_title": "Editează regula", - "back_button_description": "Înapoi", - "save_button_description": "Salvează", - "general_section_title": "General", - "rule_name_label": "Numele regulii", - "author_name_label": "Numele autorului", - "scope_section_title": "Domeniu", - "scope_all": "Toate", - "scope_whitelist": "Listă albă", - "scope_blacklist": "Listă neagră", - "select_friends_groups_button": "Selectează prieteni/grupuri ({count})", - "events_section_title": "Evenimente", - "add_event_button": "Adaugă eveniment", - "no_events_text": "Niciun eveniment" - }, - "friend_tracker_catalog": { - "download_failed": "Descărcarea a eșuat: {code}", - "error": "Eroare: {message}", - "no_repos_added": "Niciun depozit adăugat.", - "no_rules_available": "Nicio regulă disponibilă din niciun depozit.", - "by_author": "de {author}", - "imported_button": "Importat", - "import_button": "Importă", - "title": "Catalogul Friend Tracker", - "manage_repos_description": "Gestionează depozitele" - }, - "friend_tracker_export": { - "title": "Exportă reguli", - "back_button_description": "Înapoi", - "exported_toast": "Regulile Friend Tracker au fost exportate!", - "export_failed_toast": "Exportul regulilor a eșuat: {message}", - "save_button": "Salvează", - "expand_button_description": "Extinde" - }, - "friend_tracker_import": { - "title": "Importă reguli", - "back_button_description": "Înapoi", - "imported_toast": "Regulile Friend Tracker au fost importate!", - "import_failed_toast": "Importul regulilor a eșuat: {message}", - "confirm_button": "Confirmă", - "expand_button_description": "Extinde" - }, - "friend_tracker_repos": { - "invalid_repo_title": "Depozit nevalid", - "add_repo_button": "Adaugă depozit", - "add_repo_dialog_title": "Adaugă URL-ul depozitului", - "repo_url_label": "URL-ul depozitului", - "repo_added_toast": "Depozitul a fost adăugat cu succes!", - "invalid_repo_error": "Acesta nu pare a fi un depozit Friend Tracker valid.", - "add_repo_failed_toast": "Adăugarea depozitului a eșuat: {message}", - "add_button": "Adaugă", - "no_repos_added": "Niciun depozit adăugat", - "remove_button": "Elimină", - "remove_repo_dialog_title": "Elimină depozitul", - "remove_repo_dialog_text": "Sigur doriți să eliminați acest depozit?" - }, - "navigation": { - "tracker_tab_label": "Tracker", - "customize_bottom_bar_title": "Personalizează bara inferioară", - "customize_bottom_bar_subtitle": "Reordonează, adaugă sau elimină file. Maxim cinci.", - "shown_tabs_title": "Filele afișate", - "no_tabs_selected_text": "Nicio filă selectată", - "available_tabs_title": "Filele disponibile", - "reset_button": "Resetează", - "done_button": "Terminat" - }, - "scripting": { - "script_already_installed": "Scriptul este deja instalat!", - "downloading_script": "Se descarcă scriptul...", - "script_downloaded": "Scriptul {name} a fost descărcat!", - "download_script_failed": "Descărcarea scriptului a eșuat. Verificați jurnalele pentru mai multe detalii", - "import_script_from_url_title": "Importă script din URL", - "import_script_warning": "Avertisment: scripturile importate pot fi dăunătoare pentru dispozitivul dvs. Importați scripturi doar din surse de încredere.", - "enter_url_label": "Introduceți URL-ul aici:", - "script_imported": "Scriptul {name} a fost importat!", - "import_failed": "Importul scriptului a eșuat. {message}. Verificați jurnalele pentru mai multe detalii", - "import_button": "Importă", - "update_module_button": "Actualizează modulul", - "updating_script": "Se actualizează scriptul {name}...", - "module_not_found": "Modulul nu a fost găsit", - "updated_script": "{name} a fost actualizat la versiunea {version}", - "update_module_failed": "Actualizarea modulului a eșuat. Verificați jurnalele pentru mai multe detalii", - "edit_module_button": "Editează modulul", - "open_module_failed": "Deschiderea fișierului modulului a eșuat. Verificați jurnalele pentru mai multe detalii", - "clear_module_data_button": "Șterge datele modulului", - "module_data_cleared": "Datele modulului au fost șterse!", - "clear_module_data_failed": "Ștergerea datelor modulului a eșuat. Verificați jurnalele pentru mai multe detalii", - "delete_module_button": "Șterge modulul", - "deleted_script": "Scriptul {name} a fost șters!", - "delete_module_failed": "Ștergerea modulului a eșuat. Verificați jurnalele pentru mai multe detalii", - "actions_title": "Acțiuni", - "no_description": "Fără descriere", - "update_available": "Actualizare disponibilă: {version}", - "actions_button": "Acțiuni", - "loaded_script": "Scriptul {name} a fost încărcat", - "unloaded_script": "Scriptul {name} a fost descărcat", - "enable_script_failed": "Activarea scriptului a eșuat. Verificați jurnalele pentru mai multe detalii", - "disable_script_failed": "Dezactivarea scriptului a eșuat. Verificați jurnalele pentru mai multe detalii", - "select_scripts_folder_toast": "Vă rugăm să selectați folderul Scripts!", - "manage_repos_button": "Gestionează depozitele", - "import_from_url_button": "Importă din URL", - "open_scripts_folder_button": "Deschide folderul Scripts", - "no_settings_for_module": "Acest modul nu are setări", - "installed_scripts_tab": "Scripturi instalate", - "catalog_tab": "Catalog", - "no_scripts_folder_selected_title": "Niciun folder de scripturi selectat", - "select_folder_button": "Selectează folder", - "no_scripts_found_title": "Nu s-au găsit scripturi.", - "use_catalog_to_add_scripts": "Utilizați fila Catalog pentru a adăuga scripturi!", - "ok_button_timeout": "OK ({timeout})", - "documentation_button": "Documentație", - "catalog": { - "script_already_installed": "Scriptul este deja instalat!", - "download_failed": "Descărcarea a eșuat: {code}", - "script_downloaded": "Script descărcat!", - "could_not_create_file": "Nu s-a putut crea fișierul.", - "no_scripts_folder_selected": "Niciun folder de scripturi selectat.", - "error": "Eroare: {message}", - "no_repos_added": "Niciun depozit adăugat.", - "repo_list_info": "Aici puteți găsi o listă de depozite:", - "link_text": "Link", - "no_scripts_available": "Niciun script disponibil din niciun depozit.", - "by_author": "de {author}", - "version": "Versiune: {version}", - "installed_button": "Instalat", - "download_button": "Descarcă" - }, - "repos": { - "invalid_repo_title": "Depozit nevalid", - "add_repo_button": "Adaugă depozit", - "add_repo_dialog_title": "Adaugă URL-ul depozitului", - "repo_url_label": "URL-ul depozitului", - "repo_added_toast": "Depozitul a fost adăugat cu succes!", - "invalid_repo_error": "Acesta nu pare a fi un depozit de scripturi valid.", - "add_repo_failed_toast": "Adăugarea depozitului a eșuat: {message}", - "add_button": "Adaugă", - "no_repos_added": "Niciun depozit adăugat", - "remove_button": "Elimină", - "remove_repo_dialog_title": "Elimină depozitul", - "remove_repo_dialog_text": "Sigur doriți să eliminați acest depozit?" - } - }, - "features": { - "config_import": { - "title": "Confirmă importul", - "back_button_description": "Înapoi", - "config_imported_toast": "Configurație importată!", - "confirm_button": "Confirmă", - "expand_button_description": "Extinde", - "enable_feature": "Activează funcția", - "enabled": "Activat", - "disabled": "Dezactivat" - }, - "config_export": { - "title": "Rezumatul exportului", - "back_button_description": "Înapoi", - "save_button": "Salvează", - "expand_button_description": "Extinde", - "enable_feature": "Activează funcția", - "enabled": "Activat", - "disabled": "Dezactivat" - } - }, - "manage_repos": { - "title": "Gestionează depozitele {featureName}", - "add_repo_button": "Adaugă depozit", - "add_repo_dialog_title": "Adaugă URL-ul depozitului", - "repo_url_label": "URL-ul depozitului", - "repo_added_successfully": "Depozitul a fost adăugat cu succes!", - "add_repo_failed": "Adăugarea depozitului a eșuat: {message}", - "add_button": "Adaugă", - "no_repos_added": "Niciun depozit adăugat", - "remove_button": "Elimină" } }, "rules": { - "toasts": { - "enabled": "{ruleName} activat", - "disabled": "{ruleName} dezactivat" - }, - "modes": { - "blacklist": "Mod listă neagră", - "whitelist": "Mod listă albă" - }, "properties": { "auto_download": { - "name": "Descărcare automată", - "description": "Descărcați automat Snap-urile când le vizualizați", + "description": "Descarcă automat Snap-uri în timpul vizualizării acestora", "options": { - "blacklist": "Exclude de la descărcarea automată", - "whitelist": "Descărcare automată" - } + "whitelist": "Descărcare Automată", + "blacklist": "Exclude din Descărcare Automată" + }, + "name": "Descărcare automată" }, "stealth": { - "name": "Mod invizibil", - "description": "Împiedică pe oricine să știe că i-ai deschis Snap-urile/chaturile și conversațiile", + "name": "Mod Ascuns", + "description": "Împiedică pe oricine să știe că le-ați deschis Snap-urile/Chat-urile și conversațiile", "options": { - "blacklist": "Exclude din modul invizibil", - "whitelist": "Mod invizibil" + "blacklist": "Exclude din Modul Ascuns", + "whitelist": "Mod Ascuns" } }, "auto_save": { - "name": "Salvare automată", - "description": "Salvează mesajele de chat când le vizualizați", + "description": "Salvează mesajele când sunt vizualizate", "options": { - "blacklist": "Exclude de la salvarea automată", + "blacklist": "Exclude din Salvare Automată", "whitelist": "Salvare automată" - } + }, + "name": "Salvare Automată" }, "unsaveable_messages": { - "name": "Mesaje nesalvabile", - "description": "Împiedică salvarea mesajelor în chat de către alte persoane", + "description": "Împiedică mesajele să fie salvate în chat de către alte persoane", + "name": "Mesaje Nesalvabile", "options": { - "blacklist": "Exclude din mesajele nesalvabile", - "whitelist": "Mesaje nesalvabile" + "whitelist": "Mesaje nesalvate", + "blacklist": "Excludeți din Mesaje Nesalvate" } }, + "e2e_encryption": { + "name": "Utilizați criptarea E2E" + }, + "pin_conversation": { + "name": "Fixați conversația" + }, + "hide_friend_feed": { + "name": "Ascundeți din feedul prietenilor" + }, "auto_open_snaps": { "name": "Deschidere automată Snap-uri", - "description": "Deschide automat Snap-urile când le primești", + "description": "Deschide automat Snap-urile când le primiți", "options": { - "blacklist": "Exclude din deschiderea automată a Snap-urilor", + "blacklist": "Excludeți din deschiderea automată a snap-urilor", "whitelist": "Deschidere automată Snap-uri" } - }, - "hide_friend_feed": { - "name": "Ascunde din feed-ul prietenilor" - }, - "e2e_encryption": { - "name": "Utilizează criptarea E2E" - }, - "pin_conversation": { - "name": "Fixează conversația" - }, - "exclude_message_logger": { - "name": "Exclude din jurnalul de mesaje" } - } - }, - "actions": { - "clean_snapchat_cache": { - "name": "Șterge cache-ul Snapchat", - "description": "Șterge cache-ul Snapchat" }, - "manage_friend_list": { - "name": "Gestionează lista de prieteni", - "description": "Importă/exportă lista de prieteni la crearea unei copii de rezervă" + "modes": { + "blacklist": "Mod Lista Neagră", + "whitelist": "Modul Lista albă" }, - "export_chat_messages": { - "name": "Exportă mesajele de chat", - "description": "Exportă mesajele de conversație într-un fișier JSON/HTML/TXT" - }, - "export_memories": { - "name": "Exportă amintirile", - "description": "Exportă amintirile într-un fișier ZIP" - }, - "bulk_messaging_action": { - "name": "Acțiune de mesagerie în masă", - "description": "Efectuează operațiuni precum ștergerea prietenilor sau ștergerea în masă a conversațiilor" - }, - "regen_mappings": { - "name": "Regenerează mapările", - "description": "Regenerează manual mapările" - }, - "change_language": { - "name": "Schimbă limba", - "description": "Schimbă limba PurrfectSnap" - }, - "file_imports": { - "name": "Importuri de fișiere", - "description": "Importă fișiere pentru a le utiliza în Snapchat" - }, - "friend_tracker": { - "name": "Friend Tracker", - "description": "Urmărește-ți prietenii pe Snapchat" - }, - "logger_history": { - "name": "Istoricul jurnalului", - "description": "Vezi istoricul mesajelor înregistrate" + "toasts": { + "enabled": "{ruleName} activat", + "disabled": "{ruleName} dezactivat" } }, "features": { - "notices": { - "unstable": "⚠ Instabil", - "ban_risk": "⚠ Această funcție poate duce la interdicții", - "internal_behavior": "⚠ Acest lucru poate perturba comportamentul intern al Snapchat" - }, "properties": { - "downloader": { - "name": "Descărcător", - "description": "Descarcă media Snapchat", - "properties": { - "save_folder": { - "name": "Salvează folderul", - "description": "Selectează directorul în care ar trebui descărcate toate mediile" - }, - "auto_download_sources": { - "name": "Surse de descărcare automată", - "description": "Selectează sursele din care să descarci automat" - }, - "prevent_self_auto_download": { - "name": "Previne descărcarea automată a propriilor fișiere", - "description": "Previne descărcarea automată a propriilor Snap-uri" - }, - "path_format": { - "name": "Formatul căii", - "description": "Specifică formatul căii fișierului" - }, - "allow_duplicate": { - "name": "Permite duplicate", - "description": "Permite descărcarea aceluiași fișier media de mai multe ori" - }, - "merge_overlays": { - "name": "Îmbină suprapunerile", - "description": "Combină textul și media unui Snap într-un singur fișier" - }, - "force_image_format": { - "name": "Forțează formatul imaginii", - "description": "Forțează salvarea imaginilor într-un format specificat" - }, - "force_voice_note_format": { - "name": "Forțează formatul notei vocale", - "description": "Forțează salvarea notelor vocale într-un format specificat" - }, - "auto_download_voice_notes": { - "name": "Descărcare automată a notelor vocale", - "description": "Descarcă automat notele vocale la redarea lor" - }, - "download_profile_pictures": { - "name": "Descarcă pozele de profil", - "description": "Permite descărcarea pozelor de profil de pe pagina de profil" - }, - "opera_download_button": { - "name": "Buton de descărcare Opera", - "description": "Adaugă un buton de descărcare în colțul din dreapta sus la vizualizarea unui Snap.\nO apăsare lungă pe buton va forța descărcarea" - }, - "download_context_menu": { - "name": "Meniu contextual de descărcare", - "description": "Permite descărcarea/previzualizarea mesajelor dintr-o conversație sau poveste folosind meniul contextual.\nO apăsare lungă pe buton va forța descărcarea" - }, - "ffmpeg_options": { - "name": "Opțiuni FFmpeg", - "description": "Specifică opțiuni FFmpeg suplimentare", - "properties": { - "threads": { - "name": "Fire de execuție", - "description": "Numărul de fire de execuție de utilizat" - }, - "preset": { - "name": "Presetare", - "description": "Setează viteza de conversie" - }, - "constant_rate_factor": { - "name": "Factor de rată constantă", - "description": "Setează factorul de rată constantă pentru codificatorul video\nDe la 0 la 51 pentru libx264" - }, - "video_bitrate": { - "name": "Rată de biți video", - "description": "Setează rata de biți video (kbps)" - }, - "audio_bitrate": { - "name": "Rată de biți audio", - "description": "Setează rata de biți audio (kbps)" - }, - "custom_video_codec": { - "name": "Codec video personalizat", - "description": "Setează un codec video personalizat (de ex. libx264)" - }, - "custom_audio_codec": { - "name": "Codec audio personalizat", - "description": "Setează un codec audio personalizat (de ex. aac)" - } - } - }, - "logging": { - "name": "Înregistrare", - "description": "Afișează notificări la descărcarea media" - }, - "custom_path_format": { - "name": "Format de cale personalizat", - "description": "Specifică un format de cale personalizat pentru media descărcată\n\nVariabile disponibile:\n - %username%\n - %source%\n - %hash%\n - %date_time%" - } - } - }, "user_interface": { - "name": "Interfață utilizator", - "description": "Schimbă aspectul și senzația Snapchat", "properties": { - "enable_app_appearance": { - "name": "Activează setările de aspect ale aplicației", - "description": "Activează setarea ascunsă de aspect a aplicației.\nS-ar putea să nu fie necesar în versiunile mai noi ale Snapchat." - }, - "friend_feed_message_preview": { - "name": "Previzualizare mesaj în feed-ul prietenilor", - "description": "Afișează o previzualizare a ultimelor mesaje în feed-ul prietenilor", - "properties": { - "amount": { - "name": "Cantitate", - "description": "Numărul de mesaje de previzualizat" - } - } - }, - "snap_preview": { - "name": "Previzualizare Snap", - "description": "Afișează o mică previzualizare lângă Snap-urile nevăzute în chat" - }, - "bootstrap_override": { - "name": "Suprascriere Bootstrap", - "description": "Suprascrie setările de bootstrap ale interfeței de utilizator", - "properties": { - "app_appearance": { - "name": "Aspectul aplicației", - "description": "Setează un aspect persistent al aplicației" - }, - "home_tab": { - "name": "Fila Acasă", - "description": "Suprascrie fila de pornire la deschiderea Snapchat" - } - } - }, - "force_amoled_theme": { - "name": "Mod întunecat AMOLED", - "description": "Folosește un fundal negru real pentru tema întunecată" - }, - "map_friend_nametags": { - "name": "Etichete de nume îmbunătățite pe harta prietenilor", - "description": "Îmbunătățește etichetele de nume ale prietenilor pe Snapmap" - }, - "prevent_message_list_auto_scroll": { - "name": "Previne derularea automată a listei de mesaje", - "description": "Previne derularea listei de mesaje în jos la trimiterea/primirea unui mesaj" - }, - "streak_expiration_info": { - "name": "Afișează informațiile despre expirarea seriei", - "description": "Afișează un cronometru de expirare a seriei lângă contorul de serii" - }, - "hide_friend_feed_entry": { - "name": "Ascunde intrarea din feed-ul prietenilor", - "description": "Ascunde un anumit prieten din feed-ul prietenilor.\nUtilizați fila Social pentru a gestiona această funcție" - }, - "hide_streak_restore": { - "name": "Ascunde restaurarea seriei", - "description": "Ascunde butonul de restaurare în feed-ul prietenilor" - }, - "hide_quick_add_suggestions": { - "name": "Ascunde sugestiile de adăugare rapidă", - "description": "Elimină sugestiile de adăugare rapidă a prietenilor" - }, - "hide_story_suggestions": { - "name": "Ascunde sugestiile de povești", - "description": "Elimină sugestiile de pe pagina Povești" - }, - "hide_ui_components": { - "name": "Ascunde componentele UI", - "description": "Selectează ce componente UI să ascunzi" - }, - "opera_media_quick_info": { - "name": "Informații rapide despre media Opera", - "description": "Afișează informații utile despre media, cum ar fi data creării, în meniul contextual al vizualizatorului Opera" - }, - "old_bitmoji_selfie": { - "name": "Selfie Bitmoji vechi", - "description": "Readuce selfie-urile Bitmoji din versiunile mai vechi ale Snapchat" - }, - "disable_spotlight": { - "name": "Dezactivează Spotlight", - "description": "Dezactivează pagina Spotlight" - }, - "friend_feed_menu_buttons": { - "name": "Butoane meniu feed prieteni", - "description": "Selectează ce butoane să se afișeze în meniul feed-ului prietenilor" - }, - "auto_close_friend_feed_menu": { - "name": "Meniu de închidere automată a feed-ului prietenilor", - "description": "Închide automat meniul feed-ului prietenilor după apăsarea unui buton de setare" - }, - "vertical_story_viewer": { - "name": "Vizualizator de povești vertical", - "description": "Activează vizualizatorul de povești vertical pentru toate poveștile" - }, "enable_friend_feed_menu_bar": { - "name": "Activează bara de meniu a feed-ului prietenilor", - "description": "Activează noua bară de meniu a feed-ului prietenilor" + "name": "Feed pentru prieteni bară de meniu", + "description": "Activează noua bară de meniu Friend pentru prieteni" }, "message_indicators": { "name": "Indicatori de mesaje", - "description": "Adaugă pictograme indicatoare specifice la mesaje.\nNotă: indicatorii s-ar putea să nu fie 100% exacți" + "description": "Adaugă pictograme indicatoare specifice la mesaje\nNotă: este posibil ca indicatorii să nu fie 100% precisi" }, "stealth_mode_indicator": { - "name": "Indicator mod invizibil", - "description": "Adaugă un emoji 👻 lângă conversațiile în modul invizibil" + "name": "Indicator mod ascuns", + "description": "Adaugă un emoji 👻 lângă conversații în modul ascuns" + }, + "vertical_story_viewer": { + "description": "Activează vizualizatorul vertical de povești pentru toate poveștile", + "name": "Vizualizator de Povești Vertical" }, "edit_text_override": { - "name": "Suprascrie editarea textului", - "description": "Suprascrie comportamentul câmpului de text" + "description": "Anulează comportamentul câmpului de text", + "name": "Modificați modificarea textului" }, - "prevent_forced_keyboard": { - "name": "Previne tastatura forțată", - "description": "Previne afișarea automată a tastaturii de către Snapchat la deschiderea unei conversații" + "hide_streak_restore": { + "name": "Ascundeți restaurarea liniei fierbinți", + "description": "Ascunde butonul Restaurare din fluxul prietenilor" }, - "settings_menu": { - "name": "Meniu Setări", - "description": "Schimbă modul de deschidere a meniului PurrfectSnap", - "options": { - "default": "Implicit", - "legacy": "Vechi" + "enable_app_appearance": { + "description": "Activează setările ascunse ale aspectului aplicației\nEste posibil să nu fie necesar pentru versiunile Snapchat mai noi", + "name": "Activați Setările de aspect al aplicației" + }, + "snap_preview": { + "name": "Previzualizare Snapului", + "description": "Afișează o mică previzualizare lângă snapurile nevăzute în chat" + }, + "bootstrap_override": { + "name": "Suprascriere Bootstrap", + "description": "Ignoră setările de bootstrap a interfeței de utilizator", + "properties": { + "home_tab": { + "description": "Ignoră fila de pornire la deschiderea Snapchat", + "name": "Fila Acasă" + }, + "app_appearance": { + "name": "Aspectul aplicației", + "description": "Setează un aspect persistent al aplicației" + } } + }, + "map_friend_nametags": { + "description": "Îmbunătățește numele prietenilor de pe mapa Snapchat", + "name": "Îmbunătățește numele prietenilor de pe mapă" + }, + "prevent_message_list_auto_scroll": { + "description": "Împiedică derularea listei de mesaje în jos la trimiterea/primirea unui mesaj", + "name": "Preveniți derularea automată a listei de mesaje" + }, + "hide_ui_components": { + "description": "Selectați ce componente ale interfeței de utilizator să ascundeți", + "name": "Ascundeți componentele interfeței de utilizator" + }, + "opera_media_quick_info": { + "name": "Informații rapide Opera Media", + "description": "Afișează informații utile despre media, cum ar fi data creării, în meniul contextual al vizualizatorului opera" + }, + "old_bitmoji_selfie": { + "description": "Readuce selfie-urile Bitmoji din versiuni mai vechi Snapchat", + "name": "Selfie vechi Bitmoji" + }, + "disable_spotlight": { + "name": "Dezactivați Spotlight", + "description": "Dezactivează pagina Spotlight" + }, + "friend_feed_message_preview": { + "properties": { + "amount": { + "name": "Cantitate", + "description": "Cantitatea de mesaje care trebuie previzualizate" + } + }, + "name": "Previzualizarea mesajului din feedul prietenilor", + "description": "Afișează o previzualizare a ultimelor mesaje din Fluxul prietenilor" + }, + "friend_feed_menu_buttons": { + "description": "Selectați ce butoane să afișați în meniul fluxul prietenilor", + "name": "Butoanele pentru meniul fluxul prietenilor" + }, + "streak_expiration_info": { + "name": "Afișați informații despre expirarea liniei fierbinți", + "description": "Afișează un temporizator de expirare a liniei fierbinți lângă contorul de linii" + }, + "hide_friend_feed_entry": { + "name": "Ascundeți intrarea în feedul prietenilor", + "description": "Ascunde un anumit prieten din Fluxul de prieteni\nUtilizați fila socială pentru a gestiona această funcție" + }, + "hide_story_suggestions": { + "name": "Ascundeți sugestiile de povești", + "description": "Elimină sugestiile din pagina Povestiri" } - } + }, + "name": "Interfața cu utilizatorul", + "description": "Schimbați aspectul Snapchat" }, "messaging": { - "name": "Mesagerie", - "description": "Schimbă modul în care interacționezi cu prietenii", "properties": { - "bypass_screenshot_detection": { - "name": "Ocolește detectarea capturilor de ecran", - "description": "Împiedică Snapchat să detecteze când faci o captură de ecran" - }, - "anonymous_story_viewing": { - "name": "Vizualizare anonimă a poveștilor", - "description": "Împiedică pe oricine să știe că i-ai văzut povestea" - }, "prevent_story_rewatch_indicator": { - "name": "Previne indicatorul de revizionare a poveștii", - "description": "Împiedică pe oricine să știe că ai revăzut povestea lor" - }, - "hide_peek_a_peek": { - "name": "Ascunde peek-a-peek", - "description": "Împiedică trimiterea notificării când te uiți pe furiș într-un chat" - }, - "hide_bitmoji_presence": { - "name": "Ascunde prezența Bitmoji", - "description": "Împiedică apariția Bitmoji-ului tău în timpul chat-ului" + "name": "Preveniți indicatorul de revizionare a poveștii", + "description": "Împiedică pe oricine să știe că le-ați revizionat povestea" }, "hide_typing_notifications": { - "name": "Ascunde notificările de tastare", - "description": "Împiedică pe oricine să știe că tastezi un mesaj" + "name": "Ascunde Notificarea Scrie", + "description": "Împiedică pe oricine să știe că introduci un mesaj" }, - "unlimited_snap_view_time": { - "name": "Timp nelimitat de vizualizare a Snap-urilor", - "description": "Elimină limita de timp pentru vizualizarea Snap-urilor" + "hide_peek_a_peek": { + "name": "Ascunde Peek-a-Peek", + "description": "Împiedică trimiterea notificărilor atunci când glisați pe jumătate într-o conversație" }, - "auto_mark_as_read": { - "name": "Marchează automat ca citit", - "description": "Marchează automat mesajele/snap-urile ca citite chiar și atunci când modul Invizibil este activat" + "bypass_screenshot_detection": { + "name": "Anulare Detectarea Capturii de Ecran", + "description": "Împiedică Snapchat să detecteze când faceți o captură de ecran" }, - "mark_snap_as_seen_button": { - "name": "Butonul Marchează Snap ca văzut", - "description": "Adaugă un buton pentru a marca un Snap ca văzut în timp ce îl vizualizezi.\nAcest lucru va funcționa chiar și atunci când modul Invizibil este activat" + "anonymous_story_viewing": { + "name": "Vizionare anonimă a poveștii", + "description": "Împiedică pe oricine să știe că le-ai văzut povestea" }, - "skip_when_marking_as_seen": { - "name": "Sari la marcarea ca văzut", - "description": "Sare automat la următorul Snap la marcarea unui Snap ca văzut.\nFolosește în combinație cu butonul Marchează Snap ca văzut" - }, - "loop_media_playback": { - "name": "Redare media în buclă", - "description": "Redă în buclă media la vizualizarea Snap-urilor/Poveștilor" - }, - "disable_replay_in_ff": { - "name": "Dezactivează reluarea în FF", - "description": "Dezactivează posibilitatea de a relua cu o apăsare lungă din feed-ul prietenilor" + "hide_bitmoji_presence": { + "name": "Ascundeți prezența Bitmoji", + "description": "Împiedică apariția Bitmoji-ului dvs. în timp ce sunteți într-o conversație" }, "half_swipe_notifier": { - "name": "Notificator de jumătate de glisare", - "description": "Te notifică atunci când cineva se uită pe furiș într-o conversație", "properties": { - "min_duration": { - "name": "Durată minimă", - "description": "Durata minimă a jumătății de glisare (în secunde)" - }, "max_duration": { - "name": "Durată maximă", - "description": "Durata maximă a jumătății de glisare (în secunde)" + "description": "Durata maximă a jumătății de glisare (în secunde)", + "name": "Durata maximă" + }, + "min_duration": { + "name": "Durata minimă", + "description": "Durata minimă a jumătății de glisare (în secunde)" } - } + }, + "name": "Notificator glisare pe jumătate", + "description": "Anunță-mă când cineva glisează pe jumătate într-o conversație" }, - "call_start_confirmation": { - "name": "Confirmare începere apel", - "description": "Afișează un dialog de confirmare la începerea unui apel" - }, - "unlimited_conversation_pinning": { - "name": "Fixare nelimitată a conversațiilor", - "description": "Permite fixarea unui număr nelimitat de conversații local" - }, - "disable_snap_mode_restrictions": { - "name": "Dezactivează restricțiile modului Snap", - "description": "Permite vizualizarea Snap-urilor cu autodistrugere fără restricții" - }, - "prevent_message_sending": { - "name": "Previne trimiterea mesajelor", - "description": "Previne trimiterea anumitor tipuri de mesaje" - }, - "friend_mutation_notifier": { - "name": "Notificator de mutații ale prietenilor", - "description": "Te notifică atunci când ceva se schimbă în profilul unui prieten" - }, - "better_notifications": { - "name": "Notificări mai bune", - "description": "Adaugă mai multe informații în notificările primite", - "properties": { - "group_notifications": { - "name": "Notificări de grup", - "description": "Grupează notificările într-una singură" - }, - "chat_preview": { - "name": "Previzualizare chat", - "description": "Afișează o previzualizare a mesajelor primite în notificare" - }, - "media_preview": { - "name": "Previzualizare media", - "description": "Afișează o previzualizare a tipurilor de media selectate în notificare" - }, - "media_caption": { - "name": "Legendă media", - "description": "Afișează legenda atașată a mediei în notificare" - }, - "stacked_media_messages": { - "name": "Mesaje media stivuite", - "description": "Combină mai multe mesaje media într-o singură notificare text atunci când nu pot fi previzualizate. Folosește în combinație cu previzualizarea chat-ului" - }, - "friend_add_source": { - "name": "Sursă adăugare prieten", - "description": "Afișează sursa unei cereri de prietenie în notificare" - }, - "reply_button": { - "name": "Buton de răspuns", - "description": "Adaugă un buton de răspuns la notificare" - }, - "smart_replies": { - "name": "Răspunsuri inteligente", - "description": "Adaugă răspunsuri sugerate la notificări (Android 10+). Folosește în combinație cu butonul de răspuns" - }, - "download_button": { - "name": "Buton de descărcare", - "description": "Permite descărcarea media din notificare" - }, - "mark_as_read_button": { - "name": "Buton Marchează ca citit", - "description": "Permite marcarea unui mesaj ca citit din notificare" - }, - "mark_as_read_and_save_in_chat": { - "name": "Marchează ca citit și salvează în chat", - "description": "Adaugă un buton Marchează ca citit și salvează în chat la notificare" - } - } + "auto_save_messages_in_conversations": { + "description": "Salvează automat fiecare mesaj din conversații", + "name": "Salvare automată a mesajelor" }, "notification_blacklist": { - "name": "Listă neagră de notificări", - "description": "Selectează notificările care ar trebui blocate" + "description": "Selectați notificările care ar trebui să fie blocate", + "name": "Lista neagră de notificări" + }, + "unlimited_snap_view_time": { + "description": "Elimină limita de timp pentru vizualizarea snapurilor", + "name": "Timp nelimitat de vizualizare a Snapurilor" + }, + "call_start_confirmation": { + "name": "Confirmare pornire apel", + "description": "Afișează un dialog de confirmare la inițierea unui apel" + }, + "better_notifications": { + "description": "Adaugă mai multe informații în notificările primite", + "name": "Notificări mai bune" }, "message_logger": { - "name": "Jurnal de mesaje", - "description": "Previne ștergerea mesajelor", + "name": "Înregistrare mesaje", + "description": "Împiedică ștergerea mesajelor", "properties": { + "auto_purge": { + "name": "Curățare Automată", + "description": "Șterge automat mesajele din memoria temporală care sunt mai vechi decât perioada de timp specificată" + }, "keep_my_own_messages": { "name": "Păstrează-mi propriile mesaje", - "description": "Previne ștergerea propriilor mesaje" - }, - "auto_purge": { - "name": "Curățare automată", - "description": "Șterge automat mesajele din cache mai vechi decât perioada de timp specificată" + "description": "Împiedică ștergerea propriilor mesaje" }, "message_filter": { "name": "Filtru de mesaje", - "description": "Selectează ce mesaje ar trebui înregistrate (gol pentru toate mesajele)" - }, - "deleted_message_color": { - "name": "Culoare mesaj șters", - "description": "Setează culoarea mesajelor șterse" + "description": "Selectați ce mesaje ar trebui să fie înregistrate (gol pentru toate mesajele)" } } }, - "auto_save_messages_in_conversations": { - "name": "Salvează automat mesajele", - "description": "Salvează automat fiecare mesaj din conversații" - }, - "gallery_media_send_override": { - "name": "Suprascrie trimiterea media din galerie", - "description": "Falsifică sursa media la trimiterea din Galerie" - }, - "strip_media_metadata": { - "name": "Elimină metadatele media", - "description": "Elimină metadatele media înainte de a le trimite ca mesaj" - }, "bypass_message_retention_policy": { - "name": "Ocolește politica de reținere a mesajelor", - "description": "Previne ștergerea mesajelor după vizualizarea lor" - }, - "bypass_message_action_restrictions": { - "name": "Ocolește restricțiile de acțiune a mesajelor", - "description": "Permite reacționarea la un snap fără a-l deschide sau salvarea unui mesaj nesalvabil" + "description": "Împiedică ștergerea mesajelor după ce le-ați vizualizat", + "name": "Ocoliți politica de păstrare a mesajelor" }, "remove_groups_locked_status": { - "name": "Elimină starea blocată a grupurilor", - "description": "Permite vizualizarea informațiilor despre grup după ce ai fost dat afară" + "description": "Vă permite să vizualizați informații despre grup după ce ați fost dat afară", + "name": "Eliminați starea grupurilor blocate" }, - "double_tap_chat_action": { - "name": "Acțiune de dublă atingere în chat", - "description": "Efectuează o acțiune personalizată la dubla atingere a unui mesaj în chat" + "auto_mark_as_read": { + "name": "Marcare automată ca citit", + "description": "Marchează automat mesajele/snapurile ca citite chiar și atunci când modul invizibil este activat" }, - "double_tap_chat_action_custom_emoji": { - "name": "Reacție emoji personalizată la acțiunea de dublă atingere în chat", - "description": "Setează o reacție emoji personalizată pentru acțiunea de dublă atingere în chat" + "loop_media_playback": { + "name": "Redare media în buclă", + "description": "Redare media în buclă când vizualizați snapurile/povestirile" + }, + "disable_replay_in_ff": { + "description": "Dezactivează capacitatea de a relua cu o apăsare lungă din fluxul prietenilor", + "name": "Dezactivați redarea în FF" + }, + "prevent_message_sending": { + "name": "Preveniți trimiterea mesajelor", + "description": "Împiedică trimiterea anumitor tipuri de mesaje" + }, + "gallery_media_send_override": { + "name": "Suprascrierea Trimiterii Media din Galerie", + "description": "Falsifică sursa media atunci când trimiteți din Galerie" + }, + "strip_media_metadata": { + "name": "Eliminarea Metadatelor Media", + "description": "Elimină metadatele media înainte de a le trimite ca mesaj" + }, + "bypass_message_action_restrictions": { + "name": "Ocoliți restricțiile privind acțiunea mesajului", + "description": "Vă permite să reacționați la un snap fără a-l deschide sau să salvați un mesaj care nu poate fi salvat" + }, + "friend_mutation_notifier": { + "name": "Notificator de modificări la lista de prieteni", + "description": "Te anunță când se schimbă ceva în profilul unui prieten" } - } + }, + "description": "Schimbă cum te interacționezi cu prietenii", + "name": "Mesaje" }, "global": { - "name": "Global", - "description": "Ajustează setările globale Snapchat", "properties": { + "snapchat_plus": { + "description": "Activează funcțiile Snapchat Plus\nEste posibil ca unele caracteristici ale serverului să nu funcționeze", + "name": "Snapchat Plus(premium)" + }, + "hide_active_music": { + "name": "Ascunde muzica activă", + "description": "Împiedică Snapchat să știe că asculți muzică\nAcest lucru vă va permite să faceți instantanee folosind butoanele de control al volumului în timp ce ascultați muzică" + }, "better_location": { "name": "Locație mai bună", - "description": "Îmbunătățește locația Snapchat", + "description": "Îmbunătățește locația pentru Snapchat", "properties": { + "spoof_battery_level": { + "name": "Falsifică nivelului bateriei", + "description": "Falsifică nivelul bateriei dispozitivului dumneavoastră pe hartă\nValoarea trebuie să fie între 0 și 100" + }, "spoof_location": { - "name": "Falsifică locația", - "description": "Falsifică locația ta într-una specificată" + "name": "Falsificarea Locației", + "description": "Falsifică locația dumneavoastră la una specificată" }, "coordinates": { - "name": "Coordonate", - "description": "Setează coordonatele locației falsificate" - }, - "walk_radius": { - "name": "Raza de mers", - "description": "Mergi la întâmplare în interiorul acestei raze (picioare)" + "name": "Coordonatele", + "description": "Setați coordonatele locației falsificate" }, "always_update_location": { - "name": "Actualizează mereu locația", - "description": "Forțează Snapchat să actualizeze locația chiar dacă nu se primesc date GPS" + "name": "Actualizați întotdeauna locația", + "description": "Forțați Snapchat să actualizeze locația chiar dacă nu sunt primite date GPS" }, "suspend_location_updates": { - "name": "Suspendă actualizările de locație", - "description": "Împiedică actualizarea locației tale" - }, - "spoof_battery_level": { - "name": "Falsifică nivelul bateriei", - "description": "Falsifică nivelul bateriei dispozitivului tău pe hartă.\nValoarea trebuie să fie între 0 și 100" + "name": "Suspendați actualizările locației", + "description": "Adaugă un buton în setările hărții pentru a suspenda actualizările locației" }, "spoof_headphones": { - "name": "Falsifică căștile", - "description": "Falsifică starea de ascultare a muzicii pe hartă" + "description": "Falsifică starea de a asculta muzică pe hartă", + "name": "Falsificarea purtării Căștilor" }, - "show_battery_level": { - "name": "Afișează nivelul bateriei", - "description": "Afișează nivelul bateriei prietenilor tăi pe hartă" - } - } - }, - "snapchat_plus": { - "name": "Snapchat+", - "description": "Activează funcțiile Snapchat+.\nUnele funcții de pe partea de server s-ar putea să nu funcționeze" - }, - "media_upload_quality": { - "name": "Calitatea încărcării media", - "description": "Suprascrie calitatea încărcării media", - "properties": { - "force_video_upload_source_quality": { - "name": "Forțează calitatea sursei la încărcarea video", - "description": "Forțează Snapchat să utilizeze calitatea sursei la încărcarea videoclipurilor.\nRețineți că acest lucru s-ar putea să nu elimine metadatele din media" - }, - "disable_image_compression": { - "name": "Dezactivează compresia imaginilor", - "description": "Dezactivează compresia imaginilor la încărcarea media" - }, - "custom_image_upload_format": { - "name": "Format de încărcare a imaginilor personalizat", - "description": "Setează un format de încărcare a imaginilor personalizat.\nSelectează un format fără pierderi (cum ar fi PNG) pentru cea mai bună calitate" + "walk_radius": { + "name": "Raza de deplasare", + "description": "Mergeți la întâmplare în această rază (ft)" } } }, "disable_confirmation_dialogs": { - "name": "Dezactivează dialogurile de confirmare", - "description": "Confirmă automat acțiunile selectate" + "description": "Confirmă automat acțiunile selectate", + "name": "Dezactivați casetele de dialog de confirmare" + }, + "disable_permission_requests": { + "name": "Dezactivați solicitările de permisiune", + "description": "Împiedică Snapchat să solicite permisiuni specifice" + }, + "disable_story_sections": { + "description": "Elimină secțiuni din pagina Povestiri\nPoate necesita o reîmprospătare pentru a funcționa corect", + "name": "Dezactivați secțiunile de poveste" + }, + "disable_memories_snap_feed": { + "description": "Împiedică Snapchat să arate amintiri recente atunci când glisați în sus în cameră", + "name": "Dezactivare Flux Snapuri din Amintiri" + }, + "spotlight_comments_username": { + "name": "Nume utilizator în comentarii Spotlight", + "description": "Afișează numele de utilizator al autorului în comentariile Spotlight" }, "auto_updater": { - "name": "Actualizator automat", + "name": "Actualizare automată", "description": "Verifică automat pentru noi actualizări" }, "disable_metrics": { - "name": "Dezactivează metricele", + "name": "Dezactivare Metrice", "description": "Blochează trimiterea de date analitice specifice către Snapchat" }, - "disable_story_sections": { - "name": "Dezactivează secțiunile de povești", - "description": "Elimină secțiuni de pe pagina Povești.\nPoate necesita o reîmprospătare pentru a funcționa corect" - }, - "block_ads": { - "name": "Blochează reclamele", - "description": "Împiedică afișarea reclamelor" - }, - "disable_custom_tabs": { - "name": "Dezactivează filele personalizate", - "description": "Deschide link-urile în aplicațiile acceptate în loc de browserul web" - }, - "disable_permission_requests": { - "name": "Dezactivează cererile de permisiuni", - "description": "Împiedică Snapchat să solicite permisiuni specifice" - }, - "disable_memories_snap_feed": { - "name": "Dezactivează feed-ul de Snap-uri din Amintiri", - "description": "Împiedică Snapchat să afișeze amintiri recente când glisezi în sus în cameră" - }, - "spotlight_comments_username": { - "name": "Nume de utilizator în comentariile Spotlight", - "description": "Afișează numele de utilizator al autorului în comentariile Spotlight" - }, - "bypass_video_length_restriction": { - "name": "Ocolește restricțiile de lungime a videoclipului", - "description": "Singur: trimite un singur videoclip.\nÎmpărțit: împarte videoclipurile după editare" - }, "default_video_playback_rate": { - "name": "Rată de redare video implicită", - "description": "Setează viteza implicită pentru redarea videoclipurilor.\nValoarea trebuie să fie între 0.1 și 4.0" + "name": "Rata de redare video implicită", + "description": "Setează viteza implicită pentru redarea videoclipurilor\nValoarea trebuie să fie între 0,1 și 4,0" }, "video_playback_rate_slider": { - "name": "Cursor pentru rata de redare video", - "description": "Adaugă un cursor în meniul contextual Opera pentru a schimba rata de redare video.\nNotă: modificările se aplică doar videoclipurilor ulterioare" + "name": "Glisor pentru rata de redare video", + "description": "Adaugă un glisor în meniul contextual al operei pentru a modifica rata de redare a videoclipurilor\nNotă: modificările se aplică numai videoclipurilor ulterioare" }, "disable_google_play_dialogs": { - "name": "Dezactivează dialogurile Serviciilor Google Play", - "description": "Previne afișarea dialogurilor de disponibilitate a Serviciilor Google Play" + "name": "Dezactivați casetele de dialog pentru serviciile Google Play", + "description": "Împiedicați afișarea dialogurilor privind disponibilitatea Serviciilor Google Play" + }, + "bypass_video_length_restriction": { + "name": "Ocoliți restricțiile privind durata videoclipului", + "description": "Singur: trimite un singur videoclip\nDivizare: împarte videoclipurile după editare" + }, + "block_ads": { + "description": "Împiedică afișarea reclamelor", + "name": "Blocați anunțurile" }, "default_volume_controls": { "name": "Controale de volum implicite", - "description": "Forțează Snapchat să utilizeze controalele de volum ale sistemului" - }, - "disable_telecom_framework": { - "name": "Dezactivează cadrul Telecom", - "description": "Împiedică Snapchat să utilizeze cadrul Android Telecom.\nAcest lucru îți permite să asculți muzică în timpul unui apel" - }, - "hide_active_music": { - "name": "Ascunde muzica activă", - "description": "Împiedică Snapchat să știe că asculți muzică.\nAcest lucru îți va permite să faci Snap-uri folosind butoanele de control al volumului în timp ce asculți muzică" + "description": "Forțează Snapchat să folosească controalele de volum ale sistemului" }, "disable_snap_splitting": { - "name": "Dezactivează împărțirea Snap-urilor", - "description": "Împiedică împărțirea Snap-urilor în mai multe părți.\nImaginile pe care le trimiți se vor transforma în videoclipuri" + "name": "Dezactivare divizare Snap", + "description": "Împiedică împărțirea instantaneelor în mai multe părți\nImaginile pe care le trimiteți se vor transforma în videoclipuri" + }, + "disable_custom_tabs": { + "name": "Dezactivați filele personalizate", + "description": "Deschide linkuri în aplicațiile acceptate și nu în browserul web" } - } + }, + "name": "Global", + "description": "Modificați setările globale Snapchat" + }, + "downloader": { + "properties": { + "ffmpeg_options": { + "description": "Specificați opțiuni suplimentare FFmpeg", + "properties": { + "threads": { + "name": "Fire", + "description": "Cantitatea de fire de folosit" + }, + "preset": { + "name": "Presetat", + "description": "Setați viteza conversiei" + }, + "constant_rate_factor": { + "name": "Factor de rată constantă", + "description": "Setați factorul de rată constantă pentru codificatorul video\nDe la 0 la 51 pentru libx264" + }, + "custom_video_codec": { + "description": "Setați un codec video personalizat (de exemplu, libx264)", + "name": "Codec video personalizat" + }, + "custom_audio_codec": { + "name": "Codec audio personalizat", + "description": "Setați un codec audio personalizat (de exemplu, AAC)" + }, + "audio_bitrate": { + "name": "Rata de biți audio", + "description": "Setați rata de biți audio (kbps)" + }, + "video_bitrate": { + "name": "Rata de transfer video", + "description": "Setați rata de biți video (kbps)" + } + }, + "name": "Opțiuni FFmpeg" + }, + "save_folder": { + "name": "Salvare dosar", + "description": "Selectați directorul în care ar trebui să fie descărcate toate fișierele media" + }, + "prevent_self_auto_download": { + "description": "Împiedică descărcarea automată a Snapurilor proprii", + "name": "Preveniți descărcarea automată a fișierelor proprii" + }, + "path_format": { + "name": "Format cale", + "description": "Specificați formatul căii fișierului" + }, + "merge_overlays": { + "description": "Combină textul și media unui Snap într-un singur fișier", + "name": "Îmbinați suprapunerile" + }, + "download_profile_pictures": { + "description": "Vă permite să descărcați imagini de profil de pe pagina de profil", + "name": "Descărcați poze de profil" + }, + "opera_download_button": { + "description": "Adaugă un buton de descărcare în colțul din dreapta sus când vizualizați un Snap.\nApăsarea lungă a butoanelor va forța descărcarea", + "name": "Butonul de descărcare Opera" + }, + "download_context_menu": { + "name": "Descărcați meniul contextual", + "description": "Vă permite să descărcați/previzualizați mesaje dintr-o conversație sau o poveste folosind meniul contextual.\nApăsarea lungă a butoanelor va forța descărcarea" + }, + "logging": { + "description": "Arată notificări când se descarcă media", + "name": "Logare" + }, + "custom_path_format": { + "description": "Specificați un format de cale personalizat pentru conținutul media descărcat\n\nVariabile disponibile:\n- %nume de utilizator%\n- %sursă%\n- %hash%\n- %dată_timp%", + "name": "Format de cale personalizat" + }, + "force_voice_note_format": { + "name": "Formatare forțată a înregistrărilor audio vocale", + "description": "Forțează ca înregistrările audio vocale să fie salvate într-un format specificat" + }, + "allow_duplicate": { + "name": "Permite duplicarea", + "description": "Permite descărcarea aceluiași suport media de mai multe ori" + }, + "force_image_format": { + "description": "Forțează salvarea imaginilor într-un format specificat", + "name": "Forțați formatul imaginii" + }, + "auto_download_sources": { + "name": "Surse de descărcare automată", + "description": "Selectați sursele din care să descărcați automat" + } + }, + "description": "Descarcă conținut media de pe Snapchat", + "name": "Descărcător" }, "rules": { "name": "Reguli", - "description": "Gestionează funcțiile automate pentru persoane individuale" + "description": "Gestionați funcțiile automate pentru persoane individuale" }, "camera": { - "name": "Cameră", - "description": "Ajustează setările potrivite pentru Snap-ul perfect", + "name": "Cameră foto", "properties": { - "disable_cameras": { - "name": "Dezactivează camerele", - "description": "Împiedică Snapchat să utilizeze camerele selectate" + "back_custom_frame_rate": { + "name": "Rată de cadre personalizată cameră din spate", + "description": "Ignoră rata de cadre a camerei din spate" }, - "black_photos": { - "name": "Fotografii negre", - "description": "Înlocuiește fotografiile capturate cu un fundal negru.\nVideoclipurile nu sunt afectate" + "force_camera_source_encoding": { + "name": "Forțează Codificarea Sursă a Camerei", + "description": "Forțează codificarea sursei camerei" + }, + "disable_cameras": { + "name": "Dezactivează Camerele", + "description": "Previne utilizarea camerelor selectate de către Snapchat" }, "immersive_camera_preview": { - "name": "Previzualizare imersivă a camerei", - "description": "Împiedică Snapchat să decupeze previzualizarea camerei.\nAcest lucru ar putea face ca camera să pâlpâie pe unele dispozitive" - }, - "override_front_resolution": { - "name": "Suprascrie rezoluția frontală", - "description": "Suprascrie rezoluția camerei pentru camera frontală" + "name": "Previzualizare Întreruptoare", + "description": "Împiedică Snapchat să decupeze previzualizarea camerei\nAcest lucru poate face ca camera să pâlpâie pe unele dispozitive" }, "override_back_resolution": { - "name": "Suprascrie rezoluția din spate", + "name": "Suprascrieți Rezoluția Camerei Spate", "description": "Suprascrie rezoluția camerei pentru camera din spate" }, "custom_resolution": { - "name": "Rezoluție personalizată", - "description": "Setează o rezoluție personalizată a camerei, lățime x înălțime (de ex. 1920x1080).\nRezoluția personalizată trebuie să fie acceptată de dispozitivul dvs." + "description": "Setează o rezoluție personalizată a camerei, lățime x înălțime (de exemplu, 1920x1080).\nRezoluția personalizată trebuie să fie acceptată de dispozitivul dumneavoastră", + "name": "Rezoluție personalizată" }, "front_custom_frame_rate": { - "name": "Rată de cadre personalizată frontală", - "description": "Suprascrie rata de cadre a camerei frontale" + "name": "Rata de cadre personalizată față", + "description": "Ignoră rata de cadre a camerei frontale" }, - "back_custom_frame_rate": { - "name": "Rată de cadre personalizată din spate", - "description": "Suprascrie rata de cadre a camerei din spate" + "black_photos": { + "description": "Înlocuiește fotografiile capturate cu un fundal negru\nVideoclipurile nu sunt afectate", + "name": "Fotografii Negre" }, - "force_camera_source_encoding": { - "name": "Forțează codificarea sursei camerei", - "description": "Forțează codificarea sursei camerei" - }, - "startup_default_camera": { - "name": "Cameră implicită la pornire", - "description": "Setează camera implicită la deschiderea Snapchat" + "override_front_resolution": { + "name": "Suprascrieți Rezoluția Camerei Frontale", + "description": "Suprascrie rezoluția camerei pentru camera frontală" }, "hevc_recording": { "name": "Înregistrare HEVC", "description": "Utilizează codecul HEVC (H.265) pentru înregistrarea video" } - } + }, + "description": "Ajustați setările potrivite pentru un snap perfect" }, "streaks_reminder": { - "name": "Memento Serii", - "description": "Vă notifică periodic cu privire la serii", "properties": { - "interval": { - "name": "Interval", - "description": "Intervalul dintre fiecare memento (ore)" - }, "remaining_hours": { "name": "Timp rămas", - "description": "Timpul rămas înainte de afișarea notificării (ore)" + "description": "Timpul rămas înainte ca notificarea să fie afișată (ore)" }, "group_notifications": { - "name": "Notificări de grup", - "description": "Grupează notificările într-una singură" + "description": "Grupați notificările într-una singură", + "name": "Notificări de grup" + }, + "interval": { + "description": "Intervalul dintre fiecare memento (ore)", + "name": "Setează interval" } - } + }, + "name": "Reamintire Streak-uri(pierderea liniilor fierbinți/focurilor)", + "description": "Vă anunță periodic despre liniile fierbinți ale dumneavoastră" }, "experimental": { - "name": "Experimental", - "description": "Caracteristici experimentale", "properties": { - "native_hooks": { - "name": "Hook-uri native", - "description": "Caracteristici nesigure care se conectează la codul nativ al Snapchat", - "properties": { - "composer_hooks": { - "name": "Hook-uri Composer", - "description": "Injectează cod în framework-ul UI Composer multi-platformă", - "properties": { - "show_first_created_username": { - "name": "Afișează primul nume de utilizator creat", - "description": "Afișează primul nume de utilizator creat lângă numele de utilizator curent în pagina de profil" - }, - "bypass_camera_roll_limit": { - "name": "Ocolește limita pentru galeria camerei", - "description": "Mărește numărul maxim de fișiere media pe care le puteți trimite din galeria camerei" - }, - "custom_self_destruct_snap_delay": { - "name": "Întârziere personalizată de autodistrugere", - "description": "Oferă mai multe opțiuni pentru cronometrul de autodistrugere la trimiterea unui Snap" - }, - "composer_console": { - "name": "Consolă Composer", - "description": "Vă permite să executați cod JavaScript în Composer (doar ARM64)" - }, - "composer_logs": { - "name": "Jurnale Composer", - "description": "Redirecționează jurnalele consolei Composer către PurrfectSnap" - } - } - }, - "disable_bitmoji": { - "name": "Dezactivează Bitmoji", - "description": "Dezactivează Bitmoji-ul din profilul prietenilor" - }, - "custom_emoji_font": { - "name": "Font emoji personalizat", - "description": "Vă permite să utilizați un font Emoji personalizat. Funcționează doar cu fonturi .ttf" - }, - "custom_shared_library": { - "name": "Bibliotecă partajată personalizată", - "description": "Încarcă o bibliotecă partajată personalizată în Snapchat. Această funcție este doar în scopuri de testare" - } - } + "infinite_story_boost": { + "description": "Evită întârzierea limitării Boost-ului de Povestire", + "name": "Boost nelimitat de Povestire" }, - "spoof": { - "name": "Falsificare", - "description": "Falsifică diverse informații despre tine", + "account_switcher": { + "description": "Vă permite să comutați între conturi fără a vă deconecta\nApăsați lung pe pictograma de căutare de lângă profilul dumneavoastră Bitmoji pentru a deschide meniul\nNotă: această funcție este experimentală și probabil se va schimba în viitor", "properties": { - "play_store_installer_package_name": { - "name": "Numele pachetului de instalare Play Store", - "description": "Înlocuiește numele pachetului de instalare cu com.android.vending" - }, - "remove_vpn_transport_flag": { - "name": "Elimină indicatorul de transport VPN", - "description": "Împiedică Snapchat să detecteze VPN-uri" - }, - "remove_mock_location_flag": { - "name": "Elimină indicatorul de locație falsă", - "description": "Împiedică Snapchat să detecteze locația falsă" + "auto_backup_current_account": { + "description": "Face automat o copie de rezervă a contului curent la deconectare sau la schimbarea contului", + "name": "Backup automat pentru contul curent" } - } + }, + "name": "Comutator de cont" }, "convert_message_locally": { - "name": "Convertește mesajul local", - "description": "Convertește Snap-urile în media externă local. Aceasta apare în meniul contextual de descărcare din chat" + "description": "Transformă snapurile în chat media externă local. Aceasta apare în meniul contextual de descărcare prin chat", + "name": "Convertiți mesajul local" + }, + "meo_passcode_bypass": { + "name": "Ocolire Cod de Acces pentru \"Doar pentru ochii mei\"", + "description": "Ocolirea codului de acces pentru \"Doar pentru ochii mei\"\nAceasta va funcționa doar dacă codul de acces a fost introdus corect anterior" + }, + "spoof": { + "properties": { + "remove_vpn_transport_flag": { + "name": "Elimină Indicatorul de Transport VPN", + "description": "Împiedică Snapchat să detecteze VPN-urile" + }, + "remove_mock_location_flag": { + "description": "Previne detectarea de către Snapchat a locației false", + "name": "Elimină Indicatorul de Locație Falsă" + }, + "play_store_installer_package_name": { + "name": "Numele pachetului de instalare a magazinului Play", + "description": "Înlocuiește numele pachetului de instalare la com.android.vending" + } + }, + "name": "Falsifică", + "description": "Falsifică diverse informații despre tine" + }, + "native_hooks": { + "properties": { + "disable_bitmoji": { + "description": "Dezactivează Bitmoji-ul Profilului Prietenilor", + "name": "Dezactivează Bitmoji" + }, + "composer_hooks": { + "name": "Ganți Composer", + "properties": { + "composer_console": { + "description": "Permite executarea de cod JavaScript în Composer (doar pentru arhitectura arm64)", + "name": "Consolă Composer" + }, + "composer_logs": { + "name": "Jurnalele Composer", + "description": "Redirecționează jurnalele consolei Composer către SnapEnhance" + }, + "bypass_camera_roll_limit": { + "description": "Crește cantitatea maximă de media pe care o poți trimite din Ruloul Camerei", + "name": "Ocolește Limita Ruloului Camerei" + }, + "show_first_created_username": { + "name": "Afișează primul nume de utilizator creat", + "description": "Afișează primul nume de utilizator creat lângă numele de utilizator actual în pagina de profil" + } + }, + "description": "Injectează cod în framework-ul UI cross-platform Composer" + } + }, + "name": "Hook-uri Native(Un set de funcții încorporate care permit dezvoltatorilor să adauge funcționalități la componente)", + "description": "Caracteristici nesigure care se leagă de codul nativ al Snapchat-ului" }, "media_file_picker": { - "name": "Selector de fișiere media", + "name": "Selector de Fișiere Media", "description": "Vă permite să alegeți orice fișier video/audio din galerie" }, "story_logger": { - "name": "Jurnal de povești", - "description": "Oferă un istoric al poveștilor prietenilor" + "description": "Oferă o istorie a poveștilor prietenilor", + "name": "Înregistrare Poveste" }, - "call_recorder": { - "name": "Înregistrator de apeluri", - "description": "Înregistrează automat apelurile audio" + "edit_message": { + "description": "Vă permite să editați mesaje în conversații", + "name": "Editați mesajele" }, - "account_switcher": { - "name": "Comutator de cont", - "description": "Vă permite să comutați între conturi fără a vă deconecta\nApăsați lung pe pictograma de căutare de lângă profilul Bitmoji pentru a deschide meniul\nNotă: Această funcție este experimentală și se va schimba probabil în viitor", + "e2ee": { + "description": "Criptează mesajele dumneavoastră cu AES folosind o cheie secretă partajată\nAsigurați-vă că păstrați cheia într-un loc sigur!", "properties": { - "auto_backup_current_account": { - "name": "Backup automat pentru contul curent", - "description": "Faceți o copie de rezervă automată a contului curent la deconectarea sau comutarea conturilor" - } - } - }, - "better_transcript": { - "name": "Transcriere mai bună", - "description": "Îmbunătățește transcrierea notelor vocale", - "properties": { - "force_transcription": { - "name": "Forțează transcrierea notelor vocale", - "description": "Permite transcrierea tuturor notelor vocale" + "force_message_encryption": { + "description": "Împiedică trimiterea de mesaje criptate către persoane care nu au criptarea E2E activată numai atunci când sunt selectate mai multe conversații", + "name": "Forțați criptarea mesajelor" }, - "preferred_transcription_lang": { - "name": "Limba de transcriere preferată", - "description": "Limba preferată pentru transcrierea notelor vocale (de ex., RO, EN, ES, FR)" - }, - "notification_transcript": { - "name": "Transcriere în notificare", - "description": "Transcrie notele vocale în notificări\nAceastă funcție necesită activarea funcției de previzualizare a chat-ului în Notificări mai bune" + "encrypted_message_indicator": { + "name": "Indicator de mesaj criptat", + "description": "Adaugă un emoji 🔒 lângă mesajele criptate" } - } + }, + "name": "Criptare End-To-End" }, - "voice_note_auto_play": { - "name": "Redare automată a notelor vocale", - "description": "Redă automat următoarea notă vocală după ce se termină cea curentă" + "add_friend_source_spoof": { + "description": "Falsifică sursa unei solicitări de prietenie", + "name": "Falsificare Sursă Adăugare Prieten" }, - "friend_notes": { - "name": "Note prieten", - "description": "Vă permite să adăugați note la profilurile prietenilor" + "hidden_snapchat_plus_features": { + "name": "Funcții ascunse Snapchat Plus", + "description": "Activează funcțiile Snapchat Plus nelansate/beta\nEste posibil să nu funcționeze pe versiunile mai vechi Snapchat" }, - "cof_experiments": { - "name": "Experimente COF", - "description": "Activează funcții Snapchat nelansate/beta" - }, - "context_menu_fix": { - "name": "Remediere meniu contextual", - "description": "Încearcă să remediezi meniul din feed-ul prietenilor, deoarece atunci când dispozitivul este offline, este posibil să nu se afișeze corect" + "no_friend_score_delay": { + "name": "Nicio întârziere a scorului prietenului", + "description": "Elimină întârzierea la vizualizarea unui scor al prietenilor" }, "app_lock": { "name": "Blocare aplicație", - "description": "Împiedică accesul la Snapchat fără o parolă", + "description": "Împiedică accesul la Snapchat fără un cod de acces", "properties": { "lock_on_resume": { - "name": "Blochează la reluare", + "name": "Blocare la Reluare", "description": "Blochează aplicația când este redeschisă" } } }, - "infinite_story_boost": { - "name": "Boost infinit pentru povești", - "description": "Ocolește limita de timp pentru boost-ul poveștilor" + "prevent_forced_logout": { + "name": "Preveniți deconectarea forțată", + "description": "Împiedică Snapchat să vă deconecteze atunci când vă conectați pe alt dispozitiv" }, - "meo_passcode_bypass": { - "name": "Ocolire parolă Doar Ochii Mei", - "description": "Ocolește parola pentru Doar Ochii Mei\nAcest lucru va funcționa numai dacă parola a fost introdusă corect înainte" - }, - "no_friend_score_delay": { - "name": "Fără întârziere scor prieten", - "description": "Elimină întârzierea la vizualizarea scorului unui prieten" - }, - "best_friend_pinning": { - "name": "Fixare cel mai bun prieten", - "description": "Vă permite să fixați un prieten ca cel mai bun prieten numărul unu. Notă: Doar tu poți vedea cel mai bun prieten fixat" - }, - "e2ee": { - "name": "Criptare end-to-end", - "description": "Criptează mesajele cu AES folosind o cheie secretă partajată\nAsigurați-vă că vă salvați cheia undeva în siguranță!", - "properties": { - "encrypted_message_indicator": { - "name": "Indicator mesaj criptat", - "description": "Adaugă un emoji 🔒 lângă mesajele criptate" - }, - "force_message_encryption": { - "name": "Forțează criptarea mesajelor", - "description": "Împiedică trimiterea de mesaje criptate către persoanele care nu au criptarea E2E activată numai atunci când sunt selectate mai multe conversații" - } - } - }, - "add_friend_source_spoof": { - "name": "Falsificare sursă adăugare prieten", - "description": "Falsifică sursa unei cereri de prietenie" - }, - "hidden_snapchat_plus_features": { - "name": "Funcții ascunse Snapchat Plus", - "description": "Activează funcții nelansate/beta Snapchat Plus\nS-ar putea să nu funcționeze la versiunile mai vechi de Snapchat" + "call_recorder": { + "name": "Înregistrare Apeluri", + "description": "Înregistrează automat apelurile audio" }, "custom_streaks_expiration_format": { - "name": "Format personalizat de expirare a seriilor", - "description": "Personalizează formatul de expirare a seriilor\n\nVariabile disponibile:\n - %c: număr de serii\n - %e: emoji de clepsidră\n - %d: zile\n - %h: ore\n - %m: minute\n - %s: secunde\n - %t: timpul rămas" + "name": "Format personalizat de expirare a liniilor fierbinți", + "description": "Personalizează formatul Streaks Expiration\n\nVariabile disponibile:\n- %c: Număr de linii\n- %e: Emoji cu clepsidra\n- %d: zile\n- %h: ore\n- %m: minute\n- %s: secunde\n- %w: Timp rămas" }, - "prevent_forced_logout": { - "name": "Previne deconectarea forțată", - "description": "Împiedică Snapchat să vă deconecteze atunci când vă autentificați pe un alt dispozitiv" - }, - "snapscore_changes": { - "name": "Modificări Snapscore", - "description": "Urmărește modificările în Snapscore-ul prietenilor\nUtilizați această funcție doar în versiuni mai noi de Snapchat" + "best_friend_pinning": { + "name": "Fixarea celui mai bun prieten", + "description": "Vă permite să fixați un prieten drept cel mai bun prieten numărul unu. Notă: numai tu poți să-ți vezi cel mai bun prieten fixat" } - } + }, + "description": "Caracteristici experimentale", + "name": "Experimentale" }, "scripting": { - "name": "Scripting", - "description": "Rulează scripturi personalizate pentru a extinde PurrfectSnap", + "name": "Scriptare", "properties": { - "developer_mode": { - "name": "Modul dezvoltator", - "description": "Afișează informații de depanare pe UI Snapchat" - }, - "module_folder": { - "name": "Folder module", - "description": "Folderul în care se află scripturile" - }, - "auto_reload": { - "name": "Reîncărcare automată", - "description": "Reîncărcați automat scripturile atunci când se schimbă" - }, "integrated_ui": { - "name": "UI integrată", + "name": "Interfață de utilizare integrată", "description": "Permite scripturilor să adauge componente UI personalizate la Snapchat" }, + "auto_reload": { + "description": "Reîncarcă automat scripturile când se schimbă", + "name": "Reîncărcare automată" + }, + "module_folder": { + "description": "Dosarul în care se află scripturile", + "name": "Folderul modulului" + }, "disable_log_anonymization": { - "name": "Dezactivează anonimizarea jurnalului", + "name": "Dezactivați anonimizarea jurnalului", "description": "Dezactivează anonimizarea jurnalelor" }, - "disable_optimization": { - "name": "Dezactivează optimizarea", - "description": "Dezactivează optimizarea scripturilor. Acest lucru poate cauza probleme de performanță." + "developer_mode": { + "name": "Modul dezvoltator", + "description": "Afișează informații de depanare pe interfața de utilizare a Snapchat" } - } - }, - "friend_tracker": { - "name": "Friend Tracker", - "description": "Înregistrează activitatea prietenilor pe Snapchat", - "properties": { - "record_messaging_events": { - "name": "Înregistrează evenimente de mesagerie", - "description": "Înregistrează evenimente de mesagerie, cum ar fi deschiderea unui Snap, citirea unui mesaj etc." - }, - "allow_running_in_background": { - "name": "Permite rularea în fundal", - "description": "Permite tracker-ului să ruleze în fundal. Notă: Acest lucru va consuma semnificativ bateria" - }, - "auto_purge": { - "name": "Curățare automată", - "description": "Șterge automat evenimentele din cache care sunt mai vechi decât perioada de timp specificată" - } - } + }, + "description": "Rulați scripturi personalizate pentru a extinde SnapEnhance" } }, + "notices": { + "ban_risk": "⚠ Această funcție poate provoca interdicții ale conului de Snapchat", + "internal_behavior": "⚠ Acest lucru poate rupe comportamentul intern al Snapchat", + "unstable": "⚠ Instabil" + }, "options": { - "app_appearance": { - "always_light": "Întotdeauna luminos", - "always_dark": "Întotdeauna întunecat" - }, "friend_feed_menu_buttons": { + "mark_stories_as_seen_locally": "👀 Marchează Poveștile ca fiind văzute local", "auto_download": "⬇️ Descărcare automată", - "auto_save": "💬 Salvare automată mesaje", - "unsaveable_messages": "⬇️ Mesaje nesalvabile", - "auto_open_snaps": "📷 Deschidere automată Snap-uri", - "stealth": "👻 Mod invizibil", - "mark_snaps_as_seen": "👀 Marchează Snap-urile ca văzute", - "mark_stories_as_seen_locally": "👀 Marchează poveștile ca văzute local", - "conversation_info": "👤 Informații conversație", - "e2e_encryption": "🔒 Utilizează criptarea E2E" + "auto_save": "💬 Salvare automată a mesajelor", + "mark_snaps_as_seen": "👀 Marchează Snap-ul ca fiind văzut", + "conversation_info": "👤 Informații despre conversație", + "e2e_encryption": "🔒 Utilizați criptarea E2E", + "stealth": "👻 Modul Furt", + "unsaveable_messages": "⬇️ Mesaje care nu pot fi salvate", + "auto_open_snaps": "📷 Deschidere automată a Snapurilor" + }, + "logging": { + "success": "Succes", + "started": "Pornit", + "progress": "Progres", + "failure": "Eșec" + }, + "strip_media_metadata": { + "remove_audio_note_transcript_capability": "Eliminați capacitatea de transcriere a notelor audio", + "hide_caption_text": "Ascunde textul subtitrării", + "hide_snap_filters": "Ascunde filtrele Snap", + "hide_extras": "Ascundeți extra (de exemplu, mențiuni)", + "remove_audio_note_duration": "Eliminare Durată Notă Audio" + }, + "disable_confirmation_dialogs": { + "clear_conversation": "Șterge Conversația din Feed-ul de Prieteni", + "hide_conversation": "Ascunde conversația", + "hide_friend": "Ascunde prietenul", + "ignore_friend": "Ignora prietenul", + "remove_friend": "Șterge prieten", + "block_friend": "Blocați prietenul", + "erase_message": "Șterge mesajul" + }, + "auto_reload": { + "snapchat_only": "Numai Snapchat", + "all": "Toate (Snapchat + SnapEnhance)" + }, + "auto_purge": { + "1_month": "1 Lună", + "2_weeks": "2 Săptămâni", + "6_hours": "6 Ore", + "1_day": "1 Zi", + "3_days": "3 Zile", + "3_months": "3 Luni", + "1_week": "1 Săptămână", + "6_months": "6 Luni", + "never": "Niciodată", + "1_hour": "1 Oră", + "3_hours": "3 Ore", + "12_hours": "12 Ore" + }, + "disable_permission_requests": { + "microphone": "Microfon", + "location": "Locație", + "notifications": "Notificări", + "read_media_images": "Citiți imagini media", + "camera": "Cameră", + "read_media_video": "Citiți videoclipul media", + "phone_calls": "Apeluri telefonice", + "read_contacts": "Citească Contactele", + "nearby_devices": "Dispozitive din apropiere" + }, + "notifications": { + "chat_screenshot": "Captură de ecran", + "stories": "Povești", + "chat_reaction": "Reacție în privat", + "typing": "Scrie", + "chat": "Conversație", + "chat_reply": "Răspuns la conversație", + "initiate_audio": "Apel audio primit", + "group_chat_reaction": "Reacția de grup", + "snap": "Snap", + "abandon_audio": "Apel audio pierdut", + "initiate_video": "Apel video primit", + "chat_screen_record": "Înregistrare ecran", + "snap_replay": "Redare Repetată a Snap-ului", + "camera_roll_save": "Salvare în Rola de Cameră", + "abandon_video": "Apel video pierdut" }, "path_format": { - "create_author_folder": "Creează folder pentru fiecare autor", - "create_source_folder": "Creează folder pentru fiecare tip de sursă media", - "append_hash": "Adaugă un hash unic la numele fișierului", - "append_source": "Adaugă sursa media la numele fișierului", - "append_username": "Adaugă numele de utilizator la numele fișierului", - "append_date_time": "Adaugă data și ora la numele fișierului" + "create_author_folder": "Creați un folder pentru fiecare autor", + "create_source_folder": "Creați un folder pentru fiecare tip de sursă media", + "append_source": "Adăugați sursa media la numele fișierului", + "append_hash": "Adăugați un hash unic la numele fișierului", + "append_username": "Adăugați numele de utilizator la numele fișierului", + "append_date_time": "Adăugați data și ora la numele fișierului" }, "auto_download_sources": { - "friend_snaps": "Snap-uri de la prieteni", + "friend_snaps": "Snap-uri de la Prieteni", "friend_stories": "Povești de la prieteni", "public_stories": "Povești publice", "spotlight": "Spotlight" }, - "logging": { - "started": "A început", - "success": "Succes", - "progress": "Progres", - "failure": "Eșec" - }, - "notifications": { - "chat_screenshot": "Captură de ecran", - "chat_screen_record": "Înregistrare ecran", - "snap_replay": "Reluare Snap", - "camera_roll_save": "Salvare în galeria camerei", - "chat": "Chat", - "chat_reply": "Răspuns la chat", - "snap": "Snap", - "typing": "Scrie", - "stories": "Povești", - "speaking": "Vorbește", - "chat_reaction": "Reacție DM", - "group_chat_reaction": "Reacție de grup", - "initiate_audio": "Apel audio primit", - "abandon_audio": "Apel audio pierdut", - "initiate_video": "Apel video primit", - "abandon_video": "Apel video pierdut", - "map_live_location": "Locație live pe hartă" - }, - "gallery_media_send_override": { - "always_ask": "Întreabă întotdeauna", - "ORIGINAL": "Media originală", - "NOTE": "Notă audio", - "SNAP": "Snap", - "SAVEABLE_SNAP": "Salvabil" - }, - "strip_media_metadata": { - "hide_caption_text": "Ascunde textul legendei", - "hide_snap_filters": "Ascunde filtrele Snap", - "hide_extras": "Ascunde extra (de ex., mențiuni)", - "remove_audio_note_duration": "Elimină durata notei audio", - "remove_audio_note_transcript_capability": "Elimină capacitatea de transcriere a notelor audio" - }, "hide_ui_components": { - "hide_profile_call_buttons": "Elimină butoanele de apel din profil", - "hide_chat_call_buttons": "Elimină butoanele de apel din chat", - "hide_live_location_share_button": "Elimină butonul de partajare a locației live", - "hide_stickers_button": "Elimină butonul de stickere", - "hide_voice_record_button": "Elimină butonul de înregistrare vocală", - "hide_unread_chat_hint": "Elimină indiciul de chat necitit", - "hide_post_to_story_buttons": "Elimină butoanele Postează în poveste înainte de a trimite un Snap", - "hide_billboard_prompt": "Elimină promptul Billboard din feed-ul prietenilor", - "hide_snapchat_plus_gift_reminders": "Elimină memento-urile de cadouri Snapchat Plus din conversații", - "hide_map_reactions": "Elimină reacțiile de pe hartă" + "hide_live_location_share_button": "Eliminați butonul de distribuire a locației live", + "hide_stickers_button": "Eliminare Butonul de Stickere", + "hide_unread_chat_hint": "Elimină Sugerarea de Chaturi Necitite", + "hide_profile_call_buttons": "Eliminați butoanele de apel din profil", + "hide_chat_call_buttons": "Eliminați butoanele de apel din conversație", + "hide_voice_record_button": "Eliminați butonul de înregistrare vocală" }, "hide_story_suggestions": { - "hide_suggested_friend_stories": "Ascunde poveștile sugerate de prieteni", - "hide_my_stories": "Ascunde poveștile mele" + "hide_suggested_friend_stories": "Ascunde poveștile prietenilor sugerați", + "hide_my_stories": "Ascunde-mi poveștile" }, "home_tab": { - "map": "Hartă", - "chat": "Chat", - "camera": "Cameră", "discover": "Descoperă", - "spotlight": "Spotlight" + "spotlight": "Spotlight", + "chat": "Conversație", + "camera": "Cameră", + "map": "Hartă" }, "add_friend_source_spoof": { - "added_by_username": "Prin nume de utilizator", - "added_by_mention": "Prin mențiune", - "added_by_group_chat": "Prin chat de grup", - "added_by_qr_code": "Prin cod QR", - "added_by_community": "Prin comunitate", - "added_by_quick_add": "Prin adăugare rapidă (risc ridicat de a fi interzis)" - }, - "bypass_video_length_restriction": { - "single": "Media unică", - "split": "Media împărțită" - }, - "old_bitmoji_selfie": { - "2d": "Bitmoji 2D", - "3d": "Bitmoji 3D" - }, - "disable_confirmation_dialogs": { - "erase_message": "Șterge mesajul", - "remove_friend": "Elimină prietenul", - "block_friend": "Blochează prietenul", - "ignore_friend": "Ignoră prietenul", - "hide_friend": "Ascunde prietenul", - "hide_conversation": "Ascunde conversația", - "clear_conversation": "Golește conversația din feed-ul prietenilor" - }, - "auto_reload": { - "snapchat_only": "Doar Snapchat", - "all": "Toate (Snapchat + PurrfectSnap)" - }, - "edit_text_override": { - "multi_line_chat_input": "Intrare de chat pe mai multe rânduri", - "bypass_text_input_limit": "Ocolește limita de intrare a textului" - }, - "auto_purge": { - "never": "Niciodată", - "1_hour": "1 oră", - "3_hours": "3 ore", - "6_hours": "6 ore", - "12_hours": "12 ore", - "1_day": "1 zi", - "3_days": "3 zile", - "1_week": "1 săptămână", - "2_weeks": "2 săptămâni", - "1_month": "1 lună", - "3_months": "3 luni", - "6_months": "6 luni" + "added_by_username": "După numele de utilizator", + "added_by_mention": "După mențiune", + "added_by_qr_code": "După codul QR", + "added_by_group_chat": "După conversația de grup", + "added_by_community": "După comunitate" }, "disable_story_sections": { "friends": "Prieteni", - "suggested_stories": "Povești sugerate", - "following": "Urmăriți", + "following": "Urmărire", "discover": "Descoperă" }, "disable_cameras": { "front": "Camera frontală", "back": "Camera din spate" }, - "disable_permission_requests": { - "notifications": "Notificări", - "read_media_images": "Citește imagini media", - "read_media_video": "Citește video media", - "camera": "Cameră", - "microphone": "Microfon", - "location": "Locație", - "read_contacts": "Citește contacte", - "nearby_devices": "Dispozitive din apropiere", - "phone_calls": "Apeluri telefonice" - }, "message_indicators": { - "encryption_indicator": "Adaugă o pictogramă 🔒 lângă mesajele care ți-au fost trimise doar ție", - "platform_indicator": "Adaugă pictograma platformei de pe care a fost trimis un fișier media (de ex., Android, iOS, Web)", - "location_indicator": "Adaugă o pictogramă 📍 la Snap-uri atunci când au fost trimise cu locația activată", - "ovf_editor_indicator": "Indică dacă un Snap a fost trimis folosind editorul OVF", - "director_mode_indicator": "Adaugă o pictogramă ✏️ la Snap-uri atunci când au fost trimise folosind Modul Regizor, care poate fi utilizat pentru a trimite imagini din galerie ca Snap-uri" + "encryption_indicator": "Adaugă o pictogramă 🔒 lângă mesajele care au fost trimise numai ție", + "ovf_editor_indicator": "Indică dacă a fost trimis un snap folosind Editorul OVF", + "director_mode_indicator": "Adaugă o pictogramă ✏️ la snap-uri atunci când acestea au fost trimise folosind modul Director, care poate fi folosit pentru a trimite imaginile galeriei ca instantanee", + "platform_indicator": "Adaugă pictograma platformei de pe care a fost trimis un conținut media (de exemplu, Android, iOS, Web)", + "location_indicator": "Adaugă o pictogramă 📍 la snap-uri atunci când acestea au fost trimise cu locația activată" + }, + "gallery_media_send_override": { + "SNAP": "Snap", + "ORIGINAL": "Original", + "NOTE": "Notă audio", + "always_ask": "Intreaba mereu" + }, + "app_appearance": { + "always_light": "Întotdeauna Luminat", + "always_dark": "Întotdeauna întunecat" + }, + "edit_text_override": { + "multi_line_chat_input": "Intrare conversație pe mai multe linii", + "bypass_text_input_limit": "Ocoliți limita de introducere a textului" + }, + "old_bitmoji_selfie": { + "2d": "Bitmoji 2D", + "3d": "Bitmoji 3D" + }, + "bypass_video_length_restriction": { + "single": "Media unică", + "split": "Împărțiți media" }, "auto_mark_as_read": { - "conversation_read": "Marchează conversația ca citită când trimiți un mesaj", - "snap_reply": "Marchează Snap-urile ca citite când le răspunzi", - "save_snap_in_chat": "Marchează Snap-urile ca citite când le salvezi în chat în timp ce ești în modul Invizibil" + "conversation_read": "Marcați conversația ca citită atunci când trimiteți un mesaj", + "snap_reply": "Marchează snap-urile ca citite când răspunzi la ele" }, "friend_mutation_notifier": { - "remove_friend": "Anunță când cineva te elimină ca prieten", - "birthday_changes": "Anunță când cineva își schimbă ziua de naștere", - "bitmoji_selfie_changes": "Anunță când cineva își schimbă selfie-ul Bitmoji", - "bitmoji_avatar_changes": "Anunță când cineva își schimbă avatarul Bitmoji", - "bitmoji_background_changes": "Anunță când cineva își schimbă fundalul Bitmoji", - "bitmoji_scene_changes": "Anunță când cineva își schimbă scena Bitmoji" - }, - "snapchat_plus": { - "not_subscribed": "Neabonat", - "basic": "De bază", - "ad_free": "Fără reclame" - }, - "double_tap_chat_action": { - "like_message": "Apreciază mesajul", - "copy_text": "Copiază textul în clipboard", - "delete_message": "Șterge mesajul", - "mark_as_read": "Marchează ca citit", - "custom_emoji_reaction": "Reacție emoji personalizată" - }, - "startup_default_camera": { - "front": "Camera frontală", - "back": "Camera din spate" + "remove_friend": "Notifică când cineva te șterge din lista de prieteni", + "birthday_changes": "Notifică când cineva își schimbă data de naștere", + "bitmoji_avatar_changes": "Notifică când cineva își schimbă avatarul Bitmoji", + "bitmoji_background_changes": "Notifică când cineva își schimbă fundalul Bitmoji", + "bitmoji_scene_changes": "Notifică când cineva își schimbă scena Bitmoji", + "bitmoji_selfie_changes": "Notifică când cineva își schimbă selfie-ul Bitmoji" } } }, - "friend_menu_option": { - "mark_snaps_as_seen": "Marchează Snap-urile ca văzute", - "mark_stories_as_seen_locally": "Marchează poveștile ca văzute local", - "preview": "Previzualizare", - "stealth_mode": "Mod invizibil", - "auto_download_blacklist": "Listă neagră pentru descărcare automată", - "anti_auto_save": "Anti-salvare automată" + "scopes": { + "friend": "Prieten", + "group": "Grup" + }, + "actions": { + "export_memories": { + "name": "Exportați Amintirile", + "description": "Exportă amintirile într-un fișier ZIP" + }, + "export_chat_messages": { + "name": "Exportați mesajele de chat", + "description": "Exportă mesajele de conversație într-un fișier JSON/HTML/TXT" + }, + "manage_friend_list": { + "name": "Gestionați lista de prieteni", + "description": "Importați/exportați lista de prieteni când faceți backup" + }, + "clean_snapchat_cache": { + "name": "Golire memorie temporară Snapchat", + "description": "Curățați memoria temporară de la Snapchat" + }, + "bulk_messaging_action": { + "name": "Acțiune de Trimitere în Masă a Mesajelor", + "description": "Efectuează operațiuni precum ștergerea prietenilor sau ștergerea în masă a conversațiilor" + }, + "regen_mappings": { + "description": "Regenerați manual mapările", + "name": "Regenerați mapările" + }, + "change_language": { + "name": "Schimbă limba", + "description": "Schimbați limba SnapEnhance" + } }, "content_type": { - "CHAT": "Chat", - "SNAP": "Snap", "EXTERNAL_MEDIA": "Media externă", "NOTE": "Notă audio", - "STICKER": "Sticker", - "SHARE": "Partajare", + "SNAP": "Snap", + "FAMILY_CENTER_ACCEPT": "Centrul de familie Accept", + "FAMILY_CENTER_LEAVE": "Părăsirea Centrului Familial", "STATUS": "Stare", "LOCATION": "Locație", - "STATUS_SAVE_TO_CAMERA_ROLL": "Salvat în galeria camerei", + "STATUS_SAVE_TO_CAMERA_ROLL": "Salvat în camera foto", + "FAMILY_CENTER_INVITE": "Invitație la Centrul Familiei", + "CHAT": "Conversație", + "STICKER": "Autocolant", + "CREATIVE_TOOL_ITEM": "Element Instrument Creativ", "STATUS_CONVERSATION_CAPTURE_SCREENSHOT": "Captură de ecran", - "STATUS_CONVERSATION_CAPTURE_RECORD": "Înregistrare ecran", "STATUS_CALL_MISSED_VIDEO": "Apel video pierdut", "STATUS_CALL_MISSED_AUDIO": "Apel audio pierdut", - "LIVE_LOCATION_SHARE": "Partajare locație live", - "CREATIVE_TOOL_ITEM": "Element instrument creativ", - "FAMILY_CENTER_INVITE": "Invitație centru familial", - "FAMILY_CENTER_ACCEPT": "Acceptare centru familial", - "FAMILY_CENTER_LEAVE": "Părăsire centru familial", + "LIVE_LOCATION_SHARE": "Distribuirea locației live", + "STATUS_CONVERSATION_CAPTURE_RECORD": "Înregistrare ecran", "STATUS_PLUS_GIFT": "Cadou Status Plus", - "TINY_SNAP": "Snap mic", + "TINY_SNAP": "Snap Mic", "STATUS_COUNTDOWN": "Numărătoare inversă", - "MAP_REACTION": "Reacție pe hartă" + "MAP_REACTION": "Reacția pe hartă" }, "media_download_source": { - "none": "Niciuna", - "pending": "În așteptare", - "chat_media": "Media din chat", - "story": "Poveste", - "public_story": "Poveste publică", - "spotlight": "Spotlight", "profile_picture": "Poză de profil", - "story_logger": "Jurnal de povești", - "message_logger": "Jurnal de mesaje", + "chat_media": "Conversație Media", + "none": "Niciuna", + "story_logger": "Înregistrare Poveste", + "message_logger": "Mesaje înregistrate", "merged": "Îmbinat", - "voice_call": "Apel vocal" - }, - "chat_action_menu": { - "preview_button": "Previzualizare", - "download_button": "Descărcare", - "delete_logged_message_button": "Șterge mesajul înregistrat", - "show_chat_edit_history": "Afișează istoricul de editare al chat-ului", - "convert_message": "Convertește mesajul" + "voice_call": "Apel vocal", + "pending": "În așteptare", + "story": "Poveste", + "public_story": "Povestea publică", + "spotlight": "Lumea snapchat" }, "opera_context_menu": { - "download": "Descărcare media", + "download": "Descărcați Media", "sent_at": "Trimis la {date}", + "media_duration": "Durata media: {duration} milisecunde", "created_at": "Creat la {date}", "expires_at": "Expiră la {date}", "media_size": "Dimensiune media: {size}", - "media_duration": "Durată media: {duration} ms", - "show_debug_info": "Afișează informații de depanare" - }, - "modal_option": { - "profile_info": "Informații profil", - "close": "Închide" - }, - "gallery_media_send_override": { - "multiple_media_toast": "Puteți trimite doar un singur fișier media odată" + "show_debug_info": "Afișați informațiile de depanare" }, "mark_as_seen": { - "no_unseen_snaps_toast": "Nu s-au găsit Snap-uri nevăzute!", + "no_unseen_snaps_toast": "Nu s-au găsit snap-uri nevăzute!", "seen_toast": "Marcat ca văzut!", "unseen_toast": "Marcat ca nevăzut!", "already_seen_toast": "Deja marcat ca văzut!", "already_unseen_toast": "Deja marcat ca nevăzut!" }, - "conversation_preview": { - "streak_expiration": "expiră în {day} zile, {hour} ore, {minute} minute", - "total_messages": "Total mesaje trimise/primite: {count}", - "title": "Previzualizare", - "unknown_user": "Utilizator necunoscut", - "no_messages": "Nu s-au găsit mesaje!" + "end_to_end_encryption": { + "accept_public_key_failure_toast": "Nu s-a acceptat cheia publică", + "outgoing_pk_message": "Cerere de schimb de chei", + "outgoing_secret_message": "Răspuns la schimbul de chei", + "confirmation_dialogs": { + "title": "Criptare Final-Spre-Final", + "confirmation_2": "Ești CHIAR sigur că vrei să continui? Aceasta este ultima ta șansă să dai înapoi.", + "confirmation_1": "AVERTISMENT: Aceasta va suprascrie cheia existentă. Veți pierde accesul la toate mesajele criptate de la acest prieten. Ești sigur ca vrei să continui?" + }, + "toolbox": { + "shared_key_fingerprint": "Amprenta ta este:\n\n{amprentă}\n\nAsigurați-vă că verificați dacă se potrivește cu amprenta prietenului dumneavoastră!", + "no_shared_key": "Încă nu aveți un secret împărtășit cu acest prieten. Faceți clic mai jos pentru a iniția unul nou.", + "initiate_exchange_button": "Inițiați schimbul de chei" + }, + "no_participants_to_encrypt_toast": "Nu aveți prieteni în această conversație cu care să criptați mesajele!", + "encryption_failed_toast": "Nu s-a putut cripta mesajul! Verificați mesajele din log pentru mai multe detalii.", + "accept_secret_key_success_toast": "Terminat! Acum puteți trimite și primi mesaje criptate cu acest prieten.", + "accept_secret_key_failure_toast": "Nu s-a acceptat cheia secretă", + "unencrypted_conversation_send_failure_toast": "Nu puteți trimite conținut criptat atât la conversații criptate, cât și la conversații necriptate!", + "native_hooks_send_failure_toast": "Trimitere eșuată! Vă rugăm să activați Hook-urile Native în setările aplicației.", + "accept_secret_button": "Acceptați Secretul", + "incoming_pk_message": "Tocmai ați primit o solicitare de cheie publică. Faceți clic mai jos pentru a o accepta.", + "incoming_secret_message": "Prietenul tău tocmai a acceptat cheia ta publică. Faceți clic mai jos pentru a accepta secretul.", + "accept_public_key_success_toast": "Cheie publică acceptată cu succes!", + "accept_public_key_button": "Acceptați cheia publică" }, - "profile_info": { - "title": "Informații profil", - "first_created_username": "Primul nume de utilizator creat", - "mutable_username": "Nume de utilizator mutabil", - "display_name": "Nume afișat", - "added_date": "Data adăugării", - "birthday": "Zi de naștere: {day} {month}", - "hidden_birthday": "Zi de naștere: ascunsă", - "friendship": "Prietenie", - "add_source": "Sursă adăugare", - "snapchat_plus": "Snapchat Plus", - "snapchat_plus_state": { - "subscribed": "Abonat", - "not_subscribed": "Neabonat" - } + "material3_strings": { + "date_range_input_invalid_range_input": "Interval de date nevalid", + "date_range_picker_scroll_to_next_month": "Luna viitoare", + "date_input_invalid_for_pattern": "Dată nevalidă", + "date_range_picker_day_in_range": "Selectat", + "date_input_invalid_year_range": "An invalid", + "date_range_picker_end_headline": "La", + "date_range_picker_start_headline": "De la", + "date_range_picker_title": "Selectați intervalul de date", + "date_picker_switch_to_calendar_mode": "Agendă", + "date_picker_switch_to_input_mode": "Intrare", + "date_range_picker_scroll_to_previous_month": "Luna trecută", + "date_picker_today_description": "Azi", + "date_input_invalid_not_allowed": "Data invalidă" + }, + "chat_action_menu": { + "preview_button": "Previzualizare", + "download_button": "Descarcă", + "delete_logged_message_button": "Ștergeți mesajul salvat", + "convert_message": "Convertiți mesajul", + "edit_message": "Editați mesajul" }, "friendship_link_type": { "mutual": "Reciproc", - "outgoing": "Trimis", - "blocked": "Blocat", + "outgoing": "De ieșire", "deleted": "Șters", - "following": "Urmărit", - "suggested": "Sugerată", - "incoming": "Primit", - "incoming_follower": "Urmăritor primit" + "incoming_follower": "Abonat primit", + "incoming": "Primire", + "blocked": "Blocat", + "suggested": "Sugerat", + "following": "Urmărești" }, "bulk_messaging_action": { - "choose_action_title": "Alege o acțiune", - "progress_status": "Se procesează {index} din {total}", - "selection_dialog_continue_button": "Continuă", "confirmation_dialog": { "title": "Ești sigur?", "message": "Acest lucru va afecta toți prietenii selectați. Această acțiune nu poate fi anulată." }, "actions": { - "remove_friends": "Elimină prietenii", - "clear_conversations": "Golește conversațiile" - } - }, - "chat_export": { - "exporter_dialog": { - "select_conversations_title": "Selectează conversații", - "text_field_selection": "{count} selectate", - "text_field_selection_all": "Toate", - "export_file_format_title": "Format fișier de export", - "message_type_filter_title": "Filtrează mesajele după tip", - "amount_of_messages_title": "Numărul de mesaje (lăsați necompletat pentru toate)", - "download_medias_title": "Descărcare media" + "remove_friends": "Eliminați prietenii", + "clear_conversations": "Ștergeți conversațiile" }, - "dialog_negative_button": "Anulează", - "dialog_positive_button": "Exportă", - "exported_to": "Exportat la {path}", - "exporting_chats": "Se exportă chat-urile...", - "processing_chats": "Se procesează {amount} conversații...", - "export_fail": "Exportul conversației {conversation} a eșuat", - "writing_output": "Se scrie rezultatul...", - "finished": "Gata! Acum poți închide acest dialog.", - "no_messages_found": "Nu s-au găsit mesaje!", - "exporting_message": "Se exportă {message}..." - }, - "button": { - "ok": "OK", - "positive": "Da", - "negative": "Nu", - "cancel": "Anulează", - "open": "Deschide", - "download": "Descărcare", - "send": "Trimite", - "restore_original": "Restaurează originalul", - "convert_external_media": "Convertește media externă", - "save": "Salvează" - }, - "tracker_events": { - "conversation_enter": "A intrat în conversație", - "conversation_exit": "A ieșit din conversație", - "started_typing": "A început să scrie", - "stopped_typing": "S-a oprit din scris", - "started_speaking": "A început să vorbească", - "stopped_speaking": "S-a oprit din vorbit", - "started_peeking": "A început să se uite pe furiș", - "stopped_peeking": "S-a oprit din uitat pe furiș", - "message_read": "Mesaj citit", - "message_deleted": "Mesaj șters", - "message_saved": "Mesaj salvat", - "message_unsaved": "Mesaj nesalvat", - "message_edited": "Mesaj editat", - "message_reaction_add": "Reacție la mesaj adăugată", - "message_reaction_remove": "Reacție la mesaj eliminată", - "snap_opened": "Snap deschis", - "snap_replayed": "Snap reluat", - "snap_replayed_twice": "Snap reluat de două ori", - "snap_screenshot": "Captură de ecran Snap", - "snap_screen_record": "Înregistrare ecran Snap" - }, - "tracker_actions": { - "log": "Jurnal", - "in_app_notification": "Notificare în aplicație", - "push_notification": "Notificare push", - "custom": "Personalizat" + "choose_action_title": "Alegeți o acțiune", + "progress_status": "Se procesează {index} din {total}", + "selection_dialog_continue_button": "Continuă" }, "better_notifications": { "button": { - "reply": "Răspunde", - "download": "Descărcare", - "mark_as_read": "Marchează ca citit" - } - }, - "profile_picture_downloader": { - "button": "Descărcare poză de profil", - "title": "Descărcător de poze de profil", - "avatar_option": "Avatar", - "background_option": "Fundal" - }, - "call_start_confirmation": { - "dialog_title": "Începe apelul", - "dialog_message": "Ești sigur că vrei să începi un apel?" - }, - "half_swipe_notifier": { - "notification_channel_name": "Jumătate de glisare", - "notification_content_dm": "{friend} s-a uitat pe furiș în chat-ul tău timp de {duration} secunde", - "notification_content_group": "{friend} s-a uitat pe furiș în {group} timp de {duration} secunde" - }, - "download_processor": { - "attachment_type": { - "snap": "Snap", - "sticker": "Sticker", - "gif": "GIF", - "external_media": "Media externă", - "note": "Notă", - "original_story": "Poveste originală" - }, - "select_attachments_title": "Selectează atașamente", - "download_started_toast": "Descărcarea a început", - "unsupported_content_type_toast": "Tip de conținut neacceptat!", - "failed_no_longer_available_toast": "Media nu mai este disponibilă", - "no_attachments_toast": "Nu s-au găsit atașamente!", - "already_queued_toast": "Media este deja în coadă!", - "already_downloaded_toast": "Media este deja descărcată!", - "content_saved_toast": "Conținut salvat!", - "download_toast": "Se descarcă {type}...", - "processing_toast": "Se procesează {type}...", - "failed_generic_toast": "Descărcarea a eșuat", - "failed_to_create_preview_toast": "Crearea previzualizării a eșuat", - "failed_processing_toast": "Procesarea a eșuat: {error}", - "failed_gallery_toast": "Salvarea în galerie a eșuat: {error}", - "dash_no_chapter": "Nu s-a găsit niciun capitol", - "dash_dialog": { - "title": "Descărcare media DASH", - "download_all": "Descarcă tot", - "segment_text": "Segment {from} - {to}" + "reply": "Răspundeți", + "download": "Descărcați", + "mark_as_read": "Marcați ca citit" } }, "streaks_reminder": { - "notification_title": "Serii", - "notification_text": "Vei pierde seria cu {friend} în {hoursLeft} ore" + "notification_title": "Linie fierbinte", + "notification_text": "Îți vei pierde linia fierbinte cu {friend} în {hourLeft} ore" + }, + "call_start_confirmation": { + "dialog_message": "Sigur vrei să inițiezi un apel?", + "dialog_title": "Începeți apelul" + }, + "half_swipe_notifier": { + "notification_content_group": "{friend} a trecut pe jumătate în {grup} timp de {durata} secunde", + "notification_channel_name": "Glisare pe jumătate", + "notification_content_dm": "{friend} a trecut pe jumătate în chat-ul tău timp de {durata} secunde" }, "biometric_auth": { - "unlock_button": "Deblochează", + "unlock_button": "Deblocați", "title": "Deblochează Snapchat", - "subtitle": "Te rugăm să te autentifici pentru a debloca Snapchat" + "subtitle": "Vă rugăm să vă autentificați pentru a debloca Snapchat" }, - "end_to_end_encryption": { - "toolbox": { - "no_shared_key": "Încă nu ai o cheie secretă partajată cu acest prieten. Apasă mai jos pentru a iniția una nouă.", - "shared_key_fingerprint": "Amprenta ta este:\n\n{fingerprint}\n\nAsigură-te că verifici dacă se potrivește cu amprenta prietenului tău!", - "initiate_exchange_button": "Inițiază schimbul de chei" - }, - "confirmation_dialogs": { - "title": "Criptare end-to-end", - "confirmation_1": "AVERTISMENT: Aceasta va suprascrie cheia existentă. Vei pierde accesul la toate mesajele criptate de la acest prieten. Ești sigur că vrei să continui?", - "confirmation_2": "Ești absolut sigur că vrei să continui? Aceasta este ultima ta șansă de a te răzgândi." - }, - "unencrypted_conversation_send_failure_toast": "Nu poți trimite conținut criptat atât în conversații criptate, cât și necriptate!", - "native_hooks_send_failure_toast": "Trimiterea a eșuat! Te rugăm să activezi hook-urile native din setări.", - "no_participants_to_encrypt_toast": "Nu ai prieteni în această conversație cu care să criptezi mesaje!", - "encryption_failed_toast": "Criptarea mesajului a eșuat! Verifică LogCat pentru mai multe detalii.", - "accept_public_key_success_toast": "Cheia publică a fost acceptată cu succes!", - "accept_secret_key_success_toast": "Gata! Acum poți trimite și primi mesaje criptate cu acest prieten.", - "accept_public_key_failure_toast": "Acceptarea cheii publice a eșuat", - "accept_secret_key_failure_toast": "Acceptarea cheii secrete a eșuat", - "accept_secret_button": "Acceptă secretul", - "accept_public_key_button": "Acceptă cheia publică", - "outgoing_pk_message": "Cerere de schimb de chei", - "outgoing_secret_message": "Răspuns la schimbul de chei", - "incoming_pk_message": "Tocmai ai primit o cerere de cheie publică. Apasă mai jos pentru a o accepta.", - "incoming_secret_message": "Prietenul tău tocmai a acceptat cheia publică. Apasă mai jos pentru a accepta secretul." + "profile_picture_downloader": { + "button": "Descărcați poza de profil", + "title": "Descărcător de imagini de profil", + "avatar_option": "Avatar", + "background_option": "Fundal" }, "auto_open_snaps": { - "title": "DESCHIDERE AUTOMATĂ SNAP-URI", - "notification_content": "{count} Snap-uri deschise" + "title": "Deschidere automată Snap-uri", + "notification_content": "{număr} Snap-uri deschise" }, "friend_mutation_observer": { - "notification_channel_name": "Observator de mutații ale prietenilor", - "friend_removed": "{username} te-a eliminat ca prieten", - "birthday_removed": "{username} și-a eliminat ziua de naștere ({birthday})", - "birthday_added": "{username} și-a adăugat ziua de naștere ({birthday})", - "birthday_changed": "{username} și-a schimbat ziua de naștere de la {oldBirthday} la {newBirthday}", - "bitmoji_selfie_changed": "{username} și-a schimbat selfie-ul Bitmoji", + "notification_channel_name": "Observator de Mutare a Prietenilor", + "friend_removed": "{username} te-a șters din lista de prieteni", + "birthday_removed": "{username} a șters data de naștere ({birthday})", + "birthday_added": "{username} a adăugat data de naștere ({birthday})", + "birthday_changed": "{username} și-a schimbat data de naștere de la {oldBirthday} la {newBirthday}", "bitmoji_avatar_changed": "{username} și-a schimbat avatarul Bitmoji", - "bitmoji_background_changed": "{username} și-a schimbat fundalul Bitmoji", - "bitmoji_scene_changed": "{username} și-a schimbat scena Bitmoji" - }, - "material3_strings": { - "date_range_picker_start_headline": "De la", - "date_range_picker_end_headline": "Până la", - "date_range_picker_title": "Selectează intervalul de date", - "date_picker_switch_to_calendar_mode": "Mod calendar", - "date_picker_switch_to_input_mode": "Mod introducere", - "date_range_picker_scroll_to_previous_month": "Luna anterioară", - "date_range_picker_scroll_to_next_month": "Luna următoare", - "date_picker_today_description": "Astăzi", - "date_range_picker_day_in_range": "Selectat", - "date_input_invalid_for_pattern": "Dată nevalidă", - "date_input_invalid_year_range": "An nevalid", - "date_input_invalid_not_allowed": "Dată nepermisă", - "date_range_input_invalid_range_input": "Interval de date nevalid" - }, - "send_override_dialog": { - "title": "Trimite media ca {type}", - "duration": "Durată: {duration}", - "saveable_snap_hint": "Fă Snap-ul salvabil în chat", - "unlimited_duration": "Nelimitat" - }, - "invalid_input_toast": "Intrare nevalidă! Asigură-te că ai introdus o valoare validă." -} \ No newline at end of file + "bitmoji_scene_changed": "{username} și-a schimbat scena Bitmoji", + "bitmoji_selfie_changed": "{username} și-a schimbat selfie-ul Bitmoji", + "bitmoji_background_changed": "{username} și-a schimbat fundalul Bitmoji" + } +} diff --git a/common/src/main/assets/lang/ru.json b/common/src/main/assets/lang/ru.json index 38281d98..3360e398 100644 --- a/common/src/main/assets/lang/ru.json +++ b/common/src/main/assets/lang/ru.json @@ -2,574 +2,222 @@ "setup": { "dialogs": { "select_language": "Выберите язык", - "save_folder": "PurrfectSnap требует разрешения на доступ к хранилищу для загрузки и сохранения медиа из Snapchat.\nПожалуйста, выберите место для сохранения медиа.", + "save_folder": "SnapEnhance требует разрешения хранилища для загрузки и сохранения медиафайлов из Snapchat.\nВыберите место, куда следует загружать медиафайлы.", "select_save_folder_button": "Выберите папку" }, "mappings": { - "dialog": "Генерация сопоставлений, это может занять некоторое время...", - "generate_failure_no_snapchat": "PurrfectSnap не обнаружил Snapchat, пожалуйста, попробуйте переустановить Snapchat.", - "generate_failure": "Произошла ошибка при генерации сопоставлений, пожалуйста, попробуйте снова." + "dialog": "Составление карт, это может занять некоторое время ...", + "generate_failure_no_snapchat": "SnapEnhance не удалось обнаружить Snapchat, попробуйте переустановить Snapchat.", + "generate_failure": "Произошла ошибка при генерации сопоставлений, пожалуйста, попробуйте еще раз." }, "permissions": { - "dialog": "Для продолжения необходимо выполнить следующие требования:", "notification_access": "Доступ к уведомлениям", + "display_over_other_apps": "Отображение поверх других приложений", + "dialog": "Для продолжения вам необходимо соответствовать следующим требованиям:", "battery_optimization": "Оптимизация батареи", - "display_over_other_apps": "Показывать поверх других приложений", - "request_button": "Запросить" + "request_button": "Запрос" } }, - "scopes": { - "friend": "Друг", - "group": "Группа" - }, "manager": { - "routes": { - "tasks": "Задачи", - "features": "Функции", - "manage_rule_feature": "Управление правилами", - "home": "Главная", - "home_settings": "Настройки", - "home_logs": "Логи", - "logger_history": "История логов", - "logged_stories": "Сохраненные истории", - "friend_tracker": "Трекер друзей", - "edit_rule": "Редактировать правило", - "file_imports": "Импорт файлов", - "manage_repos": "Управление репозиториями", - "social": "Соцсети", - "manage_scope": "Управление областью", - "messaging_preview": "Предпросмотр", - "scripts": "Скрипты", - "better_location": "Улучшенное местоположение" - }, "sections": { - "home": { - "version_title": "v{versionName} · форк от Eternal", - "update_title": "Обновление PurrfectSnap", - "update_content": "Доступна версия {version}!", - "update_button": "Скачать", - "debug_build_summary_title": "Вы используете отладочную сборку PurrfectSnap.", - "debug_build_summary_content": "Версия {versionName} ({versionCode})", - "debug_build_summary_date": "Дата сборки: {date} ({days} дней назад)", - "quick_actions_title": "Быстлые действия", - "download_icon_description": "Скачать", - "completed_icon_description": "Завершено", - "failed_icon_description": "Ошибка", - "manage_quick_actions_description": "Управление быстрыми действиями", - "quick_actions_icon_description": "Быстрые действия", - "add_quick_action_description": "Добавить быстрое действие" - }, - "home_logs": { - "no_logs_hint": "Нет доступных логов", - "clear_logs_button": "Очистить логи", - "export_logs_button": "Экспорт логов", - "saving_logs_toast": "Сохранение логов, это может занять некоторое время...", - "saved_logs_success_toast": "Логи успешно сохранены", - "saved_logs_failure_toast": "Не удалось сохранить логи." - }, - "home_settings": { - "actions_title": "Действия", - "message_logger_title": "Логгер сообщений", - "debug_title": "Отладка", - "success_toast": "Готово!", - "message_logger_summary": "{messageCount} сообщений\n{storyCount} историй", - "export_button": "Экспорт", - "clear_button": "Очистить", - "view_logger_history_button": "Просмотр истории логгера", - "updates_title": "Обновления", - "auto_update_check": "Автоматически проверять обновления", - "update_check_frequency": "Частота проверки обновлений", - "update_check_frequency_daily": "Ежедневно", - "update_check_frequency_weekly": "Еженедельно", - "update_check_frequency_monthly": "Ежемесячно", - "theme_icon_description": "Тема", - "app_theme_title": "Тема приложения", - "theme_mode_system": "Системная", - "theme_mode_light": "Светлая", - "theme_mode_dark": "Темная", - "ui_settings_title": "Настройки интерфейса", - "haptic_feedback_label": "Тактильный отклик", - "test_mode_label": "Тестовый режим (ТОЛЬКО ДЛЯ ОТЛАДКИ)", - "disable_feature_loading_label": "Отключить загрузку функций", - "disable_auto_mapper_label": "Отключить авто-маппер", - "disable_bypass_indicator_label": "Отключить индикатор обхода", - "update_notification_channel_name": "Обновления PurrfectSnap", - "update_notification_channel_description": "Уведомления об обновлениях PurrfectSnap", - "update_notification_title": "Доступно обновление PurrfectSnap", - "update_notification_text": "Версия {version} теперь доступна.", - "export_database_failed_toast": "Не удалось экспортировать базу данных! {message}", - "clear_messages_failed_toast": "Не удалось удалить сообщения! {message}", - "clear_file_failed_toast": "Не удалось очистить файл! {message}", - "debug_file_config": "Конфигурация", - "debug_file_mappings": "Сопоставления", - "debug_file_message_logger": "Логгер сообщений", - "debug_file_pinned_best_friend": "Закрепленный лучший друг", - "debug_file_native_sig_cache": "Кэш нативных сигнатур" - }, "tasks": { "no_tasks": "Нет задач", - "merge_button": "Объединить", - "failed_to_open_file": "Не удалось открыть файл", - "merge_files_toast": "Объединение {count} файлов", "remove_selected_tasks_title": "Вы уверены, что хотите удалить выбранные задачи?", "remove_all_tasks_title": "Вы уверены, что хотите удалить все задачи?", "delete_files_option": "Также удалить файлы", - "remove_selected_tasks_confirm": "Удалить {count} задачи?", - "remove_all_tasks_confirm": "Удалить все задачи?", - "clear_tasks_description": "Очистить задачи", - "file_not_found_icon_description": "Файл не найден", - "image_icon_description": "Изображение", - "video_icon_description": "Видео", - "audio_icon_description": "Аудио", - "file_icon_description": "Файл", - "download_icon_description": "Скачать", - "chat_action_icon_description": "Действие в чате", - "cancel_icon_description": "Отмена", - "success_icon_description": "Успешно", - "failure_icon_description": "Ошибка", - "cancelled_icon_description": "Отменено", - "task_status_failure": "Ошибка", - "task_status_cancelled": "Отменено" + "remove_selected_tasks_confirm": "Удалить {count} задач?", + "remove_all_tasks_confirm": "Убрать все задачи?", + "merge_files_toast": "Объединение {count} файла", + "failed_to_open_file": "Не удалось открыть файл" + }, + "home_logs": { + "clear_logs_button": "Очистить логи", + "saved_logs_failure_toast": "Не удалось сохранить логи", + "no_logs_hint": "Нет доступных логов", + "export_logs_button": "Экспорт логов", + "saving_logs_toast": "Сохранение логов, это может занять некоторое время...", + "saved_logs_success_toast": "Логи успешно сохранены" + }, + "home_settings": { + "export_button": "Экспорт", + "clear_button": "Очистить", + "view_logger_history_button": "Посмотреть логгер историй", + "message_logger_title": "Логгер сообщений", + "success_toast": "Сделанно!", + "message_logger_summary": "{messageCount} сообщений\n{storyCount} историй", + "actions_title": "Действия", + "debug_title": "Режим отладки" + }, + "home": { + "update_title": "Обновить SnapEnchance", + "update_content": "Версия {version} доступна!", + "update_button": "Скачать", + "debug_build_summary_content": "Версия {названиеВерсии} ({кодВерсии})", + "debug_build_summary_title": "Вы используете устранение ошибок от SnapEnhance", + "version_title": "v(названиеВерсии) · создал eternal", + "debug_build_summary_date": "Назначить дату: {дата} ({дни} дней назад)", + "quick_actions_title": "Быстрые Действия" }, "features": { - "disabled": "Отключено", + "disabled": "Отключенно", "export_option": "Экспорт", "import_option": "Импорт", - "reset_option": "Сбросить", "config_export_success_toast": "Конфигурация успешно экспортирована", "config_import_success_toast": "Конфигурация успешно импортирована", - "config_import_failure_toast": "Не удалось импортировать конфигурацию: {error}", - "config_export_failure_toast": "Не удалось экспортировать конфигурацию: {error}", - "saved_config_snackbar": "Конфигурация сохранена.", - "older_required": "Для этой функции требуется Snapchat v{version} или старше.", - "newer_required": "Для этой функции требуется Snapchat v{version} или новее.", - "search_button": "Поиск" - }, - "manage_rule_feature": { - "disable_state_option": "Отключено", - "disable_state_subtext": "Никакие друзья/группы не будут затронуты.", - "whitelist_state_option": "Никто кроме...", - "whitelist_state_subtext": "Только {count} друзей/групп будут затронуты этим правилом.", - "whitelist_state_button": "Выбрать разрешенных друзей/группы", - "blacklist_state_option": "Все кроме...", - "blacklist_state_subtext": "Все, кроме {count} друзей/групп, будут затронуты этим правилом.", - "blacklist_state_button": "Выбрать исключенных друзей/группы", - "clear_list_button": "Очистить список друзей/групп", - "dialog_clear_confirmation_text": "Вы уверены, что хотите очистить список?" - }, - "social": { - "friends_tab": "Друзья", - "groups_tab": "Группы", - "empty_hint": "(пусто)", - "streaks_expiration_short": "{hours} ч" + "config_import_failure_toast": "Не удалось импортировать конфигурацию {error}", + "saved_config_snackbar": "Конфигурация сохранена", + "reset_option": "Сброс", + "config_export_failure_toast": "Не удалось экспортировать конфигурацию {ошибка}" }, "manage_scope": { - "logged_stories_button": "Показать сохраненные истории", + "logged_stories_button": "Показать сохранённые истории", "e2ee_title": "Сквозное шифрование", "rules_title": "Правила", "participants_text": "{count} участников", "not_found": "Не найдено", - "streaks_title": "Серии", "streaks_length_text": "Длина: {length}", "streaks_expiration_text": "Истекает через {eta}", + "streaks_title": "Серия", "streaks_expiration_text_expired": "Истекло", "reminder_button": "Установить напоминание", - "delete_scope_confirm_dialog_title": "Вы уверены, что хотите удалить {scope}?", - "notes_placeholder": "Нажмите, чтобы добавить заметку", - "invalid_key_size_32_bytes": "Неверный размер ключа (должно быть 32 байта).", - "successfully_imported_key": "Ключ успешно импортирован", - "failed_to_import_key": "Не удалось импортировать ключ: {message}.", - "export_base64_button": "Экспорт в Base64", - "import_base64_button": "Импорт из Base64" + "delete_scope_confirm_dialog_title": "Вы уверены, что хотите удалить {scope}?" + }, + "social": { + "streaks_expiration_short": "{hours} ч", + "friends_tab": "Друзья", + "groups_tab": "Группы", + "empty_hint": "(пусто)" }, "logged_stories": { - "story_failed_to_load": "Не удалось загрузить", + "story_failed_to_load": "Ошибка загрузки", "no_stories": "Истории не найдены", - "save_from_cache_button": "Сохранить из кэша", - "downloaded_to_path": "Загружено в {path}.", - "download_failed": "Не удалось загрузить: {message}", - "posted_at": "Опубликовано {date}", - "created_at": "Создано {date}", - "failed_to_open_file": "Не удалось открыть файл. Проверьте логи для получения дополнительной информации.", - "failed_to_get_file": "Не удалось получить файл" + "save_from_cache_button": "Сохранить из кэша" }, "messaging_preview": { - "processed_messages_toast": "{count} сообщений обработано", - "processed_messages_text": "{count} сообщений обработано", - "close_button_description": "Закрыть", - "bridge_connection_failed": "Не удалось подключиться к мосту. Убедитесь, что Snapchat работает в фоновом режиме.", - "bridge_init_failed": "Не удалось инициализировать мост сообщений. Убедитесь, что Snapchat работает в фоновом режиме.", - "message_fetch_failed": "Не удалось получить сообщения.", + "bridge_connection_failed": "Не удалось подключиться к Snapchat через службу моста", + "bridge_init_failed": "Не удалось инициализировать мост обмена сообщениями", + "message_fetch_failed": "Не удалось получить сообщения", "no_message_hint": "Нет сообщений", "save_selection_option": "Сохранить выбранное", "save_all_option": "Сохранить все", - "unsave_selection_option": "Отменить сохранение выбранного", - "unsave_all_option": "Отменить сохранение всего", - "mark_selection_as_seen_option": "Отметить выбранные Snap как просмотренные", + "mark_selection_as_seen_option": "Авторами выбранный Snap как просмотренный", "mark_all_as_seen_option": "Отметить все Snap как просмотренные", "delete_selection_option": "Удалить выбранное", - "delete_all_option": "Удалить все" + "delete_all_option": "Удалить все", + "unsave_all_option": "Не сохранять все", + "unsave_selection_option": "Отменить выбор" }, "logger_history": { - "download_started_toast": "Загрузка началась!", - "download_success_toast": "Загружено в {path}.", - "download_failed_toast": "Не удалось загрузить {message}.", - "edited_at_text": "{message} (отредактировано {date})", - "download_button": "Скачать", - "select_conversation_placeholder": "Выберите беседу", - "close_button_description": "Закрыть", - "search_button_description": "Поиск", "list_friend_format": "Друг {name}", "list_group_format": "Группа {name}", "no_more_messages": "Больше нет сообщений", - "reverse_order_checkbox": "Обратный порядок", "chat_attachment": "Вложение {index}", - "empty_message": "Пустое сообщение чата", - "message_parse_failed": "Не удалось разобрать сообщение", + "reverse_order_checkbox": "Обратный порядок", + "message_parse_failed": "Не удалось проанализировать сообщение", "unknown_sender": "Неизвестный отправитель", "download_attachment_failed_toast": "Не удалось загрузить вложение", - "log_header_format": "{username} ({type}) - {date}" + "empty_message": "Пустой чат" }, - "file_imports": { - "import_file_button": "Импортировать файл", - "file_not_found": "Файл не найден", - "file_import_failed": "Не удалось импортировать файл: {error}.", - "file_imported": "Файл успешно импортирован", - "file_delete_failed": "Не удалось удалить файл", - "no_files_hint": "Здесь вы можете импортировать файлы для использования в Snapchat. Нажмите кнопку ниже, чтобы импортировать файл." - }, - "better_location": { - "spoofed_coordinates_title": "Широта {latitude}, Долгота {longitude}", - "save_coordinates_dialog_title": "Сохранить координаты", - "saved_name_dialog_hint": "Сохраненное имя", - "latitude_dialog_hint": "Широта", - "longitude_dialog_hint": "Долгота", - "save_dialog_button": "Сохранить", - "choose_location_button": "Выбрать местоположение", - "teleport_to_friend_button": "Телепортироваться к другу", - "spoof_location_toggle": "Подмена местоположения", - "suspend_location_updates": "Приостановить обновление местоположения", - "saved_coordinates_title": "Сохраненные координаты", - "no_saved_coordinates_hint": "Нет сохраненных координат", - "delete_dialog_title": "Удалить сохраненные координаты", - "delete_dialog_message": "Вы уверены, что хотите удалить эти сохраненные координаты?", - "teleport_to_friend_title": "Телепортироваться к другу", - "search_bar": "Поиск", - "no_friends_map": "Нет друзей на карте", - "no_friends_found": "Друзья не найдены", - "edit_location_button_description": "Редактировать местоположение", - "add_icon_description": "Добавить", - "edit_icon_description": "Редактировать", - "delete_icon_description": "Удалить" + "manage_rule_feature": { + "disable_state_option": "Выведенный из строя", + "disable_state_subtext": "Друзья/группы не будут изменены", + "whitelist_state_option": "Ни одного исключения ...", + "whitelist_state_subtext": "Только {число} друзей/групп будет изменено этим правилом" } }, + "routes": { + "home_logs": "Логи", + "tasks": "Задания", + "features": "Функции", + "home": "Дом", + "home_settings": "Настройки", + "scripts": "Скрипты", + "logger_history": "История логов", + "messaging_preview": "Предварительный просмотр", + "logged_stories": "Сохранённые истории", + "manage_scope": "Управление область", + "social": "Соц. сети", + "better_location": "Улучшенная Локация", + "manage_rule_feature": "Изменить настройки", + "file_imports": "Импорт файлов", + "friend_tracker": "Остлеживание друга", + "edit_rule": "Изменить правила", + "theming": "Интерфейс", + "edit_theme": "Изменть Тему", + "manage_repos": "Управлять Хранилищами" + }, "dialogs": { - "add_friend": { - "title": "Добавить друга или группу", - "search_hint": "Поиск", - "fetch_error": "Не удалось получить данные.", - "category_groups": "Группы", - "category_friends": "Друзья", - "participants_text": "{count} участников", - "search_icon_description": "Поиск" - }, "scripting_warning": { "title": "Предупреждение", - "content": "PurrfectSnap включает инструмент для создания скриптов, позволяющий выполнять пользовательский код на вашем устройстве. Будьте предельно осторожны и устанавливайте модули только из известных и надежных источников. Неавторизованные или непроверенные модули могут представлять угрозу безопасности для вашей системы." + "content": "SnapEnhance включает в себя инструмент сценариев, позволяющий выполнять пользовательский код на вашем устройстве. Будьте предельно осторожны и устанавливайте модули только из известных и надежных источников. Неавторизованные или непроверенные модули могут представлять угрозу безопасности вашей системы." }, "reset_config": { "title": "Сбросить конфигурацию", "content": "Вы уверены, что хотите сбросить конфигурацию?", "success_toast": "Конфигурация успешно сброшена" }, - "export_config": { - "title": "Экспортировать конфиденциальные данные?", - "content": "Вы хотите экспортировать конфигурацию с конфиденциальными данными (например, координаты местоположения и т.д.)?" - }, "messaging_action": { "title": "Выберите типы контента для обработки", "select_all_button": "Выбрать все" }, - "file_imports": { - "no_files_settings_hint": "Файлы не найдены. Убедитесь, что вы импортировали необходимые файлы в разделе 'Импорт файлов'.", - "settings_select_file_hint": "Выберите импортированный файл" - }, - "quick_actions_dialog": { - "title": "Редактировать быстрые действия", - "subtitle": "Выберите и измените размер быстрых действий." + "add_friend": { + "title": "Добавить друга или группу", + "search_hint": "Поиск", + "fetch_error": "Не удалось получить данные", + "category_groups": "Группы", + "category_friends": "Друзья" } - }, - "friend_tracker": { - "rules_tab": "Правила", - "logs_tab": "Логи", - "export_dialog_title": "Экспорт", - "bulk_export_button": "Массовый экспорт", - "individual_export_button": "Индивидуальный экспорт", - "invalid_import_type_dialog_title": "Неверный тип импорта", - "invalid_import_type_dialog_text": "Выбранный файл несовместим с этим типом импорта. Пожалуйста, выберите правильный тип импорта.", - "import_dialog_title": "Импорт", - "bulk_import_button": "Массовый импорт", - "individual_import_button": "Индивидуальный импорт", - "import_button_description": "Импорт", - "export_button_description": "Экспорт", - "export_button": "Экспорт", - "delete_button_description": "Удалить", - "delete_button": "Удалить", - "catalog_button_description": "Каталог", - "catalog_button": "Каталог", - "add_rule_button_description": "Добавить правило", - "add_rule_button": "Добавить правило", - "no_rules_found": "Правила не найдены", - "empty_rule_name": "(пусто)", - "events_suffix": "событий", - "scopes_suffix": "областей", - "select_rule_to_export_title": "Выберите правило для экспорта", - "deleted_logs_toast": "{count} логов удалено.", - "delete_logs_dialog_title": "Удалить логи?", - "deleting_logs_dialog_text": "Удаление {count} логов...", - "delete_logs_dialog_confirm_text": "Это удалит логи на основе текущего фильтра и поискового запроса. Это действие необратимо.", - "exported_logs_toast": "Логи экспортированы!", - "export_logs_failed_toast": "Не удалось экспортировать логи. Проверьте logcat для получения дополнительной информации.", - "export_logs_dialog_title": "Экспортировать логи?", - "exporting_logs_dialog_text": "Экспорт логов...", - "export_logs_dialog_confirm_text": "Это экспортирует логи на основе текущего фильтра и поискового запроса.", - "export_as_button": "Экспортировать как {type}", - "filters_title": "Фильтры", - "search_by_label": "Искать по", - "newest_first_label": "Сначала новые", - "since_label": "С", - "until_label": "До", - "pick_a_date_button": "Выберите дату", - "search_placeholder": "Поиск", - "filter_button_description": "Фильтр", - "clear_button_description": "Очистить", - "no_logs_found": "Логи не найдены", - "log_event_format": "{event} в {conversation}", - "condition_only_inside_conversation": "Только когда я в беседе", - "condition_only_outside_conversation": "Только когда я вне беседы", - "condition_only_when_app_active": "Только когда Snapchat активен", - "condition_only_when_app_inactive": "Только когда Snapchat неактивен", - "condition_no_push_notification_when_app_active": "Нет push-уведомлений, когда Snapchat активен", - "add_event_dialog_title": "Добавить событие", - "event_type_label": "Тип события", - "triggers_title": "Триггеры", - "conditions_title": "Условия", - "add_button": "Добавить", - "default_rule_name": "Пользовательское правило", - "discard_changes_dialog_title": "Отменить изменения?", - "discard_changes_dialog_text": "У вас есть несохраненные изменения. Вы уверены, что хотите их отменить?", - "discard_button": "Отменить", - "cannot_save_rule_dialog_title": "Не удается сохранить правило", - "cannot_save_rule_dialog_text": "Правило должно содержать хотя бы одно событие для сохранения.", - "duplicate_rule_name_dialog_title": "Дублирующееся имя правила", - "duplicate_rule_name_dialog_text": "Правило с таким именем уже существует. Пожалуйста, выберите другое имя.", - "delete_rule_dialog_title": "Удалить правило", - "delete_rule_dialog_text": "Вы уверены, что хотите удалить это правило?", - "new_rule_title": "Новое правило", - "edit_rule_title": "Редактировать правило", - "back_button_description": "Назад", - "save_button_description": "Сохранить", - "general_section_title": "Общие", - "rule_name_label": "Имя правила", - "author_name_label": "Имя автора", - "scope_section_title": "Область", - "scope_all": "Все", - "scope_whitelist": "Белый список", - "scope_blacklist": "Черный список", - "select_friends_groups_button": "Выбрать друзей/группы ({count})", - "events_section_title": "События", - "add_event_button": "Добавить событие", - "no_events_text": "Нет событий" - }, - "friend_tracker_catalog": { - "download_failed": "Не удалось загрузить: {code}", - "error": "Ошибка: {message}", - "no_repos_added": "Репозитории не добавлены.", - "no_rules_available": "В репозиториях нет доступных правил.", - "by_author": "от {author}", - "imported_button": "Импортировано", - "import_button": "Импорт", - "title": "Каталог трекера друзей", - "manage_repos_description": "Управление репозиториями" - }, - "friend_tracker_export": { - "title": "Экспорт правил", - "back_button_description": "Назад", - "exported_toast": "Правила трекера друзей экспортированы!", - "export_failed_toast": "Не удалось экспортировать правила: {message}.", - "save_button": "Сохранить", - "expand_button_description": "Развернуть" - }, - "friend_tracker_import": { - "title": "Импорт правил", - "back_button_description": "Назад", - "imported_toast": "Правила трекера друзей импортированы!", - "import_failed_toast": "Не удалось импортировать правила: {message}.", - "confirm_button": "Подтвердить", - "expand_button_description": "Развернуть" - }, - "friend_tracker_repos": { - "invalid_repo_title": "Неверный репозиторий", - "add_repo_button": "Добавить репозиторий", - "add_repo_dialog_title": "Добавить URL репозитория", - "repo_url_label": "URL репозитория", - "repo_added_toast": "Репозиторий успешно добавлен!", - "invalid_repo_error": "Это не похоже на действительный репозиторий Friend Tracker.", - "add_repo_failed_toast": "Не удалось добавить репозиторий: {message}.", - "add_button": "Добавить", - "no_repos_added": "Репозитории не добавлены", - "remove_button": "Удалить", - "remove_repo_dialog_title": "Удалить репозиторий", - "remove_repo_dialog_text": "Вы уверены, что хотите удалить этот репозиторий?" - }, - "navigation": { - "tracker_tab_label": "Трекер", - "customize_bottom_bar_title": "Настроить нижнюю панель", - "customize_bottom_bar_subtitle": "Переупорядочивайте, добавляйте или удаляйте вкладки. Максимум пять.", - "shown_tabs_title": "Отображаемые вкладки", - "no_tabs_selected_text": "Вкладки не выбраны", - "available_tabs_title": "Доступные вкладки", - "reset_button": "Сбросить", - "done_button": "Готово" - }, - "scripting": { - "script_already_installed": "Скрипт уже установлен!", - "downloading_script": "Загрузка скрипта...", - "script_downloaded": "Скрипт {name} загружен!", - "download_script_failed": "Не удалось загрузить скрипт. Проверьте логи для получения дополнительной информации.", - "import_script_from_url_title": "Импортировать скрипт из URL", - "import_script_warning": "Предупреждение: импортированные скрипты могут нанести вред вашему устройству. Импортируйте скрипты только из надежных источников.", - "enter_url_label": "Введите URL здесь:", - "script_imported": "Скрипт {name} импортирован!", - "import_failed": "Не удалось импортировать скрипт: {message}. Проверьте логи для получения дополнительной информации.", - "import_button": "Импорт", - "update_module_button": "Обновить модуль", - "updating_script": "Обновление скрипта {name}...", - "module_not_found": "Модуль не найден", - "updated_script": "{name} обновлен до версии {version}.", - "update_module_failed": "Не удалось обновить модуль. Проверьте логи для получения дополнительной информации.", - "edit_module_button": "Редактировать модуль", - "open_module_failed": "Не удалось открыть файл модуля. Проверьте логи для получения дополнительной информации.", - "clear_module_data_button": "Очистить данные модуля", - "module_data_cleared": "Данные модуля очищены!", - "clear_module_data_failed": "Не удалось очистить данные модуля. Проверьте логи для получения дополнительной информации.", - "delete_module_button": "Удалить модуль", - "deleted_script": "Скрипт {name} удален!", - "delete_module_failed": "Не удалось удалить модуль. Проверьте логи для получения дополнительной информации.", - "actions_title": "Действия", - "no_description": "Нет описания", - "update_available": "Доступно обновление: {version}", - "actions_button": "Действия", - "loaded_script": "Скрипт {name} загружен", - "unloaded_script": "Скрипт {name} выгружен", - "enable_script_failed": "Не удалось включить скрипт. Проверьте логи для получения дополнительной информации.", - "disable_script_failed": "Не удалось отключить скрипт. Проверьте логи для получения дополнительной информации.", - "select_scripts_folder_toast": "Пожалуйста, выберите папку со скриптами!", - "manage_repos_button": "Управление репозиториями", - "import_from_url_button": "Импорт из URL", - "open_scripts_folder_button": "Открыть папку скриптов", - "no_settings_for_module": "У этого модуля нет настроек", - "installed_scripts_tab": "Установленные скрипты", - "catalog_tab": "Каталог", - "no_scripts_folder_selected_title": "Папка со скриптами не выбрана", - "select_folder_button": "Выбрать папку", - "no_scripts_found_title": "Скрипты не найдены.", - "use_catalog_to_add_scripts": "Используйте вкладку 'Каталог' для добавления скриптов!", - "ok_button_timeout": "OK ({timeout})", - "documentation_button": "Документация", - "catalog": { - "script_already_installed": "Скрипт уже установлен!", - "download_failed": "Не удалось загрузить: {code}", - "script_downloaded": "Скрипт загружен!", - "could_not_create_file": "Не удалось создать файл.", - "no_scripts_folder_selected": "Папка для скриптов не выбрана.", - "error": "Ошибка: {message}", - "no_repos_added": "Репозитории не добавлены.", - "repo_list_info": "Здесь вы можете найти список репозиториев:", - "link_text": "Ссылка", - "no_scripts_available": "В репозиториях нет доступных скриптов.", - "by_author": "от {author}", - "version": "Версия: {version}", - "installed_button": "Установлен", - "download_button": "Скачать" - }, - "repos": { - "invalid_repo_title": "Неверный репозиторий", - "add_repo_button": "Добавить репозиторий", - "add_repo_dialog_title": "Добавить URL репозитория", - "repo_url_label": "URL репозитория", - "repo_added_toast": "Репозиторий успешно добавлен!", - "invalid_repo_error": "Это не похоже на действительный репозиторий скриптов.", - "add_repo_failed_toast": "Не удалось добавить репозиторий: {message}.", - "add_button": "Добавить", - "no_repos_added": "Репозитории не добавлены", - "remove_button": "Удалить", - "remove_repo_dialog_title": "Удалить репозиторий", - "remove_repo_dialog_text": "Вы уверены, что хотите удалить этот репозиторий?" - } - }, - "features": { - "config_import": { - "title": "Подтвердить импорт", - "back_button_description": "Назад", - "config_imported_toast": "Конфигурация импортирована!", - "confirm_button": "Подтвердить", - "expand_button_description": "Развернуть", - "enable_feature": "Включить функцию", - "enabled": "Включено", - "disabled": "Отключено" - }, - "config_export": { - "title": "Сводка экспорта", - "back_button_description": "Назад", - "save_button": "Сохранить", - "expand_button_description": "Развернуть", - "enable_feature": "Включить функцию", - "enabled": "Включено", - "disabled": "Отключено" - } - }, - "manage_repos": { - "title": "Управление репозиториями {featureName}", - "add_repo_button": "Добавить репозиторий", - "add_repo_dialog_title": "Добавить URL репозитория", - "repo_url_label": "URL репозитория", - "repo_added_successfully": "Репозиторий успешно добавлен!", - "add_repo_failed": "Не удалось добавить репозиторий: {message}.", - "add_button": "Добавить", - "no_repos_added": "Репозитории не добавлены", - "remove_button": "Удалить" } }, + "scopes": { + "friend": "Друг", + "group": "Группа" + }, + "material3_strings": { + "date_range_input_invalid_range_input": "Неверный диапазон дат", + "date_range_picker_start_headline": "От", + "date_input_invalid_year_range": "Неверный год", + "date_input_invalid_not_allowed": "Недействительная дата", + "date_range_picker_end_headline": "К", + "date_range_picker_title": "Выберите диапазон дат", + "date_picker_switch_to_calendar_mode": "Календарь", + "date_picker_switch_to_input_mode": "Вход", + "date_picker_today_description": "Сегодня", + "date_input_invalid_for_pattern": "Недействительная дата", + "date_range_picker_scroll_to_previous_month": "Предыдущий месяц", + "date_range_picker_day_in_range": "Выбрано", + "date_range_picker_scroll_to_next_month": "В следующем месяце" + }, + "half_swipe_notifier": { + "notification_content_dm": "Пользователь {friend} только что наполовину перешел в ваш чат на {duration} сек", + "notification_channel_name": "Половина смахивания", + "notification_content_group": "Пользователь {friend} только что наполовину перешел в {группу} на {duration} сек" + }, + "conversation_preview": { + "total_messages": "Всего отправленных/полученных сообщений: {count}", + "title": "Предварительный просмотр", + "streak_expiration": "истекает через {day} дней {час} часов {минуту} минут", + "unknown_user": "Неизвестный пользователь" + }, "rules": { - "toasts": { - "enabled": "{ruleName} включено", - "disabled": "{ruleName} отключено" - }, - "modes": { - "blacklist": "Режим черного списка", - "whitelist": "Режим белого списка" - }, "properties": { - "auto_download": { - "name": "Автозагрузка", - "description": "Автоматически загружать Snap при просмотре", - "options": { - "blacklist": "Исключить из автозагрузки", - "whitelist": "Автозагрузка" - } - }, "stealth": { - "name": "Скрытый режим", - "description": "Не позволяет никому узнать, что вы открыли их Snap, чаты и разговоры.", + "name": "Режим скрытности", + "description": "Не позволяет никому узнать, что вы открыли их Snap/чаты и разговоры", "options": { "blacklist": "Исключить из скрытого режима", - "whitelist": "Скрытый режим" + "whitelist": "Режим скрытности" } }, + "pin_conversation": { + "name": "Закрепить разговор" + }, + "e2e_encryption": { + "name": "Использовать шифрование E2E" + }, "auto_save": { - "name": "Автосохранение", - "description": "Сохраняет сообщения чата при их просмотре.", + "name": "Авто сохранение", + "description": "Сохраняет сообщения чата при их просмотре", "options": { "blacklist": "Исключить из автосохранения", "whitelist": "Автосохранение" @@ -577,1446 +225,1129 @@ }, "unsaveable_messages": { "name": "Несохраняемые сообщения", - "description": "Запрещает другим сохранять сообщения в чате", + "description": "Предотвращает сохранение сообщений в чате другими людьми", "options": { "blacklist": "Исключить из несохраняемых сообщений", "whitelist": "Несохраняемые сообщения" } }, - "auto_open_snaps": { - "name": "Автоматическое открытие Snap", - "description": "Автоматически открывает Snap при их получении", - "options": { - "blacklist": "Исключить из автоматического открытия Snap", - "whitelist": "Автоматическое открытие Snap" - } - }, "hide_friend_feed": { "name": "Скрыть из ленты друзей" }, - "e2e_encryption": { - "name": "Использовать E2E шифрование" + "auto_download": { + "options": { + "blacklist": "Исключить из автоматической загрузки", + "whitelist": "Автоматическая загрузка" + }, + "description": "Автоматически загружать Snap при их просмотре", + "name": "Авто загрузка" }, - "pin_conversation": { - "name": "Закрепить беседу" - }, - "exclude_message_logger": { - "name": "Исключить из логгера сообщений" + "auto_open_snaps": { + "name": "Автоматическое открытие Снапов", + "description": "Автоматическое открытие Снапов при их получении", + "options": { + "blacklist": "Исключить из автоматического открытия Снапов", + "whitelist": "Автоматическое открытие Снапов" + } } + }, + "toasts": { + "enabled": "{ruleName} включено", + "disabled": "{ruleName} отключено" + }, + "modes": { + "blacklist": "Режим черного списка", + "whitelist": "Режим белого списка" } }, - "actions": { - "clean_snapchat_cache": { - "name": "Очистить кэш Snapchat", - "description": "Очищает кэш Snapchat" + "button": { + "ok": "ОК", + "open": "Открыть", + "positive": "Да", + "negative": "Нет", + "cancel": "Отмена", + "download": "Скачать" + }, + "end_to_end_encryption": { + "accept_public_key_button": "Принять открытый ключ", + "toolbox": { + "no_shared_key": "У вас еще нет общего секрета с этим другом. Нажмите ниже, чтобы начать новый.", + "shared_key_fingerprint": "Ваш отпечаток пальца:\n\n{fingerprint}\n\nОбязательно проверьте, совпадает ли он с отпечатком пальца вашего друга!", + "initiate_exchange_button": "Инициировать обмен ключами" }, - "manage_friend_list": { - "name": "Управление списком друзей", - "description": "Импорт/экспорт списка друзей при резервном копировании." + "confirmation_dialogs": { + "title": "Сквозное шифрование", + "confirmation_1": "ВНИМАНИЕ: это приведет к перезаписи существующего ключа. Вы потеряете доступ ко всем зашифрованным сообщениям этого друга. Вы уверены что хотите продолжить?", + "confirmation_2": "Вы ДЕЙСТВИТЕЛЬНО уверены, что хотите продолжить? Это ваш последний шанс отступить." }, - "export_chat_messages": { - "name": "Экспорт сообщений чата", - "description": "Экспортирует сообщения беседы в файл JSON/HTML/TXT." - }, - "export_memories": { - "name": "Экспорт воспоминаний", - "description": "Экспортирует воспоминания в ZIP-файл." - }, - "bulk_messaging_action": { - "name": "Массовая рассылка сообщений", - "description": "Выполняет такие операции, как удаление друзей или массовое удаление бесед." - }, - "regen_mappings": { - "name": "Перегенерировать сопоставления", - "description": "Перегенерировать сопоставления вручную" - }, - "change_language": { - "name": "Изменить язык", - "description": "Изменить язык PurrfectSnap" - }, - "file_imports": { - "name": "Импорт файлов", - "description": "Импортируйте файлы для использования в Snapchat." - }, - "friend_tracker": { - "name": "Трекер друзей", - "description": "Отслеживайте своих друзей в Snapchat" - }, - "logger_history": { - "name": "История логгера", - "description": "Просмотр истории сохраненных сообщений" - } + "unencrypted_conversation_send_failure_toast": "Вы не можете отправлять зашифрованный контент одновременно в зашифрованные и незашифрованные беседы!", + "no_participants_to_encrypt_toast": "У вас нет друзей в этом разговоре, с которыми можно шифровать сообщения!", + "accept_secret_key_success_toast": "Сделанно! Теперь вы можете отправлять и получать зашифрованные сообщения с этим другом.", + "accept_public_key_failure_toast": "Не удалось принять открытый ключ", + "accept_secret_button": "Принять секрет", + "encryption_failed_toast": "Не удалось зашифровать сообщение! Проверьте logcat для получения более подробной информации.", + "accept_public_key_success_toast": "Открытый ключ успешно принят!", + "outgoing_secret_message": "Ответ на обмен ключами", + "incoming_pk_message": "Вы только что получили запрос открытого ключа. Нажмите ниже, чтобы принять его.", + "incoming_secret_message": "Ваш друг только что принял ваш открытый ключ. Нажмите ниже, чтобы принять секрет.", + "native_hooks_send_failure_toast": "Не удалось отправить! Пожалуйста, включите Native Hooks в настройках.", + "accept_secret_key_failure_toast": "Не удалось принять секретный ключ", + "outgoing_pk_message": "Запрос на обмен ключами" }, "features": { - "notices": { - "unstable": "⚠ Нестабильно", - "ban_risk": "⚠ Эта функция может привести к бану", - "internal_behavior": "⚠ Это может нарушить внутреннее поведение Snapchat." - }, "properties": { "downloader": { - "name": "Загрузчик", - "description": "Скачивание медиа из Snapchat", "properties": { - "save_folder": { - "name": "Папка для сохранения", - "description": "Выберите папку, в которую будут загружаться все медиафайлы." + "ffmpeg_options": { + "properties": { + "preset": { + "description": "Установите скорость конвертации", + "name": "Предустановка" + }, + "custom_audio_codec": { + "description": "Установите собственный аудиокодек (например, AAC)", + "name": "Пользовательский аудиокодек" + }, + "threads": { + "description": "Количество потоков, которые нужно использовать", + "name": "Потоки" + }, + "video_bitrate": { + "description": "Установите битрейт видео (кбит/с)", + "name": "Битрейт видео" + }, + "audio_bitrate": { + "description": "Установите битрейт аудио (кбит/с)", + "name": "Аудио битрейт" + }, + "custom_video_codec": { + "name": "Пользовательский видеокодек", + "description": "Установите собственный видеокодек (например, libx264)" + }, + "constant_rate_factor": { + "description": "Установите коэффициент постоянной скорости для видеокодера\n От 0 до 51 для libx264", + "name": "Фактор постоянной скорости" + } + }, + "description": "Укажите дополнительные параметры FFmpeg", + "name": "Параметры FFmpeg" + }, + "force_image_format": { + "name": "Принудительный формат изображения", + "description": "Принудительно сохраняет изображения в указанном формате" + }, + "download_profile_pictures": { + "name": "Загрузить изображения профиля", + "description": "Позволяет загружать изображения профиля со страницы профиля" + }, + "opera_download_button": { + "name": "Кнопка загрузки оперы", + "description": "Добавляет кнопку загрузки в правом верхнем углу при просмотре снимка.\nДлительное нажатие кнопки активирует загрузку" + }, + "logging": { + "name": "Ведение журнала", + "description": "Показывает всплывающие сообщения при загрузке мультимедиа" }, "auto_download_sources": { - "name": "Источники автозагрузки", + "name": "Источники автоматической загрузки", "description": "Выберите источники для автоматической загрузки" }, + "download_context_menu": { + "description": "«Позволяет загружать/просматривать сообщения из разговора или истории с помощью контекстного меню.\nДлительное нажатие на кнопки приведет к принудительной загрузке»", + "name": "Загрузить контекстное меню" + }, + "save_folder": { + "name": "Сохранить папку", + "description": "Выберите каталог, в который должны быть загружены все медиафайлы" + }, "prevent_self_auto_download": { - "name": "Запретить автозагрузку своих медиа", - "description": "Предотвращает автоматическую загрузку ваших собственных Snap" + "name": "Запретить самостоятельную автоматическую загрузку", + "description": "Предотвращает автоматическую загрузку ваших собственных снимков" }, "path_format": { "name": "Формат пути", "description": "Укажите формат пути к файлу" }, "allow_duplicate": { - "name": "Разрешить дубликаты", - "description": "Позволяет загружать один и тот же медиафайл несколько раз." + "name": "Разрешить дублирование", + "description": "Позволяет загружать один и тот же носитель несколько раз" }, "merge_overlays": { "name": "Объединить наложения", - "description": "Объединяет текст и медиафайл Snap в один файл." - }, - "force_image_format": { - "name": "Принудительный формат изображения", - "description": "Принудительно сохранять изображения в указанном формате." + "description": "Объединяет текст и медиафайл Snap в один файл" }, "force_voice_note_format": { - "name": "Принудительный формат голосовых заметок", - "description": "Принудительно сохранять голосовые заметки в указанном формате." - }, - "auto_download_voice_notes": { - "name": "Автозагрузка голосовых заметок", - "description": "Автоматически загружает голосовые заметки при их воспроизведении" - }, - "download_profile_pictures": { - "name": "Скачать фото профиля", - "description": "Позволяет загружать фото профиля со страницы профиля." - }, - "opera_download_button": { - "name": "Кнопка загрузки в Opera", - "description": "Добавляет кнопку загрузки в правый верхний угол при просмотре Snap.\nДлительное нажатие на кнопку принудительно начнет загрузку." - }, - "download_context_menu": { - "name": "Контекстное меню загрузки", - "description": "Позволяет загружать/просматривать сообщения из беседы или истории с помощью контекстного меню.\nДлительное нажатие на кнопку принудительно начнет загрузку." - }, - "ffmpeg_options": { - "name": "Опции FFmpeg", - "description": "Укажите дополнительные опции FFmpeg", - "properties": { - "threads": { - "name": "Потоки", - "description": "Количество используемых потоков" - }, - "preset": { - "name": "Пресет", - "description": "Установите скорость конвертации" - }, - "constant_rate_factor": { - "name": "Фактор постоянного качества", - "description": "Установите фактор постоянного качества для видеокодера\nОт 0 до 51 для libx264" - }, - "video_bitrate": { - "name": "Битрейт видео", - "description": "Установите битрейт видео (кбит/с)" - }, - "audio_bitrate": { - "name": "Битрейт аудио", - "description": "Установите битрейт аудио (кбит/с)" - }, - "custom_video_codec": { - "name": "Пользовательский видеокодек", - "description": "Установите пользовательский видеокодек (например, libx264)" - }, - "custom_audio_codec": { - "name": "Пользовательский аудиокодек", - "description": "Установите пользовательский аудиокодек (например, aac)" - } - } - }, - "logging": { - "name": "Логирование", - "description": "Показывать уведомления при загрузке медиа" + "name": "Принудительный формат голосовой заметки", + "description": "Принудительное сохранение голосовых заметок в указанном формате" }, "custom_path_format": { "name": "Пользовательский формат пути", - "description": "Укажите пользовательский формат пути для загруженных медиафайлов.\n\nДоступные переменные:\n - %username%\n - %source%\n - %hash%\n - %date_time%" + "description": "Укажите собственный формат пути для загруженных медия.\n\n Доступные переменные:\n - %username%\n - %source%\n - %hash% \n- %date_time%" } - } + }, + "description": "Скачать Snapchat Media", + "name": "Загрузчик" }, "user_interface": { - "name": "Интерфейс", - "description": "Измените внешний вид Snapchat", "properties": { "enable_app_appearance": { "name": "Включить настройки внешнего вида приложения", - "description": "Включает скрытую настройку внешнего вида приложения.\nМожет не потребоваться в новых версиях Snapchat." + "description": "Включает скрытую настройку внешнего вида приложения\nМожет не потребоваться в новых версиях Snapchat" }, "friend_feed_message_preview": { - "name": "Предпросмотр сообщений в ленте друзей", - "description": "Показывает предпросмотр последних сообщений в ленте друзей.", + "description": "Показывает предварительный просмотр последних сообщений в ленте друзей", + "name": "Предварительный просмотр сообщения в ленте друзей", "properties": { "amount": { "name": "Количество", - "description": "Количество сообщений для предпросмотра" + "description": "Количество сообщений для предварительного просмотра" } } }, - "snap_preview": { - "name": "Предпросмотр Snap", - "description": "Отображает небольшой предпросмотр рядом с непросмотренными Snap в чате." - }, "bootstrap_override": { "name": "Переопределение Bootstrap", - "description": "Переопределяет настройки начальной загрузки интерфейса.", "properties": { + "home_tab": { + "name": "Главная вкладка", + "description": "Переопределяет вкладку запуска при открытии Snapchat" + }, "app_appearance": { "name": "Внешний вид приложения", "description": "Устанавливает постоянный внешний вид приложения" - }, - "home_tab": { - "name": "Домашняя вкладка", - "description": "Переопределяет стартовую вкладку при открытии Snapchat" } - } - }, - "force_amoled_theme": { - "name": "AMOLED-тема", - "description": "Использует настоящий черный фон для темной темы." - }, - "map_friend_nametags": { - "name": "Улучшенные теги имен на карте друзей", - "description": "Улучшает теги имен друзей на Snap Map." - }, - "prevent_message_list_auto_scroll": { - "name": "Отключить автопрокрутку списка сообщений", - "description": "Предотвращает прокрутку списка сообщений вниз при отправке/получении сообщения." - }, - "streak_expiration_info": { - "name": "Информация об истечении серии", - "description": "Показывает таймер истечения серии рядом со счетчиком серий." - }, - "hide_friend_feed_entry": { - "name": "Скрыть запись в ленте друзей", - "description": "Скрывает определенного друга из ленты друзей.\nИспользуйте вкладку 'Соцсети' для управления этой функцией." + }, + "description": "Переопределяет настройки пользовательского интерфейса Bootstrap" }, "hide_streak_restore": { - "name": "Скрыть восстановление серии", - "description": "Скрывает кнопку 'Восстановить' в ленте друзей." + "description": "Скрывает кнопку восстановления в ленте друзей", + "name": "Скрыть восстановление знака в ленте друзей" }, - "hide_quick_add_suggestions": { - "name": "Скрыть предложения быстрого добавления", - "description": "Удаляет предложения быстрого добавления друзей." + "snap_preview": { + "description": "Отображает небольшой предварительный просмотр рядом с неоткрытыми Snap в чате", + "name": "Предварительный просмотр Snap" + }, + "prevent_message_list_auto_scroll": { + "description": "Предотвращает автоматическую прокрутку списка сообщений к нижней части при отправке/получении сообщения", + "name": "Предотвращение автоматической прокрутки списка сообщений" + }, + "streak_expiration_info": { + "name": "Показ информации о сроке действия знака", + "description": "Показывает таймер истечения срока действия знака рядом с счетчиком знаков" }, "hide_story_suggestions": { "name": "Скрыть предложения историй", - "description": "Удаляет предложения на странице 'Истории'." + "description": "Удаляет предложения с страницы историй" }, "hide_ui_components": { - "name": "Скрыть элементы интерфейса", - "description": "Выберите, какие элементы интерфейса скрыть" + "name": "Скрыть элементы пользовательского интерфейса", + "description": "Выберите, какие элементы пользовательского интерфейса скрыть" }, "opera_media_quick_info": { - "name": "Быстрая информация о медиа в Opera", - "description": "Показывает полезную информацию о медиафайле, такую как дата создания, в контекстном меню Opera Viewer." + "description": "Показывает полезную информацию о медиафайлах, такую как дата создания, в контекстном меню просмотра оперы", + "name": "Информация о медиафайлах в Опере" }, "old_bitmoji_selfie": { - "name": "Старое селфи Bitmoji", - "description": "Возвращает селфи Bitmoji из старых версий Snapchat." + "name": "Старые селфи Битмоджи", + "description": "Возвращает селфи с Битмоджи из более старых версий Snapchat" }, "disable_spotlight": { - "name": "Отключить Spotlight", - "description": "Отключает страницу Spotlight" - }, - "friend_feed_menu_buttons": { - "name": "Кнопки меню ленты друзей", - "description": "Выберите, какие кнопки отображать в меню ленты друзей." - }, - "auto_close_friend_feed_menu": { - "name": "Автозакрытие меню ленты друзей", - "description": "Автоматически закрывает меню ленты друзей после нажатия кнопки настройки." + "name": "Отключить \"Спотлайт\"", + "description": "Отключает страницу \"Спотлайт\"" }, "vertical_story_viewer": { "name": "Вертикальный просмотр историй", - "description": "Включает вертикальный просмотр для всех историй." - }, - "enable_friend_feed_menu_bar": { - "name": "Включить панель меню ленты друзей", - "description": "Включает новую панель меню ленты друзей." + "description": "Включает вертикальный просмотр историй для всех историй" }, "message_indicators": { "name": "Индикаторы сообщений", - "description": "Добавляет специальные значки-индикаторы к сообщениям.\nПримечание: индикаторы могут быть не на 100% точными." - }, - "stealth_mode_indicator": { - "name": "Индикатор скрытого режима", - "description": "Добавляет эмодзи 👻 рядом с беседами в скрытом режиме." + "description": "Добавляет специфические значки индикаторов к сообщениям\nПримечание: индикаторы могут быть не на 100% точными" }, "edit_text_override": { - "name": "Переопределение редактирования текста", + "name": "Переопределение текста редактирования", "description": "Переопределяет поведение текстового поля" }, - "prevent_forced_keyboard": { - "name": "Отключить принудительное открытие клавиатуры", - "description": "Запрещает Snapchat автоматически показывать клавиатуру при открытии беседы." + "friend_feed_menu_buttons": { + "description": "Выберите, какие кнопки показывать в меню ленты друзей", + "name": "Кнопки меню ленты друзей" }, - "settings_menu": { - "name": "Меню настроек", - "description": "Изменяет способ открытия меню PurrfectSnap.", - "options": { - "default": "По умолчанию", - "legacy": "Классическое" - } + "map_friend_nametags": { + "name": "Улучшенные теги имен друзей на карте Snap", + "description": "Улучшает теги имен друзей на карте Snapmap" + }, + "enable_friend_feed_menu_bar": { + "name": "Панель меню ленты друзей", + "description": "Включает новую панель меню ленты друзей" + }, + "stealth_mode_indicator": { + "name": "Индикатор режима невидимки", + "description": "Добавляет эмодзи 👻 рядом с беседами в режиме невидимки" + }, + "hide_friend_feed_entry": { + "name": "Скрыть запись о друге в ленте друзей", + "description": "Скрывает определенного друга из ленты друзей\nИспользуйте вкладку «Социальное» для управления этой функцией" } - } + }, + "description": "Измените внешний вид Snapchat", + "name": "Пользовательский интерфейс" }, - "messaging": { - "name": "Сообщения", - "description": "Измените способ взаимодействия с друзьями", + "experimental": { "properties": { - "bypass_screenshot_detection": { - "name": "Обход обнаружения скриншотов", - "description": "Запрещает Snapchat обнаруживать, когда вы делаете скриншот" + "story_logger": { + "name": "Журнал истории", + "description": "Предоставляет историю историй друзей" }, - "anonymous_story_viewing": { - "name": "Анонимный просмотр историй", - "description": "Не позволяет никому узнать, что вы просмотрели их историю" + "meo_passcode_bypass": { + "description": "Обход пароля \"Только мои глаза\"\nЭто сработает только в том случае, если пароль был введен правильно ранее", + "name": "Обход пароля «Только мои глаза»" }, - "prevent_story_rewatch_indicator": { - "name": "Запретить индикатор повторного просмотра истории", - "description": "Не позволяет никому узнать, что вы пересмотрели их историю." - }, - "hide_peek_a_peek": { - "name": "Скрыть 'peek-a-peek'", - "description": "Предотвращает отправку уведомления, когда вы 'подглядываете' в чат" - }, - "hide_bitmoji_presence": { - "name": "Скрыть присутствие Bitmoji", - "description": "Запрещает вашему Bitmoji появляться во время чата" - }, - "hide_typing_notifications": { - "name": "Скрыть уведомления о наборе текста", - "description": "Не позволяет никому узнать, что вы печатаете сообщение" - }, - "unlimited_snap_view_time": { - "name": "Неограниченное время просмотра Snap", - "description": "Убирает ограничение по времени на просмотр Snap." - }, - "auto_mark_as_read": { - "name": "Автоматически отмечать как прочитанное", - "description": "Автоматически отмечает сообщения/Snap как прочитанные, даже если включен скрытый режим." - }, - "mark_snap_as_seen_button": { - "name": "Кнопка 'Отметить Snap как просмотренный'", - "description": "Добавляет кнопку для отметки Snap как просмотренного во время его просмотра.\nЭто будет работать, даже если включен скрытый режим." - }, - "skip_when_marking_as_seen": { - "name": "Пропускать при отметке как просмотренное", - "description": "Автоматически переходит к следующему Snap при отметке текущего как просмотренного.\nИспользуйте в сочетании с кнопкой 'Отметить Snap как просмотренный'." - }, - "loop_media_playback": { - "name": "Зацикленное воспроизведение медиа", - "description": "Зацикливает воспроизведение медиа при просмотре Snap/историй." - }, - "disable_replay_in_ff": { - "name": "Отключить повторный просмотр в ленте друзей", - "description": "Отключает возможность повторного просмотра долгим нажатием в ленте друзей." - }, - "half_swipe_notifier": { - "name": "Уведомление о 'подглядывании'", - "description": "Уведомляет вас, когда кто-то 'подглядывает' в вашу беседу", + "native_hooks": { "properties": { - "min_duration": { - "name": "Минимальная длительность", - "description": "Минимальная длительность 'подглядывания' (в секундах)" + "disable_bitmoji": { + "description": "Отключает Bitmoji профиля друзей", + "name": "Отключить Bitmoji" }, - "max_duration": { - "name": "Максимальная длительность", - "description": "Максимальная длительность 'подглядывания' (в секундах)" + "composer_hooks": { + "name": "Крюки композитора", + "description": "Встраивает код в кросс-платформенный UI-фреймворк Composer (только для архитектуры arm64)", + "properties": { + "bypass_camera_roll_limit": { + "name": "Обход ограничения на количество фотографий в галерее", + "description": "Увеличивает максимальное количество медиафайлов, которые можно отправить из галереи" + }, + "composer_logs": { + "name": "Логи Composer", + "description": "Перенаправляет журналы консоли Composer в SnapEnhance" + }, + "composer_console": { + "name": "Консоль Composer", + "description": "Позволяет выполнять JavaScript-код в Composer" + } + } + } + }, + "name": "Native Hooks", + "description": "Небезопасные функции, которые встраиваются в нативный код Snapchat" + }, + "spoof": { + "description": "Подделывает различную информацию о вас", + "properties": { + "play_store_installer_package_name": { + "name": "Имя пакета установщика Play Store", + "description": "Переопределяет имя пакета установщика на com.android.vending" + }, + "fingerprint": { + "name": "Отпечаток устройства", + "description": "Подделывает отпечаток вашего устройства" + }, + "remove_mock_location_flag": { + "description": "Предотвращает обнаружение фиктивного местоположения Snapchat", + "name": "Удалить флаг мокрого местоположения" + } + }, + "name": "Подделка" + }, + "edit_message": { + "description": "Позволяет редактировать сообщения в разговорах", + "name": "Редактирование сообщений" + }, + "e2ee": { + "name": "End-to-end шифрование", + "description": "Шифрует ваши сообщения с помощью AES с использованием общего секретного ключа\nОбязательно сохраните свой ключ в надежном месте!", + "properties": { + "encrypted_message_indicator": { + "name": "Индикатор зашифрованного сообщения", + "description": "Добавляет 🔒 эмодзи к зашифрованным сообщениям" + }, + "force_message_encryption": { + "name": "Принудительное шифрование сообщений", + "description": "Предотвращает отправку зашифрованных сообщений людям, у которых отключено конечно-конечное шифрование, только когда выбраны несколько бесед" } } }, + "media_file_picker": { + "name": "Выбор медиафайла", + "description": "Позволяет выбирать любой видео/аудиофайл из галереи" + }, + "call_recorder": { + "name": "Запись вызова", + "description": "Автоматически записывает аудиовызовы" + }, + "account_switcher": { + "name": "Переключатель аккаунтов", + "description": "Позволяет переключаться между аккаунтами без выхода из системы\nДолгое нажатие на значок поиска рядом с вашим профилем Bitmoji для открытия меню\nПримечание: эта функция является экспериментальной и, вероятно, будет изменена в будущем", + "properties": { + "auto_backup_current_account": { + "name": "Автоматическое резервное копирование текущего аккаунта", + "description": "Автоматически создает резервную копию текущего аккаунта при выходе из системы или переключении аккаунтов" + } + } + }, + "infinite_story_boost": { + "name": "Бесконечное ускорение истории", + "description": "Обходит ограничение задержки ускорения истории" + }, + "no_friend_score_delay": { + "name": "Отключить задержку оценки друзей", + "description": "Убирает задержку при просмотре оценки друзей" + }, + "convert_message_locally": { + "description": "Локально преобразует снепы во внешние медиафайлы для чата. Это появляется в контекстном меню загрузки чата", + "name": "Преобразование сообщения локально" + }, + "add_friend_source_spoof": { + "name": "Подделка источника запроса на добавление в друзья", + "description": "Маскировка источника запроса на добавление в друзья" + }, + "prevent_forced_logout": { + "name": "Предотвращение принудительного выхода из системы", + "description": "Предотвращает выход из системы Snapchat при входе на другом устройстве" + }, + "hidden_snapchat_plus_features": { + "description": "Включает нереализованные/бета-версии функций Snapchat Plus\nМожет не работать в старых версиях Snapchat", + "name": "Скрытые функции Snapchat Plus" + }, + "app_lock": { + "description": "Запрещает доступ к Snapchat без пароля", + "properties": { + "lock_on_resume": { + "description": "Блокирует приложение при его повторном открытии", + "name": "Заблокировать при продолжении" + } + }, + "name": "Блокировка приложения" + }, + "custom_streaks_expiration_format": { + "name": "Пользовательский формат истечения Streaks", + "description": "Настройка формата истечения Стриков\n\nДоступные переменные:\n- %c: Количество Стриков\n- %e: Эмодзи песочных часов\n- %d: Дни\n- %h: Часы\n- %m: Минуты\n- %s: Секунды\n- %w: Оставшееся время" + } + }, + "name": "Экспериментальные", + "description": "Экспериментальные функции" + }, + "messaging": { + "properties": { "call_start_confirmation": { "name": "Подтверждение начала звонка", "description": "Показывает диалоговое окно подтверждения при начале звонка" }, - "unlimited_conversation_pinning": { - "name": "Неограниченное закрепление бесед", - "description": "Позволяет закреплять неограниченное количество бесед локально" + "bypass_screenshot_detection": { + "name": "Обход обнаружения снимка экрана", + "description": "Предотвращает обнаружение Snapchat, когда вы делаете снимок экрана" }, - "disable_snap_mode_restrictions": { - "name": "Отключить ограничения режима Snap", - "description": "Позволяет просматривать самоуничтожающиеся Snap без ограничений." + "unlimited_snap_view_time": { + "description": "Удаляет ограничение времени просмотра Snap", + "name": "Неограниченное время просмотра Snap" }, - "prevent_message_sending": { - "name": "Запретить отправку сообщений", - "description": "Запрещает отправку определенных типов сообщений" + "anonymous_story_viewing": { + "description": "Предотвращает, чтобы кто-либо узнал, что вы просматривали их историю", + "name": "Анонимный просмотр историй" }, - "friend_mutation_notifier": { - "name": "Уведомление об изменениях друга", - "description": "Уведомляет вас, когда что-то меняется в профиле друга" + "prevent_story_rewatch_indicator": { + "name": "Предотвращение индикатора повторного просмотра истории", + "description": "Предотвращает, чтобы кто-либо узнал, что вы пересматривали их историю" }, - "better_notifications": { - "name": "Улучшенные уведомления", - "description": "Добавляет дополнительную информацию в получаемые уведомления.", + "hide_bitmoji_presence": { + "name": "Скрыть присутствие Битмоджи", + "description": "Предотвращает появление вашего Битмоджи во время чата" + }, + "disable_replay_in_ff": { + "description": "Отключает возможность повтора с долгим нажатием в ленте друзей", + "name": "Отключить повтор в FF" + }, + "half_swipe_notifier": { + "name": "Уведомитель о половинчатом смахивании", "properties": { - "group_notifications": { - "name": "Групповые уведомления", - "description": "Группировать уведомления в одно" + "min_duration": { + "description": "Минимальная длительность половинчатого смахивания (в секундах)", + "name": "Минимальная длительность" }, - "chat_preview": { - "name": "Предпросмотр чата", - "description": "Показывает предпросмотр полученных сообщений в уведомлении." - }, - "media_preview": { - "name": "Предпросмотр медиа", - "description": "Показывает предпросмотр выбранных типов медиа в уведомлении." - }, - "media_caption": { - "name": "Подпись к медиа", - "description": "Показывает прикрепленную подпись к медиа в уведомлении." - }, - "stacked_media_messages": { - "name": "Сгруппированные медиа-сообщения", - "description": "Объединяет несколько медиа-сообщений в одно текстовое уведомление, когда их предпросмотр невозможен. Используйте в сочетании с предпросмотром чата." - }, - "friend_add_source": { - "name": "Источник добавления в друзья", - "description": "Показывает источник запроса на добавление в друзья в уведомлении." - }, - "reply_button": { - "name": "Кнопка ответа", - "description": "Добавляет кнопку ответа в уведомление" - }, - "smart_replies": { - "name": "Умные ответы", - "description": "Добавляет предлагаемые ответы в уведомления (Android 10+). Используйте в сочетании с кнопкой 'Ответить'." - }, - "download_button": { - "name": "Кнопка загрузки", - "description": "Позволяет загружать медиафайлы из уведомления." - }, - "mark_as_read_button": { - "name": "Кнопка 'Отметить как прочитанное'", - "description": "Позволяет отметить сообщение как прочитанное из уведомления." - }, - "mark_as_read_and_save_in_chat": { - "name": "Отметить как прочитанное и сохранить в чате", - "description": "Добавляет кнопку 'Отметить как прочитанное и сохранить в чате' в уведомление." + "max_duration": { + "name": "Максимальная длительность", + "description": "Максимальная длительность половинчатого смахивания (в секундах)" } - } + }, + "description": "Уведомляет вас, когда кто-то половинчато смахивает в беседу" }, "notification_blacklist": { - "name": "Черный список уведомлений", - "description": "Выберите уведомления, которые следует блокировать" + "name": "Выберите уведомления, которые следует заблокировать", + "description": "Журнал сообщений" }, "message_logger": { - "name": "Логгер сообщений", - "description": "Предотвращает удаление сообщений", + "name": "Предотвращает удаление сообщений", "properties": { "keep_my_own_messages": { - "name": "Сохранять мои собственные сообщения", - "description": "Предотвращает удаление ваших собственных сообщений" + "description": "Автоочистка", + "name": "Предотвращает удаление ваших собственных сообщений" }, "auto_purge": { - "name": "Автоочистка", - "description": "Автоматически удаляет кэшированные сообщения, которые старше указанного периода времени." + "description": "Фильтр сообщений", + "name": "Автоматически удаляет кэшированные сообщения, которые старше указанного времени" }, "message_filter": { - "name": "Фильтр сообщений", - "description": "Выберите, какие сообщения должны логироваться (пусто для всех сообщений)." - }, - "deleted_message_color": { - "name": "Цвет удаленного сообщения", - "description": "Устанавливает цвет удаленных сообщений" + "name": "Выберите, какие сообщения должны быть зарегистрированы (пусто для всех сообщений)", + "description": "Автосохранение сообщений" } - } - }, - "auto_save_messages_in_conversations": { - "name": "Автосохранение сообщений в беседах", - "description": "Автоматически сохраняет каждое сообщение в беседах" - }, - "gallery_media_send_override": { - "name": "Переопределение отправки медиа из галереи", - "description": "Подменяет источник медиа при отправке из галереи." - }, - "strip_media_metadata": { - "name": "Удаление метаданных медиа", - "description": "Удаляет метаданные медиа перед отправкой в сообщении." + }, + "description": "Сохранение собственных сообщений" }, "bypass_message_retention_policy": { - "name": "Обход политики хранения сообщений", - "description": "Предотвращает удаление сообщений после их просмотра" - }, - "bypass_message_action_restrictions": { - "name": "Обход ограничений на действия с сообщениями", - "description": "Позволяет реагировать на Snap, не открывая его, или сохранять несохраняемое сообщение." + "description": "Обход ограничений на действия с сообщениями", + "name": "Предотвращает удаление сообщений после их просмотра" }, "remove_groups_locked_status": { - "name": "Снять статус блокировки групп", - "description": "Позволяет просматривать информацию о группе после того, как вас исключили." + "description": "Глобальные", + "name": "Позволяет просматривать информацию о группе после исключения" }, - "double_tap_chat_action": { - "name": "Действие по двойному нажатию в чате", - "description": "Выполняет пользовательское действие при двойном нажатии на сообщение в чате." + "prevent_message_sending": { + "description": "Мгновенное удаление", + "name": "Предотвращает отправку определенных типов сообщений" }, - "double_tap_chat_action_custom_emoji": { - "name": "Пользовательская эмодзи-реакция по двойному нажатию в чате", - "description": "Устанавливает пользовательскую эмодзи-реакцию для действия по двойному нажатию в чате." + "hide_peek_a_peek": { + "name": "Скрыть Peek-a-Peek", + "description": "Предотвращает отправку уведомления, когда вы половинчато смахиваете в чате" + }, + "hide_typing_notifications": { + "name": "Скрыть уведомления о наборе текста", + "description": "Предотвращает, чтобы кто-либо узнал, что вы набираете сообщение" + }, + "loop_media_playback": { + "name": "Повторное воспроизведение медиафайлов", + "description": "Повторное воспроизведение медиафайлов при просмотре Snap / Историй" + }, + "better_notifications": { + "description": "Черный список уведомлений", + "name": "Добавляет больше информации в полученные уведомления" + }, + "strip_media_metadata": { + "name": "Удаляет метаданные медиафайлов перед отправкой как сообщение", + "description": "Обход политики хранения сообщений" + }, + "bypass_message_action_restrictions": { + "name": "Позволяет реагировать на снеп без его открытия или сохранять сообщение, которое нельзя сохранить", + "description": "Удалить статус заблокированной группы" + }, + "auto_save_messages_in_conversations": { + "name": "Автоматически сохраняет каждое сообщение в разговорах", + "description": "Переопределение отправки медиафайлов из галереи" + }, + "gallery_media_send_override": { + "name": "Маскировка источника медиафайлов при отправке из галереи", + "description": "Удаление метаданных медиафайлов" + }, + "auto_mark_as_read": { + "description": "Автоматически помечает сообщения/снапы как прочитанные даже при включенном режиме невидимости", + "name": "Автоматическая отметка как прочитанное" + }, + "friend_mutation_notifier": { + "description": "Уведомляет вас, когда что-то меняется в профиле друга", + "name": "Уведомление о мутации друга" } - } + }, + "description": "Изменяет ваш способ взаимодействия с друзьями", + "name": "Общение" + }, + "streaks_reminder": { + "properties": { + "interval": { + "description": "Интервал между каждым напоминанием (часы)", + "name": "Интервал" + }, + "remaining_hours": { + "name": "Оставшееся время", + "description": "Оставшееся время до показа уведомления (часы)" + }, + "group_notifications": { + "name": "Уведомления о группе", + "description": "Группирует уведомления в одно" + } + }, + "name": "Напоминания о серии", + "description": "Периодически уведомляет вас о ваших сериях" }, "global": { - "name": "Глобальные", - "description": "Измените глобальные настройки Snapchat", "properties": { + "hide_active_music": { + "name": "Скрыть активную музыку", + "description": "Предотвращает Snapchat от знания о том, что вы слушаете музыку\nЭто позволит вам делать снимки с помощью кнопок управления громкостью во время прослушивания музыки" + }, "better_location": { - "name": "Улучшенное местоположение", - "description": "Улучшает функционал местоположения Snapchat", + "name": "Улучшает местоположение Snapchat", "properties": { - "spoof_location": { - "name": "Подмена местоположения", - "description": "Подменяет ваше местоположение на указанное" - }, "coordinates": { - "name": "Координаты", - "description": "Установите координаты для подмены местоположения" - }, - "walk_radius": { - "name": "Радиус ходьбы", - "description": "Случайное перемещение в пределах этого радиуса (в футах)" + "description": "Установите координаты поддельного местоположения", + "name": "Координаты" }, "always_update_location": { "name": "Всегда обновлять местоположение", - "description": "Заставляет Snapchat обновлять местоположение, даже если данные GPS не получены" + "description": "Принудительное обновление местоположения даже при отсутствии данных GPS" }, "suspend_location_updates": { "name": "Приостановить обновление местоположения", - "description": "Предотвращает обновление вашего местоположения" + "description": "Добавляет кнопку в настройки карты для приостановки обновления местоположения" }, - "spoof_battery_level": { - "name": "Подмена уровня заряда батареи", - "description": "Подменяет уровень заряда батареи вашего устройства на карте.\nЗначение должно быть от 0 до 100." + "spoof_location": { + "name": "Маскирует ваше местоположение до указанного места", + "description": "Имитирует ваше местоположение до указанного места" }, "spoof_headphones": { - "name": "Подмена наушников", - "description": "Подменяет статус прослушивания музыки на карте" + "name": "Поддельные наушники", + "description": "Подделывает статус прослушивания музыки на карте" }, - "show_battery_level": { - "name": "Показывать уровень заряда батареи", - "description": "Показывает уровень заряда батареи ваших друзей на карте" + "spoof_battery_level": { + "name": "Поддельный уровень заряда батареи", + "description": "Подделывает уровень заряда батареи вашего устройства на карте\nЗначение должно быть от 0 до 100" } - } + }, + "description": "Маскировка местоположения" + }, + "disable_metrics": { + "description": "Блокирует отправку определенных аналитических данных в Snapchat", + "name": "Отключить метрики" + }, + "disable_memories_snap_feed": { + "name": "Отключить ленту моментов", + "description": "Предотвращает отображение последних моментов при свайпе вверх в камере" + }, + "spotlight_comments_username": { + "name": "Имя пользователя в комментариях", + "description": "Показывает имя автора в комментариях к 'Spotlight'" + }, + "disable_google_play_dialogs": { + "description": "Предотвращает отображение диалогов о доступности Google Play Services", + "name": "Отключить диалоги Google Play Services" + }, + "disable_snap_splitting": { + "name": "Отключить разделение снепов", + "description": "Предотвращает разделение снепов на несколько частей\nОтправленные вами изображения будут превращаться в видео" }, "snapchat_plus": { - "name": "Snapchat+", - "description": "Включает функции Snapchat+.\nНекоторые серверные функции могут не работать" - }, - "media_upload_quality": { - "name": "Качество загрузки медиа", - "description": "Переопределяет качество загрузки медиа", - "properties": { - "force_video_upload_source_quality": { - "name": "Принудительное качество источника при загрузке видео", - "description": "Заставляет Snapchat использовать исходное качество при загрузке видео.\nОбратите внимание, что это может не удалить метаданные из медиа." - }, - "disable_image_compression": { - "name": "Отключить сжатие изображений", - "description": "Отключает сжатие изображений при загрузке медиа." - }, - "custom_image_upload_format": { - "name": "Пользовательский формат загрузки изображений", - "description": "Устанавливает пользовательский формат загрузки изображений.\nВыберите формат без потерь (например, PNG) для наилучшего качества." - } - } + "description": "Активирует функции Snapchat Plus\nНекоторые функции на стороне сервера могут не работать", + "name": "Snapchat Plus" }, "disable_confirmation_dialogs": { "name": "Отключить диалоги подтверждения", "description": "Автоматически подтверждает выбранные действия" }, "auto_updater": { - "name": "Автообновление", - "description": "Автоматически проверять наличие новых обновлений" - }, - "disable_metrics": { - "name": "Отключить метрики", - "description": "Блокирует отправку определенных аналитических данных в Snapchat." + "name": "Автоматическое обновление", + "description": "Автоматически проверяет наличие новых обновлений" }, "disable_story_sections": { - "name": "Отключить разделы историй", - "description": "Удаляет разделы со страницы 'Истории'.\nДля правильной работы может потребоваться обновление." + "description": "Удаляет разделы на странице историй\nМожет потребоваться обновление для корректной работы", + "name": "Отключить разделы историй" }, "block_ads": { "name": "Блокировать рекламу", - "description": "Предотвращает показ рекламы" - }, - "disable_custom_tabs": { - "name": "Отключить кастомные вкладки", - "description": "Открывает ссылки в поддерживаемых приложениях вместо веб-браузера." + "description": "Предотвращает отображение рекламы" }, "disable_permission_requests": { "name": "Отключить запросы разрешений", - "description": "Запрещает Snapchat запрашивать определенные разрешения" - }, - "disable_memories_snap_feed": { - "name": "Отключить ленту Snap в Воспоминаниях", - "description": "Запрещает Snapchat показывать недавние воспоминания при свайпе вверх в камере." - }, - "spotlight_comments_username": { - "name": "Имя пользователя в комментариях Spotlight", - "description": "Показывает имя пользователя автора в комментариях Spotlight." + "description": "Предотвращает запрос разрешений в Snapchat" }, "bypass_video_length_restriction": { - "name": "Обход ограничения длины видео", - "description": "Одиночный: отправляет одно видео.\nРазделить: разделяет видео после редактирования" - }, - "default_video_playback_rate": { - "name": "Скорость воспроизведения видео по умолчанию", - "description": "Устанавливает скорость воспроизведения видео по умолчанию.\nЗначение должно быть от 0.1 до 4.0." + "name": "Обход ограничений длины видео", + "description": "Одиночный: отправляет одно видео\nРазделенный: разделяет видео после редактирования" }, "video_playback_rate_slider": { "name": "Ползунок скорости воспроизведения видео", - "description": "Добавляет ползунок в контекстное меню Opera для изменения скорости воспроизведения видео.\nПримечание: изменения применяются только к последующим видео." - }, - "disable_google_play_dialogs": { - "name": "Отключить диалоги Google Play Services", - "description": "Запрещает отображение диалогов о доступности Google Play Services" + "description": "Добавляет ползунок в контекстное меню оперы для изменения скорости воспроизведения видео\nПримечание: изменения применяются только к последующим видео" }, "default_volume_controls": { - "name": "Системные регуляторы громкости", - "description": "Заставляет Snapchat использовать системные регуляторы громкости" + "name": "Стандартные элементы управления громкостью", + "description": "Принудительно заставляет Snapchat использовать стандартные элементы управления громкостью системы" }, - "disable_telecom_framework": { - "name": "Отключить Telecom Framework", - "description": "Запрещает Snapchat использовать Android Telecom Framework.\nЭто позволяет слушать музыку во время звонка." - }, - "hide_active_music": { - "name": "Скрыть активную музыку", - "description": "Запрещает Snapchat знать, что вы слушаете музыку.\nЭто позволит вам делать Snap с помощью кнопок громкости во время прослушивания музыки." - }, - "disable_snap_splitting": { - "name": "Отключить разделение Snap", - "description": "Предотвращает разделение Snap на несколько частей.\nОтправленные вами изображения превратятся в видео." + "default_video_playback_rate": { + "description": "Устанавливает стандартную скорость воспроизведения видео\nЗначение должно быть от 0.1 до 4.0", + "name": "Стандартная скорость воспроизведения видео" } - } + }, + "name": "Настройки глобального Snapchat", + "description": "Лучшее местоположение" + }, + "camera": { + "properties": { + "force_camera_source_encoding": { + "name": "Принудительное кодирование источника камеры", + "description": "Принудительно кодирует источник камеры" + }, + "black_photos": { + "description": "Заменяет захваченные фотографии черным фоном\nВидео не затрагиваются", + "name": "Черные фотографии" + }, + "immersive_camera_preview": { + "name": "Иммерсивный предпросмотр", + "description": "Предотвращает обрезку предпросмотра камеры Snapchat\nЭто может вызвать мерцание камеры на некоторых устройствах" + }, + "override_front_resolution": { + "name": "Переопределение разрешения для передней камеры", + "description": "Переопределяет разрешение камеры для передней камеры" + }, + "custom_resolution": { + "description": "Устанавливает пользовательское разрешение камеры, ширина x высота (например, 1920x1080).\nПользовательское разрешение должно поддерживаться вашим устройством", + "name": "Пользовательское разрешение" + }, + "back_custom_frame_rate": { + "description": "Переопределяет частоту кадров задней камеры", + "name": "Пользовательский кадровый режим для задней камеры" + }, + "disable_cameras": { + "name": "Отключить камеры", + "description": "Предотвращает использование Snapchat выбранными камерами" + }, + "override_back_resolution": { + "name": "Переопределение разрешения для задней камеры", + "description": "Переопределяет разрешение камеры для задней камеры" + }, + "front_custom_frame_rate": { + "name": "Пользовательский кадровый режим для передней камеры", + "description": "Переопределяет частоту кадров передней камеры" + }, + "hevc_recording": { + "name": "Запись в формате HEVC", + "description": "Использует кодек HEVC (H.265) для записи видео" + } + }, + "name": "Камера", + "description": "Настройте правильные параметры для идеального снимка" }, "rules": { "name": "Правила", "description": "Управление автоматическими функциями для отдельных пользователей" }, - "camera": { - "name": "Камера", - "description": "Настройте идеальные параметры для идеального Snap", - "properties": { - "disable_cameras": { - "name": "Отключить камеры", - "description": "Запрещает Snapchat использовать выбранные камеры." - }, - "black_photos": { - "name": "Черные фото", - "description": "Заменяет снятые фото черным фоном.\nВидео не затрагиваются." - }, - "immersive_camera_preview": { - "name": "Иммерсивный предпросмотр камеры", - "description": "Запрещает Snapchat обрезать предпросмотр камеры.\nЭто может вызвать мерцание камеры на некоторых устройствах." - }, - "override_front_resolution": { - "name": "Переопределить разрешение фронтальной камеры", - "description": "Переопределяет разрешение для фронтальной камеры." - }, - "override_back_resolution": { - "name": "Переопределить разрешение задней камеры", - "description": "Переопределяет разрешение для задней камеры." - }, - "custom_resolution": { - "name": "Пользовательское разрешение", - "description": "Устанавливает пользовательское разрешение камеры: ширина x высота (например, 1920x1080).\nПользовательское разрешение должно поддерживаться вашим устройством." - }, - "front_custom_frame_rate": { - "name": "Пользовательская частота кадров фронтальной камеры", - "description": "Переопределяет частоту кадров фронтальной камеры" - }, - "back_custom_frame_rate": { - "name": "Пользовательская частота кадров задней камеры", - "description": "Переопределяет частоту кадров задней камеры" - }, - "force_camera_source_encoding": { - "name": "Принудительное кодирование источника камеры", - "description": "Принудительно использует кодирование источника камеры" - }, - "startup_default_camera": { - "name": "Камера по умолчанию при запуске", - "description": "Устанавливает камеру по умолчанию при открытии Snapchat" - }, - "hevc_recording": { - "name": "Запись в HEVC", - "description": "Использует кодек HEVC (H.265) для записи видео." - } - } - }, - "streaks_reminder": { - "name": "Напоминание о сериях", - "description": "Периодически уведомляет вас о ваших сериях", - "properties": { - "interval": { - "name": "Интервал", - "description": "Интервал между напоминаниями (в часах)" - }, - "remaining_hours": { - "name": "Оставшееся время", - "description": "Оставшееся время до отображения уведомления (в часах)" - }, - "group_notifications": { - "name": "Групповые уведомления", - "description": "Группировать уведомления в одно" - } - } - }, - "experimental": { - "name": "Экспериментальное", - "description": "Экспериментальные функции", - "properties": { - "native_hooks": { - "name": "Нативные хуки", - "description": "Небезопасные функции, которые взаимодействуют с нативным кодом Snapchat", - "properties": { - "composer_hooks": { - "name": "Хуки Composer", - "description": "Внедряет код в кроссплатформенный UI-фреймворк Composer.", - "properties": { - "show_first_created_username": { - "name": "Показывать первое созданное имя пользователя", - "description": "Показывает первое созданное имя пользователя рядом с текущим на странице профиля." - }, - "bypass_camera_roll_limit": { - "name": "Обход лимита галереи", - "description": "Увеличивает максимальное количество медиа, которое можно отправить из галереи." - }, - "custom_self_destruct_snap_delay": { - "name": "Пользовательская задержка самоуничтожения Snap", - "description": "Предоставляет больше опций для таймера самоуничтожения при отправке Snap." - }, - "composer_console": { - "name": "Консоль Composer", - "description": "Позволяет выполнять JavaScript-код в Composer (только для Arm64)." - }, - "composer_logs": { - "name": "Логи Composer", - "description": "Перенаправляет логи консоли Composer в PurrfectSnap." - } - } - }, - "disable_bitmoji": { - "name": "Отключить Bitmoji", - "description": "Отключает Bitmoji в профилях друзей" - }, - "custom_emoji_font": { - "name": "Пользовательский шрифт эмодзи", - "description": "Позволяет использовать пользовательский шрифт эмодзи. Работает только со шрифтами .ttf." - }, - "custom_shared_library": { - "name": "Пользовательская общая библиотека", - "description": "Загружает пользовательскую общую библиотеку в Snapchat. Эта функция предназначена только для тестирования." - } - } - }, - "spoof": { - "name": "Подмена", - "description": "Подменяйте различную информацию о себе", - "properties": { - "play_store_installer_package_name": { - "name": "Имя пакета установщика Play Store", - "description": "Заменяет имя пакета установщика на com.android.vending." - }, - "remove_vpn_transport_flag": { - "name": "Удалить флаг VPN-транспорта", - "description": "Запрещает Snapchat обнаруживать VPN" - }, - "remove_mock_location_flag": { - "name": "Удалить флаг фиктивного местоположения", - "description": "Запрещает Snapchat обнаруживать фиктивное местоположение." - } - } - }, - "convert_message_locally": { - "name": "Конвертировать сообщение локально", - "description": "Конвертирует Snap во внешние медиа локально. Отображается в контекстном меню загрузки чата." - }, - "media_file_picker": { - "name": "Выбор медиафайлов", - "description": "Позволяет выбрать любой видео/аудио файл из галереи." - }, - "story_logger": { - "name": "Логгер историй", - "description": "Предоставляет историю историй друзей" - }, - "call_recorder": { - "name": "Запись звонков", - "description": "Автоматически записывает аудиозвонки" - }, - "account_switcher": { - "name": "Переключатель аккаунтов", - "description": "Позволяет переключаться между аккаунтами без выхода из системы.\nДлительно нажмите на значок поиска рядом с вашим Bitmoji, чтобы открыть меню.\nПримечание: Эта функция экспериментальная и, вероятно, изменится в будущем.", - "properties": { - "auto_backup_current_account": { - "name": "Автоматическое резервное копирование текущего аккаунта", - "description": "Автоматически создает резервную копию текущего аккаунта при выходе или переключении аккаунтов." - } - } - }, - "better_transcript": { - "name": "Улучшенная транскрипция", - "description": "Улучшает транскрипцию голосовых заметок", - "properties": { - "force_transcription": { - "name": "Принудительная транскрипция голосовых заметок", - "description": "Позволяет транскрибировать все голосовые заметки" - }, - "preferred_transcription_lang": { - "name": "Предпочтительный язык транскрипции", - "description": "Предпочтительный язык для транскрипции голосовых заметок (например, RU, EN, ES, FR)" - }, - "notification_transcript": { - "name": "Транскрипция в уведомлении", - "description": "Транскрибирует голосовые заметки в уведомлениях.\nДля этой функции требуется включение предпросмотра чата в 'Улучшенных уведомлениях'." - } - } - }, - "voice_note_auto_play": { - "name": "Автовоспроизведение голосовых заметок", - "description": "Автоматически воспроизводит следующую голосовую заметку после окончания текущей." - }, - "friend_notes": { - "name": "Заметки о друзьях", - "description": "Позволяет добавлять заметки в профили друзей." - }, - "cof_experiments": { - "name": "Эксперименты COF", - "description": "Включает невыпущенные/бета-функции Snapchat." - }, - "context_menu_fix": { - "name": "Исправление контекстного меню", - "description": "Пытается исправить меню ленты друзей, так как при оффлайн-режиме оно может отображаться некорректно." - }, - "app_lock": { - "name": "Блокировка приложения", - "description": "Запрещает доступ к Snapchat без пароля", - "properties": { - "lock_on_resume": { - "name": "Блокировать при возобновлении", - "description": "Блокирует приложение при повторном открытии" - } - } - }, - "infinite_story_boost": { - "name": "Бесконечный буст историй", - "description": "Обход лимита времени для буста историй" - }, - "meo_passcode_bypass": { - "name": "Обход пароля 'Только для моих глаз'", - "description": "Обходит пароль 'Только для моих глаз'.\nЭто сработает только если пароль был введен правильно ранее." - }, - "no_friend_score_delay": { - "name": "Нет задержки при просмотре очков друга", - "description": "Убирает задержку при просмотре очков друга." - }, - "best_friend_pinning": { - "name": "Закрепление лучшего друга", - "description": "Позволяет закрепить друга как лучшего друга номер один. Примечание: Только вы можете видеть закрепленного лучшего друга." - }, - "e2ee": { - "name": "Сквозное шифрование", - "description": "Шифрует ваши сообщения с помощью AES, используя общий секретный ключ.\nОбязательно сохраните ключ в безопасном месте!", - "properties": { - "encrypted_message_indicator": { - "name": "Индикатор зашифрованного сообщения", - "description": "Добавляет эмодзи 🔒 рядом с зашифрованными сообщениями." - }, - "force_message_encryption": { - "name": "Принудительное шифрование сообщений", - "description": "Предотвращает отправку зашифрованных сообщений людям, у которых не включено E2E-шифрование, только если выбрано несколько бесед." - } - } - }, - "add_friend_source_spoof": { - "name": "Подмена источника добавления в друзья", - "description": "Подменяет источник запроса на добавление в друзья" - }, - "hidden_snapchat_plus_features": { - "name": "Скрытые функции Snapchat+", - "description": "Включает невыпущенные/бета-функции Snapchat+.\nМожет не работать в старых версиях Snapchat." - }, - "custom_streaks_expiration_format": { - "name": "Пользовательский формат истечения серий", - "description": "Настраивает формат истечения серий.\n\nДоступные переменные:\n - %c: количество серий\n - %e: эмодзи песочных часов\n - %d: дни\n - %h: часы\n - %m: минуты\n - %s: секунды\n - %t: оставшееся время" - }, - "prevent_forced_logout": { - "name": "Предотвратить принудительный выход", - "description": "Запрещает Snapchat выходить из системы при входе на другом устройстве." - }, - "snapscore_changes": { - "name": "Изменения Snapscore", - "description": "Отслеживает изменения Snapscore друзей.\nИспользуйте эту функцию только в новых версиях Snapchat." - } - } - }, "scripting": { - "name": "Скриптинг", - "description": "Запускайте пользовательские скрипты для расширения PurrfectSnap", "properties": { - "developer_mode": { - "name": "Режим разработчика", - "description": "Показывает отладочную информацию в интерфейсе Snapchat." - }, "module_folder": { - "name": "Папка модулей", + "name": "Папка модуля", "description": "Папка, в которой находятся скрипты" }, - "auto_reload": { - "name": "Автоперезагрузка", - "description": "Автоматически перезагружает скрипты при их изменении" + "disable_log_anonymization": { + "description": "Отключает анонимизацию журналов", + "name": "Отключение анонимизации журнала" + }, + "developer_mode": { + "name": "Режим разработчика", + "description": "Отображает отладочную информацию на пользовательском интерфейсе Snapchat" }, "integrated_ui": { - "name": "Интегрированный интерфейс", - "description": "Позволяет скриптам добавлять пользовательские элементы интерфейса в Snapchat." + "name": "Интегрированный пользовательский интерфейс", + "description": "Позволяет скриптам добавлять пользовательские компоненты интерфейса в Snapchat" }, - "disable_log_anonymization": { - "name": "Отключить анонимизацию логов", - "description": "Отключает анонимизацию логов" - }, - "disable_optimization": { - "name": "Отключить оптимизацию", - "description": "Отключает оптимизацию скриптов. Это может вызвать проблемы с производительностью." + "auto_reload": { + "name": "Автоматическая перезагрузка", + "description": "Автоматически перезагружает скрипты при их изменении" } - } - }, - "friend_tracker": { - "name": "Трекер друзей", - "description": "Записывает активность друзей в Snapchat", - "properties": { - "record_messaging_events": { - "name": "Запись событий сообщений", - "description": "Записывает события сообщений, такие как открытие Snap, чтение сообщения и т.д." - }, - "allow_running_in_background": { - "name": "Разрешить работу в фоновом режиме", - "description": "Позволяет трекеру работать в фоновом режиме. Примечание: это значительно разрядит батарею." - }, - "auto_purge": { - "name": "Автоочистка", - "description": "Автоматически удаляет кэшированные события, которые старше указанного периода времени." - } - } + }, + "name": "Скриптинг", + "description": "Запуск пользовательских скриптов для расширения SnapEnhance" } }, + "notices": { + "unstable": "⚠ Нестабильный", + "ban_risk": "⚠ Эта функция может стать причиной бана", + "internal_behavior": "⚠ Это может нарушить внутреннее поведение Snapchat" + }, "options": { - "app_appearance": { - "always_light": "Всегда светлая", - "always_dark": "Всегда темная" - }, - "friend_feed_menu_buttons": { - "auto_download": "⬇️ Автозагрузка", - "auto_save": "💬 Автосохранение сообщений", - "unsaveable_messages": "⬇️ Несохраняемые сообщения", - "auto_open_snaps": "📷 Автооткрытие Snap", - "stealth": "👻 Скрытый режим", - "mark_snaps_as_seen": "👀 Отметить Snap как просмотренные", - "mark_stories_as_seen_locally": "👀 Отметить истории как просмотренные локально", - "conversation_info": "👤 Информация о беседе", - "e2e_encryption": "🔒 Использовать E2E шифрование" - }, - "path_format": { - "create_author_folder": "Создать папку для каждого автора", - "create_source_folder": "Создать папку для каждого типа медиа-источника.", - "append_hash": "Добавить уникальный хэш к имени файла", - "append_source": "Добавить источник медиа к имени файла", - "append_username": "Добавить имя пользователя к имени файла", - "append_date_time": "Добавить дату и время к имени файла" - }, - "auto_download_sources": { - "friend_snaps": "Snap друзей", - "friend_stories": "Истории друзей", - "public_stories": "Публичные истории", - "spotlight": "Spotlight" - }, - "logging": { - "started": "Начато", - "success": "Успешно", - "progress": "В процессе", - "failure": "Ошибка" - }, - "notifications": { - "chat_screenshot": "Скриншот", - "chat_screen_record": "Запись экрана", - "snap_replay": "Повтор Snap", - "camera_roll_save": "Сохранение в галерею", - "chat": "Чат", - "chat_reply": "Ответ в чате", - "snap": "Snap", - "typing": "Печатает", - "stories": "Истории", - "speaking": "Говорит", - "chat_reaction": "Реакция в ЛС", - "group_chat_reaction": "Реакция в группе", - "initiate_audio": "Входящий аудиозвонок", - "abandon_audio": "Пропущенный аудиозвонок", - "initiate_video": "Входящий видеозвонок", - "abandon_video": "Пропущенный видеозвонок", - "map_live_location": "Текущее местоположение на карте" - }, - "gallery_media_send_override": { - "always_ask": "Всегда спрашивать", - "ORIGINAL": "Оригинальное медиа", - "NOTE": "Аудиозаметка", - "SNAP": "Snap", - "SAVEABLE_SNAP": "Сохраняемый Snap" - }, - "strip_media_metadata": { - "hide_caption_text": "Скрыть подпись", - "hide_snap_filters": "Скрыть фильтры Snap", - "hide_extras": "Скрыть доп. информацию (например, упоминания)", - "remove_audio_note_duration": "Удалить длительность аудиозаметки", - "remove_audio_note_transcript_capability": "Удалить возможность транскрипции аудиозаметки" - }, - "hide_ui_components": { - "hide_profile_call_buttons": "Скрыть кнопки звонка в профиле", - "hide_chat_call_buttons": "Скрыть кнопки звонка в чате", - "hide_live_location_share_button": "Скрыть кнопку 'Поделиться текущим местоположением'", - "hide_stickers_button": "Скрыть кнопку стикеров", - "hide_voice_record_button": "Скрыть кнопку записи голоса", - "hide_unread_chat_hint": "Скрыть подсказку о непрочитанном чате", - "hide_post_to_story_buttons": "Скрыть кнопки 'Опубликовать в историю' перед отправкой Snap.", - "hide_billboard_prompt": "Скрыть рекламный баннер в ленте друзей", - "hide_snapchat_plus_gift_reminders": "Скрыть напоминания о подарках Snapchat+ в беседах", - "hide_map_reactions": "Скрыть реакции на карте" - }, - "hide_story_suggestions": { - "hide_suggested_friend_stories": "Скрыть предложенные истории друзей", - "hide_my_stories": "Скрыть мои истории" - }, "home_tab": { - "map": "Карта", "chat": "Чат", - "camera": "Камера", - "discover": "Обзор", - "spotlight": "Spotlight" - }, - "add_friend_source_spoof": { - "added_by_username": "По имени пользователя", - "added_by_mention": "По упоминанию", - "added_by_group_chat": "Из группового чата", - "added_by_qr_code": "По QR-коду", - "added_by_community": "Из сообщества", - "added_by_quick_add": "Через быстрое добавление (высокий риск бана)" - }, - "bypass_video_length_restriction": { - "single": "Один медиафайл", - "split": "Разделенный медиафайл" - }, - "old_bitmoji_selfie": { - "2d": "2D Bitmoji", - "3d": "3D Bitmoji" - }, - "disable_confirmation_dialogs": { - "erase_message": "Стереть сообщение", - "remove_friend": "Удалить друга", - "block_friend": "Заблокировать друга", - "ignore_friend": "Игнорировать друга", - "hide_friend": "Скрыть друга", - "hide_conversation": "Скрыть беседу", - "clear_conversation": "Очистить беседу из ленты друзей" - }, - "auto_reload": { - "snapchat_only": "Только Snapchat", - "all": "Все (Snapchat + PurrfectSnap)" - }, - "edit_text_override": { - "multi_line_chat_input": "Многострочный ввод в чате", - "bypass_text_input_limit": "Обход лимита на ввод текста" + "discover": "Открытие", + "spotlight": "Spotlight", + "map": "Карта", + "camera": "Камера" }, "auto_purge": { "never": "Никогда", - "1_hour": "1 час", - "3_hours": "3 часа", - "6_hours": "6 часов", - "12_hours": "12 часов", - "1_day": "1 день", - "3_days": "3 дня", - "1_week": "1 неделя", - "2_weeks": "2 недели", - "1_month": "1 месяц", - "3_months": "3 месяца", - "6_months": "6 месяцев" + "3_days": "3 Дня", + "1_month": "1 Месяц", + "1_hour": "1 Час", + "3_hours": "3 Часа", + "6_hours": "6 Часов", + "12_hours": "12 Часов", + "1_week": "1 Неделя", + "2_weeks": "2 Недели", + "3_months": "3 Месяца", + "6_months": "6 Месяцев", + "1_day": "1 День" }, - "disable_story_sections": { - "friends": "Друзья", - "suggested_stories": "Предложенные истории", - "following": "Подписки", - "discover": "Обзор" + "path_format": { + "append_hash": "Добавить уникальный хеш к имени файла", + "append_source": "Добавить источник медиафайла к имени файла", + "create_author_folder": "Создать папку для каждого автора", + "create_source_folder": "Создать папку для каждого типа источника медиафайла", + "append_username": "Добавить имя пользователя к имени файла", + "append_date_time": "Добавить дату и время к имени файла" + }, + "notifications": { + "chat": "Чат", + "chat_reply": "Ответ в чате", + "initiate_audio": "Входящий аудиовызов", + "chat_screenshot": "Снимок экрана", + "chat_screen_record": "Запись экрана", + "snap_replay": "Повтор Snap", + "camera_roll_save": "Сохранить в камеру", + "typing": "Печать", + "stories": "Истории", + "initiate_video": "Входящий видеовызов", + "abandon_video": "Пропущенный видеовызов", + "snap": "Snap", + "abandon_audio": "Пропущенный аудиовызов", + "chat_reaction": "Реакция в ЛС", + "group_chat_reaction": "Реакция в группе" + }, + "add_friend_source_spoof": { + "added_by_mention": "По упоминанию", + "added_by_username": "По имени пользователя", + "added_by_group_chat": "В групповом чате", + "added_by_qr_code": "По QR-коду", + "added_by_community": "По сообществу" + }, + "disable_confirmation_dialogs": { + "hide_friend": "Скрыть друга", + "hide_conversation": "Скрыть беседу", + "clear_conversation": "Очистить беседу из Ленты друзей", + "ignore_friend": "Игнорировать друга", + "remove_friend": "Удалить друга", + "block_friend": "Заблокировать друга", + "erase_message": "Удалить сообщение" }, "disable_cameras": { "front": "Передняя камера", "back": "Задняя камера" }, "disable_permission_requests": { + "nearby_devices": "Устройства поблизости", + "phone_calls": "Телефонные вызовы", "notifications": "Уведомления", - "read_media_images": "Чтение изображений", - "read_media_video": "Чтение видео", + "read_media_video": "Чтение медиа-видео", "camera": "Камера", "microphone": "Микрофон", + "read_media_images": "Чтение медиа-изображений", "location": "Местоположение", - "read_contacts": "Чтение контактов", - "nearby_devices": "Устройства поблизости", - "phone_calls": "Телефонные звонки" + "read_contacts": "Чтение контактов" + }, + "friend_feed_menu_buttons": { + "stealth": "👻 Режим невидимки", + "auto_download": "⬇️ Автозагрузка", + "auto_save": "💬 Автосохранение сообщений", + "unsaveable_messages": "⬇️ Непроходимые сообщения", + "mark_stories_as_seen_locally": "👀 Отметить истории как просмотренные локально", + "conversation_info": "👤 Информация о беседе", + "e2e_encryption": "🔒 Использовать конечно-конечное шифрование", + "mark_snaps_as_seen": "👀 Отметить снапы как просмотренные", + "auto_open_snaps": "📷 Автоматическое открытие Снапов" + }, + "gallery_media_send_override": { + "ORIGINAL": "Оригинал", + "NOTE": "Аудио-заметка", + "SNAP": "Snap" + }, + "hide_ui_components": { + "hide_unread_chat_hint": "Убрать подсказку о непрочитанных сообщениях", + "hide_profile_call_buttons": "Убрать кнопки звонка в профиле", + "hide_chat_call_buttons": "Убрать кнопки звонка в чате", + "hide_live_location_share_button": "Убрать кнопку обмена местоположением в реальном времени", + "hide_stickers_button": "Убрать кнопку стикеров", + "hide_voice_record_button": "Убрать кнопку голосовой записи" + }, + "app_appearance": { + "always_light": "Всегда светлый", + "always_dark": "Всегда темный" + }, + "auto_download_sources": { + "friend_stories": "Истории друзей", + "public_stories": "Публичные истории", + "spotlight": "Spotlight", + "friend_snaps": "Snap друзей" + }, + "logging": { + "started": "Начало", + "success": "Успех", + "progress": "Прогресс", + "failure": "Ошибка" + }, + "auto_reload": { + "all": "Все (Snapchat + SnapEnhance)", + "snapchat_only": "Только Snapchat" + }, + "edit_text_override": { + "multi_line_chat_input": "Многострочный ввод в чат", + "bypass_text_input_limit": "Обход ограничения на количество вводимого текста" }, "message_indicators": { - "encryption_indicator": "Добавляет значок 🔒 рядом с сообщениями, которые были отправлены только вам.", - "platform_indicator": "Добавляет значок платформы, с которой был отправлен медиафайл (например, Android, iOS, Web).", - "location_indicator": "Добавляет значок 📍 к Snap, когда они были отправлены с включенным местоположением.", - "ovf_editor_indicator": "Указывает, был ли Snap отправлен с помощью редактора OVF.", - "director_mode_indicator": "Добавляет значок ✏️ к Snap, когда они были отправлены в режиме режиссера, который можно использовать для отправки изображений из галереи как Snap." + "encryption_indicator": "Добавляет значок 🔒 рядом с сообщениями, отправленными только вам", + "platform_indicator": "Добавляет значок платформы, с которой было отправлено медиа (например, Android, iOS, веб)", + "location_indicator": "Добавляет значок 📍 к снэпам, если было включено местоположение при отправке", + "ovf_editor_indicator": "Указывает, был ли снэп отправлен с использованием редактора OVF", + "director_mode_indicator": "Добавляет значок ✏️ к снэпам, если они были отправлены с использованием режима режиссера, который можно использовать для отправки изображений из галереи в качестве снэпов" + }, + "strip_media_metadata": { + "hide_caption_text": "Скрыть текст подписи", + "hide_extras": "Скрыть дополнительные элементы", + "hide_snap_filters": "Скрыть фильтры Snap", + "remove_audio_note_duration": "Убрать длительность аудиозаметки", + "remove_audio_note_transcript_capability": "Убрать возможность транскрибации аудиозаметки" + }, + "hide_story_suggestions": { + "hide_suggested_friend_stories": "Скрыть предложенные истории друзей", + "hide_my_stories": "Скрыть Мои истории" + }, + "disable_story_sections": { + "following": "Подписан на", + "discover": "Исследовать", + "friends": "Друзья" + }, + "bypass_video_length_restriction": { + "single": "Одиночные медиафайлы", + "split": "Разделение медиафайлов" + }, + "old_bitmoji_selfie": { + "2d": "2D Битмоджи", + "3d": "3D Битмоджи" }, "auto_mark_as_read": { - "conversation_read": "Отмечать беседу как прочитанную при отправке сообщения", - "snap_reply": "Отмечать Snap как прочитанные при ответе на них", - "save_snap_in_chat": "Отмечать Snap как прочитанные при сохранении их в чате в скрытом режиме." + "conversation_read": "Пометить беседу как прочитанную при отправке сообщения", + "snap_reply": "Отмечать снэпы как прочитанные при ответе на них" }, "friend_mutation_notifier": { - "remove_friend": "Уведомлять, когда кто-то удаляет вас из друзей", - "birthday_changes": "Уведомлять, когда кто-то меняет свой день рождения", - "bitmoji_selfie_changes": "Уведомлять, когда кто-то меняет свое селфи Bitmoji", - "bitmoji_avatar_changes": "Уведомлять, когда кто-то меняет свой аватар Bitmoji", - "bitmoji_background_changes": "Уведомлять, когда кто-то меняет свой фон Bitmoji", - "bitmoji_scene_changes": "Уведомлять, когда кто-то меняет свою сцену Bitmoji" - }, - "snapchat_plus": { - "not_subscribed": "Нет подписки", - "basic": "Базовая", - "ad_free": "Без рекламы" - }, - "double_tap_chat_action": { - "like_message": "Лайкнуть сообщение", - "copy_text": "Скопировать текст", - "delete_message": "Удалить сообщение", - "mark_as_read": "Отметить как прочитанное", - "custom_emoji_reaction": "Своя эмодзи-реакция" - }, - "startup_default_camera": { - "front": "Передняя камера", - "back": "Задняя камера" + "bitmoji_selfie_changes": "Уведомление о изменении кем-то своего битмоджи-селфи", + "remove_friend": "Уведомление о том, что кто-то удалил вас из друзей", + "birthday_changes": "Уведомление о изменении дня рождения кого-то", + "bitmoji_avatar_changes": "Уведомление о изменении кем-то своего аватара Битмоджи", + "bitmoji_scene_changes": "Уведомление о изменении кем-то своего сценария Bitmoji", + "bitmoji_background_changes": "Уведомление о изменении кем-то своего фонового изображения в Bitmoji" } } }, - "friend_menu_option": { - "mark_snaps_as_seen": "Отметить Snap как просмотренные", - "mark_stories_as_seen_locally": "Отметить истории как просмотренные локально", - "preview": "Предпросмотр", - "stealth_mode": "Скрытый режим", - "auto_download_blacklist": "Черный список автозагрузки", - "anti_auto_save": "Анти-автосохранение" - }, - "content_type": { - "CHAT": "Чат", - "SNAP": "Snap", - "EXTERNAL_MEDIA": "Внешние медиа", - "NOTE": "Аудиозаметка", - "STICKER": "Стикер", - "SHARE": "Поделиться", - "STATUS": "Статус", - "LOCATION": "Местоположение", - "STATUS_SAVE_TO_CAMERA_ROLL": "Сохранено в галерею.", - "STATUS_CONVERSATION_CAPTURE_SCREENSHOT": "Скриншот", - "STATUS_CONVERSATION_CAPTURE_RECORD": "Запись экрана", - "STATUS_CALL_MISSED_VIDEO": "Пропущенный видеозвонок", - "STATUS_CALL_MISSED_AUDIO": "Пропущенный аудиозвонок", - "LIVE_LOCATION_SHARE": "Поделиться текущим местоположением", - "CREATIVE_TOOL_ITEM": "Элемент креативного инструмента", - "FAMILY_CENTER_INVITE": "Приглашение в Семейный центр", - "FAMILY_CENTER_ACCEPT": "Принятие в Семейный центр", - "FAMILY_CENTER_LEAVE": "Выход из Семейного центра", - "STATUS_PLUS_GIFT": "Подарок Status+", - "TINY_SNAP": "Маленький Snap", - "STATUS_COUNTDOWN": "Обратный отсчет", - "MAP_REACTION": "Реакция на карте" - }, - "media_download_source": { - "none": "Нет", - "pending": "В ожидании", - "chat_media": "Медиа из чата", - "story": "История", - "public_story": "Публичная история", - "spotlight": "Spotlight", - "profile_picture": "Фото профиля", - "story_logger": "Логгер историй", - "message_logger": "Логгер сообщений", - "merged": "Объединенные", - "voice_call": "Голосовой звонок" - }, - "chat_action_menu": { - "preview_button": "Предпросмотр", - "download_button": "Скачать", - "delete_logged_message_button": "Удалить сохраненное сообщение", - "show_chat_edit_history": "Показать историю изменений чата", - "convert_message": "Конвертировать сообщение" - }, - "opera_context_menu": { - "download": "Скачать медиа", - "sent_at": "Отправлено {date}", - "created_at": "Создано {date}", - "expires_at": "Истекает {date}", - "media_size": "Размер медиа: {size}", - "media_duration": "Длительность медиа: {duration} мс", - "show_debug_info": "Показать отладочную информацию" - }, - "modal_option": { - "profile_info": "Информация о профиле", - "close": "Закрыть" - }, - "gallery_media_send_override": { - "multiple_media_toast": "Вы можете отправить только один медиафайл за раз" - }, - "mark_as_seen": { - "no_unseen_snaps_toast": "Непросмотренные Snap не найдены!", - "seen_toast": "Отмечено как просмотренное!", - "unseen_toast": "Отмечено как непросмотренное!", - "already_seen_toast": "Уже отмечено как просмотренное!", - "already_unseen_toast": "Уже отмечено как непросмотренное!" - }, - "conversation_preview": { - "streak_expiration": "Истекает через {day} дней {hour} часов {minute} минут", - "total_messages": "Всего отправлено/получено сообщений: {count}", - "title": "Предпросмотр", - "unknown_user": "Неизвестный пользователь", - "no_messages": "Сообщения не найдены!" - }, - "profile_info": { - "title": "Информация о профиле", - "first_created_username": "Первое созданное имя пользователя", - "mutable_username": "Изменяемое имя пользователя", - "display_name": "Отображаемое имя", - "added_date": "Дата добавления", - "birthday": "День рождения: {day} {month}", - "hidden_birthday": "День рождения: Скрыто", - "friendship": "Дружба", - "add_source": "Источник добавления", - "snapchat_plus": "Snapchat+", - "snapchat_plus_state": { - "subscribed": "Есть подписка", - "not_subscribed": "Нет подписки" - } - }, - "friendship_link_type": { - "mutual": "Взаимная", - "outgoing": "Исходящая", - "blocked": "Заблокирован", - "deleted": "Удален", - "following": "Подписка", - "suggested": "Предложенный", - "incoming": "Входящая", - "incoming_follower": "Входящий подписчик" - }, - "bulk_messaging_action": { - "choose_action_title": "Выберите действие", - "progress_status": "Обработка {index} из {total}", - "selection_dialog_continue_button": "Продолжить", - "confirmation_dialog": { - "title": "Вы уверены?", - "message": "Это затронет всех выбранных друзей. Это действие необратимо." - }, - "actions": { - "remove_friends": "Удалить друзей", - "clear_conversations": "Очистить беседы" - } - }, "chat_export": { "exporter_dialog": { - "select_conversations_title": "Выберите беседы", - "text_field_selection": "Выбрано: {count}", + "message_type_filter_title": "Фильтровать сообщения по типу", "text_field_selection_all": "Все", "export_file_format_title": "Формат файла экспорта", - "message_type_filter_title": "Фильтровать сообщения по типу", - "amount_of_messages_title": "Количество сообщений (оставьте пустым для всех)", + "select_conversations_title": "Выберите разговоры", + "text_field_selection": "{amount} выбрано", + "amount_of_messages_title": "Количество сообщений (оставьте поле пустым для всех)", "download_medias_title": "Скачать медиафайлы" }, + "processing_chats": "Обработка цепочек: {amount}...", + "export_fail": "Не удалось экспортировать разговор {conversation}", + "writing_output": "Запись вывода...", + "finished": "Сделанно! Теперь вы можете закрыть это диалоговое окно.", + "no_messages_found": "Сообщений не найдено!", + "exporting_message": "Экспорт {conversation}...", "dialog_negative_button": "Отмена", "dialog_positive_button": "Экспорт", - "exported_to": "Экспортировано в {path}.", "exporting_chats": "Экспорт чатов...", - "processing_chats": "Обработка {amount} бесед...", - "export_fail": "Не удалось экспортировать беседу {conversation}.", - "writing_output": "Запись результата...", - "finished": "Готово! Теперь вы можете закрыть это диалоговое окно.", - "no_messages_found": "Сообщения не найдены!", - "exporting_message": "Экспорт {conversation}..." - }, - "button": { - "ok": "OK", - "positive": "Да", - "negative": "Нет", - "cancel": "Отмена", - "open": "Открыть", - "download": "Скачать", - "send": "Отправить", - "restore_original": "Восстановить оригинал", - "convert_external_media": "Конвертировать внешние медиа", - "save": "Сохранить" - }, - "tracker_events": { - "conversation_enter": "Вход в беседу", - "conversation_exit": "Выход из беседы", - "started_typing": "Начал(а) печатать", - "stopped_typing": "Перестал(а) печатать", - "started_speaking": "Начал(а) говорить", - "stopped_speaking": "Перестал(а) говорить", - "started_peeking": "Начал(а) подглядывать", - "stopped_peeking": "Перестал(а) подглядывать", - "message_read": "Сообщение прочитано", - "message_deleted": "Сообщение удалено", - "message_saved": "Сообщение сохранено", - "message_unsaved": "Сохранение отменено", - "message_edited": "Сообщение отредактировано", - "message_reaction_add": "Реакция на сообщение добавлена", - "message_reaction_remove": "Реакция на сообщение удалена", - "snap_opened": "Snap открыт", - "snap_replayed": "Snap пересмотрен", - "snap_replayed_twice": "Snap пересмотрен дважды", - "snap_screenshot": "Скриншот Snap", - "snap_screen_record": "Запись экрана Snap" - }, - "tracker_actions": { - "log": "Лог", - "in_app_notification": "Уведомление в приложении", - "push_notification": "Push-уведомление", - "custom": "Пользовательское" - }, - "better_notifications": { - "button": { - "reply": "Ответить", - "download": "Скачать", - "mark_as_read": "Отметить как прочитанное" - } - }, - "profile_picture_downloader": { - "button": "Скачать фото профиля", - "title": "Загрузчик фото профиля", - "avatar_option": "Аватар", - "background_option": "Фон" + "exported_to": "Экспортировано в {path}" }, "call_start_confirmation": { "dialog_title": "Начать звонок", "dialog_message": "Вы уверены, что хотите начать звонок?" }, - "half_swipe_notifier": { - "notification_channel_name": "Подглядывание", - "notification_content_dm": "{friend} только что подглядывал(а) в ваш чат в течение {duration} секунд.", - "notification_content_group": "{friend} только что подглядывал(а) в {group} в течение {duration} секунд" - }, - "download_processor": { - "attachment_type": { - "snap": "Snap", - "sticker": "Стикер", - "gif": "GIF", - "external_media": "Внешние медиа", - "note": "Заметка", - "original_story": "Оригинальная история" + "actions": { + "export_memories": { + "name": "Экспорт воспоминаний", + "description": "Экспортирует воспоминания в ZIP-файл" }, - "select_attachments_title": "Выберите вложения", - "download_started_toast": "Загрузка началась", - "unsupported_content_type_toast": "Неподдерживаемый тип контента!", - "failed_no_longer_available_toast": "Медиа больше не доступно", - "no_attachments_toast": "Вложения не найдены!", - "already_queued_toast": "Медиа уже в очереди!", - "already_downloaded_toast": "Медиа уже загружено!", - "content_saved_toast": "Сохранено!", - "download_toast": "Загрузка {type}...", - "processing_toast": "Обработка {type}...", - "failed_generic_toast": "Не удалось загрузить", - "failed_to_create_preview_toast": "Не удалось создать предпросмотр.", - "failed_processing_toast": "Ошибка обработки: {error}", - "failed_gallery_toast": "Не удалось сохранить в галерею: {error}.", - "dash_no_chapter": "Глава не найдена", - "dash_dialog": { - "title": "Скачать DASH медиа", - "download_all": "Скачать все", - "segment_text": "Сегмент {from} - {to}" + "change_language": { + "description": "Изменяет язык SnapEnhance", + "name": "Изменение языка" + }, + "clean_snapchat_cache": { + "name": "Очистить кеш Snapchat", + "description": "Очищает кэш Snapchat" + }, + "manage_friend_list": { + "name": "Управление списком друзей", + "description": "Импортируйте/экспортируйте список друзей при резервном копировании" + }, + "export_chat_messages": { + "name": "Экспорт сообщений чата", + "description": "Экспортирует сообщения разговора в файл JSON/HTML/TXT" + }, + "regen_mappings": { + "name": "Восстановить сопоставления", + "description": "Восстановить сопоставления вручную" + }, + "bulk_messaging_action": { + "name": "Массовая рассылка сообщений", + "description": "Выполняет такие операции, как удаление друзей или массовое удаление бесед" } }, + "download_processor": { + "dash_no_chapter": "Глава не найдена", + "attachment_type": { + "snap": "Snap", + "original_story": "Оригинальная история", + "sticker": "наклейка", + "external_media": "Внешняя медиа", + "note": "Примечание" + }, + "no_attachments_toast": "Вложений не найдено!", + "already_queued_toast": "СМИ уже в очереди!", + "already_downloaded_toast": "Медиа уже загружено!", + "download_toast": "Загрузка {path}...", + "processing_toast": "Обработка {path}...", + "failed_generic_toast": "Не удалось скачать", + "failed_to_create_preview_toast": "Не удалось создать предварительный просмотр", + "failed_gallery_toast": "Не удалось сохранить в галерею {error}", + "unsupported_content_type_toast": "Неподдерживаемый тип контента!", + "failed_no_longer_available_toast": "Медиа больше не доступны", + "failed_processing_toast": "Не удалось обработать {error}", + "select_attachments_title": "Выберите вложения для загрузки", + "download_started_toast": "Загрузка началась", + "dash_dialog": { + "title": "Скачать тире медиа", + "download_all": "Скачать все", + "segment_text": "Сегмент {from} – {to}" + } + }, + "profile_info": { + "display_name": "Отображаемое имя", + "added_date": "Дата добавления", + "birthday": "День рождения: {месяц} {день}", + "hidden_birthday": "День рождения: Скрытый", + "snapchat_plus_state": { + "subscribed": "Подписан", + "not_subscribed": "Не подписан" + }, + "friendship": "Дружба", + "add_source": "Добавить источник", + "snapchat_plus": "Снапчат Плюс", + "first_created_username": "Первое созданное имя пользователя", + "mutable_username": "Изменяемое имя пользователя", + "title": "Информация о профиле" + }, + "friendship_link_type": { + "following": "Следующий", + "suggested": "Предложенный", + "incoming": "Входящий", + "incoming_follower": "Входящий подписчик", + "mutual": "Взаимный", + "outgoing": "Исходящий", + "blocked": "Заблокировано", + "deleted": "Удалено" + }, + "bulk_messaging_action": { + "choose_action_title": "Выберите действие", + "progress_status": "Обработка {index} из {total}", + "confirmation_dialog": { + "message": "Это повлияет на всех выбранных друзей. Это действие не может быть отменено.", + "title": "Вы уверены?" + }, + "actions": { + "clear_conversations": "Очистить разговоры", + "remove_friends": "Удалить друзей" + }, + "selection_dialog_continue_button": "Продолжать" + }, + "better_notifications": { + "button": { + "download": "Скачать", + "reply": "Ответить", + "mark_as_read": "Пометить, как прочитанное" + } + }, + "profile_picture_downloader": { + "button": "Загрузить изображение профиля", + "background_option": "Фон", + "title": "Загружает изображение профиля", + "avatar_option": "Аватар" + }, + "mark_as_seen": { + "seen_toast": "Отмечено как замеченное!", + "unseen_toast": "Помечено как невидимое!", + "already_seen_toast": "Уже отмечено как просмотренное!", + "already_unseen_toast": "Уже отмечено как невидимое!", + "no_unseen_snaps_toast": "Нет непросмотренных Snap!" + }, "streaks_reminder": { - "notification_title": "Серии", - "notification_text": "Вы потеряете свою серию с {friend} через {hoursLeft} часов." + "notification_text": "Вы потеряете свою серию с {friend} через {hoursLeft} ч", + "notification_title": "Полосы" + }, + "content_type": { + "STICKER": "Стикер", + "NOTE": "Голосове сообщение", + "STATUS": "Статус", + "LOCATION": "локация", + "EXTERNAL_MEDIA": "Внешние носитель", + "STATUS_SAVE_TO_CAMERA_ROLL": "Сохранено в Галерею", + "STATUS_CONVERSATION_CAPTURE_SCREENSHOT": "Снимок экрана", + "STATUS_CONVERSATION_CAPTURE_RECORD": "Запись экрана", + "STATUS_CALL_MISSED_VIDEO": "Пропущенный видеовызов", + "CREATIVE_TOOL_ITEM": "Креативный элемент", + "FAMILY_CENTER_INVITE": "Приглашение в Центр семьи", + "FAMILY_CENTER_LEAVE": "Покинуть Центр семьи", + "STATUS_COUNTDOWN": "Обратный отсчёт", + "FAMILY_CENTER_ACCEPT": "Принятие приглашения в Центр семьи", + "STATUS_PLUS_GIFT": "Статус Plus подарок", + "TINY_SNAP": "Маленький Snap", + "MAP_REACTION": "Реакция на карту", + "LIVE_LOCATION_SHARE": "Поделиться местоположением в реальном времени", + "STATUS_CALL_MISSED_AUDIO": "Пропущенный аудиовызов", + "CHAT": "Чат", + "SNAP": "Snap" + }, + "media_download_source": { + "pending": "В ожидании", + "merged": "Объединённый", + "chat_media": "Медиа в чате", + "story": "История", + "none": "Ничего", + "public_story": "Публичная история", + "story_logger": "Журнал историй", + "message_logger": "Журнал сообщений", + "voice_call": "Голосовой вызов", + "profile_picture": "Аватар", + "spotlight": "Spotlight" + }, + "opera_context_menu": { + "media_size": "Размер медиа: {size}", + "download": "Скачать медиа", + "sent_at": "Отправлено {date}", + "created_at": "Создано {date}", + "expires_at": "Истекает {date}", + "media_duration": "Продолжительность медиа: {duration} мс", + "show_debug_info": "Показать отладочную информацию" + }, + "friend_menu_option": { + "mark_stories_as_seen_locally": "Отметить истории как просмотренные локально", + "preview": "Предварительный просмотр", + "mark_snaps_as_seen": "Отметить снэпы как просмотренные", + "stealth_mode": "Режим невидимки", + "auto_download_blacklist": "Черный список автозагрузки", + "anti_auto_save": "Анти-автосохранение" + }, + "chat_action_menu": { + "preview_button": "Предпросмотр", + "download_button": "Скачать", + "delete_logged_message_button": "Удалить созраненные сообщения", + "convert_message": "Преобразовать сообщение", + "edit_message": "Редактировать сообщение" + }, + "gallery_media_send_override": { + "multiple_media_toast": "Вы можете отправить только одно медиа за раз" + }, + "modal_option": { + "close": "Закрыть", + "profile_info": "Информация о профиле" }, "biometric_auth": { - "unlock_button": "Разблокировать", "title": "Разблокировать Snapchat", - "subtitle": "Пожалуйста, аутентифицируйтесь, чтобы разблокировать Snapchat" - }, - "end_to_end_encryption": { - "toolbox": { - "no_shared_key": "У вас еще нет общего секрета с этим другом. Нажмите ниже, чтобы создать новый.", - "shared_key_fingerprint": "Ваш отпечаток:\n\n{fingerprint}\n\nУбедитесь, что он совпадает с отпечатком вашего друга!", - "initiate_exchange_button": "Инициировать обмен ключами" - }, - "confirmation_dialogs": { - "title": "Сквозное шифрование", - "confirmation_1": "ВНИМАНИЕ: это перезапишет ваш существующий ключ. Вы потеряете доступ ко всем зашифрованным сообщениям от этого друга. Вы уверены, что хотите продолжить?", - "confirmation_2": "Вы ДЕЙСТВИТЕЛЬНО уверены, что хотите продолжить? Это ваш последний шанс передумать." - }, - "unencrypted_conversation_send_failure_toast": "Вы не можете отправлять зашифрованный контент одновременно в зашифрованные и незашифрованные беседы!", - "native_hooks_send_failure_toast": "Не удалось отправить! Пожалуйста, включите нативные хуки в настройках.", - "no_participants_to_encrypt_toast": "В этой беседе нет друзей, с которыми можно шифровать сообщения!", - "encryption_failed_toast": "Не удалось зашифровать сообщение! Проверьте logcat для получения дополнительной информации.", - "accept_public_key_success_toast": "Открытый ключ успешно принят!", - "accept_secret_key_success_toast": "Готово! Теперь вы можете отправлять и получать зашифрованные сообщения с этим другом.", - "accept_public_key_failure_toast": "Не удалось принять открытый ключ", - "accept_secret_key_failure_toast": "Не удалось принять секретный ключ", - "accept_secret_button": "Принять секрет", - "accept_public_key_button": "Принять открытый ключ", - "outgoing_pk_message": "Запрос на обмен ключами", - "outgoing_secret_message": "Ответ на обмен ключами", - "incoming_pk_message": "Вы только что получили запрос на открытый ключ. Нажмите ниже, чтобы принять его.", - "incoming_secret_message": "Ваш друг только что принял ваш открытый ключ. Нажмите ниже, чтобы принять секрет." + "subtitle": "Пожалуйста, авторизуйтесь, чтобы разблокировать Snapchat", + "unlock_button": "Разблокировать" }, "auto_open_snaps": { - "title": "Автооткрытие Snap", - "notification_content": "{count} Snap открыто" + "title": "Автоматическое открытие Снапов", + "notification_content": "Открыто {count} Снапов" }, "friend_mutation_observer": { - "notification_channel_name": "Наблюдатель за изменениями друзей", - "friend_removed": "{username} удалил(а) вас из друзей", - "birthday_removed": "{username} удалил(а) свой день рождения ({birthday})", - "birthday_added": "{username} добавил(а) свой день рождения ({birthday})", - "birthday_changed": "{username} изменил(а) свой день рождения с {oldBirthday} на {newBirthday}", - "bitmoji_selfie_changed": "{username} изменил(а) свое селфи Bitmoji", - "bitmoji_avatar_changed": "{username} изменил(а) свой аватар Bitmoji", - "bitmoji_background_changed": "{username} изменил(а) свой фон Bitmoji", - "bitmoji_scene_changed": "{username} изменил(а) свою сцену Bitmoji" - }, - "material3_strings": { - "date_range_picker_start_headline": "От", - "date_range_picker_end_headline": "До", - "date_range_picker_title": "Выберите диапазон дат", - "date_picker_switch_to_calendar_mode": "Календарь", - "date_picker_switch_to_input_mode": "Ввод", - "date_range_picker_scroll_to_previous_month": "Предыдущий месяц", - "date_range_picker_scroll_to_next_month": "Следующий месяц", - "date_picker_today_description": "Сегодня", - "date_range_picker_day_in_range": "Выбрано", - "date_input_invalid_for_pattern": "Неверная дата", - "date_input_invalid_year_range": "Неверный год", - "date_input_invalid_not_allowed": "Неверная дата", - "date_range_input_invalid_range_input": "Неверный диапазон дат." - }, - "send_override_dialog": { - "title": "Отправить медиа как {type}", - "duration": "Длительность: {duration}", - "saveable_snap_hint": "Сделать Snap сохраняемым в чате", - "unlimited_duration": "Безлимитно" - }, - "invalid_input_toast": "Неверный ввод! Убедитесь, что вы ввели допустимое значение." -} \ No newline at end of file + "birthday_changed": "{username} изменил свой день рождения с {oldBirthday} на {newBirthday}", + "bitmoji_avatar_changed": "{username} изменил свой аватар Bitmoji", + "bitmoji_scene_changed": "{username} изменил свою сцену Bitmoji", + "bitmoji_selfie_changed": "{username} изменил свою битмоджи-селфи", + "notification_channel_name": "Наблюдатель за изменениями в друзьях", + "friend_removed": "{username} удалил вас из друзей", + "birthday_removed": "{username} удалил свой день рождения ({birthday})", + "birthday_added": "{username} добавил свой день рождения ({birthday})", + "bitmoji_background_changed": "{username} изменил свой фон Bitmoji" + } +} diff --git a/common/src/main/assets/lang/sl_SI.json b/common/src/main/assets/lang/sl_SI.json new file mode 100644 index 00000000..5476edeb --- /dev/null +++ b/common/src/main/assets/lang/sl_SI.json @@ -0,0 +1,87 @@ +{ + "setup": { + "mappings": { + "generate_failure": "Pri ustvarjanju preslikav je prišlo do napake, prosimo poskusite znova.", + "generate_failure_no_snapchat": "SnapEnhance ne zaznava Snapchata. Poizkusite ga znova naložiti.", + "dialog": "Da bi dinamično podpiral širok razpon Snapchat verzij, so preslikave potrebne za pravilno delovanje Snapenhance-a; to ne bi smelo vzeti več kot 5 sekund." + }, + "permissions": { + "dialog": "Za nadaljevanje morate izpolnjevati naslednje zahteve:", + "notification_access": "Dostop do potisnih obvestil", + "display_over_other_apps": "Prikaz čez druge aplikacije", + "request_button": "Zahtevaj", + "battery_optimization": "Optimizacija baterije" + }, + "dialogs": { + "select_language": "Izberi jezik", + "select_save_folder_button": "Izberite mapo", + "save_folder": "SnapEnhance potrebuje dovoljenje za Dostop do datotek, da lahko nalaga in shranjuje datoteke iz Snapchata.\nIzberite mapo, v katero se bodo nalagale datoteke." + } + }, + "manager": { + "routes": { + "tasks": "Naloge", + "features": "Lastnosti", + "home": "Domov", + "home_logs": "Dnevniki", + "social": "Družbena omrežja", + "scripts": "Skripte", + "home_settings": "Nastavitve", + "logger_history": "Zgodovina zapisovalnika", + "logged_stories": "Zapisane zgodbe", + "manage_scope": "Upravljaj Scope", + "messaging_preview": "Predogled", + "better_location": "Izboljšana lokacija", + "manage_repos": "Upravljaj repozitorije", + "file_imports": "Uvoz datotek", + "friend_tracker": "Sledilec prijateljev", + "edit_rule": "Uredi pravilo", + "edit_theme": "Uredi temo" + }, + "sections": { + "tasks": { + "no_tasks": "Ni nalog", + "merge_button": "Združi", + "failed_to_open_file": "Napaka pri odpiranju datoteke" + }, + "features": { + "disabled": "Onemogočeno" + }, + "social": { + "streaks_expiration_short": "{hours} ur" + }, + "home": { + "update_title": "SnapEnhance nadgradnja", + "update_content": "Verzija {version} je na voljo!", + "update_button": "Prenos", + "debug_build_summary_title": "Uporabljate razhroščevalno različico SnapEnhancea", + "debug_build_summary_date": "Dan izgradnje: {date} ({days} days ago)", + "quick_actions_title": "Hitra dejanja", + "version_title": "v{versionName} · naredil eternal", + "debug_build_summary_content": "Verzija {versionName} ({versionCode})" + }, + "home_logs": { + "no_logs_hint": "Ni dostopnih logov", + "clear_logs_button": "Počisti loge", + "export_logs_button": "Izvozi loge", + "saving_logs_toast": "Shranjevanje logov, to lahko vzame nekaj časa", + "saved_logs_success_toast": "Logi uspešno shranjeni", + "saved_logs_failure_toast": "Napaka pri shranjevanju zapisnikov" + }, + "home_settings": { + "success_toast": "Končano!", + "message_logger_summary": "{messageCount} sporočil\n{storyCount} zgodb", + "export_button": "Izvozi", + "clear_button": "Počisti", + "actions_title": "Dejanja", + "message_logger_title": "Zapisovalnik sporočil", + "debug_title": "Razhroščevanje", + "view_logger_history_button": "Ogled zgodovine zapiskov" + } + } + }, + "scopes": { + "friend": "Prijatelj", + "group": "Skupina" + } +} diff --git a/common/src/main/assets/lang/sv.json b/common/src/main/assets/lang/sv.json new file mode 100644 index 00000000..b4289a31 --- /dev/null +++ b/common/src/main/assets/lang/sv.json @@ -0,0 +1,839 @@ +{ + "setup": { + "dialogs": { + "select_save_folder_button": "Välj Mapp", + "select_language": "Välj språk", + "save_folder": "SnapEnhance kräver lagringsbehörigheter för att ladda ner och spara media från Snapchat.\nVälj var media ska laddas ner till." + }, + "mappings": { + "dialog": "För att dynamiskt stödja ett brett utbud av Snapchat Versioner, mappningar är nödvändiga för att SnapEnhance ska fungera korrekt, detta bör inte ta mer än 5 sekunder.", + "generate_failure_no_snapchat": "SnapEnhance kunde inte upptäcka Snapchat, försök att installera om Snapchat.", + "generate_failure": "Ett fel inträffade vid försök att generera mappningar, försök igen." + }, + "permissions": { + "dialog": "För att fortsätta måste du uppfylla följande krav:", + "notification_access": "Åtkomst till aviseringar", + "battery_optimization": "Batterioptimering", + "display_over_other_apps": "Visa över andra appar", + "request_button": "Begäran" + } + }, + "manager": { + "routes": { + "features": "Funktioner", + "home": "Hem", + "home_settings": "Inställningar", + "home_logs": "Loggar", + "social": "Socialt", + "scripts": "Skript", + "logged_stories": "Loggade berättelser", + "tasks": "Uppgifter", + "logger_history": "Logger Historia", + "manage_scope": "Hantera omfattning", + "messaging_preview": "Förhandsvisning" + }, + "sections": { + "features": { + "disabled": "Inaktiverad", + "export_option": "Exportera", + "import_option": "Importera", + "reset_option": "Återställ", + "saved_config_snackbar": "Konfiguration sparad" + }, + "social": { + "streaks_expiration_short": "{timmar}t" + }, + "tasks": { + "no_tasks": "Inga uppgifter", + "merge_files_toast": "Slår samman {count} filer", + "remove_selected_tasks_confirm": "Ta bort {count} uppgifter?", + "remove_all_tasks_confirm": "Ta bort alla upgifter?", + "remove_selected_tasks_title": "Är du säker på att du vill ta bort markerade uppgifter?", + "remove_all_tasks_title": "Är du säker på att du vill ta bort alla uppgifter?", + "delete_files_option": "Radera även filer" + }, + "logged_stories": { + "story_failed_to_load": "Misslyckades att ladda", + "no_stories": "Inga berättelser hittades", + "save_from_cache_button": "Spara från cachen" + }, + "messaging_preview": { + "bridge_connection_failed": "Det gick inte att ansluta till Snapchat via bryggtjänsten", + "bridge_init_failed": "Det gick inte att initiera meddelandebryggan", + "message_fetch_failed": "Det gick inte att hämta meddelanden", + "no_message_hint": "Inget meddelande", + "save_selection_option": "Spara urval", + "save_all_option": "Rädda alla", + "unsave_selection_option": "Ta bort val", + "unsave_all_option": "Ta bort alla", + "mark_selection_as_seen_option": "Markera vald Snap som sett", + "mark_all_as_seen_option": "Markera alla Snaps som sett", + "delete_selection_option": "Ta bort urval", + "delete_all_option": "Radera allt" + }, + "logger_history": { + "list_friend_format": "Vän {namn}", + "no_more_messages": "Inga fler meddelanden", + "list_group_format": "Grupp {name}", + "reverse_order_checkbox": "Omvänd ordning", + "chat_attachment": "Bilaga {index}", + "empty_message": "Tomt chattmeddelande", + "message_parse_failed": "Det gick inte att tolka meddelandet", + "unknown_sender": "Okänd avsändare", + "download_attachment_failed_toast": "Det gick inte att ladda ned bilagan" + }, + "home": { + "update_title": "SnapEnhance Updatering", + "update_content": "Version {version} är tillgänglig!", + "update_button": "Ladda ner" + }, + "home_logs": { + "clear_logs_button": "Rensa loggar", + "export_logs_button": "Exportera loggar", + "saved_logs_success_toast": "Loggarna sparades", + "saved_logs_failure_toast": "Det gick inte att spara loggar", + "no_logs_hint": "Inga loggar tillgängliga", + "saving_logs_toast": "Sparar loggar, detta kan ta ett tag ..." + }, + "home_settings": { + "debug_title": "Felsökning", + "export_button": "Exportera", + "clear_button": "Rensa", + "view_logger_history_button": "Visa Logger Historik", + "actions_title": "Handlingar", + "success_toast": "Klart!" + }, + "manage_scope": { + "rules_title": "Regler", + "reminder_button": "Sätta på påminelse", + "streaks_expiration_text_expired": "Upphörd" + } + }, + "dialogs": { + "add_friend": { + "category_friends": "Vänner", + "title": "Lägg till vän eller grupp", + "search_hint": "Sök", + "fetch_error": "Det gick inte att hämta data", + "category_groups": "Grupper" + }, + "scripting_warning": { + "title": "Varning", + "content": "SnapEnhance inkluderar ett skriptverktyg som tillåter exekvering av användardefinierad kod på din enhet. Var extremt försiktig och installera endast moduler från kända, pålitliga källor. Obehöriga eller overifierade moduler kan utgöra säkerhetsrisker för ditt system." + }, + "reset_config": { + "title": "Återställ konfiguration", + "content": "Är du säker på att du vill återställa konfigurationen?", + "success_toast": "Konfigurationsåterställningen lyckades" + } + } + }, + "rules": { + "properties": { + "auto_download": { + "name": "Automatisk nedladdning", + "description": "Ladda ned Snaps automatiskt när du tittar på dem", + "options": { + "blacklist": "Uteslut från automatisk nedladdning", + "whitelist": "Automatisk nedladdning" + } + }, + "unsaveable_messages": { + "name": "Meddelanden som inte går att spara", + "description": "Förhindrar att meddelanden sparas i chatten av andra", + "options": { + "blacklist": "Uteslut från meddelanden som inte går att spara", + "whitelist": "Meddelanden som inte går att spara" + } + }, + "auto_save": { + "description": "Sparar chattmeddelanden när du visar dem", + "name": "Automatisk sparning", + "options": { + "blacklist": "Uteslut från Autospara", + "whitelist": "Automatisk sparning" + } + }, + "stealth": { + "name": "Smygläge", + "description": "Hindrar någon från att veta att du har öppnat deras Snaps/chattar och konversationer", + "options": { + "blacklist": "Uteslut från Stealth Mode", + "whitelist": "Smygläge" + } + }, + "hide_friend_feed": { + "name": "Göm från Friend Feed" + }, + "e2e_encryption": { + "name": "Använd E2E-kryptering" + }, + "pin_conversation": { + "name": "Fäst konversation" + } + }, + "toasts": { + "enabled": "{ruleName} aktiverad", + "disabled": "{ruleName} inaktiverad" + }, + "modes": { + "blacklist": "Svartlista läge", + "whitelist": "Vitlista läge" + } + }, + "actions": { + "clean_snapchat_cache": { + "name": "Rengör Snapchat-cachen", + "description": "Rengör Snapchat-cachen" + }, + "manage_friend_list": { + "name": "Hantera vänlista", + "description": "Importera/exportera din vänlista vid säkerhetskopiering" + }, + "bulk_messaging_action": { + "description": "Genomför operationer som ta bort kompisar eller ta bort ett flertal conversationer", + "name": "Massutskick av meddelanden" + }, + "regen_mappings": { + "name": "Generera Mappar", + "description": "Manuellt Generera mappar" + }, + "export_memories": { + "description": "Exportera minnen till en ZIP fil", + "name": "Exportera minnen" + }, + "export_chat_messages": { + "name": "Exportera Chat Meddelanden", + "description": "Exporterar conversations meddelanden till en JSON/HTML/TXT fil" + }, + "change_language": { + "name": "Bytt språk", + "description": "Bytt språk av SnapEnhance" + } + }, + "features": { + "notices": { + "internal_behavior": "⚠ Detta kan förstöra Snapchats interna beteenden", + "ban_risk": "⚠ Denna funktion kan leda till avstängning", + "unstable": "⚠ Ostabilt" + }, + "properties": { + "downloader": { + "properties": { + "auto_download_sources": { + "description": "Välj vilka källor som ska automatiskt installeras från", + "name": "Automatiskt installera källor" + }, + "prevent_self_auto_download": { + "description": "Hindrar dina egna snaps från att bli nedladdade automatiskt", + "name": "Hindra automatisk nedladdning" + }, + "save_folder": { + "name": "Spara Mapp", + "description": "Välj en mapp som all media ska vara nedladdat till" + }, + "allow_duplicate": { + "description": "Tillåt samma media att bli installerat flera gånger", + "name": "Tillåt duplication" + }, + "download_context_menu": { + "description": "Gör att du kan ladda ner/förhandsgranska meddelanden från en konversation eller en story med hjälp av snabbmenyn.\nHåll ner knappen för att tvinga nedladdning", + "name": "Ladda ner Snabbmeny" + }, + "merge_overlays": { + "name": "Sammanfoga överlägg", + "description": "Kombinerar text och media från en Snap till en enda fil" + }, + "path_format": { + "name": "Sökvägsformat", + "description": "Ange filsökvägsformat" + }, + "ffmpeg_options": { + "properties": { + "threads": { + "description": "Antalet trådar som ska användas", + "name": "Trådar" + }, + "video_bitrate": { + "description": "Ställ in videobithastighet (kbps)", + "name": "Video bithastighet" + }, + "audio_bitrate": { + "name": "Ljud bithastighet", + "description": "Ställ in ljudets bithastighet (kbps)" + }, + "custom_video_codec": { + "name": "Anpassad videokodek", + "description": "Ange en anpassad videokodek (t.ex. libx264)" + }, + "custom_audio_codec": { + "description": "Ange en anpassad ljudkodek (t.ex. AAC)", + "name": "Anpassad ljudkodek" + }, + "preset": { + "name": "Förinställning", + "description": "Ställ in hastigheten för konverteringen" + }, + "constant_rate_factor": { + "name": "Konstant hastighet faktor", + "description": "Ange den konstanta hastighetsfaktorn för videokodaren\nFrån 0 till 51 för libx264" + } + }, + "name": "FFmpeg Alternativ", + "description": "Ange ytterligare FFmpeg Alternativ" + }, + "custom_path_format": { + "description": "Ange ett anpassat sökvägsformat för nedladdade media\n\nTillgängliga variabler:\n - %användarnamn%\n - %källa\n - %hash%\n - %datum_tid%", + "name": "Format för anpassad sökväg" + }, + "force_voice_note_format": { + "name": "Tvingar röstanteckningsformat", + "description": "Tvingar röstanteckningar att sparas i ett specificerat format" + }, + "logging": { + "description": "Visar toasts när media laddas ner", + "name": "Loggning" + }, + "force_image_format": { + "description": "Tvingar bilder att sparas i ett specificerat format", + "name": "Tvingar Bildformat" + }, + "download_profile_pictures": { + "name": "Ladda ner profilbilder", + "description": "Gör det möjligt att ladda ner profilbilder från profilsidan" + }, + "opera_download_button": { + "name": "Opera nedladdnings-knapp", + "description": "Lägger till en nedladdningsknapp i det övre högra hörnet när du visar en Snap.\nHåll in knappen för att tvinga nedladdning" + } + }, + "description": "Ladda ner Snapchats Media", + "name": "Nedladdare" + }, + "user_interface": { + "properties": { + "prevent_message_list_auto_scroll": { + "name": "Förhindra automatisk skrollning av meddelandelista", + "description": "Förhindrar att meddelandelistan skrollar längst ner när du skickar/tar emot ett meddelande" + }, + "snap_preview": { + "description": "Visar en liten förhandsgranskning bredvid osedda Snaps i chatten", + "name": "Förhandsvisning av snap" + }, + "bootstrap_override": { + "properties": { + "app_appearance": { + "name": "Appens utseende", + "description": "Ställer in ett beständigt App-utseende" + }, + "home_tab": { + "name": "Fliken Hem", + "description": "Överskriver startfliken när Snapchat öppnas" + } + }, + "name": "Bootstrap-överskrivning", + "description": "Överskriver användargränssnittets bootstrap-inställningar" + }, + "enable_app_appearance": { + "name": "Aktivera inställningar för apputseende", + "description": "Aktiverar de dolda Apputseendesinställningarna\nKanske inte nödvändigt på nyare Snapchat-versioner" + }, + "hide_friend_feed_entry": { + "description": "Döljer en viss vän från vänflödet\nAnvänd fliken Social för att hantera den här funktionen", + "name": "Dölj imnatning in vänflödet" + }, + "hide_streak_restore": { + "description": "Döljer knappen Återställ i vänflödet", + "name": "Göm Streak-Återställning" + }, + "hide_ui_components": { + "name": "Dölj komponenter i användargränssnittet", + "description": "Välj vilka UI-komponenter som ska döljas" + }, + "opera_media_quick_info": { + "description": "Visar användbar information om media, t.ex. skapelsedatum, i kontextmenyn i operafönstret", + "name": "Opera Media Snabbinformation" + }, + "disable_spotlight": { + "description": "Inaktiverar Spotlight-sidan", + "name": "Inaktivera Spotlight" + }, + "friend_feed_message_preview": { + "name": "Förhandsgranskning av meddelande från Vänflödet", + "description": "Visar en förhandsgranskning av de senaste meddelandena i vänflödet", + "properties": { + "amount": { + "name": "Antal", + "description": "Antalet meddelanden som ska förhandsgranskas" + } + } + }, + "map_friend_nametags": { + "description": "Förbättrar namntaggar av vänner på Snapmap", + "name": "Förbättrade Namntaggar på vänkartan" + }, + "streak_expiration_info": { + "name": "Visa info om utgång för Streak", + "description": "Visar en timer för Streakens utgång bredvid Streaks-räknaren" + }, + "old_bitmoji_selfie": { + "name": "Gamla Bitmoji-selfien", + "description": "Återinför Bitmoji-selfies från äldre Snapchat-versioner" + }, + "hide_story_suggestions": { + "name": "Dölj Story-förslag", + "description": "Tar bort förslag från Stories-fliken" + } + }, + "name": "Användargränssnitt", + "description": "Ändra utseende och känsla för Snapchat" + }, + "messaging": { + "properties": { + "hide_typing_notifications": { + "description": "Hindrar någon från att veta att du skriver ett meddelande", + "name": "Dölj skrivaviseringar" + }, + "hide_bitmoji_presence": { + "description": "Förhindrar att din Bitmoji dyker upp medan du är i chatten" + }, + "half_swipe_notifier": { + "properties": { + "min_duration": { + "description": "Minsta varaktighet för halva svep (i sekunder)", + "name": "Minsta varaktighet" + }, + "max_duration": { + "description": "Den maximala varaktigheten för halva svepningen (i sekunder)", + "name": "Maximal varaktighet" + } + }, + "name": "Halvsvep Notifier", + "description": "Meddelar dig när någon halvt sveper in i en konversation" + }, + "call_start_confirmation": { + "description": "Visar en bekräftelsedialog när du startar ett samtal", + "name": "Ring startbekräftelse" + }, + "prevent_message_sending": { + "name": "Förhindra att meddelanden skickas", + "description": "Förhindrar att vissa typer av meddelanden skickas" + }, + "better_notifications": { + "description": "Lägger till mer information i mottagna aviseringar", + "name": "Bättre aviseringar" + }, + "loop_media_playback": { + "name": "Slinga medieuppspelning", + "description": "Slingor medieuppspelning när du tittar på Snaps / Stories" + }, + "disable_replay_in_ff": { + "description": "Inaktiverar möjligheten att spela om med ett långt tryck från Friend Feed", + "name": "Inaktivera Replay i FF" + }, + "unlimited_snap_view_time": { + "name": "Obegränsad Snap View Time", + "description": "Tar bort tidsgränsen för visning av Snaps" + } + } + }, + "global": { + "properties": { + "disable_confirmation_dialogs": { + "name": "Inaktivera bekräftelsedialoger", + "description": "Bekräftar automatiskt valda åtgärder" + }, + "better_location": { + "properties": { + "always_update_location": { + "name": "Uppdatera alltid plats", + "description": "Tvinga Snapchat att uppdatera plats även om ingen GPS-data tas emot" + }, + "suspend_location_updates": { + "name": "Stäng av platsuppdateringar", + "description": "Lägger till en knapp i kartinställningarna för att avbryta platsuppdateringar" + }, + "spoof_battery_level": { + "name": "Spoof batterinivå", + "description": "Förfalskar batterinivån på din enhet på kartan\nVärdet måste vara mellan 0 och 100" + }, + "spoof_location": { + "name": "Spoof Plats", + "description": "Förfalskar din plats till en angiven" + }, + "coordinates": { + "description": "Ställ in koordinaterna för den falska platsen", + "name": "Koordinater" + }, + "spoof_headphones": { + "name": "Parodi hörlurar", + "description": "Förfalskar statusen för att lyssna på musik på kartan" + } + }, + "description": "Förbättrar Snapchat-platsen", + "name": "Bättre läge" + }, + "snapchat_plus": { + "name": "Snapchat Plus", + "description": "Aktiverar Snapchat Plus-funktioner\nVissa serversidiga funktioner kanske inte fungerar" + }, + "auto_updater": { + "name": "Automatisk uppdatering", + "description": "Söker automatiskt efter nya uppdateringar" + }, + "disable_metrics": { + "name": "Inaktivera mätvärden", + "description": "Blockerar att skicka specifik analysdata till Snapchat" + }, + "block_ads": { + "description": "Förhindrar att annonser visas", + "name": "Blockera annonser" + }, + "spotlight_comments_username": { + "description": "Visar författarens användarnamn i Spotlight-kommentarer", + "name": "Spotlight Kommentarer Användarnamn" + }, + "disable_snap_splitting": { + "description": "Förhindrar att Snaps delas upp i flera delar\nBilder du skickar förvandlas till videor", + "name": "Inaktivera Snap Splitting" + }, + "disable_memories_snap_feed": { + "name": "Inaktivera Memories Snap Feed", + "description": "Förhindrar att Snapchat visar senaste minnen när du sveper uppåt i kameran" + }, + "disable_google_play_dialogs": { + "description": "Förhindra att tillgänglighetsdialoger för Google Play-tjänster visas", + "name": "Inaktivera dialogrutor för Google Play-tjänster" + }, + "disable_story_sections": { + "name": "Inaktivera berättelsesektioner", + "description": "Tar bort avsnitt från sidan Berättelser\nKan kräva en uppdatering för att fungera korrekt" + }, + "default_video_playback_rate": { + "name": "Standard videouppspelningshastighet", + "description": "Ställer in standardhastigheten för uppspelning av videor\nVärdet måste vara mellan 0,1 och 4,0" + }, + "video_playback_rate_slider": { + "name": "Reglage för videouppspelningshastighet", + "description": "Lägger till ett skjutreglage i opera snabbmeny för att ändra videouppspelningshastigheten\nObs! Ändringar gäller endast för efterföljande videor" + }, + "default_volume_controls": { + "name": "Standardvolymkontroller", + "description": "Tvingar Snapchat att använda systemvolymkontroller" + }, + "disable_permission_requests": { + "name": "Inaktivera behörighetsförfrågningar", + "description": "Förhindrar Snapchat från att be om specifika behörigheter" + }, + "bypass_video_length_restriction": { + "name": "Förbigå videolängdsbegränsningar", + "description": "Singel: skickar en enda video\nDela: dela videor efter redigering" + } + } + }, + "rules": { + "name": "Regler", + "description": "Hantera automatiska funktioner för enskilda personer" + }, + "camera": { + "properties": { + "force_camera_source_encoding": { + "name": "Tvinga kamerakällkodning", + "description": "Framtvingar kamerans källkodning" + }, + "black_photos": { + "name": "Svarta foton", + "description": "Ersätter tagna bilder med svart bakgrund\nVideor påverkas inte" + }, + "immersive_camera_preview": { + "name": "Uppslukande förhandsvisning", + "description": "Förhindrar Snapchat från att beskära kameran förhandsvisning\nDetta kan göra att kameran flimrar på vissa enheter" + }, + "override_back_resolution": { + "name": "Åsidosätt bakupplösning", + "description": "Åsidosätter kameraupplösningen för den bakre kameran" + }, + "custom_resolution": { + "name": "Anpassad upplösning", + "description": "Ställer in en anpassad kameraupplösning, bredd x höjd (t.ex. 1920x1080).\nDen anpassade upplösningen måste stödjas av din enhet" + }, + "hevc_recording": { + "name": "HEVC-inspelning", + "description": "Använder HEVC (H.265) codec för videoinspelning" + }, + "override_front_resolution": { + "description": "Åsidosätter kameraupplösningen för den främre kameran", + "name": "Åsidosätt frontupplösning" + }, + "disable_cameras": { + "description": "Förhindrar att Snapchat använder de valda kamerorna", + "name": "Inaktivera kameror" + }, + "front_custom_frame_rate": { + "name": "Front anpassad bildhastighet", + "description": "Åsidosätter den främre kamerans bildfrekvens" + }, + "back_custom_frame_rate": { + "name": "Tillbaka Anpassad bildhastighet", + "description": "Åsidosätter den bakre kamerans bildhastighet" + } + }, + "name": "Kamera", + "description": "Justera rätt inställningar för den perfekta snäppet" + }, + "scripting": { + "properties": { + "auto_reload": { + "description": "Laddar automatiskt om skript när de ändras", + "name": "Ladda om automatiskt" + }, + "disable_log_anonymization": { + "description": "Inaktiverar anonymisering av loggar", + "name": "Inaktivera logganonymisering" + }, + "developer_mode": { + "description": "Visar felsökningsinformation på Snapchats användargränssnitt", + "name": "Utvecklarläge" + }, + "module_folder": { + "name": "Modulmapp", + "description": "Mappen där skripten finns" + }, + "integrated_ui": { + "description": "Tillåter skript att lägga till anpassade UI-komponenter till Snapchat", + "name": "Integrerat användargränssnitt" + } + }, + "name": "Skript", + "description": "Kör anpassade skript för att utöka SnapEnhance" + }, + "experimental": { + "properties": { + "native_hooks": { + "name": "Native Hooks", + "description": "Osäkra funktioner som kopplas in i Snapchats inbyggda kod", + "properties": { + "disable_bitmoji": { + "name": "Inaktivera Bitmoji", + "description": "Inaktiverar vänprofil Bitmoji" + } + } + }, + "spoof": { + "properties": { + "remove_vpn_transport_flag": { + "name": "Ta bort VPN-transportflagga", + "description": "Förhindrar att Snapchat upptäcker VPN" + }, + "remove_mock_location_flag": { + "name": "Ta bort Mock Location Flag", + "description": "Förhindrar Snapchat från att upptäcka skenplats" + }, + "play_store_installer_package_name": { + "name": "Paketnamn för Play Butik Installer", + "description": "Åsidosätter installationspaketets namn till com.android.vending" + } + }, + "description": "Förfalska diverse information om dig", + "name": "Parodi" + }, + "story_logger": { + "name": "Berättelselogger", + "description": "Ger en historia av vänners berättelser" + }, + "call_recorder": { + "name": "Samtalsinspelning", + "description": "Spelar automatiskt in ljudsamtal" + }, + "hidden_snapchat_plus_features": { + "description": "Aktiverar outgivna/beta Snapchat Plus-funktioner\nKanske inte fungerar på äldre Snapchat-versioner", + "name": "Dolda Snapchat Plus-funktioner" + }, + "prevent_forced_logout": { + "description": "Förhindrar att Snapchat loggar ut dig när du loggar in på en annan enhet", + "name": "Förhindra påtvingad utloggning" + }, + "media_file_picker": { + "name": "Mediafilväljare", + "description": "Låter dig välja valfri video-/ljudfil från galleriet" + }, + "account_switcher": { + "name": "Kontoväxling", + "description": "Låter dig växla mellan konton utan att logga ut\nTryck länge på sökikonen bredvid din Bitmoji-profil för att öppna menyn\nObs! Den här funktionen är experimentell och kommer sannolikt att ändras i framtiden", + "properties": { + "auto_backup_current_account": { + "name": "Automatisk säkerhetskopiering av aktuellt konto", + "description": "Säkerhetskopierar automatiskt det aktuella kontot när du loggar ut eller byter konto" + } + } + }, + "edit_message": { + "description": "Låter dig redigera meddelanden i konversationer", + "name": "Redigera meddelanden" + }, + "meo_passcode_bypass": { + "name": "Mina ögon förbigår bara lösenordet", + "description": "Förbigå My Eyes Only-lösenordet\nDetta fungerar bara om lösenordet har angetts korrekt tidigare" + }, + "e2ee": { + "properties": { + "encrypted_message_indicator": { + "description": "Lägger till en 🔒 emoji bredvid krypterade meddelanden", + "name": "Krypterad meddelandeindikator" + }, + "force_message_encryption": { + "name": "Forcera meddelandekryptering", + "description": "Förhindrar att krypterade meddelanden skickas till personer som inte har E2E-kryptering aktiverad endast när flera konversationer är valda" + } + }, + "name": "End-to-end-kryptering", + "description": "Krypterar dina meddelanden med AES med hjälp av en delad hemlig nyckel\nSe till att spara din nyckel på ett säkert ställe!" + }, + "add_friend_source_spoof": { + "name": "Lägg till vänkälla förfalskning", + "description": "Förfalskar källan till en vänförfrågan" + }, + "infinite_story_boost": { + "name": "Oändlig Story Boost", + "description": "Gå förbi Story Boost Limit-fördröjningen" + }, + "no_friend_score_delay": { + "name": "Ingen vänpoängfördröjning", + "description": "Tar bort fördröjningen vid visning av ett kompisresultat" + }, + "convert_message_locally": { + "name": "Konvertera meddelande lokalt", + "description": "Konverterar snaps till att chatta externt media lokalt. Detta visas i chattens snabbmeny" + } + }, + "name": "Experimentell", + "description": "Experimentella funktioner" + }, + "streaks_reminder": { + "properties": { + "interval": { + "name": "Intervall", + "description": "Intervallet mellan varje påminnelse (timmar)" + }, + "remaining_hours": { + "name": "Återstående tid", + "description": "Återstående tid innan meddelandet visas (timmar)" + }, + "group_notifications": { + "description": "Gruppera aviseringar till en enda", + "name": "Gruppmeddelanden" + } + }, + "name": "Påminnelse om streck", + "description": "Meddelar dig regelbundet om dina Streaks" + } + }, + "options": { + "notifications": { + "abandon_audio": "Missat ljudsamtal", + "initiate_audio": "Inkommande ljudsamtal", + "chat_screenshot": "Skärmdump", + "chat_screen_record": "Skärminspelning", + "chat": "Chatt", + "typing": "Skriver", + "snap_replay": "Snap Replay", + "camera_roll_save": "Spara kamerarulle", + "chat_reply": "Chatt Svara", + "snap": "Snap", + "stories": "Berättelser", + "chat_reaction": "DM-reaktion", + "group_chat_reaction": "Gruppreaktion", + "initiate_video": "Inkommande videosamtal", + "abandon_video": "Missat videosamtal" + }, + "friend_feed_menu_buttons": { + "auto_save": "💬 Spara meddelanden automatiskt", + "unsaveable_messages": "⬇️ Meddelanden som inte går att spara", + "stealth": "👻 Smygläge", + "mark_snaps_as_seen": "👀 Markera Snaps som sett", + "conversation_info": "👤 Konversationsinfo", + "auto_download": "⬇️ Automatisk nedladdning", + "mark_stories_as_seen_locally": "👀 Markera berättelser som ses lokalt", + "e2e_encryption": "🔒 Använd E2E-kryptering" + }, + "path_format": { + "create_source_folder": "Skapa mapp för varje typ av mediakälla", + "append_hash": "Lägg till en unik hash till filnamnet", + "append_source": "Lägg till mediekällan till filnamnet", + "append_username": "Lägg till användarnamnet i filnamnet", + "create_author_folder": "Skapa mapp för varje författare", + "append_date_time": "Lägg till datum och tid i filnamnet" + }, + "logging": { + "success": "Framgång", + "progress": "Framsteg", + "started": "Satte igång", + "failure": "Fel" + }, + "hide_ui_components": { + "hide_live_location_share_button": "Ta bort Live Location Share-knapp", + "hide_voice_record_button": "Ta bort röstinspelningsknappen", + "hide_chat_call_buttons": "Ta bort chattsamtalsknappar", + "hide_stickers_button": "Knappen Ta bort klistermärken", + "hide_unread_chat_hint": "Ta bort oläst chatttips", + "hide_profile_call_buttons": "Ta bort profilanropsknappar" + }, + "bypass_video_length_restriction": { + "single": "Enstaka media", + "split": "Dela media" + }, + "gallery_media_send_override": { + "ORIGINAL": "Original", + "NOTE": "Ljudnotering", + "SNAP": "Snap" + }, + "app_appearance": { + "always_light": "Alltid ljus", + "always_dark": "Alltid mörkt" + }, + "auto_download_sources": { + "friend_snaps": "Vän Snaps", + "friend_stories": "Vänberättelser", + "public_stories": "Offentliga berättelser", + "spotlight": "Strålkastare" + }, + "home_tab": { + "discover": "Upptäck", + "spotlight": "Strålkastare", + "chat": "Chatt", + "camera": "Kamera", + "map": "Karta" + }, + "hide_story_suggestions": { + "hide_suggested_friend_stories": "Dölj föreslagna vänberättelser", + "hide_my_stories": "Dölj mina berättelser" + }, + "add_friend_source_spoof": { + "added_by_username": "Efter användarnamn", + "added_by_mention": "Genom att nämna", + "added_by_qr_code": "Med QR-kod", + "added_by_community": "Efter gemenskap", + "added_by_group_chat": "Via gruppchatt" + }, + "strip_media_metadata": { + "remove_audio_note_transcript_capability": "Ta bort Audio Note Transcript Capability", + "remove_audio_note_duration": "Ta bort ljudanteckningslängd", + "hide_caption_text": "Dölj bildtext", + "hide_snap_filters": "Dölj Snap-filter", + "hide_extras": "Dölj extrafunktioner (t.ex. omnämnanden)" + } + } + }, + "scopes": { + "friend": "Vän", + "group": "Grupp" + }, + "streaks_reminder": { + "notification_text": "Du kommer att förlora din Streak med {friend} om {hoursLeft} timmar" + }, + "download_processor": { + "dash_dialog": { + "segment_text": "Segmentera {från} - {till}" + } + } +} diff --git a/common/src/main/assets/lang/sw.json b/common/src/main/assets/lang/sw.json deleted file mode 100644 index 3f0b9b08..00000000 --- a/common/src/main/assets/lang/sw.json +++ /dev/null @@ -1,2022 +0,0 @@ -{ - "setup": { - "dialogs": { - "select_language": "Chagua lugha", - "save_folder": "PurrfectSnap inahitaji ruhusa ya hifadhi ili kupakua na kuhifadhi midia kutoka Snapchat.\nTafadhali chagua eneo ambapo midia itapakuliwa.", - "select_save_folder_button": "Chagua folda" - }, - "mappings": { - "dialog": "Inatengeneza ramani, hii inaweza kuchukua muda...", - "generate_failure_no_snapchat": "PurrfectSnap haikuweza kutambua Snapchat, tafadhali jaribu kusakinisha tena Snapchat.", - "generate_failure": "Kosa limetokea wakati wa kujaribu kutengeneza ramani, tafadhali jaribu tena." - }, - "permissions": { - "dialog": "Ili kuendelea, unahitaji kutimiza mahitaji yafuatayo:", - "notification_access": "Ufikiaji wa arifa", - "battery_optimization": "Uboreshaji wa betri", - "display_over_other_apps": "Onyesha juu ya programu zingine", - "request_button": "Omba" - } - }, - "scopes": { - "friend": "Rafiki", - "group": "Kikundi" - }, - "manager": { - "routes": { - "tasks": "Majukumu", - "features": "Vipengele", - "manage_rule_feature": "Dhibiti kipengele cha kanuni", - "home": "Nyumbani", - "home_settings": "Mipangilio", - "home_logs": "Kumbukumbu", - "logger_history": "Historia ya Kumbukumbu", - "logged_stories": "Hadithi zilizohifadhiwa", - "friend_tracker": "Kifuatilia Marafiki", - "edit_rule": "Hariri Kanuni", - "file_imports": "Uingizaji wa Faili", - "manage_repos": "Dhibiti Hifadhi", - "social": "Kijamii", - "manage_scope": "Dhibiti Wigo", - "messaging_preview": "Onyesho la awali", - "scripts": "Hati", - "better_location": "Mahali Pazuri Zaidi" - }, - "sections": { - "home": { - "version_title": "v{versionName} · Imetengenezwa na Eternal", - "update_title": "Sasisho la PurrfectSnap", - "update_content": "Toleo la {version} linapatikana!", - "update_button": "Pakua", - "debug_build_summary_title": "Unatumia toleo la utatuzi la PurrfectSnap", - "debug_build_summary_content": "Toleo {versionName} ({versionCode})", - "debug_build_summary_date": "Tarehe ya kutengenezwa: {date} (siku {days} zilizopita)", - "quick_actions_title": "Vitendo vya Haraka", - "download_icon_description": "Pakua", - "completed_icon_description": "Imekamilika", - "failed_icon_description": "Imeshindwa", - "manage_quick_actions_description": "Dhibiti vitendo vya haraka", - "quick_actions_icon_description": "Vitendo vya Haraka", - "add_quick_action_description": "Ongeza kitendo cha haraka" - }, - "home_logs": { - "no_logs_hint": "Hakuna kumbukumbu zinazopatikana", - "clear_logs_button": "Futa kumbukumbu", - "export_logs_button": "Hamisha kumbukumbu", - "saving_logs_toast": "Inahifadhi kumbukumbu, hii inaweza kuchukua muda...", - "saved_logs_success_toast": "Kumbukumbu zimehifadhiwa kwa mafanikio", - "saved_logs_failure_toast": "Imeshindwa kuhifadhi kumbukumbu" - }, - "home_settings": { - "actions_title": "Vitendo", - "message_logger_title": "Kihifadhi Ujumbe", - "debug_title": "Utatuzi", - "success_toast": "Imekamilika!", - "message_logger_summary": "{messageCount} ujumbe\n{storyCount} hadithi", - "export_button": "Hamisha", - "clear_button": "Futa", - "view_logger_history_button": "Tazama Historia ya Kihifadhi", - "updates_title": "Masasisho", - "auto_update_check": "Angalia masasisho kiotomatiki", - "update_check_frequency": "Marudio ya Kuangalia Masasisho", - "update_check_frequency_daily": "Kila siku", - "update_check_frequency_weekly": "Kila wiki", - "update_check_frequency_monthly": "Kila mwezi", - "theme_icon_description": "Mandhari", - "app_theme_title": "Mandhari ya programu", - "theme_mode_system": "Mfumo", - "theme_mode_light": "Mwangaza", - "theme_mode_dark": "Giza", - "ui_settings_title": "Mipangilio ya UI", - "haptic_feedback_label": "Maoni ya kugusa", - "test_mode_label": "Hali ya majaribio (Kwa utatuzi tu)", - "disable_feature_loading_label": "Zima upakiaji wa vipengele", - "disable_auto_mapper_label": "Zima Kiotomatiki cha Ramani", - "disable_bypass_indicator_label": "Zima kiashirio cha hali ya kupita", - "update_notification_channel_name": "Masasisho ya PurrfectSnap", - "update_notification_channel_description": "Arifa za masasisho ya PurrfectSnap", - "update_notification_title": "Sasisho la PurrfectSnap linapatikana", - "update_notification_text": "Toleo la {version} sasa linapatikana.", - "export_database_failed_toast": "Imeshindwa kuhamisha hifadhidata! {message}", - "clear_messages_failed_toast": "Imeshindwa kufuta ujumbe! {message}", - "clear_file_failed_toast": "Imeshindwa kufuta faili! {message}", - "debug_file_config": "Usanidi", - "debug_file_mappings": "Ramani", - "debug_file_message_logger": "Kihifadhi Ujumbe", - "debug_file_pinned_best_friend": "Rafiki Mpendwa Aliyebandikwa", - "debug_file_native_sig_cache": "Kashe ya saini asili" - }, - "tasks": { - "no_tasks": "Hakuna majukumu", - "merge_button": "Unganisha", - "failed_to_open_file": "Imeshindwa kufungua faili", - "merge_files_toast": "Inaunganisha faili {count}", - "remove_selected_tasks_title": "Una uhakika unataka kuondoa majukumu yaliyochaguliwa?", - "remove_all_tasks_title": "Una uhakika unataka kuondoa majukumu yote?", - "delete_files_option": "Futa faili pia", - "remove_selected_tasks_confirm": "Ondoa majukumu {count}?", - "remove_all_tasks_confirm": "Ondoa majukumu yote?", - "clear_tasks_description": "Futa majukumu", - "file_not_found_icon_description": "Faili haipatikani", - "image_icon_description": "Picha", - "video_icon_description": "Video", - "audio_icon_description": "Sauti", - "file_icon_description": "Faili", - "download_icon_description": "Pakua", - "chat_action_icon_description": "Kitendo cha gumzo", - "cancel_icon_description": "Ghairi", - "success_icon_description": "Imefanikiwa", - "failure_icon_description": "Imeshindwa", - "cancelled_icon_description": "Imeghairiwa", - "task_status_failure": "Imeshindwa", - "task_status_cancelled": "Imeghairiwa" - }, - "features": { - "disabled": "Imezimwa", - "export_option": "Hamisha", - "import_option": "Ingiza", - "reset_option": "Weka upya", - "config_export_success_toast": "Usanidi umehamishwa kwa mafanikio", - "config_import_success_toast": "Usanidi umeingizwa kwa mafanikio", - "config_import_failure_toast": "Imeshindwa kuingiza usanidi: {error}", - "config_export_failure_toast": "Imeshindwa kuhamisha usanidi: {error}", - "saved_config_snackbar": "Usanidi umehifadhiwa", - "older_required": "Kipengele hiki kinahitaji Snapchat v{version} au toleo la zamani ili kufanya kazi vizuri.", - "newer_required": "Kipengele hiki kinahitaji Snapchat v{version} au toleo jipya ili kufanya kazi vizuri.", - "search_button": "Tafuta" - }, - "manage_rule_feature": { - "disable_state_option": "Imezimwa", - "disable_state_subtext": "Hakuna marafiki/vikundi vitakavyoathiriwa", - "whitelist_state_option": "Hakuna mtu isipokuwa...", - "whitelist_state_subtext": "Marafiki/vikundi {count} pekee ndivyo vitakavyoathiriwa na kanuni hii", - "whitelist_state_button": "Chagua marafiki/vikundi vinavyoruhusiwa", - "blacklist_state_option": "Kila mtu isipokuwa...", - "blacklist_state_subtext": "Kila mtu isipokuwa marafiki/vikundi {count} ataathiriwa na kanuni hii", - "blacklist_state_button": "Chagua marafiki/vikundi vilivyotengwa", - "clear_list_button": "Futa orodha ya marafiki/vikundi", - "dialog_clear_confirmation_text": "Una uhakika unataka kufuta orodha?" - }, - "social": { - "friends_tab": "Marafiki", - "groups_tab": "Vikundi", - "empty_hint": "(tupu)", - "streaks_expiration_short": "{hours}s" - }, - "manage_scope": { - "logged_stories_button": "Onyesha hadithi zilizohifadhiwa", - "e2ee_title": "Usimbuaji wa mwisho-hadi-mwisho", - "rules_title": "Kanuni", - "participants_text": "Washiriki {count}", - "not_found": "Haipatikani", - "streaks_title": "Mfululizo", - "streaks_length_text": "Urefu: {length}", - "streaks_expiration_text": "Inaisha baada ya {eta}", - "streaks_expiration_text_expired": "Imeisha muda", - "reminder_button": "Weka kikumbusho", - "delete_scope_confirm_dialog_title": "Una uhakika unataka kufuta {scope}?", - "notes_placeholder": "Bofya ili kuongeza dokezo", - "invalid_key_size_32_bytes": "Ukubwa wa ufunguo si sahihi (lazima iwe baiti 32)", - "successfully_imported_key": "Ufunguo umeingizwa kwa mafanikio", - "failed_to_import_key": "Imeshindwa kuingiza ufunguo: {message}", - "export_base64_button": "Hamisha Base64", - "import_base64_button": "Ingiza Base64" - }, - "logged_stories": { - "story_failed_to_load": "Imeshindwa kupakia", - "no_stories": "Hakuna hadithi zilizopatikana", - "save_from_cache_button": "Hifadhi kutoka kwenye kashe", - "downloaded_to_path": "Imepakuliwa kwa {path}", - "download_failed": "Upakuaji umeshindwa: {message}", - "posted_at": "Imechapishwa mnamo {date}", - "created_at": "Imeundwa mnamo {date}", - "failed_to_open_file": "Imeshindwa kufungua faili. Angalia kumbukumbu kwa maelezo zaidi", - "failed_to_get_file": "Imeshindwa kupata faili" - }, - "messaging_preview": { - "processed_messages_toast": "Ujumbe {count} umechapishwa", - "processed_messages_text": "Ujumbe {count} umechapishwa", - "close_button_description": "Funga", - "bridge_connection_failed": "Imeshindwa kuunganisha kwenye daraja. Hakikisha Snapchat inafanya kazi chinichini", - "bridge_init_failed": "Imeshindwa kuanzisha daraja la ujumbe. Hakikisha Snapchat inafanya kazi chinichini", - "message_fetch_failed": "Imeshindwa kupata ujumbe", - "no_message_hint": "Hakuna ujumbe", - "save_selection_option": "Hifadhi uteuzi", - "save_all_option": "Hifadhi zote", - "unsave_selection_option": "Acha kuhifadhi uteuzi", - "unsave_all_option": "Acha kuhifadhi zote", - "mark_selection_as_seen_option": "Weka alama kwenye snap iliyochaguliwa kama imeonekana", - "mark_all_as_seen_option": "Weka alama kwenye snap zote kama zimeonekana", - "delete_selection_option": "Futa uteuzi", - "delete_all_option": "Futa zote" - }, - "logger_history": { - "download_started_toast": "Upakuaji umeanza!", - "download_success_toast": "Imepakuliwa kwa {path}", - "download_failed_toast": "Imeshindwa kupakua {message}", - "edited_at_text": "{message} (imehaririwa mnamo {date})", - "download_button": "Pakua", - "select_conversation_placeholder": "Chagua mazungumzo", - "close_button_description": "Funga", - "search_button_description": "Tafuta", - "list_friend_format": "Rafiki {name}", - "list_group_format": "Kikundi {name}", - "no_more_messages": "Hakuna ujumbe zaidi", - "reverse_order_checkbox": "Mpangilio wa kinyume", - "chat_attachment": "Kiambatisho {index}", - "empty_message": "Ujumbe tupu wa gumzo", - "message_parse_failed": "Imeshindwa kuchanganua ujumbe", - "unknown_sender": "Mtumaji asiyejulikana", - "download_attachment_failed_toast": "Imeshindwa kupakua kiambatisho", - "log_header_format": "{username} ({type}) - {date}" - }, - "file_imports": { - "import_file_button": "Ingiza faili", - "file_not_found": "Faili haipatikani", - "file_import_failed": "Imeshindwa kuingiza faili: {error}", - "file_imported": "Faili imeingizwa kwa mafanikio", - "file_delete_failed": "Imeshindwa kufuta faili", - "no_files_hint": "Hapa unaweza kuingiza faili za kutumia katika Snapchat. Bonyeza kitufe hapa chini ili kuingiza faili." - }, - "better_location": { - "spoofed_coordinates_title": "LAT {latitude}, LNG {longitude}", - "save_coordinates_dialog_title": "Hifadhi kuratibu", - "saved_name_dialog_hint": "Jina lililohifadhiwa", - "latitude_dialog_hint": "Latitudo", - "longitude_dialog_hint": "Longitudo", - "save_dialog_button": "Hifadhi", - "choose_location_button": "Chagua Mahali", - "teleport_to_friend_button": "Safiri kwa rafiki", - "spoof_location_toggle": "Danganya eneo", - "suspend_location_updates": "Sitisha masasisho ya eneo", - "saved_coordinates_title": "Kuratibu zilizohifadhiwa", - "no_saved_coordinates_hint": "Hakuna kuratibu zilizohifadhiwa", - "delete_dialog_title": "Futa kuratibu zilizohifadhiwa", - "delete_dialog_message": "Una uhakika unataka kufuta kuratibu hizi zilizohifadhiwa?", - "teleport_to_friend_title": "Safiri kwa rafiki", - "search_bar": "Tafuta", - "no_friends_map": "Hakuna marafiki kwenye ramani", - "no_friends_found": "Hakuna marafiki waliopatikana", - "edit_location_button_description": "Hariri Mahali", - "add_icon_description": "Ongeza", - "edit_icon_description": "Hariri", - "delete_icon_description": "Futa" - } - }, - "dialogs": { - "add_friend": { - "title": "Ongeza rafiki au kikundi", - "search_hint": "Tafuta", - "fetch_error": "Imeshindwa kupata data", - "category_groups": "Vikundi", - "category_friends": "Marafiki", - "participants_text": "Washiriki {count}", - "search_icon_description": "Tafuta" - }, - "scripting_warning": { - "title": "Onyo", - "content": "PurrfectSnap inajumuisha zana ya kuandika hati, inayoruhusu utekelezaji wa msimbo uliobainishwa na mtumiaji kwenye kifaa chako. Tumia tahadhari kali na sakinisha tu moduli kutoka kwa vyanzo vinavyojulikana, vinavyoaminika. Moduli ambazo hazijaidhinishwa au ambazo hazijathibitishwa zinaweza kusababisha hatari za usalama kwenye mfumo wako." - }, - "reset_config": { - "title": "Weka upya usanidi", - "content": "Una uhakika unataka kuweka upya usanidi?", - "success_toast": "Usanidi umewekwa upya kwa mafanikio" - }, - "export_config": { - "title": "Hamisha data nyeti?", - "content": "Je, ungependa kuhamisha usanidi na data nyeti? (Kama vile kuratibu za eneo, n.k.)" - }, - "messaging_action": { - "title": "Chagua aina za maudhui ya kuchakatwa", - "select_all_button": "Chagua Zote" - }, - "file_imports": { - "no_files_settings_hint": "Hakuna faili zilizopatikana. Hakikisha umeingiza faili zinazohitajika katika sehemu ya uingizaji wa faili", - "settings_select_file_hint": "Chagua faili iliyoingizwa" - }, - "quick_actions_dialog": { - "title": "Hariri vitendo vya haraka", - "subtitle": "Chagua na ubadilishe ukubwa wa vitendo vyako vya haraka." - } - }, - "friend_tracker": { - "rules_tab": "Kanuni", - "logs_tab": "Kumbukumbu", - "export_dialog_title": "Hamisha", - "bulk_export_button": "Uhamishaji wa jumla", - "individual_export_button": "Uhamishaji wa kibinafsi", - "invalid_import_type_dialog_title": "Aina ya uingizaji si sahihi", - "invalid_import_type_dialog_text": "Faili iliyochaguliwa haiendani na aina hii ya uingizaji. Tafadhali chagua aina sahihi ya uingizaji.", - "import_dialog_title": "Ingiza", - "bulk_import_button": "Uingizaji wa jumla", - "individual_import_button": "Uingizaji wa kibinafsi", - "import_button_description": "Ingiza", - "export_button_description": "Hamisha", - "export_button": "Hamisha", - "delete_button_description": "Futa", - "delete_button": "Futa", - "catalog_button_description": "Katalogi", - "catalog_button": "Katalogi", - "add_rule_button_description": "Ongeza kanuni", - "add_rule_button": "Ongeza kanuni", - "no_rules_found": "Hakuna kanuni zilizopatikana", - "empty_rule_name": "(tupu)", - "events_suffix": "matukio", - "scopes_suffix": "wigo", - "select_rule_to_export_title": "Chagua Kanuni ya kuhamisha", - "deleted_logs_toast": "Kumbukumbu {count} zimefutwa", - "delete_logs_dialog_title": "Futa kumbukumbu?", - "deleting_logs_dialog_text": "Inafuta kumbukumbu {count}...", - "delete_logs_dialog_confirm_text": "Hii itafuta kumbukumbu kulingana na kichujio cha sasa na hoja ya utafutaji. Kitendo hiki hakiwezi kutenduliwa.", - "exported_logs_toast": "Kumbukumbu zimehamishwa!", - "export_logs_failed_toast": "Imeshindwa kuhamisha kumbukumbu. Angalia LogCat kwa maelezo zaidi.", - "export_logs_dialog_title": "Hamisha kumbukumbu?", - "exporting_logs_dialog_text": "Inahamisha kumbukumbu...", - "export_logs_dialog_confirm_text": "Hii itahamisha kumbukumbu kulingana na kichujio cha sasa na hoja ya utafutaji.", - "export_as_button": "Hamisha kama {type}", - "filters_title": "Vichujio", - "search_by_label": "Tafuta kwa", - "newest_first_label": "Mpya kwanza", - "since_label": "Tangu", - "until_label": "Hadi", - "pick_a_date_button": "Chagua tarehe", - "search_placeholder": "Tafuta", - "filter_button_description": "Kichujio", - "clear_button_description": "Futa", - "no_logs_found": "Hakuna kumbukumbu zilizopatikana", - "log_event_format": "{event} katika {conversation}", - "condition_only_inside_conversation": "Ni wakati tu nipo ndani ya mazungumzo", - "condition_only_outside_conversation": "Ni wakati tu nipo nje ya mazungumzo", - "condition_only_when_app_active": "Ni wakati tu Snapchat inafanya kazi", - "condition_only_when_app_inactive": "Ni wakati tu Snapchat haifanyi kazi", - "condition_no_push_notification_when_app_active": "Hakuna arifa ya kushinikiza wakati Snapchat inafanya kazi", - "add_event_dialog_title": "Ongeza Tukio", - "event_type_label": "Aina ya Tukio", - "triggers_title": "Vichochezi", - "conditions_title": "Masharti", - "add_button": "Ongeza", - "default_rule_name": "Kanuni maalum", - "discard_changes_dialog_title": "Tupa mabadiliko?", - "discard_changes_dialog_text": "Una mabadiliko ambayo hayajahifadhiwa. Una uhakika unataka kuyatupa?", - "discard_button": "Tupa", - "cannot_save_rule_dialog_title": "Haiwezi kuhifadhi kanuni", - "cannot_save_rule_dialog_text": "Kanuni lazima iwe na angalau tukio moja ili kuhifadhi.", - "duplicate_rule_name_dialog_title": "Jina la kanuni rudufu", - "duplicate_rule_name_dialog_text": "Kanuni yenye jina hili tayari ipo. Tafadhali chagua jina tofauti.", - "delete_rule_dialog_title": "Futa kanuni", - "delete_rule_dialog_text": "Una uhakika unataka kufuta kanuni hii?", - "new_rule_title": "Kanuni Mpya", - "edit_rule_title": "Hariri Kanuni", - "back_button_description": "Nyuma", - "save_button_description": "Hifadhi", - "general_section_title": "Jumla", - "rule_name_label": "Jina la kanuni", - "author_name_label": "Jina la mwandishi", - "scope_section_title": "Wigo", - "scope_all": "Zote", - "scope_whitelist": "Orodha nyeupe", - "scope_blacklist": "Orodha nyeusi", - "select_friends_groups_button": "Chagua marafiki/vikundi ({count})", - "events_section_title": "Matukio", - "add_event_button": "Ongeza Tukio", - "no_events_text": "Hakuna matukio" - }, - "friend_tracker_catalog": { - "download_failed": "Imeshindwa kupakua: {code}", - "error": "Kosa: {message}", - "no_repos_added": "Hakuna hifadhi zilizoongezwa.", - "no_rules_available": "Hakuna kanuni zinazopatikana kutoka kwa hifadhi yoyote.", - "by_author": "na {author}", - "imported_button": "Imeingizwa", - "import_button": "Ingiza", - "title": "Katalogi ya Kifuatilia Marafiki", - "manage_repos_description": "Dhibiti hifadhi" - }, - "friend_tracker_export": { - "title": "Hamisha kanuni", - "back_button_description": "Nyuma", - "exported_toast": "Kanuni za kifuatilia marafiki zimehamishwa!", - "export_failed_toast": "Imeshindwa kuhamisha kanuni: {message}", - "save_button": "Hifadhi", - "expand_button_description": "Panua" - }, - "friend_tracker_import": { - "title": "Ingiza kanuni", - "back_button_description": "Nyuma", - "imported_toast": "Kanuni za kifuatilia marafiki zimeingizwa!", - "import_failed_toast": "Imeshindwa kuingiza kanuni: {message}", - "confirm_button": "Thibitisha", - "expand_button_description": "Panua" - }, - "friend_tracker_repos": { - "invalid_repo_title": "Hifadhi si sahihi", - "add_repo_button": "Ongeza hifadhi", - "add_repo_dialog_title": "Ongeza URL ya hifadhi", - "repo_url_label": "URL ya hifadhi", - "repo_added_toast": "Hifadhi imeongezwa kwa mafanikio!", - "invalid_repo_error": "Hii haionekani kuwa hifadhi halali ya Kifuatilia Marafiki.", - "add_repo_failed_toast": "Imeshindwa kuongeza hifadhi: {message}", - "add_button": "Ongeza", - "no_repos_added": "Hakuna hifadhi zilizoongezwa", - "remove_button": "Ondoa", - "remove_repo_dialog_title": "Ondoa hifadhi", - "remove_repo_dialog_text": "Una uhakika unataka kuondoa hifadhi hii?" - }, - "navigation": { - "tracker_tab_label": "Kifuatilia", - "customize_bottom_bar_title": "Geuza upau wa chini kukufaa", - "customize_bottom_bar_subtitle": "Panga upya, ongeza, au ondoa vichupo. Upeo wa tano.", - "shown_tabs_title": "Vichupo vilivyoonyeshwa", - "no_tabs_selected_text": "Hakuna vichupo vilivyochaguliwa", - "available_tabs_title": "Vichupo vinavyopatikana", - "reset_button": "Weka upya", - "done_button": "Imekamilika" - }, - "scripting": { - "script_already_installed": "Hati tayari imesakinishwa!", - "downloading_script": "Inapakua hati...", - "script_downloaded": "Hati {name} imepakuliwa!", - "download_script_failed": "Imeshindwa kupakua hati. Angalia kumbukumbu kwa maelezo zaidi", - "import_script_from_url_title": "Ingiza hati kutoka URL", - "import_script_warning": "Onyo: Hati zilizoingizwa zinaweza kuwa na madhara kwa kifaa chako. Ingiza tu hati kutoka kwa vyanzo vinavyoaminika.", - "enter_url_label": "Weka URL hapa:", - "script_imported": "Hati {name} imeingizwa!", - "import_failed": "Imeshindwa kuingiza hati. {message}. Angalia kumbukumbu kwa maelezo zaidi", - "import_button": "Ingiza", - "update_module_button": "Sasisha moduli", - "updating_script": "Inasasisha hati {name}...", - "module_not_found": "Moduli haipatikani", - "updated_script": "Imesasishwa {name} hadi toleo la {version}", - "update_module_failed": "Imeshindwa kusasisha moduli. Angalia kumbukumbu kwa maelezo zaidi", - "edit_module_button": "Hariri moduli", - "open_module_failed": "Imeshindwa kufungua faili ya moduli. Angalia kumbukumbu kwa maelezo zaidi", - "clear_module_data_button": "Futa data ya moduli", - "module_data_cleared": "Data ya moduli imefutwa!", - "clear_module_data_failed": "Imeshindwa kufuta data ya moduli. Angalia kumbukumbu kwa maelezo zaidi", - "delete_module_button": "Futa moduli", - "deleted_script": "Hati {name} imefutwa!", - "delete_module_failed": "Imeshindwa kufuta moduli. Angalia kumbukumbu kwa maelezo zaidi", - "actions_title": "Vitendo", - "no_description": "Hakuna maelezo", - "update_available": "Sasisho linapatikana: {version}", - "actions_button": "Vitendo", - "loaded_script": "Hati {name} imepakiwa", - "unloaded_script": "Hati {name} haijapakiwa", - "enable_script_failed": "Imeshindwa kuwezesha hati. Angalia kumbukumbu kwa maelezo zaidi", - "disable_script_failed": "Imeshindwa kuzima hati. Angalia kumbukumbu kwa maelezo zaidi", - "select_scripts_folder_toast": "Tafadhali chagua folda yako ya Hati!", - "manage_repos_button": "Dhibiti hifadhi", - "import_from_url_button": "Ingiza kutoka URL", - "open_scripts_folder_button": "Fungua folda ya Hati", - "no_settings_for_module": "Moduli hii haina mipangilio yoyote", - "installed_scripts_tab": "Hati zilizosakinishwa", - "catalog_tab": "Katalogi", - "no_scripts_folder_selected_title": "Hakuna folda ya hati iliyochaguliwa", - "select_folder_button": "Chagua folda", - "no_scripts_found_title": "Hakuna hati zilizopatikana.", - "use_catalog_to_add_scripts": "Tumia kichupo cha Katalogi kuongeza hati!", - "ok_button_timeout": "Sawa ({timeout})", - "documentation_button": "Nyaraka", - "catalog": { - "script_already_installed": "Hati tayari imesakinishwa!", - "download_failed": "Imeshindwa kupakua: {code}", - "script_downloaded": "Hati imepakuliwa!", - "could_not_create_file": "Haikuweza kuunda faili.", - "no_scripts_folder_selected": "Hakuna folda ya hati iliyochaguliwa.", - "error": "Kosa: {message}", - "no_repos_added": "Hakuna hifadhi zilizoongezwa.", - "repo_list_info": "Hapa unaweza kupata orodha ya hifadhi:", - "link_text": "Kiungo", - "no_scripts_available": "Hakuna hati zinazopatikana kutoka kwa hifadhi yoyote.", - "by_author": "na {author}", - "version": "Toleo: {version}", - "installed_button": "Imesakinishwa", - "download_button": "Pakua" - }, - "repos": { - "invalid_repo_title": "Hifadhi si sahihi", - "add_repo_button": "Ongeza hifadhi", - "add_repo_dialog_title": "Ongeza URL ya hifadhi", - "repo_url_label": "URL ya hifadhi", - "repo_added_toast": "Hifadhi imeongezwa kwa mafanikio!", - "invalid_repo_error": "Hii haionekani kuwa hifadhi halali ya hati.", - "add_repo_failed_toast": "Imeshindwa kuongeza hifadhi: {message}", - "add_button": "Ongeza", - "no_repos_added": "Hakuna hifadhi zilizoongezwa", - "remove_button": "Ondoa", - "remove_repo_dialog_title": "Ondoa hifadhi", - "remove_repo_dialog_text": "Una uhakika unataka kuondoa hifadhi hii?" - } - }, - "features": { - "config_import": { - "title": "Thibitisha uingizaji", - "back_button_description": "Nyuma", - "config_imported_toast": "Usanidi umeingizwa!", - "confirm_button": "Thibitisha", - "expand_button_description": "Panua", - "enable_feature": "Washa kipengele", - "enabled": "Imewashwa", - "disabled": "Imezimwa" - }, - "config_export": { - "title": "Muhtasari wa uhamishaji", - "back_button_description": "Nyuma", - "save_button": "Hifadhi", - "expand_button_description": "Panua", - "enable_feature": "Washa kipengele", - "enabled": "Imewashwa", - "disabled": "Imezimwa" - } - }, - "manage_repos": { - "title": "Dhibiti hifadhi za {featureName}", - "add_repo_button": "Ongeza hifadhi", - "add_repo_dialog_title": "Ongeza URL ya hifadhi", - "repo_url_label": "URL ya hifadhi", - "repo_added_successfully": "Hifadhi imeongezwa kwa mafanikio!", - "add_repo_failed": "Imeshindwa kuongeza hifadhi: {message}", - "add_button": "Ongeza", - "no_repos_added": "Hakuna hifadhi zilizoongezwa", - "remove_button": "Ondoa" - } - }, - "rules": { - "toasts": { - "enabled": "{ruleName} imewashwa", - "disabled": "{ruleName} imezimwa" - }, - "modes": { - "blacklist": "Hali ya orodha nyeusi", - "whitelist": "Hali ya orodha nyeupe" - }, - "properties": { - "auto_download": { - "name": "Upakuaji wa kiotomatiki", - "description": "Pakua snap kiotomatiki unapozitazama", - "options": { - "blacklist": "Ondoa kwenye upakuaji wa kiotomatiki", - "whitelist": "Upakuaji wa kiotomatiki" - } - }, - "stealth": { - "name": "Hali ya siri", - "description": "Inazuia mtu yeyote kujua kuwa umefungua snap/gumzo zao", - "options": { - "blacklist": "Ondoa kwenye hali ya siri", - "whitelist": "Hali ya siri" - } - }, - "auto_save": { - "name": "Hifadhi kiotomatiki", - "description": "Huhifadhi ujumbe wa gumzo unapoutazama", - "options": { - "blacklist": "Ondoa kwenye hifadhi ya kiotomatiki", - "whitelist": "Hifadhi kiotomatiki" - } - }, - "unsaveable_messages": { - "name": "Ujumbe usioweza kuhifadhiwa", - "description": "Inazuia ujumbe kuhifadhiwa kwenye gumzo na watu wengine", - "options": { - "blacklist": "Ondoa kwenye ujumbe usioweza kuhifadhiwa", - "whitelist": "Ujumbe usioweza kuhifadhiwa" - } - }, - "auto_open_snaps": { - "name": "Fungua snap kiotomatiki", - "description": "Hufungua snap kiotomatiki unapozipokea", - "options": { - "blacklist": "Ondoa kwenye kufungua snap kiotomatiki", - "whitelist": "Fungua snap kiotomatiki" - } - }, - "hide_friend_feed": { - "name": "Ficha kwenye mlisho wa marafiki" - }, - "e2e_encryption": { - "name": "Tumia usimbaji fiche wa E2E" - }, - "pin_conversation": { - "name": "Bandika mazungumzo" - }, - "exclude_message_logger": { - "name": "Ondoa kwenye kihifadhi ujumbe" - } - } - }, - "actions": { - "clean_snapchat_cache": { - "name": "Safisha kashe ya Snapchat", - "description": "Husafisha kashe ya Snapchat" - }, - "manage_friend_list": { - "name": "Dhibiti orodha ya marafiki", - "description": "Ingiza/Hamisha orodha yako ya marafiki kwa ajili ya kuhifadhi nakala" - }, - "export_chat_messages": { - "name": "Hamisha ujumbe wa gumzo", - "description": "Huhamisha ujumbe wa gumzo kwenye faili ya JSON/HTML/TXT" - }, - "export_memories": { - "name": "Hamisha kumbukumbu", - "description": "Huhamisha kumbukumbu kwenye faili ya zip" - }, - "bulk_messaging_action": { - "name": "Kitendo cha ujumbe wa jumla", - "description": "Hufanya vitendo kama vile kufuta marafiki kwa jumla au kufuta gumzo" - }, - "regen_mappings": { - "name": "Tengeneza ramani upya", - "description": "Hutengeneza ramani upya" - }, - "change_language": { - "name": "Badilisha lugha", - "description": "Hubadilisha lugha ya PurrfectSnap" - }, - "file_imports": { - "name": "Uingizaji wa faili", - "description": "Ingiza faili za kutumia katika Snapchat" - }, - "friend_tracker": { - "name": "Kifuatilia Marafiki", - "description": "Fuatilia marafiki zako kwenye Snapchat" - }, - "logger_history": { - "name": "Historia ya Kihifadhi", - "description": "Angalia historia ya ujumbe uliohifadhiwa" - } - }, - "features": { - "notices": { - "unstable": "⚠ Si thabiti", - "ban_risk": "⚠ Kipengele hiki kinaweza kusababisha kupigwa marufuku", - "internal_behavior": "⚠ Hii inaweza kuvunja tabia ya ndani ya Snapchat" - }, - "properties": { - "downloader": { - "name": "Kipakuzi", - "description": "Pakua Midia ya Snapchat", - "properties": { - "save_folder": { - "name": "Hifadhi folda", - "description": "Chagua saraka ambapo midia yote inapaswa kupakuliwa" - }, - "auto_download_sources": { - "name": "Vyanzo vya upakuaji wa kiotomatiki", - "description": "Chagua vyanzo vya kupakua kiotomatiki" - }, - "prevent_self_auto_download": { - "name": "Zuia upakuaji wa kiotomatiki wa kibinafsi", - "description": "Huzuia snap zako mwenyewe kupakuliwa kiotomatiki" - }, - "path_format": { - "name": "Umbizo la njia", - "description": "Bainisha umbizo la njia ya faili" - }, - "allow_duplicate": { - "name": "Ruhusu rudufu", - "description": "Huruhusu midia ileile kupakuliwa mara kadhaa" - }, - "merge_overlays": { - "name": "Unganisha viwekeleo", - "description": "Huunganisha maandishi na midia ya snap kuwa faili moja" - }, - "force_image_format": { - "name": "Lazimisha umbizo la picha", - "description": "Hulazimisha picha kuhifadhiwa katika umbizo maalum" - }, - "force_voice_note_format": { - "name": "Lazimisha umbizo la dokezo la sauti", - "description": "Hulazimisha madokezo ya sauti kuhifadhiwa katika umbizo maalum" - }, - "auto_download_voice_notes": { - "name": "Pakua madokezo ya sauti kiotomatiki", - "description": "Hupakua madokezo ya sauti kiotomatiki unapoyacheza" - }, - "download_profile_pictures": { - "name": "Pakua picha za wasifu", - "description": "Hukuruhusu kupakua picha za wasifu kutoka kwenye ukurasa wa wasifu" - }, - "opera_download_button": { - "name": "Kitufe cha kupakua cha Opera", - "description": "Huongeza kitufe cha kupakua kwenye kona ya juu kulia unapotazama snap.\nKubonyeza kwa muda mrefu kwenye vitufe kutalazimisha upakuaji" - }, - "download_context_menu": { - "name": "Menyu ya muktadha ya upakuaji", - "description": "Hukuruhusu kupakua/kuonyesha awali ujumbe kutoka kwa gumzo au hadithi kwa kutumia menyu ya muktadha.\nKubonyeza kwa muda mrefu kwenye vitufe kutalazimisha upakuaji" - }, - "ffmpeg_options": { - "name": "Chaguo za FFmpeg", - "description": "Bainisha chaguo za ziada za FFmpeg", - "properties": { - "threads": { - "name": "Nyuzi", - "description": "Idadi ya nyuzi za kutumia" - }, - "preset": { - "name": "Weka mapema", - "description": "Weka kasi ya ugeuzaji" - }, - "constant_rate_factor": { - "name": "Kiwango cha ukadiriaji cha kudumu", - "description": "Weka kiwango cha ukadiriaji cha kudumu kwa kisimbaji video\nKutoka 0 hadi 51 kwa libx264" - }, - "video_bitrate": { - "name": "Kiwango cha data ya video", - "description": "Weka Kiwango cha data ya Video (kbps)" - }, - "audio_bitrate": { - "name": "Kiwango cha data ya sauti", - "description": "Weka Kiwango cha data ya Sauti (kbps)" - }, - "custom_video_codec": { - "name": "Kisimbaji video maalum", - "description": "Weka kisimbaji video maalum (k.m. libx264)" - }, - "custom_audio_codec": { - "name": "Kisimbaji sauti maalum", - "description": "Weka kisimbaji sauti maalum (k.m. aac)" - } - } - }, - "logging": { - "name": "Kuweka kumbukumbu", - "description": "Huonyesha ujumbe mfupi midia inapopakuliwa" - }, - "custom_path_format": { - "name": "Umbizo la Njia Maalum", - "description": "Bainisha umbizo la njia maalum kwa midia iliyopakuliwa\n\nVigezo vinavyopatikana:\n - %username%\n - %source%\n - %hash%\n - %date_time%" - } - } - }, - "user_interface": { - "name": "Kiolesura cha mtumiaji", - "description": "Geuza kukufaa mwonekano na hisia za Snapchat", - "properties": { - "enable_app_appearance": { - "name": "Washa mipangilio ya mwonekano wa programu", - "description": "Huwasha mpangilio wa mwonekano wa programu uliofichwa\nHuweza isihitajike kwenye matoleo mapya ya Snapchat" - }, - "friend_feed_message_preview": { - "name": "Onyesho la awali la ujumbe wa mlisho wa marafiki", - "description": "Huonyesha onyesho la awali la ujumbe wa mwisho kwenye mlisho wa marafiki", - "properties": { - "amount": { - "name": "Kiasi", - "description": "Idadi ya ujumbe wa kuonyesha awali" - } - } - }, - "snap_preview": { - "name": "Onyesho la awali la snap", - "description": "Huonyesha onyesho la awali dogo kando ya snap ambazo hazijaonekana kwenye gumzo" - }, - "bootstrap_override": { - "name": "Ubatilishaji wa Bootstrap", - "description": "Hubatilisha mipangilio ya bootstrap inayoendeshwa na mtumiaji", - "properties": { - "app_appearance": { - "name": "Mwonekano wa programu", - "description": "Huweka mwonekano wa programu unaoendelea" - }, - "home_tab": { - "name": "Kichupo cha nyumbani", - "description": "Hubatilisha kichupo cha kuanza unapofungua Snapchat" - } - } - }, - "force_amoled_theme": { - "name": "Hali ya giza ya AMOLED", - "description": "Hutumia mandharinyuma meusi halisi kwa mandhari meusi" - }, - "map_friend_nametags": { - "name": "Lebo za majina za ramani ya marafiki zilizoboreshwa", - "description": "Huboresha lebo za majina za marafiki kwenye Snapmap" - }, - "prevent_message_list_auto_scroll": { - "name": "Zuia orodha ya ujumbe kusogeza kiotomatiki", - "description": "Huzuia orodha ya ujumbe kusogeza chini unapotuma/kupokea ujumbe" - }, - "streak_expiration_info": { - "name": "Onyesha maelezo ya kuisha kwa mfululizo", - "description": "Huonyesha kipima muda cha kuisha kando ya kaunta ya mfululizo" - }, - "hide_friend_feed_entry": { - "name": "Ficha ingizo la mlisho wa marafiki", - "description": "Huficha rafiki maalum kwenye mlisho wa marafiki\nTumia kichupo cha kijamii kudhibiti kipengele hiki" - }, - "hide_streak_restore": { - "name": "Ficha urejeshaji wa mfululizo", - "description": "Huficha kitufe cha kurejesha kwenye mlisho wa marafiki" - }, - "hide_quick_add_suggestions": { - "name": "Ficha mapendekezo ya kuongeza haraka", - "description": "Huondoa mapendekezo ya kuongeza rafiki haraka" - }, - "hide_story_suggestions": { - "name": "Ficha mapendekezo ya hadithi", - "description": "Huondoa mapendekezo kwenye ukurasa wa hadithi" - }, - "hide_ui_components": { - "name": "Ficha vipengele vya UI", - "description": "Chagua ni vipengele vipi vya UI vya kuficha" - }, - "opera_media_quick_info": { - "name": "Maelezo ya haraka ya Midia ya Opera", - "description": "Huonyesha maelezo muhimu ya midia kama vile tarehe ya kuundwa kwenye menyu ya muktadha ya kitazamaji cha Opera" - }, - "old_bitmoji_selfie": { - "name": "Selfie ya zamani ya Bitmoji", - "description": "Hurudisha selfie za Bitmoji kutoka kwa matoleo ya zamani ya Snapchat" - }, - "disable_spotlight": { - "name": "Zima Spotlight", - "description": "Huzima ukurasa wa Spotlight" - }, - "friend_feed_menu_buttons": { - "name": "Vitufe vya menyu ya mlisho wa marafiki", - "description": "Chagua ni vitufe vipi vya kuonyesha kwenye menyu ya mlisho wa marafiki" - }, - "auto_close_friend_feed_menu": { - "name": "Funga menyu ya mlisho wa marafiki kiotomatiki", - "description": "Hufunga menyu ya mlisho wa marafiki kiotomatiki baada ya kubofya kitufe cha kuweka" - }, - "vertical_story_viewer": { - "name": "Kitazamaji hadithi wima", - "description": "Huwasha kitazamaji hadithi wima kwa hadithi zote" - }, - "enable_friend_feed_menu_bar": { - "name": "Washa upau wa menyu ya mlisho wa marafiki", - "description": "Huwasha upau mpya wa menyu ya mlisho wa marafiki" - }, - "message_indicators": { - "name": "Viashiria vya ujumbe", - "description": "Huongeza aikoni maalum za viashiria kwenye ujumbe\nKumbuka: Viashiria huenda visiwe sahihi kwa 100%" - }, - "stealth_mode_indicator": { - "name": "Kiashiria cha hali ya siri", - "description": "Huongeza emoji ya 👻 kando ya mazungumzo katika hali ya siri" - }, - "edit_text_override": { - "name": "Ubatilishaji wa maandishi ya kuhariri", - "description": "Hubatilisha tabia ya sehemu ya maandishi" - }, - "prevent_forced_keyboard": { - "name": "Zuia kibodi kulazimishwa", - "description": "Huzuia Snapchat kuwasha kibodi kiotomatiki unapofungua gumzo" - }, - "settings_menu": { - "name": "Menyu ya Mipangilio", - "description": "Hubadilisha jinsi unavyofungua menyu ya PurrfectSnap", - "options": { - "default": "Chaguo-msingi", - "legacy": "Urithi" - } - } - } - }, - "messaging": { - "name": "Ujumbe", - "description": "Geuza kukufaa jinsi unavyowasiliana na marafiki", - "properties": { - "bypass_screenshot_detection": { - "name": "Pita ugunduzi wa picha ya skrini", - "description": "Huzuia Snapchat kugundua unapopiga picha ya skrini" - }, - "anonymous_story_viewing": { - "name": "Kutazama hadithi bila kujulikana", - "description": "Huzuia mtu yeyote kujua kuwa umetazama hadithi yake" - }, - "prevent_story_rewatch_indicator": { - "name": "Zuia kiashiria cha kutazama tena hadithi", - "description": "Huzuia mtu yeyote kujua kuwa umetazama tena hadithi yake" - }, - "hide_peek_a_peek": { - "name": "Ficha chungulia-chungulia", - "description": "Huzuia arifa ya nusu-telezesha unapoingia kwenye gumzo" - }, - "hide_bitmoji_presence": { - "name": "Ficha uwepo wa Bitmoji", - "description": "Huzuia Bitmoji yako kuonekana unapokuwa kwenye gumzo" - }, - "hide_typing_notifications": { - "name": "Ficha arifa za kuandika", - "description": "Huzuia mtu yeyote kujua kuwa unaandika ujumbe" - }, - "unlimited_snap_view_time": { - "name": "Muda wa kutazama snap bila kikomo", - "description": "Huondoa kikomo cha muda wa kutazama snap" - }, - "auto_mark_as_read": { - "name": "Weka alama kama imesomwa kiotomatiki", - "description": "Huweka alama kiotomatiki kwenye Ujumbe/Snap kama zimesomwa hata wakati hali ya siri imewashwa" - }, - "mark_snap_as_seen_button": { - "name": "Kitufe cha kuweka alama kama imeonekana", - "description": "Huongeza kitufe cha kuweka alama kama imeonekana unapoitazama.\nHii itafanya kazi hata wakati hali ya siri imewashwa" - }, - "skip_when_marking_as_seen": { - "name": "Ruka unapoweka alama kama imeonekana", - "description": "Hupita kiotomatiki hadi kwenye snap inayofuata unapoweka alama kwenye snap kama imeonekana.\nTumia pamoja na kitufe cha kuweka alama kama imeonekana" - }, - "loop_media_playback": { - "name": "Uchezaji wa midia unaojirudia", - "description": "Hucheza midia kwa kujirudia unapotazama snap/hadithi" - }, - "disable_replay_in_ff": { - "name": "Zima uchezaji tena katika FF", - "description": "Huzima uwezo wa kucheza tena kwa kubonyeza kwa muda mrefu kutoka kwenye mlisho wa marafiki" - }, - "half_swipe_notifier": { - "name": "Arifa ya nusu-telezesha", - "description": "Hukuarifu mtu anaponusu-telezesha kwenye mazungumzo", - "properties": { - "min_duration": { - "name": "Muda wa chini", - "description": "Muda wa chini wa nusu-telezesha (kwa sekunde)" - }, - "max_duration": { - "name": "Muda wa juu", - "description": "Muda wa juu wa nusu-telezesha (kwa sekunde)" - } - } - }, - "call_start_confirmation": { - "name": "Uthibitisho wa kuanza simu", - "description": "Huonyesha kidirisha cha uthibitisho unapoanza simu" - }, - "unlimited_conversation_pinning": { - "name": "Ubandikaji wa mazungumzo bila kikomo", - "description": "Hukuruhusu kubandika idadi isiyo na kikomo ya mazungumzo" - }, - "disable_snap_mode_restrictions": { - "name": "Zima vikwazo vya hali ya SNAP", - "description": "Hukuruhusu kutazama snap zinazojifuta zenyewe bila vikwazo" - }, - "prevent_message_sending": { - "name": "Zuia kutuma ujumbe", - "description": "Huzuia kutuma aina fulani za ujumbe" - }, - "friend_mutation_notifier": { - "name": "Arifa ya mabadiliko ya rafiki", - "description": "Hukuarifu kitu kinapobadilika kwenye wasifu wa rafiki" - }, - "better_notifications": { - "name": "Arifa bora zaidi", - "description": "Huongeza maelezo zaidi kwenye arifa zinazopokelewa", - "properties": { - "group_notifications": { - "name": "Arifa za kikundi", - "description": "Hukusanya arifa za kikundi kuwa moja" - }, - "chat_preview": { - "name": "Onyesho la awali la gumzo", - "description": "Huonyesha onyesho la awali la ujumbe uliopokelewa kwenye arifa" - }, - "media_preview": { - "name": "Onyesho la awali la midia", - "description": "Huonyesha onyesho la awali la aina za midia zilizochaguliwa kwenye arifa" - }, - "media_caption": { - "name": "Maelezo ya midia", - "description": "Huonyesha maelezo ya midia kwenye arifa" - }, - "stacked_media_messages": { - "name": "Ujumbe wa midia uliopangwa", - "description": "Huunganisha ujumbe mwingi wa midia kuwa arifa moja ya maandishi wakati haziwezi kuonyeshwa awali. Tumia pamoja na onyesho la awali la gumzo" - }, - "friend_add_source": { - "name": "Chanzo cha kuongeza rafiki", - "description": "Huonyesha chanzo cha ombi la urafiki kwenye arifa" - }, - "reply_button": { - "name": "Kitufe cha kujibu", - "description": "Huongeza kitufe cha kujibu kwenye arifa" - }, - "smart_replies": { - "name": "Majibu mahiri", - "description": "Huongeza majibu yaliyopendekezwa kwenye arifa (Android 10+). Tumia pamoja na kitufe cha kujibu" - }, - "download_button": { - "name": "Kitufe cha kupakua", - "description": "Hukuruhusu kupakua midia kutoka kwenye arifa" - }, - "mark_as_read_button": { - "name": "Kitufe cha kuweka alama kama imesomwa", - "description": "Hukuruhusu kuweka alama kwenye ujumbe kama umesomwa kutoka kwenye arifa" - }, - "mark_as_read_and_save_in_chat": { - "name": "Weka alama kama imesomwa na uhifadhi kwenye gumzo", - "description": "Huongeza kitufe cha kuweka alama kama imesomwa na kuhifadhi kwenye gumzo kwenye arifa" - } - } - }, - "notification_blacklist": { - "name": "Orodha nyeusi ya arifa", - "description": "Chagua arifa ambazo zinapaswa kuzuiwa" - }, - "message_logger": { - "name": "Kihifadhi ujumbe", - "description": "Huzuia ujumbe kufutwa", - "properties": { - "keep_my_own_messages": { - "name": "Weka ujumbe wangu mwenyewe", - "description": "Huzuia ujumbe wako mwenyewe kufutwa" - }, - "auto_purge": { - "name": "Safisha kiotomatiki", - "description": "Hufuta kiotomatiki ujumbe uliohifadhiwa ambao ni wa zamani kuliko muda uliowekwa" - }, - "message_filter": { - "name": "Kichujio cha ujumbe", - "description": "Chagua ni ujumbe gani unapaswa kuhifadhiwa (tupu kwa ujumbe wote)" - }, - "deleted_message_color": { - "name": "Rangi ya ujumbe uliofutwa", - "description": "Huweka rangi ya ujumbe uliofutwa" - } - } - }, - "auto_save_messages_in_conversations": { - "name": "Hifadhi ujumbe kiotomatiki kwenye mazungumzo", - "description": "Huhifadhi kiotomatiki kila ujumbe kwenye mazungumzo" - }, - "gallery_media_send_override": { - "name": "Ubatilishaji wa kutuma midia ya ghala", - "description": "Hubatilisha chanzo cha midia unapotuma kutoka kwenye ghala" - }, - "strip_media_metadata": { - "name": "Ondoa metadata ya midia", - "description": "Huondoa metadata ya midia kabla ya kuituma kama ujumbe" - }, - "bypass_message_retention_policy": { - "name": "Pita sera ya uhifadhi wa ujumbe", - "description": "Huzuia ujumbe kufutwa baada ya kuutazama" - }, - "bypass_message_action_restrictions": { - "name": "Pita vikwazo vya vitendo vya ujumbe", - "description": "Hukuruhusu kujibu snap bila kuifungua au kuhifadhi ujumbe usioweza kuhifadhiwa" - }, - "remove_groups_locked_status": { - "name": "Ondoa hali ya kufungwa kwa vikundi", - "description": "Hukuruhusu kutazama maelezo ya kikundi baada ya kufukuzwa" - }, - "double_tap_chat_action": { - "name": "Kitendo cha gumzo la kugonga mara mbili", - "description": "Hufanya kitendo maalum unapogonga ujumbe mara mbili kwenye gumzo" - }, - "double_tap_chat_action_custom_emoji": { - "name": "Mwitikio wa emoji maalum wa kitendo cha gumzo la kugonga mara mbili", - "description": "Huweka mwitikio wa emoji maalum kwa kitendo cha gumzo la kugonga mara mbili" - } - } - }, - "global": { - "name": "Ulimwengu", - "description": "Rekebisha Mipangilio ya Ulimwengu ya Snapchat", - "properties": { - "better_location": { - "name": "Mahali pazuri zaidi", - "description": "Huboresha eneo la Snapchat", - "properties": { - "spoof_location": { - "name": "Danganya eneo", - "description": "Hubadilisha eneo lako na lingine maalum" - }, - "coordinates": { - "name": "Kuratibu", - "description": "Weka kuratibu za eneo lililodanganywa" - }, - "walk_radius": { - "name": "Radi ya kutembea", - "description": "Tembea bila mpangilio ndani ya radi hii (futi)" - }, - "always_update_location": { - "name": "Sasisha eneo kila wakati", - "description": "Hulazimisha Snapchat kusasisha eneo hata kama hakuna data ya GPS iliyopokelewa" - }, - "suspend_location_updates": { - "name": "Sitisha masasisho ya eneo", - "description": "Huzuia eneo lako kusasishwa" - }, - "spoof_battery_level": { - "name": "Danganya kiwango cha betri", - "description": "Hubadilisha kiwango cha betri ya kifaa chako kwenye ramani\nThamani lazima iwe kati ya 0 na 100" - }, - "spoof_headphones": { - "name": "Danganya vipokea sauti", - "description": "Hubadilisha hali ya kusikiliza muziki kwenye ramani" - }, - "show_battery_level": { - "name": "Onyesha kiwango cha betri", - "description": "Huonyesha kiwango cha betri cha marafiki zako kwenye ramani" - } - } - }, - "snapchat_plus": { - "name": "Snapchat Plus", - "description": "Huwasha vipengele vya Snapchat Plus\nBaadhi ya vipengele vya upande wa seva huenda visifanye kazi" - }, - "media_upload_quality": { - "name": "Ubora wa Upakiaji wa Midia", - "description": "Hubatilisha ubora wa upakiaji wa midia", - "properties": { - "force_video_upload_source_quality": { - "name": "Lazimisha ubora wa chanzo cha upakiaji wa video", - "description": "Hulazimisha Snapchat kutumia ubora wa chanzo wakati wa kupakia video\nTafadhali kumbuka kuwa hii haiwezi kuondoa metadata kutoka kwa midia" - }, - "disable_image_compression": { - "name": "Zima ukandamizaji wa picha", - "description": "Huzima ukandamizaji wa picha wakati wa kupakia midia" - }, - "custom_image_upload_format": { - "name": "Umbizo Maalum la Upakiaji wa Picha", - "description": "Huweka umbizo maalum la upakiaji wa picha\nChagua umbizo lisilo na hasara (kama PNG) kwa ubora bora" - } - } - }, - "disable_confirmation_dialogs": { - "name": "Zima vidirisha vya uthibitisho", - "description": "Huthibitisha kiotomatiki vitendo vilivyochaguliwa" - }, - "auto_updater": { - "name": "Kisasisho kiotomatiki", - "description": "Hukagua kiotomatiki masasisho mapya" - }, - "disable_metrics": { - "name": "Zima metriki", - "description": "Huzuia kutuma data maalum ya uchanganuzi kwa Snapchat" - }, - "disable_story_sections": { - "name": "Zima sehemu za hadithi", - "description": "Huondoa sehemu kwenye ukurasa wa hadithi\nHuweza kuhitaji kuonyesha upya ili kufanya kazi vizuri" - }, - "block_ads": { - "name": "Zuia matangazo", - "description": "Huzuia matangazo kuonyeshwa" - }, - "disable_custom_tabs": { - "name": "Zima vichupo maalum", - "description": "Hufungua viungo katika programu zinazotumika badala ya kivinjari cha wavuti kilichojengewa ndani" - }, - "disable_permission_requests": { - "name": "Zima maombi ya ruhusa", - "description": "Huzuia Snapchat kuomba ruhusa maalum" - }, - "disable_memories_snap_feed": { - "name": "Zima mlisho wa snap wa kumbukumbu", - "description": "Huzuia Snapchat kuonyesha kumbukumbu za hivi karibuni unapobadilisha hadi kwenye kamera" - }, - "spotlight_comments_username": { - "name": "Jina la mtumiaji la maoni ya Spotlight", - "description": "Huonyesha jina la mtumiaji la mwandishi katika maoni ya Spotlight" - }, - "bypass_video_length_restriction": { - "name": "Pita kizuizi cha urefu wa video", - "description": "Moja: hutuma video moja\nGawanya: hugawanya video baada ya kuihariri" - }, - "default_video_playback_rate": { - "name": "Kiwango chaguomsingi cha uchezaji wa video", - "description": "Huweka kasi ya msingi ya uchezaji wa video\nThamani lazima iwe kati ya 0.1 na 4.0" - }, - "video_playback_rate_slider": { - "name": "Kitelezi cha kiwango cha uchezaji wa video", - "description": "Huongeza kitelezi kwenye menyu ya muktadha ya Opera ili kubadilisha kiwango cha uchezaji wa video\nKumbuka: Mabadiliko yanatumika tu kwa video zinazofuata" - }, - "disable_google_play_dialogs": { - "name": "Zima vidirisha vya Huduma za Google Play", - "description": "Huzuia vidirisha vya upatikanaji wa Huduma za Google Play kuonyeshwa" - }, - "default_volume_controls": { - "name": "Vidhibiti chaguomsingi vya sauti", - "description": "Hulazimisha Snapchat kutumia vidhibiti vya sauti vya mfumo" - }, - "disable_telecom_framework": { - "name": "Zima Mfumo wa Telecom", - "description": "Huzuia Snapchat kutumia mfumo wa Telecom wa Android\nHii hukuruhusu kusikiliza muziki ukiwa kwenye simu" - }, - "hide_active_music": { - "name": "Ficha muziki unaotumika", - "description": "Huzuia Snapchat kujua kuwa unasikiliza muziki\nHii itakuruhusu kupiga snap kwa kutumia vitufe vya kudhibiti sauti unaposikiliza muziki" - }, - "disable_snap_splitting": { - "name": "Zima mgawanyiko wa snap", - "description": "Huzuia snap kugawanywa katika sehemu nyingi\nPicha unazotuma zitabadilika kuwa video" - } - } - }, - "rules": { - "name": "Kanuni", - "description": "Dhibiti vipengele vya kiotomatiki kwa watu binafsi" - }, - "camera": { - "name": "Kamera", - "description": "Rekebisha mipangilio sahihi kwa snap kamili", - "properties": { - "disable_cameras": { - "name": "Zima kamera", - "description": "Huzuia Snapchat kutumia kamera zilizochaguliwa" - }, - "black_photos": { - "name": "Picha nyeusi", - "description": "Hubadilisha picha zilizopigwa na mandharinyuma meusi\nVideo haziathiriwi" - }, - "immersive_camera_preview": { - "name": "Onyesho la awali la kamera linalozama", - "description": "Huzuia Snapchat kupunguza ukubwa wa onyesho la awali la kamera\nHii inaweza kusababisha kamera kuzima kwenye baadhi ya vifaa" - }, - "override_front_resolution": { - "name": "Batilisha azimio la mbele", - "description": "Hubatilisha azimio la kamera kwa kamera ya mbele" - }, - "override_back_resolution": { - "name": "Batilisha azimio la nyuma", - "description": "Hubatilisha azimio la kamera kwa kamera ya nyuma" - }, - "custom_resolution": { - "name": "Azimio maalum", - "description": "Huweka azimio maalum la kamera, upana x urefu (k.m. 1920x1080).\nAzimio maalum lazima liungwe mkono na kifaa chako" - }, - "front_custom_frame_rate": { - "name": "Kiwango maalum cha fremu ya mbele", - "description": "Hubatilisha kiwango cha fremu ya kamera ya mbele" - }, - "back_custom_frame_rate": { - "name": "Kiwango maalum cha fremu ya nyuma", - "description": "Hubatilisha kiwango cha fremu ya kamera ya nyuma" - }, - "force_camera_source_encoding": { - "name": "Lazimisha usimbaji wa chanzo cha kamera", - "description": "Hulazimisha usimbaji wa chanzo cha kamera" - }, - "startup_default_camera": { - "name": "Kamera chaguomsingi ya kuanza", - "description": "Huweka kamera chaguomsingi unapofungua Snapchat" - }, - "hevc_recording": { - "name": "Kurekodi kwa HEVC", - "description": "Hutumia kisimbaji cha HEVC (H.265) kurekodi video" - } - } - }, - "streaks_reminder": { - "name": "Kikumbusho cha Mfululizo", - "description": "Hukukumbusha mara kwa mara kuhusu mfululizo wako", - "properties": { - "interval": { - "name": "Muda", - "description": "Muda kati ya kila kikumbusho (saa)" - }, - "remaining_hours": { - "name": "Saa zilizobaki", - "description": "Kiasi cha muda kilichobaki kabla ya arifa kuonyeshwa (saa)" - }, - "group_notifications": { - "name": "Arifa za kikundi", - "description": "Hukusanya arifa za kikundi kuwa moja" - } - } - }, - "experimental": { - "name": "Majaribio", - "description": "Vipengele vya majaribio", - "properties": { - "native_hooks": { - "name": "Hook za asili", - "description": "Vipengele visivyo salama ambavyo huingia kwenye msimbo wa asili wa Snapchat", - "properties": { - "composer_hooks": { - "name": "Hook za mtunzi", - "description": "Huingiza msimbo kwenye mfumo wa UI wa jukwaa la mtunzi", - "properties": { - "show_first_created_username": { - "name": "Onyesha jina la mtumiaji la kwanza lililoundwa", - "description": "Huonyesha jina la mtumiaji la kwanza lililoundwa kando ya jina la mtumiaji la sasa kwenye ukurasa wa wasifu" - }, - "bypass_camera_roll_limit": { - "name": "Pita kikomo cha safu ya kamera", - "description": "Huongeza idadi ya juu ya midia unayoweza kutuma kutoka kwenye safu ya kamera" - }, - "custom_self_destruct_snap_delay": { - "name": "Kuchelewa maalum kwa snap ya kujifuta yenyewe", - "description": "Hutoa chaguo zaidi kwa kipima muda cha kujifuta chenyewe unapotuma snap" - }, - "composer_console": { - "name": "Dashibodi ya mtunzi", - "description": "Hukuruhusu kutekeleza msimbo wa JavaScript katika mtunzi (arm64 pekee)" - }, - "composer_logs": { - "name": "Kumbukumbu za mtunzi", - "description": "Huelekeza kumbukumbu za dashibodi ya mtunzi kwa PurrfectSnap" - } - } - }, - "disable_bitmoji": { - "name": "Zima Bitmoji", - "description": "Huzima Bitmoji za wasifu wa marafiki" - }, - "custom_emoji_font": { - "name": "Fonti maalum ya emoji", - "description": "Hukuruhusu kutumia fonti maalum ya emoji. Inafanya kazi tu na fonti za .ttf" - }, - "custom_shared_library": { - "name": "Maktaba maalum iliyoshirikiwa", - "description": "Hupakia maktaba maalum iliyoshirikiwa kwenye Snapchat. Kipengele hiki ni kwa madhumuni ya majaribio pekee" - } - } - }, - "spoof": { - "name": "Danganya", - "description": "Danganya taarifa mbalimbali kukuhusu", - "properties": { - "play_store_installer_package_name": { - "name": "Jina la kifurushi cha kisakinishi cha Duka la Google Play", - "description": "Hubatilisha jina la kifurushi cha kisakinishi kuwa com.android.vending" - }, - "remove_vpn_transport_flag": { - "name": "Ondoa alama ya usafirishaji ya VPN", - "description": "Huzuia Snapchat kugundua VPN" - }, - "remove_mock_location_flag": { - "name": "Ondoa alama ya eneo la kudanganya", - "description": "Huzuia Snapchat kugundua eneo la kudanganya" - } - } - }, - "convert_message_locally": { - "name": "Geuza ujumbe ndani ya nchi", - "description": "Hugeuza snap kuwa midia ya gumzo ndani ya nchi. Hii inaonekana kwenye menyu ya muktadha wa gumzo" - }, - "media_file_picker": { - "name": "Kichagua faili cha midia", - "description": "Hukuruhusu kuchagua faili yoyote ya video/sauti kutoka kwenye ghala" - }, - "story_logger": { - "name": "Kihifadhi hadithi", - "description": "Hutoa historia ya hadithi za marafiki" - }, - "call_recorder": { - "name": "Kirekodi simu", - "description": "Hurekodi simu za sauti kiotomatiki" - }, - "account_switcher": { - "name": "Kibadilisha akaunti", - "description": "Hukuruhusu kubadilisha kati ya akaunti bila kuingia tena\nBonyeza kwa muda mrefu kwenye aikoni ya utafutaji kando ya wasifu wako wa Bitmoji ili kufungua menyu\nKumbuka: Kipengele hiki ni cha majaribio na kitabadilika katika siku zijazo", - "properties": { - "auto_backup_current_account": { - "name": "Hifadhi nakala ya akaunti ya sasa kiotomatiki", - "description": "Huhifadhi nakala ya akaunti ya sasa kiotomatiki unapoingia au kubadilisha akaunti" - } - } - }, - "better_transcript": { - "name": "Nakala bora zaidi", - "description": "Huboresha unukuzi wa sauti", - "properties": { - "force_transcription": { - "name": "Lazimisha unukuzi wa dokezo la sauti", - "description": "Huruhusu madokezo yote ya sauti kunukuliwa" - }, - "preferred_transcription_lang": { - "name": "Lugha inayopendelewa ya unukuzi", - "description": "Lugha inayopendelewa kwa unukuzi wa dokezo la sauti (k.m. en, es, fr)" - }, - "notification_transcript": { - "name": "Unukuzi wa arifa", - "description": "Hunukuu madokezo ya sauti katika arifa\nKipengele hiki kinahitaji kipengele cha onyesho la awali la gumzo kuwashwa katika arifa bora zaidi" - } - } - }, - "voice_note_auto_play": { - "name": "Cheza dokezo la sauti kiotomatiki", - "description": "Hucheza kiotomatiki dokezo la sauti linalofuata baada ya la sasa kumalizika" - }, - "friend_notes": { - "name": "Madokezo ya rafiki", - "description": "Hukuruhusu kuongeza madokezo kwenye wasifu wa marafiki" - }, - "cof_experiments": { - "name": "Majaribio ya COF", - "description": "Huwasha vipengele vya Snapchat ambavyo havijatolewa/beta" - }, - "context_menu_fix": { - "name": "Rekebisha menyu ya muktadha", - "description": "Hujaribu kurekebisha menyu ya mlisho wa marafiki kwani wakati kifaa kiko nje ya mtandao huenda isionyeshwe ipasavyo" - }, - "app_lock": { - "name": "Kufunga programu", - "description": "Huzuia ufikiaji wa Snapchat bila nenosiri", - "properties": { - "lock_on_resume": { - "name": "Funga unapoendelea", - "description": "Hufunga programu inapofunguliwa tena" - } - } - }, - "infinite_story_boost": { - "name": "Kuongeza hadithi bila kikomo", - "description": "Hupita kikomo cha kuchelewa cha kuongeza hadithi" - }, - "meo_passcode_bypass": { - "name": "Pita nenosiri la Macho Yangu Pekee", - "description": "Hupita nenosiri la Macho Yangu Pekee\nHii itafanya kazi tu ikiwa nenosiri limeingizwa kwa usahihi hapo awali" - }, - "no_friend_score_delay": { - "name": "Hakuna kuchelewa kwa alama ya rafiki", - "description": "Huondoa ucheleweshaji unapotazama alama za marafiki" - }, - "best_friend_pinning": { - "name": "Kubandika rafiki bora", - "description": "Hukuruhusu kubandika rafiki kama rafiki yako bora wa kwanza. KUMBUKA: Ni wewe tu unayeweza kumuona rafiki yako bora" - }, - "e2ee": { - "name": "Usimbaji fiche wa mwisho-hadi-mwisho", - "description": "Husimba fiche ujumbe wako na AES kwa kutumia ufunguo wa siri ulioshirikiwa\nHakikisha umehifadhi ufunguo wako mahali salama!", - "properties": { - "encrypted_message_indicator": { - "name": "Kiashiria cha ujumbe uliosimbwa fiche", - "description": "Huongeza emoji ya 🔒 kando ya ujumbe uliosimbwa fiche" - }, - "force_message_encryption": { - "name": "Lazimisha usimbaji fiche wa ujumbe", - "description": "Huzuia kutuma ujumbe ambao haujasimbwa fiche kwa watu ambao hawana usimbaji fiche wa E2E uliowashwa tu wakati mazungumzo mengi yamechaguliwa" - } - } - }, - "add_friend_source_spoof": { - "name": "Danganya chanzo cha kuongeza rafiki", - "description": "Hubadilisha chanzo cha ombi la urafiki" - }, - "hidden_snapchat_plus_features": { - "name": "Vipengele vilivyofichwa vya Snapchat Plus", - "description": "Huwasha vipengele vya Snapchat Plus ambavyo havijatolewa/beta\nHuweza visifanye kazi kwenye matoleo ya zamani ya Snapchat" - }, - "custom_streaks_expiration_format": { - "name": "Umbizo maalum la kuisha kwa mfululizo", - "description": "Hubadilisha umbizo la kuisha kwa mfululizo\n\nVigezo vinavyopatikana:\n - %C: Hesabu za mfululizo\n - %E: Emoji ya saa ya mchanga\n - %D: Siku\n - %H: Saa\n - %M: Dakika\n - %S: Sekunde\n - %W: Muda uliosalia" - }, - "prevent_forced_logout": { - "name": "Zuia kuingia kwa kulazimishwa", - "description": "Huzuia Snapchat kukutoa unapoingia kwenye kifaa kingine" - }, - "snapscore_changes": { - "name": "Mabadiliko ya Snapscore", - "description": "Hufuatilia mabadiliko katika alama za marafiki\nTumia kipengele hiki kwenye matoleo mapya ya Snapchat pekee" - } - } - }, - "scripting": { - "name": "Uandishi wa hati", - "description": "Endesha hati maalum ili kupanua PurrfectSnap", - "properties": { - "developer_mode": { - "name": "Hali ya msanidi programu", - "description": "Huonyesha maelezo ya utatuzi juu ya UI ya Snapchat" - }, - "module_folder": { - "name": "Folda ya moduli", - "description": "Folda ambapo hati ziko" - }, - "auto_reload": { - "name": "Pakia upya kiotomatiki", - "description": "Hupakia upya hati zinapobadilika" - }, - "integrated_ui": { - "name": "UI iliyojumuishwa", - "description": "Huruhusu hati kuongeza vipengele maalum vya UI kwenye Snapchat" - }, - "disable_log_anonymization": { - "name": "Zima ufichaji wa kumbukumbu", - "description": "Huzima ufichaji wa kumbukumbu" - }, - "disable_optimization": { - "name": "Zima uboreshaji", - "description": "Huzima uboreshaji wa hati. Hii inaweza kusababisha matatizo ya utendaji." - } - } - }, - "friend_tracker": { - "name": "Kifuatilia Marafiki", - "description": "Rekodi shughuli za marafiki kwenye Snapchat", - "properties": { - "record_messaging_events": { - "name": "Rekodi matukio ya ujumbe", - "description": "Hurekodi matukio ya ujumbe kama vile kufungua snap, kusoma ujumbe, n.k." - }, - "allow_running_in_background": { - "name": "Ruhusu kufanya kazi chinichini", - "description": "Huruhusu kifuatiliaji kufanya kazi chinichini. Kumbuka: Hii itatumia betri yako kwa kiasi kikubwa" - }, - "auto_purge": { - "name": "Safisha kiotomatiki", - "description": "Hufuta kiotomatiki matukio yaliyohifadhiwa ambayo ni ya zamani kuliko muda uliowekwa" - } - } - } - }, - "options": { - "app_appearance": { - "always_light": "Mwangaza kila wakati", - "always_dark": "Giza kila wakati" - }, - "friend_feed_menu_buttons": { - "auto_download": "Upakuaji wa kiotomatiki", - "auto_save": "💬 Hifadhi ujumbe kiotomatiki", - "unsaveable_messages": "Ujumbe usioweza kuhifadhiwa", - "auto_open_snaps": "📷 Fungua snap kiotomatiki", - "stealth": "👻 Hali ya siri", - "mark_snaps_as_seen": "👀 Weka alama kwenye snap kama zimeonekana", - "mark_stories_as_seen_locally": "Weka alama kwenye hadithi kama zimeonekana ndani ya nchi", - "conversation_info": "Maelezo ya mazungumzo", - "e2e_encryption": "Tumia usimbaji fiche wa E2E" - }, - "path_format": { - "create_author_folder": "Unda folda kwa kila mwandishi", - "create_source_folder": "Unda folda kwa kila aina ya chanzo cha midia", - "append_hash": "Ongeza heshi ya kipekee kwenye jina la faili", - "append_source": "Ongeza chanzo cha midia kwenye jina la faili", - "append_username": "Ongeza jina la mtumiaji kwenye jina la faili", - "append_date_time": "Ongeza tarehe na saa kwenye jina la faili" - }, - "auto_download_sources": { - "friend_snaps": "Snap za marafiki", - "friend_stories": "Hadithi za marafiki", - "public_stories": "Hadithi za umma", - "spotlight": "Spotlight" - }, - "logging": { - "started": "Imeanza", - "success": "Imefanikiwa", - "progress": "Inaendelea", - "failure": "Imeshindwa" - }, - "notifications": { - "chat_screenshot": "Picha ya skrini ya gumzo", - "chat_screen_record": "Rekodi ya skrini ya gumzo", - "snap_replay": "Uchezaji tena wa snap", - "camera_roll_save": "Hifadhi ya safu ya kamera", - "chat": "Gumzo", - "chat_reply": "Jibu la gumzo", - "snap": "Snap", - "typing": "Kuandika", - "stories": "Hadithi", - "speaking": "Anazungumza", - "chat_reaction": "Mwitikio wa DM", - "group_chat_reaction": "Mwitikio wa gumzo la kikundi", - "initiate_audio": "Simu ya sauti inayoingia", - "abandon_audio": "Simu ya sauti iliyokosa", - "initiate_video": "Simu ya video inayoingia", - "abandon_video": "Simu ya video iliyokosa", - "map_live_location": "Eneo la moja kwa moja la ramani" - }, - "gallery_media_send_override": { - "always_ask": "Uliza kila wakati", - "ORIGINAL": "Midia ya asili", - "NOTE": "Dokezo la sauti", - "SNAP": "Snap", - "SAVEABLE_SNAP": "Snap inayoweza kuhifadhiwa" - }, - "strip_media_metadata": { - "hide_caption_text": "Ficha maandishi ya maelezo", - "hide_snap_filters": "Ficha vichujio vya snap", - "hide_extras": "Ficha ziada (k.m. kutaja)", - "remove_audio_note_duration": "Ondoa muda wa dokezo la sauti", - "remove_audio_note_transcript_capability": "Ondoa uwezo wa unukuzi wa dokezo la sauti" - }, - "hide_ui_components": { - "hide_profile_call_buttons": "Ficha vitufe vya simu vya wasifu", - "hide_chat_call_buttons": "Ficha vitufe vya simu vya gumzo", - "hide_live_location_share_button": "Ficha kitufe cha kushiriki eneo la moja kwa moja", - "hide_stickers_button": "Ficha kitufe cha vibandiko", - "hide_voice_record_button": "Ficha kitufe cha kurekodi sauti", - "hide_unread_chat_hint": "Ficha dokezo la gumzo ambalo halijasomwa", - "hide_post_to_story_buttons": "Ficha vitufe vya kuchapisha kwenye hadithi kabla ya kutuma snap", - "hide_billboard_prompt": "Ficha dokezo la bango kwenye mlisho wa marafiki", - "hide_snapchat_plus_gift_reminders": "Ficha vikumbusho vya zawadi vya Snapchat Plus kwenye gumzo", - "hide_map_reactions": "Ficha miitikio ya ramani" - }, - "hide_story_suggestions": { - "hide_suggested_friend_stories": "Ficha hadithi za marafiki zilizopendekezwa", - "hide_my_stories": "Ficha hadithi zangu" - }, - "home_tab": { - "map": "Ramani", - "chat": "Gumzo", - "camera": "Kamera", - "discover": "Gundua", - "spotlight": "Spotlight" - }, - "add_friend_source_spoof": { - "added_by_username": "Kwa jina la mtumiaji", - "added_by_mention": "Kwa kutaja", - "added_by_group_chat": "Kwa gumzo la kikundi", - "added_by_qr_code": "Kwa msimbo wa QR", - "added_by_community": "Kwa jumuiya", - "added_by_quick_add": "Kwa kuongeza haraka (hatari kubwa ya kupigwa marufuku)" - }, - "bypass_video_length_restriction": { - "single": "Midia moja", - "split": "Gawanya midia" - }, - "old_bitmoji_selfie": { - "2d": "Bitmoji ya 2D", - "3d": "Bitmoji ya 3D" - }, - "disable_confirmation_dialogs": { - "erase_message": "Futa ujumbe", - "remove_friend": "Ondoa rafiki", - "block_friend": "Zuia rafiki", - "ignore_friend": "Puuza rafiki", - "hide_friend": "Ficha rafiki", - "hide_conversation": "Ficha mazungumzo", - "clear_conversation": "Futa mazungumzo kwenye Mlisho wa Marafiki" - }, - "auto_reload": { - "snapchat_only": "Snapchat pekee", - "all": "Zote (Snapchat + PurrfectSnap)" - }, - "edit_text_override": { - "multi_line_chat_input": "Ingizo la gumzo la mistari mingi", - "bypass_text_input_limit": "Pita kikomo cha ingizo la maandishi" - }, - "auto_purge": { - "never": "Kamwe", - "1_hour": "Saa 1", - "3_hours": "Saa 3", - "6_hours": "Saa 6", - "12_hours": "Saa 12", - "1_day": "Siku 1", - "3_days": "Siku 3", - "1_week": "Wiki 1", - "2_weeks": "Wiki 2", - "1_month": "Mwezi 1", - "3_months": "Miezi 3", - "6_months": "Miezi 6" - }, - "disable_story_sections": { - "friends": "Marafiki", - "suggested_stories": "Hadithi zilizopendekezwa", - "following": "Wanaofuatiliwa", - "discover": "Gundua" - }, - "disable_cameras": { - "front": "Kamera ya mbele", - "back": "Kamera ya nyuma" - }, - "disable_permission_requests": { - "notifications": "Arifa", - "read_media_images": "Soma picha za midia", - "read_media_video": "Soma video za midia", - "camera": "Kamera", - "microphone": "Maikrofoni", - "location": "Eneo", - "read_contacts": "Soma anwani", - "nearby_devices": "Vifaa vya karibu", - "phone_calls": "Simu" - }, - "message_indicators": { - "encryption_indicator": "Huongeza aikoni kando ya ujumbe ambao umetumwa kwako pekee", - "platform_indicator": "Huongeza aikoni ya jukwaa ambalo midia ilitumwa (k.m. Android, iOS, Wavuti)", - "location_indicator": "Huongeza aikoni ya 📍 kwenye snap zinazotumwa na eneo likiwashwa", - "ovf_editor_indicator": "Huonyesha ikiwa snap imetumwa kwa kutumia Kihariri cha OVF", - "director_mode_indicator": "Huongeza aikoni ya 🎬 kwenye snap zinazotumwa kwa kutumia hali ya mkurugenzi, ambayo inaweza kutumika kutuma picha za ghala kama snap" - }, - "auto_mark_as_read": { - "conversation_read": "Weka mazungumzo kama yamesomwa unapotuma ujumbe", - "snap_reply": "Weka alama kwenye snap kama zimesomwa unapozijibu", - "save_snap_in_chat": "Weka alama kwenye snap kama zimesomwa unapozihifadhi kwenye gumzo ukiwa katika hali ya siri" - }, - "friend_mutation_notifier": { - "remove_friend": "Arifu mtu anapokuondoa kama rafiki", - "birthday_changes": "Arifu mtu anapobadilisha siku yake ya kuzaliwa", - "bitmoji_selfie_changes": "Arifu mtu anapobadilisha selfie yake ya Bitmoji", - "bitmoji_avatar_changes": "Arifu mtu anapobadilisha avatari yake ya Bitmoji", - "bitmoji_background_changes": "Arifu mtu anapobadilisha mandharinyuma yake ya Bitmoji", - "bitmoji_scene_changes": "Arifu mtu anapobadilisha mandhari yake ya Bitmoji" - }, - "snapchat_plus": { - "not_subscribed": "Hujasajiliwa", - "basic": "Msingi", - "ad_free": "Bila matangazo" - }, - "double_tap_chat_action": { - "like_message": "Penda ujumbe", - "copy_text": "Nakili maandishi kwenye ubao wa kunakili", - "delete_message": "Futa ujumbe", - "mark_as_read": "Weka alama kama umesoma", - "custom_emoji_reaction": "Mwitikio maalum wa emoji" - }, - "startup_default_camera": { - "front": "Kamera ya mbele", - "back": "Kamera ya nyuma" - } - } - }, - "friend_menu_option": { - "mark_snaps_as_seen": "Weka alama kwenye snap kama zimeonekana", - "mark_stories_as_seen_locally": "Weka alama kwenye hadithi kama zimeonekana ndani ya nchi", - "preview": "Onyesho la awali", - "stealth_mode": "Hali ya siri", - "auto_download_blacklist": "Orodha nyeusi ya upakuaji wa kiotomatiki", - "anti_auto_save": "Zuia hifadhi ya kiotomatiki" - }, - "content_type": { - "CHAT": "Gumzo", - "SNAP": "Snap", - "EXTERNAL_MEDIA": "Midia ya nje", - "NOTE": "Dokezo la sauti", - "STICKER": "Kibandiko", - "SHARE": "Shiriki", - "STATUS": "Hali", - "LOCATION": "Eneo", - "STATUS_SAVE_TO_CAMERA_ROLL": "Imehifadhiwa kwenye safu ya kamera", - "STATUS_CONVERSATION_CAPTURE_SCREENSHOT": "Picha ya skrini", - "STATUS_CONVERSATION_CAPTURE_RECORD": "Rekodi ya skrini", - "STATUS_CALL_MISSED_VIDEO": "Simu ya video iliyokosa", - "STATUS_CALL_MISSED_AUDIO": "Simu ya sauti iliyokosa", - "LIVE_LOCATION_SHARE": "Shiriki eneo la moja kwa moja", - "CREATIVE_TOOL_ITEM": "Kipengee cha zana ya ubunifu", - "FAMILY_CENTER_INVITE": "Mwaliko wa Kituo cha Familia", - "FAMILY_CENTER_ACCEPT": "Kukubali kwa Kituo cha Familia", - "FAMILY_CENTER_LEAVE": "Kuondoka kwa Kituo cha Familia", - "STATUS_PLUS_GIFT": "Zawadi ya Hali Plus", - "TINY_SNAP": "Snap ndogo", - "STATUS_COUNTDOWN": "Kipima muda", - "MAP_REACTION": "Mwitikio wa ramani" - }, - "media_download_source": { - "none": "Hakuna", - "pending": "Inasubiri", - "chat_media": "Midia ya gumzo", - "story": "Hadithi", - "public_story": "Hadithi ya umma", - "spotlight": "Spotlight", - "profile_picture": "Picha ya wasifu", - "story_logger": "Kihifadhi hadithi", - "message_logger": "Kihifadhi ujumbe", - "merged": "Imeunganishwa", - "voice_call": "Simu ya sauti" - }, - "chat_action_menu": { - "preview_button": "Onyesho la awali", - "download_button": "Pakua", - "delete_logged_message_button": "Futa ujumbe uliohifadhiwa", - "show_chat_edit_history": "Onyesha historia ya uhariri wa gumzo", - "convert_message": "Geuza ujumbe" - }, - "opera_context_menu": { - "download": "Pakua midia", - "sent_at": "Imetumwa mnamo {date}", - "created_at": "Imeundwa mnamo {date}", - "expires_at": "Inaisha mnamo {date}", - "media_size": "Ukubwa wa midia: {size}", - "media_duration": "Muda wa midia: {duration} ms", - "show_debug_info": "Onyesha maelezo ya utatuzi" - }, - "modal_option": { - "profile_info": "Maelezo ya wasifu", - "close": "Funga" - }, - "gallery_media_send_override": { - "multiple_media_toast": "Unaweza kutuma midia moja tu kwa wakati mmoja" - }, - "mark_as_seen": { - "no_unseen_snaps_toast": "Hakuna snap ambazo hazijaonekana zilizopatikana!", - "seen_toast": "Imewekwa alama kama imeonekana!", - "unseen_toast": "Imewekwa alama kama haijaonekana!", - "already_seen_toast": "Tayari imewekwa alama kama imeonekana!", - "already_unseen_toast": "Tayari imewekwa alama kama haijaonekana!" - }, - "conversation_preview": { - "streak_expiration": "Inaisha baada ya siku {day} saa {hour} dakika {minute}", - "total_messages": "Jumla ya ujumbe uliotumwa/kupokelewa: {count}", - "title": "Onyesho la awali", - "unknown_user": "Mtumiaji asiyejulikana", - "no_messages": "Hakuna ujumbe uliopatikana!" - }, - "profile_info": { - "title": "Maelezo ya wasifu", - "first_created_username": "Jina la mtumiaji la kwanza lililoundwa", - "mutable_username": "Jina la mtumiaji linaloweza kubadilishwa", - "display_name": "Jina la kuonyesha", - "added_date": "Tarehe iliyoongezwa", - "birthday": "Siku ya kuzaliwa: {month} {day}", - "hidden_birthday": "Siku ya kuzaliwa: imefichwa", - "friendship": "Urafiki", - "add_source": "Chanzo cha kuongeza", - "snapchat_plus": "Snapchat Plus", - "snapchat_plus_state": { - "subscribed": "Amejisajili", - "not_subscribed": "Hajasajiliwa" - } - }, - "friendship_link_type": { - "mutual": "Pande zote", - "outgoing": "Anayetoka", - "blocked": "Amezuiwa", - "deleted": "Amefutwa", - "following": "Anayefuata", - "suggested": "Aliyependekezwa", - "incoming": "Anayeingia", - "incoming_follower": "Mfuasi anayeingia" - }, - "bulk_messaging_action": { - "choose_action_title": "Chagua kitendo", - "progress_status": "Inachakata {index} kati ya {total}", - "selection_dialog_continue_button": "Endelea", - "confirmation_dialog": { - "title": "Una uhakika?", - "message": "Hii itaathiri marafiki wote waliochaguliwa. Kitendo hiki hakiwezi kutenduliwa." - }, - "actions": { - "remove_friends": "Ondoa marafiki", - "clear_conversations": "Futa mazungumzo" - } - }, - "chat_export": { - "exporter_dialog": { - "select_conversations_title": "Chagua mazungumzo", - "text_field_selection": "{amount} imechaguliwa", - "text_field_selection_all": "Zote", - "export_file_format_title": "Umbizo la faili ya kuhamisha", - "message_type_filter_title": "Chuja ujumbe kwa aina", - "amount_of_messages_title": "Idadi ya ujumbe (acha tupu kwa zote)", - "download_medias_title": "Pakua midia" - }, - "dialog_negative_button": "Ghairi", - "dialog_positive_button": "Hamisha", - "exported_to": "Imehamishwa kwa {path}", - "exporting_chats": "Inahamisha mazungumzo...", - "processing_chats": "Inachakata mazungumzo {amount}...", - "export_fail": "Imeshindwa kuhamisha mazungumzo {conversation}", - "writing_output": "Inaandika matokeo...", - "finished": "Imekamilika! Sasa unaweza kufunga kidirisha hiki.", - "no_messages_found": "Hakuna ujumbe uliopatikana!", - "exporting_message": "Inahamisha {message}..." - }, - "button": { - "ok": "Sawa", - "positive": "Ndiyo", - "negative": "Hapana", - "cancel": "Ghairi", - "open": "Fungua", - "download": "Pakua", - "send": "Tuma", - "restore_original": "Rejesha asili", - "convert_external_media": "Geuza midia ya nje", - "save": "Hifadhi" - }, - "tracker_events": { - "conversation_enter": "Ingia kwenye mazungumzo", - "conversation_exit": "Toka kwenye mazungumzo", - "started_typing": "Ameanza kuandika", - "stopped_typing": "Ameacha kuandika", - "started_speaking": "Ameanza kuzungumza", - "stopped_speaking": "Ameacha kuzungumza", - "started_peeking": "Ameanza kuchungulia", - "stopped_peeking": "Ameacha kuchungulia", - "message_read": "Ujumbe umesomwa", - "message_deleted": "Ujumbe umefutwa", - "message_saved": "Ujumbe umehifadhiwa", - "message_unsaved": "Ujumbe haujahifadhiwa", - "message_edited": "Ujumbe umehaririwa", - "message_reaction_add": "Mwitikio wa ujumbe umeongezwa", - "message_reaction_remove": "Mwitikio wa ujumbe umeondolewa", - "snap_opened": "Snap imefunguliwa", - "snap_replayed": "Snap imechezwa tena", - "snap_replayed_twice": "Snap imechezwa tena mara mbili", - "snap_screenshot": "Picha ya skrini ya snap", - "snap_screen_record": "Rekodi ya skrini ya snap" - }, - "tracker_actions": { - "log": "Kumbukumbu", - "in_app_notification": "Arifa ya ndani ya programu", - "push_notification": "Arifa ya kushinikiza", - "custom": "Maalum" - }, - "better_notifications": { - "button": { - "reply": "Jibu", - "download": "Pakua", - "mark_as_read": "Weka alama kama imesomwa" - } - }, - "profile_picture_downloader": { - "button": "Pakua picha ya wasifu", - "title": "Kipakuzi cha picha ya wasifu", - "avatar_option": "Avatari", - "background_option": "Mandharinyuma" - }, - "call_start_confirmation": { - "dialog_title": "Anza simu", - "dialog_message": "Una uhakika unataka kuanza simu?" - }, - "half_swipe_notifier": { - "notification_channel_name": "Nusu-telezesha", - "notification_content_dm": "{friend} amenusu-telezesha kwenye gumzo lako kwa sekunde {duration}", - "notification_content_group": "{friend} amenusu-telezesha kwenye {group} kwa sekunde {duration}" - }, - "download_processor": { - "attachment_type": { - "snap": "Snap", - "sticker": "Kibandiko", - "gif": "GIF", - "external_media": "Midia ya nje", - "note": "Dokezo", - "original_story": "Hadithi ya asili" - }, - "select_attachments_title": "Chagua viambatisho", - "download_started_toast": "Upakuaji umeanza", - "unsupported_content_type_toast": "Aina ya maudhui haitumiki!", - "failed_no_longer_available_toast": "Midia haipatikani tena", - "no_attachments_toast": "Hakuna viambatisho vilivyopatikana!", - "already_queued_toast": "Midia tayari iko kwenye foleni!", - "already_downloaded_toast": "Midia tayari imepakuliwa!", - "content_saved_toast": "Imehifadhiwa!", - "download_toast": "Inapakua {attachment}...", - "processing_toast": "Inachakata {attachment}...", - "failed_generic_toast": "Imeshindwa kupakua", - "failed_to_create_preview_toast": "Imeshindwa kuunda onyesho la awali", - "failed_processing_toast": "Imeshindwa kuchakata: {error}", - "failed_gallery_toast": "Imeshindwa kuhifadhi kwenye ghala: {error}", - "dash_no_chapter": "Hakuna sura iliyopatikana", - "dash_dialog": { - "title": "Pakua Midia ya DASH", - "download_all": "Pakua Zote", - "segment_text": "Sehemu {from} - {to}" - } - }, - "streaks_reminder": { - "notification_title": "Mfululizo", - "notification_text": "Utapoteza mfululizo wako na {friend} baada ya saa {hoursLeft}" - }, - "biometric_auth": { - "unlock_button": "Fungua", - "title": "Fungua Snapchat", - "subtitle": "Tafadhali thibitisha ili kufungua Snapchat" - }, - "end_to_end_encryption": { - "toolbox": { - "no_shared_key": "Bado huna ufunguo wa siri ulioshirikiwa na rafiki huyu. Bofya hapa chini ili kuanzisha mpya.", - "shared_key_fingerprint": "Alama ya vidole ni:\n\n{fingerprint}\n\nHakikisha unakagua ikiwa inalingana na alama ya vidole ya rafiki yako!", - "initiate_exchange_button": "Anzisha ubadilishanaji wa ufunguo" - }, - "confirmation_dialogs": { - "title": "Usimbaji fiche wa mwisho-hadi-mwisho", - "confirmation_1": "Onyo: Hii itaondoa ufunguo wako uliopo. Utapoteza ufikiaji wa ujumbe wote uliosimbwa fiche kutoka kwa rafiki huyu. Una uhakika unataka kuendelea?", - "confirmation_2": "Una uhakika kweli unataka kuendelea? Hii ni nafasi yako ya mwisho kurudi nyuma." - }, - "unencrypted_conversation_send_failure_toast": "Huwezi kutuma maudhui yaliyosimbwa fiche kwa mazungumzo yote yaliyosimbwa fiche na yasiyosimbwa fiche!", - "native_hooks_send_failure_toast": "Imeshindwa kutuma! Tafadhali washa hook za asili katika mipangilio.", - "no_participants_to_encrypt_toast": "Huna marafiki wowote katika mazungumzo haya wa kusimba fiche ujumbe nao!", - "encryption_failed_toast": "Imeshindwa kusimba fiche ujumbe! Angalia Logcat kwa maelezo zaidi.", - "accept_public_key_success_toast": "Ufunguo wa umma umekubaliwa kwa mafanikio!", - "accept_secret_key_success_toast": "Imekamilika! Sasa unaweza kutuma na kupokea ujumbe uliosimbwa fiche na rafiki huyu.", - "accept_public_key_failure_toast": "Imeshindwa kukubali ufunguo wa umma", - "accept_secret_key_failure_toast": "Imeshindwa kukubali ufunguo wa siri", - "accept_secret_button": "Kubali siri", - "accept_public_key_button": "Kubali ufunguo wa umma", - "outgoing_pk_message": "Ombi la kubadilishana ufunguo", - "outgoing_secret_message": "Jibu la kubadilishana ufunguo", - "incoming_pk_message": "Umepokea ombi la ufunguo wa umma. Bofya hapa chini ili kulikubali.", - "incoming_secret_message": "Rafiki yako amekubali ufunguo wako wa umma. Bofya hapa chini ili kukubali siri." - }, - "auto_open_snaps": { - "title": "Fungua snap kiotomatiki", - "notification_content": "Snap {count} zimefunguliwa" - }, - "friend_mutation_observer": { - "notification_channel_name": "Mfuatiliaji wa mabadiliko ya rafiki", - "friend_removed": "{username} amekuondoa kama rafiki", - "birthday_removed": "{username} ameondoa siku yake ya kuzaliwa ({birthday})", - "birthday_added": "{username} ameongeza siku yake ya kuzaliwa ({birthday})", - "birthday_changed": "{username} amebadilisha siku yake ya kuzaliwa kutoka {oldBirthday} hadi {newBirthday}", - "bitmoji_selfie_changed": "{username} amebadilisha selfie yake ya Bitmoji", - "bitmoji_avatar_changed": "{username} amebadilisha avatari yake ya Bitmoji", - "bitmoji_background_changed": "{username} amebadilisha mandharinyuma yake ya Bitmoji", - "bitmoji_scene_changed": "{username} amebadilisha mandhari yake ya Bitmoji" - }, - "material3_strings": { - "date_range_picker_start_headline": "Kutoka", - "date_range_picker_end_headline": "Hadi", - "date_range_picker_title": "Chagua kipindi", - "date_picker_switch_to_calendar_mode": "Kalenda", - "date_picker_switch_to_input_mode": "Ingizo", - "date_range_picker_scroll_to_previous_month": "Mwezi uliopita", - "date_range_picker_scroll_to_next_month": "Mwezi ujao", - "date_picker_today_description": "Leo", - "date_range_picker_day_in_range": "Imechaguliwa", - "date_input_invalid_for_pattern": "Tarehe si sahihi", - "date_input_invalid_year_range": "Mwaka si sahihi", - "date_input_invalid_not_allowed": "Tarehe si sahihi", - "date_range_input_invalid_range_input": "Kipindi si sahihi" - }, - "send_override_dialog": { - "title": "Tuma Midia kama {type}", - "duration": "Muda: {duration}", - "saveable_snap_hint": "Fanya snap iweze kuhifadhiwa kwenye gumzo", - "unlimited_duration": "Bila kikomo" - }, - "invalid_input_toast": "Ingizo si sahihi! Hakikisha umeingiza thamani sahihi." -} \ No newline at end of file diff --git a/common/src/main/assets/lang/swg.json b/common/src/main/assets/lang/swg.json new file mode 100644 index 00000000..0967ef42 --- /dev/null +++ b/common/src/main/assets/lang/swg.json @@ -0,0 +1 @@ +{} diff --git a/common/src/main/assets/lang/ta_IN.json b/common/src/main/assets/lang/ta_IN.json new file mode 100644 index 00000000..2b4ec00d --- /dev/null +++ b/common/src/main/assets/lang/ta_IN.json @@ -0,0 +1,1705 @@ +{ + "features": { + "properties": { + "messaging": { + "properties": { + "friend_mutation_notifier": { + "description": "நண்பரின் சுயவிவரத்தில் ஏதாவது மாறும்போது உங்களுக்கு அறிவிக்கும்", + "name": "நண்பர் பிறழ்வு அறிவிப்பு" + }, + "better_notifications": { + "name": "சிறந்த அறிவிப்புகள்", + "description": "பெறப்பட்ட அறிவிப்புகளில் கூடுதல் தகவல்களைச் சேர்க்கிறது", + "properties": { + "group_notifications": { + "name": "குழு அறிவிப்புகள்", + "description": "குழு அறிவிப்புகள் ஒற்றை" + }, + "chat_preview": { + "name": "அரட்டை முன்னோட்டம்", + "description": "அறிவிப்பில் பெறப்பட்ட செய்திகளின் முன்னோட்டத்தைக் காட்டுகிறது" + }, + "media_preview": { + "name": "மீடியா முன்னோட்டம்", + "description": "அறிவிப்பில் தேர்ந்தெடுக்கப்பட்ட ஊடக வகைகளின் முன்னோட்டத்தைக் காட்டுகிறது" + }, + "media_caption": { + "name": "ஊடக தலைப்பு", + "description": "அறிவிப்பில் ஊடகங்களின் இணைக்கப்பட்ட தலைப்பைக் காட்டுகிறது" + }, + "reply_button": { + "name": "பதில் பொத்தான்", + "description": "அறிவிப்புக்கு பதில் பொத்தானைச் சேர்க்கிறது" + }, + "smart_replies": { + "name": "அறிவுள்ள பதில்கள்", + "description": "அறிவிப்புகளுக்கு பரிந்துரைக்கப்பட்ட பதில்களைச் சேர்க்கிறது (Android 10+). பதில் பொத்தானுடன் இணைந்து பயன்படுத்தவும்" + }, + "download_button": { + "name": "பதிவிறக்க பொத்தான்", + "description": "அறிவிப்பிலிருந்து மீடியாவைப் பதிவிறக்க உங்களை அனுமதிக்கிறது" + }, + "mark_as_read_button": { + "description": "அறிவிப்பிலிருந்து படிக்க ஒரு செய்தியைக் குறிக்க உங்களை அனுமதிக்கிறது", + "name": "வாசிப்பு பொத்தானாக குறிக்கவும்" + }, + "mark_as_read_and_save_in_chat": { + "name": "அரட்டையில் படிக்கவும் சேமிக்கவும்", + "description": "அறிவிப்புக்கு அரட்டை பொத்தானைப் படித்து சேமிக்க ஒரு அடையாளத்தை சேர்க்கிறது" + }, + "friend_add_source": { + "name": "நண்பர் மூலத்தைச் சேர்க்கவும்", + "description": "அறிவிப்பில் நண்பர் கோரிக்கையின் மூலத்தைக் காட்டுகிறது" + }, + "stacked_media_messages": { + "name": "அடுக்கப்பட்ட மீடியா செய்திகள்", + "description": "பல ஊடக செய்திகளை முன்னோட்டமிட முடியாதபோது ஒரு உரை அறிவிப்பாக ஒருங்கிணைக்கிறது. அரட்டை முன்னோட்டத்துடன் இணைந்து பயன்படுத்தவும்" + } + } + }, + "notification_blacklist": { + "name": "அறிவிப்பு தடுப்புப்பட்டியல்", + "description": "தடுக்கப்பட வேண்டிய அறிவிப்புகளைத் தேர்ந்தெடுக்கவும்" + }, + "message_logger": { + "description": "செய்திகளை நீக்குவதைத் தடுக்கிறது", + "properties": { + "keep_my_own_messages": { + "name": "எனது சொந்த செய்திகளை வைத்திருங்கள்", + "description": "உங்கள் சொந்த செய்திகளை நீக்குவதைத் தடுக்கிறது" + }, + "auto_purge": { + "name": "ஆட்டோ தூய்மை", + "description": "குறிப்பிட்ட நேரத்தை விட பழைய தற்காலிக சேமிப்பு செய்திகளை தானாக நீக்குகிறது" + }, + "message_filter": { + "name": "செய்தி வடிகட்டி", + "description": "எந்த செய்திகள் உள்நுழைய வேண்டும் என்பதைத் தேர்ந்தெடுக்கவும் (எல்லா செய்திகளுக்கும் காலியாக)" + }, + "deleted_message_color": { + "name": "நீக்கப்பட்ட செய்தி நிறம்", + "description": "நீக்கப்பட்ட செய்திகளின் நிறத்தை அமைக்கிறது" + } + }, + "name": "செய்தி லாகர்" + }, + "auto_save_messages_in_conversations": { + "name": "தானாக சேமி செய்திகள்", + "description": "உரையாடல்களில் ஒவ்வொரு செய்தியையும் தானாகவே சேமிக்கிறது" + }, + "gallery_media_send_override": { + "name": "கேலரி மீடியா மேலெழுதலை அனுப்புகிறது", + "description": "கேலரியில் இருந்து அனுப்பும்போது ஊடக மூலத்தை ஏமாற்றுகிறது" + }, + "strip_media_metadata": { + "name": "உரி மீடியா மேனிலை தரவு", + "description": "செய்தியாக அனுப்புவதற்கு முன்பு மீடியாவின் மெட்டாடேட்டாவை நீக்குகிறது" + }, + "bypass_message_retention_policy": { + "name": "செய்தி தக்கவைப்பு கொள்கையைத் தவிர்த்து விடுங்கள்", + "description": "செய்திகளைப் பார்த்த பிறகு அவற்றை நீக்குவதைத் தடுக்கிறது" + }, + "bypass_message_action_restrictions": { + "name": "செய்தி நடவடிக்கை கட்டுப்பாடுகள்", + "description": "ஒரு புகைப்படத்தைத் திறக்காமல் அல்லது விரும்பத்தகாத செய்தியைச் சேமிக்க உங்களை அனுமதிக்கிறது" + }, + "remove_groups_locked_status": { + "name": "குழுக்கள் பூட்டப்பட்ட நிலையை அகற்று", + "description": "உதைக்கப்பட்ட பிறகு குழு தகவல்களைக் காண உங்களை அனுமதிக்கிறது" + }, + "double_tap_chat_action": { + "name": "டபுள் டேப் அரட்டை நடவடிக்கை", + "description": "அரட்டையில் ஒரு செய்தியை இருமுறை தட்டும்போது தனிப்பயன் செயலைச் செய்கிறது" + }, + "double_tap_chat_action_custom_emoji": { + "name": "இரட்டை தட்டு அரட்டை நடவடிக்கை தனிப்பயன் ஈமோசி எதிர்வினை", + "description": "இரட்டை தட்டு அரட்டை நடவடிக்கைக்கு தனிப்பயன் ஈமோசி எதிர்வினையை அமைக்கிறது" + }, + "bypass_screenshot_detection": { + "name": "பைபாச் திரைக்காட்சி கண்டறிதல்", + "description": "நீங்கள் திரை சாட்டை எடுக்கும்போது ச்னாப்சாட் கண்டறிவதைத் தடுக்கிறது" + }, + "anonymous_story_viewing": { + "name": "அநாமதேய கதை பார்வை", + "description": "நீங்கள் அவர்களின் கதையை நீங்கள் பார்த்தீர்கள் என்பதை அறிந்து கொள்வதைத் தடுக்கிறது" + }, + "hide_peek_a_peek": { + "description": "நீங்கள் அரட்டையில் பாதி ச்வைப் செய்யும்போது அறிவிப்பு அனுப்பப்படுவதைத் தடுக்கிறது", + "name": "பீக்-எ-பீக்கை மறைக்கவும்" + }, + "hide_bitmoji_presence": { + "name": "பிட்மோசி இருப்பை மறைக்கவும்", + "description": "அரட்டையில் இருக்கும்போது உங்கள் பிட்மோசியைத் தடுக்கிறது" + }, + "hide_typing_notifications": { + "name": "தட்டச்சு அறிவிப்புகளை மறைக்கவும்", + "description": "நீங்கள் ஒரு செய்தியைத் தட்டச்சு செய்கிறீர்கள் என்பதை அறிந்து கொள்வதைத் தடுக்கிறது" + }, + "unlimited_snap_view_time": { + "name": "வரம்பற்ற ச்னாப் பார்வை நேரம்", + "description": "ச்னாப்களைப் பார்ப்பதற்கான நேர வரம்பை நீக்குகிறது" + }, + "auto_mark_as_read": { + "name": "ஆட்டோ குறி படிக்க", + "description": "திருட்டுத்தனமான பயன்முறை இயக்கப்பட்டிருந்தாலும் கூட படித்தபடி செய்திகளை/புகைப்படங்களை தானாகவே குறிக்கிறது" + }, + "mark_snap_as_seen_button": { + "name": "பார்த்த பொத்தானை குறிக்கவும்", + "description": "ஒரு ச்னாப்பைப் பார்க்கும்போது அதைப் பார்க்கும்போது ஒரு பொத்தானைச் சேர்க்கிறது.\n திருட்டுத்தனமான பயன்முறை இயக்கப்பட்டிருந்தாலும் இது செயல்படும்" + }, + "skip_when_marking_as_seen": { + "name": "பார்த்தபடி குறிக்கும் போது தவிர்க்கவும்", + "description": "பார்த்தபடி ஒரு ச்னாப்பைக் குறிக்கும் போது தானாகவே அடுத்த புகைப்படத்திற்குச் செல்லுங்கள்.\n பார்த்த பொத்தானைப் போல மார்க் ச்னாப்புடன் இணைந்து பயன்படுத்தவும்" + }, + "loop_media_playback": { + "name": "லூப் மீடியா பிளேபேக்", + "description": "ச்னாப்ச் / கதைகளைப் பார்க்கும்போது மீடியா பிளேபேக்கை சுழற்றுங்கள்" + }, + "disable_replay_in_ff": { + "name": "FF இல் மறுபதிப்பு முடக்கு", + "description": "நண்பர் ஊட்டத்திலிருந்து நீண்ட செய்தித் தாள் மூலம் மீண்டும் இயக்கும் திறனை முடக்குகிறது" + }, + "half_swipe_notifier": { + "name": "அரை ச்வைப் அறிவிப்பாளர்", + "description": "யாரோ ஒரு உரையாடலில் பாதி ச்வைப் செய்யும்போது உங்களுக்கு அறிவிக்கிறது", + "properties": { + "min_duration": { + "name": "குறைந்தபட்ச காலம்", + "description": "அரை ச்வைப்பின் குறைந்தபட்ச காலம் (நொடிகளில்)" + }, + "max_duration": { + "name": "அதிகபட்ச காலம்", + "description": "அரை ச்வைப்பின் அதிகபட்ச காலம் (நொடிகளில்)" + } + } + }, + "call_start_confirmation": { + "name": "தொடக்க உறுதிப்படுத்தல் என்று அழைக்கவும்", + "description": "அழைப்பைத் தொடங்கும்போது உறுதிப்படுத்தல் உரையாடலைக் காட்டுகிறது" + }, + "unlimited_conversation_pinning": { + "name": "வரம்பற்ற உரையாடல் பின்னிங்", + "description": "உள்நாட்டில் வரம்பற்ற உரையாடல்களை பொருத்த உங்களை அனுமதிக்கிறது" + }, + "prevent_message_sending": { + "name": "செய்தி அனுப்புவதைத் தடுக்கவும்", + "description": "சில வகையான செய்திகளை அனுப்புவதைத் தடுக்கிறது" + }, + "prevent_story_rewatch_indicator": { + "name": "கதை மறுபரிசீலனை காட்டி தடுக்கவும்", + "description": "நீங்கள் அவர்களின் கதையை மறுபரிசீலனை செய்துள்ளீர்கள் என்பதை அறிந்து கொள்வதைத் தடுக்கிறது" + } + }, + "name": "செய்தியிடல்", + "description": "நண்பர்களுடன் நீங்கள் எவ்வாறு தொடர்பு கொள்கிறீர்கள் என்பதை மாற்றவும்" + }, + "global": { + "name": "உலகளாவிய", + "description": "உலகளாவிய ச்னாப்சாட் அமைப்புகளை மாற்றவும்", + "properties": { + "better_location": { + "name": "சிறந்த இடம்", + "description": "ச்னாப்சாட் இருப்பிடத்தை மேம்படுத்துகிறது", + "properties": { + "spoof_location": { + "name": "ஏமாற்றும் இடம்", + "description": "உங்கள் இருப்பிடத்தை ஒரு குறிப்பிட்ட ஒன்றுக்கு ஏமாற்றுகிறது" + }, + "coordinates": { + "name": "ஒருங்கிணைப்புகள்", + "description": "ஏமாற்றப்பட்ட இருப்பிடத்தின் ஆயங்களை அமைக்கவும்" + }, + "walk_radius": { + "name": "நடை ஆரம்", + "description": "தோராயமாக இந்த ஆரம் (அடி)" + }, + "always_update_location": { + "name": "இருப்பிடத்தை எப்போதும் புதுப்பிக்கவும்", + "description": "சி.பி.எச் தரவு எதுவும் பெறப்படாவிட்டாலும் இருப்பிடத்தைப் புதுப்பிக்க ச்னாப்சாட்டை கட்டாயப்படுத்தவும்" + }, + "suspend_location_updates": { + "name": "இருப்பிட புதுப்பிப்புகளை இடைநிறுத்துங்கள்", + "description": "உங்கள் இருப்பிடம் புதுப்பிக்கப்படுவதைத் தடுக்கிறது" + }, + "spoof_battery_level": { + "name": "பேட்டரி அளவை ஏமாற்றுங்கள்", + "description": "வரைபடத்தில் உங்கள் சாதனத்தின் பேட்டரி அளவை ஏமாற்றுகிறது\n மதிப்பு 0 முதல் 100 வரை இருக்க வேண்டும்" + }, + "spoof_headphones": { + "name": "ச்பூஃப் எட்ஃபோன்கள்", + "description": "வரைபடத்தில் இசையைக் கேட்பதன் நிலையை ஏமாற்றுகிறது" + }, + "show_battery_level": { + "name": "பேட்டரி அளவைக் காட்டு", + "description": "வரைபடத்தில் உங்கள் நண்பர்களின் பேட்டரி அளவைக் காட்டுகிறது" + } + } + }, + "snapchat_plus": { + "name": "ச்னாப்சாட் பிளச்", + "description": "ச்னாப்சாட் பிளச் அம்சங்களை இயக்குகிறது\n சில சேவையக பக்க நற்பொருத்தங்கள் வேலை செய்யாது" + }, + "media_upload_quality": { + "name": "மீடியா பதிவேற்றும் தகுதி", + "description": "மீடியா பதிவேற்ற தரத்தை மீறுகிறது", + "properties": { + "force_video_upload_source_quality": { + "name": "வீடியோ பதிவேற்ற மூல தரத்தை கட்டாயப்படுத்துங்கள்", + "description": "வீடியோக்களைப் பதிவேற்றும்போது மூல தரத்தைப் பயன்படுத்த ச்னாப்சாட்டை கட்டாயப்படுத்துகிறது\n இது ஊடகங்களிலிருந்து மெட்டாடேட்டாவை அகற்றாது என்பதை நினைவில் கொள்க" + }, + "disable_image_compression": { + "name": "பட சுருக்கத்தை முடக்கு", + "description": "மீடியாவைப் பதிவேற்றும்போது பட சுருக்கத்தை முடக்குகிறது" + }, + "custom_image_upload_format": { + "name": "தனிப்பயன் பட பதிவேற்ற வடிவம்", + "description": "தனிப்பயன் பட பதிவேற்ற வடிவமைப்பை அமைக்கிறது\n சிறந்த தரத்திற்கு இழப்பற்ற வடிவமைப்பைத் தேர்ந்தெடுக்கவும் (பி.என்.சி போன்றது)" + } + } + }, + "disable_confirmation_dialogs": { + "name": "உறுதிப்படுத்தல் உரையாடல்களை முடக்கு", + "description": "தேர்ந்தெடுக்கப்பட்ட செயல்களை தானாக உறுதிப்படுத்துகிறது" + }, + "auto_updater": { + "name": "ஆட்டோ புதுப்பிப்பாளர்", + "description": "புதிய புதுப்பிப்புகளை தானாகவே சரிபார்க்கிறது" + }, + "disable_metrics": { + "name": "அளவீடுகளை முடக்கு", + "description": "குறிப்பிட்ட பகுப்பாய்வு தரவை ச்னாப்சாட்டுக்கு அனுப்பும் தொகுதிகள்" + }, + "disable_story_sections": { + "name": "கதை பிரிவுகளை முடக்கு", + "description": "கதைகள் பக்கத்திலிருந்து பிரிவுகளை நீக்குகிறது\n சரியாக வேலை செய்ய புதுப்பிப்பு தேவைப்படலாம்" + }, + "block_ads": { + "name": "விளம்பர விளம்பரங்கள்", + "description": "விளம்பரங்கள் காண்பிக்கப்படுவதைத் தடுக்கிறது" + }, + "disable_custom_tabs": { + "name": "தனிப்பயன் தாவல்களை முடக்கு", + "description": "வலை உலாவியில் இல்லாமல் உதவி பயன்பாடுகளில் இணைப்புகளைத் திறக்கிறது" + }, + "disable_permission_requests": { + "name": "இசைவு கோரிக்கைகளை முடக்கு", + "description": "ச்னாப்சாட் குறிப்பிட்ட அனுமதிகளைக் கேட்பதைத் தடுக்கிறது" + }, + "disable_memories_snap_feed": { + "name": "நினைவுகளை முடக்கவும்", + "description": "நீங்கள் கேமராவில் ச்வைப் செய்யும்போது ச்னாப்சாட் அண்மைக் கால நினைவுகளைக் காண்பிப்பதைத் தடுக்கிறது" + }, + "spotlight_comments_username": { + "name": "ச்பாட்லைட் கருத்துரைகள் பயனர்பெயர்", + "description": "ச்பாட்லைட் கருத்துகளில் ஆசிரியர் பயனர்பெயரைக் காட்டுகிறது" + }, + "bypass_video_length_restriction": { + "name": "வீடியோ நீள கட்டுப்பாடுகள் பைபாச்", + "description": "ஒற்றை: ஒரு வீடியோவை அனுப்புகிறது\n பிளவு: திருத்திய பின் வீடியோக்களைப் பிரிக்கவும்" + }, + "default_video_playback_rate": { + "name": "இயல்புநிலை வீடியோ பிளேபேக் வீதம்", + "description": "வீடியோக்களின் பிளேபேக்கிற்கான இயல்புநிலை வேகத்தை அமைக்கிறது\n மதிப்பு 0.1 முதல் 4.0 வரை இருக்க வேண்டும்" + }, + "video_playback_rate_slider": { + "name": "வீடியோ பிளேபேக் வீத ச்லைடர்", + "description": "வீடியோ பிளேபேக் வீதத்தை மாற்ற ஓபரா சூழல் பட்டியலில் ஒரு ச்லைடரைச் சேர்க்கிறது\n குறிப்பு: மாற்றங்கள் அடுத்தடுத்த வீடியோக்களுக்கு மட்டுமே பொருந்தும்" + }, + "disable_google_play_dialogs": { + "name": "Google Play சேவைகள் உரையாடல்களை முடக்கு", + "description": "கூகிள் பிளே சேவைகள் கிடைக்கும் உரையாடல்கள் காண்பிக்கப்படுவதைத் தடுக்கவும்" + }, + "default_volume_controls": { + "name": "இயல்புநிலை தொகுதி கட்டுப்பாடுகள்", + "description": "கணினி தொகுதி கட்டுப்பாடுகளைப் பயன்படுத்த ச்னாப்சாட்டை கட்டாயப்படுத்துகிறது" + }, + "disable_telecom_framework": { + "name": "தொலைதொடர்பு கட்டமைப்பை முடக்கு", + "description": "ஆண்ட்ராய்டு டெலிகாம் கட்டமைப்பைப் பயன்படுத்துவதைத் தடுக்கிறது\n இது அழைப்பில் இருக்கும்போது இசையைக் கேட்க உங்களை அனுமதிக்கிறது" + }, + "hide_active_music": { + "name": "செயலில் உள்ள இசையை மறைக்கவும்", + "description": "நீங்கள் இசையைக் கேட்கிறீர்கள் என்பதை அறிந்து கொள்வதிலிருந்து ச்னாப்சாட்டைத் தடுக்கிறது\n இசையைக் கேட்கும்போது கட்டுப்பாட்டு தொகுதி பொத்தான்களைப் பயன்படுத்தி புகைப்படங்களை எடுக்க இது உங்களை அனுமதிக்கும்" + }, + "disable_snap_splitting": { + "description": "புகைப்படங்கள் பல பகுதிகளாகப் பிரிக்கப்படுவதைத் தடுக்கிறது\n நீங்கள் அனுப்பும் படங்கள் வீடியோக்களாக மாறும்", + "name": "ச்னாப் பிளவுகளை முடக்கு" + } + } + }, + "rules": { + "description": "தனிப்பட்ட நபர்களுக்கான தானியங்கி அம்சங்களை நிர்வகிக்கவும்", + "name": "விதிகள்" + }, + "camera": { + "name": "கேமரா", + "description": "சரியான புகைப்படத்திற்கு சரியான அமைப்புகளை சரிசெய்யவும்", + "properties": { + "disable_cameras": { + "name": "கேமராக்களை முடக்கு", + "description": "தேர்ந்தெடுக்கப்பட்ட கேமராக்களைப் பயன்படுத்துவதைத் தடுக்கிறது" + }, + "black_photos": { + "description": "கைப்பற்றப்பட்ட புகைப்படங்களை கருப்பு பின்னணியுடன் மாற்றுகிறது\n வீடியோக்கள் பாதிக்கப்படவில்லை", + "name": "கருப்பு புகைப்படங்கள்" + }, + "immersive_camera_preview": { + "name": "அதிவேக முன்னோட்டம்", + "description": "கேமரா முன்னோட்டத்தை பயிர் செய்வதைத் தடுக்கிறது\n இது சில சாதனங்களில் கேமரா ஒளிரும்" + }, + "override_front_resolution": { + "name": "முன் தீர்மானத்தை மீறவும்", + "description": "முன் கேமராவிற்கான கேமரா தெளிவுத்திறனை மீறுகிறது" + }, + "override_back_resolution": { + "name": "பின் தீர்மானத்தை மீறவும்", + "description": "பின் கேமராவிற்கான கேமரா தெளிவுத்திறனை மீறுகிறது" + }, + "custom_resolution": { + "name": "தனிப்பயன் தீர்மானம்", + "description": "தனிப்பயன் கேமரா தீர்மானம், அகலம் ஃச் உயரம் (எ.கா. 1920x1080) அமைக்கிறது.\n தனிப்பயன் தீர்மானத்தை உங்கள் சாதனத்தால் ஆதரிக்க வேண்டும்" + }, + "front_custom_frame_rate": { + "name": "முன் தனிப்பயன் பிரேம் வீதம்", + "description": "முன் கேமரா பிரேம் வீதத்தை மீறுகிறது" + }, + "back_custom_frame_rate": { + "name": "தனிப்பயன் பிரேம் வீதத்தை பின்", + "description": "பின் கேமரா பிரேம் வீதத்தை மீறுகிறது" + }, + "force_camera_source_encoding": { + "name": "ஃபோர்ச் கேமரா மூல குறியாக்கம்", + "description": "கேமரா மூல குறியாக்கத்தை கட்டாயப்படுத்துகிறது" + }, + "hevc_recording": { + "name": "HEVC பதிவு", + "description": "வீடியோ பதிவுக்காக HEVC (H.265) கோடெக்கைப் பயன்படுத்துகிறது" + } + } + }, + "streaks_reminder": { + "name": "ச்ட்ரீக்ச் நினைவூட்டல்", + "description": "உங்கள் கோடுகளைப் பற்றி அவ்வப்போது உங்களுக்கு அறிவிக்கிறது", + "properties": { + "interval": { + "name": "இடைவேளை", + "description": "ஒவ்வொரு நினைவூட்டலுக்கும் இடையிலான இடைவெளி (மணிநேரம்)" + }, + "remaining_hours": { + "name": "மீதமுள்ள நேரம்", + "description": "அறிவிப்பு காண்பிக்கப்படுவதற்கு முன் மீதமுள்ள நேரம் (மணிநேரம்)" + }, + "group_notifications": { + "name": "குழு அறிவிப்புகள்", + "description": "குழு அறிவிப்புகள் ஒற்றை" + } + } + }, + "experimental": { + "properties": { + "native_hooks": { + "properties": { + "composer_hooks": { + "name": "இசையமைப்பாளர் கொக்கிகள்", + "description": "இசையமைப்பாளர் குறுக்கு-தளம் இடைமுகம் கட்டமைப்பில் குறியீட்டை செலுத்துகிறது", + "properties": { + "show_first_created_username": { + "name": "முதலில் உருவாக்கிய பயனர்பெயர்", + "description": "சுயவிவரப் பக்கத்தில் தற்போதைய பயனர்பெயருக்கு அடுத்ததாக முதலில் உருவாக்கப்பட்ட பயனர்பெயரைக் காட்டுகிறது" + }, + "bypass_camera_roll_limit": { + "name": "பைபாச் கேமரா ரோல் வரம்பு", + "description": "கேமரா ரோலில் இருந்து நீங்கள் அனுப்பக்கூடிய அதிகபட்ச ஊடகங்களை அதிகரிக்கிறது" + }, + "composer_console": { + "name": "இசையமைப்பாளர் கன்சோல்", + "description": "இசையமைப்பாளரில் சாவாச்கிரிப்ட் குறியீட்டை இயக்க உங்களை அனுமதிக்கிறது (ARM64 மட்டும்)" + }, + "composer_logs": { + "name": "இசையமைப்பாளர் பதிவுகள்", + "description": "இசையமைப்பாளரின் கன்சோல் பதிவுகளை ச்னாபன்ஆன்சுக்கு திருப்பி விடுகிறது" + } + } + }, + "disable_bitmoji": { + "name": "பிட்மோசியை முடக்கு", + "description": "ஊனமுற்ற நண்பர்கள் சுயவிவரம் பிட்மோசி" + }, + "custom_emoji_font": { + "name": "தனிப்பயன் ஈமோசி எழுத்துரு", + "description": "தனிப்பயன் ஈமோசி எழுத்துருவைப் பயன்படுத்த உங்களை அனுமதிக்கிறது. .Ttf எழுத்துருக்களுடன் மட்டுமே வேலை செய்கிறது" + }, + "custom_shared_library": { + "name": "தனிப்பயன் பகிரப்பட்ட நூலகம்", + "description": "தனிப்பயன் பகிரப்பட்ட நூலகத்தை ச்னாப்சாட்டில் ஏற்றுகிறது. இந்த நற்பொருத்தம் சோதனை நோக்கங்களுக்காக மட்டுமே" + } + }, + "name": "சொந்த கொக்கிகள்", + "description": "ச்னாப்சாட்டின் சொந்த குறியீட்டில் இணைந்த பாதுகாப்பற்ற நற்பொருத்தங்கள்" + }, + "spoof": { + "description": "உங்களைப் பற்றிய பல்வேறு தகவல்களை ஏமாற்றுங்கள்", + "properties": { + "play_store_installer_package_name": { + "name": "கடை நிறுவி தொகுப்பு பெயரை விளையாடுங்கள்", + "description": "நிறுவி தொகுப்பு பெயரை com.android.vending க்கு மீறுகிறது" + }, + "remove_vpn_transport_flag": { + "name": "VPN போக்குவரத்து கொடியை அகற்று", + "description": "ச்னாப்சாட் VPN ஐக் கண்டறிவதைத் தடுக்கவும்" + }, + "remove_mock_location_flag": { + "name": "போலி இருப்பிடக் கொடியை அகற்று", + "description": "போலி இருப்பிடத்தைக் கண்டறிவதைத் தடுக்கிறது" + } + }, + "name": "ஏமாற்று" + }, + "convert_message_locally": { + "description": "வெளிப்புற ஊடகங்களை உள்நாட்டில் அரட்டை அடிக்க மாற்றுகிறது. இது அரட்டை பதிவிறக்க சூழல் பட்டியலில் தோன்றும்", + "name": "செய்தியை உள்ளூரில் மாற்றவும்" + }, + "media_file_picker": { + "description": "கேலரியில் இருந்து எந்த வீடியோ/ஆடியோ கோப்பையும் எடுக்க உங்களை அனுமதிக்கிறது", + "name": "மீடியா கோப்பு எடுப்பவர்" + }, + "story_logger": { + "name": "கதை லாகர்", + "description": "நண்பர்கள் கதைகளின் வரலாற்றை வழங்குகிறது" + }, + "call_recorder": { + "name": "ரெக்கார்டரை அழைக்கவும்", + "description": "ஆடியோ அழைப்புகளை தானாக பதிவு செய்கிறது" + }, + "account_switcher": { + "name": "கணக்கு ச்விட்சர்", + "description": "வெளியேறாமல் கணக்குகளுக்கு இடையில் மாற உங்களை அனுமதிக்கிறது\n மெனுவைத் திறக்க உங்கள் பிட்மோசி சுயவிவரத்திற்கு அடுத்த தேடல் ஐகானில் நீண்ட நேரம் அழுத்தவும்\n குறிப்பு: இந்த நற்பொருத்தம் சோதனை மற்றும் எதிர்காலத்தில் மாறும்", + "properties": { + "auto_backup_current_account": { + "name": "ஆட்டோ காப்புப்பிரதி நடப்பு கணக்கு", + "description": "வெளியேறும்போது அல்லது கணக்குகளை மாற்றும்போது நடப்புக் கணக்கை தானாக ஆதரிக்கிறது" + } + } + }, + "better_transcript": { + "name": "சிறந்த டிரான்ச்கிரிப்ட்", + "description": "குரல் குறிப்பு டிரான்ச்கிரிப்டை மேம்படுத்துகிறது", + "properties": { + "force_transcription": { + "name": "குரல் குறிப்பு டிரான்ச்கிரிப்சனை கட்டாயப்படுத்துங்கள்", + "description": "அனைத்து குரல் குறிப்புகளையும் படியெடுக்க அனுமதிக்கிறது" + }, + "preferred_transcription_lang": { + "name": "விருப்பமான டிரான்ச்கிரிப்சன் மொழி", + "description": "குரல் குறிப்பு டிரான்ச்கிரிப்டுக்கு விருப்பமான மொழி (எ.கா. en, es, fr)" + }, + "enhanced_transcript": { + "name": "மேம்படுத்தப்பட்ட டிரான்ச்கிரிப்ட்", + "description": "ஆழம்எல் ஐப் பயன்படுத்தி குரல் குறிப்பு டிரான்ச்கிரிப்டை மேம்படுத்துகிறது.\n இந்த அம்சத்தைப் பயன்படுத்துவதற்கு முன், நீங்கள் அவர்களின் தனியுரிமைக் கொள்கையைப் படித்திருக்கிறீர்கள் என்பதை உறுதிப்படுத்தவும்." + }, + "enhanced_transcript_in_notifications": { + "description": "ஆழம்எல் ஐப் பயன்படுத்தி அறிவிப்புகளில் குரல் குறிப்புகளை படியெடுக்கிறது. சிறந்த அறிவிப்புகளில் அரட்டை முன்னோட்ட நற்பொருத்தம் இயக்கப்பட வேண்டும்", + "name": "அறிவிப்புகளில் மேம்படுத்தப்பட்ட டிரான்ச்கிரிப்ட்" + } + } + }, + "voice_note_auto_play": { + "name": "குரல் குறிப்பு ஆட்டோ நாடகம்", + "description": "தற்போதைய ஒன் முடிந்ததும் தானாகவே அடுத்த குரல் குறிப்பை இயக்குகிறது" + }, + "friend_notes": { + "name": "நண்பர் குறிப்புகள்", + "description": "நண்பர்கள் சுயவிவரங்களில் குறிப்புகளைச் சேர்க்க உங்களை அனுமதிக்கிறது" + }, + "cof_experiments": { + "name": "COF சோதனைகள்", + "description": "வெளியிடப்படாத/பீட்டா ச்னாப்சாட் அம்சங்களை செயல்படுத்துகிறது" + }, + "edit_message": { + "name": "செய்திகளைத் திருத்தவும்", + "description": "உரையாடல்களில் செய்திகளைத் திருத்த உங்களை அனுமதிக்கிறது" + }, + "context_menu_fix": { + "name": "சூழல் பட்டியல் சரி", + "description": "சாதனம் ஆஃப்லைனில் இருக்கும்போது அதை சரியாகக் காட்ட முடியாது போல நண்பர் ஊட்ட மெனுவை சரிசெய்ய முயற்சி" + }, + "app_lock": { + "name": "பயன்பாட்டு பூட்டு", + "description": "கடவுக்குறியீடு இல்லாமல் ச்னாப்சாட் அணுகலைத் தடுக்கிறது", + "properties": { + "lock_on_resume": { + "name": "விண்ணப்பத்தை பூட்டவும்", + "description": "பயன்பாட்டை மீண்டும் திறக்கும்போது பூட்டுகிறது" + } + } + }, + "infinite_story_boost": { + "name": "எல்லையற்ற கதை பூச்ட்", + "description": "கதை பூச்ட் வரம்பு நேரந்தவறுகை" + }, + "meo_passcode_bypass": { + "name": "என் கண்கள் கடவுக்குறியீடு பைபாச் மட்டுமே", + "description": "என் கண்களை மட்டுமே கடந்து செல்கிறது\n கடவுக்குறியீடு இதற்கு முன்பு சரியாக உள்ளிடப்பட்டிருந்தால் மட்டுமே இது செயல்படும்" + }, + "no_friend_score_delay": { + "name": "நண்பர் மதிப்பெண் நேரந்தவறுகை இல்லை", + "description": "நண்பர்கள் மதிப்பெண்ணைப் பார்க்கும்போது தாமதத்தை நீக்குகிறது" + }, + "best_friend_pinning": { + "name": "சிறந்த நண்பர் பின்னிங்", + "description": "உங்கள் நம்பர் ஒன் சிறந்த நண்பராக ஒரு நண்பரை பின்னிணைக்க உங்களை அனுமதிக்கிறது. குறிப்பு: உங்கள் பின் செய்யப்பட்ட சிறந்த நண்பரை மட்டுமே நீங்கள் காணலாம்" + }, + "e2ee": { + "name": "இறுதி-இறுதி குறியாக்கம்", + "description": "பகிரப்பட்ட ரகசிய விசையைப் பயன்படுத்தி உங்கள் செய்திகளை AES உடன் குறியாக்குகிறது\n உங்கள் விசையை எங்காவது பாதுகாப்பாக சேமிப்பதை உறுதிப்படுத்திக் கொள்ளுங்கள்!", + "properties": { + "encrypted_message_indicator": { + "name": "மறைகுறியாக்கப்பட்ட செய்தி காட்டி", + "description": "மறைகுறியாக்கப்பட்ட செய்திகளுக்கு அடுத்ததாக ஒரு 🔒 ஈமோசியை சேர்க்கிறது" + }, + "force_message_encryption": { + "name": "செய்தி குறியாக்கத்தை கட்டாயப்படுத்துங்கள்", + "description": "பல உரையாடல்கள் தேர்ந்தெடுக்கப்படும்போது மட்டுமே E2E குறியாக்கம் இல்லாத நபர்களுக்கு மறைகுறியாக்கப்பட்ட செய்திகளை அனுப்புவதைத் தடுக்கிறது" + } + } + }, + "add_friend_source_spoof": { + "name": "நண்பர் மூல ஏமாற்று சேர்க்கவும்", + "description": "நண்பர் கோரிக்கையின் மூலத்தை ஏமாற்றுகிறது" + }, + "hidden_snapchat_plus_features": { + "name": "மறைக்கப்பட்ட ச்னாப்சாட் பிளச் நற்பொருத்தங்கள்", + "description": "வெளியிடப்படாத/பீட்டா ச்னாப்சாட் பிளச் அம்சங்களை செயல்படுத்துகிறது\n பழைய ச்னாப்சாட் பதிப்புகளில் வேலை செய்யக்கூடாது" + }, + "custom_streaks_expiration_format": { + "name": "தனிப்பயன் கோடுகள் காலாவதி வடிவம்", + "description": "ச்ட்ரீக்ச் காலாவதி வடிவமைப்பைத் தனிப்பயனாக்குகிறது\n\n கிடைக்கும் மாறிகள்:\n - %சி: ச்ட்ரீக்ச் எண்ணிக்கை\n - %E: மணிநேர கிளாச் ஈமோசி\n - %d: நாட்கள்\n - %s: மணிநேரம்\n - %மீ: நிமிடங்கள்\n - %s: விநாடிகள்\n - %W: மீதமுள்ள நேரம்" + }, + "prevent_forced_logout": { + "name": "கட்டாய வெளியேறுவதைத் தடுக்கவும்", + "description": "நீங்கள் வேறொரு சாதனத்தில் உள்நுழையும்போது ச்னாப்சாட் உங்களை உள்நுழைவதைத் தடுக்கிறது" + } + }, + "name": "சோதனை", + "description": "சோதனை நற்பொருத்தங்கள்" + }, + "scripting": { + "name": "ச்கிரிப்டிங்", + "description": "ச்னாபன்ஆன்சை நீட்டிக்க தனிப்பயன் ச்கிரிப்ட்களை இயக்கவும்", + "properties": { + "developer_mode": { + "name": "உருவாக்குபவர் பயன்முறை", + "description": "ச்னாப்சாட்டின் இடைமுகம் இல் பிழைத்திருத்த தகவலைக் காட்டுகிறது" + }, + "module_folder": { + "name": "தொகுதி கோப்புறை", + "description": "ச்கிரிப்ட்கள் அமைந்துள்ள கோப்புறை" + }, + "auto_reload": { + "name": "ஆட்டோ மறுஏற்றம்", + "description": "ச்கிரிப்ட்கள் மாறும்போது தானாகவே மீண்டும் ஏற்றும்" + }, + "disable_log_anonymization": { + "name": "பதிவு அநாமதேயத்தை முடக்கு", + "description": "பதிவுகளின் அநாமதேயத்தை முடக்குகிறது" + }, + "integrated_ui": { + "name": "ஒருங்கிணைந்த இடைமுகம்", + "description": "ச்னாப்சாட்டுக்கு தனிப்பயன் இடைமுகம் கூறுகளைச் சேர்க்க ச்கிரிப்ட்களை அனுமதிக்கிறது" + } + } + }, + "friend_tracker": { + "name": "நண்பர் டிராக்கர்", + "description": "ச்னாப்சாட்டில் நண்பரின் செயல்பாட்டை பதிவு செய்கிறது", + "properties": { + "record_messaging_events": { + "name": "செய்தியிடல் நிகழ்வுகளை பதிவு செய்யுங்கள்", + "description": "ஒரு ச்னாப்பைத் திறப்பது, செய்தியைப் படிப்பது போன்ற செய்தி நிகழ்வுகளை பதிவு செய்கிறது." + }, + "allow_running_in_background": { + "name": "பின்னணியில் இயங்க அனுமதிக்கவும்", + "description": "டிராக்கரை பின்னணியில் இயக்க அனுமதிக்கிறது. குறிப்பு: இது உங்கள் பேட்டரியை கணிசமாக வெளியேற்றும்" + }, + "auto_purge": { + "description": "குறிப்பிட்ட நேரத்தை விட பழமையான தற்காலிக சேமிப்பு நிகழ்வுகளை தானாக நீக்குகிறது", + "name": "ஆட்டோ தூய்மை" + } + } + }, + "downloader": { + "description": "ச்னாப்சாட் மீடியாவைப் பதிவிறக்கவும்", + "properties": { + "save_folder": { + "name": "கோப்புறையை சேமிக்கவும்", + "description": "எல்லா ஊடகங்களையும் பதிவிறக்கம் செய்ய வேண்டிய கோப்பகத்தைத் தேர்ந்தெடுக்கவும்" + }, + "auto_download_sources": { + "description": "தானாக பதிவிறக்கம் செய்ய ஆதாரங்களைத் தேர்ந்தெடுக்கவும்", + "name": "தானாக பதிவிறக்க ஆதாரங்கள்" + }, + "prevent_self_auto_download": { + "name": "தன்வய ஆட்டோ பதிவிறக்கத்தைத் தடுக்கவும்", + "description": "உங்கள் சொந்த புகைப்படங்களை தானாக பதிவிறக்கம் செய்வதைத் தடுக்கிறது" + }, + "path_format": { + "description": "கோப்பு பாதை வடிவமைப்பைக் குறிப்பிடவும்", + "name": "பாதை வடிவம்" + }, + "allow_duplicate": { + "name": "நகல் அனுமதிக்கவும்", + "description": "ஒரே ஊடகத்தை பல முறை பதிவிறக்கம் செய்ய அனுமதிக்கிறது" + }, + "merge_overlays": { + "name": "மேலடுக்குகளை ஒன்றிணைக்கவும்", + "description": "உரை மற்றும் ஒரு ச்னாப்பின் ஊடகத்தை ஒரே கோப்பில் ஒருங்கிணைக்கிறது" + }, + "force_image_format": { + "name": "பட வடிவத்தை கட்டாயப்படுத்துங்கள்", + "description": "படங்களை ஒரு குறிப்பிட்ட வடிவத்தில் சேமிக்க வேண்டும்" + }, + "force_voice_note_format": { + "name": "குரல் குறிப்பு வடிவத்தை கட்டாயப்படுத்துங்கள்", + "description": "ஒரு குறிப்பிட்ட வடிவத்தில் சேமிக்க வேண்டிய குரல் குறிப்புகள்" + }, + "auto_download_voice_notes": { + "name": "தானாக பதிவிறக்க குரல் குறிப்புகள்", + "description": "குரல் குறிப்புகளை இயக்கும்போது தானாகவே பதிவிறக்குகிறது" + }, + "download_profile_pictures": { + "name": "சுயவிவரப் படங்களைப் பதிவிறக்கவும்", + "description": "சுயவிவரப் பக்கத்திலிருந்து சுயவிவரப் படங்களை பதிவிறக்கம் செய்ய உங்களை அனுமதிக்கிறது" + }, + "opera_download_button": { + "name": "ஓபரா பதிவிறக்க பொத்தான்", + "description": "ஒரு ச்னாப்பைப் பார்க்கும்போது மேல் வலது மூலையில் ஒரு பதிவிறக்க பொத்தானைச் சேர்க்கிறது.\n பொத்தான்களில் நீண்ட செய்தித் தாள் பதிவிறக்கத்தை கட்டாயப்படுத்தும்" + }, + "download_context_menu": { + "description": "சூழல் மெனுவைப் பயன்படுத்தி உரையாடல் அல்லது கதையிலிருந்து செய்திகளைப் பதிவிறக்க/முன்னோட்டமிட உங்களை அனுமதிக்கிறது.\n பொத்தான்களில் நீண்ட செய்தித் தாள் பதிவிறக்கத்தை கட்டாயப்படுத்தும்", + "name": "சூழல் மெனுவைப் பதிவிறக்கவும்" + }, + "ffmpeg_options": { + "name": "FFMPEG விருப்பங்கள்", + "description": "கூடுதல் FFMPEG விருப்பங்களைக் குறிப்பிடவும்", + "properties": { + "threads": { + "name": "நூல்கள்", + "description": "பயன்படுத்த வேண்டிய நூல்களின் அளவு" + }, + "preset": { + "description": "மாற்றத்தின் வேகத்தை அமைக்கவும்", + "name": "முன்னமைவு" + }, + "constant_rate_factor": { + "name": "நிலையான வீத காரணி", + "description": "வீடியோ குறியாக்கிக்கான நிலையான வீத காரணியை அமைக்கவும்\n LIBX264 க்கு 0 முதல் 51 வரை" + }, + "video_bitrate": { + "name": "வீடியோ பிட்ரேட்", + "description": "வீடியோ பிட்ரேட்டை (கே.பி.பி.எச்) அமைக்கவும்" + }, + "audio_bitrate": { + "name": "ஆடியோ பிட்ரேட்", + "description": "ஆடியோ பிட்ரேட்டை (கே.பி.பி.எச்) அமைக்கவும்" + }, + "custom_video_codec": { + "description": "தனிப்பயன் வீடியோ கோடெக்கை அமைக்கவும் (எ.கா. LIBX264)", + "name": "தனிப்பயன் வீடியோ கோடெக்" + }, + "custom_audio_codec": { + "description": "தனிப்பயன் ஆடியோ கோடெக்கை அமைக்கவும் (எ.கா. AAC)", + "name": "தனிப்பயன் ஆடியோ கோடெக்" + } + } + }, + "logging": { + "name": "பதிவு", + "description": "ஊடகங்கள் பதிவிறக்கும் போது சிற்றுண்டிகளைக் காட்டுகிறது" + }, + "custom_path_format": { + "name": "தனிப்பயன் பாதை வடிவம்", + "description": "பதிவிறக்கம் செய்யப்பட்ட ஊடகங்களுக்கான தனிப்பயன் பாதை வடிவமைப்பைக் குறிப்பிடவும்\n\n கிடைக்கும் மாறிகள்:\n - %பயனர்பெயர் %\n - %மூல %\n - %ஆச் %\n - %தேதி_ நேரம் %" + } + }, + "name": "பதிவிறக்குபவர்" + }, + "user_interface": { + "name": "பயனர் இடைமுகம்", + "description": "ச்னாப்சாட்டின் தோற்றத்தையும் உணர்வையும் மாற்றவும்", + "properties": { + "enable_app_appearance": { + "name": "பயன்பாட்டு தோற்ற அமைப்புகளை இயக்கவும்", + "description": "மறைக்கப்பட்ட பயன்பாட்டு தோற்ற அமைப்பை இயக்குகிறது\n புதிய ச்னாப்சாட் பதிப்புகளில் தேவையில்லை" + }, + "custom_theme": { + "name": "தனிப்பயன் கருப்பொருள்", + "description": "ச்னாப்சாட்டின் வண்ணங்களைத் தனிப்பயனாக்குங்கள்\n குறிப்பு: நீங்கள் ஒரு இருண்ட கருப்பொருள் (AMOLED போன்ற) தேர்வுசெய்தால், சிறந்த முடிவுகளுக்கு ச்னாப்சாட் அமைப்புகளில் இருண்ட பயன்முறையை இயக்க வேண்டியிருக்கலாம்" + }, + "friend_feed_message_preview": { + "name": "நண்பர் ஊட்ட செய்தி முன்னோட்டம்", + "description": "நண்பர் ஊட்டத்தில் கடைசி செய்திகளின் முன்னோட்டத்தைக் காட்டுகிறது", + "properties": { + "amount": { + "name": "தொகை", + "description": "முன்னோட்டமிடுவதற்கான செய்திகளின் அளவு" + } + } + }, + "snap_preview": { + "name": "ச்னாப் முன்னோட்டம்", + "description": "அரட்டையில் காணப்படாத புகைப்படங்களுக்கு அடுத்ததாக ஒரு சிறிய முன்னோட்டத்தைக் காட்டுகிறது" + }, + "bootstrap_override": { + "name": "தொடக்கவார் மேலெழுதும்", + "description": "பயனர் இடைமுகம் தொடக்கவார் அமைப்புகளை மீறுகிறது", + "properties": { + "app_appearance": { + "name": "பயன்பாட்டு தோற்றம்", + "description": "தொடர்ச்சியான பயன்பாட்டு தோற்றத்தை அமைக்கிறது" + }, + "home_tab": { + "name": "முகப்பு தாவல்", + "description": "ச்னாப்சாட்டைத் திறக்கும்போது தொடக்க தாவலை மீறுகிறது" + }, + "simple_snapchat": { + "name": "எளிய ச்னாப்சாட்", + "description": "ச்னாப்சாட்டின் எளிமைப்படுத்தப்பட்ட பதிப்பை இயக்குகிறது" + } + } + }, + "map_friend_nametags": { + "name": "மேம்படுத்தப்பட்ட நண்பர் வரைபடம் பெயர்", + "description": "ச்னாப்மேப்பில் நண்பர்களின் பெயரிடல்களை மேம்படுத்துகிறது" + }, + "prevent_message_list_auto_scroll": { + "name": "செய்தி பட்டியல் ஆட்டோ சுருளைத் தடுக்கவும்", + "description": "செய்தியை அனுப்பும்போது/பெறும்போது செய்தி பட்டியலை ச்க்ரோலிங் செய்வதிலிருந்து கீழே தடுக்கிறது" + }, + "streak_expiration_info": { + "name": "ச்ட்ரீக் காலாவதி தகவலைக் காட்டு", + "description": "ச்ட்ரீக்ச் கவுண்டருக்கு அடுத்ததாக ச்ட்ரீக் காலாவதி நேரத்தைக் காட்டுகிறது" + }, + "hide_friend_feed_entry": { + "name": "நண்பர் தீவன நுழைவை மறைக்கவும்", + "description": "நண்பர் ஊட்டத்திலிருந்து ஒரு குறிப்பிட்ட நண்பரை மறைக்கிறார்\n இந்த அம்சத்தை நிர்வகிக்க சமூக தாவலைப் பயன்படுத்தவும்" + }, + "hide_streak_restore": { + "name": "ச்ட்ரீக் மீட்டமைப்பை மறைக்கவும்", + "description": "நண்பர் ஊட்டத்தில் மீட்டெடுக்கும் பொத்தானை மறைக்கிறது" + }, + "hide_quick_add_suggestions": { + "name": "விரைவான சேர் பரிந்துரைகளை மறைக்கவும்", + "description": "நண்பர் பரிந்துரைகளை விரைவாகச் சேர்க்கவும்" + }, + "hide_story_suggestions": { + "name": "கதை பரிந்துரைகளை மறைக்கவும்", + "description": "கதைகள் பக்கத்திலிருந்து பரிந்துரைகளை நீக்குகிறது" + }, + "hide_ui_components": { + "name": "இடைமுகம் கூறுகளை மறைக்கவும்", + "description": "எந்த இடைமுகம் கூறுகளை மறைக்க தேர்ந்தெடுக்கவும்" + }, + "opera_media_quick_info": { + "name": "ஓபரா மீடியா விரைவான செய்தி", + "description": "ஓபரா பார்வையாளர் சூழல் பட்டியலில் படைப்பு தேதி போன்ற ஊடகங்களின் பயனுள்ள தகவல்களைக் காட்டுகிறது" + }, + "old_bitmoji_selfie": { + "name": "பழைய பிட்மோசி செல்பி", + "description": "பழைய ச்னாப்சாட் பதிப்புகளிலிருந்து பிட்மோசி செல்பிசை மீண்டும் கொண்டு வருகிறது" + }, + "disable_spotlight": { + "name": "ச்பாட்லைட்டை முடக்கு", + "description": "ச்பாட்லைட் பக்கத்தை முடக்குகிறது" + }, + "friend_feed_menu_buttons": { + "name": "நண்பர் ஊட்ட பட்டியல் பொத்தான்கள்", + "description": "நண்பர் ஊட்ட பட்டியலில் எந்த பொத்தான்களைக் காட்ட வேண்டும் என்பதைத் தேர்ந்தெடுக்கவும்" + }, + "auto_close_friend_feed_menu": { + "name": "தானாக நெருங்கிய நண்பர் ஊட்ட பட்டியல்", + "description": "அமைத்தல் பொத்தானை அழுத்திய பின் நண்பர் ஊட்ட மெனுவை தானாக மூடுகிறது" + }, + "message_indicators": { + "name": "செய்தி குறிகாட்டிகள்", + "description": "செய்திகளில் குறிப்பிட்ட குறிகாட்டிகள் சின்னங்களைச் சேர்க்கிறது\n குறிப்பு: குறிகாட்டிகள் 100% துல்லியமாக இருக்காது" + }, + "stealth_mode_indicator": { + "name": "திருட்டுத்தனமான பயன்முறை காட்டி", + "description": "திருட்டுத்தனமான பயன்முறையில் உரையாடல்களுக்கு அடுத்ததாக ஒரு 👻 ஈமோசியை சேர்க்கிறது" + }, + "edit_text_override": { + "name": "உரை மேலெழுதலைத் திருத்தவும்", + "description": "உரை புல நடத்தை மீறுகிறது" + }, + "vertical_story_viewer": { + "name": "செங்குத்து கதை பார்வையாளர்", + "description": "எல்லா கதைகளுக்கும் செங்குத்து கதை பார்வையாளரை செயல்படுத்துகிறது" + }, + "enable_friend_feed_menu_bar": { + "name": "நண்பர் ஊட்ட பட்டியல் பட்டி", + "description": "புதிய நண்பர் ஊட்ட பட்டியல் பட்டியை இயக்குகிறது" + } + } + } + }, + "options": { + "app_appearance": { + "always_light": "எப்போதும் ஒளி", + "always_dark": "எப்போதும் இருண்ட" + }, + "custom_theme": { + "amoled_dark_mode": "அமோல்ட் டார்க் பயன்முறை", + "custom": "தனிப்பயன் கருப்பொருள்கள் (கருப்பொருள்களை நிர்வகிக்க விரைவான செயல்களைப் பயன்படுத்தவும்)", + "material_you_light": "பொருள் நீங்கள் ஒளி (Android 12+)", + "material_you_dark": "பொருள் நீங்கள் இருண்ட (Android 12+)" + }, + "friend_feed_menu_buttons": { + "auto_download": "தானி ஆட்டோ பதிவிறக்கம்", + "auto_save": "Moades செய்திகளை சேமிக்கவும்", + "unsaveable_messages": "Nastancantancease விரும்பத்தகாத செய்திகள்", + "auto_open_snaps": "தானி ஆட்டோ திறந்த புகைப்படங்கள்", + "stealth": "👻 திருட்டுத்தனமான பயன்முறை", + "mark_snaps_as_seen": "பார்த்தபடி குறிக்கவும்", + "mark_stories_as_seen_locally": "In உள்நாட்டில் காணப்பட்ட கதைகளை குறிக்கவும்", + "conversation_info": "Contice உரையாடல் செய்தி", + "e2e_encryption": "இ 2E குறியாக்கத்தைப் பயன்படுத்தவும்" + }, + "path_format": { + "create_source_folder": "ஒவ்வொரு ஊடக மூல வகைக்கும் கோப்புறையை உருவாக்கவும்", + "append_hash": "கோப்பு பெயரில் ஒரு தனித்துவமான ஆசைச் சேர்க்கவும்", + "append_source": "கோப்பு பெயரில் மீடியா மூலத்தைச் சேர்க்கவும்", + "append_date_time": "கோப்பு பெயரில் தேதி மற்றும் நேரத்தை சேர்க்கவும்", + "create_author_folder": "ஒவ்வொரு எழுத்தாளருக்கும் கோப்புறையை உருவாக்கவும்", + "append_username": "கோப்பு பெயரில் பயனர்பெயரைச் சேர்க்கவும்" + }, + "auto_download_sources": { + "friend_stories": "நண்பர் கதைகள்", + "public_stories": "பொதுக் கதைகள்", + "spotlight": "ச்பாட்லைட்", + "friend_snaps": "நண்பர் நொறுங்குகிறார்" + }, + "logging": { + "started": "தொடங்கியது", + "success": "செய்", + "progress": "முன்னேற்றம்", + "failure": "தோல்வி" + }, + "notifications": { + "chat_reply": "அரட்டை பதில்", + "snap": "ச்னாப்", + "typing": "தட்டச்சு", + "stories": "கதைகள்", + "speaking": "பேசும்", + "chat_reaction": "டி.எம் எதிர்வினை", + "group_chat_reaction": "குழு எதிர்வினை", + "initiate_audio": "உள்வரும் ஆடியோ அழைப்பு", + "abandon_audio": "தவறவிட்ட ஆடியோ அழைப்பு", + "abandon_video": "வீடியோ அழைப்பு தவறவிட்டது", + "chat_screenshot": "திரைக்காட்சி", + "chat_screen_record": "திரை பதிவு", + "snap_replay": "ச்னாப் ரீப்ளே", + "camera_roll_save": "கேமரா ரோல் சேமி", + "chat": "அரட்டை", + "initiate_video": "உள்வரும் வீடியோ அழைப்பு" + }, + "gallery_media_send_override": { + "always_ask": "எப்போதும் கேளுங்கள்", + "ORIGINAL": "அசல் மீடியா", + "NOTE": "ஆடியோ குறிப்பு", + "SNAP": "ச்னாப்", + "SAVEABLE_SNAP": "சேமிக்கக்கூடிய ச்னாப்" + }, + "strip_media_metadata": { + "hide_caption_text": "தலைப்பு உரையை மறைக்கவும்", + "hide_snap_filters": "ச்னாப் வடிப்பான்களை மறைக்கவும்", + "hide_extras": "கூடுதல் மறைக்க (எ.கா. குறிப்பிடுகிறது)", + "remove_audio_note_duration": "ஆடியோ குறிப்பு காலத்தை அகற்று", + "remove_audio_note_transcript_capability": "ஆடியோ குறிப்பு டிரான்ச்கிரிப்ட் திறனை அகற்று" + }, + "hide_ui_components": { + "hide_stickers_button": "ச்டிக்கர்கள் பொத்தானை அகற்று", + "hide_voice_record_button": "குரல் பதிவு பொத்தானை அகற்று", + "hide_unread_chat_hint": "படிக்காத அரட்டை குறிப்பை அகற்று", + "hide_post_to_story_buttons": "ச்னாப் அனுப்புவதற்கு முன் கதை பொத்தான்களுக்கு இடுகையை அகற்று", + "hide_snapchat_plus_gift_reminders": "உரையாடல்களில் ச்னாப்சாட் பிளச் பரிசு நினைவூட்டல்களை அகற்றவும்", + "hide_map_reactions": "வரைபட எதிர்வினைகளை அகற்று", + "hide_profile_call_buttons": "சுயவிவர அழைப்பு பொத்தான்களை அகற்று", + "hide_chat_call_buttons": "அரட்டை அழைப்பு பொத்தான்களை அகற்று", + "hide_live_location_share_button": "நேரடி இருப்பிட பங்கு பொத்தானை அகற்று", + "hide_billboard_prompt": "நண்பர்கள் ஊட்டத்தில் பில்போர்டு வரியில் அகற்றவும்" + }, + "hide_story_suggestions": { + "hide_suggested_friend_stories": "பரிந்துரைக்கப்பட்ட நண்பர் கதைகளை மறைக்கவும்", + "hide_my_stories": "எனது கதைகளை மறைக்கவும்" + }, + "home_tab": { + "map": "வரைபடம்", + "chat": "அரட்டை", + "camera": "கேமரா", + "discover": "கண்டுபிடி", + "spotlight": "ச்பாட்லைட்" + }, + "simple_snapchat": { + "always_enabled": "எப்போதும் இயக்கப்பட்டது", + "always_disabled": "எப்போதும் முடக்கப்பட்டது" + }, + "add_friend_source_spoof": { + "added_by_qr_code": "QR குறியீடு மூலம்", + "added_by_quick_add": "விரைவாகச் சேர்ப்பதன் மூலம் (தடைசெய்யப்படுவதற்கான அதிக ஆபத்து)", + "added_by_username": "பயனர்பெயர் மூலம்", + "added_by_mention": "குறிப்பிடுவதன் மூலம்", + "added_by_group_chat": "குழு அரட்டை மூலம்", + "added_by_community": "சமூகத்தால்" + }, + "disable_confirmation_dialogs": { + "remove_friend": "நண்பரை அகற்று", + "block_friend": "பிளாக் நண்பரை", + "ignore_friend": "நண்பரை புறக்கணிக்கவும்", + "hide_friend": "நண்பரை மறைக்க", + "hide_conversation": "உரையாடலை மறைக்கவும்", + "clear_conversation": "நண்பர் ஊட்டத்திலிருந்து தெளிவான உரையாடல்", + "erase_message": "செய்தியை அழிக்கவும்" + }, + "auto_reload": { + "snapchat_only": "ச்னாப்சாட் மட்டும்", + "all": "அனைத்தும் (ச்னாப்சாட் + ச்னாபன்ஆன்ச்)" + }, + "edit_text_override": { + "multi_line_chat_input": "பல வரி அரட்டை உள்ளீடு", + "bypass_text_input_limit": "உரை உள்ளீட்டு வரம்பு பைபாச்" + }, + "auto_purge": { + "never": "ஒருபோதும்", + "1_hour": "1 மணி நேரம்", + "6_hours": "6 மணி நேரம்", + "12_hours": "12 மணி நேரம்", + "1_day": "1 நாள்", + "3_days": "3 நாட்கள்", + "1_month": "1 மாதம்", + "3_months": "3 மாதங்கள்", + "6_months": "6 மாதங்கள்", + "3_hours": "3 மணி நேரம்", + "1_week": "1 வாரம்", + "2_weeks": "2 வாரங்கள்" + }, + "disable_story_sections": { + "friends": "நண்பர்கள்", + "suggested_stories": "பரிந்துரைக்கப்பட்ட கதைகள்", + "following": "பின்வருமாறு", + "discover": "கண்டுபிடி" + }, + "disable_cameras": { + "front": "முன் கேமரா", + "back": "பின் கேமரா" + }, + "disable_permission_requests": { + "notifications": "அறிவிப்புகள்", + "read_media_images": "மீடியா படங்களைப் படியுங்கள்", + "location": "இடம்", + "read_contacts": "தொடர்புகளைப் படியுங்கள்", + "nearby_devices": "அருகிலுள்ள சாதனங்கள்", + "phone_calls": "தொலைபேசி அழைப்புகள்", + "read_media_video": "மீடியா வீடியோவைப் படியுங்கள்", + "camera": "கேமரா", + "microphone": "ஒலிவாங்கி" + }, + "message_indicators": { + "encryption_indicator": "உங்களுக்கு மட்டுமே அனுப்பப்பட்ட செய்திகளுக்கு அடுத்ததாக ஒரு 🔒 ஐகானைச் சேர்க்கிறது", + "platform_indicator": "ஒரு மீடியா அனுப்பப்பட்ட இயங்குதள ஐகானைச் சேர்க்கவும் (I.N. ஆண்ட்ராய்டு, ஐஇமு, Web)", + "location_indicator": "இருப்பிடத்துடன் அனுப்பப்படும் போது புகைப்படங்களுக்கு ஒரு 📍 ஐகானைச் சேர்க்கிறது", + "ovf_editor_indicator": "OVF எடிட்டரைப் பயன்படுத்தி ஒரு ச்னாப் அனுப்பப்பட்டதா என்பதைக் குறிக்கிறது", + "director_mode_indicator": "இயக்குனர் பயன்முறையைப் பயன்படுத்தி அனுப்பப்படும்போது ச்னாப்சுக்கு ஒரு ic ஐகானைச் சேர்க்கிறது, இது கேலரி படங்களை ச்னாப்சாக அனுப்ப பயன்படுகிறது" + }, + "auto_mark_as_read": { + "conversation_read": "செய்தியை அனுப்பும்போது உரையாடலைப் படித்தபடி குறிக்கவும்", + "snap_reply": "அவர்களுக்கு பதிலளிக்கும் போது படித்தபடி குறிக்கவும்" + }, + "friend_mutation_notifier": { + "bitmoji_avatar_changes": "யாராவது தங்கள் பிட்மோசி அவதாரத்தை மாற்றும்போது அறிவிக்கவும்", + "bitmoji_background_changes": "யாராவது தங்கள் பிட்மோசி பின்னணியை மாற்றும்போது அறிவிக்கவும்", + "bitmoji_scene_changes": "யாராவது தங்கள் பிட்மோசி காட்சியை மாற்றும்போது அறிவிக்கவும்", + "remove_friend": "யாராவது உங்களை ஒரு நண்பராக நீக்கும்போது அறிவிக்கவும்", + "birthday_changes": "யாராவது தங்கள் பிறந்தநாளை மாற்றும்போது அறிவிக்கவும்", + "bitmoji_selfie_changes": "யாராவது தங்கள் பிட்மோசி செல்பியை மாற்றும்போது அறிவிக்கவும்" + }, + "snapchat_plus": { + "not_subscribed": "குழுசேரவில்லை", + "basic": "அடிப்படை", + "ad_free": "விளம்பரம் இலவசம்" + }, + "double_tap_chat_action": { + "like_message": "செய்தி போன்றது", + "copy_text": "இடைநிலைப்பலகைக்கு உரையை நகலெடுக்கவும்", + "delete_message": "செய்தியை நீக்கு", + "mark_as_read": "படித்தபடி குறி", + "custom_emoji_reaction": "தனிப்பயன் ஈமோசி எதிர்வினை" + }, + "bypass_video_length_restriction": { + "single": "ஒற்றை மீடியா", + "split": "பிளவு மீடியா" + }, + "old_bitmoji_selfie": { + "2d": "அது ஏற்படலாம்", + "3d": "திரும்பி வாருங்கள்" + } + }, + "notices": { + "unstable": "⚠ நிலையற்றது", + "ban_risk": "Feature இந்த நற்பொருத்தம் தடைகளை ஏற்படுத்தக்கூடும்", + "internal_behavior": "⚠ இது ச்னாப்சாட் உள் நடத்தையை உடைக்கக்கூடும்" + } + }, + "setup": { + "mappings": { + "generate_failure": "வரைபடங்களை உருவாக்க முயற்சிக்கும்போது பிழை ஏற்பட்டது, தயவுசெய்து மீண்டும் முயற்சிக்கவும்.", + "generate_failure_no_snapchat": "ச்னாபன்ஆன்ச் ச்னாப்சாட்டைக் கண்டறிய முடியவில்லை, தயவுசெய்து ச்னாப்சாட்டை மீண்டும் நிறுவ முயற்சிக்கவும்.", + "dialog": "வரைபடங்களை உருவாக்குதல், இதற்கு சிறிது நேரம் ஆகலாம் ..." + }, + "permissions": { + "dialog": "தொடர நீங்கள் பின்வரும் தேவைகளுக்கு பொருந்த வேண்டும்:", + "notification_access": "அறிவிப்பு அணுகல்", + "battery_optimization": "பேட்டரி தேர்வுமுறை", + "display_over_other_apps": "பிற பயன்பாடுகளில் காண்பி", + "request_button": "கோரிக்கை" + }, + "dialogs": { + "save_folder": "ச்னாபன்ஆன்சுக்கு ச்னாப்சாட்டிலிருந்து ஊடகங்களை பதிவிறக்கம் செய்து சேமிக்க சேமிப்பக அனுமதிகள் தேவை.\n மீடியா பதிவிறக்கம் செய்ய வேண்டிய இடத்தைத் தேர்வுசெய்க.", + "select_language": "மொழியைத் தேர்ந்தெடுக்கவும்", + "select_save_folder_button": "கோப்புறையைத் தேர்ந்தெடு" + } + }, + "scopes": { + "friend": "நண்பர்", + "group": "குழு" + }, + "manager": { + "routes": { + "features": "நற்பொருத்தங்கள்", + "manage_rule_feature": "விதி அம்சத்தை நிர்வகிக்கவும்", + "home": "வீடு", + "home_settings": "அமைப்புகள்", + "home_logs": "பதிவுகள்", + "logger_history": "லாகர் வரலாறு", + "logged_stories": "உள்நுழைந்த கதைகள்", + "friend_tracker": "நண்பர் டிராக்கர்", + "edit_rule": "விதியைத் திருத்து", + "file_imports": "கோப்பு இறக்குமதிகள்", + "theming": "தீமிங்", + "edit_theme": "கருப்பொருள் திருத்து", + "manage_repos": "களஞ்சியங்களை நிர்வகிக்கவும்", + "social": "சமூக", + "manage_scope": "நோக்கத்தை நிர்வகிக்கவும்", + "messaging_preview": "முன்னோட்டம்", + "scripts": "ச்கிரிப்ட்கள்", + "better_location": "சிறந்த இடம்", + "tasks": "பணிகள்" + }, + "sections": { + "home": { + "version_title": "V {versionName} · · · · · · · ரங்க்", + "update_title": "ச்னாபன்ஆன்ச் புதுப்பிப்பு", + "update_content": "பதிப்பு {version} கிடைக்கிறது!", + "update_button": "பதிவிறக்கம்", + "debug_build_summary_title": "நீங்கள் ச்னாபன்ஆன்சின் பிழைத்திருத்த கட்டமைப்பை இயக்குகிறீர்கள்", + "debug_build_summary_content": "பதிப்பு {versionName} ({versionCode})", + "debug_build_summary_date": "உருவாக்க தேதி: {date} ({days} நாட்கள் முன்பு)", + "quick_actions_title": "விரைவான செயல்கள்" + }, + "home_logs": { + "no_logs_hint": "பதிவுகள் எதுவும் கிடைக்கவில்லை", + "clear_logs_button": "பதிவுகளை அழிக்கவும்", + "export_logs_button": "ஏற்றுமதி பதிவுகள்", + "saving_logs_toast": "பதிவுகளைச் சேமித்தல், இதற்கு சிறிது நேரம் ஆகலாம் ...", + "saved_logs_success_toast": "பதிவுகள் வெற்றிகரமாக சேமிக்கப்பட்டன", + "saved_logs_failure_toast": "பதிவுகளைச் சேமிப்பதில் தோல்வி" + }, + "home_settings": { + "actions_title": "செயல்கள்", + "message_logger_title": "செய்தி லாகர்", + "debug_title": "பிழைத்திருத்தம்", + "success_toast": "முடிந்தது!", + "message_logger_summary": "{messageCount} செய்திகள்\n {storyCount} கதைகள்", + "export_button": "ஏற்றுமதி", + "clear_button": "தெளிவான", + "view_logger_history_button": "லாகர் வரலாற்றைக் காண்க" + }, + "tasks": { + "no_tasks": "பணிகள் இல்லை", + "merge_button": "ஒன்றிணைக்கவும்", + "failed_to_open_file": "கோப்பைத் திறக்கத் தவறிவிட்டது", + "merge_files_toast": "இணைத்தல் {count} கோப்புகள்", + "remove_selected_tasks_title": "தேர்ந்தெடுக்கப்பட்ட பணிகளை அகற்ற விரும்புகிறீர்களா?", + "remove_all_tasks_title": "எல்லா பணிகளையும் அகற்ற விரும்புகிறீர்களா?", + "delete_files_option": "கோப்புகளையும் நீக்கவும்", + "remove_selected_tasks_confirm": "{count} பணிகளை அகற்று?", + "remove_all_tasks_confirm": "எல்லா பணிகளையும் அகற்றவா?" + }, + "features": { + "disabled": "முடக்கப்பட்டது", + "export_option": "ஏற்றுமதி", + "import_option": "இறக்குமதி", + "reset_option": "மீட்டமை", + "config_export_success_toast": "கட்டமைப்பு வெற்றிகரமாக ஏற்றுமதி செய்யப்பட்டது", + "config_import_success_toast": "வெற்றிகரமாக இறக்குமதி செய்யப்பட்டது", + "config_import_failure_toast": "கட்டமைப்பு {error} இறக்குமதி செய்வதில் தோல்வி", + "config_export_failure_toast": "உள்ளமைவு {error} ஏற்றுமதி செய்வதில் தோல்வி", + "saved_config_snackbar": "கட்டமைப்பு சேமிக்கப்பட்டது", + "older_required": "இந்த அம்சத்திற்கு ச்னாப்சாட் வி {version} அல்லது அதற்கு மேற்பட்டது சரியாக வேலை செய்ய தேவைப்படுகிறது", + "newer_required": "இந்த அம்சத்திற்கு ச்னாப்சாட் வி {version} அல்லது சரியாக வேலை செய்ய புதியது தேவைப்படுகிறது", + "search_button": "தேடல்" + }, + "manage_rule_feature": { + "disable_state_option": "முடக்கப்பட்டது", + "disable_state_subtext": "நண்பர்கள்/குழுக்கள் எதுவும் பாதிக்கப்படாது", + "whitelist_state_option": "தவிர வேறு யாரும் இல்லை ...", + "whitelist_state_subtext": "{count} நண்பர்கள்/குழுக்கள் மட்டுமே இந்த விதியால் பாதிக்கப்படும்", + "whitelist_state_button": "அனுமதிக்கப்பட்ட நண்பர்கள்/குழுக்களைத் தேர்ந்தெடுக்கவும்", + "blacklist_state_option": "தவிர எல்லோரும் ...", + "blacklist_state_subtext": "{count} நண்பர்கள்/குழுக்கள் தவிர எல்லோரும் இந்த விதியால் பாதிக்கப்படுவார்கள்", + "blacklist_state_button": "விலக்கப்பட்ட நண்பர்கள்/குழுக்களைத் தேர்ந்தெடுக்கவும்", + "clear_list_button": "நண்பர்கள்/குழுக்கள் பட்டியல்", + "dialog_clear_confirmation_text": "பட்டியலை அழிக்க விரும்புகிறீர்களா?" + }, + "social": { + "friends_tab": "நண்பர்கள்", + "groups_tab": "குழுக்கள்", + "empty_hint": "(காலியாக)", + "streaks_expiration_short": "{hours} h" + }, + "manage_scope": { + "logged_stories_button": "உள்நுழைந்த கதைகளைக் காட்டு", + "e2ee_title": "இறுதி-இறுதி குறியாக்கம்", + "rules_title": "விதிகள்", + "participants_text": "{count} பங்கேற்பாளர்கள்", + "not_found": "கண்டுபிடிக்கப்படவில்லை", + "streaks_title": "கோடுகள்", + "streaks_length_text": "நீளம்: {length}", + "streaks_expiration_text": "{eta} இல் காலாவதியாகிறது", + "streaks_expiration_text_expired": "காலாவதியான", + "reminder_button": "நினைவூட்டலை அமைக்கவும்", + "delete_scope_confirm_dialog_title": "நீங்கள் ஒரு {scope} ஐ நீக்க விரும்புகிறீர்களா?", + "notes_placeholder": "குறிப்பைச் சேர்க்க சொடுக்கு செய்க" + }, + "logged_stories": { + "story_failed_to_load": "ஏற்றுவதில் தோல்வி", + "no_stories": "கதைகள் எதுவும் கிடைக்கவில்லை", + "save_from_cache_button": "தற்காலிக சேமிப்பிலிருந்து சேமிக்கவும்" + }, + "messaging_preview": { + "bridge_connection_failed": "பாலத்துடன் இணைக்கத் தவறிவிட்டது. ச்னாப்சாட் பின்னணியில் இயங்குவதை உறுதிசெய்க", + "bridge_init_failed": "செய்தியிடல் பாலத்தைத் தொடங்கத் தவறிவிட்டது. ச்னாப்சாட் பின்னணியில் இயங்குவதை உறுதிசெய்க", + "message_fetch_failed": "செய்திகளைப் பெறுவதில் தோல்வி", + "no_message_hint": "செய்தி இல்லை", + "save_selection_option": "தேர்வைச் சேமிக்கவும்", + "save_all_option": "அனைத்தையும் சேமி", + "unsave_selection_option": "மன்னிப்பு தேர்வு", + "unsave_all_option": "அனைவரையும் விடவும்", + "mark_selection_as_seen_option": "பார்த்தபடி தேர்ந்தெடுக்கப்பட்ட ச்னாப்", + "mark_all_as_seen_option": "பார்த்தபடி அனைத்து புகைப்படங்களையும் குறிக்கவும்", + "delete_selection_option": "தேர்வை நீக்கு", + "delete_all_option": "அனைத்தையும் நீக்கு" + }, + "logger_history": { + "list_friend_format": "நண்பர் {name}", + "list_group_format": "குழு {name}", + "no_more_messages": "மேலும் செய்திகள் இல்லை", + "reverse_order_checkbox": "தலைகீழ் ஒழுங்கு", + "chat_attachment": "இணைப்பு {index}", + "empty_message": "வெற்று அரட்டை செய்தி", + "message_parse_failed": "செய்தியை அலசத் தவறிவிட்டது", + "unknown_sender": "தெரியாத அனுப்புநர்", + "download_attachment_failed_toast": "இணைப்பைப் பதிவிறக்குவதில் தோல்வி" + }, + "file_imports": { + "import_file_button": "கோப்பு இறக்குமதி", + "file_not_found": "கோப்பு கிடைக்கவில்லை", + "file_import_failed": "கோப்பை இறக்குமதி செய்வதில் தோல்வி: {error}", + "file_imported": "கோப்பு வெற்றிகரமாக இறக்குமதி செய்யப்பட்டது", + "file_delete_failed": "கோப்பை நீக்குவதில் தோல்வி", + "no_files_hint": "ச்னாப்சாட்டில் பயன்படுத்த கோப்புகளை இங்கே இறக்குமதி செய்யலாம். ஒரு கோப்பை இறக்குமதி செய்ய கீழே உள்ள பொத்தானை அழுத்தவும்." + }, + "better_location": { + "spoofed_coordinates_title": "Lat {latitude}, lng {longitude}", + "save_coordinates_dialog_title": "ஒருங்கிணைப்புகளை சேமிக்கவும்", + "saved_name_dialog_hint": "சேமித்த பெயர்", + "latitude_dialog_hint": "அகலாங்கு", + "longitude_dialog_hint": "நெட்டாங்கு", + "save_dialog_button": "சேமி", + "choose_location_button": "இருப்பிடத்தைத் தேர்வுசெய்க", + "teleport_to_friend_button": "நண்பருக்கு டெலிபோர்ட்", + "spoof_location_toggle": "ஏமாற்றும் இடம்", + "suspend_location_updates": "இருப்பிட புதுப்பிப்புகளை இடைநிறுத்துங்கள்", + "saved_coordinates_title": "சேமித்த ஆயத்தொலைவுகள்", + "no_saved_coordinates_hint": "சேமித்த ஆயத்தொலைவுகள் இல்லை", + "delete_dialog_title": "சேமித்த ஒருங்கிணைப்பை நீக்கு", + "delete_dialog_message": "இந்த சேமித்த ஒருங்கிணைப்பை நீக்க விரும்புகிறீர்களா?", + "teleport_to_friend_title": "நண்பருக்கு டெலிபோர்ட்", + "search_bar": "தேடல்", + "no_friends_map": "வரைபடத்தில் நண்பர்கள் இல்லை", + "no_friends_found": "நண்பர்கள் எதுவும் கிடைக்கவில்லை" + }, + "theming": { + "no_themes_hint": "கருப்பொருள்கள் எதுவும் கிடைக்கவில்லை" + } + }, + "dialogs": { + "add_friend": { + "title": "நண்பர் அல்லது குழுவைச் சேர்க்கவும்", + "search_hint": "தேடல்", + "fetch_error": "தரவைப் பெறுவதில் தோல்வி", + "category_groups": "குழுக்கள்", + "category_friends": "நண்பர்கள்", + "participants_text": "{count} பங்கேற்பாளர்கள்" + }, + "scripting_warning": { + "title": "எச்சரிக்கை", + "content": "ச்னாபன்ஆன்ச் ஒரு ச்கிரிப்டிங் கருவியை உள்ளடக்கியது, இது உங்கள் சாதனத்தில் பயனர் வரையறுக்கப்பட்ட குறியீட்டை செயல்படுத்த அனுமதிக்கிறது. தீவிர எச்சரிக்கையைப் பயன்படுத்துங்கள் மற்றும் அறியப்பட்ட, நம்பகமான மூலங்களிலிருந்து தொகுதிகளை மட்டுமே நிறுவவும். அங்கீகரிக்கப்படாத அல்லது சரிபார்க்கப்படாத தொகுதிகள் உங்கள் கணினிக்கு பாதுகாப்பு அபாயங்களை ஏற்படுத்தக்கூடும்." + }, + "reset_config": { + "title": "கட்டமைப்பை மீட்டமைக்கவும்", + "content": "நீங்கள் நிச்சயமாக உள்ளமைவை மீட்டமைக்க விரும்புகிறீர்களா?", + "success_toast": "கட்டமைப்பு மீட்டமைக்கவும் வெற்றிகரமாக" + }, + "export_config": { + "title": "உணர்திறன் தரவை ஏற்றுமதி செய்யவா?", + "content": "முக்கியமான தரவுகளுடன் உள்ளமைவை ஏற்றுமதி செய்ய விரும்புகிறீர்களா? (இருப்பிட ஒருங்கிணைப்புகள் போன்றவை)" + }, + "messaging_action": { + "title": "செயலாக்க உள்ளடக்க வகைகளைத் தேர்வுசெய்க", + "select_all_button": "அனைத்தையும் தெரிவுசெய்" + }, + "file_imports": { + "no_files_settings_hint": "கோப்புகள் எதுவும் கிடைக்கவில்லை. கோப்பு இறக்குமதி பிரிவில் தேவையான கோப்புகளை நீங்கள் இறக்குமதி செய்துள்ளீர்கள் என்பதை உறுதிப்படுத்திக் கொள்ளுங்கள்", + "settings_select_file_hint": "இறக்குமதி செய்யப்பட்ட கோப்பைத் தேர்ந்தெடுக்கவும்" + } + } + }, + "rules": { + "toasts": { + "enabled": "{ruleName} இயக்கப்பட்டது", + "disabled": "{ruleName} முடக்கப்பட்டது" + }, + "modes": { + "blacklist": "பிளாக்லிச்ட் பயன்முறை", + "whitelist": "அனுமதிப்பட்டியல் பயன்முறை" + }, + "properties": { + "auto_download": { + "description": "புகைப்படங்களைப் பார்க்கும்போது தானாகவே பதிவிறக்கவும்", + "options": { + "blacklist": "ஆட்டோ பதிவிறக்கத்திலிருந்து விலக்கு", + "whitelist": "ஆட்டோ பதிவிறக்கம்" + }, + "name": "ஆட்டோ பதிவிறக்கம்" + }, + "stealth": { + "name": "திருட்டுத்தனமான பயன்முறை", + "description": "நீங்கள் அவர்களின் புகைப்படங்கள்/அரட்டைகள் மற்றும் உரையாடல்களைத் திறந்துவிட்டீர்கள் என்பதை அறிந்து கொள்வதைத் தடுக்கிறது", + "options": { + "blacklist": "திருட்டுத்தனமான பயன்முறையிலிருந்து விலக்கு", + "whitelist": "திருட்டுத்தனமான பயன்முறை" + } + }, + "auto_save": { + "description": "அரட்டை செய்திகளைப் பார்க்கும்போது அவற்றைச் சேமிக்கிறது", + "options": { + "blacklist": "ஆட்டோ சேமிப்பிலிருந்து விலக்கு", + "whitelist": "தானியங்கு சேமிப்பு" + }, + "name": "தானியங்கு சேமிப்பு" + }, + "unsaveable_messages": { + "name": "சுவையற்ற செய்திகள்", + "description": "செய்திகளை மற்றவர்களால் அரட்டையில் சேமிப்பதைத் தடுக்கிறது", + "options": { + "blacklist": "விரும்பத்தகாத செய்திகளிலிருந்து விலக்கு", + "whitelist": "சுவையற்ற செய்திகள்" + } + }, + "auto_open_snaps": { + "name": "ஆட்டோ திறந்த புகைப்படங்கள்", + "description": "ச்னாப்புகளைப் பெறும்போது தானாகவே திறக்கிறது", + "options": { + "blacklist": "ஆட்டோ திறந்த புகைப்படங்களிலிருந்து விலக்கு", + "whitelist": "ஆட்டோ திறந்த புகைப்படங்கள்" + } + }, + "hide_friend_feed": { + "name": "நண்பர் ஊட்டத்திலிருந்து மறைக்கவும்" + }, + "e2e_encryption": { + "name": "E2E குறியாக்கத்தைப் பயன்படுத்தவும்" + }, + "pin_conversation": { + "name": "பின் உரையாடல்" + } + } + }, + "actions": { + "clean_snapchat_cache": { + "name": "தூய்மை ச்னாப்சாட் கேச்", + "description": "ச்னாப்சாட் தற்காலிக சேமிப்பை தூய்மை செய்கிறது" + }, + "manage_friend_list": { + "name": "நண்பர் பட்டியலை நிர்வகிக்கவும்", + "description": "காப்புப் பிரதி எடுக்கும்போது உங்கள் நண்பர்கள் பட்டியலை இறக்குமதி/ஏற்றுமதி செய்யுங்கள்" + }, + "export_chat_messages": { + "name": "அரட்டை செய்திகளை ஏற்றுமதி செய்யுங்கள்", + "description": "உரையாடல் செய்திகளை JSON/HTML/TXT கோப்பில் ஏற்றுமதி செய்கிறது" + }, + "export_memories": { + "name": "நினைவுகள் ஏற்றுமதி", + "description": "நினைவுகளை ஒரு சிப் கோப்பில் ஏற்றுமதி செய்கிறது" + }, + "bulk_messaging_action": { + "name": "மொத்த செய்தியிடல் நடவடிக்கை", + "description": "நண்பர்களை நீக்குவது அல்லது உரையாடல்களை வெகுசன நீக்குதல் போன்ற செயல்பாடுகளைச் செய்கிறது" + }, + "regen_mappings": { + "name": "மேப்பிங்சை மீளுருவாக்கம் செய்யுங்கள்", + "description": "கைமுறையாக மேப்பிங்சை மீண்டும் உருவாக்கவும்" + }, + "change_language": { + "name": "மொழியை மாற்றவும்", + "description": "ச்னாபன்ஆன்சின் மொழியை மாற்றவும்" + }, + "security_features": { + "name": "பாதுகாப்பு நற்பொருத்தங்கள்", + "description": "பாதுகாப்பு அம்சங்களின் விருப்பங்களை மாற்றவும்" + }, + "file_imports": { + "name": "கோப்பு இறக்குமதிகள்", + "description": "ச்னாப்சாட்டில் பயன்படுத்த கோப்புகளை இறக்குமதி செய்யுங்கள்" + }, + "friend_tracker": { + "name": "நண்பர் டிராக்கர்", + "description": "ச்னாப்சாட்டில் உங்கள் நண்பர்களைக் கண்காணிக்கவும்" + }, + "logger_history": { + "name": "லாகர் வரலாறு", + "description": "உள்நுழைந்த செய்திகளின் வரலாற்றைக் காண்க" + }, + "theming": { + "name": "தீமிங்", + "description": "ச்னாப்சாட்டின் தோற்றத்தையும் உணர்வையும் தனிப்பயனாக்கவும்" + } + }, + "friend_menu_option": { + "mark_snaps_as_seen": "காணப்பட்டபடி குறி", + "mark_stories_as_seen_locally": "உள்நாட்டில் காணப்பட்ட கதைகளை குறிக்கவும்", + "preview": "முன்னோட்டம்", + "stealth_mode": "திருட்டுத்தனமான பயன்முறை", + "auto_download_blacklist": "தானாக பதிவிறக்க தடுப்புப்பட்டியல்", + "anti_auto_save": "ஆன்டி ஆட்டோ சேமிப்பு" + }, + "content_type": { + "CHAT": "அரட்டை", + "SNAP": "ச்னாப்", + "EXTERNAL_MEDIA": "வெளிப்புற ஊடகங்கள்", + "NOTE": "ஆடியோ குறிப்பு", + "STICKER": "ச்டிக்கர்", + "STATUS": "நிலை", + "SHARE": "பங்கு", + "LOCATION": "இடம்", + "STATUS_SAVE_TO_CAMERA_ROLL": "கேமரா ரோலில் சேமிக்கப்பட்டது", + "STATUS_CONVERSATION_CAPTURE_SCREENSHOT": "திரைக்காட்சி", + "STATUS_CONVERSATION_CAPTURE_RECORD": "திரை பதிவு", + "STATUS_CALL_MISSED_VIDEO": "வீடியோ அழைப்பு தவறவிட்டது", + "STATUS_CALL_MISSED_AUDIO": "தவறவிட்ட ஆடியோ அழைப்பு", + "CREATIVE_TOOL_ITEM": "படைப்பு கருவி உருப்படி", + "LIVE_LOCATION_SHARE": "நேரடி இருப்பிட பங்கு", + "FAMILY_CENTER_INVITE": "குடும்ப மைய அழைப்பு", + "FAMILY_CENTER_ACCEPT": "குடும்ப நடுவண் ஏற்றுக்கொள்கிறது", + "FAMILY_CENTER_LEAVE": "குடும்ப மைய விடுப்பு", + "STATUS_PLUS_GIFT": "நிலை மற்றும் பரிசு", + "TINY_SNAP": "சிறிய ச்னாப்", + "STATUS_COUNTDOWN": "கவுண்டவுன்", + "MAP_REACTION": "வரைபட எதிர்வினை" + }, + "media_download_source": { + "none": "எதுவுமில்லை", + "pending": "நிலுவையில் உள்ளது", + "chat_media": "சராசரி அரட்டை", + "story": "கதை", + "public_story": "பொது கதை", + "spotlight": "ச்பாட்லைட்", + "profile_picture": "சுயவிவர படம்", + "story_logger": "கதை லாகர்", + "message_logger": "செய்தி லாகர்", + "merged": "ஒன்றிணைந்தது", + "voice_call": "குரல் அழைப்பு" + }, + "opera_context_menu": { + "expires_at": "{date} இல் காலாவதியாகிறது", + "media_size": "ஊடக அளவு: {size}", + "media_duration": "மீடியா காலம்: {duration} எம்.எச்", + "show_debug_info": "பிழைத்திருத்த தகவலைக் காட்டு", + "download": "மீடியாவைப் பதிவிறக்கவும்", + "sent_at": "{date} இல் அனுப்பப்பட்டது", + "created_at": "{date} இல் உருவாக்கப்பட்டது" + }, + "modal_option": { + "profile_info": "சுயவிவர செய்தி", + "close": "மூடு" + }, + "gallery_media_send_override": { + "multiple_media_toast": "நீங்கள் ஒரு நேரத்தில் ஒரு ஊடகத்தை மட்டுமே அனுப்ப முடியும்" + }, + "mark_as_seen": { + "no_unseen_snaps_toast": "காணப்படாத புகைப்படங்கள் எதுவும் கிடைக்கவில்லை!", + "seen_toast": "பார்த்தபடி குறிக்கப்பட்டுள்ளது!", + "unseen_toast": "காணப்படாதது எனக் குறிக்கப்பட்டுள்ளது!", + "already_seen_toast": "ஏற்கனவே பார்த்தபடி குறிக்கப்பட்டுள்ளது!", + "already_unseen_toast": "ஏற்கனவே காணப்படாததாக குறிக்கப்பட்டுள்ளது!" + }, + "conversation_preview": { + "streak_expiration": "{day} நாட்கள் {hour} மணிநேரம் {minute} நிமிடங்களில் காலாவதியாகிறது", + "total_messages": "மொத்தம் அனுப்பப்பட்ட/பெறப்பட்ட செய்திகள்: {count}", + "title": "முன்னோட்டம்", + "unknown_user": "தெரியாத பயனர்", + "no_messages": "செய்திகள் எதுவும் கிடைக்கவில்லை!" + }, + "profile_info": { + "title": "சுயவிவர செய்தி", + "first_created_username": "முதலில் பயனர்பெயர் உருவாக்கப்பட்டது", + "mutable_username": "மாற்றக்கூடிய பயனர்பெயர்", + "display_name": "காட்சி பெயர்", + "added_date": "சேர்க்கப்பட்ட தேதி", + "birthday": "பிறந்த நாள்: {month} {day}", + "hidden_birthday": "பிறந்த நாள்: மறைக்கப்பட்டுள்ளது", + "friendship": "நட்பு", + "add_source": "மூலத்தைச் சேர்க்கவும்", + "snapchat_plus": "ச்னாப்சாட் பிளச்", + "snapchat_plus_state": { + "subscribed": "சந்தா", + "not_subscribed": "குழுசேரவில்லை" + } + }, + "friendship_link_type": { + "mutual": "பரச்பர", + "outgoing": "வெளிச்செல்லும்", + "blocked": "தடுக்கப்பட்டது", + "deleted": "நீக்கப்பட்டது", + "following": "பின்வருமாறு", + "suggested": "பரிந்துரைக்கப்பட்டது", + "incoming": "உள்வரும்", + "incoming_follower": "உள்வரும் பின்தொடர்பவர்" + }, + "bulk_messaging_action": { + "progress_status": "{மொத்தம் {குறியீட்டு செயலாக்கம்", + "selection_dialog_continue_button": "தொடரவும்", + "confirmation_dialog": { + "title": "நீங்கள் உறுதியாக இருக்கிறீர்களா?", + "message": "இது தேர்ந்தெடுக்கப்பட்ட அனைத்து நண்பர்களையும் பாதிக்கும். இந்த செயலை செயல்தவிர்க்க முடியாது." + }, + "actions": { + "remove_friends": "நண்பர்களை அகற்று", + "clear_conversations": "உரையாடல்களை அழிக்கவும்" + }, + "choose_action_title": "ஒரு செயலைத் தேர்வுசெய்க" + }, + "chat_export": { + "exporter_dialog": { + "select_conversations_title": "உரையாடல்களைத் தேர்ந்தெடுக்கவும்", + "text_field_selection": "{amount} தேர்ந்தெடுக்கப்பட்டது", + "text_field_selection_all": "அனைத்தும்", + "export_file_format_title": "கோப்பு வடிவத்தை ஏற்றுமதி செய்யுங்கள்", + "message_type_filter_title": "வகைப்படி செய்திகளை வடிகட்டவும்", + "amount_of_messages_title": "செய்திகளின் அளவு (அனைவருக்கும் காலியாக விடுங்கள்)", + "download_medias_title": "மீடியாசை பதிவிறக்கவும்" + }, + "dialog_negative_button": "ரத்துசெய்", + "dialog_positive_button": "ஏற்றுமதி", + "exported_to": "{path} க்கு ஏற்றுமதி செய்யப்பட்டது", + "exporting_chats": "அரட்டைகளை ஏற்றுமதி செய்கிறது ...", + "processing_chats": "செயலாக்கம் {amount} உரையாடல்கள் ...", + "export_fail": "உரையாடலை ஏற்றுமதி செய்வதில் தோல்வி {conversation}", + "writing_output": "எழுதுதல் வெளியீடு ...", + "finished": "முடிந்தது! நீங்கள் இப்போது இந்த உரையாடலை மூடலாம்.", + "no_messages_found": "செய்திகள் எதுவும் கிடைக்கவில்லை!", + "exporting_message": "ஏற்றுமதி {conversation} ..." + }, + "button": { + "ok": "சரி", + "positive": "ஆம்", + "negative": "இல்லை", + "cancel": "ரத்துசெய்", + "open": "திற", + "download": "பதிவிறக்கம்", + "send": "அனுப்பு" + }, + "better_notifications": { + "button": { + "reply": "பதில்", + "download": "பதிவிறக்கம்", + "mark_as_read": "படித்தபடி குறி" + } + }, + "profile_picture_downloader": { + "button": "சுயவிவரப் படத்தைப் பதிவிறக்கவும்", + "title": "சுயவிவரப் படம் பதிவிறக்குபவர்", + "avatar_option": "அவதார்", + "background_option": "பின்னணி" + }, + "call_start_confirmation": { + "dialog_title": "அழைப்பைத் தொடங்குங்கள்", + "dialog_message": "நீங்கள் நிச்சயமாக அழைப்பைத் தொடங்க விரும்புகிறீர்களா?" + }, + "half_swipe_notifier": { + "notification_channel_name": "அரை ச்வைப்", + "notification_content_dm": "{friend} உங்கள் அரட்டையில் {duration} விநாடிகளுக்கு அரை ச்வைப் செய்யப்பட்டது", + "notification_content_group": "{friend} {காலத்திற்கு {குழுவில் {group} காலத்திற்கு} வினாடிகளுக்கு" + }, + "download_processor": { + "attachment_type": { + "snap": "ச்னாப்", + "sticker": "ச்டிக்கர்", + "gif": "Gif", + "external_media": "வெளிப்புற ஊடகங்கள்", + "note": "குறிப்பு", + "original_story": "அசல் கதை" + }, + "select_attachments_title": "இணைப்புகளைத் தேர்ந்தெடுக்கவும்", + "download_started_toast": "பதிவிறக்கம் தொடங்கியது", + "unsupported_content_type_toast": "ஆதரிக்கப்படாத உள்ளடக்க வகை!", + "failed_no_longer_available_toast": "மீடியா இனி கிடைக்காது", + "no_attachments_toast": "இணைப்புகள் எதுவும் கிடைக்கவில்லை!", + "already_queued_toast": "மீடியா ஏற்கனவே வரிசையில்!", + "already_downloaded_toast": "மீடியா ஏற்கனவே பதிவிறக்கம் செய்யப்பட்டுள்ளது!", + "content_saved_toast": "சேமிக்கப்பட்டது!", + "download_toast": "பதிவிறக்கம் {path} ...", + "processing_toast": "செயலாக்கம் {path} ...", + "failed_generic_toast": "பதிவிறக்கம் செய்யத் தவறிவிட்டது", + "failed_to_create_preview_toast": "முன்னோட்டத்தை உருவாக்கத் தவறிவிட்டது", + "failed_processing_toast": "தோல்வியுற்ற செயலாக்கம் {error}", + "failed_gallery_toast": "கேலரிக்கு சேமிப்பு தோல்வியுற்றது {error}", + "dash_dialog": { + "title": "டாச் மீடியாவைப் பதிவிறக்கவும்", + "download_all": "அனைத்தையும் பதிவிறக்கவும்", + "segment_text": "பிரிவு {from} - {to}" + }, + "dash_no_chapter": "அத்தியாயம் எதுவும் கிடைக்கவில்லை" + }, + "streaks_reminder": { + "notification_title": "கோடுகள்", + "notification_text": "{friend} மணிநேரங்களில் {hoursLeft} உடன் உங்கள் ச்ட்ரீக்கை இழப்பீர்கள்" + }, + "biometric_auth": { + "title": "ச்னாப்சாட்டை திறக்கவும்", + "subtitle": "ச்னாப்சாட்டை திறக்க தயவுசெய்து அங்கீகரிக்கவும்", + "unlock_button": "திறக்க" + }, + "end_to_end_encryption": { + "toolbox": { + "no_shared_key": "இந்த நண்பருடன் உங்களிடம் இன்னும் பகிரப்பட்ட மறைபொருள் இல்லை. புதிய ஒன்றைத் தொடங்க கீழே சொடுக்கு செய்க.", + "shared_key_fingerprint": "உங்கள் கைரேகை:\n\n {fingerprint}\n\n இது உங்கள் நண்பரின் கைரேகைக்கு பொருந்துமா என்பதை சரிபார்க்கவும்!", + "initiate_exchange_button": "முக்கிய பரிமாற்றத்தைத் தொடங்கவும்" + }, + "confirmation_dialogs": { + "title": "இறுதி-இறுதி குறியாக்கம்", + "confirmation_1": "எச்சரிக்கை: இது உங்கள் இருக்கும் விசையை மேலெழுதும். இந்த நண்பரிடமிருந்து மறைகுறியாக்கப்பட்ட அனைத்து செய்திகளுக்கும் அணுகலை நீங்கள் இழக்க நேரிடும். நீங்கள் தொடர விரும்புகிறீர்களா?", + "confirmation_2": "நீங்கள் தொடர விரும்புகிறீர்கள் என்பதில் உறுதியாக இருக்கிறீர்களா? பின்வாங்க இது உங்களுக்கு கடைசி வாய்ப்பு." + }, + "unencrypted_conversation_send_failure_toast": "மறைகுறியாக்கப்பட்ட மற்றும் மறைகுறியாக்கப்பட்ட உரையாடல்களுக்கு நீங்கள் மறைகுறியாக்கப்பட்ட உள்ளடக்கத்தை அனுப்ப முடியாது!", + "native_hooks_send_failure_toast": "அனுப்பத் தவறிவிட்டது! அமைப்புகளில் சொந்த கொக்கிகள் இயக்கவும்.", + "no_participants_to_encrypt_toast": "செய்திகளை குறியாக்க இந்த உரையாடலில் உங்களுக்கு நண்பர்கள் யாரும் இல்லை!", + "encryption_failed_toast": "செய்தியை குறியாக்கத் தவறிவிட்டது! மேலும் விவரங்களுக்கு LogCat ஐ சரிபார்க்கவும்.", + "accept_public_key_success_toast": "பொது விசை வெற்றிகரமாக ஏற்றுக்கொள்ளப்பட்டது!", + "accept_secret_key_success_toast": "முடிந்தது! இந்த நண்பருடன் மறைகுறியாக்கப்பட்ட செய்திகளை இப்போது அனுப்பலாம் மற்றும் பெறலாம்.", + "accept_public_key_failure_toast": "பொது விசையை ஏற்கத் தவறிவிட்டது", + "accept_secret_key_failure_toast": "ரகசிய விசையை ஏற்கத் தவறிவிட்டது", + "accept_secret_button": "ரகசியத்தை ஏற்றுக்கொள்", + "outgoing_secret_message": "முக்கிய பரிமாற்ற பதில்", + "accept_public_key_button": "பொது விசையை ஏற்றுக்கொள்ளுங்கள்", + "outgoing_pk_message": "முக்கிய பரிமாற்ற கோரிக்கை", + "incoming_pk_message": "நீங்கள் ஒரு பொது முக்கிய கோரிக்கையைப் பெற்றுள்ளீர்கள். அதை ஏற்க கீழே சொடுக்கு செய்க.", + "incoming_secret_message": "உங்கள் நண்பர் உங்கள் பொது விசையை ஏற்றுக்கொண்டார். ரகசியத்தை ஏற்க கீழே சொடுக்கு செய்க." + }, + "auto_open_snaps": { + "title": "ஆட்டோ திறந்த புகைப்படங்கள்", + "notification_content": "{count} புகைப்படங்கள் திறக்கப்பட்டன" + }, + "friend_mutation_observer": { + "notification_channel_name": "நண்பர் பிறழ்வு பார்வையாளர்", + "friend_removed": "{பயனர்பெயர் you உங்களை ஒரு நண்பராக நீக்கிவிட்டது", + "birthday_removed": "{பயனர்பெயர் அவர்களின் பிறந்தநாளை ({username}) அகற்றிவிட்டது", + "birthday_added": "{username} அவர்களின் பிறந்தநாளைச் சேர்த்தது ({birthday})", + "birthday_changed": "{username} அவர்களின் பிறந்தநாளை {ஓல்டிபிர்தே இருந்து இலிருந்து {oldBirthday} ஆக மாற்றியுள்ளது", + "bitmoji_selfie_changed": "{username} அவர்களின் பிட்மோசி செல்பியை மாற்றியுள்ளது", + "bitmoji_avatar_changed": "{username} அவர்களின் பிட்மோசி அவதாரத்தை மாற்றியுள்ளது", + "bitmoji_background_changed": "{username} அவர்களின் பிட்மோசி பின்னணியை மாற்றியுள்ளது", + "bitmoji_scene_changed": "{username} அவர்களின் பிட்மோசி காட்சியை மாற்றியுள்ளது" + }, + "material3_strings": { + "date_range_picker_end_headline": "பெறுநர்", + "date_range_picker_title": "தேதி வரம்பைத் தேர்ந்தெடுக்கவும்", + "date_picker_switch_to_calendar_mode": "நாட்காட்டி", + "date_picker_switch_to_input_mode": "உள்ளீடு", + "date_range_picker_scroll_to_previous_month": "முந்தைய மாதம்", + "date_range_picker_scroll_to_next_month": "அடுத்த மாதம்", + "date_picker_today_description": "இன்று", + "date_range_picker_day_in_range": "தேர்ந்தெடுக்கப்பட்டது", + "date_input_invalid_for_pattern": "தவறான தேதி", + "date_input_invalid_year_range": "தவறான ஆண்டு", + "date_input_invalid_not_allowed": "தவறான தேதி", + "date_range_input_invalid_range_input": "தவறான தேதி வரம்பு", + "date_range_picker_start_headline": "இருந்து" + }, + "theming_attributes": { + "sigColorChatChat": "முக்கிய நண்பர் உரை நிறத்திற்கு உணவளிக்கவும்", + "sigColorTextPrimary": "முக்கிய உரை நிறம்", + "sigColorBackgroundSurface": "பின்னணி மேற்பரப்பு நிறம்", + "sigColorChatPendingSending": "இரண்டாம் நிலை நண்பர் உரை நிறத்திற்கு உணவளிக்கவும்", + "sigColorChatSnapWithSound": "ஒலி உரை நிறத்துடன் புகைப்படங்கள்", + "sigColorChatSnapWithoutSound": "ஒலி உரை நிறம் இல்லாமல் ஒடிக்கிறது", + "actionSheetDescriptionTextColor": "செயல் பட்டியல் விளக்கம் உரை நிறம்", + "sigColorBackgroundMain": "பின்னணி நிறம்", + "actionSheetBackgroundDrawable": "செயல் பட்டியல் பின்னணி நிறம்", + "actionSheetRoundedBackgroundDrawable": "செயல் பட்டியல் சுற்று பின்னணி நிறம்", + "sigColorIconPrimary": "செயல் பட்டியல் படவுரு நிறம்", + "sigExceptionColorCameraGridLines": "கேமரா கிரிட்லைன்ச் நிறம்", + "listDivider": "வகுப்பி வண்ணத்தை பட்டியலிடுங்கள்", + "sigColorIconSecondary": "இரண்டாம் நிலை படவுரு நிறம்", + "itemShapeFillColor": "உருப்படி வடிவம் நிரப்பு நிறம்", + "ringStartColor": "ரிங் ச்டார்ட் கலர்", + "sigColorLayoutPlaceholder": "தளவமைப்பு பிளேச்ஓல்டர் நிறம்", + "scButtonColor": "ச்னாப்சாட் பொத்தான் நிறம்", + "recipientPillBackgroundDrawable": "பெறுநர் மாத்திரை பின்னணி", + "boxBackgroundColor": "பெட்டி பின்னணி நிறம்", + "editTextColor": "உரை நிறத்தைத் திருத்தவும்", + "chipBackgroundColor": "சில்லு பின்னணி நிறம்", + "recipientInputStyle": "பெறுநர் உள்ளீட்டு நடை", + "rangeFillColor": "வரம்பு நிரப்பு நிறம்", + "pstsIndicatorColor": "பிஎச்டிஎச் காட்டி நிறம்", + "pstsTabBackground": "பிஎச்டிஎச் தாவல் பின்னணி", + "pstsDividerColor": "PSTS வகுப்பி நிறம்", + "statusBarBackground": "நிலை பட்டி பின்னணி நிறம்", + "strokeColor": "பக்கவாதம் நிறம்", + "tabTextColor": "தாவல் உரை நிறம்", + "statusBarForeground": "நிலை பட்டி முன்புற நிறம்", + "storyReplayViewRingColor": "கதை மறுபதிப்பு காட்சி வளைய நிறம்", + "sigColorButtonPrimary": "முதன்மை பொத்தான் நிறம்", + "sigColorStoryRingFriendsFeedStoryRing": "கதை வளைய நண்பர்கள் கதை வளைய நிறத்தை உண்பார்கள்", + "sigColorBaseAppYellow": "அடிப்படை பயன்பாடு மஞ்சள் நிறம்", + "sigColorBackgroundSurfaceTranslucent": "கசியும் பின்னணி மேற்பரப்பு நிறம்", + "sigColorStoryRingDiscoverTabThumbnailStoryRing": "ச்டோரி ரிங் டிச்கவர் தாவல் சிறுபடம் கதை மோதிரம் நிறம்", + "listBackgroundDrawable": "உரையாடல் பட்டியல் பின்னணி", + "sigColorChatConversationsLine": "உரையாடல்கள் வரி நிறம்", + "ringColor": "வளைய நிறம்" + }, + "send_override_dialog": { + "title": "மீடியாவை {type அச் ஆக அனுப்பவும்", + "duration": "காலம்: {duration}", + "saveable_snap_hint": "அரட்டையில் ச்னாப் சேமிக்கக்கூடியதாக ஆக்குங்கள்", + "unlimited_duration": "வரம்பற்றது" + }, + "chat_action_menu": { + "preview_button": "முன்னோட்டம்", + "download_button": "பதிவிறக்கம்", + "delete_logged_message_button": "உள்நுழைந்த செய்தியை நீக்கு", + "show_chat_edit_history": "அரட்டை திருத்து வரலாற்றைக் காட்டு", + "convert_message": "செய்தியை மாற்றவும்", + "edit_message": "செய்தியைத் திருத்தவும்" + } +} diff --git a/common/src/main/assets/lang/te.json b/common/src/main/assets/lang/te.json deleted file mode 100644 index f4933438..00000000 --- a/common/src/main/assets/lang/te.json +++ /dev/null @@ -1,2022 +0,0 @@ -{ - "setup": { - "dialogs": { - "select_language": "భాషను ఎంచుకోండి", - "save_folder": "పర్ఫెక్ట్స్నాప్‌కు స్నాప్‌చాట్ నుండి మీడియాను డౌన్‌లోడ్ చేయడానికి మరియు సేవ్ చేయడానికి నిల్వ అనుమతులు అవసరం.\nదయచేసి మీడియాకు డౌన్‌లోడ్ చేయవలసిన స్థానాన్ని ఎంచుకోండి.", - "select_save_folder_button": "ఫోల్డర్ ఎంచుకోండి" - }, - "mappings": { - "dialog": "మ్యాపింగ్స్‌ను రూపొందించడం, దీనికి కొంత సమయం పట్టవచ్చు ...", - "generate_failure_no_snapchat": "పర్ఫెక్ట్స్నాప్ స్నాప్‌చాట్‌ను గుర్తించలేకపోయింది, దయచేసి స్నాప్‌చాట్‌ను మళ్లీ ఇన్‌స్టాల్ చేయడానికి ప్రయత్నించండి.", - "generate_failure": "మ్యాపింగ్లను రూపొందించడానికి ప్రయత్నిస్తున్నప్పుడు లోపం సంభవించింది, దయచేసి మళ్ళీ ప్రయత్నించండి." - }, - "permissions": { - "dialog": "కొనసాగించడానికి మీరు ఈ క్రింది అవసరాలకు సరిపోయేలా చేయాలి:", - "notification_access": "నోటిఫికేషన్ యాక్సెస్", - "battery_optimization": "బ్యాటరీ ఆప్టిమైజేషన్", - "display_over_other_apps": "ఇతర అనువర్తనాలపై ప్రదర్శించండి", - "request_button": "అభ్యర్థన" - } - }, - "scopes": { - "friend": "స్నేహితుడు", - "group": "సమూహం" - }, - "manager": { - "routes": { - "tasks": "పనులు", - "features": "లక్షణాలు", - "manage_rule_feature": "నియమం లక్షణాన్ని నిర్వహించండి", - "home": "హోమ్", - "home_settings": "సెట్టింగులు", - "home_logs": "లాగ్స్", - "logger_history": "లాగర్ చరిత్ర", - "logged_stories": "లాగిన్ చేసిన కథలు", - "friend_tracker": "ఫ్రెండ్ ట్రాకర్", - "edit_rule": "నియమాన్ని సవరించండి", - "file_imports": "ఫైల్ దిగుమతులు", - "manage_repos": "రిపోజిటరీలను నిర్వహించండి", - "social": "సామాజిక", - "manage_scope": "పరిధిని నిర్వహించండి", - "messaging_preview": "ప్రివ్యూ", - "scripts": "స్క్రిప్ట్స్", - "better_location": "మంచి స్థానం" - }, - "sections": { - "home": { - "version_title": "v{versionName} · ఎటర్నల్ చేత ఫోర్క్ చేయబడింది", - "update_title": "పర్ఫెక్ట్స్నాప్ నవీకరణ", - "update_content": "వెర్షన్ {version} అందుబాటులో ఉంది!", - "update_button": "డౌన్‌లోడ్", - "debug_build_summary_title": "మీరు పర్ఫెక్ట్స్నాప్ యొక్క డీబగ్ బిల్డ్ నడుపుతున్నారు", - "debug_build_summary_content": "వెర్షన్ {versionName} ({versionCode})", - "debug_build_summary_date": "బిల్డ్ తేదీ: {date} ({days} రోజుల క్రితం)", - "quick_actions_title": "శీఘ్ర చర్యలు", - "download_icon_description": "డౌన్‌లోడ్", - "completed_icon_description": "పూర్తయింది", - "failed_icon_description": "విఫలమైంది", - "manage_quick_actions_description": "శీఘ్ర చర్యలను నిర్వహించండి", - "quick_actions_icon_description": "శీఘ్ర చర్యలు", - "add_quick_action_description": "శీఘ్ర చర్యను జోడించండి" - }, - "home_logs": { - "no_logs_hint": "లాగ్‌లు అందుబాటులో లేవు", - "clear_logs_button": "లాగ్‌లు క్లియర్", - "export_logs_button": "ఎగుమతి లాగ్‌లు", - "saving_logs_toast": "లాగ్‌లను సేవ్ చేస్తోంది, దీనికి కొంత సమయం పట్టవచ్చు ...", - "saved_logs_success_toast": "లాగ్‌లు విజయవంతంగా సేవ్ చేయబడ్డాయి", - "saved_logs_failure_toast": "లాగ్‌లను సేవ్ చేయడంలో విఫలమైంది" - }, - "home_settings": { - "actions_title": "చర్యలు", - "message_logger_title": "సందేశ లాగర్", - "debug_title": "డీబగ్", - "success_toast": "పూర్తయింది!", - "message_logger_summary": "{messageCount} సందేశాలు\n{storyCount} కథలు", - "export_button": "ఎగుమతి", - "clear_button": "క్లియర్", - "view_logger_history_button": "లాగర్ చరిత్రను చూడండి", - "updates_title": "నవీకరణలు", - "auto_update_check": "నవీకరణల కోసం ఆటో చెక్", - "update_check_frequency": "నవీకరణ తనిఖీ ఫ్రీక్వెన్సీ", - "update_check_frequency_daily": "రోజువారీ", - "update_check_frequency_weekly": "వారానికోసారి", - "update_check_frequency_monthly": "నెలవారీ", - "theme_icon_description": "థీమ్", - "app_theme_title": "అనువర్తన థీమ్", - "theme_mode_system": "వ్యవస్థ", - "theme_mode_light": "కాంతి", - "theme_mode_dark": "చీకటి", - "ui_settings_title": "UI సెట్టింగులు", - "haptic_feedback_label": "హాప్టిక్ ఫీడ్‌బ్యాక్", - "test_mode_label": "పరీక్ష మోడ్ (డీబగ్గింగ్ కోసం మాత్రమే)", - "disable_feature_loading_label": "ఫీచర్ లోడింగ్‌ను నిలిపివేయండి", - "disable_auto_mapper_label": "ఆటో మాపర్‌ను నిలిపివేయండి", - "disable_bypass_indicator_label": "బైపాస్ స్థితి సూచికను నిలిపివేయండి", - "update_notification_channel_name": "పర్ఫెక్ట్స్నాప్ నవీకరణలు", - "update_notification_channel_description": "పర్ఫెక్ట్స్నాప్ నవీకరణల కోసం నోటిఫికేషన్‌లు", - "update_notification_title": "పర్ఫెక్ట్స్నాప్ నవీకరణ అందుబాటులో ఉంది", - "update_notification_text": "వెర్షన్ {version} ఇప్పుడు అందుబాటులో ఉంది.", - "export_database_failed_toast": "డేటాబేస్ ఎగుమతి చేయడంలో విఫలమైంది! {message}", - "clear_messages_failed_toast": "సందేశాలను క్లియర్ చేయడంలో విఫలమైంది! {message}", - "clear_file_failed_toast": "ఫైల్‌ను క్లియర్ చేయడంలో విఫలమైంది! {message}", - "debug_file_config": "కాన్ఫిగరేషన్", - "debug_file_mappings": "మ్యాపింగ్స్", - "debug_file_message_logger": "సందేశ లాగర్", - "debug_file_pinned_best_friend": "పిన్ చేసిన బెస్ట్ ఫ్రెండ్", - "debug_file_native_sig_cache": "స్థానిక సంతకం కాష్" - }, - "tasks": { - "no_tasks": "పనులు లేవు", - "merge_button": "విలీనం", - "failed_to_open_file": "ఫైల్ తెరవడంలో విఫలమైంది", - "merge_files_toast": "{count} ఫైల్‌లను విలీనం చేయడం", - "remove_selected_tasks_title": "మీరు ఎంచుకున్న పనులను తొలగించాలనుకుంటున్నారా?", - "remove_all_tasks_title": "మీరు ఖచ్చితంగా అన్ని పనులను తొలగించాలనుకుంటున్నారా?", - "delete_files_option": "ఫైళ్ళను కూడా తొలగించండి", - "remove_selected_tasks_confirm": "{count} పనులను తొలగించాలా?", - "remove_all_tasks_confirm": "అన్ని పనులను తొలగించాలా?", - "clear_tasks_description": "స్పష్టమైన పనులు", - "file_not_found_icon_description": "ఫైల్ కనుగొనబడలేదు", - "image_icon_description": "చిత్రం", - "video_icon_description": "వీడియో", - "audio_icon_description": "ఆడియో", - "file_icon_description": "ఫైల్", - "download_icon_description": "డౌన్‌లోడ్", - "chat_action_icon_description": "చాట్ చర్య", - "cancel_icon_description": "రద్దు చేయండి", - "success_icon_description": "విజయం", - "failure_icon_description": "వైఫల్యం", - "cancelled_icon_description": "రద్దు చేయబడింది", - "task_status_failure": "వైఫల్యం", - "task_status_cancelled": "రద్దు చేయబడింది" - }, - "features": { - "disabled": "నిలిపివేయబడింది", - "export_option": "ఎగుమతి", - "import_option": "దిగుమతి", - "reset_option": "రీసెట్", - "config_export_success_toast": "కాన్ఫిగర్ విజయవంతంగా ఎగుమతి చేయబడింది", - "config_import_success_toast": "కాన్ఫిగర్ విజయవంతంగా దిగుమతి చేయబడింది", - "config_import_failure_toast": "కాన్ఫిగర్ {error} దిగుమతి చేయడంలో విఫలమైంది", - "config_export_failure_toast": "కాన్ఫిగర్ {error} ఎగుమతి చేయడంలో విఫలమైంది", - "saved_config_snackbar": "కాన్ఫిగర్ సేవ్ చేయబడింది", - "older_required": "ఈ లక్షణానికి స్నాప్‌చాట్ v{version} లేదా అంతకంటే పాతది సరిగ్గా పనిచేయడానికి అవసరం", - "newer_required": "ఈ లక్షణానికి స్నాప్‌చాట్ v{version} లేదా కొత్తది సరిగ్గా పనిచేయడానికి అవసరం", - "search_button": "శోధన" - }, - "manage_rule_feature": { - "disable_state_option": "నిలిపివేయబడింది", - "disable_state_subtext": "స్నేహితులు/సమూహాలు ఏవీ ప్రభావితం కావు", - "whitelist_state_option": "తప్ప ఎవరూ...", - "whitelist_state_subtext": "ఈ నియమం ద్వారా {count} స్నేహితులు/సమూహాలు మాత్రమే ప్రభావితమవుతాయి", - "whitelist_state_button": "అనుమతించబడిన స్నేహితులు/సమూహాలను ఎంచుకోండి", - "blacklist_state_option": "తప్ప అందరూ...", - "blacklist_state_subtext": "{count} మినహా ప్రతి ఒక్కరూ ఈ నియమం ద్వారా స్నేహితులు/సమూహాలు ప్రభావితమవుతారు", - "blacklist_state_button": "మినహాయించబడిన స్నేహితులు/సమూహాలను ఎంచుకోండి", - "clear_list_button": "స్నేహితులు/సమూహాల జాబితాను క్లియర్ చేయండి", - "dialog_clear_confirmation_text": "మీరు ఖచ్చితంగా జాబితాను క్లియర్ చేయాలనుకుంటున్నారా?" - }, - "social": { - "friends_tab": "స్నేహితులు", - "groups_tab": "గుంపులు", - "empty_hint": "(ఖాళీ)", - "streaks_expiration_short": "{hours}h" - }, - "manage_scope": { - "logged_stories_button": "లాగిన్ చేసిన కథలను చూపించు", - "e2ee_title": "ఎండ్-టు-ఎండ్ ఎన్క్రిప్షన్", - "rules_title": "నియమాలు", - "participants_text": "{count} పాల్గొనేవారు", - "not_found": "కనుగొనబడలేదు", - "streaks_title": "స్ట్రీక్స్", - "streaks_length_text": "పొడవు: {length}", - "streaks_expiration_text": "{eta} లో ముగుస్తుంది", - "streaks_expiration_text_expired": "గడువు ముగిసింది", - "reminder_button": "రిమైండర్ సెట్ చేయండి", - "delete_scope_confirm_dialog_title": "మీరు ఖచ్చితంగా {scope} ను తొలగించాలనుకుంటున్నారా?", - "notes_placeholder": "గమనికను జోడించడానికి క్లిక్ చేయండి", - "invalid_key_size_32_bytes": "చెల్లని కీ పరిమాణం (32 బైట్లు ఉండాలి)", - "successfully_imported_key": "విజయవంతంగా దిగుమతి చేసుకున్న కీ", - "failed_to_import_key": "కీని దిగుమతి చేయడంలో విఫలమైంది: {message}", - "export_base64_button": "ఎగుమతి బేస్ 64", - "import_base64_button": "దిగుమతి బేస్ 64" - }, - "logged_stories": { - "story_failed_to_load": "లోడ్ చేయడంలో విఫలమైంది", - "no_stories": "కథలు కనుగొనబడలేదు", - "save_from_cache_button": "కాష్ నుండి సేవ్ చేయండి", - "downloaded_to_path": "{path} కు డౌన్‌లోడ్ చేయబడింది", - "download_failed": "డౌన్‌లోడ్ విఫలమైంది: {message}", - "posted_at": "{date} వద్ద పోస్ట్ చేయబడింది", - "created_at": "{date} వద్ద సృష్టించబడింది", - "failed_to_open_file": "ఫైల్‌ను తెరవడంలో విఫలమైంది. మరింత సమాచారం కోసం లాగ్‌లను తనిఖీ చేయండి", - "failed_to_get_file": "ఫైల్ పొందడంలో విఫలమైంది" - }, - "messaging_preview": { - "processed_messages_toast": "ప్రాసెస్ చేయబడిన {count} సందేశాలు", - "processed_messages_text": "ప్రాసెస్ చేయబడిన {count} సందేశాలు", - "close_button_description": "మూసివేయండి", - "bridge_connection_failed": "వంతెనకు కనెక్ట్ అవ్వడంలో విఫలమైంది. స్నాప్‌చాట్ నేపథ్యంలో నడుస్తుందని నిర్ధారించుకోండి", - "bridge_init_failed": "మెసేజింగ్ వంతెనను ప్రారంభించడంలో విఫలమైంది. స్నాప్‌చాట్ నేపథ్యంలో నడుస్తుందని నిర్ధారించుకోండి", - "message_fetch_failed": "సందేశాలను పొందడంలో విఫలమైంది", - "no_message_hint": "సందేశం లేదు", - "save_selection_option": "ఎంపికను సేవ్ చేయండి", - "save_all_option": "అన్నీ సేవ్ చేయండి", - "unsave_selection_option": "ఎంపికను అన్సేవ్ చేయండి", - "unsave_all_option": "అన్నింటినీ అన్సేవ్ చేయండి", - "mark_selection_as_seen_option": "చూసినట్లు ఎంచుకున్న స్నాప్‌ను గుర్తించండి", - "mark_all_as_seen_option": "చూసినట్లుగా అన్ని స్నాప్‌లను గుర్తించండి", - "delete_selection_option": "ఎంపికను తొలగించండి", - "delete_all_option": "అన్నీ తొలగించండి" - }, - "logger_history": { - "download_started_toast": "డౌన్‌లోడ్ ప్రారంభమైంది!", - "download_success_toast": "{path} కు డౌన్‌లోడ్ చేయబడింది", - "download_failed_toast": "{message} డౌన్‌లోడ్ చేయడంలో విఫలమైంది", - "edited_at_text": "{message} ({date} వద్ద సవరించబడింది)", - "download_button": "డౌన్‌లోడ్", - "select_conversation_placeholder": "సంభాషణను ఎంచుకోండి", - "close_button_description": "దగ్గరగా", - "search_button_description": "శోధన", - "list_friend_format": "స్నేహితుడు {name}", - "list_group_format": "సమూహం {name}", - "no_more_messages": "ఎక్కువ సందేశాలు లేవు", - "reverse_order_checkbox": "రివర్స్ ఆర్డర్", - "chat_attachment": "అటాచ్మెంట్ {index}", - "empty_message": "ఖాళీ చాట్ సందేశం", - "message_parse_failed": "సందేశాన్ని అన్వయించడంలో విఫలమైంది", - "unknown_sender": "తెలియని పంపినవారు", - "download_attachment_failed_toast": "అటాచ్మెంట్ డౌన్‌లోడ్ చేయడంలో విఫలమైంది", - "log_header_format": "{username} ({type}) - {date}" - }, - "file_imports": { - "import_file_button": "దిగుమతి ఫైల్", - "file_not_found": "ఫైల్ కనుగొనబడలేదు", - "file_import_failed": "ఫైల్‌ను దిగుమతి చేయడంలో విఫలమైంది: {error}", - "file_imported": "ఫైల్ విజయవంతంగా దిగుమతి చేయబడింది", - "file_delete_failed": "ఫైల్‌ను తొలగించడంలో విఫలమైంది", - "no_files_hint": "ఇక్కడ మీరు స్నాప్‌చాట్‌లో ఉపయోగం కోసం ఫైల్‌లను దిగుమతి చేసుకోవచ్చు. ఫైల్‌ను దిగుమతి చేయడానికి క్రింది బటన్‌ను నొక్కండి." - }, - "better_location": { - "spoofed_coordinates_title": "LAT {latitude}, lng {longitude}", - "save_coordinates_dialog_title": "కోఆర్డినేట్లను సేవ్ చేయండి", - "saved_name_dialog_hint": "సేవ్ చేసిన పేరు", - "latitude_dialog_hint": "అక్షాంశం", - "longitude_dialog_hint": "రేఖాంశం", - "save_dialog_button": "సేవ్", - "choose_location_button": "స్థానాన్ని ఎంచుకోండి", - "teleport_to_friend_button": "స్నేహితుడికి టెలిపోర్ట్ చేయండి", - "spoof_location_toggle": "స్పూఫ్ స్థానం", - "suspend_location_updates": "స్థాన నవీకరణలను నిలిపివేయండి", - "saved_coordinates_title": "సేవ్ చేసిన కోఆర్డినేట్లు", - "no_saved_coordinates_hint": "సేవ్ చేసిన కోఆర్డినేట్లు లేవు", - "delete_dialog_title": "సేవ్ చేసిన కోఆర్డినేట్‌ను తొలగించండి", - "delete_dialog_message": "ఈ సేవ్ చేసిన కోఆర్డినేట్‌ను మీరు తొలగించాలనుకుంటున్నారా?", - "teleport_to_friend_title": "స్నేహితుడికి టెలిపోర్ట్ చేయండి", - "search_bar": "శోధన", - "no_friends_map": "మ్యాప్‌లో స్నేహితులు లేరు", - "no_friends_found": "స్నేహితులు ఎవరూ కనుగొనబడలేదు", - "edit_location_button_description": "స్థానాన్ని సవరించండి", - "add_icon_description": "జోడించు", - "edit_icon_description": "సవరణ", - "delete_icon_description": "తొలగించు" - } - }, - "dialogs": { - "add_friend": { - "title": "స్నేహితుడు లేదా సమూహాన్ని జోడించండి", - "search_hint": "శోధన", - "fetch_error": "డేటాను పొందడంలో విఫలమైంది", - "category_groups": "గుంపులు", - "category_friends": "స్నేహితులు", - "participants_text": "{count} పాల్గొనేవారు", - "search_icon_description": "శోధన" - }, - "scripting_warning": { - "title": "హెచ్చరిక", - "content": "పర్ఫెక్ట్స్నాప్ స్క్రిప్టింగ్ సాధనాన్ని కలిగి ఉంటుంది, ఇది మీ పరికరంలో వినియోగదారు నిర్వచించిన కోడ్‌ను అమలు చేయడానికి అనుమతిస్తుంది. చాలా జాగ్రత్త వహించండి మరియు తెలిసిన, నమ్మదగిన మూలాల నుండి మాత్రమే మాడ్యూళ్ళను ఇన్స్టాల్ చేయండి. అనధికార లేదా ధృవీకరించని మాడ్యూల్స్ మీ సిస్టమ్‌కు భద్రతా నష్టాలను కలిగించవచ్చు." - }, - "reset_config": { - "title": "కాన్ఫిగర్ రీసెట్ చేయండి", - "content": "మీరు ఖచ్చితంగా కాన్ఫిగర్ రీసెట్ చేయాలనుకుంటున్నారా?", - "success_toast": "కాన్ఫిగర్ విజయవంతంగా రీసెట్ చేయబడింది" - }, - "export_config": { - "title": "సున్నితమైన డేటాను ఎగుమతి చేయాలా?", - "content": "మీరు సున్నితమైన డేటాతో కాన్ఫిగర్ ఎగుమతి చేయాలనుకుంటున్నారా? (స్థాన కోఆర్డినేట్లు మొదలైనవి)" - }, - "messaging_action": { - "title": "ప్రాసెస్ చేయడానికి కంటెంట్ రకాలను ఎంచుకోండి", - "select_all_button": "అన్నీ ఎంచుకోండి" - }, - "file_imports": { - "no_files_settings_hint": "ఫైల్స్ కనుగొనబడలేదు. మీరు ఫైల్ దిగుమతుల విభాగంలో అవసరమైన ఫైళ్ళను దిగుమతి చేసుకున్నారని నిర్ధారించుకోండి", - "settings_select_file_hint": "దిగుమతి చేసుకున్న ఫైల్‌ను ఎంచుకోండి" - }, - "quick_actions_dialog": { - "title": "శీఘ్ర చర్యలను సవరించండి", - "subtitle": "మీ శీఘ్ర చర్యలను ఎంచుకోండి మరియు పరిమాణం మార్చండి." - } - }, - "friend_tracker": { - "rules_tab": "నియమాలు", - "logs_tab": "లాగ్‌లు", - "export_dialog_title": "ఎగుమతి", - "bulk_export_button": "బల్క్ ఎగుమతి", - "individual_export_button": "వ్యక్తిగత ఎగుమతి", - "invalid_import_type_dialog_title": "చెల్లని దిగుమతి రకం", - "invalid_import_type_dialog_text": "ఎంచుకున్న ఫైల్ ఈ దిగుమతి రకానికి అనుకూలంగా లేదు. దయచేసి సరైన దిగుమతి రకాన్ని ఎంచుకోండి.", - "import_dialog_title": "దిగుమతి", - "bulk_import_button": "బల్క్ దిగుమతి", - "individual_import_button": "వ్యక్తిగత దిగుమతి", - "import_button_description": "దిగుమతి", - "export_button_description": "ఎగుమతి", - "export_button": "ఎగుమతి", - "delete_button_description": "తొలగించు", - "delete_button": "తొలగించు", - "catalog_button_description": "కేటలాగ్", - "catalog_button": "కేటలాగ్", - "add_rule_button_description": "నియమాన్ని జోడించండి", - "add_rule_button": "నియమాన్ని జోడించండి", - "no_rules_found": "నియమాలు కనుగొనబడలేదు", - "empty_rule_name": "(ఖాళీ)", - "events_suffix": "సంఘటనలు", - "scopes_suffix": "స్కోప్‌లు", - "select_rule_to_export_title": "ఎగుమతి చేయడానికి నియమాన్ని ఎంచుకోండి", - "deleted_logs_toast": "తొలగించబడినవి {count} లాగ్‌లు", - "delete_logs_dialog_title": "లాగ్‌లను తొలగించాలా?", - "deleting_logs_dialog_text": "{count} లాగ్‌లను తొలగిస్తోంది...", - "delete_logs_dialog_confirm_text": "ఇది ప్రస్తుత ఫిల్టర్ మరియు శోధన ప్రశ్న ఆధారంగా లాగ్‌లను తొలగిస్తుంది. ఈ చర్యను రద్దు చేయలేము.", - "exported_logs_toast": "లాగ్‌లు ఎగుమతి చేయబడ్డాయి!", - "export_logs_failed_toast": "లాగ్‌లను ఎగుమతి చేయడంలో విఫలమైంది. మరిన్ని వివరాల కోసం లాగ్‌క్యాట్‌ను తనిఖీ చేయండి.", - "export_logs_dialog_title": "లాగ్‌లను ఎగుమతి చేయాలా?", - "exporting_logs_dialog_text": "లాగ్‌లను ఎగుమతి చేస్తోంది...", - "export_logs_dialog_confirm_text": "ఇది ప్రస్తుత ఫిల్టర్ మరియు శోధన ప్రశ్న ఆధారంగా లాగ్‌లను ఎగుమతి చేస్తుంది.", - "export_as_button": "{type} గా ఎగుమతి చేయండి", - "filters_title": "ఫిల్టర్లు", - "search_by_label": "దీని ద్వారా శోధించండి", - "newest_first_label": "కొత్తవి మొదట", - "since_label": "నుండి", - "until_label": "వరకు", - "pick_a_date_button": "తేదీని ఎంచుకోండి", - "search_placeholder": "శోధన", - "filter_button_description": "ఫిల్టర్", - "clear_button_description": "క్లియర్", - "no_logs_found": "లాగ్‌లు కనుగొనబడలేదు", - "log_event_format": "{event} లో {conversation}", - "condition_only_inside_conversation": "నేను సంభాషణలో ఉన్నప్పుడు మాత్రమే", - "condition_only_outside_conversation": "నేను సంభాషణ వెలుపల ఉన్నప్పుడు మాత్రమే", - "condition_only_when_app_active": "స్నాప్‌చాట్ చురుకుగా ఉన్నప్పుడు మాత్రమే", - "condition_only_when_app_inactive": "స్నాప్‌చాట్ క్రియారహితంగా ఉన్నప్పుడు మాత్రమే", - "condition_no_push_notification_when_app_active": "స్నాప్‌చాట్ చురుకుగా ఉన్నప్పుడు పుష్ నోటిఫికేషన్ లేదు", - "add_event_dialog_title": "ఈవెంట్‌ను జోడించండి", - "event_type_label": "ఈవెంట్ రకం", - "triggers_title": "ట్రిగ్గర్‌లు", - "conditions_title": "షరతులు", - "add_button": "జోడించు", - "default_rule_name": "అనుకూల నియమం", - "discard_changes_dialog_title": "మార్పులను విస్మరించాలా?", - "discard_changes_dialog_text": "మీకు సేవ్ చేయని మార్పులు ఉన్నాయి. మీరు వాటిని విస్మరించాలనుకుంటున్నారా?", - "discard_button": "విస్మరించండి", - "cannot_save_rule_dialog_title": "నియమాన్ని సేవ్ చేయలేరు", - "cannot_save_rule_dialog_text": "ఒక నియమానికి సేవ్ చేయడానికి కనీసం ఒక సంఘటన అయినా ఉండాలి.", - "duplicate_rule_name_dialog_title": "నకిలీ నియమం పేరు", - "duplicate_rule_name_dialog_text": "ఈ పేరుతో ఒక నియమం ఇప్పటికే ఉంది. దయచేసి వేరే పేరును ఎంచుకోండి.", - "delete_rule_dialog_title": "నియమాన్ని తొలగించండి", - "delete_rule_dialog_text": "మీరు ఖచ్చితంగా ఈ నియమాన్ని తొలగించాలనుకుంటున్నారా?", - "new_rule_title": "కొత్త నియమం", - "edit_rule_title": "నియమాన్ని సవరించండి", - "back_button_description": "తిరిగి", - "save_button_description": "సేవ్", - "general_section_title": "సాధారణం", - "rule_name_label": "నియమం పేరు", - "author_name_label": "రచయిత పేరు", - "scope_section_title": "స్కోప్", - "scope_all": "అన్నీ", - "scope_whitelist": "వైట్‌లిస్ట్", - "scope_blacklist": "బ్లాక్లిస్ట్", - "select_friends_groups_button": "స్నేహితులు/సమూహాలను ఎంచుకోండి ({count})", - "events_section_title": "సంఘటనలు", - "add_event_button": "ఈవెంట్‌ను జోడించండి", - "no_events_text": "సంఘటనలు లేవు" - }, - "friend_tracker_catalog": { - "download_failed": "డౌన్‌లోడ్ విఫలమైంది: {code}", - "error": "లోపం: {message}", - "no_repos_added": "రిపోజిటరీలు ఏవీ జోడించబడలేదు.", - "no_rules_available": "ఏ రెపో నుండి నియమాలు అందుబాటులో లేవు.", - "by_author": "{author} ద్వారా", - "imported_button": "దిగుమతి చేయబడింది", - "import_button": "దిగుమతి", - "title": "ఫ్రెండ్ ట్రాకర్ కేటలాగ్", - "manage_repos_description": "రిపోజిటరీలను నిర్వహించండి" - }, - "friend_tracker_export": { - "title": "ఎగుమతి నియమాలు", - "back_button_description": "తిరిగి", - "exported_toast": "ఫ్రెండ్ ట్రాకర్ నియమాలు ఎగుమతి!", - "export_failed_toast": "నియమాలను ఎగుమతి చేయడంలో విఫలమైంది: {message}", - "save_button": "సేవ్", - "expand_button_description": "విస్తరించండి" - }, - "friend_tracker_import": { - "title": "దిగుమతి నియమాలు", - "back_button_description": "తిరిగి", - "imported_toast": "ఫ్రెండ్ ట్రాకర్ నియమాలు దిగుమతి!", - "import_failed_toast": "నియమాలను దిగుమతి చేయడంలో విఫలమైంది: {message}", - "confirm_button": "నిర్ధారించండి", - "expand_button_description": "విస్తరించండి" - }, - "friend_tracker_repos": { - "invalid_repo_title": "చెల్లని రిపోజిటరీ", - "add_repo_button": "రిపోజిటరీని జోడించండి", - "add_repo_dialog_title": "రిపోజిటరీ URL జోడించండి", - "repo_url_label": "రిపోజిటరీ url", - "repo_added_toast": "రిపోజిటరీ విజయవంతంగా జోడించబడింది!", - "invalid_repo_error": "ఇది చెల్లుబాటు అయ్యే ఫ్రెండ్ ట్రాకర్ రిపోజిటరీగా కనిపించడం లేదు.", - "add_repo_failed_toast": "రిపోజిటరీని జోడించడంలో విఫలమైంది: {message}", - "add_button": "జోడించు", - "no_repos_added": "రిపోజిటరీలు జోడించబడలేదు", - "remove_button": "తొలగించండి", - "remove_repo_dialog_title": "రిపోజిటరీని తొలగించండి", - "remove_repo_dialog_text": "మీరు ఖచ్చితంగా ఈ రిపోజిటరీని తొలగించాలనుకుంటున్నారా?" - }, - "navigation": { - "tracker_tab_label": "ట్రాకర్", - "customize_bottom_bar_title": "దిగువ పట్టీని అనుకూలీకరించండి", - "customize_bottom_bar_subtitle": "ట్యాబ్‌లను క్రమాన్ని మార్చండి, జోడించండి లేదా తొలగించండి. గరిష్టంగా ఐదు.", - "shown_tabs_title": "చూపిన ట్యాబ్‌లు", - "no_tabs_selected_text": "ట్యాబ్‌లు ఏవీ ఎంచుకోవు", - "available_tabs_title": "అందుబాటులో ఉన్న ట్యాబ్‌లు", - "reset_button": "రీసెట్", - "done_button": "పూర్తయింది" - }, - "scripting": { - "script_already_installed": "స్క్రిప్ట్ ఇప్పటికే ఇన్‌స్టాల్ చేయబడింది!", - "downloading_script": "స్క్రిప్ట్‌ను డౌన్‌లోడ్ చేస్తోంది...", - "script_downloaded": "స్క్రిప్ట్ {name} డౌన్‌లోడ్ చేయబడింది!", - "download_script_failed": "స్క్రిప్ట్‌ను డౌన్‌లోడ్ చేయడంలో విఫలమైంది. మరిన్ని వివరాల కోసం లాగ్‌లను తనిఖీ చేయండి", - "import_script_from_url_title": "URL నుండి స్క్రిప్ట్ దిగుమతి", - "import_script_warning": "హెచ్చరిక: దిగుమతి చేసుకున్న స్క్రిప్ట్‌లు మీ పరికరానికి హానికరం. విశ్వసనీయ వనరుల నుండి స్క్రిప్ట్‌లను మాత్రమే దిగుమతి చేయండి.", - "enter_url_label": "ఇక్కడ URL ను నమోదు చేయండి:", - "script_imported": "స్క్రిప్ట్ {name} దిగుమతి చేయబడింది!", - "import_failed": "స్క్రిప్ట్‌ను దిగుమతి చేయడంలో విఫలమైంది. {message}. మరిన్ని వివరాల కోసం లాగ్‌లను తనిఖీ చేయండి", - "import_button": "దిగుమతి", - "update_module_button": "మాడ్యూల్‌ను నవీకరించండి", - "updating_script": "{name} స్క్రిప్ట్‌ను నవీకరిస్తోంది...", - "module_not_found": "మాడ్యూల్ కనుగొనబడలేదు", - "updated_script": "{name} ను {version} సంస్కరణకు నవీకరించబడింది", - "update_module_failed": "మాడ్యూల్‌ను నవీకరించడంలో విఫలమైంది. మరిన్ని వివరాల కోసం లాగ్‌లను తనిఖీ చేయండి", - "edit_module_button": "మాడ్యూల్‌ను సవరించండి", - "open_module_failed": "మాడ్యూల్ ఫైల్‌ను తెరవడంలో విఫలమైంది. మరిన్ని వివరాల కోసం లాగ్‌లను తనిఖీ చేయండి", - "clear_module_data_button": "మాడ్యూల్ డేటాను క్లియర్ చేయండి", - "module_data_cleared": "మాడ్యూల్ డేటా క్లియర్ చేయబడింది!", - "clear_module_data_failed": "మాడ్యూల్ డేటాను క్లియర్ చేయడంలో విఫలమైంది. మరిన్ని వివరాల కోసం లాగ్‌లను తనిఖీ చేయండి", - "delete_module_button": "మాడ్యూల్‌ను తొలగించండి", - "deleted_script": "తొలగించబడిన స్క్రిప్ట్ {name}!", - "delete_module_failed": "మాడ్యూల్‌ను తొలగించడంలో విఫలమైంది. మరిన్ని వివరాల కోసం లాగ్‌లను తనిఖీ చేయండి", - "actions_title": "చర్యలు", - "no_description": "వివరణ లేదు", - "update_available": "నవీకరణ అందుబాటులో ఉంది: {version}", - "actions_button": "చర్యలు", - "loaded_script": "లోడ్ చేయబడిన స్క్రిప్ట్ {name}", - "unloaded_script": "అన్‌లోడ్ చేయబడిన స్క్రిప్ట్ {name}", - "enable_script_failed": "స్క్రిప్ట్‌ను ప్రారంభించడంలో విఫలమైంది. మరిన్ని వివరాల కోసం లాగ్‌లను తనిఖీ చేయండి", - "disable_script_failed": "స్క్రిప్ట్‌ను నిలిపివేయడంలో విఫలమైంది. మరిన్ని వివరాల కోసం లాగ్‌లను తనిఖీ చేయండి", - "select_scripts_folder_toast": "దయచేసి మీ స్క్రిప్ట్స్ ఫోల్డర్‌ను ఎంచుకోండి!", - "manage_repos_button": "రెపోలను నిర్వహించండి", - "import_from_url_button": "URL నుండి దిగుమతి", - "open_scripts_folder_button": "స్క్రిప్ట్స్ ఫోల్డర్‌ను తెరవండి", - "no_settings_for_module": "ఈ మాడ్యూల్‌కు సెట్టింగ్‌లు లేవు", - "installed_scripts_tab": "ఇన్‌స్టాల్ చేసిన స్క్రిప్ట్‌లు", - "catalog_tab": "కేటలాగ్", - "no_scripts_folder_selected_title": "స్క్రిప్ట్స్ ఫోల్డర్ ఎంచుకోలేదు", - "select_folder_button": "ఫోల్డర్ ఎంచుకోండి", - "no_scripts_found_title": "స్క్రిప్ట్‌లు కనుగొనబడలేదు.", - "use_catalog_to_add_scripts": "స్క్రిప్ట్‌లను జోడించడానికి కేటలాగ్ టాబ్‌ను ఉపయోగించండి!", - "ok_button_timeout": "సరే ({timeout})", - "documentation_button": "డాక్యుమెంటేషన్", - "catalog": { - "script_already_installed": "స్క్రిప్ట్ ఇప్పటికే ఇన్‌స్టాల్ చేయబడింది!", - "download_failed": "డౌన్‌లోడ్ విఫలమైంది: {code}", - "script_downloaded": "స్క్రిప్ట్ డౌన్‌లోడ్ చేయబడింది!", - "could_not_create_file": "ఫైల్‌ను సృష్టించలేకపోయారు.", - "no_scripts_folder_selected": "స్క్రిప్ట్స్ ఫోల్డర్ ఎంచుకోలేదు.", - "error": "లోపం: {message}", - "no_repos_added": "రిపోజిటరీలు ఏవీ జోడించబడలేదు.", - "repo_list_info": "ఇక్కడ మీరు రెపోల జాబితాను కనుగొనవచ్చు:", - "link_text": "లింక్", - "no_scripts_available": "ఏ రెపో నుండి స్క్రిప్ట్‌లు అందుబాటులో లేవు.", - "by_author": "{author} ద్వారా", - "version": "వెర్షన్: {version}", - "installed_button": "ఇన్‌స్టాల్ చేయబడింది", - "download_button": "డౌన్‌లోడ్" - }, - "repos": { - "invalid_repo_title": "చెల్లని రిపోజిటరీ", - "add_repo_button": "రిపోజిటరీని జోడించండి", - "add_repo_dialog_title": "రిపోజిటరీ URL జోడించండి", - "repo_url_label": "రిపోజిటరీ url", - "repo_added_toast": "రిపోజిటరీ విజయవంతంగా జోడించబడింది!", - "invalid_repo_error": "ఇది చెల్లుబాటు అయ్యే స్క్రిప్ట్ రిపోజిటరీగా కనిపించడం లేదు.", - "add_repo_failed_toast": "రిపోజిటరీని జోడించడంలో విఫలమైంది: {message}", - "add_button": "జోడించు", - "no_repos_added": "రిపోజిటరీలు జోడించబడలేదు", - "remove_button": "తొలగించండి", - "remove_repo_dialog_title": "రిపోజిటరీని తొలగించండి", - "remove_repo_dialog_text": "మీరు ఖచ్చితంగా ఈ రిపోజిటరీని తొలగించాలనుకుంటున్నారా?" - } - }, - "features": { - "config_import": { - "title": "దిగుమతిని నిర్ధారించండి", - "back_button_description": "తిరిగి", - "config_imported_toast": "కాన్ఫిగర్ దిగుమతి!", - "confirm_button": "నిర్ధారించండి", - "expand_button_description": "విస్తరించండి", - "enable_feature": "లక్షణాన్ని ప్రారంభించండి", - "enabled": "ప్రారంభించబడింది", - "disabled": "నిలిపివేయబడింది" - }, - "config_export": { - "title": "ఎగుమతి సారాంశం", - "back_button_description": "తిరిగి", - "save_button": "సేవ్", - "expand_button_description": "విస్తరించండి", - "enable_feature": "లక్షణాన్ని ప్రారంభించండి", - "enabled": "ప్రారంభించబడింది", - "disabled": "నిలిపివేయబడింది" - } - }, - "manage_repos": { - "title": "{featureName} రిపోజిటరీలను నిర్వహించండి", - "add_repo_button": "రిపోజిటరీని జోడించండి", - "add_repo_dialog_title": "రిపోజిటరీ URL జోడించండి", - "repo_url_label": "రిపోజిటరీ url", - "repo_added_successfully": "రిపోజిటరీ విజయవంతంగా జోడించబడింది!", - "add_repo_failed": "రిపోజిటరీని జోడించడంలో విఫలమైంది: {message}", - "add_button": "జోడించు", - "no_repos_added": "రిపోజిటరీలు ఏవీ జోడించబడలేదు", - "remove_button": "తొలగించండి" - } - }, - "rules": { - "toasts": { - "enabled": "{ruleName} ప్రారంభించబడింది", - "disabled": "{ruleName} నిలిపివేయబడింది" - }, - "modes": { - "blacklist": "బ్లాక్‌లిస్ట్ మోడ్", - "whitelist": "వైట్‌లిస్ట్ మోడ్" - }, - "properties": { - "auto_download": { - "name": "ఆటో డౌన్‌లోడ్", - "description": "స్నాప్‌లను చూసేటప్పుడు స్వయంచాలకంగా డౌన్‌లోడ్ చేయండి", - "options": { - "blacklist": "ఆటో డౌన్‌లోడ్ నుండి మినహాయించండి", - "whitelist": "ఆటో డౌన్‌లోడ్" - } - }, - "stealth": { - "name": "స్టీల్త్ మోడ్", - "description": "మీరు వారి స్నాప్‌లు/చాట్‌లు మరియు సంభాషణలను తెరిచారని తెలుసుకోకుండా ఎవరినైనా నిరోధిస్తుంది", - "options": { - "blacklist": "స్టీల్త్ మోడ్ నుండి మినహాయించండి", - "whitelist": "స్టీల్త్ మోడ్" - } - }, - "auto_save": { - "name": "ఆటో సేవ్", - "description": "చాట్ సందేశాలను చూసేటప్పుడు వాటిని సేవ్ చేస్తుంది", - "options": { - "blacklist": "ఆటో సేవ్ నుండి మినహాయించండి", - "whitelist": "ఆటో సేవ్" - } - }, - "unsaveable_messages": { - "name": "సేవ్ చేయలేని సందేశాలు", - "description": "ఇతర వ్యక్తుల ద్వారా సందేశాలను చాట్‌లో సేవ్ చేయకుండా నిరోధిస్తుంది", - "options": { - "blacklist": "సేవ్ చేయలేని సందేశాల నుండి మినహాయించండి", - "whitelist": "సేవ్ చేయలేని సందేశాలు" - } - }, - "auto_open_snaps": { - "name": "ఆటో ఓపెన్ స్నాప్స్", - "description": "వాటిని స్వీకరించేటప్పుడు స్వయంచాలకంగా స్నాప్‌లను తెరుస్తుంది", - "options": { - "blacklist": "ఆటో ఓపెన్ స్నాప్‌ల నుండి మినహాయించండి", - "whitelist": "ఆటో ఓపెన్ స్నాప్స్" - } - }, - "hide_friend_feed": { - "name": "ఫ్రెండ్ ఫీడ్ నుండి దాచండి" - }, - "e2e_encryption": { - "name": "E2E గుప్తీకరణను ఉపయోగించండి" - }, - "pin_conversation": { - "name": "సంభాషణను పిన్ చేయండి" - }, - "exclude_message_logger": { - "name": "సందేశ లాగర్ నుండి మినహాయించండి" - } - } - }, - "actions": { - "clean_snapchat_cache": { - "name": "స్నాప్‌చాట్ కాష్‌ను శుభ్రపరచండి", - "description": "స్నాప్‌చాట్ కాష్‌ను శుభ్రపరుస్తుంది" - }, - "manage_friend_list": { - "name": "స్నేహితుల జాబితాను నిర్వహించండి", - "description": "బ్యాకప్ చేసేటప్పుడు మీ స్నేహితుల జాబితాను దిగుమతి/ఎగుమతి చేయండి" - }, - "export_chat_messages": { - "name": "చాట్ సందేశాలను ఎగుమతి చేయండి", - "description": "సంభాషణ సందేశాలను JSON/HTML/TXT ఫైల్‌లోకి ఎగుమతి చేస్తుంది" - }, - "export_memories": { - "name": "జ్ఞాపకాలను ఎగుమతి చేయండి", - "description": "జ్ఞాపకాలను జిప్ ఫైల్‌లోకి ఎగుమతి చేస్తుంది" - }, - "bulk_messaging_action": { - "name": "బల్క్ మెసేజింగ్ చర్య", - "description": "స్నేహితులను తొలగించడం లేదా సంభాషణలను భారీగా తొలగించడం వంటి కార్యకలాపాలను నిర్వహిస్తుంది" - }, - "regen_mappings": { - "name": "మ్యాపింగ్‌లను పునరుత్పత్తి చేయండి", - "description": "మానవీయంగా మ్యాపింగ్‌లను పునరుత్పత్తి చేయండి" - }, - "change_language": { - "name": "భాష మార్చండి", - "description": "పర్ఫెక్ట్స్నాప్ యొక్క భాషను మార్చండి" - }, - "file_imports": { - "name": "ఫైల్ దిగుమతులు", - "description": "స్నాప్‌చాట్‌లో ఉపయోగం కోసం ఫైల్‌లను దిగుమతి చేయండి" - }, - "friend_tracker": { - "name": "ఫ్రెండ్ ట్రాకర్", - "description": "స్నాప్‌చాట్‌లో మీ స్నేహితులను ట్రాక్ చేయండి" - }, - "logger_history": { - "name": "లాగర్ చరిత్ర", - "description": "లాగిన్ చేసిన సందేశాల చరిత్రను చూడండి" - } - }, - "features": { - "notices": { - "unstable": "⚠ అస్థిరమైనది", - "ban_risk": "⚠ ఈ లక్షణం నిషేధానికి దారితీయవచ్చు", - "internal_behavior": "⚠ ఇది స్నాప్‌చాట్ యొక్క అంతర్గత ప్రవర్తనను విచ్ఛిన్నం చేస్తుంది" - }, - "properties": { - "downloader": { - "name": "డౌన్‌లోడ్", - "description": "స్నాప్‌చాట్ మీడియాను డౌన్‌లోడ్ చేయండి", - "properties": { - "save_folder": { - "name": "ఫోల్డర్‌ను సేవ్ చేయండి", - "description": "అన్ని మీడియా డౌన్‌లోడ్ చేయవలసిన డైరెక్టరీని ఎంచుకోండి" - }, - "auto_download_sources": { - "name": "ఆటో డౌన్‌లోడ్ మూలాలు", - "description": "స్వయంచాలకంగా డౌన్‌లోడ్ చేయడానికి మూలాలను ఎంచుకోండి" - }, - "prevent_self_auto_download": { - "name": "స్వీయ ఆటో డౌన్‌లోడ్‌ను నిరోధించండి", - "description": "మీ స్వంత స్నాప్‌లను స్వయంచాలకంగా డౌన్‌లోడ్ చేయకుండా నిరోధిస్తుంది" - }, - "path_format": { - "name": "పాత్ ఫార్మాట్", - "description": "ఫైల్ పాత్ ఆకృతిని పేర్కొనండి" - }, - "allow_duplicate": { - "name": "నకిలీని అనుమతించండి", - "description": "ఒకే మీడియాను అనేకసార్లు డౌన్‌లోడ్ చేయడానికి అనుమతిస్తుంది" - }, - "merge_overlays": { - "name": "అతివ్యాప్తులను విలీనం చేయండి", - "description": "స్నాప్ యొక్క టెక్స్ట్ మరియు మీడియాను ఒకే ఫైల్‌లో మిళితం చేస్తుంది" - }, - "force_image_format": { - "name": "చిత్ర ఆకృతిని బలవంతం చేయండి", - "description": "చిత్రాలను పేర్కొన్న ఆకృతిలో సేవ్ చేయమని బలవంతం చేస్తుంది" - }, - "force_voice_note_format": { - "name": "వాయిస్ నోట్ ఫార్మాట్‌ను బలవంతం చేయండి", - "description": "వాయిస్ నోట్స్‌ను పేర్కొన్న ఆకృతిలో సేవ్ చేయమని బలవంతం చేస్తుంది" - }, - "auto_download_voice_notes": { - "name": "ఆటో డౌన్‌లోడ్ వాయిస్ నోట్స్", - "description": "వాయిస్ నోట్లను ప్లే చేస్తున్నప్పుడు స్వయంచాలకంగా డౌన్‌లోడ్ చేస్తుంది" - }, - "download_profile_pictures": { - "name": "ప్రొఫైల్ చిత్రాలను డౌన్‌లోడ్ చేయండి", - "description": "ప్రొఫైల్ పేజీ నుండి ప్రొఫైల్ చిత్రాలను డౌన్‌లోడ్ చేయడానికి మిమ్మల్ని అనుమతిస్తుంది" - }, - "opera_download_button": { - "name": "ఒపెరా డౌన్‌లోడ్ బటన్", - "description": "స్నాప్‌ను చూసేటప్పుడు కుడి ఎగువ మూలలో డౌన్‌లోడ్ బటన్‌ను జోడిస్తుంది.\nబటన్‌లపై ఎక్కువసేపు నొక్కితే డౌన్‌లోడ్ బలవంతం అవుతుంది" - }, - "download_context_menu": { - "name": "కాంటెక్స్ట్ మెనుని డౌన్‌లోడ్ చేయండి", - "description": "సందర్భ మెనుని ఉపయోగించి సంభాషణ లేదా కథ నుండి సందేశాలను డౌన్‌లోడ్/ప్రివ్యూ చేయడానికి మిమ్మల్ని అనుమతిస్తుంది.\nబటన్‌లపై ఎక్కువసేపు నొక్కితే డౌన్‌లోడ్ బలవంతం అవుతుంది" - }, - "ffmpeg_options": { - "name": "FFmpeg ఎంపికలు", - "description": "అదనపు FFmpeg ఎంపికలను పేర్కొనండి", - "properties": { - "threads": { - "name": "థ్రెడ్‌లు", - "description": "ఉపయోగించాల్సిన థ్రెడ్‌ల మొత్తం" - }, - "preset": { - "name": "ప్రీసెట్", - "description": "మార్పిడి వేగాన్ని సెట్ చేయండి" - }, - "constant_rate_factor": { - "name": "స్థిరమైన రేటు కారకం", - "description": "వీడియో ఎన్‌కోడర్ కోసం స్థిరమైన రేటు కారకాన్ని సెట్ చేయండి\nlibx264 కోసం 0 నుండి 51 వరకు" - }, - "video_bitrate": { - "name": "వీడియో బిట్రేట్", - "description": "వీడియో బిట్రేట్ (kbps) ను సెట్ చేయండి" - }, - "audio_bitrate": { - "name": "ఆడియో బిట్రేట్", - "description": "ఆడియో బిట్రేట్ (kbps) ను సెట్ చేయండి" - }, - "custom_video_codec": { - "name": "అనుకూల వీడియో కోడెక్", - "description": "కస్టమ్ వీడియో కోడెక్‌ను సెట్ చేయండి (ఉదా. libx264)" - }, - "custom_audio_codec": { - "name": "కస్టమ్ ఆడియో కోడెక్", - "description": "కస్టమ్ ఆడియో కోడెక్‌ను సెట్ చేయండి (ఉదా. aac)" - } - } - }, - "logging": { - "name": "లాగింగ్", - "description": "మీడియా డౌన్‌లోడ్ చేస్తున్నప్పుడు టోస్ట్ చూపిస్తుంది" - }, - "custom_path_format": { - "name": "కస్టమ్ పాత్ ఫార్మాట్", - "description": "డౌన్‌లోడ్ చేసిన మీడియా కోసం అనుకూల మార్గం ఆకృతిని పేర్కొనండి\n\nఅందుబాటులో ఉన్న వేరియబుల్స్:\n - %username%\n - %source%\n - %hash%\n - %date_time%" - } - } - }, - "user_interface": { - "name": "వినియోగదారు ఇంటర్‌ఫేస్", - "description": "స్నాప్‌చాట్ యొక్క రూపాన్ని మరియు అనుభూతిని మార్చండి", - "properties": { - "enable_app_appearance": { - "name": "అనువర్తన ప్రదర్శన సెట్టింగ్‌లను ప్రారంభించండి", - "description": "దాచిన అనువర్తన ప్రదర్శన సెట్టింగ్‌ను ప్రారంభిస్తుంది\nకొత్త స్నాప్‌చాట్ సంస్కరణల్లో అవసరం లేదు" - }, - "friend_feed_message_preview": { - "name": "ఫ్రెండ్ ఫీడ్ సందేశ ప్రివ్యూ", - "description": "ఫ్రెండ్ ఫీడ్‌లోని చివరి సందేశాల ప్రివ్యూను చూపిస్తుంది", - "properties": { - "amount": { - "name": "మొత్తం", - "description": "ప్రివ్యూ చేయడానికి సందేశాల మొత్తం" - } - } - }, - "snap_preview": { - "name": "స్నాప్ ప్రివ్యూ", - "description": "చాట్‌లో కనిపించని స్నాప్‌ల పక్కన ఒక చిన్న ప్రివ్యూను ప్రదర్శిస్తుంది" - }, - "bootstrap_override": { - "name": "బూట్‌స్ట్రాప్ ఓవర్‌రైడ్", - "description": "వినియోగదారు ఇంటర్‌ఫేస్ బూట్‌స్ట్రాప్ సెట్టింగ్‌లను భర్తీ చేస్తుంది", - "properties": { - "app_appearance": { - "name": "అనువర్తన ప్రదర్శన", - "description": "నిరంతర అనువర్తన రూపాన్ని సెట్ చేస్తుంది" - }, - "home_tab": { - "name": "హోమ్ టాబ్", - "description": "స్నాప్‌చాట్ తెరిచినప్పుడు స్టార్టప్ టాబ్‌ను అధిగమిస్తుంది" - } - } - }, - "force_amoled_theme": { - "name": "అమోలెడ్ డార్క్ మోడ్", - "description": "చీకటి థీమ్ కోసం నిజమైన నల్ల నేపథ్యాన్ని ఉపయోగిస్తుంది" - }, - "map_friend_nametags": { - "name": "మెరుగైన ఫ్రెండ్ మ్యాప్ నేమ్‌ట్యాగ్‌లు", - "description": "స్నాప్‌మ్యాప్‌లో స్నేహితుల నేమ్‌ట్యాగ్‌లను మెరుగుపరుస్తుంది" - }, - "prevent_message_list_auto_scroll": { - "name": "సందేశ జాబితా ఆటో స్క్రోల్‌ను నిరోధించండి", - "description": "సందేశాన్ని పంపేటప్పుడు/స్వీకరించేటప్పుడు సందేశ జాబితాను దిగువకు స్క్రోలింగ్ చేయకుండా నిరోధిస్తుంది" - }, - "streak_expiration_info": { - "name": "స్ట్రీక్ గడువు సమాచారాన్ని చూపించు", - "description": "స్ట్రీక్స్ కౌంటర్ పక్కన స్ట్రీక్ గడువు టైమర్ చూపిస్తుంది" - }, - "hide_friend_feed_entry": { - "name": "ఫ్రెండ్ ఫీడ్ ఎంట్రీని దాచండి", - "description": "ఫ్రెండ్ ఫీడ్ నుండి ఒక నిర్దిష్ట స్నేహితుడిని దాచిపెడుతుంది\nఈ లక్షణాన్ని నిర్వహించడానికి సోషల్ టాబ్‌ను ఉపయోగించండి" - }, - "hide_streak_restore": { - "name": "స్ట్రీక్ పునరుద్ధరణను దాచు", - "description": "ఫ్రెండ్ ఫీడ్‌లోని పునరుద్ధరణ బటన్‌ను దాచిపెడుతుంది" - }, - "hide_quick_add_suggestions": { - "name": "శీఘ్ర జోడించు సూచనలను దాచండి", - "description": "ఫ్రెండ్ సూచనలను శీఘ్రంగా జోడించుటను తొలగిస్తుంది" - }, - "hide_story_suggestions": { - "name": "కథ సూచనలను దాచండి", - "description": "కథల పేజీ నుండి సూచనలను తొలగిస్తుంది" - }, - "hide_ui_components": { - "name": "UI భాగాలను దాచండి", - "description": "దాచడానికి ఏ UI భాగాలను ఎంచుకోండి" - }, - "opera_media_quick_info": { - "name": "ఒపెరా మీడియా శీఘ్ర సమాచారం", - "description": "ఒపెరా వ్యూయర్ కాంటెక్స్ట్ మెనులో సృష్టి తేదీ వంటి మీడియా యొక్క ఉపయోగకరమైన సమాచారాన్ని చూపిస్తుంది" - }, - "old_bitmoji_selfie": { - "name": "పాత బిట్‌మోజీ సెల్ఫీ", - "description": "పాత స్నాప్‌చాట్ సంస్కరణల నుండి బిట్‌మోజీ సెల్ఫీలను తిరిగి తెస్తుంది" - }, - "disable_spotlight": { - "name": "స్పాట్‌లైట్‌ను నిలిపివేయండి", - "description": "స్పాట్‌లైట్ పేజీని నిలిపివేస్తుంది" - }, - "friend_feed_menu_buttons": { - "name": "స్నేహితుడు ఫీడ్ మెను బటన్లు", - "description": "ఫ్రెండ్ ఫీడ్ మెనులో ఏ బటన్లను చూపించాలో ఎంచుకోండి" - }, - "auto_close_friend_feed_menu": { - "name": "ఆటో క్లోజ్ ఫ్రెండ్ ఫీడ్ మెను", - "description": "సెట్టింగ్ బటన్‌ను నొక్కిన తర్వాత ఫ్రెండ్ ఫీడ్ మెనుని స్వయంచాలకంగా మూసివేస్తుంది" - }, - "vertical_story_viewer": { - "name": "నిలువు కథ వీక్షకుడు", - "description": "అన్ని కథలకు నిలువు కథ వీక్షకుడిని ప్రారంభిస్తుంది" - }, - "enable_friend_feed_menu_bar": { - "name": "స్నేహితుడు ఫీడ్ మెను బార్", - "description": "కొత్త స్నేహితుడు ఫీడ్ మెను బార్‌ను ప్రారంభిస్తుంది" - }, - "message_indicators": { - "name": "సందేశ సూచికలు", - "description": "సందేశాలకు నిర్దిష్ట సూచిక చిహ్నాలను జోడిస్తుంది\nగమనిక: సూచికలు 100% ఖచ్చితమైనవి కాకపోవచ్చు" - }, - "stealth_mode_indicator": { - "name": "స్టీల్త్ మోడ్ సూచిక", - "description": "స్టీల్త్ మోడ్‌లో సంభాషణల పక్కన 👻 ఎమోజిని జోడిస్తుంది" - }, - "edit_text_override": { - "name": "టెక్స్ట్ ఓవర్‌రైడ్‌ను సవరించండి", - "description": "టెక్స్ట్ ఫీల్డ్ ప్రవర్తనను అధిగమిస్తుంది" - }, - "prevent_forced_keyboard": { - "name": "బలవంతపు కీబోర్డ్‌ను నిరోధించండి", - "description": "మీరు సంభాషణను తెరిచినప్పుడు స్నాప్‌చాట్ స్వయంచాలకంగా కీబోర్డ్‌ను పాప్ చేయకుండా నిరోధిస్తుంది" - }, - "settings_menu": { - "name": "సెట్టింగుల మెను", - "description": "మీరు పర్ఫెక్ట్స్నాప్ మెనుని తెరిచే విధానాన్ని మారుస్తుంది", - "options": { - "default": "డిఫాల్ట్", - "legacy": "లెగసీ" - } - } - } - }, - "messaging": { - "name": "మెసేజింగ్", - "description": "మీరు స్నేహితులతో ఎలా వ్యవహరిస్తారో మార్చండి", - "properties": { - "bypass_screenshot_detection": { - "name": "బైపాస్ స్క్రీన్‌షాట్ డిటెక్షన్", - "description": "మీరు స్క్రీన్‌షాట్ తీసుకున్నప్పుడు స్నాప్‌చాట్ గుర్తించకుండా నిరోధిస్తుంది" - }, - "anonymous_story_viewing": { - "name": "అనామక కథ వీక్షణ", - "description": "మీరు వారి కథను చూశారని ఎవరికీ తెలియకుండా నిరోధిస్తుంది" - }, - "prevent_story_rewatch_indicator": { - "name": "స్టోరీ రీవాచ్ సూచికను నిరోధించండి", - "description": "మీరు వారి కథను తిరిగి చూశారని ఎవరికీ తెలియకుండా నిరోధిస్తుంది" - }, - "hide_peek_a_peek": { - "name": "పీక్-ఎ-పీక్ దాచు", - "description": "మీరు సగం చాట్‌లో స్వైప్ చేసినప్పుడు నోటిఫికేషన్ పంపకుండా నిరోధిస్తుంది" - }, - "hide_bitmoji_presence": { - "name": "బిట్‌మోజీ ఉనికిని దాచండి", - "description": "చాట్‌లో ఉన్నప్పుడు మీ బిట్‌మోజీ పాప్ అప్ చేయకుండా నిరోధిస్తుంది" - }, - "hide_typing_notifications": { - "name": "టైపింగ్ నోటిఫికేషన్లను దాచండి", - "description": "మీరు సందేశం టైప్ చేస్తున్నారని ఎవరికీ తెలియకుండా నిరోధిస్తుంది" - }, - "unlimited_snap_view_time": { - "name": "అపరిమిత స్నాప్ వీక్షణ సమయం", - "description": "స్నాప్‌లను చూడటానికి కాలపరిమితిని తొలగిస్తుంది" - }, - "auto_mark_as_read": { - "name": "ఆటో మార్క్ చదివినట్లుగా", - "description": "స్టీల్త్ మోడ్ ప్రారంభించబడినప్పుడు కూడా స్వయంచాలకంగా సందేశాలు/స్నాప్‌లను చదివినట్లుగా మార్క్ చేస్తుంది" - }, - "mark_snap_as_seen_button": { - "name": "చూసినట్లుగా స్నాప్‌ను మార్క్ చేయండి", - "description": "స్నాప్ చూసేటప్పుడు చూసినట్లుగా మార్క్ చేయడానికి ఒక బటన్‌ను జోడిస్తుంది.\nస్టీల్త్ మోడ్ ప్రారంభించబడినప్పుడు కూడా ఇది పని చేస్తుంది" - }, - "skip_when_marking_as_seen": { - "name": "చూసినట్లుగా మార్క్ చేసేటప్పుడు దాటవేయండి", - "description": "చూసినట్లుగా స్నాప్‌ను మార్క్ చేసేటప్పుడు స్వయంచాలకంగా తదుపరి స్నాప్‌కు దాటవేస్తుంది.\nచూసినట్లుగా మార్క్ స్నాప్ బటన్‌తో కలిపి ఉపయోగించండి" - }, - "loop_media_playback": { - "name": "లూప్ మీడియా ప్లేబ్యాక్", - "description": "స్నాప్ / కథలను చూసేటప్పుడు మీడియా ప్లేబ్యాక్‌ను లూప్ చేస్తుంది" - }, - "disable_replay_in_ff": { - "name": "FFలో రీప్లేను నిలిపివేయండి", - "description": "ఫ్రెండ్ ఫీడ్ నుండి ఎక్కువసేపు నొక్కి రీప్లే చేసే సామర్థ్యాన్ని నిలిపివేస్తుంది" - }, - "half_swipe_notifier": { - "name": "సగం స్వైప్ నోటిఫైయర్", - "description": "ఎవరైనా సగం సంభాషణలో స్వైప్ చేసినప్పుడు మీకు తెలియజేస్తుంది", - "properties": { - "min_duration": { - "name": "కనీస వ్యవధి", - "description": "సగం స్వైప్ యొక్క కనీస వ్యవధి (సెకన్లలో)" - }, - "max_duration": { - "name": "గరిష్ట వ్యవధి", - "description": "సగం స్వైప్ యొక్క గరిష్ట వ్యవధి (సెకన్లలో)" - } - } - }, - "call_start_confirmation": { - "name": "కాల్ ప్రారంభ నిర్ధారణ", - "description": "కాల్ ప్రారంభించేటప్పుడు నిర్ధారణ డైలాగ్‌ను చూపుతుంది" - }, - "unlimited_conversation_pinning": { - "name": "అపరిమిత సంభాషణ పిన్నింగ్", - "description": "స్థానికంగా అపరిమిత సంభాషణలను పిన్ చేయడానికి మిమ్మల్ని అనుమతిస్తుంది" - }, - "disable_snap_mode_restrictions": { - "name": "స్నాప్ మోడ్ పరిమితులను నిలిపివేయండి", - "description": "పరిమితులు లేకుండా స్వీయ-వినాశన స్నాప్‌లను చూడటానికి మిమ్మల్ని అనుమతిస్తుంది" - }, - "prevent_message_sending": { - "name": "సందేశం పంపడాన్ని నిరోధించండి", - "description": "కొన్ని రకాల సందేశాలను పంపడాన్ని నిరోధిస్తుంది" - }, - "friend_mutation_notifier": { - "name": "ఫ్రెండ్ మ్యుటేషన్ నోటిఫైయర్", - "description": "స్నేహితుడి ప్రొఫైల్‌లో ఏదైనా మారినప్పుడు మీకు తెలియజేస్తుంది" - }, - "better_notifications": { - "name": "మంచి నోటిఫికేషన్‌లు", - "description": "అందుకున్న నోటిఫికేషన్లలో మరింత సమాచారాన్ని జోడిస్తుంది", - "properties": { - "group_notifications": { - "name": "సమూహ నోటిఫికేషన్‌లు", - "description": "సమూహ నోటిఫికేషన్‌లను ఒకేదానిలో సమూహపరుస్తుంది" - }, - "chat_preview": { - "name": "చాట్ ప్రివ్యూ", - "description": "నోటిఫికేషన్‌లో అందుకున్న సందేశాల ప్రివ్యూను చూపిస్తుంది" - }, - "media_preview": { - "name": "మీడియా ప్రివ్యూ", - "description": "నోటిఫికేషన్‌లో ఎంచుకున్న మీడియా రకాల ప్రివ్యూను చూపిస్తుంది" - }, - "media_caption": { - "name": "మీడియా శీర్షిక", - "description": "నోటిఫికేషన్‌లో మీడియా యొక్క జతచేయబడిన శీర్షికను చూపుతుంది" - }, - "stacked_media_messages": { - "name": "పేర్చబడిన మీడియా సందేశాలు", - "description": "బహుళ మీడియా సందేశాలను ఒక టెక్స్ట్ నోటిఫికేషన్‌గా మిళితం చేస్తుంది. చాట్ ప్రివ్యూతో కలిపి ఉపయోగించండి" - }, - "friend_add_source": { - "name": "స్నేహితుడిని జోడించు మూలం", - "description": "నోటిఫికేషన్‌లో స్నేహితుడి అభ్యర్థన యొక్క మూలాన్ని చూపిస్తుంది" - }, - "reply_button": { - "name": "ప్రత్యుత్తర బటన్", - "description": "నోటిఫికేషన్‌కు ప్రత్యుత్తర బటన్‌ను జోడిస్తుంది" - }, - "smart_replies": { - "name": "స్మార్ట్ ప్రత్యుత్తరాలు", - "description": "నోటిఫికేషన్‌లకు (ఆండ్రాయిడ్ 10+) సూచించిన ప్రత్యుత్తరాలను జోడిస్తుంది. ప్రత్యుత్తర బటన్‌తో కలిపి ఉపయోగించండి" - }, - "download_button": { - "name": "డౌన్‌లోడ్ బటన్", - "description": "నోటిఫికేషన్ నుండి మీడియాను డౌన్‌లోడ్ చేయడానికి మిమ్మల్ని అనుమతిస్తుంది" - }, - "mark_as_read_button": { - "name": "చదివినట్లుగా మార్క్ చేయండి", - "description": "నోటిఫికేషన్ నుండి చదివినట్లు సందేశాన్ని మార్క్ చేయడానికి మిమ్మల్ని అనుమతిస్తుంది" - }, - "mark_as_read_and_save_in_chat": { - "name": "చాట్‌లో చదివినట్లుగా మార్క్ చేసి సేవ్ చేయండి", - "description": "నోటిఫికేషన్‌కు చదివినట్లుగా మార్క్ చేసి చాట్ బటన్‌లో సేవ్ చేయండి" - } - } - }, - "notification_blacklist": { - "name": "నోటిఫికేషన్ బ్లాక్‌లిస్ట్", - "description": "బ్లాక్ చేయవలసిన నోటిఫికేషన్లను ఎంచుకోండి" - }, - "message_logger": { - "name": "సందేశ లాగర్", - "description": "సందేశాలను తొలగించకుండా నిరోధిస్తుంది", - "properties": { - "keep_my_own_messages": { - "name": "నా స్వంత సందేశాలను ఉంచండి", - "description": "మీ స్వంత సందేశాలను తొలగించకుండా నిరోధిస్తుంది" - }, - "auto_purge": { - "name": "ఆటో ప్రక్షాళన", - "description": "పేర్కొన్న సమయం కంటే పాత కాష్ సందేశాలను స్వయంచాలకంగా తొలగిస్తుంది" - }, - "message_filter": { - "name": "సందేశ వడపోత", - "description": "ఏ సందేశాలు లాగిన్ కావాలో ఎంచుకోండి (అన్ని సందేశాలకు ఖాళీ)" - }, - "deleted_message_color": { - "name": "తొలగించిన సందేశ రంగు", - "description": "తొలగించిన సందేశాల రంగును సెట్ చేస్తుంది" - } - } - }, - "auto_save_messages_in_conversations": { - "name": "ఆటో సేవ్ సందేశాలు", - "description": "సంభాషణలలో ప్రతి సందేశాన్ని స్వయంచాలకంగా సేవ్ చేస్తుంది" - }, - "gallery_media_send_override": { - "name": "గ్యాలరీ మీడియా ఓవర్‌రైడ్ పంపండి", - "description": "గ్యాలరీ నుండి పంపేటప్పుడు మీడియా మూలాన్ని స్పూఫ్ చేస్తుంది" - }, - "strip_media_metadata": { - "name": "స్ట్రిప్ మీడియా మెటాడేటా", - "description": "సందేశంగా పంపే ముందు మీడియా యొక్క మెటాడేటాను తొలగిస్తుంది" - }, - "bypass_message_retention_policy": { - "name": "బైపాస్ సందేశ నిలుపుదల విధానం", - "description": "సందేశాలను చూసిన తర్వాత తొలగించకుండా నిరోధిస్తుంది" - }, - "bypass_message_action_restrictions": { - "name": "బైపాస్ సందేశ చర్య పరిమితులు", - "description": "స్నాప్‌కు తెరవకుండా లేదా సేవ్ చేయలేని సందేశాన్ని సేవ్ చేయకుండా స్పందించడానికి మిమ్మల్ని అనుమతిస్తుంది" - }, - "remove_groups_locked_status": { - "name": "సమూహాలు లాక్ చేసిన స్థితిని తొలగించండి", - "description": "తన్నబడిన తర్వాత సమూహ సమాచారాన్ని చూడటానికి మిమ్మల్ని అనుమతిస్తుంది" - }, - "double_tap_chat_action": { - "name": "డబుల్ ట్యాప్ చాట్ చర్య", - "description": "చాట్‌లో సందేశాన్ని డబుల్ నొక్కేటప్పుడు అనుకూల చర్య చేస్తుంది" - }, - "double_tap_chat_action_custom_emoji": { - "name": "డబుల్ ట్యాప్ చాట్ చర్య కస్టమ్ ఎమోజి ప్రతిచర్య", - "description": "డబుల్ ట్యాప్ చాట్ చర్య కోసం అనుకూల ఎమోజి ప్రతిచర్యను సెట్ చేస్తుంది" - } - } - }, - "global": { - "name": "గ్లోబల్", - "description": "గ్లోబల్ స్నాప్‌చాట్ సెట్టింగులను సర్దుబాటు చేయండి", - "properties": { - "better_location": { - "name": "మంచి స్థానం", - "description": "స్నాప్‌చాట్ స్థానాన్ని పెంచుతుంది", - "properties": { - "spoof_location": { - "name": "స్పూఫ్ స్థానం", - "description": "మీ స్థానాన్ని పేర్కొన్నదానికి స్పూఫ్ చేస్తుంది" - }, - "coordinates": { - "name": "కోఆర్డినేట్లు", - "description": "స్పూఫ్డ్ స్థానం యొక్క కోఆర్డినేట్లను సెట్ చేయండి" - }, - "walk_radius": { - "name": "నడక వ్యాసార్థం", - "description": "యాదృచ్చికంగా ఈ వ్యాసార్థం (FT) లోపల నడవండి" - }, - "always_update_location": { - "name": "స్థానాన్ని ఎల్లప్పుడూ నవీకరించండి", - "description": "GPS డేటా రాకపోయినా స్థానాన్ని నవీకరించడానికి స్నాప్‌చాట్‌ను బలవంతం చేయండి" - }, - "suspend_location_updates": { - "name": "స్థాన నవీకరణలను నిలిపివేయండి", - "description": "మీ స్థానం నవీకరించబడకుండా నిరోధిస్తుంది" - }, - "spoof_battery_level": { - "name": "స్పూఫ్ బ్యాటరీ స్థాయి", - "description": "మ్యాప్‌లో మీ పరికరం యొక్క బ్యాటరీ స్థాయిని స్పూఫ్ చేస్తుంది\nవిలువ 0 మరియు 100 మధ్య ఉండాలి" - }, - "spoof_headphones": { - "name": "స్పూఫ్ హెడ్‌ఫోన్‌లు", - "description": "మ్యాప్‌లో సంగీతాన్ని వినే స్థితిని స్పూఫ్ చేస్తుంది" - }, - "show_battery_level": { - "name": "బ్యాటరీ స్థాయిని చూపించు", - "description": "మ్యాప్‌లో మీ స్నేహితుల బ్యాటరీ స్థాయిని చూపిస్తుంది" - } - } - }, - "snapchat_plus": { - "name": "స్నాప్‌చాట్ ప్లస్", - "description": "స్నాప్‌చాట్ ప్లస్ లక్షణాలను ప్రారంభిస్తుంది\nకొన్ని సర్వర్-సైడెడ్ లక్షణాలు పనిచేయకపోవచ్చు" - }, - "media_upload_quality": { - "name": "మీడియా అప్‌లోడ్ నాణ్యత", - "description": "మీడియా అప్‌లోడ్ నాణ్యతను అధిగమిస్తుంది", - "properties": { - "force_video_upload_source_quality": { - "name": "ఫోర్స్ వీడియో అప్‌లోడ్ మూలం నాణ్యత", - "description": "వీడియోలను అప్‌లోడ్ చేసేటప్పుడు మూల నాణ్యతను ఉపయోగించడానికి స్నాప్‌చాట్‌ను బలవంతం చేస్తుంది\nఇది మీడియా నుండి మెటాడేటాను తొలగించకపోవచ్చని దయచేసి గమనించండి" - }, - "disable_image_compression": { - "name": "చిత్ర కుదింపును నిలిపివేయండి", - "description": "మీడియాను అప్‌లోడ్ చేసేటప్పుడు చిత్ర కుదింపును నిలిపివేస్తుంది" - }, - "custom_image_upload_format": { - "name": "అనుకూల చిత్రం అప్‌లోడ్ ఫార్మాట్", - "description": "కస్టమ్ ఇమేజ్ అప్‌లోడ్ ఫార్మాట్‌ను సెట్ చేస్తుంది\nఉత్తమ నాణ్యత కోసం లాస్‌లెస్ ఫార్మాట్ (పిఎన్‌జి వంటివి) ఎంచుకోండి" - } - } - }, - "disable_confirmation_dialogs": { - "name": "నిర్ధారణ డైలాగ్‌లను నిలిపివేయండి", - "description": "ఎంచుకున్న చర్యలను స్వయంచాలకంగా నిర్ధారిస్తుంది" - }, - "auto_updater": { - "name": "ఆటో అప్‌డేటర్", - "description": "క్రొత్త నవీకరణల కోసం స్వయంచాలకంగా తనిఖీ చేస్తుంది" - }, - "disable_metrics": { - "name": "కొలమానాలను నిలిపివేయండి", - "description": "స్నాప్‌చాట్‌కు నిర్దిష్ట విశ్లేషణాత్మక డేటాను పంపే బ్లాక్‌లు" - }, - "disable_story_sections": { - "name": "కథ విభాగాలను నిలిపివేయండి", - "description": "కథల పేజీ నుండి విభాగాలను తొలగిస్తుంది\nసరిగ్గా పనిచేయడానికి రిఫ్రెష్ అవసరం కావచ్చు" - }, - "block_ads": { - "name": "ప్రకటనలను బ్లాక్ చేయండి", - "description": "ప్రకటనలను ప్రదర్శించకుండా నిరోధిస్తుంది" - }, - "disable_custom_tabs": { - "name": "కస్టమ్ ట్యాబ్‌లను నిలిపివేయండి", - "description": "వెబ్ బ్రౌజర్‌లో కాకుండా మద్దతు ఉన్న అనువర్తనాల్లో లింక్‌లను తెరుస్తుంది" - }, - "disable_permission_requests": { - "name": "అనుమతి అభ్యర్థనలను నిలిపివేయండి", - "description": "నిర్దిష్ట అనుమతులు అడగకుండా స్నాప్‌చాట్ నిరోధిస్తుంది" - }, - "disable_memories_snap_feed": { - "name": "జ్ఞాపకాలు స్నాప్ ఫీడ్ను నిలిపివేయండి", - "description": "మీరు కెమెరాలో స్వైప్ చేసినప్పుడు స్నాప్‌చాట్ ఇటీవలి జ్ఞాపకాలను చూపించకుండా నిరోధిస్తుంది" - }, - "spotlight_comments_username": { - "name": "స్పాట్‌లైట్ వ్యాఖ్యలు వినియోగదారు పేరు", - "description": "స్పాట్‌లైట్ వ్యాఖ్యలలో రచయిత వినియోగదారు పేరు చూపిస్తుంది" - }, - "bypass_video_length_restriction": { - "name": "వీడియో పొడవు పరిమితులను బైపాస్ చేయండి", - "description": "సింగిల్: ఒకే వీడియోను పంపుతుంది\nస్ప్లిట్: ఎడిటింగ్ తర్వాత వీడియోలను విభజించండి" - }, - "default_video_playback_rate": { - "name": "డిఫాల్ట్ వీడియో ప్లేబ్యాక్ రేటు", - "description": "వీడియోల ప్లేబ్యాక్ కోసం డిఫాల్ట్ వేగాన్ని సెట్ చేస్తుంది\nవిలువ 0.1 మరియు 4.0 మధ్య ఉండాలి" - }, - "video_playback_rate_slider": { - "name": "వీడియో ప్లేబ్యాక్ రేట్ స్లైడర్", - "description": "వీడియో ప్లేబ్యాక్ రేటును మార్చడానికి ఒపెరా కాంటెక్స్ట్ మెనులో స్లైడర్‌ను జోడిస్తుంది\nగమనిక: మార్పులు తదుపరి వీడియోలకు మాత్రమే వర్తిస్తాయి" - }, - "disable_google_play_dialogs": { - "name": "గూగుల్ ప్లే సేవల డైలాగ్‌లను నిలిపివేయండి", - "description": "గూగుల్ ప్లే సేవల లభ్యత డైలాగ్‌లు చూపబడకుండా నిరోధించండి" - }, - "default_volume_controls": { - "name": "డిఫాల్ట్ వాల్యూమ్ నియంత్రణలు", - "description": "సిస్టమ్ వాల్యూమ్ నియంత్రణలను ఉపయోగించడానికి స్నాప్‌చాట్‌ను బలవంతం చేస్తుంది" - }, - "disable_telecom_framework": { - "name": "టెలికాం ఫ్రేమ్‌వర్క్‌ను నిలిపివేయండి", - "description": "ఆండ్రాయిడ్ టెలికాం ఫ్రేమ్‌వర్క్‌ను ఉపయోగించకుండా స్నాప్‌చాట్ నిరోధిస్తుంది\nఇది కాల్‌లో ఉన్నప్పుడు సంగీతాన్ని వినడానికి మిమ్మల్ని అనుమతిస్తుంది" - }, - "hide_active_music": { - "name": "క్రియాశీల సంగీతాన్ని దాచండి", - "description": "మీరు సంగీతాన్ని వింటున్నట్లు తెలుసుకోకుండా స్నాప్‌చాట్ నిరోధిస్తుంది\nసంగీతం వినేటప్పుడు కంట్రోల్ వాల్యూమ్ బటన్లను ఉపయోగించి స్నాప్‌లు తీసుకోవడానికి ఇది మిమ్మల్ని అనుమతిస్తుంది" - }, - "disable_snap_splitting": { - "name": "స్నాప్ విభజనను నిలిపివేయండి", - "description": "స్నాప్‌లను బహుళ భాగాలుగా విభజించకుండా నిరోధిస్తుంది\nమీరు పంపే చిత్రాలు వీడియోలుగా మారుతాయి" - } - } - }, - "rules": { - "name": "నియమాలు", - "description": "వ్యక్తిగత వ్యక్తుల కోసం స్వయంచాలక లక్షణాలను నిర్వహించండి" - }, - "camera": { - "name": "కెమెరా", - "description": "ఖచ్చితమైన స్నాప్ కోసం సరైన సెట్టింగులను సర్దుబాటు చేయండి", - "properties": { - "disable_cameras": { - "name": "కెమెరాలను నిలిపివేయండి", - "description": "ఎంచుకున్న కెమెరాలను ఉపయోగించకుండా స్నాప్‌చాట్ నిరోధిస్తుంది" - }, - "black_photos": { - "name": "నల్ల ఫోటోలు", - "description": "సంగ్రహించిన ఫోటోలను నల్లని నేపథ్యంతో భర్తీ చేస్తుంది\nవీడియోలు ప్రభావితం కావు" - }, - "immersive_camera_preview": { - "name": "లీనమయ్యే ప్రివ్యూ", - "description": "కెమెరా ప్రివ్యూను కత్తిరించకుండా స్నాప్‌చాట్ నిరోధిస్తుంది\nఇది కొన్ని పరికరాల్లో కెమెరా ఆడుకోవడానికి కారణం కావచ్చు" - }, - "override_front_resolution": { - "name": "ఫ్రంట్ రిజల్యూషన్‌ను భర్తీ చేయండి", - "description": "ముందు కెమెరా కోసం కెమెరా రిజల్యూషన్‌ను భర్తీ చేస్తుంది" - }, - "override_back_resolution": { - "name": "తిరిగి రిజల్యూషన్‌ను భర్తీ చేయండి", - "description": "వెనుక కెమెరా కోసం కెమెరా రిజల్యూషన్‌ను భర్తీ చేస్తుంది" - }, - "custom_resolution": { - "name": "అనుకూల తీర్మానం", - "description": "కస్టమ్ కెమెరా రిజల్యూషన్, వెడల్పు x ఎత్తు (ఉదా. 1920x1080) ను సెట్ చేస్తుంది.\nకస్టమ్ రిజల్యూషన్‌కు మీ పరికరం మద్దతు ఇవ్వాలి" - }, - "front_custom_frame_rate": { - "name": "ఫ్రంట్ కస్టమ్ ఫ్రేమ్ రేట్", - "description": "ఫ్రంట్ కెమెరా ఫ్రేమ్ రేటును అధిగమిస్తుంది" - }, - "back_custom_frame_rate": { - "name": "కస్టమ్ ఫ్రేమ్ రేట్ బ్యాక్", - "description": "వెనుక కెమెరా ఫ్రేమ్ రేటును అధిగమిస్తుంది" - }, - "force_camera_source_encoding": { - "name": "ఫోర్స్ కెమెరా సోర్స్ ఎన్కోడింగ్", - "description": "కెమెరా సోర్స్ ఎన్కోడింగ్ను బలవంతం చేస్తుంది" - }, - "startup_default_camera": { - "name": "స్టార్టప్ డిఫాల్ట్ కెమెరా", - "description": "స్నాప్‌చాట్ తెరిచేటప్పుడు డిఫాల్ట్ కెమెరాను సెట్ చేస్తుంది" - }, - "hevc_recording": { - "name": "HEVC రికార్డింగ్", - "description": "వీడియో రికార్డింగ్ కోసం HEVC (H.265) కోడెక్‌ను ఉపయోగిస్తుంది" - } - } - }, - "streaks_reminder": { - "name": "స్ట్రీక్స్ రిమైండర్", - "description": "మీ స్ట్రీక్స్ గురించి క్రమానుగతంగా మీకు తెలియజేస్తుంది", - "properties": { - "interval": { - "name": "విరామం", - "description": "ప్రతి రిమైండర్ (గంటలు) మధ్య విరామం" - }, - "remaining_hours": { - "name": "మిగిలిన సమయం", - "description": "నోటిఫికేషన్ చూపించడానికి ముందు మిగిలిన సమయం (గంటలు)" - }, - "group_notifications": { - "name": "సమూహ నోటిఫికేషన్‌లు", - "description": "సమూహ నోటిఫికేషన్‌లు ఒకే విధంగా" - } - } - }, - "experimental": { - "name": "ప్రయోగాత్మక", - "description": "ప్రయోగాత్మక లక్షణాలు", - "properties": { - "native_hooks": { - "name": "స్థానిక హుక్స్", - "description": "స్నాప్‌చాట్ యొక్క స్థానిక కోడ్‌లోకి హుక్ చేసే అసురక్షిత లక్షణాలు", - "properties": { - "composer_hooks": { - "name": "స్వరకర్త హుక్స్", - "description": "కంపోజర్ క్రాస్-ప్లాట్‌ఫాం UI ఫ్రేమ్‌వర్క్‌లో కోడ్‌ను ఇంజెక్ట్ చేస్తుంది", - "properties": { - "show_first_created_username": { - "name": "మొదట సృష్టించిన వినియోగదారు పేరును చూపించు", - "description": "ప్రొఫైల్ పేజీలోని ప్రస్తుత వినియోగదారు పేరు పక్కన మొదటి సృష్టించిన వినియోగదారు పేరు చూపిస్తుంది" - }, - "bypass_camera_roll_limit": { - "name": "బైపాస్ కెమెరా రోల్ పరిమితి", - "description": "కెమెరా రోల్ నుండి మీరు పంపగల మీడియా గరిష్ట మొత్తాన్ని పెంచుతుంది" - }, - "custom_self_destruct_snap_delay": { - "name": "కస్టమ్ సెల్ఫ్ డిస్ట్రక్ట్ స్నాప్ ఆలస్యం", - "description": "స్నాప్ పంపేటప్పుడు స్వీయ-నాశనం టైమర్ కోసం మరిన్ని ఎంపికలను ఇస్తుంది" - }, - "composer_console": { - "name": "స్వరకర్త కన్సోల్", - "description": "స్వరకర్త (ARM64 మాత్రమే) లో జావాస్క్రిప్ట్ కోడ్‌ను అమలు చేయడానికి మిమ్మల్ని అనుమతిస్తుంది" - }, - "composer_logs": { - "name": "స్వరకర్త లాగ్‌లు", - "description": "స్వరకర్త యొక్క కన్సోల్ లాగ్‌లను పర్ఫెక్ట్స్నాప్‌కు మళ్ళిస్తుంది" - } - } - }, - "disable_bitmoji": { - "name": "బిట్‌మోజీని నిలిపివేయండి", - "description": "స్నేహితుల ప్రొఫైల్ బిట్‌మోజీని నిలిపివేస్తుంది" - }, - "custom_emoji_font": { - "name": "కస్టమ్ ఎమోజి ఫాంట్", - "description": "అనుకూల ఎమోజి ఫాంట్‌ను ఉపయోగించడానికి మిమ్మల్ని అనుమతిస్తుంది. .TTF ఫాంట్‌లతో మాత్రమే పనిచేస్తుంది" - }, - "custom_shared_library": { - "name": "కస్టమ్ షేర్డ్ లైబ్రరీ", - "description": "కస్టమ్ షేర్డ్ లైబ్రరీని స్నాప్‌చాట్‌లో లోడ్ చేస్తుంది. ఈ లక్షణం పరీక్షా ప్రయోజనాల కోసం మాత్రమే" - } - } - }, - "spoof": { - "name": "స్పూఫ్", - "description": "మీ గురించి వివిధ సమాచారాన్ని స్పూఫ్ చేయండి", - "properties": { - "play_store_installer_package_name": { - "name": "ప్లే స్టోర్ ఇన్‌స్టాలర్ ప్యాకేజీ పేరు", - "description": "ఇన్స్టాలర్ ప్యాకేజీ పేరును com.android.vending కు భర్తీ చేస్తుంది" - }, - "remove_vpn_transport_flag": { - "name": "VPN రవాణా జెండాను తొలగించండి", - "description": "స్నాప్‌చాట్ VPN లను గుర్తించకుండా నిరోధిస్తుంది" - }, - "remove_mock_location_flag": { - "name": "మాక్ స్థాన జెండాను తొలగించండి", - "description": "మాక్ స్థానాన్ని గుర్తించకుండా స్నాప్‌చాట్ నిరోధిస్తుంది" - } - } - }, - "convert_message_locally": { - "name": "స్థానికంగా సందేశాన్ని మార్చండి", - "description": "స్థానికంగా బాహ్య మాధ్యమాన్ని చాట్ చేయడానికి స్నాప్‌లను మారుస్తుంది. ఇది చాట్ డౌన్‌లోడ్ కాంటెక్స్ట్ మెనులో కనిపిస్తుంది" - }, - "media_file_picker": { - "name": "మీడియా ఫైల్ పికర్", - "description": "గ్యాలరీ నుండి ఏదైనా వీడియో/ఆడియో ఫైల్‌ను ఎంచుకోవడానికి మిమ్మల్ని అనుమతిస్తుంది" - }, - "story_logger": { - "name": "స్టోరీ లాగర్", - "description": "స్నేహితుల కథల చరిత్రను అందిస్తుంది" - }, - "call_recorder": { - "name": "కాల్ రికార్డర్", - "description": "ఆడియో కాల్‌లను స్వయంచాలకంగా రికార్డ్ చేస్తుంది" - }, - "account_switcher": { - "name": "ఖాతా స్విచ్చర్", - "description": "లాగిన్ చేయకుండా ఖాతాల మధ్య మారడానికి మిమ్మల్ని అనుమతిస్తుంది\nమెనుని తెరవడానికి మీ బిట్‌మోజీ ప్రొఫైల్ పక్కన ఉన్న శోధన చిహ్నంపై ఎక్కువసేపు నొక్కండి\nగమనిక: ఈ లక్షణం ప్రయోగాత్మకమైనది మరియు భవిష్యత్తులో మారుతుంది", - "properties": { - "auto_backup_current_account": { - "name": "ఆటో బ్యాకప్ ప్రస్తుత ఖాతా", - "description": "లాగ్ అవుట్ చేసేటప్పుడు లేదా ఖాతాలను మార్చేటప్పుడు ప్రస్తుత ఖాతాను స్వయంచాలకంగా బ్యాకప్ చేస్తుంది" - } - } - }, - "better_transcript": { - "name": "మంచి ట్రాన్స్క్రిప్ట్", - "description": "వాయిస్ నోట్ ట్రాన్స్క్రిప్ట్ను మెరుగుపరుస్తుంది", - "properties": { - "force_transcription": { - "name": "ఫోర్స్ వాయిస్ నోట్ ట్రాన్స్క్రిప్షన్", - "description": "అన్ని వాయిస్ నోట్లను లిప్యంతరీకరించడానికి అనుమతిస్తుంది" - }, - "preferred_transcription_lang": { - "name": "ఇష్టపడే ట్రాన్స్క్రిప్షన్ భాష", - "description": "వాయిస్ నోట్ ట్రాన్స్క్రిప్ట్ కోసం ఇష్టపడే భాష (ఉదా. EN, ES, FR)" - }, - "notification_transcript": { - "name": "నోటిఫికేషన్ ట్రాన్స్క్రిప్ట్", - "description": "నోటిఫికేషన్లలో వాయిస్ నోట్లను లిప్యంతరీకరిస్తుంది\nఈ లక్షణానికి చాట్ ప్రివ్యూ ఫీచర్ మంచి నోటిఫికేషన్లలో ప్రారంభించబడాలి" - } - } - }, - "voice_note_auto_play": { - "name": "వాయిస్ నోట్ ఆటో ప్లే", - "description": "ప్రస్తుత ఒకటి ముగిసిన తర్వాత స్వయంచాలకంగా తదుపరి వాయిస్ నోట్‌ను ప్లే చేస్తుంది" - }, - "friend_notes": { - "name": "ఫ్రెండ్ నోట్స్", - "description": "స్నేహితుల ప్రొఫైల్‌లకు గమనికలను జోడించడానికి మిమ్మల్ని అనుమతిస్తుంది" - }, - "cof_experiments": { - "name": "COF ప్రయోగాలు", - "description": "విడుదల చేయని/బీటా స్నాప్‌చాట్ లక్షణాలను ప్రారంభిస్తుంది" - }, - "context_menu_fix": { - "name": "సందర్భ మెను పరిష్కారం", - "description": "పరికరం ఆఫ్‌లైన్‌లో ఉన్నప్పుడు ఫ్రెండ్ ఫీడ్ మెనుని రిపేర్ చేసే ప్రయత్నం సరిగ్గా ప్రదర్శించబడదు" - }, - "app_lock": { - "name": "అనువర్తన లాక్", - "description": "పాస్‌కోడ్ లేకుండా స్నాప్‌చాట్‌కు ప్రాప్యతను నిరోధిస్తుంది", - "properties": { - "lock_on_resume": { - "name": "పున ume ప్రారంభం లాక్ చేయండి", - "description": "అనువర్తనం తిరిగి తెరిచినప్పుడు దాన్ని లాక్ చేస్తుంది" - } - } - }, - "infinite_story_boost": { - "name": "అనంతమైన కథ బూస్ట్", - "description": "కథను పెంచుతుంది పరిమితి ఆలస్యాన్ని పెంచుతుంది" - }, - "meo_passcode_bypass": { - "name": "నా కళ్ళు పాస్‌కోడ్ బైపాస్ మాత్రమే", - "description": "నా కళ్ళు పాస్‌కోడ్‌ను మాత్రమే దాటవేయండి\nపాస్‌కోడ్ ముందు సరిగ్గా నమోదు చేయబడితేనే ఇది పని చేస్తుంది" - }, - "no_friend_score_delay": { - "name": "ఫ్రెండ్ స్కోరు ఆలస్యం లేదు", - "description": "ఫ్రెండ్స్ స్కోర్‌ను చూసినప్పుడు ఆలస్యాన్ని తొలగిస్తుంది" - }, - "best_friend_pinning": { - "name": "బెస్ట్ ఫ్రెండ్ పిన్నింగ్", - "description": "స్నేహితుడిని మీ నంబర్ వన్ బెస్ట్ ఫ్రెండ్ గా పిన్ చేయడానికి మిమ్మల్ని అనుమతిస్తుంది. గమనిక: మీరు మాత్రమే పిన్ చేసిన బెస్ట్ ఫ్రెండ్‌ను చూడగలరు" - }, - "e2ee": { - "name": "ఎండ్-టు-ఎండ్ ఎన్క్రిప్షన్", - "description": "షేర్డ్ సీక్రెట్ కీని ఉపయోగించి మీ సందేశాలను AES తో గుప్తీకరిస్తుంది\nమీ కీని ఎక్కడో సురక్షితంగా సేవ్ చేసేలా చూసుకోండి!", - "properties": { - "encrypted_message_indicator": { - "name": "గుప్తీకరించిన సందేశ సూచిక", - "description": "గుప్తీకరించిన సందేశాల పక్కన 🔒 ఎమోజిని జోడిస్తుంది" - }, - "force_message_encryption": { - "name": "ఫోర్స్ మెసేజ్ ఎన్క్రిప్షన్", - "description": "బహుళ సంభాషణలు ఎంచుకున్నప్పుడు మాత్రమే E2E గుప్తీకరణ లేని వ్యక్తులకు గుప్తీకరించిన సందేశాలను పంపడాన్ని నిరోధిస్తుంది" - } - } - }, - "add_friend_source_spoof": { - "name": "ఫ్రెండ్ సోర్స్ స్పూఫ్ జోడించండి", - "description": "స్నేహితుల అభ్యర్థన యొక్క మూలాన్ని స్పూఫ్ చేస్తుంది" - }, - "hidden_snapchat_plus_features": { - "name": "దాచిన స్నాప్‌చాట్ ప్లస్ ఫీచర్స్", - "description": "విడుదల చేయని/బీటా స్నాప్‌చాట్ ప్లస్ లక్షణాలను ప్రారంభిస్తుంది\nపాత స్నాప్‌చాట్ వెర్షన్లలో పనిచేయకపోవచ్చు" - }, - "custom_streaks_expiration_format": { - "name": "కస్టమ్ స్ట్రీక్స్ గడువు ఆకృతి", - "description": "స్ట్రీక్స్ గడువు ఆకృతిని అనుకూలీకరిస్తుంది\n\nఅందుబాటులో ఉన్న వేరియబుల్స్:\n - %సి: స్ట్రీక్స్ లెక్కింపు\n - %ఇ: హర్గ్లాస్ ఎమోజి\n - %D: రోజులు\n - %H: గంటలు\n - %M: నిమిషాలు\n - %s: సెకన్లు\n - %W: మిగిలిన సమయం" - }, - "prevent_forced_logout": { - "name": "బలవంతపు లాగ్అవుట్‌ను నిరోధించండి", - "description": "మీరు మరొక పరికరంలో లాగిన్ అయినప్పుడు స్నాప్‌చాట్ మిమ్మల్ని లాగిన్ చేయకుండా నిరోధిస్తుంది" - }, - "snapscore_changes": { - "name": "స్నాప్‌స్కోర్ మార్పులు", - "description": "ఫ్రెండ్స్ స్నాప్‌స్కోర్‌లో ట్రాక్‌లు మార్పులు\nఈ లక్షణాన్ని స్నాప్‌చాట్ యొక్క క్రొత్త సంస్కరణల్లో మాత్రమే ఉపయోగించండి" - } - } - }, - "scripting": { - "name": "స్క్రిప్టింగ్", - "description": "పర్ఫెక్ట్స్నాప్‌ను విస్తరించడానికి కస్టమ్ స్క్రిప్ట్‌లను అమలు చేయండి", - "properties": { - "developer_mode": { - "name": "డెవలపర్ మోడ్", - "description": "స్నాప్‌చాట్ యొక్క UI లో డీబగ్ సమాచారాన్ని చూపిస్తుంది" - }, - "module_folder": { - "name": "మాడ్యూల్ ఫోల్డర్", - "description": "స్క్రిప్ట్‌లు ఉన్న ఫోల్డర్" - }, - "auto_reload": { - "name": "ఆటో రీలోడ్", - "description": "స్క్రిప్ట్‌లు మారినప్పుడు స్వయంచాలకంగా మళ్లీ లోడ్ చేస్తాయి" - }, - "integrated_ui": { - "name": "ఇంటిగ్రేటెడ్ UI", - "description": "స్నాప్‌చాట్‌కు కస్టమ్ UI భాగాలను జోడించడానికి స్క్రిప్ట్‌లను అనుమతిస్తుంది" - }, - "disable_log_anonymization": { - "name": "లాగ్ అనామకతను నిలిపివేయండి", - "description": "లాగ్ల అనామకతను నిలిపివేస్తుంది" - }, - "disable_optimization": { - "name": "ఆప్టిమైజేషన్‌ను నిలిపివేయండి", - "description": "స్క్రిప్ట్‌ల ఆప్టిమైజేషన్‌ను నిలిపివేస్తుంది. ఇది పనితీరు సమస్యలకు కారణం కావచ్చు." - } - } - }, - "friend_tracker": { - "name": "ఫ్రెండ్ ట్రాకర్", - "description": "స్నాప్‌చాట్‌లో స్నేహితుడి కార్యాచరణను రికార్డ్ చేస్తుంది", - "properties": { - "record_messaging_events": { - "name": "రికార్డ్ మెసేజింగ్ ఈవెంట్స్", - "description": "స్నాప్ తెరవడం, సందేశాన్ని చదవడం మొదలైన మెసేజింగ్ సంఘటనలను రికార్డ్ చేస్తుంది." - }, - "allow_running_in_background": { - "name": "నేపథ్యంలో నడపడానికి అనుమతించండి", - "description": "ట్రాకర్‌ను నేపథ్యంలో అమలు చేయడానికి అనుమతిస్తుంది. గమనిక: ఇది మీ బ్యాటరీని గణనీయంగా హరించడం" - }, - "auto_purge": { - "name": "ఆటో ప్రక్షాళన", - "description": "పేర్కొన్న సమయం కంటే పాత కాష్ చేసిన సంఘటనలను స్వయంచాలకంగా తొలగిస్తుంది" - } - } - } - }, - "options": { - "app_appearance": { - "always_light": "ఎల్లప్పుడూ తేలికైనది", - "always_dark": "ఎల్లప్పుడూ చీకటి" - }, - "friend_feed_menu_buttons": { - "auto_download": "Auto ఆటో డౌన్‌లోడ్", - "auto_save": "Auto ఆటో సేవ్ సందేశాలు", - "unsaveable_messages": "Saves సేవ్ చేయలేని సందేశాలు", - "auto_open_snaps": "Open ఆటో ఓపెన్ స్నాప్స్", - "stealth": "👻 స్టీల్త్ మోడ్", - "mark_snaps_as_seen": "Mark చూసినట్లు మార్క్ స్నాప్స్", - "mark_stories_as_seen_locally": "The స్థానికంగా చూసినట్లు కథలను గుర్తించండి", - "conversation_info": "సంభాషణ సమాచారం", - "e2e_encryption": "🔒 E2E గుప్తీకరణను ఉపయోగించండి" - }, - "path_format": { - "create_author_folder": "ప్రతి రచయిత కోసం ఫోల్డర్‌ను సృష్టించండి", - "create_source_folder": "ప్రతి మీడియా సోర్స్ రకం కోసం ఫోల్డర్‌ను సృష్టించండి", - "append_hash": "ఫైల్ పేరుకు ప్రత్యేకమైన హాష్‌ను జోడించండి", - "append_source": "ఫైల్ పేరుకు మీడియా మూలాన్ని జోడించండి", - "append_username": "ఫైల్ పేరుకు వినియోగదారు పేరును జోడించండి", - "append_date_time": "ఫైల్ పేరుకు తేదీ మరియు సమయాన్ని జోడించండి" - }, - "auto_download_sources": { - "friend_snaps": "స్నేహితుడు స్నాప్", - "friend_stories": "ఫ్రెండ్ కథలు", - "public_stories": "పబ్లిక్ స్టోరీస్", - "spotlight": "స్పాట్‌లైట్" - }, - "logging": { - "started": "ప్రారంభమైంది", - "success": "విజయం", - "progress": "పురోగతి", - "failure": "వైఫల్యం" - }, - "notifications": { - "chat_screenshot": "స్క్రీన్ షాట్", - "chat_screen_record": "స్క్రీన్ రికార్డ్", - "snap_replay": "స్నాప్ రీప్లే", - "camera_roll_save": "కెమెరా రోల్ సేవ్", - "chat": "చాట్", - "chat_reply": "చాట్ ప్రత్యుత్తరం", - "snap": "స్నాప్", - "typing": "టైపింగ్", - "stories": "కథలు", - "speaking": "మాట్లాడుతూ", - "chat_reaction": "DM ప్రతిచర్య", - "group_chat_reaction": "సమూహ ప్రతిచర్య", - "initiate_audio": "ఇన్కమింగ్ ఆడియో కాల్", - "abandon_audio": "ఆడియో కాల్ తప్పిపోయింది", - "initiate_video": "ఇన్‌కమింగ్ వీడియో కాల్", - "abandon_video": "వీడియో కాల్ తప్పిపోయింది", - "map_live_location": "మ్యాప్ లైవ్ స్థానం" - }, - "gallery_media_send_override": { - "always_ask": "ఎల్లప్పుడూ అడగండి", - "ORIGINAL": "అసలు మీడియా", - "NOTE": "ఆడియో నోట్", - "SNAP": "స్నాప్", - "SAVEABLE_SNAP": "సేవ్ చేయదగిన స్నాప్" - }, - "strip_media_metadata": { - "hide_caption_text": "శీర్షిక వచనాన్ని దాచండి", - "hide_snap_filters": "స్నాప్ ఫిల్టర్లను దాచండి", - "hide_extras": "అదనపు దాచు (ఉదా. ప్రస్తావనలు)", - "remove_audio_note_duration": "ఆడియో నోట్ వ్యవధిని తొలగించండి", - "remove_audio_note_transcript_capability": "ఆడియో నోట్ ట్రాన్స్క్రిప్ట్ సామర్థ్యాన్ని తొలగించండి" - }, - "hide_ui_components": { - "hide_profile_call_buttons": "ప్రొఫైల్ కాల్ బటన్లను తొలగించండి", - "hide_chat_call_buttons": "చాట్ కాల్ బటన్లను తొలగించండి", - "hide_live_location_share_button": "లైవ్ లొకేషన్ షేర్ బటన్‌ను తొలగించండి", - "hide_stickers_button": "స్టిక్కర్ల బటన్ తొలగించండి", - "hide_voice_record_button": "వాయిస్ రికార్డ్ బటన్ తొలగించండి", - "hide_unread_chat_hint": "చదవని చాట్ సూచనను తొలగించండి", - "hide_post_to_story_buttons": "స్నాప్ పంపే ముందు స్టోరీ బటన్లకు పోస్ట్‌ను తొలగించండి", - "hide_billboard_prompt": "స్నేహితుల ఫీడ్‌లో బిల్‌బోర్డ్ ప్రాంప్ట్ తొలగించండి", - "hide_snapchat_plus_gift_reminders": "సంభాషణలలో స్నాప్‌చాట్ ప్లస్ గిఫ్ట్ రిమైండర్‌లను తొలగించండి", - "hide_map_reactions": "మ్యాప్ ప్రతిచర్యలను తొలగించండి" - }, - "hide_story_suggestions": { - "hide_suggested_friend_stories": "సూచించిన స్నేహితుడి కథలను దాచండి", - "hide_my_stories": "నా కథలను దాచండి" - }, - "home_tab": { - "map": "మ్యాప్", - "chat": "చాట్", - "camera": "కెమెరా", - "discover": "కనుగొనండి", - "spotlight": "స్పాట్‌లైట్" - }, - "add_friend_source_spoof": { - "added_by_username": "వినియోగదారు పేరు ద్వారా", - "added_by_mention": "ప్రస్తావించడం ద్వారా", - "added_by_group_chat": "సమూహ చాట్ ద్వారా", - "added_by_qr_code": "QR కోడ్ ద్వారా", - "added_by_community": "సంఘం ద్వారా", - "added_by_quick_add": "శీఘ్ర జోడించడం ద్వారా (నిషేధించబడే అధిక ప్రమాదం)" - }, - "bypass_video_length_restriction": { - "single": "సింగిల్ మీడియా", - "split": "స్ప్లిట్ మీడియా" - }, - "old_bitmoji_selfie": { - "2d": "2 డి బిట్‌మోజీ", - "3d": "3 డి బిట్‌మోజీ" - }, - "disable_confirmation_dialogs": { - "erase_message": "సందేశాన్ని తొలగించండి", - "remove_friend": "స్నేహితుడిని తొలగించండి", - "block_friend": "బ్లాక్ ఫ్రెండ్", - "ignore_friend": "స్నేహితుడిని విస్మరించండి", - "hide_friend": "స్నేహితుడు దాచు", - "hide_conversation": "సంభాషణను దాచండి", - "clear_conversation": "ఫ్రెండ్ ఫీడ్ నుండి స్పష్టమైన సంభాషణ" - }, - "auto_reload": { - "snapchat_only": "స్నాప్‌చాట్ మాత్రమే", - "all": "అన్నీ (స్నాప్‌చాట్ + పర్ఫెక్ట్స్నాప్)" - }, - "edit_text_override": { - "multi_line_chat_input": "మల్టీ లైన్ చాట్ ఇన్పుట్", - "bypass_text_input_limit": "బైపాస్ టెక్స్ట్ ఇన్పుట్ పరిమితి" - }, - "auto_purge": { - "never": "ఎప్పుడూ", - "1_hour": "1 గంట", - "3_hours": "3 గంటలు", - "6_hours": "6 గంటలు", - "12_hours": "12 గంటలు", - "1_day": "1 రోజు", - "3_days": "3 రోజులు", - "1_week": "1 వారం", - "2_weeks": "2 వారాలు", - "1_month": "1 నెల", - "3_months": "3 నెలలు", - "6_months": "6 నెలలు" - }, - "disable_story_sections": { - "friends": "స్నేహితులు", - "suggested_stories": "సూచించిన కథలు", - "following": "క్రింది", - "discover": "కనుగొనండి" - }, - "disable_cameras": { - "front": "ఫ్రంట్ కెమెరా", - "back": "వెనుక కెమెరా" - }, - "disable_permission_requests": { - "notifications": "నోటిఫికేషన్‌లు", - "read_media_images": "మీడియా చిత్రాలను చదవండి", - "read_media_video": "మీడియా వీడియో చదవండి", - "camera": "కెమెరా", - "microphone": "మైక్రోఫోన్", - "location": "స్థానం", - "read_contacts": "పరిచయాలను చదవండి", - "nearby_devices": "సమీప పరికరాలు", - "phone_calls": "ఫోన్ కాల్స్" - }, - "message_indicators": { - "encryption_indicator": "మీకు మాత్రమే పంపబడిన సందేశాల పక్కన 🔒 చిహ్నాన్ని జోడిస్తుంది", - "platform_indicator": "మీడియా పంపిన ప్లాట్‌ఫాం చిహ్నాన్ని జోడిస్తుంది (ఉదా. ఆండ్రాయిడ్, iOS, వెబ్)", - "location_indicator": "స్థాన ప్రారంభించబడినప్పుడు వాటిని పంపినప్పుడు స్నాప్‌లకు 📍 చిహ్నాన్ని జోడిస్తుంది", - "ovf_editor_indicator": "OVF ఎడిటర్ ఉపయోగించి స్నాప్ పంపబడిందా అని సూచిస్తుంది", - "director_mode_indicator": "డైరెక్టర్ మోడ్‌ను ఉపయోగించి పంపినప్పుడు స్నాప్‌లకు ✏ ఐకాన్‌ను జోడిస్తుంది, ఇది గ్యాలరీ చిత్రాలను స్నాప్‌లుగా పంపడానికి ఉపయోగపడుతుంది" - }, - "auto_mark_as_read": { - "conversation_read": "సందేశాన్ని పంపేటప్పుడు సంభాషణను చదవండి", - "snap_reply": "వారికి ప్రత్యుత్తరం ఇచ్చేటప్పుడు చదివినట్లుగా మార్క్ స్నాప్‌లు", - "save_snap_in_chat": "స్టీల్త్ మోడ్‌లో ఉన్నప్పుడు చాట్‌లో వాటిని సేవ్ చేసేటప్పుడు మార్క్ స్నాప్‌లను చదవండి" - }, - "friend_mutation_notifier": { - "remove_friend": "ఎవరైనా మిమ్మల్ని స్నేహితుడిగా తొలగించినప్పుడు తెలియజేయండి", - "birthday_changes": "ఎవరైనా వారి పుట్టినరోజును మార్చినప్పుడు తెలియజేయండి", - "bitmoji_selfie_changes": "ఎవరైనా వారి బిట్‌మోజీ సెల్ఫీని మార్చినప్పుడు తెలియజేయండి", - "bitmoji_avatar_changes": "ఎవరైనా వారి బిట్‌మోజీ అవతార్‌ను మార్చినప్పుడు తెలియజేయండి", - "bitmoji_background_changes": "ఎవరైనా వారి బిట్‌మోజీ నేపథ్యాన్ని మార్చినప్పుడు తెలియజేయండి", - "bitmoji_scene_changes": "ఎవరైనా వారి బిట్‌మోజీ దృశ్యాన్ని మార్చినప్పుడు తెలియజేయండి" - }, - "snapchat_plus": { - "not_subscribed": "చందా పొందలేదు", - "basic": "ప్రాథమిక", - "ad_free": "ప్రకటన ఉచితం" - }, - "double_tap_chat_action": { - "like_message": "సందేశం వంటిది", - "copy_text": "క్లిప్‌బోర్డ్‌కు వచనాన్ని కాపీ చేయండి", - "delete_message": "సందేశాన్ని తొలగించండి", - "mark_as_read": "చదవడానికి గుర్తించండి", - "custom_emoji_reaction": "కస్టమ్ ఎమోజి ప్రతిచర్య" - }, - "startup_default_camera": { - "front": "ఫ్రంట్ కెమెరా", - "back": "వెనుక కెమెరా" - } - } - }, - "friend_menu_option": { - "mark_snaps_as_seen": "చూసినట్లు మార్క్ స్నాప్స్", - "mark_stories_as_seen_locally": "స్థానికంగా చూసినట్లు కథలను గుర్తించండి", - "preview": "ప్రివ్యూ", - "stealth_mode": "స్టీల్త్ మోడ్", - "auto_download_blacklist": "ఆటో డౌన్‌లోడ్ బ్లాక్లిస్ట్", - "anti_auto_save": "యాంటీ ఆటో సేవ్" - }, - "content_type": { - "CHAT": "చాట్", - "SNAP": "స్నాప్", - "EXTERNAL_MEDIA": "బాహ్య మీడియా", - "NOTE": "ఆడియో నోట్", - "STICKER": "స్టిక్కర్", - "SHARE": "వాటా", - "STATUS": "స్థితి", - "LOCATION": "స్థానం", - "STATUS_SAVE_TO_CAMERA_ROLL": "కెమెరా రోల్‌కు సేవ్ చేయబడింది", - "STATUS_CONVERSATION_CAPTURE_SCREENSHOT": "స్క్రీన్ షాట్", - "STATUS_CONVERSATION_CAPTURE_RECORD": "స్క్రీన్ రికార్డ్", - "STATUS_CALL_MISSED_VIDEO": "వీడియో కాల్ తప్పిపోయింది", - "STATUS_CALL_MISSED_AUDIO": "ఆడియో కాల్ తప్పిపోయింది", - "LIVE_LOCATION_SHARE": "ప్రత్యక్ష స్థాన వాటా", - "CREATIVE_TOOL_ITEM": "సృజనాత్మక సాధన అంశం", - "FAMILY_CENTER_INVITE": "కుటుంబ కేంద్రం ఆహ్వానం", - "FAMILY_CENTER_ACCEPT": "కుటుంబ కేంద్రం అంగీకరిస్తుంది", - "FAMILY_CENTER_LEAVE": "కుటుంబ కేంద్రం సెలవు", - "STATUS_PLUS_GIFT": "స్థితి ప్లస్ బహుమతి", - "TINY_SNAP": "చిన్న స్నాప్", - "STATUS_COUNTDOWN": "కౌంట్‌డౌన్", - "MAP_REACTION": "మ్యాప్ ప్రతిచర్య" - }, - "media_download_source": { - "none": "ఏదీ లేదు", - "pending": "పెండింగ్‌లో ఉంది", - "chat_media": "చాట్ మీడియా", - "story": "కథ", - "public_story": "పబ్లిక్ స్టోరీ", - "spotlight": "స్పాట్‌లైట్", - "profile_picture": "ప్రొఫైల్ చిత్రం", - "story_logger": "స్టోరీ లాగర్", - "message_logger": "సందేశ లాగర్", - "merged": "విలీనం", - "voice_call": "వాయిస్ కాల్" - }, - "chat_action_menu": { - "preview_button": "ప్రివ్యూ", - "download_button": "డౌన్‌లోడ్", - "delete_logged_message_button": "లాగిన్ చేసిన సందేశాన్ని తొలగించండి", - "show_chat_edit_history": "చాట్ సవరణ చరిత్రను చూపించు", - "convert_message": "సందేశాన్ని మార్చండి" - }, - "opera_context_menu": { - "download": "మీడియాను డౌన్‌లోడ్ చేయండి", - "sent_at": "{date} వద్ద పంపబడింది", - "created_at": "{date} వద్ద సృష్టించబడింది", - "expires_at": "{date} వద్ద ముగుస్తుంది", - "media_size": "మీడియా పరిమాణం: {size}", - "media_duration": "మీడియా వ్యవధి: {duration} MS", - "show_debug_info": "డీబగ్ సమాచారం చూపించు" - }, - "modal_option": { - "profile_info": "ప్రొఫైల్ సమాచారం", - "close": "దగ్గరగా" - }, - "gallery_media_send_override": { - "multiple_media_toast": "మీరు ఒకేసారి ఒక మీడియాను మాత్రమే పంపగలరు" - }, - "mark_as_seen": { - "no_unseen_snaps_toast": "కనిపించని స్నాప్‌లు కనుగొనబడలేదు!", - "seen_toast": "చూసినట్లు గుర్తించబడింది!", - "unseen_toast": "కనిపించనిదిగా గుర్తించబడింది!", - "already_seen_toast": "ఇప్పటికే చూసినట్లుగా గుర్తించబడింది!", - "already_unseen_toast": "ఇప్పటికే కనిపించనిదిగా గుర్తించబడింది!" - }, - "conversation_preview": { - "streak_expiration": "{day} రోజులలో ముగుస్తుంది {hour} గంటలు {minute} నిమిషాలు", - "total_messages": "మొత్తం పంపిన/స్వీకరించిన సందేశాలు: {count}", - "title": "ప్రివ్యూ", - "unknown_user": "తెలియని వినియోగదారు", - "no_messages": "సందేశాలు కనుగొనబడలేదు!" - }, - "profile_info": { - "title": "ప్రొఫైల్ సమాచారం", - "first_created_username": "మొదట సృష్టించబడిన వినియోగదారు పేరు", - "mutable_username": "మార్చగల వినియోగదారు పేరు", - "display_name": "ప్రదర్శన పేరు", - "added_date": "తేదీ జోడించబడింది", - "birthday": "పుట్టినరోజు: {month} {day}", - "hidden_birthday": "పుట్టినరోజు: దాచబడింది", - "friendship": "స్నేహం", - "add_source": "మూలాన్ని జోడించండి", - "snapchat_plus": "స్నాప్‌చాట్ ప్లస్", - "snapchat_plus_state": { - "subscribed": "చందా", - "not_subscribed": "చందా పొందలేదు" - } - }, - "friendship_link_type": { - "mutual": "మ్యూచువల్", - "outgoing": "అవుట్గోయింగ్", - "blocked": "నిరోధించబడింది", - "deleted": "తొలగించబడింది", - "following": "క్రింది", - "suggested": "సూచించబడింది", - "incoming": "ఇన్కమింగ్", - "incoming_follower": "ఇన్కమింగ్ అనుచరుడు" - }, - "bulk_messaging_action": { - "choose_action_title": "చర్యను ఎంచుకోండి", - "progress_status": "{index} యొక్క ప్రాసెసింగ్ {total}", - "selection_dialog_continue_button": "కొనసాగించండి", - "confirmation_dialog": { - "title": "మీకు ఖచ్చితంగా తెలుసా?", - "message": "ఇది ఎంచుకున్న స్నేహితులందరినీ ప్రభావితం చేస్తుంది. ఈ చర్యను రద్దు చేయలేము." - }, - "actions": { - "remove_friends": "స్నేహితులను తొలగించండి", - "clear_conversations": "స్పష్టమైన సంభాషణలు" - } - }, - "chat_export": { - "exporter_dialog": { - "select_conversations_title": "సంభాషణలను ఎంచుకోండి", - "text_field_selection": "{amount} ఎంచుకున్నారు", - "text_field_selection_all": "అన్నీ", - "export_file_format_title": "ఫైల్ ఫార్మాట్ ఎగుమతి", - "message_type_filter_title": "రకం ద్వారా సందేశాలను ఫిల్టర్ చేయండి", - "amount_of_messages_title": "సందేశాల మొత్తం (అందరికీ ఖాళీగా ఉంచండి)", - "download_medias_title": "మీడియాస్‌ను డౌన్‌లోడ్ చేయండి" - }, - "dialog_negative_button": "రద్దు చేయండి", - "dialog_positive_button": "ఎగుమతి", - "exported_to": "{path} కు ఎగుమతి చేయబడింది", - "exporting_chats": "చాట్‌లను ఎగుమతి చేస్తుంది ...", - "processing_chats": "ప్రాసెసింగ్ {amount} సంభాషణలు ...", - "export_fail": "సంభాషణను ఎగుమతి చేయడంలో విఫలమైంది {conversation}", - "writing_output": "అవుట్పుట్ రాయడం ...", - "finished": "పూర్తయింది! మీరు ఇప్పుడు ఈ డైలాగ్‌ను మూసివేయవచ్చు.", - "no_messages_found": "సందేశాలు కనుగొనబడలేదు!", - "exporting_message": "{message}..." - }, - "button": { - "ok": "సరే", - "positive": "అవును", - "negative": "లేదు", - "cancel": "రద్దు చేయండి", - "open": "ఓపెన్", - "download": "డౌన్‌లోడ్", - "send": "పంపండి", - "restore_original": "ఒరిజినల్ పునరుద్ధరించండి", - "convert_external_media": "బాహ్య మాధ్యమాన్ని మార్చండి", - "save": "సేవ్" - }, - "tracker_events": { - "conversation_enter": "సంభాషణ నమోదు చేయండి", - "conversation_exit": "సంభాషణ నిష్క్రమణ", - "started_typing": "టైప్ చేయడం ప్రారంభించింది", - "stopped_typing": "టైపింగ్ ఆపివేయబడింది", - "started_speaking": "మాట్లాడటం ప్రారంభించారు", - "stopped_speaking": "మాట్లాడటం మానేసింది", - "started_peeking": "పీకింగ్ ప్రారంభించింది", - "stopped_peeking": "పీకింగ్ ఆగిపోయింది", - "message_read": "సందేశం చదవండి", - "message_deleted": "సందేశం తొలగించబడింది", - "message_saved": "సందేశం సేవ్ చేయబడింది", - "message_unsaved": "సందేశం సేవ్ చేయబడలేదు", - "message_edited": "సందేశం సవరించబడింది", - "message_reaction_add": "సందేశ ప్రతిచర్య జోడించు", - "message_reaction_remove": "సందేశ ప్రతిచర్య తొలగించండి", - "snap_opened": "స్నాప్ తెరిచింది", - "snap_replayed": "స్నాప్ రీప్లే", - "snap_replayed_twice": "స్నాప్ రెండుసార్లు రీప్లే", - "snap_screenshot": "స్నాప్ స్క్రీన్ షాట్", - "snap_screen_record": "స్నాప్ స్క్రీన్ రికార్డ్" - }, - "tracker_actions": { - "log": "లాగ్", - "in_app_notification": "అనువర్తన నోటిఫికేషన్", - "push_notification": "పుష్ నోటిఫికేషన్", - "custom": "ఆచారం" - }, - "better_notifications": { - "button": { - "reply": "ప్రత్యుత్తరం", - "download": "డౌన్‌లోడ్", - "mark_as_read": "చదవడానికి గుర్తించండి" - } - }, - "profile_picture_downloader": { - "button": "ప్రొఫైల్ చిత్రాన్ని డౌన్‌లోడ్ చేయండి", - "title": "ప్రొఫైల్ పిక్చర్ డౌన్‌లోడ్", - "avatar_option": "అవతార్", - "background_option": "నేపథ్యం" - }, - "call_start_confirmation": { - "dialog_title": "కాల్ ప్రారంభించండి", - "dialog_message": "మీరు ఖచ్చితంగా కాల్ ప్రారంభించాలనుకుంటున్నారా?" - }, - "half_swipe_notifier": { - "notification_channel_name": "సగం స్వైప్", - "notification_content_dm": "{friend} {duration} సెకన్ల కోసం మీ చాట్‌లో సగం స్విప్ చేయబడింది", - "notification_content_group": "{friend} {duration} సెకన్ల కోసం {group} లోకి సగం స్విప్ చేయబడింది" - }, - "download_processor": { - "attachment_type": { - "snap": "స్నాప్", - "sticker": "స్టిక్కర్", - "gif": "Gif", - "external_media": "బాహ్య మీడియా", - "note": "గమనిక", - "original_story": "అసలు కథ" - }, - "select_attachments_title": "జోడింపులను ఎంచుకోండి", - "download_started_toast": "డౌన్‌లోడ్ ప్రారంభమైంది", - "unsupported_content_type_toast": "మద్దతు లేని కంటెంట్ రకం!", - "failed_no_longer_available_toast": "మీడియా ఇకపై అందుబాటులో లేదు", - "no_attachments_toast": "జోడింపులు కనుగొనబడలేదు!", - "already_queued_toast": "మీడియా ఇప్పటికే క్యూలో ఉంది!", - "already_downloaded_toast": "మీడియా ఇప్పటికే డౌన్‌లోడ్ చేయబడింది!", - "content_saved_toast": "సేవ్ చేయబడింది!", - "download_toast": "డౌన్‌లోడ్ {attachment}...", - "processing_toast": "ప్రాసెసింగ్ {attachment}...", - "failed_generic_toast": "డౌన్‌లోడ్ చేయడంలో విఫలమైంది", - "failed_to_create_preview_toast": "ప్రివ్యూను సృష్టించడంలో విఫలమైంది", - "failed_processing_toast": "ప్రాసెసింగ్ విఫలమైంది {error}", - "failed_gallery_toast": "గ్యాలరీకి సేవ్ చేయడం విఫలమైంది {error}", - "dash_no_chapter": "అధ్యాయం కనుగొనబడలేదు", - "dash_dialog": { - "title": "డాష్ మీడియాను డౌన్‌లోడ్ చేయండి", - "download_all": "అన్నీ డౌన్‌లోడ్ చేయండి", - "segment_text": "సెగ్మెంట్ {from} - {to}" - } - }, - "streaks_reminder": { - "notification_title": "స్ట్రీక్స్", - "notification_text": "{hoursLeft} గంటల్లో మీరు {friend} తో మీ పరంపరను కోల్పోతారు" - }, - "biometric_auth": { - "unlock_button": "అన్‌లాక్", - "title": "స్నాప్‌చాట్‌ను అన్‌లాక్ చేయండి", - "subtitle": "స్నాప్‌చాట్‌ను అన్‌లాక్ చేయడానికి దయచేసి ప్రామాణీకరించండి" - }, - "end_to_end_encryption": { - "toolbox": { - "no_shared_key": "ఈ స్నేహితుడితో మీకు ఇంకా పంచుకున్న రహస్యం లేదు. క్రొత్తదాన్ని ప్రారంభించడానికి క్రింద క్లిక్ చేయండి.", - "shared_key_fingerprint": "మీ వేలిముద్ర:\n\n{fingerprint}\n\nఇది మీ స్నేహితుడి వేలిముద్రతో సరిపోతుందో లేదో తనిఖీ చేయండి!", - "initiate_exchange_button": "కీ మార్పిడిని ప్రారంభించండి" - }, - "confirmation_dialogs": { - "title": "ఎండ్-టు-ఎండ్ ఎన్క్రిప్షన్", - "confirmation_1": "హెచ్చరిక: ఇది మీ ప్రస్తుత కీని ఓవర్రైట్ చేస్తుంది. మీరు ఈ స్నేహితుడి నుండి అన్ని గుప్తీకరించిన సందేశాలకు ప్రాప్యతను కోల్పోతారు. మీరు ఖచ్చితంగా కొనసాగించాలనుకుంటున్నారా?", - "confirmation_2": "మీరు నిజంగా కొనసాగించాలనుకుంటున్నారా? బ్యాక్ అవుట్ చేయడానికి ఇది మీకు చివరి అవకాశం." - }, - "unencrypted_conversation_send_failure_toast": "మీరు గుప్తీకరించిన మరియు గుప్తీకరించని సంభాషణలకు గుప్తీకరించిన కంటెంట్‌ను పంపలేరు!", - "native_hooks_send_failure_toast": "పంపడంలో విఫలమైంది! దయచేసి సెట్టింగులలో స్థానిక హుక్స్ ప్రారంభించండి.", - "no_participants_to_encrypt_toast": "ఈ సంభాషణలో సందేశాలను గుప్తీకరించడానికి మీకు స్నేహితులు లేరు!", - "encryption_failed_toast": "సందేశాన్ని గుప్తీకరించడంలో విఫలమైంది! మరిన్ని వివరాల కోసం లాగ్‌క్యాట్‌ను తనిఖీ చేయండి.", - "accept_public_key_success_toast": "పబ్లిక్ కీ విజయవంతంగా అంగీకరించబడింది!", - "accept_secret_key_success_toast": "పూర్తయింది! మీరు ఇప్పుడు ఈ స్నేహితుడితో గుప్తీకరించిన సందేశాలను పంపవచ్చు మరియు స్వీకరించవచ్చు.", - "accept_public_key_failure_toast": "పబ్లిక్ కీని అంగీకరించడంలో విఫలమైంది", - "accept_secret_key_failure_toast": "రహస్య కీని అంగీకరించడంలో విఫలమైంది", - "accept_secret_button": "రహస్యాన్ని అంగీకరించండి", - "accept_public_key_button": "పబ్లిక్ కీని అంగీకరించండి", - "outgoing_pk_message": "కీ మార్పిడి అభ్యర్థన", - "outgoing_secret_message": "కీ మార్పిడి ప్రతిస్పందన", - "incoming_pk_message": "మీరు ఇప్పుడే పబ్లిక్ కీ అభ్యర్థనను అందుకున్నారు. దీన్ని అంగీకరించడానికి క్రింద క్లిక్ చేయండి.", - "incoming_secret_message": "మీ స్నేహితుడు మీ పబ్లిక్ కీని అంగీకరించారు. రహస్యాన్ని అంగీకరించడానికి క్రింద క్లిక్ చేయండి." - }, - "auto_open_snaps": { - "title": "ఆటో ఓపెన్ స్నాప్‌లు", - "notification_content": "{count} స్నాప్‌లు తెరవబడ్డాయి" - }, - "friend_mutation_observer": { - "notification_channel_name": "ఫ్రెండ్ మ్యుటేషన్ అబ్జర్వర్", - "friend_removed": "{username} మిమ్మల్ని స్నేహితుడిగా తొలగించింది", - "birthday_removed": "{username} వారి పుట్టినరోజును తొలగించింది ({birthday})", - "birthday_added": "{username} వారి పుట్టినరోజును జోడించింది ({birthday})", - "birthday_changed": "{username} వారి పుట్టినరోజును {oldBirthday} నుండి {newBirthday} గా మార్చింది", - "bitmoji_selfie_changed": "{username} వారి బిట్‌మోజీ సెల్ఫీని మార్చింది", - "bitmoji_avatar_changed": "{username} వారి బిట్‌మోజీ అవతార్‌ను మార్చింది", - "bitmoji_background_changed": "{username} వారి బిట్‌మోజీ నేపథ్యాన్ని మార్చింది", - "bitmoji_scene_changed": "{username} వారి బిట్‌మోజీ దృశ్యాన్ని మార్చింది" - }, - "material3_strings": { - "date_range_picker_start_headline": "నుండి", - "date_range_picker_end_headline": "To", - "date_range_picker_title": "తేదీ పరిధిని ఎంచుకోండి", - "date_picker_switch_to_calendar_mode": "క్యాలెండర్", - "date_picker_switch_to_input_mode": "ఇన్పుట్", - "date_range_picker_scroll_to_previous_month": "మునుపటి నెల", - "date_range_picker_scroll_to_next_month": "వచ్చే నెల", - "date_picker_today_description": "ఈ రోజు", - "date_range_picker_day_in_range": "ఎంచుకున్నారు", - "date_input_invalid_for_pattern": "చెల్లని తేదీ", - "date_input_invalid_year_range": "చెల్లని సంవత్సరం", - "date_input_invalid_not_allowed": "చెల్లని తేదీ", - "date_range_input_invalid_range_input": "చెల్లని తేదీ పరిధి" - }, - "send_override_dialog": { - "title": "మీడియాను {type} గా పంపండి", - "duration": "వ్యవధి: {duration}", - "saveable_snap_hint": "చాట్‌లో స్నాప్‌ను సేవ్ చేయగలిగేలా చేయండి", - "unlimited_duration": "అపరిమిత" - }, - "invalid_input_toast": "చెల్లని ఇన్పుట్! మీరు చెల్లుబాటు అయ్యే విలువను నమోదు చేశారని నిర్ధారించుకోండి." -} \ No newline at end of file diff --git a/common/src/main/assets/lang/th.json b/common/src/main/assets/lang/th.json deleted file mode 100644 index 15980c43..00000000 --- a/common/src/main/assets/lang/th.json +++ /dev/null @@ -1,2022 +0,0 @@ -{ - "setup": { - "dialogs": { - "select_language": "เลือกภาษา", - "save_folder": "PurrfectSnap ต้องการสิทธิ์ในการจัดเก็บข้อมูลเพื่อดาวน์โหลดและบันทึกสื่อจาก Snapchat\nโปรดเลือกตำแหน่งที่ควรดาวน์โหลดสื่อไป", - "select_save_folder_button": "เลือกโฟลเดอร์" - }, - "mappings": { - "dialog": "กำลังสร้างการแมป อาจใช้เวลาสักครู่ ...", - "generate_failure_no_snapchat": "PurrfectSnap ตรวจไม่พบ Snapchat โปรดลองติดตั้ง Snapchat ใหม่", - "generate_failure": "เกิดข้อผิดพลาดขณะพยายามสร้างการแมป โปรดลองอีกครั้ง" - }, - "permissions": { - "dialog": "หากต้องการดำเนินการต่อ คุณจะต้องปฏิบัติตามข้อกำหนดต่อไปนี้:", - "notification_access": "การเข้าถึงการแจ้งเตือน", - "battery_optimization": "การเพิ่มประสิทธิภาพแบตเตอรี่", - "display_over_other_apps": "แสดงบนแอปอื่นๆ", - "request_button": "ขอ" - } - }, - "scopes": { - "friend": "เพื่อน", - "group": "กลุ่ม" - }, - "manager": { - "routes": { - "tasks": "งาน", - "features": "คุณสมบัติ", - "manage_rule_feature": "จัดการคุณสมบัติกฎ", - "home": "บ้าน", - "home_settings": "การตั้งค่า", - "home_logs": "บันทึก", - "logger_history": "ประวัติคนตัดไม้", - "logged_stories": "เรื่องราวที่บันทึกไว้", - "friend_tracker": "ติดตามเพื่อน", - "edit_rule": "แก้ไขกฎ", - "file_imports": "การนำเข้าไฟล์", - "manage_repos": "จัดการที่เก็บข้อมูล", - "social": "ทางสังคม", - "manage_scope": "จัดการขอบเขต", - "messaging_preview": "ดูตัวอย่าง", - "scripts": "สคริปต์", - "better_location": "ทำเลที่ตั้งดีกว่า" - }, - "sections": { - "home": { - "version_title": "v{versionName} · แยกโดย Eternal", - "update_title": "อัพเดต PurrfectSnap", - "update_content": "เวอร์ชัน {version} พร้อมใช้งานแล้ว!", - "update_button": "ดาวน์โหลด", - "debug_build_summary_title": "คุณกำลังเรียกใช้รุ่นแก้ไขข้อบกพร่องของ PurrfectSnap", - "debug_build_summary_content": "เวอร์ชัน __ตัวยึด_0__ (__ตัวยึดตำแหน่ง_1__)", - "debug_build_summary_date": "วันที่สร้าง: {date} ({days} วันที่ผ่านมา)", - "quick_actions_title": "การดำเนินการด่วน", - "download_icon_description": "ดาวน์โหลด", - "completed_icon_description": "สมบูรณ์", - "failed_icon_description": "ล้มเหลว", - "manage_quick_actions_description": "จัดการการดำเนินการด่วน", - "quick_actions_icon_description": "การดำเนินการด่วน", - "add_quick_action_description": "เพิ่มการดำเนินการด่วน" - }, - "home_logs": { - "no_logs_hint": "ไม่มีบันทึกที่ใช้ได้", - "clear_logs_button": "ล้างบันทึก", - "export_logs_button": "ส่งออกบันทึก", - "saving_logs_toast": "กำลังบันทึกบันทึก อาจใช้เวลาสักครู่ ...", - "saved_logs_success_toast": "บันทึกบันทึกเรียบร้อยแล้ว", - "saved_logs_failure_toast": "ไม่สามารถบันทึกบันทึกได้" - }, - "home_settings": { - "actions_title": "การดำเนินการ", - "message_logger_title": "เครื่องบันทึกข้อความ", - "debug_title": "ดีบัก", - "success_toast": "เสร็จแล้ว!", - "message_logger_summary": "__ตัวยึดตำแหน่ง_0__ ข้อความ\n__ตัวยึดตำแหน่ง_1__ เรื่องราว", - "export_button": "ส่งออก", - "clear_button": "ชัดเจน", - "view_logger_history_button": "ดูประวัติคนตัดไม้", - "updates_title": "อัพเดท", - "auto_update_check": "ตรวจสอบการอัปเดตอัตโนมัติ", - "update_check_frequency": "อัพเดตความถี่ในการตรวจสอบ", - "update_check_frequency_daily": "รายวัน", - "update_check_frequency_weekly": "รายสัปดาห์", - "update_check_frequency_monthly": "รายเดือน", - "theme_icon_description": "ธีม", - "app_theme_title": "ธีมแอป", - "theme_mode_system": "ระบบ", - "theme_mode_light": "แสงสว่าง", - "theme_mode_dark": "มืด", - "ui_settings_title": "การตั้งค่า UI", - "haptic_feedback_label": "การตอบสนองแบบสัมผัส", - "test_mode_label": "โหมดทดสอบ (สำหรับการดีบักเท่านั้น)", - "disable_feature_loading_label": "ปิดการใช้งานการโหลดคุณสมบัติ", - "disable_auto_mapper_label": "ปิดการใช้งาน Mapper อัตโนมัติ", - "disable_bypass_indicator_label": "ปิดใช้งานตัวบ่งชี้สถานะบายพาส", - "update_notification_channel_name": "อัพเดต PurrfectSnap", - "update_notification_channel_description": "การแจ้งเตือนสำหรับการอัพเดต PurrfectSnap", - "update_notification_title": "มีการอัปเดต PurrfectSnap", - "update_notification_text": "เวอร์ชัน %s พร้อมใช้งานแล้ว", - "export_database_failed_toast": "ส่งออกฐานข้อมูลไม่สำเร็จ! __ตัวยึดตำแหน่ง__0__", - "clear_messages_failed_toast": "ไม่สามารถล้างข้อความได้! __ตัวยึดตำแหน่ง__0__", - "clear_file_failed_toast": "ไม่สามารถล้างไฟล์ได้! __ตัวยึดตำแหน่ง__0__", - "debug_file_config": "การกำหนดค่า", - "debug_file_mappings": "การแมป", - "debug_file_message_logger": "เครื่องบันทึกข้อความ", - "debug_file_pinned_best_friend": "ปักหมุดเพื่อนที่ดีที่สุด", - "debug_file_native_sig_cache": "แคชลายเซ็นดั้งเดิม" - }, - "tasks": { - "no_tasks": "ไม่มีงาน", - "merge_button": "ผสาน", - "failed_to_open_file": "ไม่สามารถเปิดไฟล์ได้", - "merge_files_toast": "การรวมไฟล์ {count}", - "remove_selected_tasks_title": "คุณแน่ใจหรือไม่ว่าต้องการลบงานที่เลือก", - "remove_all_tasks_title": "คุณแน่ใจหรือไม่ว่าต้องการลบงานทั้งหมด", - "delete_files_option": "ลบไฟล์ด้วย", - "remove_selected_tasks_confirm": "ลบงาน {count} หรือไม่", - "remove_all_tasks_confirm": "ลบงานทั้งหมดใช่ไหม", - "clear_tasks_description": "ล้างงาน", - "file_not_found_icon_description": "ไม่พบไฟล์", - "image_icon_description": "ภาพ", - "video_icon_description": "วีดีโอ", - "audio_icon_description": "เสียง", - "file_icon_description": "ไฟล์", - "download_icon_description": "ดาวน์โหลด", - "chat_action_icon_description": "การดำเนินการแชท", - "cancel_icon_description": "ยกเลิก", - "success_icon_description": "ความสำเร็จ", - "failure_icon_description": "ความล้มเหลว", - "cancelled_icon_description": "ยกเลิก", - "task_status_failure": "ความล้มเหลว", - "task_status_cancelled": "ยกเลิก" - }, - "features": { - "disabled": "พิการ", - "export_option": "ส่งออก", - "import_option": "นำเข้า", - "reset_option": "รีเซ็ต", - "config_export_success_toast": "ส่งออกการกำหนดค่าเรียบร้อยแล้ว", - "config_import_success_toast": "นำเข้าการกำหนดค่าเรียบร้อยแล้ว", - "config_import_failure_toast": "ไม่สามารถนำเข้าการกำหนดค่า {error}", - "config_export_failure_toast": "ไม่สามารถส่งออกการกำหนดค่า {error}", - "saved_config_snackbar": "บันทึกการกำหนดค่าแล้ว", - "older_required": "คุณลักษณะนี้ต้องใช้ Snapchat v{version} หรือเก่ากว่าจึงจะทำงานได้อย่างถูกต้อง", - "newer_required": "คุณลักษณะนี้ต้องใช้ Snapchat v{version} หรือใหม่กว่าจึงจะทำงานได้อย่างถูกต้อง", - "search_button": "ค้นหา" - }, - "manage_rule_feature": { - "disable_state_option": "พิการ", - "disable_state_subtext": "ไม่มีเพื่อน/กลุ่มใดที่จะได้รับผลกระทบ", - "whitelist_state_option": "ไม่มีใครนอกจาก...", - "whitelist_state_subtext": "เฉพาะเพื่อน/กลุ่ม {count} เท่านั้นที่จะได้รับผลกระทบจากกฎนี้", - "whitelist_state_button": "เลือกเพื่อน/กลุ่มที่อนุญาต", - "blacklist_state_option": "ทุกคนยกเว้น...", - "blacklist_state_subtext": "ทุกคนยกเว้น {count} เพื่อน/กลุ่มจะได้รับผลกระทบจากกฎนี้", - "blacklist_state_button": "เลือกเพื่อน/กลุ่มที่ยกเว้น", - "clear_list_button": "ล้างรายชื่อเพื่อน/กลุ่ม", - "dialog_clear_confirmation_text": "คุณแน่ใจหรือไม่ว่าต้องการล้างรายการ" - }, - "social": { - "friends_tab": "เพื่อน", - "groups_tab": "กลุ่ม", - "empty_hint": "(ว่างเปล่า)", - "streaks_expiration_short": "__ตัวยึดตำแหน่ง_0__ชม" - }, - "manage_scope": { - "logged_stories_button": "แสดงเรื่องราวที่บันทึกไว้", - "e2ee_title": "การเข้ารหัสจากต้นทางถึงปลายทาง", - "rules_title": "กฎ", - "participants_text": "{count} ผู้เข้าร่วม", - "not_found": "ไม่พบ", - "streaks_title": "มีลายทาง", - "streaks_length_text": "ความยาว: __ตัวยึด_0__", - "streaks_expiration_text": "หมดอายุใน {eta}", - "streaks_expiration_text_expired": "หมดอายุแล้ว", - "reminder_button": "ตั้งการเตือน", - "delete_scope_confirm_dialog_title": "คุณแน่ใจหรือไม่ว่าต้องการลบ {scope}", - "notes_placeholder": "คลิกเพื่อเพิ่มบันทึก", - "invalid_key_size_32_bytes": "ขนาดคีย์ไม่ถูกต้อง (ต้องเป็น 32 ไบต์)", - "successfully_imported_key": "นำเข้าคีย์สำเร็จแล้ว", - "failed_to_import_key": "ไม่สามารถนำเข้าคีย์: {message}", - "export_base64_button": "ฐานส่งออก64", - "import_base64_button": "นำเข้า Base64" - }, - "logged_stories": { - "story_failed_to_load": "โหลดไม่สำเร็จ", - "no_stories": "ไม่พบเรื่องราว", - "save_from_cache_button": "บันทึกจากแคช", - "downloaded_to_path": "ดาวน์โหลดไปที่ {path}", - "download_failed": "การดาวน์โหลดล้มเหลว: {message}", - "posted_at": "โพสต์ที่ {date}", - "created_at": "สร้างที่ {date}", - "failed_to_open_file": "ไม่สามารถเปิดไฟล์ได้ ตรวจสอบบันทึกเพื่อดูข้อมูลเพิ่มเติม", - "failed_to_get_file": "ไม่สามารถรับไฟล์" - }, - "messaging_preview": { - "processed_messages_toast": "ประมวลผลข้อความ {count} แล้ว", - "processed_messages_text": "ประมวลผลข้อความ {count} แล้ว", - "close_button_description": "ปิด", - "bridge_connection_failed": "ไม่สามารถเชื่อมต่อกับบริดจ์ได้ ตรวจสอบให้แน่ใจว่า Snapchat ทำงานในพื้นหลัง", - "bridge_init_failed": "ไม่สามารถเริ่มต้นบริดจ์การรับส่งข้อความได้ ตรวจสอบให้แน่ใจว่า Snapchat ทำงานในพื้นหลัง", - "message_fetch_failed": "เรียกข้อความไม่สำเร็จ", - "no_message_hint": "ไม่มีข้อความ", - "save_selection_option": "บันทึกการเลือก", - "save_all_option": "บันทึกทั้งหมด", - "unsave_selection_option": "ยกเลิกการบันทึกการเลือก", - "unsave_all_option": "ยกเลิกการบันทึกทั้งหมด", - "mark_selection_as_seen_option": "ทำเครื่องหมายเลือก Snap ตามที่เห็น", - "mark_all_as_seen_option": "ทำเครื่องหมาย Snaps ทั้งหมดตามที่เห็น", - "delete_selection_option": "ลบการเลือก", - "delete_all_option": "ลบทั้งหมด" - }, - "logger_history": { - "download_started_toast": "เริ่มดาวน์โหลดแล้ว!", - "download_success_toast": "ดาวน์โหลดไปที่ {path}", - "download_failed_toast": "ไม่สามารถดาวน์โหลด {message}", - "edited_at_text": "{message} (แก้ไขที่ {date})", - "download_button": "ดาวน์โหลด", - "select_conversation_placeholder": "เลือกการสนทนา", - "close_button_description": "ปิด", - "search_button_description": "ค้นหา", - "list_friend_format": "เพื่อน __ตัวยึดตำแหน่ง_0__", - "list_group_format": "กลุ่ม __ตัวยึดตำแหน่ง_0__", - "no_more_messages": "ไม่มีข้อความอีกต่อไป", - "reverse_order_checkbox": "ลำดับย้อนกลับ", - "chat_attachment": "ไฟล์แนบ __ตัวยึดตำแหน่ง_0__", - "empty_message": "ข้อความแชทว่างเปล่า", - "message_parse_failed": "ไม่สามารถแยกวิเคราะห์ข้อความ", - "unknown_sender": "ผู้ส่งที่ไม่รู้จัก", - "download_attachment_failed_toast": "ดาวน์โหลดไฟล์แนบไม่สำเร็จ", - "log_header_format": "__ตัวยึด_0__ (__ตัวยึด_1__) - __ตัวยึด_2__" - }, - "file_imports": { - "import_file_button": "นำเข้าไฟล์", - "file_not_found": "ไม่พบไฟล์", - "file_import_failed": "ไม่สามารถนำเข้าไฟล์: {error}", - "file_imported": "นำเข้าไฟล์เรียบร้อยแล้ว", - "file_delete_failed": "ไม่สามารถลบไฟล์ได้", - "no_files_hint": "ที่นี่คุณสามารถนำเข้าไฟล์เพื่อใช้ใน Snapchat กดปุ่มด้านล่างเพื่อนำเข้าไฟล์" - }, - "better_location": { - "spoofed_coordinates_title": "ละติจูด {latitude}, Lng {longitude}", - "save_coordinates_dialog_title": "บันทึกพิกัด", - "saved_name_dialog_hint": "ชื่อที่บันทึกไว้", - "latitude_dialog_hint": "ละติจูด", - "longitude_dialog_hint": "ลองจิจูด", - "save_dialog_button": "บันทึก", - "choose_location_button": "เลือกสถานที่", - "teleport_to_friend_button": "เทเลพอร์ตไปหาเพื่อน", - "spoof_location_toggle": "สถานที่ปลอมแปลง", - "suspend_location_updates": "ระงับการอัปเดตตำแหน่ง", - "saved_coordinates_title": "พิกัดที่บันทึกไว้", - "no_saved_coordinates_hint": "ไม่มีพิกัดที่บันทึกไว้", - "delete_dialog_title": "ลบพิกัดที่บันทึกไว้", - "delete_dialog_message": "คุณแน่ใจหรือไม่ว่าต้องการลบพิกัดที่บันทึกไว้นี้", - "teleport_to_friend_title": "เทเลพอร์ตไปหาเพื่อน", - "search_bar": "ค้นหา", - "no_friends_map": "ไม่มีเพื่อนบนแผนที่", - "no_friends_found": "ไม่พบเพื่อน", - "edit_location_button_description": "แก้ไขสถานที่", - "add_icon_description": "เพิ่ม", - "edit_icon_description": "แก้ไข", - "delete_icon_description": "ลบ" - } - }, - "dialogs": { - "add_friend": { - "title": "เพิ่มเพื่อนหรือกลุ่ม", - "search_hint": "ค้นหา", - "fetch_error": "ดึงข้อมูลไม่สำเร็จ", - "category_groups": "กลุ่ม", - "category_friends": "เพื่อน", - "participants_text": "{count} ผู้เข้าร่วม", - "search_icon_description": "ค้นหา" - }, - "scripting_warning": { - "title": "คำเตือน", - "content": "PurrfectSnap มีเครื่องมือสคริปต์ที่ช่วยให้สามารถรันโค้ดที่ผู้ใช้กำหนดบนอุปกรณ์ของคุณได้ ใช้ความระมัดระวังอย่างยิ่งและติดตั้งโมดูลจากแหล่งที่รู้จักและเชื่อถือได้เท่านั้น โมดูลที่ไม่ได้รับอนุญาตหรือไม่ได้รับการตรวจสอบอาจก่อให้เกิดความเสี่ยงด้านความปลอดภัยต่อระบบของคุณ" - }, - "reset_config": { - "title": "รีเซ็ตการกำหนดค่า", - "content": "คุณแน่ใจหรือไม่ว่าต้องการรีเซ็ตการกำหนดค่า", - "success_toast": "รีเซ็ตการกำหนดค่าสำเร็จแล้ว" - }, - "export_config": { - "title": "ส่งออกข้อมูลที่ละเอียดอ่อนใช่ไหม", - "content": "คุณต้องการส่งออกการกำหนดค่าด้วยข้อมูลที่ละเอียดอ่อนหรือไม่ (เช่นพิกัดตำแหน่ง ฯลฯ )" - }, - "messaging_action": { - "title": "เลือกประเภทเนื้อหาที่จะประมวลผล", - "select_all_button": "เลือกทั้งหมด" - }, - "file_imports": { - "no_files_settings_hint": "ไม่พบไฟล์ ตรวจสอบให้แน่ใจว่าคุณได้นำเข้าไฟล์ที่จำเป็นในส่วนการนำเข้าไฟล์", - "settings_select_file_hint": "เลือกไฟล์ที่นำเข้า" - }, - "quick_actions_dialog": { - "title": "แก้ไขการดำเนินการด่วน", - "subtitle": "เลือกและปรับขนาดการดำเนินการด่วนของคุณ" - } - }, - "friend_tracker": { - "rules_tab": "กฎ", - "logs_tab": "บันทึก", - "export_dialog_title": "ส่งออก", - "bulk_export_button": "การส่งออกจำนวนมาก", - "individual_export_button": "การส่งออกส่วนบุคคล", - "invalid_import_type_dialog_title": "ประเภทการนำเข้าไม่ถูกต้อง", - "invalid_import_type_dialog_text": "ไฟล์ที่เลือกเข้ากันไม่ได้กับประเภทการนำเข้านี้ โปรดเลือกประเภทการนำเข้าที่ถูกต้อง", - "import_dialog_title": "นำเข้า", - "bulk_import_button": "การนำเข้าจำนวนมาก", - "individual_import_button": "การนำเข้าส่วนบุคคล", - "import_button_description": "นำเข้า", - "export_button_description": "ส่งออก", - "export_button": "ส่งออก", - "delete_button_description": "ลบ", - "delete_button": "ลบ", - "catalog_button_description": "แคตตาล็อก", - "catalog_button": "แคตตาล็อก", - "add_rule_button_description": "เพิ่มกฎ", - "add_rule_button": "เพิ่มกฎ", - "no_rules_found": "ไม่พบกฎเกณฑ์", - "empty_rule_name": "(ว่างเปล่า)", - "events_suffix": "เหตุการณ์ต่างๆ", - "scopes_suffix": "ขอบเขต", - "select_rule_to_export_title": "เลือกกฎที่จะส่งออก", - "deleted_logs_toast": "ลบบันทึก {count} แล้ว", - "delete_logs_dialog_title": "ลบบันทึกใช่ไหม", - "deleting_logs_dialog_text": "กำลังลบบันทึก {count}...", - "delete_logs_dialog_confirm_text": "การดำเนินการนี้จะลบบันทึกตามตัวกรองปัจจุบันและคำค้นหา การดำเนินการนี้ไม่สามารถยกเลิกได้", - "exported_logs_toast": "บันทึกที่ส่งออก!", - "export_logs_failed_toast": "ส่งออกบันทึกไม่สำเร็จ ตรวจสอบ logcat เพื่อดูรายละเอียดเพิ่มเติม", - "export_logs_dialog_title": "ส่งออกบันทึก?", - "exporting_logs_dialog_text": "กำลังส่งออกบันทึก...", - "export_logs_dialog_confirm_text": "การดำเนินการนี้จะส่งออกบันทึกตามตัวกรองปัจจุบันและคำค้นหา", - "export_as_button": "ส่งออกเป็น {type}", - "filters_title": "ตัวกรอง", - "search_by_label": "ค้นหาโดย", - "newest_first_label": "ใหม่ล่าสุดก่อน", - "since_label": "เนื่องจาก", - "until_label": "จนกระทั่ง", - "pick_a_date_button": "เลือกวัน", - "search_placeholder": "ค้นหา", - "filter_button_description": "กรอง", - "clear_button_description": "ชัดเจน", - "no_logs_found": "ไม่พบบันทึก", - "log_event_format": "__ตัวยึดตำแหน่ง_0__ ใน __ตัวยึดตำแหน่ง_1__", - "condition_only_inside_conversation": "เฉพาะเมื่อฉันอยู่ในการสนทนา", - "condition_only_outside_conversation": "เมื่อฉันออกไปสนทนาข้างนอกเท่านั้น", - "condition_only_when_app_active": "เมื่อ Snapchat ทำงานอยู่เท่านั้น", - "condition_only_when_app_inactive": "เฉพาะเมื่อ Snapchat ไม่ได้ใช้งานเท่านั้น", - "condition_no_push_notification_when_app_active": "ไม่มีการแจ้งเตือนเมื่อ Snapchat ทำงานอยู่", - "add_event_dialog_title": "เพิ่มเหตุการณ์", - "event_type_label": "ประเภทเหตุการณ์", - "triggers_title": "ทริกเกอร์", - "conditions_title": "เงื่อนไข", - "add_button": "เพิ่ม", - "default_rule_name": "กฎที่กำหนดเอง", - "discard_changes_dialog_title": "ยกเลิกการเปลี่ยนแปลงใช่ไหม", - "discard_changes_dialog_text": "คุณมีการเปลี่ยนแปลงที่ยังไม่ได้บันทึก คุณแน่ใจหรือไม่ว่าต้องการยกเลิก", - "discard_button": "ทิ้ง", - "cannot_save_rule_dialog_title": "ไม่สามารถบันทึกกฎได้", - "cannot_save_rule_dialog_text": "กฎต้องมีอย่างน้อยหนึ่งเหตุการณ์ที่จะบันทึก", - "duplicate_rule_name_dialog_title": "ชื่อกฎที่ซ้ำกัน", - "duplicate_rule_name_dialog_text": "มีกฎที่ใช้ชื่อนี้อยู่แล้ว โปรดเลือกชื่ออื่น", - "delete_rule_dialog_title": "ลบกฎ", - "delete_rule_dialog_text": "คุณแน่ใจหรือไม่ว่าต้องการลบกฎนี้", - "new_rule_title": "กฎใหม่", - "edit_rule_title": "แก้ไขกฎ", - "back_button_description": "กลับ", - "save_button_description": "บันทึก", - "general_section_title": "ทั่วไป", - "rule_name_label": "ชื่อกฎ", - "author_name_label": "ชื่อผู้แต่ง", - "scope_section_title": "ขอบเขต", - "scope_all": "ทั้งหมด", - "scope_whitelist": "ไวท์ลิสต์", - "scope_blacklist": "บัญชีดำ", - "select_friends_groups_button": "เลือกเพื่อน/กลุ่ม ({count})", - "events_section_title": "กิจกรรม", - "add_event_button": "เพิ่มเหตุการณ์", - "no_events_text": "ไม่มีกิจกรรม" - }, - "friend_tracker_catalog": { - "download_failed": "การดาวน์โหลดล้มเหลว: {code}", - "error": "ข้อผิดพลาด: {message}", - "no_repos_added": "ไม่มีการเพิ่มที่เก็บข้อมูล", - "no_rules_available": "ไม่มีกฎเกณฑ์จาก repo ใด ๆ", - "by_author": "โดย __ตัวยึดตำแหน่ง_0__", - "imported_button": "นำเข้า", - "import_button": "นำเข้า", - "title": "แคตตาล็อกติดตามเพื่อน", - "manage_repos_description": "จัดการที่เก็บข้อมูล" - }, - "friend_tracker_export": { - "title": "กฎการส่งออก", - "back_button_description": "กลับ", - "exported_toast": "ส่งออกกฎการติดตามเพื่อนแล้ว!", - "export_failed_toast": "ไม่สามารถส่งออกกฎ: {message}", - "save_button": "บันทึก", - "expand_button_description": "ขยาย" - }, - "friend_tracker_import": { - "title": "กฎการนำเข้า", - "back_button_description": "กลับ", - "imported_toast": "นำเข้ากฎการติดตามเพื่อนแล้ว!", - "import_failed_toast": "ไม่สามารถนำเข้ากฎ: {message}", - "confirm_button": "ยืนยัน", - "expand_button_description": "ขยาย" - }, - "friend_tracker_repos": { - "invalid_repo_title": "พื้นที่เก็บข้อมูลไม่ถูกต้อง", - "add_repo_button": "เพิ่มพื้นที่เก็บข้อมูล", - "add_repo_dialog_title": "เพิ่ม URL ที่เก็บ", - "repo_url_label": "URL ที่เก็บ", - "repo_added_toast": "เพิ่มพื้นที่เก็บข้อมูลเรียบร้อยแล้ว!", - "invalid_repo_error": "ดูเหมือนจะไม่ใช่พื้นที่เก็บข้อมูล Friend Tracker ที่ถูกต้อง", - "add_repo_failed_toast": "ไม่สามารถเพิ่มที่เก็บ: {message}", - "add_button": "เพิ่ม", - "no_repos_added": "ไม่มีการเพิ่มที่เก็บข้อมูล", - "remove_button": "ลบ", - "remove_repo_dialog_title": "ลบพื้นที่เก็บข้อมูล", - "remove_repo_dialog_text": "คุณแน่ใจหรือไม่ว่าต้องการลบที่เก็บนี้" - }, - "navigation": { - "tracker_tab_label": "ตัวติดตาม", - "customize_bottom_bar_title": "ปรับแต่งแถบด้านล่าง", - "customize_bottom_bar_subtitle": "เรียงลำดับ เพิ่ม หรือลบแท็บ สูงสุดห้า", - "shown_tabs_title": "แท็บที่แสดง", - "no_tabs_selected_text": "ไม่ได้เลือกแท็บ", - "available_tabs_title": "แท็บที่มีอยู่", - "reset_button": "รีเซ็ต", - "done_button": "เสร็จแล้ว" - }, - "scripting": { - "script_already_installed": "ติดตั้งสคริปต์แล้ว!", - "downloading_script": "กำลังดาวน์โหลดสคริปต์...", - "script_downloaded": "ดาวน์โหลดสคริปต์ {name} แล้ว!", - "download_script_failed": "ดาวน์โหลดสคริปต์ไม่สำเร็จ ตรวจสอบบันทึกเพื่อดูรายละเอียดเพิ่มเติม", - "import_script_from_url_title": "นำเข้าสคริปต์จาก URL", - "import_script_warning": "คำเตือน: สคริปต์ที่นำเข้าอาจเป็นอันตรายต่ออุปกรณ์ของคุณ นำเข้าสคริปต์จากแหล่งที่เชื่อถือได้เท่านั้น", - "enter_url_label": "ป้อน URL ที่นี่:", - "script_imported": "สคริปต์ {name} นำเข้าแล้ว!", - "import_failed": "ไม่สามารถนำเข้าสคริปต์ __ตัวยึดตำแหน่ง_0__. ตรวจสอบบันทึกเพื่อดูรายละเอียดเพิ่มเติม", - "import_button": "นำเข้า", - "update_module_button": "อัพเดตโมดูล", - "updating_script": "กำลังอัปเดตสคริปต์ {name}...", - "module_not_found": "ไม่พบโมดูล", - "updated_script": "อัปเดต {name} เป็นเวอร์ชัน {version}", - "update_module_failed": "ไม่สามารถอัปเดตโมดูลได้ ตรวจสอบบันทึกเพื่อดูรายละเอียดเพิ่มเติม", - "edit_module_button": "แก้ไขโมดูล", - "open_module_failed": "ไม่สามารถเปิดไฟล์โมดูลได้ ตรวจสอบบันทึกเพื่อดูรายละเอียดเพิ่มเติม", - "clear_module_data_button": "ล้างข้อมูลโมดูล", - "module_data_cleared": "ล้างข้อมูลโมดูลแล้ว!", - "clear_module_data_failed": "ไม่สามารถล้างข้อมูลโมดูลได้ ตรวจสอบบันทึกเพื่อดูรายละเอียดเพิ่มเติม", - "delete_module_button": "ลบโมดูล", - "deleted_script": "ลบสคริปต์ {name}!", - "delete_module_failed": "ไม่สามารถลบโมดูล ตรวจสอบบันทึกเพื่อดูรายละเอียดเพิ่มเติม", - "actions_title": "การดำเนินการ", - "no_description": "ไม่มีคำอธิบาย", - "update_available": "มีการอัปเดต: {version}", - "actions_button": "การดำเนินการ", - "loaded_script": "สคริปต์ที่โหลด {name}", - "unloaded_script": "สคริปต์ยกเลิกการโหลด {name}", - "enable_script_failed": "ไม่สามารถเปิดใช้งานสคริปต์ได้ ตรวจสอบบันทึกเพื่อดูรายละเอียดเพิ่มเติม", - "disable_script_failed": "ไม่สามารถปิดการใช้งานสคริปต์ ตรวจสอบบันทึกเพื่อดูรายละเอียดเพิ่มเติม", - "select_scripts_folder_toast": "โปรดเลือกโฟลเดอร์สคริปต์ของคุณ!", - "manage_repos_button": "จัดการ Repos", - "import_from_url_button": "นำเข้าจาก URL", - "open_scripts_folder_button": "เปิดโฟลเดอร์สคริปต์", - "no_settings_for_module": "โมดูลนี้ไม่มีการตั้งค่าใดๆ", - "installed_scripts_tab": "สคริปต์ที่ติดตั้ง", - "catalog_tab": "แคตตาล็อก", - "no_scripts_folder_selected_title": "ไม่ได้เลือกโฟลเดอร์สคริปต์", - "select_folder_button": "เลือกโฟลเดอร์", - "no_scripts_found_title": "ไม่พบสคริปต์", - "use_catalog_to_add_scripts": "ใช้แท็บแคตตาล็อกเพื่อเพิ่มสคริปต์!", - "ok_button_timeout": "ตกลง (__ตัวยึดตำแหน่ง_0__)", - "documentation_button": "เอกสารประกอบ", - "catalog": { - "script_already_installed": "ติดตั้งสคริปต์แล้ว!", - "download_failed": "การดาวน์โหลดล้มเหลว: {code}", - "script_downloaded": "ดาวน์โหลดสคริปต์แล้ว!", - "could_not_create_file": "ไม่สามารถสร้างไฟล์ได้", - "no_scripts_folder_selected": "ไม่ได้เลือกโฟลเดอร์สคริปต์", - "error": "ข้อผิดพลาด: {message}", - "no_repos_added": "ไม่มีการเพิ่มที่เก็บข้อมูล", - "repo_list_info": "คุณจะพบรายการ repos ได้ที่นี่:", - "link_text": "ลิงค์", - "no_scripts_available": "ไม่มีสคริปต์จาก repo ใด ๆ", - "by_author": "โดย __ตัวยึดตำแหน่ง_0__", - "version": "เวอร์ชัน: __ตัวยึดตำแหน่ง_0__", - "installed_button": "ติดตั้งแล้ว", - "download_button": "ดาวน์โหลด" - }, - "repos": { - "invalid_repo_title": "พื้นที่เก็บข้อมูลไม่ถูกต้อง", - "add_repo_button": "เพิ่มพื้นที่เก็บข้อมูล", - "add_repo_dialog_title": "เพิ่ม URL ที่เก็บ", - "repo_url_label": "URL ที่เก็บ", - "repo_added_toast": "เพิ่มพื้นที่เก็บข้อมูลเรียบร้อยแล้ว!", - "invalid_repo_error": "ดูเหมือนจะไม่ใช่ที่เก็บสคริปต์ที่ถูกต้อง", - "add_repo_failed_toast": "ไม่สามารถเพิ่มที่เก็บ: {message}", - "add_button": "เพิ่ม", - "no_repos_added": "ไม่มีการเพิ่มที่เก็บข้อมูล", - "remove_button": "ลบ", - "remove_repo_dialog_title": "ลบพื้นที่เก็บข้อมูล", - "remove_repo_dialog_text": "คุณแน่ใจหรือไม่ว่าต้องการลบที่เก็บนี้" - } - }, - "features": { - "config_import": { - "title": "ยืนยันการนำเข้า", - "back_button_description": "กลับ", - "config_imported_toast": "นำเข้าการกำหนดค่าแล้ว!", - "confirm_button": "ยืนยัน", - "expand_button_description": "ขยาย", - "enable_feature": "เปิดใช้งานคุณสมบัติ", - "enabled": "เปิดใช้งานแล้ว", - "disabled": "พิการ" - }, - "config_export": { - "title": "สรุปการส่งออก", - "back_button_description": "กลับ", - "save_button": "บันทึก", - "expand_button_description": "ขยาย", - "enable_feature": "เปิดใช้งานคุณสมบัติ", - "enabled": "เปิดใช้งานแล้ว", - "disabled": "พิการ" - } - }, - "manage_repos": { - "title": "จัดการที่เก็บ {type}", - "add_repo_button": "เพิ่มพื้นที่เก็บข้อมูล", - "add_repo_dialog_title": "เพิ่ม URL ที่เก็บ", - "repo_url_label": "URL ที่เก็บ", - "repo_added_successfully": "เพิ่มพื้นที่เก็บข้อมูลเรียบร้อยแล้ว!", - "add_repo_failed": "ไม่สามารถเพิ่มที่เก็บ: {message}", - "add_button": "เพิ่ม", - "no_repos_added": "ไม่มีการเพิ่มที่เก็บข้อมูล", - "remove_button": "ลบ" - } - }, - "rules": { - "toasts": { - "enabled": "{ruleName} เปิดใช้งานแล้ว", - "disabled": "{ruleName} ปิดการใช้งาน" - }, - "modes": { - "blacklist": "โหมดบัญชีดำ", - "whitelist": "โหมดไวท์ลิสต์" - }, - "properties": { - "auto_download": { - "name": "ดาวน์โหลดอัตโนมัติ", - "description": "ดาวน์โหลด Snaps โดยอัตโนมัติเมื่อดู", - "options": { - "blacklist": "แยกออกจากการดาวน์โหลดอัตโนมัติ", - "whitelist": "ดาวน์โหลดอัตโนมัติ" - } - }, - "stealth": { - "name": "โหมดซ่อนตัว", - "description": "ป้องกันไม่ให้ใครรู้ว่าคุณได้เปิด Snaps/แชทและการสนทนาของพวกเขาแล้ว", - "options": { - "blacklist": "แยกออกจากโหมดซ่อนตัว", - "whitelist": "โหมดซ่อนตัว" - } - }, - "auto_save": { - "name": "บันทึกอัตโนมัติ", - "description": "บันทึกข้อความแชทเมื่อดู", - "options": { - "blacklist": "แยกออกจากบันทึกอัตโนมัติ", - "whitelist": "บันทึกอัตโนมัติ" - } - }, - "unsaveable_messages": { - "name": "ข้อความที่ไม่สามารถบันทึกได้", - "description": "ป้องกันไม่ให้บุคคลอื่นบันทึกข้อความในการแชท", - "options": { - "blacklist": "แยกออกจากข้อความที่ไม่สามารถบันทึกได้", - "whitelist": "ข้อความที่ไม่สามารถบันทึกได้" - } - }, - "auto_open_snaps": { - "name": "เปิด Snaps อัตโนมัติ", - "description": "เปิด Snaps โดยอัตโนมัติเมื่อได้รับ", - "options": { - "blacklist": "แยกออกจาก Auto Open Snaps", - "whitelist": "เปิด Snaps อัตโนมัติ" - } - }, - "hide_friend_feed": { - "name": "ซ่อนจากฟีดเพื่อน" - }, - "e2e_encryption": { - "name": "ใช้การเข้ารหัส E2E" - }, - "pin_conversation": { - "name": "ปักหมุดการสนทนา" - }, - "exclude_message_logger": { - "name": "แยกออกจากเครื่องบันทึกข้อความ" - } - } - }, - "actions": { - "clean_snapchat_cache": { - "name": "ทำความสะอาดแคช Snapchat", - "description": "ทำความสะอาดแคช Snapchat" - }, - "manage_friend_list": { - "name": "จัดการรายชื่อเพื่อน", - "description": "นำเข้า/ส่งออกรายชื่อเพื่อนของคุณเมื่อสำรองข้อมูล" - }, - "export_chat_messages": { - "name": "ส่งออกข้อความแชท", - "description": "ส่งออกข้อความการสนทนาเป็นไฟล์ JSON/HTML/TXT" - }, - "export_memories": { - "name": "ส่งออกความทรงจำ", - "description": "ส่งออกความทรงจำเป็นไฟล์ ZIP" - }, - "bulk_messaging_action": { - "name": "การดำเนินการส่งข้อความจำนวนมาก", - "description": "ดำเนินการต่างๆ เช่น การลบเพื่อนหรือการลบการสนทนาจำนวนมาก" - }, - "regen_mappings": { - "name": "สร้างการแมปใหม่", - "description": "สร้างการแมปใหม่ด้วยตนเอง" - }, - "change_language": { - "name": "เปลี่ยนภาษา", - "description": "เปลี่ยนภาษาของ PurrfectSnap" - }, - "file_imports": { - "name": "การนำเข้าไฟล์", - "description": "นำเข้าไฟล์เพื่อใช้ใน Snapchat" - }, - "friend_tracker": { - "name": "ติดตามเพื่อน", - "description": "ติดตามเพื่อนของคุณบน Snapchat" - }, - "logger_history": { - "name": "ประวัติคนตัดไม้", - "description": "ดูประวัติข้อความที่บันทึกไว้" - } - }, - "features": { - "notices": { - "unstable": "⚠ ไม่เสถียร", - "ban_risk": "⚠ คุณสมบัตินี้อาจทำให้เกิดการแบน", - "internal_behavior": "⚠ สิ่งนี้อาจทำลายพฤติกรรมภายในของ Snapchat" - }, - "properties": { - "downloader": { - "name": "ดาวน์โหลด", - "description": "ดาวน์โหลด Snapchat สื่อ", - "properties": { - "save_folder": { - "name": "บันทึกโฟลเดอร์", - "description": "เลือกไดเร็กทอรีที่ควรดาวน์โหลดสื่อทั้งหมดไป" - }, - "auto_download_sources": { - "name": "แหล่งดาวน์โหลดอัตโนมัติ", - "description": "เลือกแหล่งที่จะดาวน์โหลดโดยอัตโนมัติ" - }, - "prevent_self_auto_download": { - "name": "ป้องกันการดาวน์โหลดอัตโนมัติด้วยตนเอง", - "description": "ป้องกันไม่ให้ Snaps ของคุณถูกดาวน์โหลดโดยอัตโนมัติ" - }, - "path_format": { - "name": "รูปแบบเส้นทาง", - "description": "ระบุรูปแบบเส้นทางไฟล์" - }, - "allow_duplicate": { - "name": "อนุญาตให้ทำซ้ำ", - "description": "อนุญาตให้ดาวน์โหลดสื่อเดียวกันได้หลายครั้ง" - }, - "merge_overlays": { - "name": "ผสานการซ้อนทับ", - "description": "รวมข้อความและสื่อของ Snap ไว้ในไฟล์เดียว" - }, - "force_image_format": { - "name": "รูปแบบภาพบังคับ", - "description": "บังคับให้บันทึกรูปภาพในรูปแบบที่ระบุ" - }, - "force_voice_note_format": { - "name": "บังคับรูปแบบบันทึกเสียง", - "description": "บังคับให้บันทึกเสียงบันทึกในรูปแบบที่ระบุ" - }, - "auto_download_voice_notes": { - "name": "ดาวน์โหลดบันทึกเสียงอัตโนมัติ", - "description": "ดาวน์โหลดบันทึกเสียงโดยอัตโนมัติเมื่อเล่น" - }, - "download_profile_pictures": { - "name": "ดาวน์โหลดรูปภาพโปรไฟล์", - "description": "อนุญาตให้คุณดาวน์โหลดรูปภาพโปรไฟล์จากหน้าโปรไฟล์" - }, - "opera_download_button": { - "name": "ปุ่มดาวน์โหลด Opera", - "description": "เพิ่มปุ่มดาวน์โหลดที่มุมขวาบนเมื่อดู Snap\nการกดปุ่มค้างไว้จะบังคับให้ดาวน์โหลด" - }, - "download_context_menu": { - "name": "ดาวน์โหลดเมนูบริบท", - "description": "ช่วยให้คุณสามารถดาวน์โหลด/ดูตัวอย่างข้อความจากการสนทนาหรือเรื่องราวโดยใช้เมนูบริบท\nการกดปุ่มค้างไว้จะบังคับให้ดาวน์โหลด" - }, - "ffmpeg_options": { - "name": "ตัวเลือก FFmpeg", - "description": "ระบุตัวเลือก FFmpeg เพิ่มเติม", - "properties": { - "threads": { - "name": "กระทู้", - "description": "จำนวนเธรดที่จะใช้" - }, - "preset": { - "name": "ที่ตั้งไว้ล่วงหน้า", - "description": "ตั้งค่าความเร็วของการแปลง" - }, - "constant_rate_factor": { - "name": "ปัจจัยอัตราคงที่", - "description": "ตั้งค่าปัจจัยอัตราคงที่สำหรับตัวเข้ารหัสวิดีโอ\nจาก 0 ถึง 51 สำหรับ libx264" - }, - "video_bitrate": { - "name": "อัตราบิตของวิดีโอ", - "description": "ตั้งค่าบิตเรตของวิดีโอ (kbps)" - }, - "audio_bitrate": { - "name": "อัตราบิตของเสียง", - "description": "ตั้งค่าบิตเรตเสียง (kbps)" - }, - "custom_video_codec": { - "name": "ตัวแปลงสัญญาณวิดีโอแบบกำหนดเอง", - "description": "ตั้งค่า Video Codec แบบกำหนดเอง (เช่น libx264)" - }, - "custom_audio_codec": { - "name": "ตัวแปลงสัญญาณเสียงแบบกำหนดเอง", - "description": "ตั้งค่าตัวแปลงสัญญาณเสียงแบบกำหนดเอง (เช่น AAC)" - } - } - }, - "logging": { - "name": "การบันทึก", - "description": "แสดงคำอวยพรเมื่อมีการดาวน์โหลดสื่อ" - }, - "custom_path_format": { - "name": "รูปแบบเส้นทางที่กำหนดเอง", - "description": "ระบุรูปแบบเส้นทางที่กำหนดเองสำหรับสื่อที่ดาวน์โหลด\n\nตัวแปรที่มีอยู่:\n - %ชื่อผู้ใช้%\n - %แหล่งที่มา%\n - %แฮช%\n - %วันที่_เวลา%" - } - } - }, - "user_interface": { - "name": "ส่วนต่อประสานกับผู้ใช้", - "description": "เปลี่ยนรูปลักษณ์ของ Snapchat", - "properties": { - "enable_app_appearance": { - "name": "เปิดใช้งานการตั้งค่าลักษณะที่ปรากฏของแอป", - "description": "เปิดใช้งานการตั้งค่าลักษณะที่ปรากฏของแอปที่ซ่อนอยู่\nอาจไม่จำเป็นสำหรับ Snapchat เวอร์ชันใหม่กว่า" - }, - "friend_feed_message_preview": { - "name": "ดูตัวอย่างข้อความฟีดเพื่อน", - "description": "แสดงตัวอย่างข้อความล่าสุดในฟีดเพื่อน", - "properties": { - "amount": { - "name": "จำนวน", - "description": "จำนวนข้อความที่จะดูตัวอย่าง" - } - } - }, - "snap_preview": { - "name": "ดูตัวอย่างสแนป", - "description": "แสดงตัวอย่างเล็กๆ ถัดจาก Snaps ที่มองไม่เห็นในแชท" - }, - "bootstrap_override": { - "name": "Bootstrap แทนที่", - "description": "แทนที่การตั้งค่าบูตสแตรปของอินเทอร์เฟซผู้ใช้", - "properties": { - "app_appearance": { - "name": "รูปลักษณ์ของแอพ", - "description": "ตั้งค่าลักษณะที่ปรากฏของแอปแบบถาวร" - }, - "home_tab": { - "name": "แท็บหน้าแรก", - "description": "แทนที่แท็บเริ่มต้นเมื่อเปิด Snapchat" - } - } - }, - "force_amoled_theme": { - "name": "โหมดมืด Amoled", - "description": "ใช้พื้นหลังสีดำจริงสำหรับธีมสีเข้ม" - }, - "map_friend_nametags": { - "name": "แท็กชื่อแผนที่เพื่อนที่ได้รับการปรับปรุง", - "description": "ปรับปรุง Nametags ของเพื่อนบน Snapmap" - }, - "prevent_message_list_auto_scroll": { - "name": "ป้องกันรายการข้อความเลื่อนอัตโนมัติ", - "description": "ป้องกันไม่ให้รายการข้อความเลื่อนไปที่ด้านล่างเมื่อส่ง/รับข้อความ" - }, - "streak_expiration_info": { - "name": "แสดงข้อมูลการหมดอายุของริ้ว", - "description": "แสดงตัวจับเวลาการหมดอายุของ Streak ถัดจากตัวนับ Streaks" - }, - "hide_friend_feed_entry": { - "name": "ซ่อนรายการฟีดเพื่อน", - "description": "ซ่อนเพื่อนที่ระบุจากฟีดเพื่อน\nใช้แท็บโซเชียลเพื่อจัดการฟีเจอร์นี้" - }, - "hide_streak_restore": { - "name": "ซ่อนการคืนค่าริ้ว", - "description": "ซ่อนปุ่มคืนค่าในฟีดเพื่อน" - }, - "hide_quick_add_suggestions": { - "name": "ซ่อนคำแนะนำเพิ่มด่วน", - "description": "ลบการแนะนำเพื่อนอย่างรวดเร็ว" - }, - "hide_story_suggestions": { - "name": "ซ่อนคำแนะนำเรื่องราว", - "description": "ลบคำแนะนำออกจากหน้าเรื่องราว" - }, - "hide_ui_components": { - "name": "ซ่อนส่วนประกอบ UI", - "description": "เลือกองค์ประกอบ UI ที่จะซ่อน" - }, - "opera_media_quick_info": { - "name": "ข้อมูลด่วนของ Opera Media", - "description": "แสดงข้อมูลที่เป็นประโยชน์ของสื่อ เช่น วันที่สร้างในเมนูบริบทของโปรแกรมดูโอเปร่า" - }, - "old_bitmoji_selfie": { - "name": "เซลฟี่ Bitmoji เก่า", - "description": "นำภาพเซลฟี่ Bitmoji กลับมาจาก Snapchat เวอร์ชันเก่า" - }, - "disable_spotlight": { - "name": "ปิดการใช้งานสปอตไลท์", - "description": "ปิดการใช้งานหน้าสปอตไลท์" - }, - "friend_feed_menu_buttons": { - "name": "ปุ่มเมนูฟีดเพื่อน", - "description": "เลือกปุ่มที่จะแสดงในเมนูฟีดเพื่อน" - }, - "auto_close_friend_feed_menu": { - "name": "ปิดเมนูฟีดเพื่อนอัตโนมัติ", - "description": "ปิดเมนูฟีดเพื่อนโดยอัตโนมัติหลังจากกดปุ่มตั้งค่า" - }, - "vertical_story_viewer": { - "name": "โปรแกรมดูเรื่องราวแนวตั้ง", - "description": "เปิดใช้งานโปรแกรมดูเรื่องราวแนวตั้งสำหรับเรื่องราวทั้งหมด" - }, - "enable_friend_feed_menu_bar": { - "name": "แถบเมนูฟีดเพื่อน", - "description": "เปิดใช้งานแถบเมนูฟีดเพื่อนใหม่" - }, - "message_indicators": { - "name": "ตัวบ่งชี้ข้อความ", - "description": "เพิ่มไอคอนตัวบ่งชี้เฉพาะให้กับข้อความ\nหมายเหตุ: ตัวบ่งชี้อาจไม่แม่นยำ 100%" - }, - "stealth_mode_indicator": { - "name": "ตัวบ่งชี้โหมดซ่อนตัว", - "description": "เพิ่มอิโมจิ 🎃 ถัดจากการสนทนาในโหมดซ่อนตัว" - }, - "edit_text_override": { - "name": "แก้ไขการแทนที่ข้อความ", - "description": "แทนที่ลักษณะการทำงานของช่องข้อความ" - }, - "prevent_forced_keyboard": { - "name": "ป้องกันการบังคับคีย์บอร์ด", - "description": "ป้องกันไม่ให้ Snapchat เปิดคีย์บอร์ดโดยอัตโนมัติเมื่อคุณเปิดการสนทนา" - }, - "settings_menu": { - "name": "เมนูการตั้งค่า", - "description": "เปลี่ยนวิธีการเปิดเมนู PurrfectSnap", - "options": { - "default": "ค่าเริ่มต้น", - "legacy": "มรดก" - } - } - } - }, - "messaging": { - "name": "การส่งข้อความ", - "description": "เปลี่ยนวิธีการโต้ตอบกับเพื่อน", - "properties": { - "bypass_screenshot_detection": { - "name": "บายพาสการตรวจจับภาพหน้าจอ", - "description": "ป้องกันไม่ให้ Snapchat ตรวจพบเมื่อคุณถ่ายภาพหน้าจอ" - }, - "anonymous_story_viewing": { - "name": "การดูเรื่องราวที่ไม่ระบุชื่อ", - "description": "ป้องกันไม่ให้ใครรู้ว่าคุณได้เห็นเรื่องราวของพวกเขาแล้ว" - }, - "prevent_story_rewatch_indicator": { - "name": "ป้องกันตัวบ่งชี้การดูเรื่องราวซ้ำ", - "description": "ป้องกันไม่ให้ใครรู้ว่าคุณได้ดูเรื่องราวของพวกเขาซ้ำแล้ว" - }, - "hide_peek_a_peek": { - "name": "ซ่อน Peek-a-Peek", - "description": "ป้องกันไม่ให้มีการส่งการแจ้งเตือนเมื่อคุณปัดนิ้วลงครึ่งหนึ่งในการแชท" - }, - "hide_bitmoji_presence": { - "name": "ซ่อนการแสดงตนของ Bitmoji", - "description": "ป้องกันไม่ให้ Bitmoji ของคุณปรากฏขึ้นขณะอยู่ในแชท" - }, - "hide_typing_notifications": { - "name": "ซ่อนการแจ้งเตือนการพิมพ์", - "description": "ป้องกันไม่ให้ใครรู้ว่าคุณกำลังพิมพ์ข้อความ" - }, - "unlimited_snap_view_time": { - "name": "ไม่จำกัดเวลาดู Snap", - "description": "ลบการจำกัดเวลาสำหรับการดู Snaps" - }, - "auto_mark_as_read": { - "name": "ทำเครื่องหมายอัตโนมัติว่าอ่านแล้ว", - "description": "ทำเครื่องหมายข้อความ/สแน็ปอินว่าอ่านแล้วโดยอัตโนมัติแม้ว่าจะเปิดใช้งานโหมดซ่อนตัวก็ตาม" - }, - "mark_snap_as_seen_button": { - "name": "ทำเครื่องหมายปุ่ม Snap ตามที่เห็น", - "description": "เพิ่มปุ่มเพื่อทำเครื่องหมาย Snap ตามที่เห็นเมื่อดู\nสิ่งนี้จะทำงานได้แม้ว่าจะเปิดใช้งานโหมดซ่อนตัวก็ตาม" - }, - "skip_when_marking_as_seen": { - "name": "ข้ามเมื่อทำเครื่องหมายว่าดูแล้ว", - "description": "ข้ามไปยัง Snap ถัดไปโดยอัตโนมัติเมื่อทำเครื่องหมาย Snap ตามที่เห็น\nใช้ร่วมกับปุ่มทำเครื่องหมาย Snap ตามที่เห็น" - }, - "loop_media_playback": { - "name": "การเล่นสื่อแบบวนซ้ำ", - "description": "วนการเล่นสื่อเมื่อดู Snaps / Stories" - }, - "disable_replay_in_ff": { - "name": "ปิดการใช้งานการเล่นซ้ำใน FF", - "description": "ปิดการใช้งานความสามารถในการเล่นซ้ำด้วยการกดแบบยาวจากฟีดเพื่อน" - }, - "half_swipe_notifier": { - "name": "ตัวแจ้งเตือนการปัดครึ่งนิ้ว", - "description": "แจ้งเตือนคุณเมื่อมีคนปัดนิ้วเข้าสู่การสนทนาเพียงครึ่งเดียว", - "properties": { - "min_duration": { - "name": "ระยะเวลาขั้นต่ำ", - "description": "ระยะเวลาขั้นต่ำของการปัดครึ่งนิ้ว (เป็นวินาที)" - }, - "max_duration": { - "name": "ระยะเวลาสูงสุด", - "description": "ระยะเวลาสูงสุดของการปัดครึ่งนิ้ว (เป็นวินาที)" - } - } - }, - "call_start_confirmation": { - "name": "การยืนยันการเริ่มต้นการโทร", - "description": "แสดงข้อความยืนยันเมื่อเริ่มการโทร" - }, - "unlimited_conversation_pinning": { - "name": "การปักหมุดการสนทนาไม่จำกัด", - "description": "ช่วยให้คุณสามารถปักหมุดการสนทนาในเครื่องได้ไม่จำกัดจำนวน" - }, - "disable_snap_mode_restrictions": { - "name": "ปิดใช้งานข้อจำกัดโหมดสแน็ป", - "description": "ช่วยให้คุณดู Snaps ที่ทำลายตัวเองได้โดยไม่มีข้อจำกัด" - }, - "prevent_message_sending": { - "name": "ป้องกันการส่งข้อความ", - "description": "ป้องกันการส่งข้อความบางประเภท" - }, - "friend_mutation_notifier": { - "name": "ตัวแจ้งการกลายพันธุ์ของเพื่อน", - "description": "แจ้งเตือนคุณเมื่อมีการเปลี่ยนแปลงในโปรไฟล์ของเพื่อน" - }, - "better_notifications": { - "name": "การแจ้งเตือนที่ดีขึ้น", - "description": "เพิ่มข้อมูลเพิ่มเติมในการแจ้งเตือนที่ได้รับ", - "properties": { - "group_notifications": { - "name": "การแจ้งเตือนแบบกลุ่ม", - "description": "การแจ้งเตือนกลุ่มเป็นอันเดียว" - }, - "chat_preview": { - "name": "ดูตัวอย่างการแชท", - "description": "แสดงตัวอย่างข้อความที่ได้รับในการแจ้งเตือน" - }, - "media_preview": { - "name": "การแสดงตัวอย่างสื่อ", - "description": "แสดงตัวอย่างสื่อประเภทที่เลือกในการแจ้งเตือน" - }, - "media_caption": { - "name": "คำบรรยายสื่อ", - "description": "แสดงคำบรรยายสื่อที่แนบมาในการแจ้งเตือน" - }, - "stacked_media_messages": { - "name": "ข้อความสื่อแบบซ้อน", - "description": "รวมข้อความสื่อหลายรายการไว้ในการแจ้งเตือนข้อความเดียวเมื่อไม่สามารถดูตัวอย่างได้ ใช้ร่วมกับการดูตัวอย่างแชท" - }, - "friend_add_source": { - "name": "เพื่อนเพิ่มแหล่งที่มา", - "description": "แสดงแหล่งที่มาของคำขอเป็นเพื่อนในการแจ้งเตือน" - }, - "reply_button": { - "name": "ปุ่มตอบกลับ", - "description": "เพิ่มปุ่มตอบกลับไปยังการแจ้งเตือน" - }, - "smart_replies": { - "name": "การตอบกลับอัจฉริยะ", - "description": "เพิ่มการตอบกลับที่แนะนำสำหรับการแจ้งเตือน (Android 10+) ใช้ร่วมกับปุ่มตอบกลับ" - }, - "download_button": { - "name": "ปุ่มดาวน์โหลด", - "description": "ให้คุณดาวน์โหลดสื่อจากการแจ้งเตือน" - }, - "mark_as_read_button": { - "name": "ทำเครื่องหมายว่าปุ่มอ่านแล้ว", - "description": "ช่วยให้คุณสามารถทำเครื่องหมายข้อความว่าอ่านแล้วจากการแจ้งเตือน" - }, - "mark_as_read_and_save_in_chat": { - "name": "ทำเครื่องหมายว่าอ่านแล้วและบันทึกในการแชท", - "description": "เพิ่มเครื่องหมายว่าอ่านแล้วและบันทึกในปุ่มแชทในการแจ้งเตือน" - } - } - }, - "notification_blacklist": { - "name": "บัญชีดำการแจ้งเตือน", - "description": "เลือกการแจ้งเตือนที่ควรถูกบล็อก" - }, - "message_logger": { - "name": "เครื่องบันทึกข้อความ", - "description": "ป้องกันไม่ให้ข้อความถูกลบ", - "properties": { - "keep_my_own_messages": { - "name": "เก็บข้อความของฉันเอง", - "description": "ป้องกันไม่ให้ข้อความของคุณถูกลบ" - }, - "auto_purge": { - "name": "ล้างอัตโนมัติ", - "description": "ลบข้อความแคชที่เก่ากว่าระยะเวลาที่ระบุโดยอัตโนมัติ" - }, - "message_filter": { - "name": "ตัวกรองข้อความ", - "description": "เลือกข้อความที่จะบันทึก (ว่างสำหรับข้อความทั้งหมด)" - }, - "deleted_message_color": { - "name": "สีข้อความที่ถูกลบ", - "description": "ตั้งค่าสีของข้อความที่ถูกลบ" - } - } - }, - "auto_save_messages_in_conversations": { - "name": "บันทึกข้อความอัตโนมัติ", - "description": "บันทึกทุกข้อความในการสนทนาโดยอัตโนมัติ" - }, - "gallery_media_send_override": { - "name": "แทนที่การส่งสื่อแกลเลอรี", - "description": "ปลอมแปลงแหล่งสื่อเมื่อส่งจากแกลเลอรี" - }, - "strip_media_metadata": { - "name": "ตัดข้อมูลเมตาของสื่อ", - "description": "ลบข้อมูลเมตาของสื่อก่อนที่จะส่งเป็นข้อความ" - }, - "bypass_message_retention_policy": { - "name": "ข้ามนโยบายการเก็บรักษาข้อความ", - "description": "ป้องกันไม่ให้ข้อความถูกลบหลังจากดูแล้ว" - }, - "bypass_message_action_restrictions": { - "name": "ข้ามข้อจำกัดการดำเนินการข้อความ", - "description": "ช่วยให้คุณโต้ตอบได้ทันทีโดยไม่ต้องเปิดหรือบันทึกข้อความที่ไม่สามารถบันทึกได้" - }, - "remove_groups_locked_status": { - "name": "ลบสถานะล็อคกลุ่ม", - "description": "ช่วยให้คุณดูข้อมูลกลุ่มหลังจากถูกเตะ" - }, - "double_tap_chat_action": { - "name": "การดำเนินการแชทด้วยการแตะสองครั้ง", - "description": "ดำเนินการแบบกำหนดเองเมื่อแตะสองครั้งที่ข้อความในการแชท" - }, - "double_tap_chat_action_custom_emoji": { - "name": "ปฏิกิริยาโต้ตอบอีโมจิที่กำหนดเองด้วยการแตะสองครั้ง", - "description": "ตั้งค่าการตอบสนองอีโมจิแบบกำหนดเองสำหรับการแชทด้วยการแตะสองครั้ง" - } - } - }, - "global": { - "name": "ทั่วโลก", - "description": "ปรับแต่งการตั้งค่า Snapchat ทั่วโลก", - "properties": { - "better_location": { - "name": "ทำเลที่ตั้งดีกว่า", - "description": "ปรับปรุงตำแหน่ง Snapchat", - "properties": { - "spoof_location": { - "name": "สถานที่ปลอมแปลง", - "description": "ปลอมแปลงตำแหน่งของคุณไปยังตำแหน่งที่ระบุ" - }, - "coordinates": { - "name": "พิกัด", - "description": "กำหนดพิกัดของตำแหน่งที่ถูกปลอมแปลง" - }, - "walk_radius": { - "name": "รัศมีการเดิน", - "description": "สุ่มเดินไปรอบๆ ในรัศมีนี้ (ฟุต)" - }, - "always_update_location": { - "name": "อัปเดตตำแหน่งเสมอ", - "description": "บังคับให้ Snapchat อัปเดตตำแหน่งแม้ว่าจะไม่ได้รับข้อมูล GPS ก็ตาม" - }, - "suspend_location_updates": { - "name": "ระงับการอัปเดตตำแหน่ง", - "description": "ป้องกันไม่ให้ตำแหน่งของคุณอัปเดต" - }, - "spoof_battery_level": { - "name": "ระดับแบตเตอรี่ปลอม", - "description": "ปลอมแปลงระดับแบตเตอรี่ของอุปกรณ์ของคุณบนแผนที่\nค่าต้องอยู่ระหว่าง 0 ถึง 100" - }, - "spoof_headphones": { - "name": "หูฟังปลอม", - "description": "ปลอมแปลงสถานะการฟังเพลงบนแผนที่" - }, - "show_battery_level": { - "name": "แสดงระดับแบตเตอรี่", - "description": "แสดงระดับแบตเตอรี่ของเพื่อนของคุณบนแผนที่" - } - } - }, - "snapchat_plus": { - "name": "สแนปแชต พลัส", - "description": "เปิดใช้งานคุณสมบัติ Snapchat Plus\nคุณลักษณะฝั่งเซิร์ฟเวอร์บางอย่างอาจไม่ทำงาน" - }, - "media_upload_quality": { - "name": "คุณภาพการอัพโหลดสื่อ", - "description": "แทนที่คุณภาพการอัพโหลดสื่อ", - "properties": { - "force_video_upload_source_quality": { - "name": "บังคับคุณภาพแหล่งที่มาของการอัปโหลดวิดีโอ", - "description": "บังคับให้ Snapchat ใช้คุณภาพแหล่งที่มาเมื่ออัปโหลดวิดีโอ\nโปรดทราบว่าการดำเนินการนี้อาจไม่สามารถลบข้อมูลเมตาออกจากสื่อได้" - }, - "disable_image_compression": { - "name": "ปิดใช้งานการบีบอัดรูปภาพ", - "description": "ปิดใช้งานการบีบอัดภาพเมื่ออัพโหลดสื่อ" - }, - "custom_image_upload_format": { - "name": "รูปแบบการอัปโหลดรูปภาพที่กำหนดเอง", - "description": "ตั้งค่ารูปแบบการอัพโหลดรูปภาพแบบกำหนดเอง\nเลือกรูปแบบแบบไม่สูญเสียข้อมูล (เช่น PNG) เพื่อให้ได้คุณภาพที่ดีที่สุด" - } - } - }, - "disable_confirmation_dialogs": { - "name": "ปิดการใช้งานกล่องโต้ตอบการยืนยัน", - "description": "ยืนยันการกระทำที่เลือกโดยอัตโนมัติ" - }, - "auto_updater": { - "name": "อัปเดตอัตโนมัติ", - "description": "ตรวจสอบการอัปเดตใหม่โดยอัตโนมัติ" - }, - "disable_metrics": { - "name": "ปิดการใช้งานตัวชี้วัด", - "description": "บล็อกการส่งข้อมูลการวิเคราะห์เฉพาะไปยัง Snapchat" - }, - "disable_story_sections": { - "name": "ปิดการใช้งานส่วนเรื่องราว", - "description": "ลบส่วนต่างๆ ออกจากหน้าเรื่องราว\nอาจต้องมีการรีเฟรชเพื่อให้ทำงานได้อย่างถูกต้อง" - }, - "block_ads": { - "name": "บล็อกโฆษณา", - "description": "ป้องกันไม่ให้โฆษณาแสดง" - }, - "disable_custom_tabs": { - "name": "ปิดการใช้งานแท็บแบบกำหนดเอง", - "description": "เปิดลิงก์ในแอปพลิเคชันที่รองรับ แทนที่จะเปิดในเว็บเบราว์เซอร์" - }, - "disable_permission_requests": { - "name": "ปิดการใช้งานการร้องขอสิทธิ์", - "description": "ป้องกันไม่ให้ Snapchat ขอสิทธิ์เฉพาะ" - }, - "disable_memories_snap_feed": { - "name": "ปิดใช้งานฟีด Snap ความทรงจำ", - "description": "ป้องกันไม่ให้ Snapchat แสดงความทรงจำล่าสุดเมื่อคุณปัดขึ้นในกล้อง" - }, - "spotlight_comments_username": { - "name": "ชื่อผู้ใช้ความคิดเห็นสปอตไลท์", - "description": "แสดงชื่อผู้ใช้ของผู้เขียนในความคิดเห็นของ Spotlight" - }, - "bypass_video_length_restriction": { - "name": "บายพาสข้อจำกัดความยาววิดีโอ", - "description": "โสด: ส่งวิดีโอเดียว\nแยก: แยกวิดีโอหลังจากแก้ไข" - }, - "default_video_playback_rate": { - "name": "อัตราการเล่นวิดีโอเริ่มต้น", - "description": "ตั้งค่าความเร็วเริ่มต้นสำหรับการเล่นวิดีโอ\nค่าต้องอยู่ระหว่าง 0.1 ถึง 4.0" - }, - "video_playback_rate_slider": { - "name": "ตัวเลื่อนอัตราการเล่นวิดีโอ", - "description": "เพิ่มแถบเลื่อนในเมนูบริบทของโอเปร่าเพื่อเปลี่ยนอัตราการเล่นวิดีโอ\nหมายเหตุ: การเปลี่ยนแปลงมีผลกับวิดีโอต่อๆ ไปเท่านั้น" - }, - "disable_google_play_dialogs": { - "name": "ปิดการใช้งานกล่องโต้ตอบบริการ Google Play", - "description": "ป้องกันไม่ให้แสดงกล่องโต้ตอบความพร้อมใช้งานของบริการ Google Play" - }, - "default_volume_controls": { - "name": "การควบคุมระดับเสียงเริ่มต้น", - "description": "บังคับให้ Snapchat ใช้การควบคุมระดับเสียงของระบบ" - }, - "disable_telecom_framework": { - "name": "ปิดการใช้งานกรอบโทรคมนาคม", - "description": "ป้องกันไม่ให้ Snapchat ใช้เฟรมเวิร์ก Android Telecom\nซึ่งจะทำให้คุณสามารถฟังเพลงขณะใช้สายได้" - }, - "hide_active_music": { - "name": "ซ่อนเพลงที่ใช้งานอยู่", - "description": "ป้องกันไม่ให้ Snapchat รู้ว่าคุณกำลังฟังเพลง\nซึ่งจะช่วยให้คุณสามารถถ่ายภาพได้โดยใช้ปุ่มควบคุมระดับเสียงขณะฟังเพลง" - }, - "disable_snap_splitting": { - "name": "ปิดใช้งานการแยก Snap", - "description": "ป้องกันไม่ให้ Snaps ถูกแบ่งออกเป็นหลายส่วน\nรูปภาพที่คุณส่งจะกลายเป็นวิดีโอ" - } - } - }, - "rules": { - "name": "กฎ", - "description": "จัดการคุณสมบัติอัตโนมัติสำหรับบุคคลแต่ละบุคคล" - }, - "camera": { - "name": "กล้อง", - "description": "ปรับการตั้งค่าที่เหมาะสมเพื่อให้ได้ภาพที่สมบูรณ์แบบ", - "properties": { - "disable_cameras": { - "name": "ปิดการใช้งานกล้อง", - "description": "ป้องกันไม่ให้ Snapchat ใช้กล้องที่เลือก" - }, - "black_photos": { - "name": "ภาพถ่ายสีดำ", - "description": "แทนที่ภาพถ่ายที่ถ่ายด้วยพื้นหลังสีดำ\nวิดีโอจะไม่ได้รับผลกระทบ" - }, - "immersive_camera_preview": { - "name": "การแสดงตัวอย่างที่สมจริง", - "description": "ป้องกันไม่ให้ Snapchat ครอบตัดการแสดงตัวอย่างกล้อง\nนี่อาจทำให้กล้องสั่นไหวในอุปกรณ์บางอย่าง" - }, - "override_front_resolution": { - "name": "แทนที่ความละเอียดด้านหน้า", - "description": "แทนที่ความละเอียดของกล้องสำหรับกล้องหน้า" - }, - "override_back_resolution": { - "name": "แทนที่ความละเอียดด้านหลัง", - "description": "แทนที่ความละเอียดของกล้องสำหรับกล้องหลัง" - }, - "custom_resolution": { - "name": "ความละเอียดที่กำหนดเอง", - "description": "ตั้งค่าความละเอียดของกล้องเอง กว้าง x สูง (เช่น 1920x1080)\nอุปกรณ์ของคุณต้องรองรับความละเอียดที่กำหนดเอง" - }, - "front_custom_frame_rate": { - "name": "อัตราเฟรมที่กำหนดเองด้านหน้า", - "description": "แทนที่อัตราเฟรมของกล้องหน้า" - }, - "back_custom_frame_rate": { - "name": "กลับอัตราเฟรมที่กำหนดเอง", - "description": "แทนที่อัตราเฟรมของกล้องหลัง" - }, - "force_camera_source_encoding": { - "name": "บังคับให้เข้ารหัสแหล่งที่มาของกล้อง", - "description": "บังคับให้เข้ารหัสแหล่งที่มาของกล้อง" - }, - "startup_default_camera": { - "name": "กล้องเริ่มต้นเริ่มต้น", - "description": "ตั้งค่ากล้องเริ่มต้นเมื่อเปิด Snapchat" - }, - "hevc_recording": { - "name": "การบันทึก HEVC", - "description": "ใช้ตัวแปลงสัญญาณ HEVC (H.265) สำหรับการบันทึกวิดีโอ" - } - } - }, - "streaks_reminder": { - "name": "การแจ้งเตือนลายเส้น", - "description": "แจ้งให้คุณทราบเป็นระยะเกี่ยวกับลายเส้นของคุณ", - "properties": { - "interval": { - "name": "ช่วงเวลา", - "description": "ช่วงเวลาระหว่างการเตือนแต่ละครั้ง (ชั่วโมง)" - }, - "remaining_hours": { - "name": "เวลาที่เหลืออยู่", - "description": "ระยะเวลาที่เหลือก่อนที่จะแสดงการแจ้งเตือน (ชั่วโมง)" - }, - "group_notifications": { - "name": "การแจ้งเตือนแบบกลุ่ม", - "description": "การแจ้งเตือนกลุ่มเป็นอันเดียว" - } - } - }, - "experimental": { - "name": "การทดลอง", - "description": "คุณสมบัติการทดลอง", - "properties": { - "native_hooks": { - "name": "ตะขอพื้นเมือง", - "description": "คุณสมบัติที่ไม่ปลอดภัยที่เชื่อมต่อกับโค้ดเนทิฟของ Snapchat", - "properties": { - "composer_hooks": { - "name": "นักแต่งเพลงฮุคส์", - "description": "แทรกโค้ดลงในเฟรมเวิร์ก UI ข้ามแพลตฟอร์มของ Composer", - "properties": { - "show_first_created_username": { - "name": "แสดงชื่อผู้ใช้ที่สร้างขึ้นครั้งแรก", - "description": "แสดงชื่อผู้ใช้ที่สร้างขึ้นครั้งแรกถัดจากชื่อผู้ใช้ปัจจุบันในหน้าโปรไฟล์" - }, - "bypass_camera_roll_limit": { - "name": "บายพาสขีดจำกัดม้วนฟิล์ม", - "description": "เพิ่มจำนวนสื่อสูงสุดที่คุณสามารถส่งจากม้วนฟิล์ม" - }, - "custom_self_destruct_snap_delay": { - "name": "ความล่าช้าในการทำลายตนเองของ Snap แบบกำหนดเอง", - "description": "ให้ตัวเลือกเพิ่มเติมสำหรับตัวจับเวลาการทำลายตนเองเมื่อส่ง Snap" - }, - "composer_console": { - "name": "คอนโซลนักแต่งเพลง", - "description": "ช่วยให้คุณสามารถรันโค้ด JavaScript ใน Composer (arm64 เท่านั้น)" - }, - "composer_logs": { - "name": "บันทึกของผู้แต่ง", - "description": "เปลี่ยนเส้นทางบันทึกคอนโซลของ Composer ไปยัง PurrfectSnap" - } - } - }, - "disable_bitmoji": { - "name": "ปิดการใช้งาน Bitmoji", - "description": "ปิดการใช้งานโปรไฟล์เพื่อน Bitmoji" - }, - "custom_emoji_font": { - "name": "แบบอักษรอีโมจิที่กำหนดเอง", - "description": "ช่วยให้คุณใช้แบบอักษรอีโมจิที่กำหนดเองได้ ใช้ได้กับแบบอักษร .ttf เท่านั้น" - }, - "custom_shared_library": { - "name": "ไลบรารีที่ใช้ร่วมกันแบบกำหนดเอง", - "description": "โหลดไลบรารีที่ใช้ร่วมกันแบบกำหนดเองลงใน Snapchat คุณลักษณะนี้มีไว้เพื่อการทดสอบเท่านั้น" - } - } - }, - "spoof": { - "name": "หลอก", - "description": "ปลอมแปลงข้อมูลต่างๆ เกี่ยวกับคุณ", - "properties": { - "play_store_installer_package_name": { - "name": "ชื่อแพ็คเกจตัวติดตั้ง Play Store", - "description": "แทนที่ชื่อแพ็คเกจตัวติดตั้งเป็น com.android.vending" - }, - "remove_vpn_transport_flag": { - "name": "ลบการตั้งค่าสถานะการขนส่ง VPN", - "description": "ป้องกันไม่ให้ Snapchat ตรวจจับ VPN" - }, - "remove_mock_location_flag": { - "name": "ลบธงตำแหน่งจำลอง", - "description": "ป้องกันไม่ให้ Snapchat ตรวจจับตำแหน่งจำลอง" - } - } - }, - "convert_message_locally": { - "name": "แปลงข้อความในเครื่อง", - "description": "แปลงสแนปเพื่อแชทสื่อภายนอกในเครื่อง ซึ่งจะปรากฏในเมนูบริบทการดาวน์โหลดแชท" - }, - "media_file_picker": { - "name": "ตัวเลือกไฟล์มีเดีย", - "description": "ให้คุณเลือกไฟล์วิดีโอ/เสียงจากแกลเลอรี" - }, - "story_logger": { - "name": "เครื่องบันทึกเรื่องราว", - "description": "นำเสนอประวัติเรื่องราวของเพื่อนๆ" - }, - "call_recorder": { - "name": "บันทึกการโทร", - "description": "บันทึกการโทรด้วยเสียงโดยอัตโนมัติ" - }, - "account_switcher": { - "name": "ตัวสลับบัญชี", - "description": "ช่วยให้คุณสามารถสลับระหว่างบัญชีโดยไม่ต้องออกจากระบบ\nกดที่ไอคอนค้นหาถัดจากโปรไฟล์ Bitmoji ของคุณค้างไว้เพื่อเปิดเมนู\nหมายเหตุ: คุณลักษณะนี้ยังอยู่ในช่วงทดลองและอาจมีการเปลี่ยนแปลงในอนาคต", - "properties": { - "auto_backup_current_account": { - "name": "สำรองบัญชีกระแสรายวันอัตโนมัติ", - "description": "สำรองข้อมูลบัญชีปัจจุบันโดยอัตโนมัติเมื่อออกจากระบบหรือเปลี่ยนบัญชี" - } - } - }, - "better_transcript": { - "name": "การถอดเสียงที่ดีขึ้น", - "description": "ปรับปรุงการถอดเสียงบันทึกเสียง", - "properties": { - "force_transcription": { - "name": "บังคับให้ถอดเสียงบันทึกเสียง", - "description": "อนุญาตให้ถอดเสียงบันทึกเสียงทั้งหมด" - }, - "preferred_transcription_lang": { - "name": "ภาษาการถอดความที่ต้องการ", - "description": "ภาษาที่ต้องการสำหรับการถอดเสียงบันทึกเสียง (เช่น EN, ES, FR)" - }, - "notification_transcript": { - "name": "สำเนาการแจ้งเตือน", - "description": "ถอดเสียงบันทึกเสียงในการแจ้งเตือน\nคุณลักษณะนี้จำเป็นต้องเปิดใช้งานคุณลักษณะตัวอย่างการแชทในการแจ้งเตือนที่ดีกว่า" - } - } - }, - "voice_note_auto_play": { - "name": "บันทึกเสียงเล่นอัตโนมัติ", - "description": "เล่นบันทึกเสียงถัดไปโดยอัตโนมัติหลังจากบันทึกเสียงปัจจุบันเสร็จสิ้น" - }, - "friend_notes": { - "name": "บันทึกของเพื่อน", - "description": "ช่วยให้คุณสามารถเพิ่มบันทึกลงในโปรไฟล์เพื่อนได้" - }, - "cof_experiments": { - "name": "การทดลอง COF", - "description": "เปิดใช้งานคุณสมบัติ Snapchat ที่ยังไม่เผยแพร่/เบต้า" - }, - "context_menu_fix": { - "name": "แก้ไขเมนูบริบท", - "description": "พยายามซ่อมแซมเมนูฟีดเพื่อน เนื่องจากเมื่ออุปกรณ์ออฟไลน์อยู่จะไม่สามารถแสดงได้อย่างถูกต้อง" - }, - "app_lock": { - "name": "ล็อคแอพ", - "description": "ป้องกันการเข้าถึง Snapchat โดยไม่ต้องใช้รหัสผ่าน", - "properties": { - "lock_on_resume": { - "name": "ล็อคประวัติการทำงาน", - "description": "ล็อคแอปเมื่อเปิดขึ้นมาใหม่" - } - } - }, - "infinite_story_boost": { - "name": "เพิ่มเรื่องราวที่ไม่มีที่สิ้นสุด", - "description": "ข้ามความล่าช้าของขีดจำกัดการเพิ่มเรื่องราว" - }, - "meo_passcode_bypass": { - "name": "บายพาสรหัสผ่าน My Eyes Only", - "description": "ข้ามรหัสผ่าน My Eyes Only\nวิธีนี้จะใช้งานได้ก็ต่อเมื่อมีการป้อนรหัสผ่านอย่างถูกต้องก่อนหน้านี้" - }, - "no_friend_score_delay": { - "name": "ไม่มีความล่าช้าของคะแนนเพื่อน", - "description": "ลบความล่าช้าในการดูคะแนนเพื่อน" - }, - "best_friend_pinning": { - "name": "ปักหมุดเพื่อนที่ดีที่สุด", - "description": "ให้คุณปักหมุดเพื่อนเป็นเพื่อนที่ดีที่สุดอันดับหนึ่งของคุณ หมายเหตุ: มีเพียงคุณเท่านั้นที่สามารถเห็นเพื่อนสนิทที่คุณปักหมุดไว้" - }, - "e2ee": { - "name": "การเข้ารหัสจากต้นทางถึงปลายทาง", - "description": "เข้ารหัสข้อความของคุณด้วย AES โดยใช้รหัสลับที่ใช้ร่วมกัน\nอย่าลืมเก็บกุญแจของคุณไว้ในที่ปลอดภัย!", - "properties": { - "encrypted_message_indicator": { - "name": "ตัวบ่งชี้ข้อความที่เข้ารหัส", - "description": "เพิ่ม 🔒 อีโมจิ ถัดจากข้อความที่เข้ารหัส" - }, - "force_message_encryption": { - "name": "บังคับให้เข้ารหัสข้อความ", - "description": "ป้องกันการส่งข้อความที่เข้ารหัสไปยังผู้ที่ไม่ได้เปิดใช้งานการเข้ารหัส E2E เมื่อเลือกการสนทนาหลายรายการเท่านั้น" - } - } - }, - "add_friend_source_spoof": { - "name": "เพิ่มแหล่งที่มาของเพื่อนปลอม", - "description": "ปลอมแปลงแหล่งที่มาของคำขอเป็นเพื่อน" - }, - "hidden_snapchat_plus_features": { - "name": "คุณสมบัติ Snapchat Plus ที่ซ่อนอยู่", - "description": "เปิดใช้งานฟีเจอร์ Snapchat Plus ที่ยังไม่เผยแพร่/เบต้า\nอาจใช้ไม่ได้กับ Snapchat เวอร์ชันเก่า" - }, - "custom_streaks_expiration_format": { - "name": "รูปแบบการหมดอายุของ Streaks แบบกำหนดเอง", - "description": "ปรับแต่งรูปแบบการหมดอายุของ Streaks\n\nตัวแปรที่มีอยู่:\n - %c: จำนวนลายเส้น\n - %e: อิโมจินาฬิกาทราย\n - %d: วัน\n - %h: ชั่วโมง\n - %m: นาที\n - %s: วินาที\n - %w: เวลาที่เหลืออยู่" - }, - "prevent_forced_logout": { - "name": "ป้องกันการบังคับให้ออกจากระบบ", - "description": "ป้องกันไม่ให้ Snapchat ออกจากระบบเมื่อคุณเข้าสู่ระบบบนอุปกรณ์อื่น" - }, - "snapscore_changes": { - "name": "การเปลี่ยนแปลงสแนปสกอร์", - "description": "ติดตามการเปลี่ยนแปลงใน Snapscore ของเพื่อน\nใช้ฟีเจอร์นี้ใน Snapchat เวอร์ชันใหม่เท่านั้น" - } - } - }, - "scripting": { - "name": "การเขียนสคริปต์", - "description": "เรียกใช้สคริปต์แบบกำหนดเองเพื่อขยาย PurrfectSnap", - "properties": { - "developer_mode": { - "name": "โหมดนักพัฒนาซอฟต์แวร์", - "description": "แสดงข้อมูลการแก้ไขข้อบกพร่องบน UI ของ Snapchat" - }, - "module_folder": { - "name": "โฟลเดอร์โมดูล", - "description": "โฟลเดอร์ที่มีสคริปต์อยู่" - }, - "auto_reload": { - "name": "โหลดซ้ำอัตโนมัติ", - "description": "โหลดสคริปต์ซ้ำโดยอัตโนมัติเมื่อมีการเปลี่ยนแปลง" - }, - "integrated_ui": { - "name": "UI แบบรวม", - "description": "อนุญาตให้สคริปต์เพิ่มองค์ประกอบ UI ที่กำหนดเองลงใน Snapchat" - }, - "disable_log_anonymization": { - "name": "ปิดใช้งานการลบข้อมูลระบุตัวตนของบันทึก", - "description": "ปิดใช้งานการไม่ระบุชื่อบันทึก" - }, - "disable_optimization": { - "name": "ปิดการใช้งานการเพิ่มประสิทธิภาพ", - "description": "ปิดใช้งานการปรับสคริปต์ให้เหมาะสม นี่อาจทำให้เกิดปัญหาด้านประสิทธิภาพการทำงาน" - } - } - }, - "friend_tracker": { - "name": "ติดตามเพื่อน", - "description": "บันทึกกิจกรรมของเพื่อนใน Snapchat", - "properties": { - "record_messaging_events": { - "name": "บันทึกเหตุการณ์การส่งข้อความ", - "description": "บันทึกเหตุการณ์การส่งข้อความ เช่น การเปิดสแน็ป การอ่านข้อความ ฯลฯ" - }, - "allow_running_in_background": { - "name": "อนุญาตให้ทำงานในพื้นหลัง", - "description": "อนุญาตให้ตัวติดตามทำงานในพื้นหลัง หมายเหตุ: การดำเนินการนี้จะทำให้แบตเตอรี่ของคุณหมดลงอย่างมาก" - }, - "auto_purge": { - "name": "ล้างอัตโนมัติ", - "description": "ลบเหตุการณ์แคชที่เก่ากว่าระยะเวลาที่ระบุโดยอัตโนมัติ" - } - } - } - }, - "options": { - "app_appearance": { - "always_light": "สว่างเสมอ", - "always_dark": "มืดมนเสมอ" - }, - "friend_feed_menu_buttons": { - "auto_download": "⬇️ ดาวน์โหลดอัตโนมัติ", - "auto_save": "💌 บันทึกข้อความอัตโนมัติ", - "unsaveable_messages": "⬇️ ข้อความที่ไม่สามารถบันทึกได้", - "auto_open_snaps": "📷 เปิดสแนปอัตโนมัติ", - "stealth": "🎃 โหมดซ่อนตัว", - "mark_snaps_as_seen": "👀 ทำเครื่องหมาย Snaps ตามที่เห็น", - "mark_stories_as_seen_locally": "👀 ทำเครื่องหมายเรื่องราวตามที่เห็นในพื้นที่", - "conversation_info": "👤 ข้อมูลการสนทนา", - "e2e_encryption": "🔒 ใช้การเข้ารหัส E2E" - }, - "path_format": { - "create_author_folder": "สร้างโฟลเดอร์สำหรับผู้เขียนแต่ละคน", - "create_source_folder": "สร้างโฟลเดอร์สำหรับแหล่งสื่อแต่ละประเภท", - "append_hash": "เพิ่มแฮชที่ไม่ซ้ำให้กับชื่อไฟล์", - "append_source": "เพิ่มแหล่งสื่อลงในชื่อไฟล์", - "append_username": "เพิ่มชื่อผู้ใช้ให้กับชื่อไฟล์", - "append_date_time": "เพิ่มวันที่และเวลาให้กับชื่อไฟล์" - }, - "auto_download_sources": { - "friend_snaps": "สแนปเพื่อน", - "friend_stories": "เรื่องราวของเพื่อน", - "public_stories": "เรื่องสาธารณะ", - "spotlight": "สปอตไลท์" - }, - "logging": { - "started": "เริ่ม", - "success": "ความสำเร็จ", - "progress": "ความคืบหน้า", - "failure": "ความล้มเหลว" - }, - "notifications": { - "chat_screenshot": "ภาพหน้าจอ", - "chat_screen_record": "บันทึกหน้าจอ", - "snap_replay": "สแน็ปเล่นซ้ำ", - "camera_roll_save": "บันทึกม้วนฟิล์ม", - "chat": "แชท", - "chat_reply": "ตอบแชท", - "snap": "สแน็ป", - "typing": "กำลังพิมพ์", - "stories": "เรื่องราว", - "speaking": "การพูด", - "chat_reaction": "ปฏิกิริยา DM", - "group_chat_reaction": "ปฏิกิริยาของกลุ่ม", - "initiate_audio": "สายเรียกเข้าด้วยเสียง", - "abandon_audio": "ไม่ได้รับสายสนทนา", - "initiate_video": "สายวิดีโอขาเข้า", - "abandon_video": "ไม่ได้รับสายวิดีโอ", - "map_live_location": "แผนที่ตำแหน่งสด" - }, - "gallery_media_send_override": { - "always_ask": "ถามเสมอ", - "ORIGINAL": "สื่อต้นฉบับ", - "NOTE": "หมายเหตุเสียง", - "SNAP": "สแน็ป", - "SAVEABLE_SNAP": "Snap ที่บันทึกได้" - }, - "strip_media_metadata": { - "hide_caption_text": "ซ่อนข้อความคำบรรยาย", - "hide_snap_filters": "ซ่อนตัวกรอง Snap", - "hide_extras": "ซ่อนสิ่งพิเศษ (เช่น การกล่าวถึง)", - "remove_audio_note_duration": "ลบระยะเวลาบันทึกเสียง", - "remove_audio_note_transcript_capability": "ลบความสามารถในการถอดเสียงบันทึกย่อ" - }, - "hide_ui_components": { - "hide_profile_call_buttons": "ลบปุ่มโทรโปรไฟล์", - "hide_chat_call_buttons": "ลบปุ่มโทรแชท", - "hide_live_location_share_button": "ลบปุ่มแชร์ตำแหน่งสด", - "hide_stickers_button": "ปุ่มลบสติ๊กเกอร์", - "hide_voice_record_button": "ลบปุ่มบันทึกเสียง", - "hide_unread_chat_hint": "ลบคำแนะนำการแชทที่ยังไม่ได้อ่าน", - "hide_post_to_story_buttons": "ลบปุ่มโพสต์ไปที่เรื่องราวก่อนที่จะส่ง Snap", - "hide_billboard_prompt": "ลบ Billboard Prompt ในฟีดเพื่อน", - "hide_snapchat_plus_gift_reminders": "ลบการแจ้งเตือนของขวัญ Snapchat Plus ในการสนทนา", - "hide_map_reactions": "ลบปฏิกิริยาของแผนที่" - }, - "hide_story_suggestions": { - "hide_suggested_friend_stories": "ซ่อนเรื่องราวของเพื่อนที่แนะนำ", - "hide_my_stories": "ซ่อนเรื่องราวของฉัน" - }, - "home_tab": { - "map": "แผนที่", - "chat": "แชท", - "camera": "กล้อง", - "discover": "ค้นพบ", - "spotlight": "สปอตไลท์" - }, - "add_friend_source_spoof": { - "added_by_username": "โดยชื่อผู้ใช้", - "added_by_mention": "โดยการกล่าวถึง", - "added_by_group_chat": "โดยการแชทเป็นกลุ่ม", - "added_by_qr_code": "โดยคิวอาร์โค้ด", - "added_by_community": "โดยชุมชน", - "added_by_quick_add": "โดย Quick Add (มีความเสี่ยงสูงที่จะถูกแบน)" - }, - "bypass_video_length_restriction": { - "single": "สื่อเดี่ยว", - "split": "แยกสื่อ" - }, - "old_bitmoji_selfie": { - "2d": "บิตโมจิ 2 มิติ", - "3d": "3D บิตโมจิ" - }, - "disable_confirmation_dialogs": { - "erase_message": "ลบข้อความ", - "remove_friend": "ลบเพื่อน", - "block_friend": "บล็อกเพื่อน", - "ignore_friend": "ไม่สนใจเพื่อน", - "hide_friend": "ซ่อนเพื่อน", - "hide_conversation": "ซ่อนการสนทนา", - "clear_conversation": "ล้างการสนทนาจากฟีดเพื่อน" - }, - "auto_reload": { - "snapchat_only": "สแนปแชทเท่านั้น", - "all": "ทั้งหมด (Snapchat + PurrfectSnap)" - }, - "edit_text_override": { - "multi_line_chat_input": "อินพุตแชทหลายสาย", - "bypass_text_input_limit": "ข้ามขีดจำกัดการป้อนข้อความ" - }, - "auto_purge": { - "never": "ไม่เคย", - "1_hour": "1 ชม", - "3_hours": "3 ชั่วโมง", - "6_hours": "6 ชั่วโมง", - "12_hours": "12 ชม", - "1_day": "1 วัน", - "3_days": "3 วัน", - "1_week": "1 สัปดาห์", - "2_weeks": "2 สัปดาห์", - "1_month": "1 เดือน", - "3_months": "3 เดือน", - "6_months": "6 เดือน" - }, - "disable_story_sections": { - "friends": "เพื่อน", - "suggested_stories": "เรื่องแนะนำ", - "following": "กำลังติดตาม", - "discover": "ค้นพบ" - }, - "disable_cameras": { - "front": "กล้องหน้า", - "back": "กล้องหลัง" - }, - "disable_permission_requests": { - "notifications": "การแจ้งเตือน", - "read_media_images": "อ่านภาพสื่อ", - "read_media_video": "อ่านสื่อวิดีโอ", - "camera": "กล้อง", - "microphone": "ไมโครโฟน", - "location": "ที่ตั้ง", - "read_contacts": "อ่านรายชื่อติดต่อ", - "nearby_devices": "อุปกรณ์ใกล้เคียง", - "phone_calls": "โทรศัพท์" - }, - "message_indicators": { - "encryption_indicator": "เพิ่มไอคอน 🔒 ถัดจากข้อความที่ส่งถึงคุณเท่านั้น", - "platform_indicator": "เพิ่มไอคอนแพลตฟอร์มที่ใช้ส่งสื่อ (เช่น Android, iOS, เว็บ)", - "location_indicator": "เพิ่มไอคอน 📍 เพื่อสแน็ปเมื่อถูกส่งโดยเปิดใช้งานตำแหน่ง", - "ovf_editor_indicator": "ระบุว่าสแนปถูกส่งโดยใช้ OVF Editor หรือไม่", - "director_mode_indicator": "เพิ่มไอคอน ✏️ เพื่อสแน็ปเมื่อถูกส่งโดยใช้โหมดผู้กำกับ ซึ่งสามารถใช้เพื่อส่งภาพแกลเลอรี่เป็นสแนป" - }, - "auto_mark_as_read": { - "conversation_read": "ทำเครื่องหมายการสนทนาว่าอ่านแล้วเมื่อส่งข้อความ", - "snap_reply": "ทำเครื่องหมายว่าอ่านแล้วเมื่อตอบกลับ", - "save_snap_in_chat": "ทำเครื่องหมายว่าอ่านแล้วเมื่อบันทึกลงในแชทขณะอยู่ในโหมดซ่อนตัว" - }, - "friend_mutation_notifier": { - "remove_friend": "แจ้งเตือนเมื่อมีคนลบคุณออกจากการเป็นเพื่อน", - "birthday_changes": "แจ้งเตือนเมื่อมีคนเปลี่ยนวันเกิด", - "bitmoji_selfie_changes": "แจ้งเตือนเมื่อมีคนเปลี่ยน Bitmoji เซลฟีของตน", - "bitmoji_avatar_changes": "แจ้งเตือนเมื่อมีคนเปลี่ยนอวาตาร์ Bitmoji", - "bitmoji_background_changes": "แจ้งเตือนเมื่อมีคนเปลี่ยนพื้นหลัง Bitmoji", - "bitmoji_scene_changes": "แจ้งเตือนเมื่อมีคนเปลี่ยนฉาก Bitmoji" - }, - "snapchat_plus": { - "not_subscribed": "ไม่ได้สมัครสมาชิก", - "basic": "ขั้นพื้นฐาน", - "ad_free": "โฆษณาฟรี" - }, - "double_tap_chat_action": { - "like_message": "ชอบข้อความ", - "copy_text": "คัดลอกข้อความไปยังคลิปบอร์ด", - "delete_message": "ลบข้อความ", - "mark_as_read": "ทำเครื่องหมายว่าอ่านแล้ว", - "custom_emoji_reaction": "ปฏิกิริยาอีโมจิแบบกำหนดเอง" - }, - "startup_default_camera": { - "front": "กล้องหน้า", - "back": "กล้องหลัง" - } - } - }, - "friend_menu_option": { - "mark_snaps_as_seen": "ทำเครื่องหมาย Snaps ตามที่เห็น", - "mark_stories_as_seen_locally": "ทำเครื่องหมายเรื่องราวตามที่เห็นในท้องถิ่น", - "preview": "ดูตัวอย่าง", - "stealth_mode": "โหมดซ่อนตัว", - "auto_download_blacklist": "ดาวน์โหลดบัญชีดำอัตโนมัติ", - "anti_auto_save": "ป้องกันการบันทึกอัตโนมัติ" - }, - "content_type": { - "CHAT": "แชท", - "SNAP": "สแน็ป", - "EXTERNAL_MEDIA": "สื่อภายนอก", - "NOTE": "หมายเหตุเสียง", - "STICKER": "สติ๊กเกอร์", - "SHARE": "แบ่งปัน", - "STATUS": "สถานะ", - "LOCATION": "ที่ตั้ง", - "STATUS_SAVE_TO_CAMERA_ROLL": "บันทึกลงในม้วนฟิล์มแล้ว", - "STATUS_CONVERSATION_CAPTURE_SCREENSHOT": "ภาพหน้าจอ", - "STATUS_CONVERSATION_CAPTURE_RECORD": "บันทึกหน้าจอ", - "STATUS_CALL_MISSED_VIDEO": "ไม่ได้รับสายวิดีโอ", - "STATUS_CALL_MISSED_AUDIO": "ไม่ได้รับสายสนทนา", - "LIVE_LOCATION_SHARE": "แบ่งปันตำแหน่งสด", - "CREATIVE_TOOL_ITEM": "รายการเครื่องมือสร้างสรรค์", - "FAMILY_CENTER_INVITE": "เชิญศูนย์ครอบครัว", - "FAMILY_CENTER_ACCEPT": "ศูนย์ครอบครัวยอมรับ", - "FAMILY_CENTER_LEAVE": "ลาศูนย์ครอบครัว", - "STATUS_PLUS_GIFT": "ของขวัญสถานะพลัส", - "TINY_SNAP": "สแนปเล็กๆ", - "STATUS_COUNTDOWN": "นับถอยหลัง", - "MAP_REACTION": "ปฏิกิริยาแผนที่" - }, - "media_download_source": { - "none": "ไม่มี", - "pending": "รอดำเนินการ", - "chat_media": "สื่อสนทนา", - "story": "เรื่องราว", - "public_story": "เรื่องราวสาธารณะ", - "spotlight": "สปอตไลท์", - "profile_picture": "รูปโปรไฟล์", - "story_logger": "เครื่องบันทึกเรื่องราว", - "message_logger": "เครื่องบันทึกข้อความ", - "merged": "รวมแล้ว", - "voice_call": "โทรด้วยเสียง" - }, - "chat_action_menu": { - "preview_button": "ดูตัวอย่าง", - "download_button": "ดาวน์โหลด", - "delete_logged_message_button": "ลบข้อความที่บันทึกไว้", - "show_chat_edit_history": "แสดงประวัติการแก้ไขแชท", - "convert_message": "แปลงข้อความ" - }, - "opera_context_menu": { - "download": "ดาวน์โหลดสื่อ", - "sent_at": "ส่งที่ {date}", - "created_at": "สร้างที่ {date}", - "expires_at": "หมดอายุที่ {date}", - "media_size": "ขนาดสื่อ: {size}", - "media_duration": "ระยะเวลาสื่อ: {duration} ms", - "show_debug_info": "แสดงข้อมูลการแก้ไขข้อบกพร่อง" - }, - "modal_option": { - "profile_info": "ข้อมูลโปรไฟล์", - "close": "ปิด" - }, - "gallery_media_send_override": { - "multiple_media_toast": "คุณสามารถส่งสื่อได้ครั้งละหนึ่งรายการเท่านั้น" - }, - "mark_as_seen": { - "no_unseen_snaps_toast": "ไม่พบ Snaps ที่มองไม่เห็น!", - "seen_toast": "ทำเครื่องหมายว่าเห็นแล้ว!", - "unseen_toast": "ทำเครื่องหมายว่ามองไม่เห็น!", - "already_seen_toast": "ทำเครื่องหมายว่าเห็นแล้ว!", - "already_unseen_toast": "ทำเครื่องหมายว่าไม่เห็นแล้ว!" - }, - "conversation_preview": { - "streak_expiration": "หมดอายุใน {day} วัน {hour} ชั่วโมง {minute} นาที", - "total_messages": "ข้อความที่ส่ง/รับทั้งหมด: {count}", - "title": "ดูตัวอย่าง", - "unknown_user": "ผู้ใช้ที่ไม่รู้จัก", - "no_messages": "ไม่พบข้อความ!" - }, - "profile_info": { - "title": "ข้อมูลโปรไฟล์", - "first_created_username": "ชื่อผู้ใช้ที่สร้างขึ้นครั้งแรก", - "mutable_username": "ชื่อผู้ใช้ที่ไม่แน่นอน", - "display_name": "ชื่อที่แสดง", - "added_date": "เพิ่มวันที่", - "birthday": "วันเกิด : {month} {day}", - "hidden_birthday": "วันเกิด : ซ่อนเร้น", - "friendship": "มิตรภาพ", - "add_source": "เพิ่มแหล่งที่มา", - "snapchat_plus": "สแนปแชต พลัส", - "snapchat_plus_state": { - "subscribed": "สมัครสมาชิกแล้ว", - "not_subscribed": "ไม่ได้สมัครสมาชิก" - } - }, - "friendship_link_type": { - "mutual": "ซึ่งกันและกัน", - "outgoing": "ขาออก", - "blocked": "ถูกบล็อก", - "deleted": "ลบแล้ว", - "following": "กำลังติดตาม", - "suggested": "แนะนำ", - "incoming": "เข้ามา", - "incoming_follower": "ผู้ติดตามที่เข้ามา" - }, - "bulk_messaging_action": { - "choose_action_title": "เลือกการกระทำ", - "progress_status": "กำลังประมวลผล {index} จาก {total}", - "selection_dialog_continue_button": "ดำเนินการต่อ", - "confirmation_dialog": { - "title": "คุณแน่ใจเหรอ?", - "message": "สิ่งนี้จะส่งผลต่อเพื่อนที่เลือกทั้งหมด การดำเนินการนี้ไม่สามารถยกเลิกได้" - }, - "actions": { - "remove_friends": "ลบเพื่อน", - "clear_conversations": "ล้างการสนทนา" - } - }, - "chat_export": { - "exporter_dialog": { - "select_conversations_title": "เลือกการสนทนา", - "text_field_selection": "{amount} เลือกแล้ว", - "text_field_selection_all": "ทั้งหมด", - "export_file_format_title": "รูปแบบไฟล์ส่งออก", - "message_type_filter_title": "กรองข้อความตามประเภท", - "amount_of_messages_title": "จำนวนข้อความ (เว้นว่างไว้สำหรับทั้งหมด)", - "download_medias_title": "ดาวน์โหลดมีเดีย" - }, - "dialog_negative_button": "ยกเลิก", - "dialog_positive_button": "ส่งออก", - "exported_to": "ส่งออกไปยัง {path}", - "exporting_chats": "กำลังส่งออกแชท...", - "processing_chats": "กำลังประมวลผล {amount} การสนทนา...", - "export_fail": "ไม่สามารถส่งออกการสนทนา {conversation}", - "writing_output": "กำลังเขียนเอาต์พุต...", - "finished": "เสร็จแล้ว! ตอนนี้คุณสามารถปิดกล่องโต้ตอบนี้ได้แล้ว", - "no_messages_found": "ไม่พบข้อความ!", - "exporting_message": "กำลังส่งออก {conversation}..." - }, - "button": { - "ok": "ตกลง", - "positive": "ใช่", - "negative": "เลขที่", - "cancel": "ยกเลิก", - "open": "เปิด", - "download": "ดาวน์โหลด", - "send": "ส่ง", - "restore_original": "คืนค่าต้นฉบับ", - "convert_external_media": "แปลงสื่อภายนอก", - "save": "บันทึก" - }, - "tracker_events": { - "conversation_enter": "เข้าสู่การสนทนา", - "conversation_exit": "ออกจากการสนทนา", - "started_typing": "เริ่มพิมพ์", - "stopped_typing": "หยุดพิมพ์แล้ว", - "started_speaking": "เริ่มพูด", - "stopped_speaking": "หยุดพูดแล้ว", - "started_peeking": "เริ่มแอบดู", - "stopped_peeking": "หยุดการแอบดู", - "message_read": "อ่านข้อความ", - "message_deleted": "ลบข้อความแล้ว", - "message_saved": "บันทึกข้อความแล้ว", - "message_unsaved": "ข้อความที่ไม่ได้บันทึก", - "message_edited": "แก้ไขข้อความแล้ว", - "message_reaction_add": "เพิ่มการโต้ตอบข้อความ", - "message_reaction_remove": "ลบปฏิกิริยาโต้ตอบข้อความ", - "snap_opened": "เปิดสแนปแล้ว", - "snap_replayed": "Snap เล่นซ้ำ", - "snap_replayed_twice": "Snap เล่นซ้ำสองครั้ง", - "snap_screenshot": "สแนปภาพหน้าจอ", - "snap_screen_record": "บันทึกหน้าจอ Snap" - }, - "tracker_actions": { - "log": "บันทึก", - "in_app_notification": "การแจ้งเตือนในแอป", - "push_notification": "การแจ้งเตือนแบบพุช", - "custom": "กำหนดเอง" - }, - "better_notifications": { - "button": { - "reply": "ตอบ", - "download": "ดาวน์โหลด", - "mark_as_read": "ทำเครื่องหมายว่าอ่านแล้ว" - } - }, - "profile_picture_downloader": { - "button": "ดาวน์โหลดรูปโปรไฟล์", - "title": "เครื่องมือดาวน์โหลดรูปภาพโปรไฟล์", - "avatar_option": "อวตาร", - "background_option": "พื้นหลัง" - }, - "call_start_confirmation": { - "dialog_title": "เริ่มการโทร", - "dialog_message": "คุณแน่ใจหรือไม่ว่าต้องการเริ่มการโทร?" - }, - "half_swipe_notifier": { - "notification_channel_name": "ปัดครึ่ง", - "notification_content_dm": "{friend} เพียงปัดนิ้วครึ่งเข้าไปในแชทของคุณเป็นเวลา {duration} วินาที", - "notification_content_group": "{friend} เพียงปัดครึ่งลงใน {group} เป็นเวลา {duration} วินาที" - }, - "download_processor": { - "attachment_type": { - "snap": "สแน็ป", - "sticker": "สติ๊กเกอร์", - "gif": "กิฟ", - "external_media": "สื่อภายนอก", - "note": "บันทึก", - "original_story": "เรื่องราวดั้งเดิม" - }, - "select_attachments_title": "เลือกไฟล์แนบ", - "download_started_toast": "เริ่มดาวน์โหลดแล้ว", - "unsupported_content_type_toast": "ประเภทเนื้อหาที่ไม่รองรับ!", - "failed_no_longer_available_toast": "สื่อไม่มีอีกต่อไป", - "no_attachments_toast": "ไม่พบเอกสารแนบ!", - "already_queued_toast": "สื่อเข้าคิวแล้ว!", - "already_downloaded_toast": "ดาวน์โหลดสื่อแล้ว!", - "content_saved_toast": "บันทึกแล้ว!", - "download_toast": "กำลังดาวน์โหลด {path}...", - "processing_toast": "กำลังประมวลผล {path}...", - "failed_generic_toast": "ดาวน์โหลดไม่สำเร็จ", - "failed_to_create_preview_toast": "ไม่สามารถสร้างการแสดงตัวอย่างได้", - "failed_processing_toast": "การประมวลผลล้มเหลว {error}", - "failed_gallery_toast": "ไม่สามารถบันทึกลงในแกลเลอรี {error}", - "dash_no_chapter": "ไม่พบบท", - "dash_dialog": { - "title": "ดาวน์โหลดสื่อประ", - "download_all": "ดาวน์โหลดทั้งหมด", - "segment_text": "ส่วน {from} - {to}" - } - }, - "streaks_reminder": { - "notification_title": "มีลายทาง", - "notification_text": "คุณจะสูญเสียสตรีคของคุณด้วย {friend} ใน {hoursLeft} ชั่วโมง" - }, - "biometric_auth": { - "unlock_button": "ปลดล็อค", - "title": "ปลดล็อคสแนปแชท", - "subtitle": "โปรดตรวจสอบสิทธิ์เพื่อปลดล็อค Snapchat" - }, - "end_to_end_encryption": { - "toolbox": { - "no_shared_key": "คุณยังไม่มีความลับที่เปิดเผยกับเพื่อนคนนี้ คลิกด้านล่างเพื่อเริ่มต้นใหม่", - "shared_key_fingerprint": "ลายนิ้วมือของคุณคือ:\n\n__ตัวยึดตำแหน่ง__0__\n\nอย่าลืมตรวจสอบว่าตรงกับลายนิ้วมือของเพื่อนของคุณหรือไม่!", - "initiate_exchange_button": "เริ่มต้นการแลกเปลี่ยนคีย์" - }, - "confirmation_dialogs": { - "title": "การเข้ารหัสจากต้นทางถึงปลายทาง", - "confirmation_1": "คำเตือน: การดำเนินการนี้จะเขียนทับคีย์ที่มีอยู่ของคุณ คุณจะสูญเสียการเข้าถึงข้อความที่เข้ารหัสทั้งหมดจากเพื่อนคนนี้ คุณแน่ใจหรือไม่ว่าต้องการดำเนินการต่อ?", - "confirmation_2": "คุณแน่ใจจริงๆ ว่าต้องการดำเนินการต่อหรือไม่ นี่เป็นโอกาสสุดท้ายของคุณที่จะถอยกลับ" - }, - "unencrypted_conversation_send_failure_toast": "คุณไม่สามารถส่งเนื้อหาที่เข้ารหัสไปยังการสนทนาทั้งที่เข้ารหัสและไม่ได้เข้ารหัสได้!", - "native_hooks_send_failure_toast": "ส่งไม่สำเร็จ! โปรดเปิดใช้งาน Native Hooks ในการตั้งค่า", - "no_participants_to_encrypt_toast": "คุณไม่มีเพื่อนในการสนทนานี้ที่จะเข้ารหัสข้อความด้วย!", - "encryption_failed_toast": "ล้มเหลวในการเข้ารหัสข้อความ! ตรวจสอบ logcat เพื่อดูรายละเอียดเพิ่มเติม", - "accept_public_key_success_toast": "ยอมรับรหัสสาธารณะสำเร็จแล้ว!", - "accept_secret_key_success_toast": "เสร็จแล้ว! ตอนนี้คุณสามารถส่งและรับข้อความที่เข้ารหัสกับเพื่อนคนนี้ได้แล้ว", - "accept_public_key_failure_toast": "ไม่สามารถยอมรับรหัสสาธารณะได้", - "accept_secret_key_failure_toast": "ไม่สามารถยอมรับรหัสลับได้", - "accept_secret_button": "ยอมรับความลับ", - "accept_public_key_button": "ยอมรับกุญแจสาธารณะ", - "outgoing_pk_message": "คำขอแลกเปลี่ยนกุญแจ", - "outgoing_secret_message": "การตอบสนองการแลกเปลี่ยนคีย์", - "incoming_pk_message": "คุณเพิ่งได้รับคำขอกุญแจสาธารณะ คลิกด้านล่างเพื่อยอมรับ", - "incoming_secret_message": "เพื่อนของคุณเพิ่งยอมรับกุญแจสาธารณะของคุณ คลิกด้านล่างเพื่อยอมรับความลับ" - }, - "auto_open_snaps": { - "title": "เปิด Snaps อัตโนมัติ", - "notification_content": "{count} เปิดสแนปแล้ว" - }, - "friend_mutation_observer": { - "notification_channel_name": "ผู้สังเกตการณ์การกลายพันธุ์ของเพื่อน", - "friend_removed": "{username} ลบคุณออกจากการเป็นเพื่อน", - "birthday_removed": "{username} ลบวันเกิดของพวกเขาแล้ว ({birthday})", - "birthday_added": "{username} ได้เพิ่มวันเกิดของพวกเขา ({birthday})", - "birthday_changed": "{username} ได้เปลี่ยนวันเกิดของพวกเขาจาก {oldBirthday} เป็น {newBirthday}", - "bitmoji_selfie_changed": "{username} ได้เปลี่ยนรูปเซลฟี่ Bitmoji ของพวกเขา", - "bitmoji_avatar_changed": "{username} ได้เปลี่ยนอวาตาร์ Bitmoji ของพวกเขา", - "bitmoji_background_changed": "{username} ได้เปลี่ยนพื้นหลัง Bitmoji แล้ว", - "bitmoji_scene_changed": "{username} ได้เปลี่ยนฉาก Bitmoji ของพวกเขา" - }, - "material3_strings": { - "date_range_picker_start_headline": "จาก", - "date_range_picker_end_headline": "ถึง", - "date_range_picker_title": "เลือกช่วงวันที่", - "date_picker_switch_to_calendar_mode": "ปฏิทิน", - "date_picker_switch_to_input_mode": "ป้อนข้อมูล", - "date_range_picker_scroll_to_previous_month": "เดือนที่แล้ว", - "date_range_picker_scroll_to_next_month": "เดือนหน้า", - "date_picker_today_description": "วันนี้", - "date_range_picker_day_in_range": "เลือกแล้ว", - "date_input_invalid_for_pattern": "วันที่ไม่ถูกต้อง", - "date_input_invalid_year_range": "ปีไม่ถูกต้อง", - "date_input_invalid_not_allowed": "วันที่ไม่ถูกต้อง", - "date_range_input_invalid_range_input": "ช่วงวันที่ไม่ถูกต้อง" - }, - "send_override_dialog": { - "title": "ส่งสื่อเป็น {type}", - "duration": "ระยะเวลา: {duration}", - "saveable_snap_hint": "ทำให้ Snap สามารถบันทึกได้ในแชท", - "unlimited_duration": "ไม่จำกัด" - }, - "invalid_input_toast": "ข้อมูลไม่ถูกต้อง! ตรวจสอบให้แน่ใจว่าคุณป้อนค่าที่ถูกต้อง" -} \ No newline at end of file diff --git a/common/src/main/assets/lang/tr_TR.json b/common/src/main/assets/lang/tr_TR.json new file mode 100644 index 00000000..c11656cf --- /dev/null +++ b/common/src/main/assets/lang/tr_TR.json @@ -0,0 +1,1658 @@ +{ + "setup": { + "dialogs": { + "select_language": "Dil Seçin", + "save_folder": "SnapEnhance, Snapchat'ten Medya indirmek ve Kaydetmek için Depolama izinleri gerektirir.\nLütfen medyanın indirileceği konumu seçin.", + "select_save_folder_button": "Klasör Seç" + }, + "mappings": { + "dialog": "Eşlemeler oluşturuluyor, bu biraz zaman alabilir ...", + "generate_failure_no_snapchat": "SnapEnhance Snapchat'i algılayamadı, lütfen Snapchat'i yeniden yüklemeyi deneyin.", + "generate_failure": "Eşlemeleri oluşturmaya çalışırken bir hata oluştu, lütfen tekrar deneyin." + }, + "permissions": { + "dialog": "Devam etmek için aşağıdaki gerekliliklere uymanız gerekir:", + "notification_access": "Bildirim Erişimi", + "battery_optimization": "Pil Optimizasyonu", + "display_over_other_apps": "Diğer Uygulamaların Üzerinde Göster", + "request_button": "İstek" + } + }, + "manager": { + "routes": { + "features": "Özellikler", + "home": "Ana Sayfa", + "home_settings": "Ayarlar", + "home_logs": "Kayıtlar", + "social": "Sosyal", + "scripts": "Scriptler", + "tasks": "Görevler", + "logger_history": "Kaydedici Geçmişi", + "logged_stories": "Kaydedilen Hikayeler", + "manage_scope": "Kapsamı Yönet", + "messaging_preview": "Önizleme", + "friend_tracker": "Arkadaş Takibi", + "edit_rule": "Kuralı Düzenle", + "file_imports": "Dosya İçe Aktarımları", + "better_location": "Daha İyi Konum", + "edit_theme": "Temayı Düzenle", + "manage_repos": "Depoları Yönet", + "theming": "Temalandırma", + "manage_rule_feature": "Kural Yönetme Özelliği" + }, + "sections": { + "features": { + "disabled": "Devre Dışı", + "export_option": "Dışa Aktar", + "import_option": "İçe Aktar", + "reset_option": "Sıfırla", + "config_import_success_toast": "Konfigürasyon başarıyla içe aktarıldı", + "config_import_failure_toast": "Konfigürasyon içe aktarılamadı {error}", + "saved_config_snackbar": "Konfigürasyon kaydedildi", + "config_export_success_toast": "Konfigürasyon başarıyla dışa aktarıldı", + "config_export_failure_toast": "Konfigürasyon dışa aktarılamadı {error}" + }, + "social": { + "streaks_expiration_short": "{hours} saat", + "friends_tab": "Arkadaşlar", + "empty_hint": "(boş)", + "groups_tab": "Gruplar" + }, + "tasks": { + "no_tasks": "Görev yok", + "remove_selected_tasks_title": "Seçili görevleri kaldırmak istediğinizden emin misiniz?", + "remove_all_tasks_title": "Tüm görevleri kaldırmak istediğinizden emin misiniz?", + "delete_files_option": "Ayrıca dosyaları sil", + "remove_selected_tasks_confirm": "{count} görev kaldırılsın mı?", + "merge_files_toast": "{count} dosya birleştiriliyor", + "remove_all_tasks_confirm": "Tüm görevler kaldırılsın mı?", + "failed_to_open_file": "Dosya açılamadı" + }, + "home": { + "update_title": "SnapEnhance Güncellemesi", + "update_button": "İndir", + "update_content": "Sürüm {version} kullanılabilir!", + "debug_build_summary_content": "Sürüm {versionName} ({versionCode})", + "quick_actions_title": "Hızlı Eylemler", + "version_title": "eternal tarafından - v{versionName}", + "debug_build_summary_title": "SnapEnhance'in bir hata ayıklama versiyonunu çalıştırıyorsunuz", + "debug_build_summary_date": "Oluşturma tarihi: {date} ({days} gün önce)" + }, + "home_logs": { + "clear_logs_button": "Günlükleri Temizle", + "no_logs_hint": "Mevcut günlük yok", + "export_logs_button": "Günlükleri Dışa Aktar", + "saving_logs_toast": "Günlükler kaydediliyor, bu biraz zaman alabilir ...", + "saved_logs_success_toast": "Günlükler başarıyla kaydedildi", + "saved_logs_failure_toast": "Günlükler kaydedilemedi" + }, + "home_settings": { + "actions_title": "Eylemler", + "message_logger_title": "Mesaj Kaydedici", + "debug_title": "Hata Ayıklama", + "success_toast": "Tamam!", + "message_logger_summary": "{messageCount} mesajlar\n{storyCount} hikayeler", + "export_button": "Dışa Aktar", + "clear_button": "Temizle", + "view_logger_history_button": "Günlük Geçmişini Görüntüle" + }, + "manage_scope": { + "logged_stories_button": "Kaydedilen Hikayeleri Göster", + "e2ee_title": "Uçtan Uca Şifreleme", + "rules_title": "Kurallar", + "not_found": "Bulunamadı", + "streaks_title": "Seriler", + "streaks_length_text": "Uzunluk: {length}", + "streaks_expiration_text": "{eta} içinde sona erecek", + "streaks_expiration_text_expired": "Süresi doldu", + "reminder_button": "Hatırlatıcı Ayarla", + "participants_text": "{sayı} katılımcı", + "delete_scope_confirm_dialog_title": "Bir {scope} silmek istediğinizden emin misiniz?" + }, + "logged_stories": { + "story_failed_to_load": "Yükleme başarısız oldu", + "no_stories": "Hikaye bulunamadı", + "save_from_cache_button": "Önbellekten Kaydet" + }, + "messaging_preview": { + "bridge_connection_failed": "Köprüye bağlanılamadı. Snapchat'in arka planda çalıştığından emin olun", + "message_fetch_failed": "Mesajlar alınamadı", + "save_all_option": "Tümünü Kaydet", + "unsave_selection_option": "Seçimi Kaydetmeyi Kaldır", + "unsave_all_option": "Tümünü Kaydet'i Kaldır", + "bridge_init_failed": "Mesajlaşma köprüsü başlatılamadı. Snapchat'in arka planda çalıştığından emin olun", + "no_message_hint": "Mesaj yok", + "save_selection_option": "Seçimi Kaydet", + "mark_selection_as_seen_option": "Seçilen Snap'i görüldü olarak işaretle", + "mark_all_as_seen_option": "Tüm Snap'leri görüldü olarak işaretle", + "delete_selection_option": "Seçimi Sil", + "delete_all_option": "Tümünü Sil" + }, + "logger_history": { + "list_friend_format": "Arkadaş {name}", + "list_group_format": "Grup {name}", + "no_more_messages": "Daha fazla mesaj yok", + "reverse_order_checkbox": "Ters Sıralama", + "chat_attachment": "Ek {index}", + "empty_message": "Boş Sohbet Mesajı", + "message_parse_failed": "Mesaj ayrıştırılamadı", + "unknown_sender": "Bilinmeyen Gönderen", + "download_attachment_failed_toast": "Ek indirilemedi" + }, + "file_imports": { + "import_file_button": "Dosya İçe Aktar", + "file_not_found": "Dosya bulunamadı", + "file_import_failed": "Dosya içe aktarılamadı: {error}", + "file_imported": "Dosya başarıyla içe aktarıldı", + "file_delete_failed": "Dosya silinemedi", + "no_files_hint": "Burada Snapchat'te kullanmak için dosyaları içe aktarabilirsiniz. Bir dosyayı içe aktarmak için aşağıdaki düğmeye basın." + }, + "better_location": { + "save_coordinates_dialog_title": "Koordinatları Kaydet", + "saved_name_dialog_hint": "İsim Kaydedildi", + "choose_location_button": "Konum Seçin", + "teleport_to_friend_button": "Arkadaşa Işınlan", + "no_saved_coordinates_hint": "Kayıtlı koordinat yok", + "delete_dialog_title": "Kayıtlı Koordinatı Sil", + "delete_dialog_message": "Bu kayıtlı koordinatı silmek istediğinizden emin misiniz?", + "teleport_to_friend_title": "Arkadaşa Işınlan", + "search_bar": "Ara", + "no_friends_map": "Haritada arkadaş yok", + "no_friends_found": "Arkadaş bulunamadı", + "save_dialog_button": "Kaydet", + "spoofed_coordinates_title": "{latitude} Enlem, {longitude} Boylam", + "spoof_location_toggle": "Sahte Konum", + "saved_coordinates_title": "Koordinatlar Kaydedildi", + "longitude_dialog_hint": "Boylam", + "latitude_dialog_hint": "Enlem", + "suspend_location_updates": "Konum Güncellemelerini Askıya Al" + }, + "theming": { + "no_themes_hint": "Tema bulunamadı" + }, + "manage_rule_feature": { + "disable_state_subtext": "Hiçbir arkadaş/grup etkilenmeyecektir", + "whitelist_state_option": "Kimse hariç ...", + "whitelist_state_subtext": "Bu kuraldan yalnızca {count} arkadaş/grup etkilenecektir", + "whitelist_state_button": "İzin verilen arkadaşları/grupları seçin", + "blacklist_state_option": "Herkes hariç...", + "blacklist_state_subtext": "Bu kuraldan {count} arkadaş/grup dışındaki herkes etkilenecektir", + "blacklist_state_button": "Hariç tutulan arkadaşları/grupları seçin", + "clear_list_button": "Arkadaş/grup listesini temizle", + "dialog_clear_confirmation_text": "Listeyi temizlemek istediğinizden emin misiniz?", + "disable_state_option": "Devre dışı" + } + }, + "dialogs": { + "add_friend": { + "title": "Arkadaş veya Grup Ekle", + "search_hint": "Ara", + "fetch_error": "Veri alınamadı", + "category_groups": "Gruplar", + "category_friends": "Arkadaşlar" + }, + "scripting_warning": { + "content": "SnapEnhance, cihazınızda kullanıcı tanımlı kodun yürütülmesine izin veren bir komut dosyası aracı içerir. Çok dikkatli olun ve modülleri yalnızca bilinen, güvenilir kaynaklardan yükleyin. Yetkisiz veya doğrulanmamış modüller sisteminiz için güvenlik riskleri oluşturabilir.", + "title": "Uyarı" + }, + "reset_config": { + "title": "Konfigürasyonu sıfırla", + "content": "Konfigürasyonu sıfırlamak istediğinizden emin misiniz?", + "success_toast": "Konfigürasyon başarıyla sıfırlandı" + }, + "messaging_action": { + "title": "İşlenecek içerik türlerini seçin", + "select_all_button": "Tümünü Seç" + }, + "file_imports": { + "no_files_settings_hint": "Dosya bulunamadı. Dosya İçe Aktarma bölümünde gerekli dosyaları içe aktardığınızdan emin olun", + "settings_select_file_hint": "İçe aktarılan bir dosya seçin" + }, + "export_config": { + "title": "Hassas Verileri Dışa Aktar?", + "content": "Konfigürasyonu hassas verilerle dışa aktarmak istiyor musunuz? (Konum koordinatları vb. gibi)" + } + } + }, + "rules": { + "modes": { + "blacklist": "Kara liste modu", + "whitelist": "Beyaz liste modu" + }, + "properties": { + "auto_download": { + "name": "Otomatik İndirme", + "description": "Snap'leri görüntülerken otomatik olarak indir", + "options": { + "blacklist": "Otomatik İndirmelerden Hariç Tut", + "whitelist": "Otomatik İndirme" + } + }, + "stealth": { + "name": "Gizli Mod", + "description": "Herhangi birinin Snap'lerini/Sohbetlerini ve konuşmalarını açtığınızı bilmesini engeller", + "options": { + "blacklist": "Gizli Moddan Hariç Tut", + "whitelist": "Gizli mod" + } + }, + "auto_save": { + "name": "Otomatik Kaydet", + "description": "Sohbet mesajlarını görüntülerken kaydeder", + "options": { + "blacklist": "Otomatik kaydetmelerden hariç tut", + "whitelist": "Otomatik kaydetme" + } + }, + "hide_friend_feed": { + "name": "Arkadaş Akışından Gizle" + }, + "e2e_encryption": { + "name": "E2E Şifreleme Kullanın" + }, + "pin_conversation": { + "name": "Konuşmayı Sabitle" + }, + "unsaveable_messages": { + "name": "Kaydedilemeyen Mesajlar", + "options": { + "blacklist": "Kaydedilemeyen Mesajlardan Hariç Tut", + "whitelist": "Kaydedilemeyen Mesajlar" + }, + "description": "Mesajların diğer kişiler tarafından sohbete kaydedilmesini önler" + }, + "auto_open_snaps": { + "description": "Snap'leri alırken otomatik olarak açar", + "options": { + "whitelist": "Snap'leri Otomatik Aç", + "blacklist": "Otomatik Açılan Snap'lerden Hariç Tut" + }, + "name": "Snap'leri Otomatik Aç" + } + }, + "toasts": { + "enabled": "{ruleName} etkin", + "disabled": "{ruleName} devre dışı" + } + }, + "features": { + "notices": { + "unstable": "⚠ Stabil Değil", + "ban_risk": "⚠ Bu özellik banlanmanıza neden olabilir", + "internal_behavior": "⚠ Bu Snapchat'in dahili davranışını bozabilir" + }, + "properties": { + "downloader": { + "name": "İndirici", + "description": "Snapchat Media'yı İndirin", + "properties": { + "save_folder": { + "name": "Kayıt Klasörü", + "description": "Tüm medyanın indirileceği dizini seçin" + }, + "auto_download_sources": { + "name": "Otomatik İndirme Kaynakları", + "description": "Otomatik olarak indirilecek kaynakları seçin" + }, + "prevent_self_auto_download": { + "name": "Kendi Kendine Otomatik İndirmeyi Önle", + "description": "Kendi Snap'lerinizin otomatik olarak indirilmesini önler" + }, + "path_format": { + "name": "Yol Formatı", + "description": "Dosya Yolu Formatını Belirleme" + }, + "allow_duplicate": { + "name": "Yinelenmesine İzin Ver", + "description": "Aynı medyanın birden çok kez indirilebilmesini sağlar" + }, + "merge_overlays": { + "name": "Kaplamaları Birleştirme", + "description": "Bir Snap'in Metnini ve ortamını tek bir dosyada birleştirir" + }, + "force_image_format": { + "name": "Görüntü Formatını Zorla", + "description": "Görüntülerin belirli bir Formatta kaydedilmesini zorlar" + }, + "force_voice_note_format": { + "name": "Ses Biçimini Zorla", + "description": "Sesli Notların belirli bir Formatta kaydedilmesini zorlar" + }, + "download_profile_pictures": { + "name": "Profil Resimlerini İndir", + "description": "Profil Resimlerini profil sayfasından indirmenize olanak sağlar" + }, + "ffmpeg_options": { + "name": "FFmpeg Ayarları", + "description": "Ek FFmpeg seçeneklerini belirleyin", + "properties": { + "threads": { + "name": "İş Parçacıkları", + "description": "Kullanılacak iş parçacığı miktarı" + }, + "preset": { + "name": "Ön Ayar", + "description": "Dönüştürme hızını ayarlayın" + }, + "constant_rate_factor": { + "name": "Sabit Hız Faktörü", + "description": "Video kodlayıcı için sabit hız faktörünü ayarlayın\nlibx264 için 0 ile 51 arasında" + }, + "video_bitrate": { + "name": "Video Bit Hızı", + "description": "Video bit hızını ayarlayın (kbps)" + }, + "audio_bitrate": { + "name": "Ses Bit Hızı", + "description": "Ses bit hızını ayarlayın (kbps)" + }, + "custom_video_codec": { + "name": "Özel Video Codec'i", + "description": "Özel bir Video Codec'i ayarlayın (örn. libx264)" + }, + "custom_audio_codec": { + "name": "Özel Ses Codec'i", + "description": "Özel bir Ses Codec'i ayarlayın (örn. AAC)" + } + } + }, + "logging": { + "name": "Günlük Kaydı", + "description": "Medya indirilirken tost mesajlarını gösterir" + }, + "custom_path_format": { + "description": "İndirilen medya için özel bir yol biçimi belirtin\n\nKullanılabilir değişkenler:\n - %username%\n - %source%\n - %hash%\n - %date_time%", + "name": "Özel Yol Formatı" + }, + "opera_download_button": { + "description": "Bir Snap görüntülerken sağ üst köşeye bir indirme düğmesi ekler.\nDüğmelere uzun basıldığında indirmeye zorlar", + "name": "Opera İndirme Düğmesi" + }, + "download_context_menu": { + "name": "İndirme Bağlam Menüsü", + "description": "Bağlam menüsünü kullanarak bir sohbetten veya hikayeden mesajları indirmenize/önizlemenize olanak tanır.\nDüğmelere uzun basmak indirmeye zorlar" + }, + "auto_download_voice_notes": { + "name": "Sesli Notları Otomatik İndir", + "description": "Sesli notları oynatırken otomatik olarak indirir" + } + } + }, + "user_interface": { + "name": "Kullanıcı Arayüzü", + "description": "Snapchat'in görünümünü ve hissini değiştirin", + "properties": { + "enable_app_appearance": { + "name": "Uygulama Görünüm Ayarlarını Etkinleştir", + "description": "Gizli Uygulama Görünümü Ayarını etkinleştirir\nDaha yeni Snapchat sürümlerinde gerekli olmayabilir" + }, + "friend_feed_message_preview": { + "name": "Arkadaş Akışı Mesaj Önizlemesi", + "description": "Arkadaş Akışındaki son mesajların önizlemesini gösterir", + "properties": { + "amount": { + "name": "Miktar", + "description": "Önizlemesi yapılacak mesaj miktarı" + } + } + }, + "bootstrap_override": { + "name": "Önyükleme Geçersiz Kılma", + "description": "Kullanıcı arayüzü önyükleme ayarlarını geçersiz kılar", + "properties": { + "app_appearance": { + "name": "Uygulama Görünümü", + "description": "Kalıcı bir Uygulama Görünümü ayarlar" + }, + "home_tab": { + "name": "Ana Sayfa Sekmesi", + "description": "Snapchat açılırken başlangıç sekmesini geçersiz kılar" + } + } + }, + "map_friend_nametags": { + "name": "Geliştirilmiş Arkadaş Haritası İsim Etiketleri", + "description": "Snapmap'teki arkadaşların İsim Etiketlerini iyileştirir" + }, + "streak_expiration_info": { + "name": "Seri Sona Erme Bilgisini Göster", + "description": "Seriler sayacının yanında bir Seri Sona Erme zamanlayıcısı gösterir" + }, + "hide_friend_feed_entry": { + "name": "Arkadaş Akışı Girişini Gizle", + "description": "Arkadaş Akışı'ndan belirli bir arkadaşı gizler\nBu özelliği yönetmek için sosyal sekmesini kullanın" + }, + "hide_streak_restore": { + "name": "Seri Geri Yüklemeyi Gizle", + "description": "Arkadaş akışındaki Seri Geri Yükle düğmesini gizler" + }, + "hide_ui_components": { + "name": "Kullanıcı Arayüzü Bileşenlerini Gizle", + "description": "Hangi kullanıcı arayüzü bileşenlerinin gizleneceğini seçin" + }, + "disable_spotlight": { + "name": "Spotlight'ı Devre Dışı Bırak", + "description": "Spotlight sayfasını devre dışı bırakır" + }, + "friend_feed_menu_buttons": { + "name": "Arkadaş Akışı Menü Düğmeleri", + "description": "Arkadaş Akışı Menü Çubuğunda hangi düğmelerin gösterileceğini seçin" + }, + "enable_friend_feed_menu_bar": { + "name": "Arkadaş Akışı Menü Çubuğu", + "description": "Yeni Arkadaş Akışı Menüsü Çubuğunu etkinleştirir" + }, + "opera_media_quick_info": { + "description": "Opera görüntüleyici içerik menüsünde oluşturma tarihi gibi medyanın yararlı bilgilerini gösterir", + "name": "Opera Medya Hızlı Bilgi" + }, + "vertical_story_viewer": { + "name": "Dikey Hikaye Görüntüleyici", + "description": "Tüm hikayeler için dikey hikaye görüntüleyiciyi etkinleştirir" + }, + "old_bitmoji_selfie": { + "name": "Eski Bitmoji Selfie'si", + "description": "Eski Snapchat sürümlerindeki Bitmoji Selfie'lerini geri getirir" + }, + "prevent_message_list_auto_scroll": { + "name": "Mesaj Listesi Otomatik Kaydırmayı Önle", + "description": "Mesaj gönderirken/alırken mesaj listesinin en alta kaymasını engeller" + }, + "edit_text_override": { + "name": "Metin Geçersiz Kılmayı Düzenle", + "description": "Metin alanı davranışını geçersiz kılar" + }, + "snap_preview": { + "name": "Snap Önizleme", + "description": "Sohbette açılmayan Snap'lerin yanında küçük bir önizleme görüntüler" + }, + "hide_story_suggestions": { + "name": "Hikaye Önerilerini Gizle", + "description": "Hikayeler sayfasından önerileri kaldırır" + }, + "stealth_mode_indicator": { + "name": "Gizli Mod Göstergesi", + "description": "Gizli modundaki konuşmaların yanına bir 👻 emojisi ekler" + }, + "message_indicators": { + "name": "Mesaj Göstergeleri", + "description": "Mesajlara belirli gösterge simgeleri ekler\nNot: Göstergeler %100 doğru olmayabilir" + }, + "auto_close_friend_feed_menu": { + "name": "Arkadaş Akışı Menüsünü Otomatik Olarak Kapat", + "description": "Bir ayar düğmesine basıldıktan sonra Arkadaş Akışı Menüsünü otomatik olarak kapatır" + }, + "custom_theme": { + "name": "Özel Tema", + "description": "Snapchat'in Renklerini Özelleştirme\nNot: Koyu bir tema seçerseniz (Amoled gibi), daha iyi sonuçlar için Snapchat ayarlarında karanlık modu etkinleştirmeniz gerekebilir" + } + } + }, + "messaging": { + "name": "Mesajlaşma", + "description": "Arkadaşlarınızla etkileşim şeklinizi değiştirin", + "properties": { + "anonymous_story_viewing": { + "name": "Anonim Hikaye Görüntüleme", + "description": "Herhangi birinin hikayelerini gördüğünüzü bilmesini engeller" + }, + "hide_bitmoji_presence": { + "name": "Bitmoji'yi Gizle", + "description": "Sohbet sırasında Bitmoji'nizin görünmesini engeller" + }, + "hide_typing_notifications": { + "name": "Yazıyor Bildirimlerini Gizle", + "description": "Herhangi birinin mesaj yazdığınızı bilmesini engeller" + }, + "unlimited_snap_view_time": { + "name": "Sınırsız Snap Görüntüleme Süresi", + "description": "Snap'leri görüntülemek için Zaman Sınırını kaldırır" + }, + "disable_replay_in_ff": { + "name": "AA'da Tekrar Oynatmayı Devre Dışı Bırak", + "description": "Arkadaş Akışından uzun basarak yeniden oynatma özelliğini devre dışı bırakır" + }, + "prevent_message_sending": { + "name": "Mesaj Gönderimini Önleme", + "description": "Belirli mesaj türlerinin gönderilmesini engeller" + }, + "better_notifications": { + "name": "Daha İyi Bildirimler", + "description": "Alınan bildirimlere daha fazla bilgi ekler", + "properties": { + "group_notifications": { + "name": "Grup Bildirimleri", + "description": "Bildirimleri tek bir bildirimde grupla" + }, + "media_preview": { + "description": "Bildirimde seçilen medya türlerinin önizlemesini gösterir", + "name": "Medya Önizlemesi" + }, + "friend_add_source": { + "name": "Arkadaş Ekleme Kaynağı", + "description": "Bildirimde bir arkadaşlık isteğinin kaynağını gösterir" + }, + "download_button": { + "name": "İndirme Düğmesi", + "description": "Bildirimden medya indirmenize izin verir" + }, + "chat_preview": { + "name": "Sohbet Önizlemesi", + "description": "Bildirimde alınan mesajların önizlemesini gösterir" + }, + "media_caption": { + "name": "Medya Başlığı", + "description": "Bildirimdeki ekli medya başlığını gösterir" + }, + "stacked_media_messages": { + "name": "Yığılmış Medya Mesajları", + "description": "Önizleme yapılamadığında birden fazla medya mesajını tek bir metin bildiriminde birleştirir. Sohbet Önizleme ile birlikte kullanın" + }, + "reply_button": { + "name": "Yanıt Düğmesi", + "description": "Bildirime bir yanıt düğmesi ekler" + }, + "mark_as_read_button": { + "name": "Okundu Olarak İşaretle Düğmesi", + "description": "Bir mesajı bildirimden okundu olarak işaretlemenizi sağlar" + }, + "mark_as_read_and_save_in_chat": { + "name": "Okundu Olarak İşaretle ve Sohbete Kaydet", + "description": "Bildirime okundu olarak işaretle ve sohbete kaydet düğmesi ekler" + }, + "smart_replies": { + "description": "Bildirimlere önerilen yanıtlar ekler (Android 10+). Yanıtla Düğmesi ile birlikte kullanın", + "name": "Akıllı Yanıtlar" + } + } + }, + "notification_blacklist": { + "name": "Bildirim Kara Listesi", + "description": "Engellenecek bildirimleri seçin" + }, + "message_logger": { + "name": "Mesaj Kaydedici", + "description": "Mesajların silinmesini önler", + "properties": { + "message_filter": { + "name": "Mesaj Filtresi", + "description": "Hangi mesajların günlüğe kaydedileceğini seçin (tüm mesajlar için boş bırakın)" + }, + "auto_purge": { + "description": "Belirtilen süreden daha eski olan önbelleğe alınmış mesajları otomatik olarak siler", + "name": "Otomatik Temizleme" + }, + "keep_my_own_messages": { + "name": "Kendi Mesajlarımı Sakla", + "description": "Kendi mesajlarınızın silinmesini önler" + } + } + }, + "auto_save_messages_in_conversations": { + "name": "Mesajları Otomatik Kaydet", + "description": "Görüşmelerdeki her mesajı otomatik olarak kaydeder" + }, + "gallery_media_send_override": { + "name": "Galeri Medya Göndermesini Geçersiz Kılma", + "description": "Galeri'den gönderirken medya kaynağını taklit eder" + }, + "call_start_confirmation": { + "name": "Arama Başlatma Onayı", + "description": "Arama başlatırken bir onay iletişim kutusu gösterir" + }, + "half_swipe_notifier": { + "properties": { + "min_duration": { + "name": "Minimum Süre", + "description": "Yarım kaydırmanın minimum süresi (saniye cinsinden)" + }, + "max_duration": { + "description": "Yarım kaydırmanın maksimum süresi (saniye cinsinden)", + "name": "Maksimum Süre" + } + }, + "name": "Yarım Kaydırma Bildiricisi", + "description": "Birisi konuşmaya yarım kaydırma yaptığında sizi bilgilendirir" + }, + "bypass_screenshot_detection": { + "description": "Snapchat'in ekran görüntüsü aldığınızı algılamasını engeller", + "name": "Ekran Görüntüsü Algılamayı Kapat" + }, + "strip_media_metadata": { + "description": "Mesaj olarak göndermeden önce medyanın meta verilerini kaldırır", + "name": "Medya Meta Verilerini Kaldır" + }, + "bypass_message_retention_policy": { + "name": "Mesaj Saklama Politikasını Atlayın", + "description": "Mesajların görüntülendikten sonra silinmesini önler" + }, + "prevent_story_rewatch_indicator": { + "name": "Hikaye Tekrar İzleme Göstergesini Önle", + "description": "Herhangi birinin hikayelerini tekrar izlediğinizi bilmesini engeller" + }, + "hide_peek_a_peek": { + "description": "Bir sohbete yarım kaydırma yaptığınızda bildirim gönderilmesini önler", + "name": "Peek-a-Peek'i Gizle" + }, + "loop_media_playback": { + "name": "Medya Oynatmayı Döngüye Al", + "description": "Snap'leri / Hikayeleri görüntülerken medya oynatmayı döngüye alır" + }, + "bypass_message_action_restrictions": { + "name": "Mesaj Eylemi Kısıtlamalarını Atla", + "description": "Bir snap'i açmadan tepki vermenizi veya kaydedilemeyen bir mesajı kaydetmenizi sağlar" + }, + "remove_groups_locked_status": { + "name": "Grupların Kilitli Durumunu Kaldır", + "description": "Atıldıktan sonra grup bilgilerini görüntülemenizi sağlar" + }, + "auto_mark_as_read": { + "name": "Otomatik Okundu Olarak İşaretle", + "description": "Gizli Mod etkinleştirildiğinde bile mesajları/snapleri otomatik olarak okundu olarak işaretler" + }, + "friend_mutation_notifier": { + "name": "Arkadaş Değişimi Bildiricisi", + "description": "Bir arkadaşınızın profilinde bir değişiklik olduğunda size bildirir" + }, + "unlimited_conversation_pinning": { + "description": "Sınırsız sayıda konuşmayı yerel olarak sabitlemenizi sağlar", + "name": "Sınırsız Konuşma Sabitleme" + }, + "mark_snap_as_seen_button": { + "name": "Snap'i Görüldü Olarak İşaretle Düğmesi", + "description": "Bir Snap'i görüntülerken görüldü olarak işaretlemek için bir düğme ekler.\nBu, Gizli Mod etkinleştirildiğinde bile çalışacaktır" + }, + "skip_when_marking_as_seen": { + "name": "Görüldü Olarak İşaretlerken Atla", + "description": "Bir Snap'i görüldü olarak işaretlerken otomatik olarak bir sonraki Snap'e atlar.\nSnap'i Görüldü Olarak İşaretle Düğmesi ile birlikte kullanın" + } + } + }, + "global": { + "name": "Genel", + "description": "Genel Snapchat Ayarlarını Değiştirin", + "properties": { + "snapchat_plus": { + "name": "Snapchat Plus", + "description": "Snapchat Plus özelliklerini etkinleştirir\nBazı Sunucu taraflı özellikler çalışmayabilir" + }, + "auto_updater": { + "name": "Otomatik Güncelleyici", + "description": "Yeni güncellemeleri otomatik olarak kontrol eder" + }, + "disable_metrics": { + "name": "Ölçümleri Devre Dışı Bırak", + "description": "Snapchat'e belirli analitik verilerin gönderilmesini engeller" + }, + "block_ads": { + "name": "Reklamları Engelle", + "description": "Reklamların görüntülenmesini engeller" + }, + "bypass_video_length_restriction": { + "name": "Video Uzunluğu Kısıtlamalarını Atlayın", + "description": "Tek: tek bir video gönderir\nBöl: videoları düzenledikten sonra böl" + }, + "disable_google_play_dialogs": { + "name": "Google Play Hizmetleri İletişim Kutularını Devre Dışı Bırak", + "description": "Google Play Hizmetleri mevcutluk iletişim kutularının gönderilmesini önlemer" + }, + "disable_snap_splitting": { + "name": "Snap Bölmeyi Devre Dışı Bırak", + "description": "Snap'lerin birden fazla parçaya bölünmesini önler\nGönderdiğiniz resimler videoya dönüşecek" + }, + "disable_confirmation_dialogs": { + "name": "Onay İletişim Kutularını Devre Dışı Bırak", + "description": "Seçilen eylemleri otomatik olarak onaylar" + }, + "spotlight_comments_username": { + "name": "Spotlight Yorumlar Kullanıcı Adı", + "description": "Spotlight yorumlarında yazar kullanıcı adını gösterir" + }, + "disable_story_sections": { + "name": "Hikaye Bölümlerini Devre Dışı Bırak", + "description": "Hikayeler sayfasından bölümleri kaldırır\nDüzgün çalışması için yenileme gerekebilir" + }, + "disable_memories_snap_feed": { + "description": "Kamerada yukarı kaydırdığınızda Snapchat'in son anıları göstermesini engeller", + "name": "Anılar Snap Feed'ini Devre Dışı Bırak" + }, + "default_video_playback_rate": { + "name": "Varsayılan Video Oynatma Hızı", + "description": "Videoların oynatılması için varsayılan hızı ayarlar\nDeğer 0.1 ile 4.0 arasında olmalıdır" + }, + "video_playback_rate_slider": { + "name": "Video Oynatma Hızı Kaydırıcısı", + "description": "Video oynatma hızını değiştirmek için opera içerik menüsüne bir kaydırıcı ekler\nNot: Değişiklikler yalnızca sonraki videolar için geçerlidir" + }, + "default_volume_controls": { + "name": "Varsayılan Ses Kontrolleri", + "description": "Snapchat'i sistem ses kontrollerini kullanmaya zorlar" + }, + "disable_permission_requests": { + "name": "İzin İsteklerini Devre Dışı Bırak", + "description": "Snapchat'in belirli izinleri istemesini engeller" + }, + "better_location": { + "description": "Snapchat Konumunu İyileştirir", + "properties": { + "spoof_location": { + "name": "Sahte Konum", + "description": "Konumunuzu belirli bir konumla değiştirir" + }, + "coordinates": { + "description": "Sahte konumun koordinatlarını ayarlayın", + "name": "Koordinatlar" + }, + "always_update_location": { + "name": "Konumu Her Zaman Güncelle", + "description": "GPS verisi alınmasa bile Snapchat'i konumu güncellemeye zorlama" + }, + "suspend_location_updates": { + "name": "Konum Güncellemelerini Askıya Al", + "description": "Konumunuzun güncellenmesini engeller" + }, + "spoof_battery_level": { + "name": "Sahte Pil Seviyesi", + "description": "Cihazınızın pil seviyesini harita üzerinde gösterir\nDeğer 0 ile 100 arasında olmalıdır" + }, + "spoof_headphones": { + "name": "Sahte Kulaklıklar", + "description": "Harita üzerinde müzik dinleme durumunu taklit eder" + }, + "walk_radius": { + "name": "Yürüyüş Yarıçapı", + "description": "Bu yarıçap (ft) içinde haritada rastgele dolaşın" + }, + "show_battery_level": { + "name": "Pil Seviyesini Göster", + "description": "Arkadaşlarınızın pil seviyesini haritada gösterir" + } + }, + "name": "Daha İyi Konum" + }, + "hide_active_music": { + "name": "Aktif Müziği Gizle", + "description": "Snapchat'in müzik dinlediğinizi bilmesini engeller\nBu sayede müzik dinlerken ses kontrol düğmelerini kullanarak fotoğraf çekebilirsiniz" + }, + "disable_custom_tabs": { + "name": "Özel Sekmeleri Devre Dışı Bırak", + "description": "Bağlantıları Web Tarayıcı yerine desteklenen uygulamalarda açar" + }, + "media_upload_quality": { + "name": "Medya Yükleme Kalitesi", + "description": "Medya yükleme kalitesini geçersiz kılar", + "properties": { + "force_video_upload_source_quality": { + "name": "Video Yükleme Kaynak Kalitesini Zorla", + "description": "Snapchat'i video yüklerken kaynak kalitesini kullanmaya zorlar\nLütfen bunun medyadan meta verileri kaldırmayabileceğini unutmayın" + }, + "disable_image_compression": { + "name": "Görüntü Sıkıştırmayı Devre Dışı Bırak", + "description": "Medya yüklerken görüntü sıkıştırmayı devre dışı bırakır" + }, + "custom_image_upload_format": { + "name": "Özel Resim Yükleme Formatı", + "description": "Özel bir resim yükleme biçimi ayarlar\nEn iyi kalite için kayıpsız bir format (PNG gibi) seçin" + } + } + }, + "disable_telecom_framework": { + "description": "Snapchat'in Android Telecom çerçevesini kullanmasını engeller\nBu, görüşme sırasında müzik dinlemenizi sağlar", + "name": "Telekom Çerçevesini Devre Dışı Bırak" + } + } + }, + "rules": { + "name": "Kurallar", + "description": "Tek tek kişiler için Otomatik Özellikleri Yönetme" + }, + "camera": { + "name": "Kamera", + "description": "Mükemmel çekim için doğru ayarları yapın", + "properties": { + "immersive_camera_preview": { + "name": "Sürükleyici Önizleme", + "description": "Snapchat'in Kamera önizlemesini Kırpmasını Önler\nBu, kameranın bazı cihazlarda titremesine neden olabilir" + }, + "force_camera_source_encoding": { + "name": "Kamera Kaynağı Kodlamasını Zorla", + "description": "Kamera kaynak kodlamasını zorlar" + }, + "hevc_recording": { + "name": "HEVC Kaydı", + "description": "Video kaydı için HEVC (H.265) codec bileşenini kullanır" + }, + "black_photos": { + "description": "Çekilen fotoğrafları siyah bir arka planla değiştirir\nVideolar etkilenmez", + "name": "Siyah Fotoğraflar" + }, + "override_front_resolution": { + "name": "Ön Çözünürlüğü Geçersiz Kılma", + "description": "Ön kamera için kamera çözünürlüğünü geçersiz kılar" + }, + "override_back_resolution": { + "name": "Arka Çözünürlüğü Geçersiz Kılma", + "description": "Arka kamera için kamera çözünürlüğünü geçersiz kılar" + }, + "custom_resolution": { + "name": "Özel Çözünürlük", + "description": "Özel bir kamera çözünürlüğü, genişlik x yükseklik (örn. 1920x1080) ayarlar.\nÖzel çözünürlük cihazınız tarafından desteklenmelidir" + }, + "disable_cameras": { + "name": "Kameraları Devre Dışı Bırak", + "description": "Snapchat'in seçilen kameraları kullanmasını engeller" + }, + "front_custom_frame_rate": { + "name": "Ön Kamera Özel Kare Hızı", + "description": "Ön kamera kare hızını geçersiz kılar" + }, + "back_custom_frame_rate": { + "name": "Arka Kamera Özel Kare Hızı", + "description": "Arka kamera kare hızını geçersiz kılar" + } + } + }, + "streaks_reminder": { + "name": "Seri Hatırlatma", + "description": "Seri'leriniz hakkında sizi periyodik olarak bilgilendirir", + "properties": { + "interval": { + "name": "Aralık", + "description": "Her hatırlatma arasındaki aralık (saat)" + }, + "remaining_hours": { + "name": "Kalan Süre", + "description": "Bildirim gösterilmeden önce kalan süre (saat)" + }, + "group_notifications": { + "name": "Bildirimleri Grupla", + "description": "Bildirimleri tek bir bildirimde gruplama" + } + } + }, + "experimental": { + "name": "Deneysel", + "description": "Deneysel özellikler", + "properties": { + "native_hooks": { + "name": "Yerel Kancalar", + "description": "Snapchat'in yerel koduna bağlanan Güvenli Olmayan Özellikler", + "properties": { + "disable_bitmoji": { + "name": "Bitmoji'yi Devre Dışı Bırak", + "description": "Arkadaş Profili Bitmoji'sini devre dışı bırakır" + }, + "composer_hooks": { + "properties": { + "bypass_camera_roll_limit": { + "name": "Film Rulosu Sınırını Atla", + "description": "Film rulosundan gönderebileceğiniz maksimum medya miktarını artırır" + }, + "composer_console": { + "name": "Composer Konsolu", + "description": "Composer'da JavaScript kodu çalıştırmanıza izin verir (yalnızca arm64)" + }, + "composer_logs": { + "name": "Composer Günlükleri", + "description": "Composer'ın konsol günlüklerini SnapEnhance'a yönlendirir" + }, + "show_first_created_username": { + "name": "İlk Oluşturulan Kullanıcı Adını Göster", + "description": "Profil sayfasında mevcut kullanıcı adının yanında ilk oluşturulan kullanıcı adını gösterir" + } + }, + "name": "Composer Kancaları", + "description": "Composer çapraz platform UI çerçevesine kod enjekte eder" + }, + "custom_emoji_font": { + "name": "Özel Emoji Fontu", + "description": "Özel bir emoji yazı tipi kullanmanızı sağlar. Yalnızca .ttf yazı tipleriyle çalışır" + }, + "custom_shared_library": { + "name": "Özel Paylaşımlı Kütüphane", + "description": "Snapchat'e özel bir paylaşımlı kütüphane yükler. Bu özellik yalnızca test amaçlıdır" + } + } + }, + "spoof": { + "name": "Taklit", + "description": "Hakkınızdaki çeşitli bilgileri taklit eder", + "properties": { + "remove_mock_location_flag": { + "name": "Sahte Konum İşaretini Kaldır", + "description": "Snapchat'in Mock konumunu algılamasını engeller" + }, + "remove_vpn_transport_flag": { + "description": "Snapchat'in VPN'leri algılamasını engeller", + "name": "VPN Aktarım İşaretini Kaldır" + }, + "play_store_installer_package_name": { + "description": "Yükleyici paket adını com.android.vending olarak geçersiz kılar", + "name": "Play Store Yükleyici Paket Adı" + } + } + }, + "infinite_story_boost": { + "name": "Sonsuz Hikaye Takviyesi", + "description": "Hikaye Takviye Limiti gecikmesini atlayın" + }, + "meo_passcode_bypass": { + "name": "My Eyes Only Şifresini Kır", + "description": "My Eyes Only şifresini atlayın\nBu yalnızca parola daha önce doğru girilmişse çalışacaktır" + }, + "no_friend_score_delay": { + "name": "Arkadaş Puanı Gecikmesi Yok", + "description": "Arkadaş Skoru görüntülenirken yaşanan gecikmeyi kaldırır" + }, + "e2ee": { + "name": "Uçtan-Uca Şifreleme", + "description": "Paylaşılan bir gizli anahtar kullanarak mesajlarınızı AES ile şifreler\nAnahtarınızı güvenli bir yere kaydettiğinizden emin olun!", + "properties": { + "encrypted_message_indicator": { + "name": "Şifrelenmiş Mesaj Göstergesi", + "description": "Şifrelenmiş mesajların yanına bir 🔒 emojisi ekler" + }, + "force_message_encryption": { + "name": "Mesaj Şifrelemeyi Zorla", + "description": "Yalnızca birden fazla konuşma seçildiğinde E2E Şifrelemesi etkin olmayan kişilere şifreli mesaj gönderilmesini engeller" + } + } + }, + "add_friend_source_spoof": { + "name": "Arkadaş Kaynağı Taklidi Ekle", + "description": "Arkadaşlık İsteğinin kaynağını taklit eder" + }, + "hidden_snapchat_plus_features": { + "name": "Gizli Snapchat Plus Özellikleri", + "description": "Yayınlanmamış/beta Snapchat Plus özelliklerini etkinleştirir\nEski Snapchat sürümlerinde çalışmayabilir" + }, + "prevent_forced_logout": { + "name": "Zorla Oturum Kapatmayı Önleme", + "description": "Başka bir cihazdan giriş yaptığınızda Snapchat'in oturumunuzu kapatmasını engeller" + }, + "convert_message_locally": { + "description": "Snap'leri yerel olarak sohbet harici ortamına dönüştürür. Bu, sohbet indirme içerik menüsünde görünür", + "name": "Mesajı Yerel Olarak Dönüştür" + }, + "story_logger": { + "description": "Arkadaş hikayelerinin bir tarihçesini sunar", + "name": "Hikaye Kaydedici" + }, + "media_file_picker": { + "name": "Medya Dosyası Seçici", + "description": "Galeriden herhangi bir video/ses dosyası seçmenizi sağlar" + }, + "call_recorder": { + "description": "Sesli aramaları otomatik olarak kaydeder", + "name": "Arama Kaydedici" + }, + "account_switcher": { + "name": "Hesap Değiştirici", + "description": "Oturumu kapatmadan hesaplar arasında geçiş yapmanızı sağlar\nMenüyü açmak için Bitmoji profilinizin yanındaki arama simgesine uzun basın\nNot: Bu özellik deneyseldir ve muhtemelen gelecekte değişecektir", + "properties": { + "auto_backup_current_account": { + "name": "Mevcut Hesabı Otomatik Olarak Yedekle", + "description": "Oturumu kapatırken veya hesap değiştirirken mevcut hesabı otomatik olarak yedekler" + } + } + }, + "edit_message": { + "name": "Mesajları Düzenle", + "description": "Görüşmelerdeki mesajları düzenlemenizi sağlar" + }, + "app_lock": { + "properties": { + "lock_on_resume": { + "description": "Uygulama yeniden başlatıldığında otomatik olarak kilitler", + "name": "Yeniden Başlatmada Kilitle" + } + }, + "name": "Uygulama Kilidi", + "description": "Snapchat'e şifre olmadan erişimi engeller" + }, + "custom_streaks_expiration_format": { + "name": "Özel Serilerin Sona Erme Biçimi", + "description": "Seri Sona Erme biçimini özelleştirir\n\nKullanılabilir değişkenler:\n - %c: Seri Sayısı\n - %e: Kum Saati Emojisi\n - %d: Gün\n - %h: Saat\n - %m: Dakika\n - %s: Saniye\n - %w: Kalan Süre" + }, + "best_friend_pinning": { + "description": "Bir arkadaşınızı bir numaralı en iyi arkadaşınız olarak sabitlemenizi sağlar. Not: Sabitlediğiniz en iyi arkadaşınızı sadece siz görebilirsiniz", + "name": "En İyi Arkadaş Sabitleme" + }, + "cof_experiments": { + "name": "COF Deneyleri", + "description": "Yayınlanmamış/beta Snapchat özelliklerini etkinleştirir" + }, + "context_menu_fix": { + "name": "Bağlam Menüsü Düzeltme", + "description": "Cihaz çevrimdışı olduğunda doğru şekilde görüntülenemediği için Arkadaş Besleme Menüsünü onarmaya çalışın" + }, + "better_transcript": { + "properties": { + "force_transcription": { + "name": "Sesli not transkriptine zorla", + "description": "Tüm sesli notların yazıya dökülmesini sağlar" + }, + "preferred_transcription_lang": { + "name": "Tercih Edilen Transkripsiyon Dili", + "description": "Sesli not metni için tercih edilen dil (örn. EN, ES, FR)" + }, + "enhanced_transcript": { + "name": "Geliştirilmiş Transkript", + "description": "DeepL adresini kullanarak sesli not dökümünü iyileştirir.\nBu özelliği kullanmadan önce lütfen gizlilik politikasını okuduğunuzdan emin olun." + }, + "enhanced_transcript_in_notifications": { + "description": "DeepL adresini kullanarak bildirimlerdeki sesli notları yazıya döker. Bu, Sohbet Önizleme özelliğinin Daha İyi Bildirimler'de etkinleştirilmesini gerektirir", + "name": "Bildirimlerde Geliştirilmiş Transkript" + } + }, + "name": "Daha İyi Transkript", + "description": "Sesli not transkriptini iyileştirir" + }, + "voice_note_auto_play": { + "name": "Sesli Not Otomatik Oynatma", + "description": "Geçerli sesli not bittikten sonra otomatik olarak bir sonraki sesli notu çalar" + } + } + }, + "scripting": { + "name": "Komut Dosyaları", + "description": "SnapEnhance'i genişletmek için özel komut dosyaları çalıştırın", + "properties": { + "developer_mode": { + "name": "Geliştirici Modu", + "description": "Snapchat'in kullanıcı arayüzünde hata ayıklama bilgilerini gösterir" + }, + "module_folder": { + "name": "Modül Klasörü", + "description": "Komut dosyalarının bulunduğu klasör" + }, + "integrated_ui": { + "name": "Entegre Kullanıcı Arayüzü", + "description": "Komut dosyalarının Snapchat'e özel kullanıcı arayüzü bileşenleri eklemesine izin verir" + }, + "disable_log_anonymization": { + "description": "Günlüklerin anonimleştirilmesini devre dışı bırakır", + "name": "Günlük Anonimleştirmeyi Devre Dışı Bırak" + }, + "auto_reload": { + "description": "Değiştiklerinde komut dosyalarını otomatik olarak yeniden yükler", + "name": "Otomatik Yeniden Yükleme" + } + } + }, + "friend_tracker": { + "name": "Arkadaş Takibi", + "description": "Arkadaşınızın Snapchat'teki etkinliğini kaydeder", + "properties": { + "allow_running_in_background": { + "name": "Arka Planda Çalışmaya İzin Ver", + "description": "İzleyicinin arka planda çalışmasına izin verir. Not: Bu, pilinizi önemli ölçüde tüketecektir" + }, + "record_messaging_events": { + "name": "Mesajlaşma Olaylarını Kaydetme", + "description": "Snap açma, mesaj okuma gibi mesajlaşma olaylarını kaydeder." + }, + "auto_purge": { + "name": "Otomatik Temizleme", + "description": "Belirtilen süreden daha eski olan önbelleğe alınmış olayları otomatik olarak siler" + } + } + } + }, + "options": { + "app_appearance": { + "always_light": "Daima Aydınlık", + "always_dark": "Daima Koyu" + }, + "friend_feed_menu_buttons": { + "auto_download": "⬇️ Otomatik İndirme", + "auto_save": "💬 Mesajları Otomatik Kaydetme", + "stealth": "👻 Gizli Mod", + "conversation_info": "👤 Konuşma Bilgileri", + "e2e_encryption": "🔒 E2E Şifreleme Kullan", + "mark_stories_as_seen_locally": "👀 Hikayeleri görüldü olarak işaretleyin", + "mark_snaps_as_seen": "👀 Snap'leri görüldü olarak işaretleyin", + "unsaveable_messages": "⬇️ Kaydedilemeyen Mesajlar", + "auto_open_snaps": "📷 Snap'leri Otomatik Aç" + }, + "path_format": { + "create_author_folder": "Her kullanıcı için klasör oluştur", + "create_source_folder": "Her medya kaynağı türü için klasör oluşturma", + "append_hash": "Dosya adına benzersiz bir hash ekle", + "append_source": "Medya kaynağını dosya adına ekleyin", + "append_username": "Dosya adına kullanıcı adını ekle", + "append_date_time": "Dosya adına tarih ve saati ekle" + }, + "auto_download_sources": { + "friend_snaps": "Arkadaş Snapleri", + "friend_stories": "Arkadaş Hikayeleri", + "public_stories": "Herkese Açık Hikayeler", + "spotlight": "Spotlight" + }, + "logging": { + "started": "Başladı", + "success": "Başarılı", + "progress": "İlerleme", + "failure": "Başarısız" + }, + "notifications": { + "chat_screenshot": "Ekran Görüntüsü", + "chat_screen_record": "Ekran Kaydı", + "snap_replay": "Snap Tekrar Oynatma", + "camera_roll_save": "Film Rulosu Kaydı", + "chat": "Sohbet", + "chat_reply": "Sohbet Cevabı", + "snap": "Snap", + "typing": "Yazıyor", + "stories": "Hikayeler", + "chat_reaction": "DM Tepkisi", + "group_chat_reaction": "Grup Tepkisi", + "initiate_audio": "Gelen Sesli Arama", + "abandon_audio": "Cevapsız Sesli Arama", + "initiate_video": "Gelen Görüntülü Arama", + "abandon_video": "Cevapsız Görüntülü Arama", + "speaking": "Konuşma" + }, + "gallery_media_send_override": { + "ORIGINAL": "Orijinal Medya", + "NOTE": "Sesli Not", + "SNAP": "Snap", + "always_ask": "Her Zaman Sor", + "SAVEABLE_SNAP": "Kaydedilebilir Snap" + }, + "hide_ui_components": { + "hide_profile_call_buttons": "Profil Arama Düğmelerini Kaldır", + "hide_chat_call_buttons": "Sohbet Arama Düğmelerini Kaldır", + "hide_live_location_share_button": "Canlı Konum Paylaş Düğmesini Kaldır", + "hide_stickers_button": "Çıkartmalar Butonunu Kaldır", + "hide_voice_record_button": "Ses Kayıt Butonunu Kaldır", + "hide_unread_chat_hint": "Okunmamış Sohbet İpucunu Kaldır", + "hide_post_to_story_buttons": "Snap göndermeden önce Hikayeye Gönder düğmelerini kaldırın", + "hide_billboard_prompt": "Arkadaş Akışındaki Reklam Panolarını Kaldır", + "hide_snapchat_plus_gift_reminders": "Sohbetlerdeki Snapchat Plus hediye hatırlatıcılarını kaldır", + "hide_map_reactions": "Harita Tepkilerini Kaldır" + }, + "home_tab": { + "map": "Harita", + "chat": "Sohbet", + "camera": "Kamera", + "discover": "Keşfet", + "spotlight": "Spotlight" + }, + "add_friend_source_spoof": { + "added_by_username": "Kullanıcı Adına Göre", + "added_by_mention": "Bahsetmeye Göre", + "added_by_group_chat": "Grup Sohbetine Göre", + "added_by_qr_code": "QR Kodu'na Göre", + "added_by_community": "Topluluğa Göre", + "added_by_quick_add": "Hızlı Ekleme ile (yüksek yasaklanma riski)" + }, + "bypass_video_length_restriction": { + "single": "Tek medya", + "split": "Bölünmüş medya" + }, + "auto_reload": { + "snapchat_only": "Sadece Snapchat", + "all": "Tümü (Snapchat + SnapEnhance)" + }, + "strip_media_metadata": { + "remove_audio_note_duration": "Ses Notası Süresini Kaldır", + "remove_audio_note_transcript_capability": "Ses Notu Transkript Özelliğini Kaldır", + "hide_extras": "Ekstraları Gizle (örn. bahsedenler)", + "hide_caption_text": "Başlık Metnini Gizle", + "hide_snap_filters": "Snap Filtrelerini Gizle" + }, + "auto_purge": { + "1_day": "1 Gün", + "1_week": "1 Hafta", + "1_month": "1 Ay", + "2_weeks": "2 Hafta", + "never": "Asla", + "1_hour": "1 Saat", + "3_hours": "3 Saat", + "6_months": "6 Ay", + "3_days": "3 Gün", + "6_hours": "6 Saat", + "3_months": "3 Ay", + "12_hours": "12 Saat" + }, + "disable_confirmation_dialogs": { + "hide_conversation": "Konuşmayı Gizle", + "clear_conversation": "Arkadaş Akışından Konuşmayı Temizle", + "remove_friend": "Arkadaşı Kaldır", + "hide_friend": "Arkadaşı Gizle", + "ignore_friend": "Arkadaşı Yoksay", + "block_friend": "Arkadaşı Engelle", + "erase_message": "Mesajı Sil" + }, + "edit_text_override": { + "bypass_text_input_limit": "Metin Giriş Sınırını Atla", + "multi_line_chat_input": "Çok Hatlı Sohbet Girişi" + }, + "old_bitmoji_selfie": { + "2d": "2D Bitmoji", + "3d": "3D Bitmoji" + }, + "hide_story_suggestions": { + "hide_suggested_friend_stories": "Önerilen arkadaş hikayelerini gizle", + "hide_my_stories": "Hikayelerimi Gizle" + }, + "disable_story_sections": { + "friends": "Arkadaşlar", + "discover": "Keşfet", + "following": "Takip Edilen", + "suggested_stories": "Önerilen Hikayeler" + }, + "disable_cameras": { + "front": "Ön Kamera", + "back": "Arka Kamera" + }, + "disable_permission_requests": { + "read_media_images": "Medya Görsellerini Oku", + "microphone": "Mikrofon", + "read_contacts": "Kişileri Oku", + "nearby_devices": "Yakındaki Cihazlar", + "phone_calls": "Telefon Çağrıları", + "notifications": "Bildirimler", + "read_media_video": "Medya Videosunu Oku", + "camera": "Kamera", + "location": "Konum" + }, + "message_indicators": { + "encryption_indicator": "Sadece size gönderilen mesajların yanına bir 🔒 simgesi ekler", + "platform_indicator": "Medyanın gönderildiği platform simgesini ekler (örn. Android, iOS, Web)", + "ovf_editor_indicator": "OVF Editor kullanılarak bir snap gönderilip gönderilmediğini gösterir", + "director_mode_indicator": "Galeri görüntülerini snap olarak göndermek için kullanılabilen Yönetmen Modu kullanılarak gönderildiklerinde snap'lere bir ✏️ simgesi ekler", + "location_indicator": "Konum etkinleştirilerek gönderildiklerinde snap'lere bir 📍 simgesi ekler" + }, + "auto_mark_as_read": { + "conversation_read": "Mesaj gönderirken konuşmayı okundu olarak işaretle", + "snap_reply": "Yanıt verirken snap'leri okundu olarak işaretle" + }, + "friend_mutation_notifier": { + "bitmoji_selfie_changes": "Birisi Bitmoji selfie'sini değiştirdiğinde bildir", + "bitmoji_scene_changes": "Birisi Bitmoji sahnesini değiştirdiğinde bildir", + "bitmoji_avatar_changes": "Birisi Bitmoji avatarını değiştirdiğinde bildir", + "remove_friend": "Birisi sizi arkadaşlıktan çıkardığında bildir", + "birthday_changes": "Birisi doğum gününü değiştirdiğinde bildir", + "bitmoji_background_changes": "Birisi Bitmoji arka planını değiştirdiğinde bildir" + }, + "custom_theme": { + "amoled_dark_mode": "Amoled Karanlık Mod", + "custom": "Özel Temalar (Temaları yönetmek için Hızlı Eylemleri kullanın)", + "material_you_light": "Material You Aydınlık (Android 12+)", + "material_you_dark": "Material You Karanlık (Android 12+)" + } + } + }, + "friend_menu_option": { + "preview": "Önizleme", + "stealth_mode": "Gizli Mod", + "auto_download_blacklist": "Kara Liste Otomatik İndirme", + "anti_auto_save": "Anti Otomatik Kaydetme", + "mark_snaps_as_seen": "Snap'leri Görüldü Olarak İşaretle", + "mark_stories_as_seen_locally": "Hikayeleri yerel olarak görüldü olarak işaretle" + }, + "chat_action_menu": { + "preview_button": "Önizleme", + "download_button": "İndir", + "delete_logged_message_button": "Kaydedilen Mesajı Sil", + "convert_message": "Mesajı Dönüştür", + "edit_message": "Mesajı Düzenle", + "show_chat_edit_history": "Sohbet Düzenleme Geçmişini Göster" + }, + "opera_context_menu": { + "download": "Medyayı İndir", + "media_duration": "Medya süresi: {duration} ms", + "show_debug_info": "Hata Ayıklama Bilgilerini Göster", + "expires_at": "{date}'de sona erer", + "created_at": "{date}'te oluşturuldu", + "sent_at": "{date}'de gönderildi", + "media_size": "Medya boyutu: {size}" + }, + "modal_option": { + "profile_info": "Profil Bilgisi", + "close": "Kapat" + }, + "gallery_media_send_override": { + "multiple_media_toast": "Bir seferde yalnızca bir medya gönderebilirsiniz" + }, + "conversation_preview": { + "streak_expiration": "{day} gün {hour} saat {minute} dakika içinde sona eriyor", + "total_messages": "Toplam gönderilen/alınan mesajlar: {count}", + "title": "Önizleme", + "unknown_user": "Bilinmeyen Kullanıcı", + "no_messages": "Mesaj bulunamadı!" + }, + "profile_info": { + "title": "Profil Bilgisi", + "first_created_username": "İlk Oluşturulan Kullanıcı Adı", + "mutable_username": "Değiştirilebilir Kullanıcı Adı", + "display_name": "Görünen İsim", + "added_date": "Eklenme Tarihi", + "birthday": "Doğum Günü: {day} {month}", + "friendship": "Arkadaşlık", + "add_source": "Kaynak Ekle", + "snapchat_plus": "Snapchat Plus", + "snapchat_plus_state": { + "subscribed": "Abone Olunanlar", + "not_subscribed": "Abone Olunmayanlar" + }, + "hidden_birthday": "Doğum Günü : Gizli" + }, + "chat_export": { + "dialog_negative_button": "İptal", + "dialog_positive_button": "Dışa Aktar", + "exported_to": "{path}'a aktarıldı", + "exporting_chats": "Sohbetler Dışa Aktarılıyor...", + "processing_chats": "{amount} konuşma işleniyor...", + "export_fail": "Konuşma {conversation} dışa aktarılamadı", + "writing_output": "Çıktı yazılıyor...", + "finished": "Bitti! Artık bu iletişim kutusunu kapatabilirsiniz.", + "no_messages_found": "Mesaj bulunamadı!", + "exporting_message": "{conversation} dışa aktarılıyor...", + "exporter_dialog": { + "text_field_selection_all": "Tümü", + "export_file_format_title": "Dosya Formatını Dışa Aktar", + "download_medias_title": "Medyaları İndirin", + "amount_of_messages_title": "Mesaj Miktarı (hepsi için boş bırakın)", + "message_type_filter_title": "Mesajları Türe Göre Filtreleme", + "text_field_selection": "{amount} seçildi", + "select_conversations_title": "Konuşmaları Seç" + } + }, + "button": { + "ok": "Tamam", + "positive": "Evet", + "negative": "Hayır", + "cancel": "İptal", + "open": "Aç", + "download": "İndir", + "send": "Gönder" + }, + "profile_picture_downloader": { + "button": "Profil Resmini İndir", + "title": "Profil Resmi İndirici", + "avatar_option": "Profil Resmi", + "background_option": "Arkaplan" + }, + "download_processor": { + "attachment_type": { + "snap": "Snap", + "sticker": "Çıkartma", + "external_media": "Harici Medya", + "note": "Not", + "original_story": "Orijinal Hikaye", + "gif": "GIF" + }, + "select_attachments_title": "Ekleri seçin", + "download_started_toast": "İndirme başladı", + "unsupported_content_type_toast": "Desteklenmeyen içerik türü!", + "failed_no_longer_available_toast": "Medya artık mevcut değil", + "no_attachments_toast": "Ek bulunamadı!", + "already_queued_toast": "Medya zaten sırada!", + "already_downloaded_toast": "Medya zaten indirildi!", + "download_toast": "{path} indiriliyor...", + "processing_toast": "{path} işleniyor...", + "failed_generic_toast": "İndirme başarısız oldu", + "failed_to_create_preview_toast": "Önizleme oluşturulamadı", + "failed_processing_toast": "İşlem başarısız {error}", + "failed_gallery_toast": "Galeriye kaydedilemedi {error}", + "dash_dialog": { + "title": "Dash medyasını indir", + "download_all": "Tümünü İndir", + "segment_text": "Segment {from} - {to}" + }, + "dash_no_chapter": "Bölüm bulunamadı" + }, + "streaks_reminder": { + "notification_title": "Seriler", + "notification_text": "{friend} ile olan Serini {hoursLeft} saat içinde kaybedeceksin" + }, + "content_type": { + "FAMILY_CENTER_INVITE": "Aile Merkezi Davetiyesi", + "STATUS_CONVERSATION_CAPTURE_RECORD": "Ekran Kaydı", + "STATUS_CALL_MISSED_VIDEO": "Cevapsız Görüntülü Arama", + "CREATIVE_TOOL_ITEM": "Yaratıcı Araç Öğesi", + "STICKER": "Çıkartma", + "TINY_SNAP": "Minik Snap", + "STATUS_SAVE_TO_CAMERA_ROLL": "Film Rulosuna Kaydedildi", + "EXTERNAL_MEDIA": "Harici Medya", + "SNAP": "Snap", + "LOCATION": "Konum", + "CHAT": "Sohbet", + "STATUS_PLUS_GIFT": "Durum Artı Hediyesi", + "STATUS_COUNTDOWN": "Geri Sayım", + "LIVE_LOCATION_SHARE": "Canlı Konum Paylaşımı", + "STATUS": "Durum", + "STATUS_CONVERSATION_CAPTURE_SCREENSHOT": "Ekran görüntüsü", + "FAMILY_CENTER_ACCEPT": "Aile Merkezi Kabul", + "FAMILY_CENTER_LEAVE": "Aile Merkezi Ayrıl", + "STATUS_CALL_MISSED_AUDIO": "Cevapsız Sesli Arama", + "NOTE": "Sesli Not", + "MAP_REACTION": "Harita Tepkisi", + "SHARE": "Paylaş" + }, + "better_notifications": { + "button": { + "download": "İndir", + "reply": "Yanıtla", + "mark_as_read": "Okundu olarak işaretle" + } + }, + "half_swipe_notifier": { + "notification_content_group": "{friend} {duration} saniye boyunca {group}'a yarım kaydırma yaptı", + "notification_channel_name": "Yarım Kaydırma", + "notification_content_dm": "{friend} sohbetinize {duration} saniye boyunca yarım kaydırma yaptı" + }, + "friendship_link_type": { + "mutual": "Karşılıklı", + "deleted": "Silinen", + "following": "Takip Edilen", + "incoming_follower": "Gelen Takipçi", + "incoming": "Gelen", + "blocked": "Engellenen", + "suggested": "Önerilen", + "outgoing": "Giden" + }, + "call_start_confirmation": { + "dialog_message": "Bir arama başlatmak istediğinizden emin misiniz?", + "dialog_title": "Arama Başlat" + }, + "bulk_messaging_action": { + "choose_action_title": "Bir eylem seçin", + "progress_status": "{total} öğesinin {index} öğesi işleniyor", + "actions": { + "clear_conversations": "Konuşmaları Temizle", + "remove_friends": "Arkadaşları Kaldır" + }, + "selection_dialog_continue_button": "Devam et", + "confirmation_dialog": { + "message": "Bu, seçilen tüm arkadaşları etkileyecektir. Bu eylem geri alınamaz.", + "title": "Emin misiniz?" + } + }, + "media_download_source": { + "public_story": "Herkese Açık Hikaye", + "spotlight": "Spotlight", + "pending": "Beklemede", + "merged": "Birleştirilmiş", + "story_logger": "Hikaye Kaydedici", + "none": "Hiçbiri", + "profile_picture": "Profil Fotoğrafı", + "story": "Hikaye", + "chat_media": "Sohbet Medyası", + "message_logger": "Mesaj Kaydedici", + "voice_call": "Sesli Arama" + }, + "material3_strings": { + "date_input_invalid_not_allowed": "Geçersiz tarih", + "date_range_input_invalid_range_input": "Geçersiz tarih aralığı", + "date_range_picker_scroll_to_previous_month": "Önceki ay", + "date_picker_switch_to_input_mode": "Giriş", + "date_range_picker_day_in_range": "Seçilen", + "date_input_invalid_for_pattern": "Geçersiz tarih", + "date_picker_today_description": "Bugün", + "date_picker_switch_to_calendar_mode": "Takvim", + "date_range_picker_start_headline": "Şuradan", + "date_range_picker_end_headline": "Şuraya", + "date_range_picker_scroll_to_next_month": "Sonraki ay", + "date_range_picker_title": "Tarih aralığı seçin", + "date_input_invalid_year_range": "Geçersiz yıl" + }, + "mark_as_seen": { + "unseen_toast": "Görülmedi olarak işaretlendi!", + "already_seen_toast": "Zaten görüldü olarak işaretlendi!", + "already_unseen_toast": "Zaten görülmemiş olarak işaretlendi!", + "no_unseen_snaps_toast": "Görülmeyen Snap bulunamadı!", + "seen_toast": "Görüldü olarak işaretlendi!" + }, + "actions": { + "clean_snapchat_cache": { + "name": "Snapchat Önbelleğini Temizle", + "description": "Snapchat Önbelleğini Temizler" + }, + "manage_friend_list": { + "name": "Arkadaş Listesini Yönet", + "description": "Yedekleme yaparken arkadaş listenizi içe/dışa aktarın" + }, + "export_chat_messages": { + "name": "Sohbet Mesajlarını Dışa Aktar", + "description": "Konuşma mesajlarını bir JSON/HTML/TXT dosyasına aktarır" + }, + "export_memories": { + "name": "Anıları Dışa Aktar", + "description": "Anıları bir ZIP dosyasına aktarır" + }, + "bulk_messaging_action": { + "name": "Toplu Mesajlaşma Eylemi", + "description": "Arkadaş silme veya konuşmaları toplu silme gibi işlemleri gerçekleştirir" + }, + "regen_mappings": { + "name": "Eşlemeleri Yeniden Oluştur", + "description": "Eşlemeleri manuel olarak yeniden oluşturma" + }, + "change_language": { + "name": "Dili Değiştir", + "description": "SnapEnhance'in dilini değiştir" + }, + "friend_tracker": { + "name": "Arkadaş Takibi", + "description": "Snapchat'te arkadaşlarınızı takip edin" + }, + "logger_history": { + "name": "Kaydedici Geçmişi", + "description": "Günlüğe kaydedilen mesajların geçmişini görüntüle" + }, + "file_imports": { + "name": "Dosya İçe Aktarımları", + "description": "Snapchat'te kullanmak için dosyaları içe aktarma" + }, + "security_features": { + "name": "Güvenlik Özellikleri", + "description": "Güvenlik özellikleri tercihlerini değiştir" + }, + "theming": { + "name": "Temalandırma", + "description": "Snapchat'in görünümünü ve hissini özelleştirin" + } + }, + "scopes": { + "friend": "Arkadaş", + "group": "Grup" + }, + "end_to_end_encryption": { + "toolbox": { + "initiate_exchange_button": "Anahtar Değişimini Başlat", + "no_shared_key": "Bu arkadaşınızla henüz paylaşılmış bir sırrınız yok. Yeni bir tane başlatmak için aşağıya tıklayın.", + "shared_key_fingerprint": "Parmak iziniz:\n\n{fingerprint}\n\nArkadaşınızın parmak iziyle eşleşip eşleşmediğini kontrol edin!" + }, + "confirmation_dialogs": { + "title": "Uçtan uca şifreleme", + "confirmation_2": "Devam etmek istediğinizden gerçekten emin misiniz? Bu geri çekilmek için son şansın.", + "confirmation_1": "UYARI: Bu işlem mevcut anahtarınızın üzerine yazacaktır. Bu arkadaşınızdan gelen tüm şifreli mesajlara erişiminizi kaybedeceksiniz. Devam etmek istediğinizden emin misiniz?" + }, + "unencrypted_conversation_send_failure_toast": "Hem şifrelenmiş hem de şifrelenmemiş konuşmalara şifrelenmiş içerik gönderemezsiniz!", + "no_participants_to_encrypt_toast": "Bu konuşmada mesajlarınızı şifreleyebileceğiniz hiç arkadaşınız yok!", + "accept_public_key_failure_toast": "Açık anahtar kabul edilemedi", + "accept_secret_button": "Sırrı Kabul Et", + "accept_public_key_button": "Açık Anahtarı Kabul Et", + "outgoing_pk_message": "Anahtar değişim talebi", + "outgoing_secret_message": "Anahtar değişimi yanıtı", + "incoming_secret_message": "Arkadaşınız az önce açık anahtarınızı kabul etti. Sırrı kabul etmek için aşağıya tıklayın.", + "accept_public_key_success_toast": "Açık anahtar başarıyla kabul edildi!", + "accept_secret_key_success_toast": "Tamamlandı! Artık bu arkadaşınızla şifreli mesajlar gönderip alabilirsiniz.", + "accept_secret_key_failure_toast": "Gizli anahtar kabul edilemedi", + "incoming_pk_message": "Az önce bir açık anahtar isteği aldınız. Kabul etmek için aşağıya tıklayın.", + "native_hooks_send_failure_toast": "Gönderilemedi! Lütfen ayarlardan Yerel Kancaları etkinleştirin.", + "encryption_failed_toast": "İleti şifrelenemedi! Daha fazla ayrıntı için logcat'i kontrol edin." + }, + "biometric_auth": { + "unlock_button": "Kilidi Aç", + "title": "Snapchat Kilidini Aç", + "subtitle": "Snapchat'in kilidini açmak için lütfen giriş yap" + }, + "auto_open_snaps": { + "title": "Snap'leri Otomatik Aç", + "notification_content": "{count} Snap Açıldı" + }, + "friend_mutation_observer": { + "notification_channel_name": "Arkadaş Değişim Gözlemcisi", + "birthday_removed": "{username} doğum gününü ({birthday}) kaldırdı", + "birthday_added": "{username} doğum gününü ekledi ({birthday})", + "bitmoji_avatar_changed": "{username} Bitmoji avatarını değiştirdi", + "friend_removed": "{username} sizi arkadaşlıktan çıkardı", + "birthday_changed": "{username} doğum gününü {oldBirthday} yerine {newBirthday} olarak değiştirdi", + "bitmoji_selfie_changed": "{username} Bitmoji selfie'sini değiştirdi", + "bitmoji_background_changed": "{username} Bitmoji arka planını değiştirdi", + "bitmoji_scene_changed": "{username} Bitmoji sahnesini değiştirdi" + }, + "theming_attributes": { + "sigColorTextPrimary": "Ana Metin Rengi", + "sigColorChatChat": "Ana Arkadaş Besleme Metin Rengi", + "sigColorChatPendingSending": "İkincil Arkadaş Besleme Metin Rengi", + "sigColorChatSnapWithSound": "Sesli Metin Renkli Snapler", + "sigColorChatSnapWithoutSound": "Sesli Metin Rengi Olmayan Snapler", + "actionSheetDescriptionTextColor": "Eylem Menüsü Açıklama Metin Rengi", + "sigColorBackgroundMain": "Arkaplan Rengi", + "listBackgroundDrawable": "Konuşma listesi Arkaplanı", + "sigColorChatConversationsLine": "Konuşmalar Çizgi Rengi", + "actionSheetBackgroundDrawable": "Eylem Menüsü Arkaplan Rengi", + "actionSheetRoundedBackgroundDrawable": "Eylem Menüsü Yuvarlak Arkaplan Rengi", + "sigColorBackgroundSurface": "Arkaplan Yüzey Rengi", + "sigColorIconPrimary": "Eylem Menüsü Simge Rengi", + "sigExceptionColorCameraGridLines": "Kamera Izgara Çizgileri Rengi", + "listDivider": "Liste Bölücü Rengi", + "sigColorIconSecondary": "İkincil Simge Rengi", + "itemShapeFillColor": "Ürün Şekli Dolgu Rengi", + "ringColor": "Halka Rengi", + "ringStartColor": "Halka Başlangıç Rengi", + "sigColorLayoutPlaceholder": "Düzen Yer Tutucu Rengi", + "scButtonColor": "Snapchat Buton Rengi", + "recipientPillBackgroundDrawable": "Alıcı Hap Arkaplanı", + "boxBackgroundColor": "Kutu Arkaplan Rengi", + "editTextColor": "Metin Rengini Düzenle", + "chipBackgroundColor": "Çip Arkaplan Rengi", + "recipientInputStyle": "Alıcı Giriş Stili", + "rangeFillColor": "Aralık Dolgu Rengi", + "pstsIndicatorColor": "PSTS Gösterge Rengi", + "pstsTabBackground": "PSTS Sekme Arkaplanı", + "pstsDividerColor": "PSTS Bölücü Rengi", + "tabTextColor": "Sekme Metin Rengi", + "statusBarForeground": "Durum Çubuğu Önplan Rengi", + "statusBarBackground": "Durum Çubuğu Arkaplan Rengi", + "strokeColor": "Vuruş Rengi", + "storyReplayViewRingColor": "Hikaye Tekrarı Görünüm Daire Rengi", + "sigColorButtonPrimary": "Birincil Düğme Rengi", + "sigColorBaseAppYellow": "Temel Uygulama Sarı Renk", + "sigColorBackgroundSurfaceTranslucent": "Yarı Saydam Arkaplan Yüzey Rengi", + "sigColorStoryRingDiscoverTabThumbnailStoryRing": "Hikaye Halkası Keşfet Sekmesi Küçük Resim Hikaye Halkası Rengi", + "sigColorStoryRingFriendsFeedStoryRing": "Hikaye Halkası Arkadaş Beslemesi Hikaye Halkası Rengi" + }, + "send_override_dialog": { + "title": "Medyayı {type} olarak gönder", + "duration": "Süre: {duration}", + "saveable_snap_hint": "Snap'i sohbette kaydedilebilir hale getirin", + "unlimited_duration": "Sınırsız" + } +} diff --git a/common/src/main/assets/lang/uk_UA.json b/common/src/main/assets/lang/uk_UA.json new file mode 100644 index 00000000..f8a124ff --- /dev/null +++ b/common/src/main/assets/lang/uk_UA.json @@ -0,0 +1,1732 @@ +{ + "setup": { + "dialogs": { + "select_language": "Оберіть мову", + "save_folder": "SnapEnhance вимагає дозволів на зберігання для завантаження та збереження медіафайлів із Snapchat.\nБудь ласка, виберіть місце, куди потрібно завантажити медіа.", + "select_save_folder_button": "Виберіть папку" + }, + "mappings": { + "dialog": "Створення зіставлень, це може зайняти деякий час...", + "generate_failure_no_snapchat": "SnapEnhance не вдалося виявити Snapchat, спробуйте перевстановити Snapchat.", + "generate_failure": "Під час створення зіставлення сталася помилка. Повторіть спробу." + }, + "permissions": { + "dialog": "Щоб продовжити, потрібно відповідати таким вимогам:", + "notification_access": "Доступ до сповіщень", + "display_over_other_apps": "Відображення поверх інших програм", + "request_button": "Запит", + "battery_optimization": "Оптимізація батареї" + } + }, + "manager": { + "routes": { + "home_settings": "Налаштування", + "tasks": "Завдання", + "features": "Особливості", + "home": "Додому", + "logged_stories": "Зареєстровані історії", + "better_location": "Краще розташування", + "manage_rule_feature": "Керувати функцією правила", + "friend_tracker": "Відстеження друзів", + "edit_rule": "Редагувати правило", + "home_logs": "Журнали", + "logger_history": "Історія реєстратора", + "edit_theme": "Редагувати тему", + "manage_repos": "Керування репозиторіями", + "manage_scope": "Керувати обсягом", + "messaging_preview": "Попередній перегляд", + "scripts": "Сценарії", + "file_imports": "Імпорт файлів", + "social": "Соціальний", + "theming": "Тематизація" + }, + "sections": { + "features": { + "reset_option": "Скинути", + "saved_config_snackbar": "Конфігурацію збережено", + "import_option": "Імпорт", + "config_export_failure_toast": "Не вдалося експортувати конфігурацію {error}", + "config_export_success_toast": "Конфігурацію успішно експортовано", + "disabled": "Вимкнено", + "export_option": "Експорт", + "config_import_success_toast": "Конфігурацію успішно імпортовано", + "config_import_failure_toast": "Не вдалося імпортувати конфігурацію {error}", + "older_required": "Для правильної роботи цієї функції потрібен Snapchat v{version} або старішої версії", + "newer_required": "Для правильної роботи цієї функції потрібен Snapchat v{version} або новішої версії", + "search_button": "Пошук" + }, + "manage_scope": { + "rules_title": "Правила", + "streaks_length_text": "Довжина: {length}", + "streaks_expiration_text": "Термін дії закінчується через {eta}", + "streaks_expiration_text_expired": "Термін дії минув", + "reminder_button": "Встановити нагадування", + "delete_scope_confirm_dialog_title": "Ви впевнені, що бажаєте видалити {scope}?", + "e2ee_title": "Наскрізне шифрування", + "not_found": "Не знайдено", + "streaks_title": "Смуги", + "logged_stories_button": "Показати зареєстровані історії", + "notes_placeholder": "Натисніть, щоб додати примітку", + "participants_text": "{count} учасників" + }, + "home": { + "version_title": "v{versionName} · шляхом eternal", + "debug_build_summary_title": "Ви використовуєте збірку для налагодження SnapEnhance", + "debug_build_summary_content": "Версія {versionName} ({versionCode})", + "quick_actions_title": "Швидкі дії", + "debug_build_summary_date": "Дата складання: {date} ({days} днів тому)", + "update_title": "Оновлення SnapEnhance", + "update_content": "Доступна версія {version}!", + "update_button": "Завантажити" + }, + "home_settings": { + "actions_title": "Дії", + "export_button": "Експорт", + "clear_button": "Очистити", + "success_toast": "Готово!", + "message_logger_title": "Реєстратор повідомлень", + "message_logger_summary": "{messageCount} повідомлень\n{storyCount} історій", + "view_logger_history_button": "Переглянути історію реєстратора", + "debug_title": "Налагодження" + }, + "tasks": { + "remove_selected_tasks_title": "Ви впевнені, що бажаєте видалити вибрані завдання?", + "remove_all_tasks_title": "Ви впевнені, що хочете видалити всі завдання?", + "delete_files_option": "Також видалити файли", + "no_tasks": "Завдань немає", + "failed_to_open_file": "Не вдалося відкрити файл", + "merge_files_toast": "Об’єднання {count} файлів", + "remove_selected_tasks_confirm": "Видалити {count} завдань?", + "remove_all_tasks_confirm": "Видалити всі завдання?", + "merge_button": "Об’єднати" + }, + "social": { + "friends_tab": "Друзі", + "groups_tab": "Групи", + "streaks_expiration_short": "{hours} год", + "empty_hint": "(порожній)" + }, + "messaging_preview": { + "unsave_all_option": "Скасувати збереження всіх", + "save_selection_option": "Зберегти вибране", + "bridge_connection_failed": "Не вдалося підключитися до мосту. Переконайтеся, що Snapchat працює у фоновому режимі", + "save_all_option": "Зберегти все", + "mark_selection_as_seen_option": "Позначити вибране зображення як видиме", + "unsave_selection_option": "Скасувати збереження виділеного", + "no_message_hint": "Немає повідомлення", + "bridge_init_failed": "Не вдалося ініціалізувати міст обміну повідомленнями. Переконайтеся, що Snapchat працює у фоновому режимі", + "message_fetch_failed": "Не вдалося отримати повідомлення", + "mark_all_as_seen_option": "Позначити всі знімки як видимі", + "delete_selection_option": "Видалити виділення", + "delete_all_option": "Видалити все" + }, + "file_imports": { + "file_import_failed": "Не вдалося імпортувати файл: {error}", + "file_imported": "Файл успішно імпортовано", + "file_delete_failed": "Не вдалося видалити файл", + "import_file_button": "Імпорт файлу", + "file_not_found": "Файл не знайдено", + "no_files_hint": "Тут ви можете імпортувати файли для використання в Snapchat. Натисніть кнопку нижче, щоб імпортувати файл." + }, + "better_location": { + "spoofed_coordinates_title": "Широта {latitude}, Висота {longitude}", + "choose_location_button": "Виберіть Розташування", + "teleport_to_friend_button": "Телепорт до друга", + "search_bar": "Пошук", + "latitude_dialog_hint": "Широта", + "teleport_to_friend_title": "Телепорт до друга", + "suspend_location_updates": "Призупинити оновлення місцезнаходження", + "delete_dialog_title": "Видалити збережену координату", + "no_friends_map": "На карті немає друзів", + "saved_coordinates_title": "Збережені координати", + "delete_dialog_message": "Ви впевнені, що бажаєте видалити цю збережену координату?", + "no_saved_coordinates_hint": "Немає збережених координат", + "longitude_dialog_hint": "Висота", + "save_coordinates_dialog_title": "Зберегти координати", + "saved_name_dialog_hint": "Збережена назва", + "save_dialog_button": "Зберегти", + "spoof_location_toggle": "Локація підробки", + "no_friends_found": "Друзів не знайдено" + }, + "home_logs": { + "no_logs_hint": "Журнали відсутні", + "clear_logs_button": "Очистити журнали", + "export_logs_button": "Експорт журналів", + "saving_logs_toast": "Зберігання журналів, це може зайняти деякий час...", + "saved_logs_failure_toast": "Не вдалося зберегти журнали", + "saved_logs_success_toast": "Журнали успішно збережено" + }, + "manage_rule_feature": { + "whitelist_state_option": "Ніхто, крім...", + "blacklist_state_option": "Усі, крім...", + "whitelist_state_subtext": "Це правило стосуватиметься лише {count} друзів/груп", + "whitelist_state_button": "Виберіть дозволених друзів/групи", + "blacklist_state_subtext": "Це правило стосуватиметься всіх, крім {count} друзів/груп", + "dialog_clear_confirmation_text": "Ви впевнені, що бажаєте очистити список?", + "blacklist_state_button": "Виберіть виключених друзів/групи", + "clear_list_button": "Очистити список друзів/груп", + "disable_state_option": "Вимкнено", + "disable_state_subtext": "Це не вплине на друзів/групи" + }, + "logged_stories": { + "no_stories": "Історій не знайдено", + "save_from_cache_button": "Зберегти з кешу", + "story_failed_to_load": "Не вдалося завантажити" + }, + "logger_history": { + "list_group_format": "Група {name}", + "reverse_order_checkbox": "Зворотний порядок", + "chat_attachment": "Вкладення {index}", + "empty_message": "Порожнє повідомлення чату", + "no_more_messages": "Більше жодних повідомлень", + "message_parse_failed": "Не вдалося проаналізувати повідомлення", + "download_attachment_failed_toast": "Не вдалося завантажити вкладений файл", + "list_friend_format": "Друг {name}", + "unknown_sender": "Невідомий відправник" + }, + "theming": { + "no_themes_hint": "Теми не знайдено" + } + }, + "dialogs": { + "add_friend": { + "category_friends": "Друзі", + "search_hint": "Пошук", + "title": "Додати друга або групу", + "fetch_error": "Не вдалося отримати дані", + "category_groups": "Групи", + "participants_text": "{count} учасників" + }, + "scripting_warning": { + "title": "Увага", + "content": "SnapEnhance містить інструмент створення сценаріїв, що дозволяє виконувати визначений користувачем код на вашому пристрої. Будьте вкрай обережні та встановлюйте модулі лише з відомих надійних джерел. Неавторизовані або неперевірені модулі можуть становити загрозу безпеці вашої системи." + }, + "file_imports": { + "no_files_settings_hint": "Файли не знайдено. Переконайтеся, що ви імпортували необхідні файли в розділ «Імпорт файлів»", + "settings_select_file_hint": "Виберіть імпортований файл" + }, + "reset_config": { + "content": "Ви впевнені, що бажаєте скинути конфігурацію?", + "success_toast": "Конфігурацію успішно скинуто", + "title": "Скинути конфігурацію" + }, + "export_config": { + "title": "Експортувати конфіденційні дані?", + "content": "Бажаєте експортувати конфігурацію з конфіденційними даними? (Наприклад, координати розташування тощо)" + }, + "messaging_action": { + "select_all_button": "Виберіть усі", + "title": "Виберіть типи вмісту для обробки" + } + } + }, + "scopes": { + "friend": "Друг", + "group": "Група" + }, + "rules": { + "modes": { + "blacklist": "Режим чорного списку", + "whitelist": "Режим білого списку" + }, + "properties": { + "auto_download": { + "name": "Автоматичне завантаження", + "options": { + "blacklist": "Виключити з автоматичного завантаження", + "whitelist": "Автоматичне завантаження" + }, + "description": "Автоматично завантажувати знімки під час їх перегляду" + }, + "auto_open_snaps": { + "options": { + "blacklist": "Виключити з Auto Open Snaps", + "whitelist": "Автоматичне відкриття знімків" + }, + "name": "Автоматичне відкриття знімків", + "description": "Автоматично відкриває знімки під час їх отримання" + }, + "hide_friend_feed": { + "name": "Приховати від стрічки друзів" + }, + "e2e_encryption": { + "name": "Використовуйте шифрування E2E" + }, + "pin_conversation": { + "name": "Закріпити розмову" + }, + "auto_save": { + "description": "Зберігає повідомлення чату під час їх перегляду", + "options": { + "blacklist": "Виключити з автозбереження", + "whitelist": "Автоматичне збереження" + }, + "name": "Автоматичне збереження" + }, + "stealth": { + "options": { + "blacklist": "Виключити з прихованого режиму", + "whitelist": "Стелс режим" + }, + "name": "Режим скритності", + "description": "Запобігає тому, щоб хтось дізнався, що ви відкрили їхні знімки/чати та розмови" + }, + "unsaveable_messages": { + "description": "Запобігає збереженню повідомлень у чаті іншими людьми", + "name": "Повідомлення, які не можна зберегти", + "options": { + "whitelist": "Повідомлення, які не можна зберегти", + "blacklist": "Виключити з повідомлень, які не можна зберегти" + } + }, + "exclude_message_logger": { + "name": "Виключити з реєстратора повідомлень" + } + }, + "toasts": { + "enabled": "{ruleName} включено", + "disabled": "{ruleName} вимкнено" + } + }, + "features": { + "properties": { + "downloader": { + "properties": { + "prevent_self_auto_download": { + "name": "Запобігання самостійного автоматичного завантаження", + "description": "Запобігає автоматичному завантаженню ваших власних знімків" + }, + "path_format": { + "name": "Формат шляху", + "description": "Вкажіть формат шляху до файлу" + }, + "allow_duplicate": { + "description": "Дозволяє завантажувати одне й те саме медіа кілька разів", + "name": "Дозволити дублювання" + }, + "ffmpeg_options": { + "description": "Укажіть додаткові параметри FFmpeg", + "properties": { + "audio_bitrate": { + "name": "Бітрейт аудіо", + "description": "Встановити бітрейт аудіо (кбіт/с)" + }, + "constant_rate_factor": { + "name": "Фактор постійної ставки", + "description": "Встановіть коефіцієнт постійної швидкості для відеокодера\nВід 0 до 51 для libx264" + }, + "threads": { + "name": "Нитки", + "description": "Кількість ниток для використання" + }, + "video_bitrate": { + "description": "Встановити бітрейт відео (кбіт/с)", + "name": "Бітрейт відео" + }, + "preset": { + "name": "Попереднє налаштування", + "description": "Встановіть швидкість перетворення" + }, + "custom_video_codec": { + "description": "Встановити спеціальний відеокодек (наприклад, libx264)", + "name": "Спеціальний відеокодек" + }, + "custom_audio_codec": { + "name": "Спеціальний аудіокодек", + "description": "Встановіть спеціальний аудіокодек (наприклад, AAC)" + } + }, + "name": "Параметри FFmpeg" + }, + "save_folder": { + "description": "Виберіть каталог, куди потрібно завантажити всі медіафайли", + "name": "Зберегти папку" + }, + "force_voice_note_format": { + "name": "Примусовий формат голосової нотатки", + "description": "Примушує зберігати голосові нотатки у вказаному форматі" + }, + "download_context_menu": { + "name": "Завантажити контекстне меню", + "description": "Дозволяє завантажувати/переглядати повідомлення з бесіди чи історії за допомогою контекстного меню.\nТривале натискання кнопок призведе до примусового завантаження" + }, + "auto_download_voice_notes": { + "description": "Автоматично завантажує голосові нотатки під час їх відтворення", + "name": "Автоматичне завантаження голосових нотаток" + }, + "opera_download_button": { + "description": "Додає кнопку завантаження у верхньому правому куті під час перегляду Snap.\nТривале натискання кнопок призведе до примусового завантаження", + "name": "Кнопка завантаження Opera" + }, + "merge_overlays": { + "name": "Об’єднати накладення", + "description": "Об’єднує текст і медіафайл Snap в один файл" + }, + "force_image_format": { + "name": "Примусовий формат зображення", + "description": "Примусове збереження зображень у вказаному форматі" + }, + "auto_download_sources": { + "description": "Виберіть джерела для автоматичного завантаження", + "name": "Джерела автоматичного завантаження" + }, + "download_profile_pictures": { + "description": "Дозволяє завантажувати зображення профілю зі сторінки профілю", + "name": "Завантажте зображення профілю" + }, + "logging": { + "name": "Лісозаготівля", + "description": "Показує тости під час завантаження медіа" + }, + "custom_path_format": { + "name": "Спеціальний формат шляху", + "description": "Укажіть спеціальний формат шляху для завантажених медіа\n\nДоступні змінні:\n - %ім'я користувача%\n - %джерело%\n - %хеш%\n - %date_time%" + } + }, + "name": "Завантажувач", + "description": "Завантажте Snapchat Media" + }, + "messaging": { + "properties": { + "message_logger": { + "properties": { + "auto_purge": { + "description": "Автоматично видаляє кешовані повідомлення, які старші за вказаний період часу", + "name": "Автоматичне очищення" + }, + "message_filter": { + "name": "Фільтр повідомлень", + "description": "Виберіть, які повідомлення слід реєструвати (пусто для всіх повідомлень)" + }, + "keep_my_own_messages": { + "name": "Зберігати мої власні повідомлення", + "description": "Запобігає видаленню ваших власних повідомлень" + }, + "deleted_message_color": { + "name": "Колір видаленого повідомлення", + "description": "Встановлює колір видалених повідомлень" + } + }, + "description": "Запобігає видаленню повідомлень", + "name": "Реєстратор повідомлень" + }, + "auto_mark_as_read": { + "description": "Автоматично позначає повідомлення/знімки як прочитані, навіть якщо ввімкнено режим невидимості", + "name": "Автоматичне позначення як прочитане" + }, + "disable_replay_in_ff": { + "name": "Вимкнути відтворення в FF", + "description": "Вимикає можливість повторного відтворення за допомогою тривалого натискання зі стрічки друзів" + }, + "loop_media_playback": { + "name": "Цикл відтворення медіа", + "description": "Зациклює відтворення медіа під час перегляду знімків/історій" + }, + "hide_peek_a_peek": { + "description": "Запобігає надсиланню сповіщень, коли ви наполовину проводите пальцем у чаті", + "name": "Приховати Peek-a-Peek" + }, + "hide_bitmoji_presence": { + "name": "Приховати присутність Bitmoji", + "description": "Запобігає появі Bitmoji під час чату" + }, + "bypass_screenshot_detection": { + "name": "Обхід виявлення знімка екрана", + "description": "Запобігає Snapchat виявляти, коли ви робите знімок екрана" + }, + "half_swipe_notifier": { + "properties": { + "min_duration": { + "name": "Мінімальна тривалість", + "description": "Мінімальна тривалість напівсвайпу (у секундах)" + }, + "max_duration": { + "name": "Максимальна тривалість", + "description": "Максимальна тривалість половини свайпа (у секундах)" + } + }, + "name": "Сповіщувач згортання наполовину", + "description": "Сповіщає, коли хтось наполовину переходить у розмову" + }, + "skip_when_marking_as_seen": { + "name": "Пропустити під час позначення як побаченого", + "description": "Автоматично переходить до наступного кадру, коли знімок позначається як видимий.\nВикористовуйте разом із кнопкою «Позначити прив’язку як видиме»" + }, + "better_notifications": { + "description": "Додає більше інформації в отримані сповіщення", + "name": "Кращі сповіщення", + "properties": { + "chat_preview": { + "name": "Попередній перегляд чату", + "description": "Показує попередній перегляд отриманих повідомлень у сповіщенні" + }, + "media_preview": { + "name": "Попередній перегляд медіа", + "description": "Показує попередній перегляд вибраних типів медіа в сповіщенні" + }, + "media_caption": { + "description": "Показує вкладений заголовок медіафайлу в сповіщенні", + "name": "Медіапідпис" + }, + "mark_as_read_button": { + "name": "Кнопка «Позначити як прочитане»", + "description": "Дозволяє позначити повідомлення як прочитане зі сповіщення" + }, + "smart_replies": { + "name": "Розумні відповіді", + "description": "Додає запропоновані відповіді на сповіщення (Android 10+). Використовуйте разом із кнопкою відповіді" + }, + "group_notifications": { + "name": "Групові сповіщення", + "description": "Згрупуйте сповіщення в одне" + }, + "stacked_media_messages": { + "description": "Об’єднує кілька медіа-повідомлень в одне текстове сповіщення, якщо їх неможливо попередньо переглянути. Використовуйте в поєднанні з попереднім переглядом чату", + "name": "Складені медіа-повідомлення" + }, + "friend_add_source": { + "description": "Показує джерело запиту друга в сповіщенні", + "name": "Джерело додавання друга" + }, + "mark_as_read_and_save_in_chat": { + "name": "Позначити як прочитане та зберегти в чаті", + "description": "Додає до сповіщення позначку прочитаного та кнопку збереження в чаті" + }, + "reply_button": { + "name": "Кнопка відповіді", + "description": "До сповіщення додається кнопка відповіді" + }, + "download_button": { + "name": "Кнопка завантаження", + "description": "Дозволяє завантажувати медіа зі сповіщення" + } + } + }, + "prevent_message_sending": { + "name": "Заборонити надсилання повідомлень", + "description": "Запобігає надсиланню певних типів повідомлень" + }, + "friend_mutation_notifier": { + "description": "Повідомляє, коли щось змінюється в профілі друга", + "name": "Сповіщувач про мутацію друзів" + }, + "bypass_message_action_restrictions": { + "name": "Обійти обмеження щодо дії повідомлення", + "description": "Дозволяє реагувати на знімок, не відкриваючи його, або зберегти повідомлення, яке неможливо зберегти" + }, + "auto_save_messages_in_conversations": { + "name": "Автоматичне збереження повідомлень", + "description": "Автоматично зберігає кожне повідомлення в розмовах" + }, + "strip_media_metadata": { + "description": "Видаляє метадані медіа перед надсиланням у вигляді повідомлення", + "name": "Видалення медіа-метаданих" + }, + "bypass_message_retention_policy": { + "name": "Обхід політики збереження повідомлень", + "description": "Запобігає видаленню повідомлень після їх перегляду" + }, + "unlimited_conversation_pinning": { + "description": "Дозволяє закріплювати необмежену кількість розмов локально", + "name": "Необмежене закріплення розмов" + }, + "notification_blacklist": { + "name": "Чорний список сповіщень", + "description": "Виберіть сповіщення, які потрібно заблокувати" + }, + "gallery_media_send_override": { + "name": "Заміна надсилання медіафайлів із галереї", + "description": "Підроблює медіаджерело під час надсилання з галереї" + }, + "prevent_story_rewatch_indicator": { + "description": "Запобігає тому, щоб хтось дізнався, що ви переглянули їхню історію", + "name": "Індикатор запобігання перегляду історії" + }, + "remove_groups_locked_status": { + "name": "Видалення статусу заблокованих груп", + "description": "Дозволяє переглядати інформацію про групу після того, як вас вигнали" + }, + "hide_typing_notifications": { + "name": "Приховати сповіщення про введення", + "description": "Не дозволяє нікому знати, що ви набираєте повідомлення" + }, + "unlimited_snap_view_time": { + "name": "Необмежений час перегляду знімків", + "description": "Знімає часове обмеження для перегляду знімків" + }, + "call_start_confirmation": { + "name": "Підтвердження початку виклику", + "description": "Відображає діалогове вікно підтвердження під час виклику" + }, + "anonymous_story_viewing": { + "description": "Не дозволяє нікому знати, що ви бачили їх історію", + "name": "Анонімний перегляд історії" + }, + "mark_snap_as_seen_button": { + "name": "Кнопка «Позначити прив’язку як видиму»", + "description": "Додає кнопку для позначення Snap як видимого під час його перегляду.\nЦе працюватиме, навіть якщо ввімкнено режим Stealth" + }, + "double_tap_chat_action_custom_emoji": { + "name": "Двічі торкніться чату. Реакція власних емодзі", + "description": "Встановлює спеціальну реакцію емодзі для дії чату подвійним дотиком" + }, + "double_tap_chat_action": { + "name": "Дія чату подвійним дотиком", + "description": "Виконує спеціальну дію, коли двічі торкається повідомлення в чаті" + } + }, + "description": "Змініть спосіб спілкування з друзями", + "name": "Обмін повідомленнями" + }, + "user_interface": { + "properties": { + "custom_theme": { + "name": "Спеціальна тема", + "description": "Налаштуйте кольори Snapchat\nПримітка: якщо ви виберете темну тему (наприклад, Amoled), можливо, вам доведеться ввімкнути темний режим у налаштуваннях Snapchat для кращих результатів" + }, + "hide_ui_components": { + "name": "Приховати компоненти інтерфейсу користувача", + "description": "Виберіть, які компоненти інтерфейсу користувача приховати" + }, + "old_bitmoji_selfie": { + "name": "Старе селфі Bitmoji", + "description": "Повертає селфі Bitmoji зі старих версій Snapchat" + }, + "enable_friend_feed_menu_bar": { + "description": "Вмикає нову панель меню стрічки друзів", + "name": "Рядок меню стрічки друзів" + }, + "message_indicators": { + "name": "Індикатори повідомлень", + "description": "Додає до повідомлень спеціальні значки індикаторів \nПримітка. Індикатори можуть бути неточними на 100%" + }, + "edit_text_override": { + "name": "Редагувати перевизначення тексту", + "description": "Перевизначає поведінку текстового поля" + }, + "snap_preview": { + "name": "Попередній перегляд знімків", + "description": "Відображає невеликий попередній перегляд поруч із невидимими знімками в чаті" + }, + "bootstrap_override": { + "properties": { + "app_appearance": { + "name": "Зовнішній вигляд програми", + "description": "Встановлює постійний зовнішній вигляд програми" + }, + "home_tab": { + "description": "Перевизначає вкладку запуску під час відкриття Snapchat", + "name": "Вкладка «Домашня сторінка»" + }, + "simple_snapchat": { + "name": "Простий Snapchat", + "description": "Вмикає спрощену версію Snapchat" + } + }, + "name": "Перевизначення Bootstrap", + "description": "Замінює параметри завантаження інтерфейсу користувача" + }, + "map_friend_nametags": { + "name": "Покращені теги імен на карті друзів", + "description": "Покращує теги імен друзів на Snapmap" + }, + "streak_expiration_info": { + "description": "Показує таймер завершення смуги поряд із лічильником смуг", + "name": "Показати інформацію про закінчення серії" + }, + "hide_story_suggestions": { + "description": "Видаляє пропозиції зі сторінки «Історії»", + "name": "Приховати пропозиції історії" + }, + "prevent_message_list_auto_scroll": { + "name": "Запобігання автоматичного прокручування списку повідомлень", + "description": "Запобігає прокручування списку повідомлень униз під час надсилання/отримання повідомлення" + }, + "opera_media_quick_info": { + "description": "Показує корисну інформацію про медіа, наприклад дату створення, у контекстному меню програми перегляду Opera", + "name": "Opera Media Коротка інформація" + }, + "disable_spotlight": { + "description": "Вимикає сторінку Spotlight", + "name": "Вимкнути Spotlight" + }, + "vertical_story_viewer": { + "name": "Вертикальний переглядач історій", + "description": "Вмикає вертикальний переглядач для всіх історій" + }, + "stealth_mode_indicator": { + "name": "Індикатор режиму Stealth", + "description": "Додає 👻 emoji поруч із розмовами в прихованому режимі" + }, + "hide_friend_feed_entry": { + "description": "Приховує певного друга зі стрічки друзів\nВикористовуйте вкладку соціальних мереж, щоб керувати цією функцією", + "name": "Приховати запис стрічки друзів" + }, + "enable_app_appearance": { + "name": "Увімкніть налаштування зовнішнього вигляду програми", + "description": "Вмикає приховане налаштування зовнішнього вигляду програми\nМоже не потрібний для новіших версій Snapchat" + }, + "friend_feed_message_preview": { + "name": "Попередній перегляд повідомлень стрічки друзів", + "description": "Показує попередній перегляд останніх повідомлень у стрічці друзів", + "properties": { + "amount": { + "name": "Сума", + "description": "Кількість повідомлень для попереднього перегляду" + } + } + }, + "friend_feed_menu_buttons": { + "description": "Виберіть, які кнопки відображати в меню «Стрічка друзів»", + "name": "Кнопки меню стрічки друзів" + }, + "auto_close_friend_feed_menu": { + "name": "Автоматичне закриття меню стрічки друзів", + "description": "Автоматично закриває меню Friend Feed після натискання кнопки налаштування" + }, + "hide_quick_add_suggestions": { + "name": "Приховати пропозиції швидкого додавання", + "description": "Видаляє пропозиції щодо швидкого додавання друзів" + }, + "hide_streak_restore": { + "description": "Приховує кнопку «Відновити» у стрічці друзів", + "name": "Приховати відновлення смуги" + } + }, + "description": "Змініть зовнішній вигляд Snapchat", + "name": "Інтерфейс користувача" + }, + "global": { + "properties": { + "media_upload_quality": { + "properties": { + "custom_image_upload_format": { + "description": "Встановлює спеціальний формат завантаження зображень\nДля найкращої якості виберіть формат без втрат (наприклад, PNG)", + "name": "Спеціальний формат завантаження зображень" + }, + "force_video_upload_source_quality": { + "description": "Примушує Snapchat використовувати вихідну якість під час завантаження відео\nЗауважте, що це може не видалити метадані з медіа", + "name": "Примусове завантаження вихідної якості відео" + }, + "disable_image_compression": { + "name": "Вимкнути стиснення зображень", + "description": "Вимикає стиснення зображень під час завантаження медіа" + } + }, + "description": "Перекриває якість завантаження медіа", + "name": "Якість завантаження медіа" + }, + "disable_confirmation_dialogs": { + "description": "Автоматично підтверджує вибрані дії", + "name": "Вимкнути діалогові вікна підтвердження" + }, + "snapchat_plus": { + "name": "Snapchat Plus", + "description": "Вмикає функції Snapchat Plus\nДеякі серверні функції можуть не працювати" + }, + "better_location": { + "properties": { + "coordinates": { + "name": "Координати", + "description": "Встановіть координати підробленого місця" + }, + "walk_radius": { + "name": "Радіус ходьби", + "description": "Навмання ходити в межах цього радіусу (футів)" + }, + "suspend_location_updates": { + "name": "Призупинити оновлення місцезнаходження", + "description": "Запобігає оновленню вашого місцезнаходження" + }, + "spoof_location": { + "description": "Підмінює ваше місцезнаходження за вказане", + "name": "Локація підробки" + }, + "always_update_location": { + "name": "Завжди оновлювати місцезнаходження", + "description": "Примусово оновлювати місцезнаходження Snapchat, навіть якщо дані GPS не отримано" + }, + "spoof_battery_level": { + "description": "Підроблює рівень заряду акумулятора вашого пристрою на карті\nЗначення має бути від 0 до 100", + "name": "Підробка рівня заряду батареї" + }, + "spoof_headphones": { + "name": "Підроблені навушники", + "description": "Підробляє статус прослуховування музики на карті" + }, + "show_battery_level": { + "name": "Показати рівень заряду батареї", + "description": "Показує рівень заряду акумулятора ваших друзів на карті" + } + }, + "description": "Покращує розташування Snapchat", + "name": "Краще розташування" + }, + "block_ads": { + "name": "Блокувати рекламу", + "description": "Запобігає показу реклами" + }, + "hide_active_music": { + "name": "Приховати активну музику", + "description": "Не дозволяє Snapchat знати, що ви слухаєте музику\nЦе дозволить вам робити знімки за допомогою кнопок керування гучністю під час прослуховування музики" + }, + "auto_updater": { + "name": "Автоматичне оновлення", + "description": "Автоматично перевіряє наявність нових оновлень" + }, + "disable_custom_tabs": { + "description": "Відкриває посилання у підтримуваних програмах, а не у веб-браузері", + "name": "Вимкнути спеціальні вкладки" + }, + "disable_permission_requests": { + "name": "Вимкнути запити на дозвіл", + "description": "Запобігає запиту Snapchat конкретних дозволів" + }, + "bypass_video_length_restriction": { + "description": "Одиночне: надсилає одне відео\nРозділити: розділити відео після редагування", + "name": "Обійти обмеження щодо тривалості відео" + }, + "default_video_playback_rate": { + "description": "Встановлює стандартну швидкість для відтворення відео\nЗначення має бути від 0,1 до 4,0", + "name": "Стандартна швидкість відтворення відео" + }, + "video_playback_rate_slider": { + "name": "Повзунок швидкості відтворення відео", + "description": "Додає повзунок у контекстне меню Opera для зміни швидкості відтворення відео\nПримітка. Зміни стосуються лише наступних відео" + }, + "default_volume_controls": { + "name": "Регулятори гучності за замовчуванням", + "description": "Змушує Snapchat використовувати системні елементи керування гучністю" + }, + "disable_metrics": { + "name": "Вимкнути показники", + "description": "Блокує надсилання певних аналітичних даних до Snapchat" + }, + "disable_snap_splitting": { + "description": "Запобігає розділенню знімків на кілька частин\nНадіслані вами фотографії перетворюються на відео", + "name": "Вимкнути Snap Splitting" + }, + "disable_story_sections": { + "name": "Вимкнути розділи історії", + "description": "Видаляє розділи зі сторінки «Історії».\nДля належної роботи може знадобитися оновлення" + }, + "disable_telecom_framework": { + "name": "Вимкнути Telecom Framework", + "description": "Запобігає Snapchat використовувати структуру Android Telecom\nЦе дозволяє слухати музику під час розмови" + }, + "spotlight_comments_username": { + "name": "Ім'я користувача Spotlight Comments", + "description": "Показує ім’я користувача автора в коментарях Spotlight" + }, + "disable_google_play_dialogs": { + "name": "Вимкнути діалогові вікна служб Google Play", + "description": "Заборонити показ діалогових вікон доступності служб Google Play" + }, + "disable_memories_snap_feed": { + "description": "Запобігає Snapchat показувати останні спогади, коли ви проводите пальцем угору в камері", + "name": "Вимкнути спогади Snap Feed" + } + }, + "description": "Налаштуйте глобальні налаштування Snapchat", + "name": "Глобальний" + }, + "streaks_reminder": { + "properties": { + "interval": { + "name": "Інтервал", + "description": "Інтервал між кожним нагадуванням (годин)" + }, + "group_notifications": { + "description": "Згрупуйте сповіщення в одне", + "name": "Групові сповіщення" + }, + "remaining_hours": { + "name": "Час, що залишився", + "description": "Час, що залишився до відображення сповіщення (годин)" + } + }, + "name": "Нагадування про смуги", + "description": "Періодично сповіщає вас про ваші смуги" + }, + "camera": { + "properties": { + "override_front_resolution": { + "name": "Перевизначити передню роздільну здатність", + "description": "Замінює роздільну здатність передньої камери" + }, + "back_custom_frame_rate": { + "name": "Назад Користувацька частота кадрів", + "description": "Перевизначає частоту кадрів задньої камери" + }, + "disable_cameras": { + "description": "Забороняє Snapchat використовувати вибрані камери", + "name": "Вимкнути камери" + }, + "override_back_resolution": { + "name": "Перевизначити зворотну роздільну здатність", + "description": "Замінює роздільну здатність камери для задньої камери" + }, + "force_camera_source_encoding": { + "name": "Примусове кодування джерела камери", + "description": "Примусове кодування джерела камери" + }, + "immersive_camera_preview": { + "name": "Імерсивний попередній перегляд", + "description": "Не дозволяє Snapchat обрізати попередній перегляд камери\nЦе може призвести до мерехтіння камери на деяких пристроях" + }, + "black_photos": { + "name": "Чорні фотографії", + "description": "Замінює зроблені фотографії чорним фоном\nЦе не впливає на відео" + }, + "front_custom_frame_rate": { + "description": "Перевизначає частоту кадрів передньої камери", + "name": "Фронтальна частота кадрів" + }, + "hevc_recording": { + "name": "Запис HEVC", + "description": "Використовує кодек HEVC (H.265) для запису відео" + }, + "custom_resolution": { + "description": "Встановлює спеціальну роздільну здатність камери, ширину x висоту (наприклад, 1920x1080).\nКористувацька роздільна здатність має підтримуватися вашим пристроєм", + "name": "Спеціальна роздільна здатність" + }, + "startup_default_camera": { + "name": "Запуск камери за замовчуванням", + "description": "Встановлює камеру за умовчанням під час відкриття Snapchat" + } + }, + "name": "Камера", + "description": "Налаштуйте правильні параметри для ідеального знімка" + }, + "rules": { + "name": "Правила", + "description": "Керуйте автоматичними функціями для окремих людей" + }, + "experimental": { + "properties": { + "native_hooks": { + "description": "Небезпечні функції, які підключаються до рідного коду Snapchat", + "properties": { + "composer_hooks": { + "properties": { + "composer_logs": { + "name": "Журнали композитора", + "description": "Переспрямовує журнали консолі Composer до SnapEnhance" + }, + "show_first_created_username": { + "description": "Показує перше створене ім’я користувача поруч із поточним іменем користувача на сторінці профілю", + "name": "Показати перше створене ім'я користувача" + }, + "bypass_camera_roll_limit": { + "description": "Збільшує максимальну кількість медіафайлів, які можна надіслати з папки камери", + "name": "Обійти ліміт камери" + }, + "composer_console": { + "name": "Консоль композитора", + "description": "Дозволяє виконувати код JavaScript у Composer (лише arm64)" + } + }, + "description": "Впроваджує код у кросплатформну структуру інтерфейсу користувача Composer", + "name": "Композиторські гачки" + }, + "custom_emoji_font": { + "name": "Спеціальний шрифт Emoji", + "description": "Дозволяє використовувати спеціальний шрифт emoji. Працює лише зі шрифтами .ttf" + }, + "disable_bitmoji": { + "name": "Вимкнути Bitmoji", + "description": "Вимикає Bitmoji профілю друзів" + }, + "custom_shared_library": { + "description": "Завантажує спеціальну спільну бібліотеку в Snapchat. Ця функція призначена лише для тестування", + "name": "Спеціальна спільна бібліотека" + } + }, + "name": "Рідні гачки" + }, + "convert_message_locally": { + "description": "Перетворює знімки на локальний зовнішній носій чату. Це відображається в контекстному меню завантаження чату", + "name": "Конвертувати повідомлення локально" + }, + "edit_message": { + "description": "Дозволяє редагувати повідомлення в бесідах", + "name": "Редагувати повідомлення" + }, + "add_friend_source_spoof": { + "description": "Підроблює джерело запиту друга", + "name": "Додати друга Source Spoof" + }, + "app_lock": { + "name": "Блокування програми", + "properties": { + "lock_on_resume": { + "name": "Заблокувати резюме", + "description": "Блокує програму, коли її повторно відкривають" + } + }, + "description": "Запобігає доступу до Snapchat без пароля" + }, + "custom_streaks_expiration_format": { + "description": "Налаштовує формат терміну дії смуг\n\nДоступні змінні:\n - %c: кількість смуг\n - %e: Емодзі «Пісочний годинник».\n - %d: днів\n - %h: години\n - %m: хвилини\n - %s: Секунди\n - %w: час, що залишився", + "name": "Спеціальний формат терміну дії смуг" + }, + "spoof": { + "properties": { + "remove_vpn_transport_flag": { + "name": "Видаліть прапор транспортування VPN", + "description": "Запобігає Snapchat виявляти VPN" + }, + "fingerprint": { + "name": "Відбиток пальця пристрою", + "description": "Підробка відбитків пальців вашого пристрою" + }, + "play_store_installer_package_name": { + "name": "Назва пакета інсталятора Play Store", + "description": "Замінює назву пакета інсталятора на com.android.vending" + }, + "android_id": { + "name": "Android ID", + "description": "Підмінює ваш Android ID на вказане значення" + }, + "remove_mock_location_flag": { + "name": "Видаліть позначку фіктивного розташування", + "description": "Запобігає Snapchat виявляти фальшиве місцезнаходження" + }, + "randomize_persistent_device_token": { + "description": "Генерує випадковий маркер пристрою після кожного входу", + "name": "Рандомізуйте постійний маркер пристрою" + } + }, + "description": "Підробка різної інформації про вас", + "name": "Обман" + }, + "best_friend_pinning": { + "description": "Дозволяє закріпити друга як найкращого друга номер один. Примітка: лише ви можете бачити свого закріпленого найкращого друга", + "name": "Закріплення найкращого друга" + }, + "e2ee": { + "properties": { + "encrypted_message_indicator": { + "name": "Індикатор зашифрованого повідомлення", + "description": "Додає 🔒 emoji поруч із зашифрованими повідомленнями" + }, + "force_message_encryption": { + "description": "Запобігає надсиланню зашифрованих повідомлень людям, у яких не ввімкнено шифрування E2E, лише якщо вибрано кілька розмов", + "name": "Примусове шифрування повідомлень" + } + }, + "description": "Шифрує ваші повідомлення за допомогою AES за допомогою спільного секретного ключа\nОбов’язково зберігайте ключ у безпечному місці!", + "name": "Наскрізне шифрування" + }, + "better_transcript": { + "properties": { + "enhanced_transcript_in_notifications": { + "name": "Розширена транскрипція в сповіщеннях", + "description": "Транскрибує голосові нотатки в сповіщеннях за допомогою DeepL. Для цього в Better Notifications потрібно ввімкнути функцію попереднього перегляду чату" + }, + "force_transcription": { + "name": "Примусова транскрипція голосової нотатки", + "description": "Дозволяє транскрибувати всі голосові нотатки" + }, + "preferred_transcription_lang": { + "name": "Бажана мова транскрипції", + "description": "Бажана мова для розшифровки голосової нотатки (наприклад, EN, ES, FR)" + }, + "enhanced_transcript": { + "name": "Покращена транскрипція", + "description": "Покращує розшифровку голосових нотаток за допомогою DeepL.\nПеред використанням цієї функції переконайтеся, що ви прочитали їхню політику конфіденційності." + } + }, + "name": "Краща транскрипція", + "description": "Покращує розшифровку голосових нотаток" + }, + "infinite_story_boost": { + "name": "Нескінченна Story Boost", + "description": "Обійти затримку Story Boost Limit" + }, + "media_file_picker": { + "name": "Вибір мультимедійних файлів", + "description": "Дозволяє вибрати будь-який відео/аудіофайл із галереї" + }, + "account_switcher": { + "description": "Дозволяє перемикатися між обліковими записами без виходу з системи \nНатисніть і утримуйте значок пошуку поруч із вашим профілем Bitmoji, щоб відкрити меню \nПримітка. Ця функція є експериментальною та, ймовірно, буде змінена в майбутньому", + "properties": { + "auto_backup_current_account": { + "name": "Автоматичне резервне копіювання поточного облікового запису", + "description": "Автоматично створює резервну копію поточного облікового запису під час виходу з системи або зміни облікового запису" + } + }, + "name": "Перемикач облікових записів" + }, + "context_menu_fix": { + "name": "Виправлення контекстного меню", + "description": "Спробуйте відновити меню Friend Feed, оскільки коли пристрій не в мережі, воно не відображається належним чином" + }, + "cof_experiments": { + "name": "Експерименти COF", + "description": "Вмикає невипущені/бета-функції Snapchat" + }, + "voice_note_auto_play": { + "description": "Автоматично відтворює наступну голосову нотатку після закінчення поточної", + "name": "Автовідтворення голосової нотатки" + }, + "no_friend_score_delay": { + "name": "Немає затримки оцінки друзів", + "description": "Усуває затримку під час перегляду результатів друзів" + }, + "story_logger": { + "name": "Реєстратор історій", + "description": "Надає історію історій друзів" + }, + "call_recorder": { + "name": "Запис дзвінків", + "description": "Автоматично записує аудіодзвінки" + }, + "prevent_forced_logout": { + "description": "Запобігає виходу Snapchat під час входу на іншому пристрої", + "name": "Запобігання примусового виходу з системи" + }, + "hidden_snapchat_plus_features": { + "name": "Приховані функції Snapchat Plus", + "description": "Вмикає невипущені/бета-функції Snapchat Plus\nМоже не працювати на старіших версіях Snapchat" + }, + "friend_notes": { + "description": "Дозволяє додавати нотатки до профілів друзів", + "name": "Примітки друзів" + }, + "meo_passcode_bypass": { + "description": "Обійти пароль лише для моїх очей\nЦе спрацює, лише якщо код доступу було введено правильно раніше", + "name": "Обхід пароля лише для моїх очей" + }, + "snapscore_changes": { + "name": "Зміни Snapscore", + "description": "Відстежує зміни в Snapscore друзів\nВикористовуйте цю функцію лише в новіших версіях Snapchat" + } + }, + "description": "Експериментальні особливості", + "name": "Експериментальний" + }, + "scripting": { + "properties": { + "developer_mode": { + "name": "Режим розробника", + "description": "Показує інформацію про налагодження в інтерфейсі користувача Snapchat" + }, + "auto_reload": { + "name": "Автоматичне перезавантаження", + "description": "Автоматично перезавантажує сценарії, коли вони змінюються" + }, + "module_folder": { + "name": "Папка модуля", + "description": "Папка, в якій знаходяться сценарії" + }, + "integrated_ui": { + "name": "Інтегрований інтерфейс користувача", + "description": "Дозволяє сценаріям додавати спеціальні компоненти інтерфейсу до Snapchat" + }, + "disable_log_anonymization": { + "description": "Вимикає анонімізацію журналів", + "name": "Вимкнути анонімізацію журналу" + } + }, + "name": "Сценарії", + "description": "Запустіть власні сценарії, щоб розширити SnapEnhance" + }, + "friend_tracker": { + "properties": { + "record_messaging_events": { + "description": "Записує події обміну повідомленнями, такі як відкриття знімка, читання повідомлення тощо.", + "name": "Записуйте події обміну повідомленнями" + }, + "auto_purge": { + "description": "Автоматично видаляє кешовані події, давніші за вказаний проміжок часу", + "name": "Автоматичне очищення" + }, + "allow_running_in_background": { + "name": "Дозволити роботу у фоновому режимі", + "description": "Дозволяє трекеру працювати у фоновому режимі. Примітка. Це значно розрядить акумулятор" + } + }, + "name": "Відстеження друзів", + "description": "Записує активність друга в Snapchat" + } + }, + "notices": { + "unstable": "⚠ Нестабільний", + "ban_risk": "⚠ Ця функція може спричинити бан", + "internal_behavior": "⚠ Це може порушити внутрішню роботу Snapchat" + }, + "options": { + "notifications": { + "typing": "Введення", + "stories": "Оповідання", + "snap": "Знімок", + "speaking": "Говорячи", + "chat_reaction": "Реакція DM", + "group_chat_reaction": "Групова реакція", + "chat_screenshot": "Скріншот", + "chat_screen_record": "Запис екрана", + "snap_replay": "Повторити Знімок", + "camera_roll_save": "Зберегти фотоплівку", + "chat": "Чат", + "initiate_audio": "Вхідний аудіодзвінок", + "initiate_video": "Вхідний відеодзвінок", + "abandon_audio": "Пропущений аудіодзвінок", + "chat_reply": "Чат Відповідь", + "abandon_video": "Пропущений відеодзвінок" + }, + "auto_purge": { + "3_months": "3 Місяці", + "6_months": "6 Місяці", + "never": "Ніколи", + "3_hours": "3 години", + "1_day": "1 День", + "3_days": "3 Днів", + "1_week": "1 Тиждень", + "1_month": "1 Місяць", + "1_hour": "1 годину", + "6_hours": "6 годин", + "12_hours": "12 годин", + "2_weeks": "2 Тижнів" + }, + "path_format": { + "append_hash": "Додайте унікальний хеш до імені файлу", + "append_source": "До назви файлу додайте джерело медіа", + "append_date_time": "Додайте дату й час до імені файлу", + "create_source_folder": "Створіть папку для кожного типу медіаджерела", + "append_username": "До назви файлу додайте ім’я користувача", + "create_author_folder": "Створіть папку для кожного автора" + }, + "strip_media_metadata": { + "remove_audio_note_duration": "Видалити тривалість звукової нотатки", + "hide_extras": "Приховати додаткові елементи (наприклад, згадки)", + "hide_snap_filters": "Сховати фільтри прив’язки", + "remove_audio_note_transcript_capability": "Видалення можливості розшифровки звукової нотатки", + "hide_caption_text": "Приховати текст підпису" + }, + "hide_ui_components": { + "hide_map_reactions": "Видалити реакції карти", + "hide_billboard_prompt": "Видалити підказку Billboard у стрічці друзів", + "hide_voice_record_button": "Видалити кнопку запису голосу", + "hide_chat_call_buttons": "Видаліть кнопки виклику чату", + "hide_live_location_share_button": "Видалити кнопку прямого доступу до місцезнаходження", + "hide_unread_chat_hint": "Видалити непрочитану підказку чату", + "hide_profile_call_buttons": "Видалити кнопки виклику профілю", + "hide_post_to_story_buttons": "Видаліть кнопки «Опублікувати в історії», перш ніж надсилати знімок", + "hide_stickers_button": "Кнопка видалення наклейок", + "hide_snapchat_plus_gift_reminders": "Видаліть нагадування про подарунки Snapchat Plus у розмовах" + }, + "disable_story_sections": { + "discover": "Відкрийте для себе", + "following": "Слідую", + "friends": "Друзі", + "suggested_stories": "Запропоновані історії" + }, + "double_tap_chat_action": { + "delete_message": "Видалити повідомлення", + "copy_text": "Копіювати текст у буфер обміну", + "mark_as_read": "Позначити як прочитане", + "like_message": "Як повідомлення", + "custom_emoji_reaction": "Спеціальна реакція Emoji" + }, + "old_bitmoji_selfie": { + "2d": "2D Bitmoji", + "3d": "3D Bitmoji" + }, + "hide_story_suggestions": { + "hide_my_stories": "Сховати мої історії", + "hide_suggested_friend_stories": "Сховати запропоновані історії друзів" + }, + "friend_feed_menu_buttons": { + "unsaveable_messages": "⬇️ Повідомлення, які не можна зберегти", + "e2e_encryption": "🔒 Використовуйте шифрування E2E", + "stealth": "👻 Режим скритності", + "mark_snaps_as_seen": "👀 Позначте знімки як видимі", + "auto_save": "💬 Автоматичне збереження повідомлень", + "mark_stories_as_seen_locally": "👀 Позначити історії як видимі локально", + "auto_download": "⬇️ Автоматичне завантаження", + "conversation_info": "👤 Інформація про розмову", + "auto_open_snaps": "📷 Автоматичне відкриття знімків" + }, + "app_appearance": { + "always_light": "Завжди Світло", + "always_dark": "Завжди темно" + }, + "auto_download_sources": { + "friend_snaps": "Друг Snaps", + "friend_stories": "Історії друзів", + "public_stories": "Публічні історії", + "spotlight": "Прожектор" + }, + "add_friend_source_spoof": { + "added_by_group_chat": "Через груповий чат", + "added_by_username": "За іменем користувача", + "added_by_mention": "За згадкою", + "added_by_qr_code": "За QR-кодом", + "added_by_community": "Від спільноти", + "added_by_quick_add": "Швидким додаванням (високий ризик бути заблокованим)" + }, + "disable_permission_requests": { + "notifications": "Сповіщення", + "read_media_video": "Читайте медіа-відео", + "location": "Розташування", + "read_media_images": "Читайте медіа-зображення", + "microphone": "Мікрофон", + "camera": "Камера", + "read_contacts": "Читати контакти", + "nearby_devices": "Пристрої поблизу", + "phone_calls": "Телефонні дзвінки" + }, + "friend_mutation_notifier": { + "bitmoji_selfie_changes": "Сповіщати, коли хтось змінює своє селфі Bitmoji", + "bitmoji_scene_changes": "Сповіщати, коли хтось змінює свою сцену Bitmoji", + "birthday_changes": "Сповіщати, коли хтось змінює свій день народження", + "bitmoji_background_changes": "Сповіщати, коли хтось змінює свій фон Bitmoji", + "bitmoji_avatar_changes": "Сповіщати, коли хтось змінює свій аватар Bitmoji", + "remove_friend": "Сповіщати, коли хтось видаляє вас зі списку друзів" + }, + "custom_theme": { + "amoled_dark_mode": "Темний режим Amoled", + "custom": "Спеціальні теми (використовуйте швидкі дії для керування темами)", + "material_you_light": "Material You Світло (Android 12+)", + "material_you_dark": "Material You Темний (Android 12+)" + }, + "gallery_media_send_override": { + "ORIGINAL": "Оригінальний носій", + "SNAP": "Знімок", + "SAVEABLE_SNAP": "Знімок, який можна зберегти", + "always_ask": "Завжди запитуйте", + "NOTE": "Аудіозаписка" + }, + "disable_confirmation_dialogs": { + "ignore_friend": "Ігнорувати друга", + "hide_friend": "Приховати друга", + "block_friend": "Заблокувати друга", + "hide_conversation": "Приховати розмову", + "clear_conversation": "Очистити розмову зі стрічки друзів", + "erase_message": "Видалити повідомлення", + "remove_friend": "Видалити друга" + }, + "disable_cameras": { + "front": "Фронтальна камера", + "back": "Задня камера" + }, + "message_indicators": { + "location_indicator": "Додає піктограму 📍 до знімків, якщо їх було надіслано з увімкненим місцеположенням", + "platform_indicator": "Додає піктограму платформи, з якої було надіслано медіафайл (наприклад, Android, iOS, Web)", + "encryption_indicator": "Додає значок 🔒 поруч із повідомленнями, надісланими лише вам", + "ovf_editor_indicator": "Вказує, чи було надіслано знімок за допомогою редактора OVF", + "director_mode_indicator": "Додає піктограму ✏️ до знімків, коли їх було надіслано в режимі режисера, який можна використовувати для надсилання зображень із галереї як знімків" + }, + "edit_text_override": { + "bypass_text_input_limit": "Обійти ліміт введення тексту", + "multi_line_chat_input": "Багаторядковий ввід чату" + }, + "auto_mark_as_read": { + "snap_reply": "Відповідаючи на них, позначайте знімки як прочитані", + "conversation_read": "Позначайте бесіду як прочитану під час надсилання повідомлення" + }, + "logging": { + "success": "Успіх", + "failure": "Провал", + "started": "Розпочато", + "progress": "Прогрес" + }, + "bypass_video_length_restriction": { + "single": "Один носій", + "split": "Розділення медіа" + }, + "snapchat_plus": { + "not_subscribed": "Не підписаний", + "basic": "Базовий", + "ad_free": "Без реклами" + }, + "home_tab": { + "chat": "Чат", + "map": "Карта", + "camera": "Камера", + "discover": "Відкрийте для себе", + "spotlight": "Прожектор" + }, + "auto_reload": { + "all": "Усі (Snapchat + SnapEnhance)", + "snapchat_only": "Лише Snapchat" + }, + "simple_snapchat": { + "always_disabled": "Завжди вимкнено", + "always_enabled": "Завжди ввімкнено" + }, + "startup_default_camera": { + "front": "Фронтальна камера", + "back": "Задня камера" + } + } + }, + "actions": { + "clean_snapchat_cache": { + "name": "Очистити кеш Snapchat", + "description": "Очищає кеш Snapchat" + }, + "change_language": { + "name": "Змінити мову", + "description": "Змініть мову SnapEnhance" + }, + "manage_friend_list": { + "name": "Керувати списком друзів", + "description": "Імпорт/експорт списку друзів під час резервного копіювання" + }, + "export_chat_messages": { + "name": "Експортувати повідомлення чату", + "description": "Експортує повідомлення розмов у файл JSON/HTML/TXT" + }, + "export_memories": { + "name": "Експорт спогадів", + "description": "Експорт спогадів у файл ZIP" + }, + "file_imports": { + "name": "Імпорт файлів", + "description": "Імпорт файлів для використання в Snapchat" + }, + "friend_tracker": { + "description": "Відстежуйте своїх друзів у Snapchat", + "name": "Відстеження друзів" + }, + "logger_history": { + "name": "Історія реєстратора", + "description": "Переглянути історію зареєстрованих повідомлень" + }, + "bulk_messaging_action": { + "description": "Виконує такі операції, як видалення друзів або масове видалення розмов", + "name": "Дія масового обміну повідомленнями" + }, + "regen_mappings": { + "name": "Відновити зіставлення", + "description": "Відновити зіставлення вручну" + }, + "security_features": { + "name": "Функції безпеки", + "description": "Змінити налаштування функцій безпеки" + }, + "theming": { + "name": "Тематизація", + "description": "Налаштуйте зовнішній вигляд Snapchat" + } + }, + "half_swipe_notifier": { + "notification_content_group": "{friend} щойно наполовину перейшов до {group} на {duration} с", + "notification_channel_name": "Проведіть наполовину", + "notification_content_dm": "{friend} щойно наполовину перейшов у ваш чат на {duration} с" + }, + "download_processor": { + "failed_no_longer_available_toast": "Медіафайли більше недоступні", + "download_started_toast": "Завантаження розпочато", + "select_attachments_title": "Виберіть вкладення", + "failed_processing_toast": "Помилка обробки {error}", + "attachment_type": { + "snap": "Знімок", + "sticker": "Стікери", + "external_media": "Зовнішній носій", + "note": "Примітка", + "original_story": "Оригінальна історія", + "gif": "GIF" + }, + "dash_dialog": { + "download_all": "Завантажити всі", + "segment_text": "Відрізок {from} - {to}", + "title": "Завантажити медіадаш" + }, + "unsupported_content_type_toast": "Непідтримуваний тип вмісту!", + "dash_no_chapter": "Розділ не знайдено", + "no_attachments_toast": "Вкладень не знайдено!", + "already_downloaded_toast": "Медіа вже завантажено!", + "failed_to_create_preview_toast": "Не вдалося створити попередній перегляд", + "failed_gallery_toast": "Не вдалося зберегти в галерею {error}", + "processing_toast": "Обробка {path}...", + "failed_generic_toast": "Не вдалося завантажити", + "already_queued_toast": "ЗМІ вже в черзі!", + "content_saved_toast": "Збережено!", + "download_toast": "Завантаження {path}..." + }, + "friendship_link_type": { + "incoming_follower": "Вхідний послідовник", + "deleted": "Видалено", + "suggested": "Запропоновано", + "outgoing": "Вихідний", + "following": "Слідую", + "blocked": "Заблоковано", + "incoming": "Вхідні", + "mutual": "Взаємний" + }, + "end_to_end_encryption": { + "outgoing_secret_message": "Відповідь обміну ключами", + "incoming_pk_message": "Ви щойно отримали запит на відкритий ключ. Натисніть нижче, щоб прийняти його.", + "incoming_secret_message": "Ваш друг щойно прийняв ваш відкритий ключ. Натисніть нижче, щоб прийняти секрет.", + "encryption_failed_toast": "Не вдалося зашифрувати повідомлення! Щоб дізнатися більше, перевірте logcat.", + "toolbox": { + "no_shared_key": "У вас ще немає спільного секрету з цим другом. Натисніть нижче, щоб розпочати новий.", + "shared_key_fingerprint": "Ваш відбиток пальця:\n\n{fingerprint}\n\nПеревірте, чи збігається він з відбитком пальця вашого друга!", + "initiate_exchange_button": "Ініціювати обмін ключами" + }, + "outgoing_pk_message": "Запит на обмін ключами", + "confirmation_dialogs": { + "title": "Наскрізне шифрування", + "confirmation_1": "ПОПЕРЕДЖЕННЯ: це перезапише наявний ключ. Ви втратите доступ до всіх зашифрованих повідомлень від цього друга. Ви впевнені, що бажаєте продовжити?", + "confirmation_2": "Ви ДІЙСНО впевнені, що бажаєте продовжити? Це ваш останній шанс відступити." + }, + "native_hooks_send_failure_toast": "Не вдалося надіслати! Увімкніть Native Hooks у налаштуваннях.", + "accept_secret_key_success_toast": "Готово! Тепер ви можете надсилати та отримувати зашифровані повідомлення з цим другом.", + "accept_secret_button": "Прийняти секрет", + "unencrypted_conversation_send_failure_toast": "Ви не можете надсилати зашифрований вміст одночасно в зашифровані та незашифровані розмови!", + "no_participants_to_encrypt_toast": "У вас немає друзів у цій розмові, з якими можна шифрувати повідомлення!", + "accept_public_key_success_toast": "Відкритий ключ успішно прийнято!", + "accept_public_key_failure_toast": "Не вдалося прийняти відкритий ключ", + "accept_secret_key_failure_toast": "Не вдалося прийняти секретний ключ", + "accept_public_key_button": "Прийняти відкритий ключ" + }, + "theming_attributes": { + "sigColorTextPrimary": "Основний колір тексту", + "sigColorChatChat": "Колір тексту основної стрічки друзів", + "sigColorChatSnapWithSound": "Знімки зі звуковим кольором тексту", + "ringStartColor": "Початковий колір дзвінка", + "sigColorLayoutPlaceholder": "Колір заповнювача макета", + "recipientPillBackgroundDrawable": "Одержувач таблетки фону", + "scButtonColor": "Колір кнопки Snapchat", + "rangeFillColor": "Колір заливки діапазону", + "pstsDividerColor": "Колір розділювача PSTS", + "statusBarBackground": "Колір тла рядка стану", + "editTextColor": "Редагувати колір тексту", + "chipBackgroundColor": "Колір фону мікросхеми", + "sigColorBackgroundSurface": "Колір фонової поверхні", + "sigColorChatPendingSending": "Колір тексту каналу вторинних друзів", + "sigColorBackgroundMain": "Колір фону", + "listBackgroundDrawable": "Тло списку розмов", + "sigColorChatConversationsLine": "Колір лінії розмов", + "sigColorStoryRingDiscoverTabThumbnailStoryRing": "Історійне кільце Відкрийте вкладку Мініатюра Колір сюжетного кільця", + "boxBackgroundColor": "Колір фону коробки", + "recipientInputStyle": "Стиль введення одержувача", + "actionSheetRoundedBackgroundDrawable": "Круглий фоновий колір меню дій", + "strokeColor": "Колір обведення", + "listDivider": "Колір роздільника списку", + "sigColorIconSecondary": "Додатковий колір значка", + "pstsIndicatorColor": "Колір індикатора PSTS", + "pstsTabBackground": "Фон вкладки PSTS", + "sigColorChatSnapWithoutSound": "Знімки без звукового кольору тексту", + "actionSheetDescriptionTextColor": "Дія Меню Опис Колір тексту", + "actionSheetBackgroundDrawable": "Колір фону меню дій", + "sigColorIconPrimary": "Колір значка меню дій", + "sigExceptionColorCameraGridLines": "Колір сітки камери", + "itemShapeFillColor": "Колір заливки форми елемента", + "ringColor": "Колір кільця", + "tabTextColor": "Колір тексту вкладки", + "statusBarForeground": "Колір переднього плану рядка стану", + "storyReplayViewRingColor": "Колір кільця перегляду історії", + "sigColorButtonPrimary": "Колір основної кнопки", + "sigColorBaseAppYellow": "Базовий додаток жовтого кольору", + "sigColorBackgroundSurfaceTranslucent": "Напівпрозорий фоновий колір поверхні", + "sigColorStoryRingFriendsFeedStoryRing": "Колір кільця Story Ring Friends Feed Story Ring" + }, + "conversation_preview": { + "no_messages": "Повідомлень не знайдено!", + "streak_expiration": "закінчується через {day} днів {hour} годин {minute} хвилин", + "total_messages": "Усього надісланих/отриманих повідомлень: {count}", + "title": "Попередній перегляд", + "unknown_user": "Невідомий користувач" + }, + "bulk_messaging_action": { + "choose_action_title": "Виберіть дію", + "progress_status": "Обробка {index} із {total}", + "selection_dialog_continue_button": "Продовжити", + "confirmation_dialog": { + "message": "Це вплине на всіх вибраних друзів. Цю дію не можна скасувати.", + "title": "Ви впевнені?" + }, + "actions": { + "remove_friends": "Видалити друзів", + "clear_conversations": "Очистити розмови" + } + }, + "content_type": { + "STATUS_COUNTDOWN": "Зворотний відлік", + "FAMILY_CENTER_LEAVE": "Сімейний центр Відпустка", + "STATUS_CALL_MISSED_AUDIO": "Пропущений аудіодзвінок", + "STATUS_CALL_MISSED_VIDEO": "Пропущений відеодзвінок", + "SNAP": "Змінок", + "EXTERNAL_MEDIA": "Зовнішній носій", + "FAMILY_CENTER_ACCEPT": "Сімейний центр Прийняти", + "FAMILY_CENTER_INVITE": "Сімейний центр запрошення", + "STATUS": "Статус", + "TINY_SNAP": "Крихітний знімок", + "NOTE": "Аудіозаписка", + "STICKER": "Стікери", + "LIVE_LOCATION_SHARE": "Обмін геоданими в реальному часі", + "CHAT": "Чат", + "SHARE": "Поділіться", + "LOCATION": "Розташування", + "STATUS_SAVE_TO_CAMERA_ROLL": "Збережено в фотоплівку", + "STATUS_CONVERSATION_CAPTURE_SCREENSHOT": "Скріншот", + "STATUS_CONVERSATION_CAPTURE_RECORD": "Запис екрана", + "CREATIVE_TOOL_ITEM": "Творчий інструмент", + "STATUS_PLUS_GIFT": "Статус плюс подарунок", + "MAP_REACTION": "Реакція карти" + }, + "friend_menu_option": { + "auto_download_blacklist": "Чорний список автоматичного завантаження", + "stealth_mode": "Режим скритності", + "mark_snaps_as_seen": "Позначте знімки як видимі", + "mark_stories_as_seen_locally": "Позначити історії як видимі локально", + "anti_auto_save": "Антиавтозбереження", + "preview": "Попередній перегляд" + }, + "mark_as_seen": { + "unseen_toast": "Позначено як непереглянуте!", + "no_unseen_snaps_toast": "Невидимі знімки не знайдено!", + "seen_toast": "Позначено як бачене!", + "already_seen_toast": "Вже позначено як бачене!", + "already_unseen_toast": "Вже позначено як непереглянуте!" + }, + "opera_context_menu": { + "sent_at": "Надіслано {date}", + "media_size": "Розмір носія: {size}", + "media_duration": "Тривалість медіа: {duration} мс", + "show_debug_info": "Показати інформацію про налагодження", + "expires_at": "Термін дії закінчується {date}", + "download": "Завантажити медіа", + "created_at": "Створено {date}" + }, + "material3_strings": { + "date_input_invalid_for_pattern": "Недійсна дата", + "date_picker_today_description": "Сьогодні", + "date_range_picker_title": "Виберіть діапазон дат", + "date_range_input_invalid_range_input": "Недійсний діапазон дат", + "date_picker_switch_to_input_mode": "Введення", + "date_range_picker_scroll_to_next_month": "Наступного місяця", + "date_input_invalid_year_range": "Недійсний рік", + "date_picker_switch_to_calendar_mode": "Календар", + "date_range_picker_start_headline": "Від", + "date_range_picker_end_headline": "До", + "date_range_picker_scroll_to_previous_month": "Попередній місяць", + "date_range_picker_day_in_range": "Вибране", + "date_input_invalid_not_allowed": "Недійсна дата" + }, + "auto_open_snaps": { + "title": "Автоматичне відкриття знімків", + "notification_content": "Відкрито знімків: {count}" + }, + "friend_mutation_observer": { + "birthday_changed": "{username} змінив день народження з {oldBirthday} на {newBirthday}", + "bitmoji_background_changed": "{username} змінив фон Bitmoji", + "bitmoji_selfie_changed": "{username} змінив своє селфі Bitmoji", + "bitmoji_scene_changed": "{username} змінив сцену Bitmoji", + "birthday_removed": "{username} видалив свою дату народження ({birthday})", + "birthday_added": "{username} додав свій день народження ({birthday})", + "bitmoji_avatar_changed": "{username} змінив свій аватар Bitmoji", + "notification_channel_name": "Друг спостерігач мутації", + "friend_removed": "{username} видалив вас зі списку друзів" + }, + "send_override_dialog": { + "duration": "Тривалість: {duration}", + "unlimited_duration": "Необмежений", + "saveable_snap_hint": "Зробіть Snap доступним для збереження в чаті", + "title": "Надіслати медіа як {type}" + }, + "profile_info": { + "add_source": "Додати джерело", + "mutable_username": "Змінне ім'я користувача", + "display_name": "Відображуване ім'я", + "birthday": "День народження : {month} {day}", + "friendship": "Дружба", + "snapchat_plus_state": { + "subscribed": "Підписався", + "not_subscribed": "Не підписаний" + }, + "added_date": "Дата додавання", + "hidden_birthday": "День народження: приховано", + "snapchat_plus": "Snapchat Plus", + "title": "Інформація про профіль", + "first_created_username": "Перше створене ім'я користувача" + }, + "button": { + "ok": "OK", + "negative": "Ні", + "cancel": "Скасувати", + "send": "Надіслати", + "download": "Завантажити", + "positive": "Так", + "open": "Відкрити" + }, + "chat_export": { + "exporter_dialog": { + "amount_of_messages_title": "Кількість повідомлень (залиште поле порожнім для всіх)", + "export_file_format_title": "Формат файлу експорту", + "download_medias_title": "Завантажити медіа", + "text_field_selection": "Вибрано {amount}", + "message_type_filter_title": "Фільтрувати повідомлення за типом", + "select_conversations_title": "Виберіть Розмови", + "text_field_selection_all": "Всі" + }, + "exported_to": "Експортовано в {path}", + "no_messages_found": "Повідомлень не знайдено!", + "dialog_positive_button": "Експорт", + "export_fail": "Не вдалося експортувати бесіду {conversation}", + "finished": "Готово! Тепер ви можете закрити це діалогове вікно.", + "writing_output": "Запис вихідних даних...", + "exporting_chats": "Експорт чатів...", + "exporting_message": "Експорт {conversation}...", + "processing_chats": "Обробка {amount} розмов...", + "dialog_negative_button": "Скасувати" + }, + "chat_action_menu": { + "delete_logged_message_button": "Видалити зареєстроване повідомлення", + "show_chat_edit_history": "Показати історію редагування чату", + "preview_button": "Попередній перегляд", + "download_button": "Завантажити", + "convert_message": "Перетворити повідомлення", + "edit_message": "Редагувати повідомлення" + }, + "profile_picture_downloader": { + "button": "Завантажити зображення профілю", + "title": "Завантажувач зображень профілю", + "avatar_option": "Аватар", + "background_option": "Фон" + }, + "call_start_confirmation": { + "dialog_title": "Розпочати виклик", + "dialog_message": "Ви впевнені, що хочете почати дзвінок?" + }, + "media_download_source": { + "story_logger": "Реєстратор історій", + "spotlight": "Прожектор", + "merged": "Об'єднано", + "none": "Жодного", + "public_story": "Публічна історія", + "voice_call": "Голосовий виклик", + "chat_media": "Медіа-чат", + "pending": "В очікуванні", + "story": "Розповідь", + "profile_picture": "Фото профілю", + "message_logger": "Реєстратор повідомлень" + }, + "streaks_reminder": { + "notification_text": "Ви втратите серію з {friend} через {hoursLeft} год", + "notification_title": "Смуги" + }, + "modal_option": { + "close": "Закрити", + "profile_info": "Інформація про профіль" + }, + "gallery_media_send_override": { + "multiple_media_toast": "Ви можете надсилати лише одне медіа за раз" + }, + "better_notifications": { + "button": { + "mark_as_read": "Позначити як прочитане", + "download": "Завантажити", + "reply": "Відповісти" + } + }, + "biometric_auth": { + "unlock_button": "Розблокувати", + "subtitle": "Щоб розблокувати Snapchat, пройдіть авторизацію", + "title": "Розблокуйте Snapchat" + } +} diff --git a/common/src/main/assets/lang/ur.json b/common/src/main/assets/lang/ur.json deleted file mode 100644 index fe54df99..00000000 --- a/common/src/main/assets/lang/ur.json +++ /dev/null @@ -1,2022 +0,0 @@ -{ - "setup": { - "dialogs": { - "select_language": "زبان منتخب کریں", - "save_folder": "Purrfectsnap کو میڈیا کو ڈاؤن لوڈ کرنے اور اسنیپ چیٹ سے بچانے کے لئے اسٹوریج کی اجازت کی ضرورت ہے۔\nبراہ کرم وہ مقام منتخب کریں جہاں میڈیا کو ڈاؤن لوڈ کیا جانا چاہئے۔", - "select_save_folder_button": "فولڈر منتخب کریں" - }, - "mappings": { - "dialog": "نقشہ سازی پیدا کرنے میں ، اس میں کچھ وقت لگ سکتا ہے ...", - "generate_failure_no_snapchat": "Pirefectsnap اسنیپ چیٹ کا پتہ لگانے سے قاصر تھا ، براہ کرم اسنیپ چیٹ کو دوبارہ انسٹال کرنے کی کوشش کریں۔", - "generate_failure": "نقشہ سازی پیدا کرنے کی کوشش کرتے وقت ایک خرابی پیش آگئی ، براہ کرم دوبارہ کوشش کریں۔" - }, - "permissions": { - "dialog": "جاری رکھنے کے ل you آپ کو درج ذیل ضروریات کو فٹ کرنے کی ضرورت ہے:", - "notification_access": "اطلاع تک رسائی", - "battery_optimization": "بیٹری کی اصلاح", - "display_over_other_apps": "دوسرے ایپس پر ڈسپلے کریں", - "request_button": "درخواست" - } - }, - "scopes": { - "friend": "دوست", - "group": "گروپ" - }, - "manager": { - "routes": { - "tasks": "کام", - "features": "خصوصیات", - "manage_rule_feature": "قاعدہ کی خصوصیت کا نظم کریں", - "home": "گھر", - "home_settings": "ترتیبات", - "home_logs": "نوشتہ جات", - "logger_history": "لاگر کی تاریخ", - "logged_stories": "لاگ ان کہانیاں", - "friend_tracker": "دوست ٹریکر", - "edit_rule": "قاعدہ میں ترمیم کریں", - "file_imports": "فائل کی درآمدات", - "manage_repos": "ذخیروں کا انتظام کریں", - "social": "معاشرتی", - "manage_scope": "دائرہ کار کا انتظام کریں", - "messaging_preview": "پیش نظارہ", - "scripts": "اسکرپٹس", - "better_location": "بہتر مقام" - }, - "sections": { - "home": { - "version_title": "v__ پلیس ہولڈر_0__ · ابدی کے ذریعہ کانٹا ہوا", - "update_title": "purrfectsnap اپ ڈیٹ", - "update_content": "ورژن __ پلیس ہولڈر_0__ دستیاب ہے!", - "update_button": "ڈاؤن لوڈ", - "debug_build_summary_title": "آپ Purfectsnap کی ڈیبگ بلڈ چلا رہے ہیں", - "debug_build_summary_content": "ورژن __ پلیس ہولڈر_0__ (__ پلیس ہولڈر_1__)", - "debug_build_summary_date": "تاریخ کی تاریخ: __ پلیس ہولڈر_0__ (__ پلیس ہولڈر_1 دن پہلے)", - "quick_actions_title": "فوری اعمال", - "download_icon_description": "ڈاؤن لوڈ", - "completed_icon_description": "مکمل", - "failed_icon_description": "ناکام", - "manage_quick_actions_description": "فوری کارروائیوں کا نظم کریں", - "quick_actions_icon_description": "فوری اعمال", - "add_quick_action_description": "فوری کارروائی شامل کریں" - }, - "home_logs": { - "no_logs_hint": "کوئی نوشتہ دستیاب نہیں ہے", - "clear_logs_button": "واضح نوشتہ جات", - "export_logs_button": "نوشتہ جات برآمد کریں", - "saving_logs_toast": "لاگ ان کی بچت ، اس میں کچھ وقت لگ سکتا ہے ...", - "saved_logs_success_toast": "نوشتہ جات کامیابی کے ساتھ بچ گئے", - "saved_logs_failure_toast": "نوشتہ جات کو بچانے میں ناکام" - }, - "home_settings": { - "actions_title": "اعمال", - "message_logger_title": "میسج لاگر", - "debug_title": "ڈیبگ", - "success_toast": "کیا!", - "message_logger_summary": "__ پلیس ہولڈر_0__ پیغامات\n__ پلیس ہولڈر_1__ کہانیاں", - "export_button": "برآمد", - "clear_button": "صاف", - "view_logger_history_button": "لاگر کی تاریخ دیکھیں", - "updates_title": "تازہ کارییں", - "auto_update_check": "اپ ڈیٹس کے لئے آٹو چیک کریں", - "update_check_frequency": "تازہ کاری کی تعدد کو اپ ڈیٹ کریں", - "update_check_frequency_daily": "روزانہ", - "update_check_frequency_weekly": "ہفتہ وار", - "update_check_frequency_monthly": "ماہانہ", - "theme_icon_description": "تھیم", - "app_theme_title": "ایپ تھیم", - "theme_mode_system": "نظام", - "theme_mode_light": "روشنی", - "theme_mode_dark": "تاریک", - "ui_settings_title": "UI کی ترتیبات", - "haptic_feedback_label": "ہپٹک آراء", - "test_mode_label": "ٹیسٹ وضع (صرف ڈیبگ کرنے کے لئے)", - "disable_feature_loading_label": "فیچر لوڈنگ کو غیر فعال کریں", - "disable_auto_mapper_label": "آٹو میپر کو غیر فعال کریں", - "disable_bypass_indicator_label": "بائی پاس کی حیثیت کے اشارے کو غیر فعال کریں", - "update_notification_channel_name": "purrfectsnap اپڈیٹس", - "update_notification_channel_description": "purrfectsnap اپ ڈیٹس کے لئے اطلاعات", - "update_notification_title": "purrfectsnap اپ ڈیٹ دستیاب ہے", - "update_notification_text": "ورژن ٪ s اب دستیاب ہے۔", - "export_database_failed_toast": "ڈیٹا بیس کو برآمد کرنے میں ناکام! __ پلیس ہولڈر_0__", - "clear_messages_failed_toast": "پیغامات کو صاف کرنے میں ناکام! __ پلیس ہولڈر_0__", - "clear_file_failed_toast": "فائل کو صاف کرنے میں ناکام! __ پلیس ہولڈر_0__", - "debug_file_config": "ترتیب", - "debug_file_mappings": "میپنگز", - "debug_file_message_logger": "میسج لاگر", - "debug_file_pinned_best_friend": "بہترین دوست پن", - "debug_file_native_sig_cache": "مقامی دستخطی کیشے" - }, - "tasks": { - "no_tasks": "کوئی کام نہیں", - "merge_button": "ضم", - "failed_to_open_file": "فائل کھولنے میں ناکام", - "merge_files_toast": "__ پلیس ہولڈر_0__ فائلوں کو ضم کرنا", - "remove_selected_tasks_title": "کیا آپ واقعی منتخب کردہ کاموں کو ختم کرنا چاہتے ہیں؟", - "remove_all_tasks_title": "کیا آپ واقعی تمام کاموں کو ختم کرنا چاہتے ہیں؟", - "delete_files_option": "فائلوں کو بھی حذف کریں", - "remove_selected_tasks_confirm": "__ پلیس ہولڈر_0__ کاموں کو ہٹا دیں؟", - "remove_all_tasks_confirm": "تمام کاموں کو ہٹا دیں؟", - "clear_tasks_description": "واضح کام", - "file_not_found_icon_description": "فائل نہیں ملی", - "image_icon_description": "تصویر", - "video_icon_description": "ویڈیو", - "audio_icon_description": "آڈیو", - "file_icon_description": "فائل", - "download_icon_description": "ڈاؤن لوڈ", - "chat_action_icon_description": "چیٹ ایکشن", - "cancel_icon_description": "منسوخ کریں", - "success_icon_description": "کامیابی", - "failure_icon_description": "ناکامی", - "cancelled_icon_description": "منسوخ", - "task_status_failure": "ناکامی", - "task_status_cancelled": "منسوخ" - }, - "features": { - "disabled": "غیر فعال", - "export_option": "برآمد", - "import_option": "درآمد", - "reset_option": "ری سیٹ کریں", - "config_export_success_toast": "تشکیل کامیابی کے ساتھ برآمد ہوا", - "config_import_success_toast": "ترتیب کامیابی کے ساتھ درآمد", - "config_import_failure_toast": "کنفگ __ پلیس ہولڈر_0__ درآمد کرنے میں ناکام", - "config_export_failure_toast": "کنفگ __ پلیس ہولڈر_0__ برآمد کرنے میں ناکام", - "saved_config_snackbar": "تشکیل محفوظ", - "older_required": "اس خصوصیت کے لئے اسنیپ چیٹ v__ پلیس ہولڈر_0 یا اس سے زیادہ عمر کے لئے صحیح طریقے سے کام کرنے کی ضرورت ہے", - "newer_required": "اس خصوصیت کے لئے صحیح طریقے سے کام کرنے کے لئے اسنیپ چیٹ v__ پلیس ہولڈر_0__ یا نئی ضرورت ہے", - "search_button": "تلاش" - }, - "manage_rule_feature": { - "disable_state_option": "غیر فعال", - "disable_state_subtext": "کوئی دوست/گروپس متاثر نہیں ہوں گے", - "whitelist_state_option": "کے سوا کوئی نہیں ...", - "whitelist_state_subtext": "اس اصول سے صرف __ پلیس ہولڈر_0__ دوست/گروپس متاثر ہوں گے", - "whitelist_state_button": "اجازت شدہ دوستوں/گروپس کو منتخب کریں", - "blacklist_state_option": "سب کے سوا ...", - "blacklist_state_subtext": "__ placeholder_0__ دوستوں/گروپس کے سوا ہر ایک اس اصول سے متاثر ہوگا", - "blacklist_state_button": "خارج شدہ دوستوں/گروپس کو منتخب کریں", - "clear_list_button": "صاف دوست/گروپس کی فہرست", - "dialog_clear_confirmation_text": "کیا آپ واقعی فہرست کو صاف کرنا چاہتے ہیں؟" - }, - "social": { - "friends_tab": "دوستو", - "groups_tab": "گروپ", - "empty_hint": "(خالی)", - "streaks_expiration_short": "__ پلیس ہولڈر_0__ ایچ" - }, - "manage_scope": { - "logged_stories_button": "لاگ ان کہانیاں دکھائیں", - "e2ee_title": "اختتام سے آخر میں خفیہ کاری", - "rules_title": "قواعد", - "participants_text": "__ پلیس ہولڈر_0__ شرکاء", - "not_found": "نہیں ملا", - "streaks_title": "لکیریں", - "streaks_length_text": "لمبائی: __ پلیس ہولڈر_0__", - "streaks_expiration_text": "__ پلیس ہولڈر_0__ میں میعاد ختم ہوجاتا ہے", - "streaks_expiration_text_expired": "میعاد ختم", - "reminder_button": "یاد دہانی کریں", - "delete_scope_confirm_dialog_title": "کیا آپ واقعی __ پلیس ہولڈر_0__ کو حذف کرنا چاہتے ہیں؟", - "notes_placeholder": "نوٹ شامل کرنے کے لئے کلک کریں", - "invalid_key_size_32_bytes": "غلط کلیدی سائز (32 بائٹس کا ہونا ضروری ہے)", - "successfully_imported_key": "کامیابی کے ساتھ امپورٹڈ کلید", - "failed_to_import_key": "کلید درآمد کرنے میں ناکام: __ پلیس ہولڈر_0__", - "export_base64_button": "BASE64 برآمد کریں", - "import_base64_button": "امپورٹ بیس 64" - }, - "logged_stories": { - "story_failed_to_load": "لوڈ کرنے میں ناکام", - "no_stories": "کوئی کہانیاں نہیں ملی", - "save_from_cache_button": "کیشے سے بچائیں", - "downloaded_to_path": "__ placeholder_0__ پر ڈاؤن لوڈ کیا گیا", - "download_failed": "ڈاؤن لوڈ ناکام: __ پلیس ہولڈر_0__", - "posted_at": "__ placeholder_0__ پر پوسٹ کیا گیا", - "created_at": "__ placeholder_0__ پر تخلیق کیا گیا", - "failed_to_open_file": "فائل کھولنے میں ناکام۔ مزید معلومات کے لئے لاگز چیک کریں", - "failed_to_get_file": "فائل حاصل کرنے میں ناکام" - }, - "messaging_preview": { - "processed_messages_toast": "عملدرآمد __ پلیس ہولڈر_0__ پیغامات", - "processed_messages_text": "عملدرآمد __ پلیس ہولڈر_0__ پیغامات", - "close_button_description": "بند کریں", - "bridge_connection_failed": "پل سے رابطہ قائم کرنے میں ناکام۔ اس بات کو یقینی بنائیں کہ اسنیپ چیٹ پس منظر میں چل رہا ہے", - "bridge_init_failed": "میسجنگ برج کو شروع کرنے میں ناکام۔ اس بات کو یقینی بنائیں کہ اسنیپ چیٹ پس منظر میں چل رہا ہے", - "message_fetch_failed": "پیغامات لانے میں ناکام", - "no_message_hint": "کوئی پیغام نہیں", - "save_selection_option": "انتخاب کو بچائیں", - "save_all_option": "سب کو بچائیں", - "unsave_selection_option": "انتخاب کا انتخاب کریں", - "unsave_all_option": "سب کو غمزدہ کریں", - "mark_selection_as_seen_option": "جیسا کہ دیکھا گیا منتخب کردہ سنیپ کو نشان زد کریں", - "mark_all_as_seen_option": "جیسا کہ دیکھا گیا تمام سنیپس کو نشان زد کریں", - "delete_selection_option": "انتخاب کو حذف کریں", - "delete_all_option": "سب کو حذف کریں" - }, - "logger_history": { - "download_started_toast": "ڈاؤن لوڈ شروع!", - "download_success_toast": "__ placeholder_0__ پر ڈاؤن لوڈ کیا گیا", - "download_failed_toast": "__ پلیس ہولڈر_0 __ ڈاؤن لوڈ کرنے میں ناکام", - "edited_at_text": "__ پلیس ہولڈر_0__ (__ پلیس ہولڈر_1 میں ترمیم شدہ)", - "download_button": "ڈاؤن لوڈ", - "select_conversation_placeholder": "گفتگو کا انتخاب کریں", - "close_button_description": "بند کریں", - "search_button_description": "تلاش", - "list_friend_format": "دوست __ پلیس ہولڈر_0__", - "list_group_format": "گروپ __ پلیس ہولڈر_0__", - "no_more_messages": "مزید پیغامات نہیں", - "reverse_order_checkbox": "ریورس آرڈر", - "chat_attachment": "منسلک __ پلیس ہولڈر_0__", - "empty_message": "خالی چیٹ میسج", - "message_parse_failed": "پیغام کی تجزیہ کرنے میں ناکام", - "unknown_sender": "نامعلوم مرسل", - "download_attachment_failed_toast": "اٹیچمنٹ ڈاؤن لوڈ کرنے میں ناکام", - "log_header_format": "__ پلیس ہولڈر_0__ (__ پلیس ہولڈر_1__) - __ پلیس ہولڈر_2__" - }, - "file_imports": { - "import_file_button": "فائل درآمد کریں", - "file_not_found": "فائل نہیں ملی", - "file_import_failed": "فائل درآمد کرنے میں ناکام: __ پلیس ہولڈر_0__", - "file_imported": "فائل کو کامیابی کے ساتھ درآمد کیا گیا", - "file_delete_failed": "فائل کو حذف کرنے میں ناکام", - "no_files_hint": "یہاں آپ اسنیپ چیٹ میں استعمال کے لئے فائلیں درآمد کرسکتے ہیں۔ فائل کو درآمد کرنے کے لئے نیچے دیئے گئے بٹن کو دبائیں۔" - }, - "better_location": { - "spoofed_coordinates_title": "لیٹ __ پلیس ہولڈر_0__ ، lng __ پلیس ہولڈر_1__", - "save_coordinates_dialog_title": "کوآرڈینیٹ کو بچائیں", - "saved_name_dialog_hint": "محفوظ نام", - "latitude_dialog_hint": "عرض البلد", - "longitude_dialog_hint": "طول البلد", - "save_dialog_button": "بچت کریں", - "choose_location_button": "مقام کا انتخاب کریں", - "teleport_to_friend_button": "دوست کو ٹیلی پورٹ", - "spoof_location_toggle": "اسپوف مقام", - "suspend_location_updates": "مقام کی تازہ کاریوں کو معطل کریں", - "saved_coordinates_title": "محفوظ شدہ نقاط", - "no_saved_coordinates_hint": "کوئی بچت کوآرڈینیٹ نہیں", - "delete_dialog_title": "محفوظ کردہ کوآرڈینیٹ کو حذف کریں", - "delete_dialog_message": "کیا آپ واقعی اس محفوظ کردہ کوآرڈینیٹ کو حذف کرنا چاہتے ہیں؟", - "teleport_to_friend_title": "دوست کو ٹیلی پورٹ", - "search_bar": "تلاش", - "no_friends_map": "نقشے پر کوئی دوست نہیں", - "no_friends_found": "کوئی دوست نہیں ملا", - "edit_location_button_description": "مقام میں ترمیم کریں", - "add_icon_description": "شامل کریں", - "edit_icon_description": "ترمیم کریں", - "delete_icon_description": "حذف کریں" - } - }, - "dialogs": { - "add_friend": { - "title": "دوست یا گروپ شامل کریں", - "search_hint": "تلاش", - "fetch_error": "ڈیٹا لانے میں ناکام", - "category_groups": "گروپ", - "category_friends": "دوستو", - "participants_text": "__ پلیس ہولڈر_0__ شرکاء", - "search_icon_description": "تلاش" - }, - "scripting_warning": { - "title": "انتباہ", - "content": "pirefectsnap میں ایک اسکرپٹنگ ٹول شامل ہوتا ہے ، جس سے آپ کے آلے پر صارف کے بیان کردہ کوڈ پر عمل درآمد ہوتا ہے۔ انتہائی احتیاط کا استعمال کریں اور معروف ، قابل اعتماد ذرائع سے صرف ماڈیول انسٹال کریں۔ غیر مجاز یا غیر تصدیق شدہ ماڈیول آپ کے سسٹم میں سیکیورٹی کے خطرات پیدا کرسکتے ہیں۔" - }, - "reset_config": { - "title": "کنفیگ کو دوبارہ ترتیب دیں", - "content": "کیا آپ کو یقین ہے کہ آپ کنفیگ کو دوبارہ ترتیب دینا چاہتے ہیں؟", - "success_toast": "کامیابی کے ساتھ دوبارہ ترتیب دیں" - }, - "export_config": { - "title": "حساس ڈیٹا برآمد کریں؟", - "content": "کیا آپ حساس اعداد و شمار کے ساتھ تشکیل برآمد کرنا چاہتے ہیں؟ (جیسے مقام کوآرڈینیٹ وغیرہ)" - }, - "messaging_action": { - "title": "عمل کے ل content مواد کی اقسام کا انتخاب کریں", - "select_all_button": "سب کو منتخب کریں" - }, - "file_imports": { - "no_files_settings_hint": "کوئی فائلیں نہیں ملی۔ اس بات کو یقینی بنائیں کہ آپ نے فائل امپورٹ سیکشن میں مطلوبہ فائلوں کو درآمد کیا ہے", - "settings_select_file_hint": "ایک درآمد شدہ فائل منتخب کریں" - }, - "quick_actions_dialog": { - "title": "فوری کارروائیوں میں ترمیم کریں", - "subtitle": "اپنے تیز عمل کو منتخب کریں اور ان کا سائز بنائیں۔" - } - }, - "friend_tracker": { - "rules_tab": "قواعد", - "logs_tab": "نوشتہ جات", - "export_dialog_title": "برآمد", - "bulk_export_button": "بلک برآمد", - "individual_export_button": "انفرادی برآمد", - "invalid_import_type_dialog_title": "غلط درآمد کی قسم", - "invalid_import_type_dialog_text": "منتخب فائل اس درآمد کی قسم کے ساتھ مطابقت نہیں رکھتی ہے۔ براہ کرم درست درآمد کی قسم منتخب کریں۔", - "import_dialog_title": "درآمد", - "bulk_import_button": "بلک درآمد", - "individual_import_button": "انفرادی درآمد", - "import_button_description": "درآمد", - "export_button_description": "برآمد", - "export_button": "برآمد", - "delete_button_description": "حذف کریں", - "delete_button": "حذف کریں", - "catalog_button_description": "کیٹلاگ", - "catalog_button": "کیٹلاگ", - "add_rule_button_description": "قاعدہ شامل کریں", - "add_rule_button": "قاعدہ شامل کریں", - "no_rules_found": "کوئی قواعد نہیں ملے", - "empty_rule_name": "(خالی)", - "events_suffix": "واقعات", - "scopes_suffix": "اسکوپس", - "select_rule_to_export_title": "برآمد کرنے کے لئے قاعدہ منتخب کریں", - "deleted_logs_toast": "حذف شدہ __ پلیس ہولڈر_0__ لاگز", - "delete_logs_dialog_title": "نوشتہ جات کو حذف کریں؟", - "deleting_logs_dialog_text": "__ پلیس ہولڈر_0__ لاگز کو حذف کرنا ...", - "delete_logs_dialog_confirm_text": "یہ موجودہ فلٹر اور تلاش کے استفسار کی بنیاد پر لاگ کو حذف کردے گا۔ اس عمل کو ختم نہیں کیا جاسکتا۔", - "exported_logs_toast": "برآمد شدہ لاگز!", - "export_logs_failed_toast": "نوشتہ جات برآمد کرنے میں ناکام۔ مزید تفصیلات کے لئے لاگ کیٹ چیک کریں۔", - "export_logs_dialog_title": "برآمد لاگ؟", - "exporting_logs_dialog_text": "نوشتہ جات برآمد ...", - "export_logs_dialog_confirm_text": "یہ موجودہ فلٹر اور تلاش کے استفسار کی بنیاد پر لاگ ان برآمد کرے گا۔", - "export_as_button": "__ placeholder_0__ کے طور پر برآمد کریں", - "filters_title": "فلٹرز", - "search_by_label": "بذریعہ تلاش کریں", - "newest_first_label": "سب سے پہلے", - "since_label": "چونکہ", - "until_label": "جب تک", - "pick_a_date_button": "ایک تاریخ منتخب کریں", - "search_placeholder": "تلاش", - "filter_button_description": "فلٹر", - "clear_button_description": "صاف", - "no_logs_found": "کوئی نوشتہ نہیں ملا", - "log_event_format": "__ پلیس ہولڈر_0 __ میں __ پلیسولڈر_1__", - "condition_only_inside_conversation": "صرف اس وقت جب میں گفتگو کے اندر ہوں", - "condition_only_outside_conversation": "صرف اس وقت جب میں بات چیت سے باہر ہوں", - "condition_only_when_app_active": "صرف اس وقت جب اسنیپ چیٹ فعال ہو", - "condition_only_when_app_inactive": "صرف اس وقت جب اسنیپ چیٹ غیر فعال ہو", - "condition_no_push_notification_when_app_active": "جب اسنیپ چیٹ فعال ہوتا ہے تو کوئی اطلاع نہیں ہے", - "add_event_dialog_title": "واقعہ شامل کریں", - "event_type_label": "واقعہ کی قسم", - "triggers_title": "محرکات", - "conditions_title": "شرائط", - "add_button": "شامل کریں", - "default_rule_name": "کسٹم رول", - "discard_changes_dialog_title": "تبدیلیوں کو ضائع کریں؟", - "discard_changes_dialog_text": "آپ کی غیر محفوظ تبدیلیاں ہیں۔ کیا آپ واقعی ان کو ضائع کرنا چاہتے ہیں؟", - "discard_button": "خارج کردیں", - "cannot_save_rule_dialog_title": "حکمرانی کو نہیں بچا سکتا", - "cannot_save_rule_dialog_text": "ایک قاعدہ میں کم از کم ایک واقعہ بچانے کے لئے ہونا ضروری ہے۔", - "duplicate_rule_name_dialog_title": "ڈپلیکیٹ رول کا نام", - "duplicate_rule_name_dialog_text": "اس نام کے ساتھ ایک اصول پہلے سے موجود ہے۔ براہ کرم ایک مختلف نام منتخب کریں۔", - "delete_rule_dialog_title": "قاعدہ کو حذف کریں", - "delete_rule_dialog_text": "کیا آپ واقعی اس اصول کو حذف کرنا چاہتے ہیں؟", - "new_rule_title": "نیا قاعدہ", - "edit_rule_title": "قاعدہ میں ترمیم کریں", - "back_button_description": "واپس", - "save_button_description": "بچت کریں", - "general_section_title": "جنرل", - "rule_name_label": "قاعدہ کا نام", - "author_name_label": "مصنف کا نام", - "scope_section_title": "دائرہ کار", - "scope_all": "سب", - "scope_whitelist": "وائٹ لسٹ", - "scope_blacklist": "بلیک لسٹ", - "select_friends_groups_button": "دوست/گروپس منتخب کریں (__ پلیس ہولڈر_0__)", - "events_section_title": "واقعات", - "add_event_button": "واقعہ شامل کریں", - "no_events_text": "کوئی واقعات نہیں" - }, - "friend_tracker_catalog": { - "download_failed": "ناکام ڈاؤن لوڈ: __ پلیس ہولڈر_0__", - "error": "غلطی: __ پلیس ہولڈر_0__", - "no_repos_added": "کوئی ذخیرے شامل نہیں کیا گیا۔", - "no_rules_available": "کسی بھی ریپو سے کوئی قواعد دستیاب نہیں ہیں۔", - "by_author": "بذریعہ __ پلیس ہولڈر_0__", - "imported_button": "درآمد", - "import_button": "درآمد", - "title": "دوست ٹریکر کیٹلاگ", - "manage_repos_description": "ذخیروں کا نظم کریں" - }, - "friend_tracker_export": { - "title": "برآمد کے قواعد", - "back_button_description": "واپس", - "exported_toast": "فرینڈ ٹریکر کے قواعد برآمد ہوئے!", - "export_failed_toast": "قواعد برآمد کرنے میں ناکام: __ پلیس ہولڈر_0__", - "save_button": "بچت کریں", - "expand_button_description": "توسیع" - }, - "friend_tracker_import": { - "title": "درآمد کے قواعد", - "back_button_description": "واپس", - "imported_toast": "دوست ٹریکر کے قواعد درآمد!", - "import_failed_toast": "قواعد درآمد کرنے میں ناکام: __ پلیس ہولڈر_0__", - "confirm_button": "تصدیق کریں", - "expand_button_description": "توسیع" - }, - "friend_tracker_repos": { - "invalid_repo_title": "غلط ذخیرہ", - "add_repo_button": "ذخیرہ شامل کریں", - "add_repo_dialog_title": "ذخیرہ یو آر ایل شامل کریں", - "repo_url_label": "ذخیرہ یو آر ایل", - "repo_added_toast": "ذخیرہ کامیابی کے ساتھ شامل کیا گیا!", - "invalid_repo_error": "ایسا نہیں لگتا ہے کہ یہ ایک درست دوست ٹریکر ذخیرہ ہے۔", - "add_repo_failed_toast": "ذخیرہ شامل کرنے میں ناکام: __ پلیس ہولڈر_0__", - "add_button": "شامل کریں", - "no_repos_added": "کوئی ذخیرے شامل نہیں کیا گیا", - "remove_button": "ہٹا دیں", - "remove_repo_dialog_title": "ذخیرہ کو ہٹا دیں", - "remove_repo_dialog_text": "کیا آپ واقعی اس ذخیرے کو ختم کرنا چاہتے ہیں؟" - }, - "navigation": { - "tracker_tab_label": "ٹریکر", - "customize_bottom_bar_title": "نیچے بار کو اپنی مرضی کے مطابق بنائیں", - "customize_bottom_bar_subtitle": "ٹیبز کو دوبارہ ترتیب دیں ، شامل کریں یا ہٹائیں۔ زیادہ سے زیادہ پانچ", - "shown_tabs_title": "ٹیبز دکھائے گئے", - "no_tabs_selected_text": "کوئی ٹیب منتخب نہیں کیا گیا", - "available_tabs_title": "دستیاب ٹیبز", - "reset_button": "ری سیٹ کریں", - "done_button": "کیا" - }, - "scripting": { - "script_already_installed": "اسکرپٹ پہلے ہی انسٹال ہے!", - "downloading_script": "اسکرپٹ ڈاؤن لوڈ کرنا ...", - "script_downloaded": "اسکرپٹ __ پلیس ہولڈر_0__ ڈاؤن لوڈ!", - "download_script_failed": "اسکرپٹ ڈاؤن لوڈ کرنے میں ناکام۔ مزید تفصیلات کے لئے لاگ ان چیک کریں", - "import_script_from_url_title": "URL سے اسکرپٹ درآمد کریں", - "import_script_warning": "انتباہ: درآمد شدہ اسکرپٹس آپ کے آلے کے لئے نقصان دہ ثابت ہوسکتی ہیں۔ صرف قابل اعتماد ذرائع سے اسکرپٹ درآمد کریں۔", - "enter_url_label": "یہاں URL درج کریں:", - "script_imported": "اسکرپٹ __ پلیس ہولڈر_0__ درآمد!", - "import_failed": "اسکرپٹ درآمد کرنے میں ناکام۔ __ پلیس ہولڈر_0__۔ مزید تفصیلات کے لئے لاگ ان چیک کریں", - "import_button": "درآمد", - "update_module_button": "ماڈیول کو اپ ڈیٹ کریں", - "updating_script": "اسکرپٹ کو اپ ڈیٹ کرنا __ پلیس ہولڈر_0 __...", - "module_not_found": "ماڈیول نہیں ملا", - "updated_script": "__ پلیس ہولڈر_0 __ ورژن __ پلیس ہولڈر_1__ میں تازہ کاری کی گئی", - "update_module_failed": "ماڈیول کو اپ ڈیٹ کرنے میں ناکام۔ مزید تفصیلات کے لئے لاگ ان چیک کریں", - "edit_module_button": "ماڈیول میں ترمیم کریں", - "open_module_failed": "ماڈیول فائل کھولنے میں ناکام۔ مزید تفصیلات کے لئے لاگ ان چیک کریں", - "clear_module_data_button": "ماڈیول کا ڈیٹا صاف کریں", - "module_data_cleared": "ماڈیول ڈیٹا صاف!", - "clear_module_data_failed": "ماڈیول ڈیٹا کو صاف کرنے میں ناکام۔ مزید تفصیلات کے لئے لاگ ان چیک کریں", - "delete_module_button": "ماڈیول کو حذف کریں", - "deleted_script": "حذف شدہ اسکرپٹ __ پلیس ہولڈر_0__!", - "delete_module_failed": "ماڈیول کو حذف کرنے میں ناکام۔ مزید تفصیلات کے لئے لاگ ان چیک کریں", - "actions_title": "اعمال", - "no_description": "کوئی تفصیل نہیں", - "update_available": "تازہ کاری دستیاب: __ پلیس ہولڈر_0__", - "actions_button": "اعمال", - "loaded_script": "بھری ہوئی اسکرپٹ __ پلیس ہولڈر_0__", - "unloaded_script": "غیر لوڈ شدہ اسکرپٹ __ پلیس ہولڈر_0__", - "enable_script_failed": "اسکرپٹ کو قابل بنانے میں ناکام۔ مزید تفصیلات کے لئے لاگ ان چیک کریں", - "disable_script_failed": "اسکرپٹ کو غیر فعال کرنے میں ناکام۔ مزید تفصیلات کے لئے لاگ ان چیک کریں", - "select_scripts_folder_toast": "براہ کرم اپنے اسکرپٹ فولڈر کو منتخب کریں!", - "manage_repos_button": "ریپوز کا انتظام کریں", - "import_from_url_button": "یو آر ایل سے درآمد کریں", - "open_scripts_folder_button": "اسکرپٹ فولڈر کھولیں", - "no_settings_for_module": "اس ماڈیول میں کوئی ترتیب نہیں ہے", - "installed_scripts_tab": "نصب اسکرپٹ", - "catalog_tab": "کیٹلاگ", - "no_scripts_folder_selected_title": "کوئی اسکرپٹ فولڈر منتخب نہیں ہوا", - "select_folder_button": "فولڈر منتخب کریں", - "no_scripts_found_title": "کوئی اسکرپٹ نہیں ملا۔", - "use_catalog_to_add_scripts": "اسکرپٹ شامل کرنے کے لئے کیٹلاگ ٹیب کا استعمال کریں!", - "ok_button_timeout": "ٹھیک ہے (__ پلیس ہولڈر_0__)", - "documentation_button": "دستاویزات", - "catalog": { - "script_already_installed": "اسکرپٹ پہلے ہی انسٹال ہے!", - "download_failed": "ناکام ڈاؤن لوڈ: __ پلیس ہولڈر_0__", - "script_downloaded": "اسکرپٹ ڈاؤن لوڈ!", - "could_not_create_file": "فائل نہیں بناسکا۔", - "no_scripts_folder_selected": "کوئی اسکرپٹ فولڈر منتخب نہیں ہوا۔", - "error": "غلطی: __ پلیس ہولڈر_0__", - "no_repos_added": "کوئی ذخیرے شامل نہیں کیا گیا۔", - "repo_list_info": "یہاں آپ کو ریپوز کی ایک فہرست مل سکتی ہے:", - "link_text": "لنک", - "no_scripts_available": "کسی بھی ریپو سے کوئی اسکرپٹ دستیاب نہیں ہے۔", - "by_author": "بذریعہ __ placeholder_0__", - "version": "ورژن: __ پلیس ہولڈر_0__", - "installed_button": "انسٹال", - "download_button": "ڈاؤن لوڈ" - }, - "repos": { - "invalid_repo_title": "غلط ذخیرہ", - "add_repo_button": "ذخیرہ شامل کریں", - "add_repo_dialog_title": "ذخیرہ یو آر ایل شامل کریں", - "repo_url_label": "ذخیرہ یو آر ایل", - "repo_added_toast": "ذخیرہ کامیابی کے ساتھ شامل کیا گیا!", - "invalid_repo_error": "یہ ایک درست اسکرپٹ ذخیرہ نہیں ہے۔", - "add_repo_failed_toast": "ذخیرہ شامل کرنے میں ناکام: __ پلیس ہولڈر_0__", - "add_button": "شامل کریں", - "no_repos_added": "کوئی ذخیرے شامل نہیں کیا گیا", - "remove_button": "ہٹا دیں", - "remove_repo_dialog_title": "ذخیرہ کو ہٹا دیں", - "remove_repo_dialog_text": "کیا آپ واقعی اس ذخیرے کو ختم کرنا چاہتے ہیں؟" - } - }, - "features": { - "config_import": { - "title": "درآمد کی تصدیق کریں", - "back_button_description": "واپس", - "config_imported_toast": "تشکیل درآمد!", - "confirm_button": "تصدیق کریں", - "expand_button_description": "توسیع", - "enable_feature": "خصوصیت کو فعال کریں", - "enabled": "فعال", - "disabled": "غیر فعال" - }, - "config_export": { - "title": "برآمد کا خلاصہ", - "back_button_description": "واپس", - "save_button": "بچت کریں", - "expand_button_description": "توسیع", - "enable_feature": "خصوصیت کو فعال کریں", - "enabled": "فعال", - "disabled": "غیر فعال" - } - }, - "manage_repos": { - "title": "__ پلیس ہولڈر_0__ ذخیروں کا نظم کریں", - "add_repo_button": "ذخیرہ شامل کریں", - "add_repo_dialog_title": "ذخیرہ یو آر ایل شامل کریں", - "repo_url_label": "ذخیرہ یو آر ایل", - "repo_added_successfully": "ذخیرہ کامیابی کے ساتھ شامل کیا گیا!", - "add_repo_failed": "ذخیرہ شامل کرنے میں ناکام: __ پلیس ہولڈر_0__", - "add_button": "شامل کریں", - "no_repos_added": "کوئی ذخیرے شامل نہیں کیا گیا", - "remove_button": "ہٹا دیں" - } - }, - "rules": { - "toasts": { - "enabled": "__ پلیس ہولڈر_0__ فعال", - "disabled": "__ پلیس ہولڈر_0__ غیر فعال" - }, - "modes": { - "blacklist": "بلیک لسٹ وضع", - "whitelist": "وائٹ لسٹ وضع" - }, - "properties": { - "auto_download": { - "name": "آٹو ڈاؤن لوڈ", - "description": "جب ان کو دیکھتے ہو تو خود بخود ڈاؤن لوڈ کریں", - "options": { - "blacklist": "آٹو ڈاؤن لوڈ سے خارج", - "whitelist": "آٹو ڈاؤن لوڈ" - } - }, - "stealth": { - "name": "اسٹیلتھ موڈ", - "description": "کسی کو بھی یہ جاننے سے روکتا ہے کہ آپ نے ان کے سنیپ/چیٹس اور گفتگو کو کھول دیا ہے", - "options": { - "blacklist": "اسٹیلتھ موڈ سے خارج کریں", - "whitelist": "اسٹیلتھ موڈ" - } - }, - "auto_save": { - "name": "آٹو بچت", - "description": "چیٹ پیغامات کو دیکھتے وقت انہیں بچاتا ہے", - "options": { - "blacklist": "آٹو سیو سے خارج کریں", - "whitelist": "آٹو بچت" - } - }, - "unsaveable_messages": { - "name": "ناقابل قابل پیغامات", - "description": "دوسرے لوگوں کے ذریعہ چیٹ میں محفوظ ہونے سے پیغامات کو روکتا ہے", - "options": { - "blacklist": "ناقابل قابل پیغامات سے خارج کریں", - "whitelist": "ناقابل قابل پیغامات" - } - }, - "auto_open_snaps": { - "name": "آٹو اوپن سنیپس", - "description": "جب ان کو وصول کرتے ہو تو خود بخود اسنیپ کھول دیتے ہیں", - "options": { - "blacklist": "آٹو اوپن سنیپس سے خارج کریں", - "whitelist": "آٹو اوپن سنیپس" - } - }, - "hide_friend_feed": { - "name": "فرینڈ فیڈ سے چھپائیں" - }, - "e2e_encryption": { - "name": "E2E انکرپشن استعمال کریں" - }, - "pin_conversation": { - "name": "پن گفتگو" - }, - "exclude_message_logger": { - "name": "میسج لاگر سے خارج کریں" - } - } - }, - "actions": { - "clean_snapchat_cache": { - "name": "صاف سنیپ چیٹ کیشے", - "description": "اسنیپ چیٹ کیشے کو صاف کرتا ہے" - }, - "manage_friend_list": { - "name": "فرینڈ لسٹ کا نظم کریں", - "description": "بیک اپ کرتے وقت اپنے دوستوں کی فہرست درآمد/برآمد کریں" - }, - "export_chat_messages": { - "name": "چیٹ پیغامات برآمد کریں", - "description": "گفتگو کے پیغامات کو JSON/HTML/TXT فائل میں برآمد کرتا ہے" - }, - "export_memories": { - "name": "برآمد یادیں", - "description": "یادوں کو زپ فائل میں برآمد کرتا ہے" - }, - "bulk_messaging_action": { - "name": "بلک میسجنگ ایکشن", - "description": "دوستوں کو حذف کرنا یا گفتگو کو بڑے پیمانے پر حذف کرنا جیسے کام انجام دیتا ہے" - }, - "regen_mappings": { - "name": "نقشہ سازی کو دوبارہ تخلیق کریں", - "description": "دستی طور پر نقشہ سازی کو دوبارہ تخلیق کریں" - }, - "change_language": { - "name": "زبان کو تبدیل کریں", - "description": "purrfectsnap کی زبان کو تبدیل کریں" - }, - "file_imports": { - "name": "فائل کی درآمدات", - "description": "اسنیپ چیٹ میں استعمال کے لئے فائلیں درآمد کریں" - }, - "friend_tracker": { - "name": "دوست ٹریکر", - "description": "اپنے دوستوں کو اسنیپ چیٹ پر ٹریک کریں" - }, - "logger_history": { - "name": "لاگر کی تاریخ", - "description": "لاگ ان پیغامات کی تاریخ دیکھیں" - } - }, - "features": { - "notices": { - "unstable": "⚠ غیر مستحکم", - "ban_risk": "⚠ اس خصوصیت پر پابندی کا سبب بن سکتا ہے", - "internal_behavior": "⚠ اس سے اسنیپ چیٹ داخلی طرز عمل کو توڑ سکتا ہے" - }, - "properties": { - "downloader": { - "name": "ڈاؤن لوڈر", - "description": "اسنیپ چیٹ میڈیا ڈاؤن لوڈ کریں", - "properties": { - "save_folder": { - "name": "فولڈر کو محفوظ کریں", - "description": "اس ڈائریکٹری کو منتخب کریں جس پر تمام میڈیا کو ڈاؤن لوڈ کیا جانا چاہئے" - }, - "auto_download_sources": { - "name": "آٹو ڈاؤن لوڈ کے ذرائع", - "description": "خود بخود ڈاؤن لوڈ کرنے کے لئے ذرائع کو منتخب کریں" - }, - "prevent_self_auto_download": { - "name": "خود آٹو ڈاؤن لوڈ کو روکیں", - "description": "آپ کے اپنے سنیپ کو خود بخود ڈاؤن لوڈ کرنے سے روکتا ہے" - }, - "path_format": { - "name": "راستہ کی شکل", - "description": "فائل پاتھ فارمیٹ کی وضاحت کریں" - }, - "allow_duplicate": { - "name": "ڈپلیکیٹ کی اجازت دیں", - "description": "ایک ہی میڈیا کو متعدد بار ڈاؤن لوڈ کرنے کی اجازت دیتا ہے" - }, - "merge_overlays": { - "name": "اوورلیز کو ضم کریں", - "description": "ایک فائل میں متن اور میڈیا کو سنیپ کے ساتھ جوڑتا ہے" - }, - "force_image_format": { - "name": "فورس امیج فارمیٹ", - "description": "ایک مخصوص شکل میں تصاویر کو محفوظ کرنے کی مجبور کرتا ہے" - }, - "force_voice_note_format": { - "name": "فورس وائس نوٹ فارمیٹ", - "description": "فورسز وائس نوٹ کو ایک مخصوص شکل میں محفوظ کیا جائے" - }, - "auto_download_voice_notes": { - "name": "آٹو ڈاؤن لوڈ وائس نوٹس", - "description": "وائس نوٹس کو خود بخود ڈاؤن لوڈ کرتا ہے" - }, - "download_profile_pictures": { - "name": "پروفائل کی تصاویر ڈاؤن لوڈ کریں", - "description": "آپ کو پروفائل پیج سے پروفائل کی تصاویر ڈاؤن لوڈ کرنے کی اجازت دیتا ہے" - }, - "opera_download_button": { - "name": "اوپیرا ڈاؤن لوڈ کا بٹن", - "description": "سنیپ دیکھتے وقت اوپر دائیں کونے پر ڈاؤن لوڈ کا بٹن شامل کرتا ہے۔\nبٹنوں پر لمبی پریس ڈاؤن لوڈ کو مجبور کرے گی" - }, - "download_context_menu": { - "name": "سیاق و سباق کا مینو ڈاؤن لوڈ کریں", - "description": "آپ کو سیاق و سباق کے مینو کا استعمال کرتے ہوئے گفتگو یا کہانی سے پیغامات ڈاؤن لوڈ/پیش نظارہ کرنے کی اجازت دیتا ہے۔\nبٹنوں پر لمبی پریس ڈاؤن لوڈ کو مجبور کرے گی" - }, - "ffmpeg_options": { - "name": "FFMPEG اختیارات", - "description": "اضافی FFMPEG اختیارات کی وضاحت کریں", - "properties": { - "threads": { - "name": "دھاگے", - "description": "استعمال کرنے کے لئے دھاگوں کی مقدار" - }, - "preset": { - "name": "پیش سیٹ", - "description": "تبادلوں کی رفتار طے کریں" - }, - "constant_rate_factor": { - "name": "مستقل شرح عنصر", - "description": "ویڈیو انکوڈر کے لئے مستقل شرح عنصر مرتب کریں\nlibx264 کے لئے 0 سے 51 تک" - }, - "video_bitrate": { - "name": "ویڈیو بٹریٹ", - "description": "ویڈیو بٹریٹ (کے بی پی ایس) سیٹ کریں" - }, - "audio_bitrate": { - "name": "آڈیو بٹریٹ", - "description": "آڈیو بٹریٹ (کے بی پی ایس) سیٹ کریں" - }, - "custom_video_codec": { - "name": "کسٹم ویڈیو کوڈیک", - "description": "ایک کسٹم ویڈیو کوڈیک مرتب کریں (جیسے LIBX264)" - }, - "custom_audio_codec": { - "name": "کسٹم آڈیو کوڈیک", - "description": "کسٹم آڈیو کوڈیک (جیسے AAC) مرتب کریں" - } - } - }, - "logging": { - "name": "لاگنگ", - "description": "جب میڈیا ڈاؤن لوڈ ہو رہا ہے تو ٹوسٹ دکھاتا ہے" - }, - "custom_path_format": { - "name": "کسٹم پاتھ فارمیٹ", - "description": "ڈاؤن لوڈ میڈیا کے لئے کسٹم پاتھ فارمیٹ کی وضاحت کریں\n\nدستیاب متغیرات:\n - ٪ صارف نام ٪\n - ٪ ماخذ ٪\n - ٪ ہیش ٪\n - ٪ تاریخ_ وقت ٪" - } - } - }, - "user_interface": { - "name": "یوزر انٹرفیس", - "description": "اسنیپ چیٹ کی شکل و صورت کو تبدیل کریں", - "properties": { - "enable_app_appearance": { - "name": "ایپ کی ظاہری ترتیبات کو فعال کریں", - "description": "پوشیدہ ایپ کی ظاہری ترتیب کو قابل بناتا ہے\nنئے اسنیپ چیٹ ورژن پر ضرورت نہیں ہوسکتی ہے" - }, - "friend_feed_message_preview": { - "name": "فرینڈ فیڈ پیغام پیش نظارہ", - "description": "فرینڈ فیڈ میں آخری پیغامات کا پیش نظارہ دکھاتا ہے", - "properties": { - "amount": { - "name": "رقم", - "description": "پیش نظارہ کرنے کے لئے پیغامات کی مقدار" - } - } - }, - "snap_preview": { - "name": "سنیپ پیش نظارہ", - "description": "چیٹ میں نظر نہ آنے والے سنیپ کے آگے ایک چھوٹا سا پیش نظارہ دکھاتا ہے" - }, - "bootstrap_override": { - "name": "بوٹسٹریپ اوور رائڈ", - "description": "یوزر انٹرفیس بوٹسٹریپ کی ترتیبات کو اوور رائڈ کریں", - "properties": { - "app_appearance": { - "name": "ایپ کی ظاہری شکل", - "description": "ایک مستقل ایپ کی ظاہری شکل مرتب کرتا ہے" - }, - "home_tab": { - "name": "ہوم ٹیب", - "description": "اسنیپ چیٹ کھولتے وقت اسٹارٹ اپ ٹیب کو اوور رائڈس کریں" - } - } - }, - "force_amoled_theme": { - "name": "AMOLED ڈارک موڈ", - "description": "تاریک تھیم کے لئے ایک حقیقی سیاہ پس منظر استعمال کرتا ہے" - }, - "map_friend_nametags": { - "name": "بہتر دوست نقشہ نام ٹیگس", - "description": "اسنیپ میپ پر دوستوں کے ناموں کو بہتر بناتا ہے" - }, - "prevent_message_list_auto_scroll": { - "name": "پیغام کی فہرست آٹو اسکرول کو روکیں", - "description": "پیغام بھیجنے/وصول کرتے وقت میسج کی فہرست کو نیچے تک سکرول کرنے سے روکتا ہے" - }, - "streak_expiration_info": { - "name": "اسٹریک میعاد ختم ہونے کی معلومات دکھائیں", - "description": "اسٹریکس کاؤنٹر کے ساتھ ہی ایک اسٹریک میعاد ختم ہونے کا ٹائمر دکھاتا ہے" - }, - "hide_friend_feed_entry": { - "name": "دوست فیڈ انٹری کو چھپائیں", - "description": "دوست فیڈ سے ایک مخصوص دوست کو چھپاتا ہے\nاس خصوصیت کو سنبھالنے کے لئے سوشل ٹیب کا استعمال کریں" - }, - "hide_streak_restore": { - "name": "اسٹریک بحالی کو چھپائیں", - "description": "فرینڈ فیڈ میں بحالی کے بٹن کو چھپاتا ہے" - }, - "hide_quick_add_suggestions": { - "name": "فوری اضافی تجاویز کو چھپائیں", - "description": "دوست شامل کرنے کی فوری تجاویز کو ہٹا دیتا ہے" - }, - "hide_story_suggestions": { - "name": "کہانی کی تجاویز چھپائیں", - "description": "کہانیوں کے صفحے سے تجاویز کو ہٹا دیتا ہے" - }, - "hide_ui_components": { - "name": "UI اجزاء کو چھپائیں", - "description": "منتخب کریں کہ کون سے UI اجزاء چھپائیں" - }, - "opera_media_quick_info": { - "name": "اوپیرا میڈیا فوری معلومات", - "description": "اوپیرا ناظرین کے سیاق و سباق کے مینو میں تخلیق کی تاریخ جیسے میڈیا کی مفید معلومات دکھاتا ہے" - }, - "old_bitmoji_selfie": { - "name": "پرانا بٹ موجی سیلفی", - "description": "پرانے اسنیپ چیٹ ورژن سے بٹ موجی سیلفیز کو واپس لاتا ہے" - }, - "disable_spotlight": { - "name": "اسپاٹ لائٹ کو غیر فعال کریں", - "description": "اسپاٹ لائٹ پیج کو غیر فعال کرتا ہے" - }, - "friend_feed_menu_buttons": { - "name": "فرینڈ فیڈ مینو بٹن", - "description": "فرینڈ فیڈ مینو میں کون سا بٹن دکھائیں منتخب کریں" - }, - "auto_close_friend_feed_menu": { - "name": "آٹو قریبی دوست فیڈ مینو", - "description": "سیٹنگ بٹن دبانے کے بعد خود بخود فرینڈ فیڈ مینو کو بند کردیتا ہے" - }, - "vertical_story_viewer": { - "name": "عمودی کہانی دیکھنے والا", - "description": "تمام کہانیوں کے لئے عمودی کہانی دیکھنے والے کو قابل بناتا ہے" - }, - "enable_friend_feed_menu_bar": { - "name": "فرینڈ فیڈ مینو بار", - "description": "نئے دوست فیڈ مینو بار کو قابل بناتا ہے" - }, - "message_indicators": { - "name": "پیغام کے اشارے", - "description": "پیغامات میں مخصوص اشارے کے شبیہیں شامل کرتا ہے\nنوٹ: اشارے 100 ٪ درست نہیں ہوسکتے ہیں" - }, - "stealth_mode_indicator": { - "name": "اسٹیلتھ موڈ اشارے", - "description": "اسٹیلتھ موڈ میں گفتگو کے بعد ایک 👻 ایموجی شامل کرتا ہے" - }, - "edit_text_override": { - "name": "متن کو اوور رائڈ میں ترمیم کریں", - "description": "ٹیکسٹ فیلڈ سلوک کو اوور رائڈ کریں" - }, - "prevent_forced_keyboard": { - "name": "جبری کی بورڈ کو روکیں", - "description": "جب آپ گفتگو کھولتے ہیں تو اسنیپ چیٹ کو خود بخود کی بورڈ کو پاپ کرنے سے روکتا ہے" - }, - "settings_menu": { - "name": "ترتیبات کا مینو", - "description": "آپ پرفرفیکسٹنپ مینو کھولنے کے طریقے کو تبدیل کرتے ہیں", - "options": { - "default": "پہلے سے طے شدہ", - "legacy": "میراث" - } - } - } - }, - "messaging": { - "name": "پیغام رسانی", - "description": "دوستوں کے ساتھ بات چیت کرنے کا طریقہ تبدیل کریں", - "properties": { - "bypass_screenshot_detection": { - "name": "بائی پاس اسکرین شاٹ کا پتہ لگانا", - "description": "جب آپ اسکرین شاٹ لیتے ہیں تو اسنیپ چیٹ کا پتہ لگانے سے روکتا ہے" - }, - "anonymous_story_viewing": { - "name": "گمنام کہانی دیکھنا", - "description": "کسی کو بھی جاننے سے روکتا ہے کہ آپ نے ان کی کہانی دیکھی ہے" - }, - "prevent_story_rewatch_indicator": { - "name": "اسٹوری ریواچ اشارے کو روکیں", - "description": "کسی کو بھی جاننے سے روکتا ہے کہ آپ نے ان کی کہانی کو دوبارہ دیکھا ہے" - }, - "hide_peek_a_peek": { - "name": "جھانکنے والا جھانک چھپائیں", - "description": "جب آپ آدھے چیٹ میں سوائپ کرتے ہیں تو نوٹیفکیشن کو بھیجنے سے روکتا ہے" - }, - "hide_bitmoji_presence": { - "name": "بٹ موجی کی موجودگی کو چھپائیں", - "description": "چیٹ میں رہتے ہوئے آپ کے بٹ موجی کو پوپ اپ کرنے سے روکتا ہے" - }, - "hide_typing_notifications": { - "name": "ٹائپنگ کی اطلاعات کو چھپائیں", - "description": "کسی کو بھی یہ جاننے سے روکتا ہے کہ آپ میسج ٹائپ کررہے ہیں" - }, - "unlimited_snap_view_time": { - "name": "لامحدود اسنیپ ویو ٹائم", - "description": "سنیپ دیکھنے کے لئے وقت کی حد کو دور کرتا ہے" - }, - "auto_mark_as_read": { - "name": "آٹو مارک کے طور پر پڑھا", - "description": "جب اسٹیلتھ موڈ فعال ہوجاتا ہے تو خود بخود پیغامات/سنیپس کو نشان زد کرتا ہے" - }, - "mark_snap_as_seen_button": { - "name": "جیسا کہ دیکھا ہوا بٹن پر نشان لگائیں", - "description": "اسنیپ کو نشان زد کرنے کے لئے ایک بٹن شامل کرتا ہے جیسا کہ دیکھا جاتا ہے۔\nجب اسٹیلتھ موڈ فعال ہوجائے تب بھی یہ کام کرے گا" - }, - "skip_when_marking_as_seen": { - "name": "جیسا کہ دیکھا ہوا نشان لگاتے ہو تو چھوڑیں", - "description": "جیسا کہ دیکھا گیا ہے کہ اسنیپ کو نشان زد کرتے وقت خود بخود اگلے سنیپ پر جائیں۔\nبطور دیکھا ہوا بٹن مارک سنیپ کے ساتھ مل کر استعمال کریں" - }, - "loop_media_playback": { - "name": "لوپ میڈیا پلے بیک", - "description": "جب سنیپس / کہانیاں دیکھتے ہو تو میڈیا پلے بیک" - }, - "disable_replay_in_ff": { - "name": "ایف ایف میں ری پلے کو غیر فعال کریں", - "description": "فرینڈ فیڈ سے طویل پریس کے ساتھ ری پلے کرنے کی صلاحیت کو غیر فعال کرتا ہے" - }, - "half_swipe_notifier": { - "name": "آدھا سوائپ نوٹیفائر", - "description": "جب کوئی آدھا گفتگو میں سوائپ کرتا ہے تو آپ کو مطلع کرتا ہے", - "properties": { - "min_duration": { - "name": "کم سے کم مدت", - "description": "آدھے سوائپ کی کم سے کم مدت (سیکنڈ میں)" - }, - "max_duration": { - "name": "زیادہ سے زیادہ دورانیہ", - "description": "آدھے سوائپ کی زیادہ سے زیادہ مدت (سیکنڈ میں)" - } - } - }, - "call_start_confirmation": { - "name": "کال اسٹارٹ تصدیق", - "description": "کال شروع کرتے وقت تصدیقی ڈائیلاگ دکھاتا ہے" - }, - "unlimited_conversation_pinning": { - "name": "لامحدود گفتگو پن", - "description": "آپ کو مقامی طور پر گفتگو کی لامحدود مقدار میں پن کرنے کی اجازت دیتا ہے" - }, - "disable_snap_mode_restrictions": { - "name": "اسنیپ موڈ کی پابندیوں کو غیر فعال کریں", - "description": "آپ کو بغیر کسی پابندی کے خود کو تباہ کرنے والے سنیپ دیکھنے کی اجازت دیتا ہے" - }, - "prevent_message_sending": { - "name": "پیغام بھیجنے کو روکیں", - "description": "کچھ قسم کے پیغامات بھیجنے سے روکتا ہے" - }, - "friend_mutation_notifier": { - "name": "دوست اتپریورتن نوٹیفائر", - "description": "جب کسی دوست کے پروفائل میں کچھ تبدیل ہوتا ہے تو آپ کو مطلع کرتا ہے" - }, - "better_notifications": { - "name": "بہتر اطلاعات", - "description": "موصولہ اطلاعات میں مزید معلومات شامل کرتا ہے", - "properties": { - "group_notifications": { - "name": "گروپ اطلاعات", - "description": "ایک ایک میں گروپ کی اطلاعات" - }, - "chat_preview": { - "name": "چیٹ پیش نظارہ", - "description": "نوٹیفکیشن میں موصولہ پیغامات کا پیش نظارہ دکھاتا ہے" - }, - "media_preview": { - "name": "میڈیا پیش نظارہ", - "description": "نوٹیفکیشن میں منتخب میڈیا اقسام کا ایک پیش نظارہ دکھاتا ہے" - }, - "media_caption": { - "name": "میڈیا کیپشن", - "description": "نوٹیفکیشن میں میڈیا کے منسلک عنوان کو ظاہر کرتا ہے" - }, - "stacked_media_messages": { - "name": "اسٹیک میڈیا پیغامات", - "description": "متعدد میڈیا پیغامات کو ایک متن کی اطلاع میں جوڑتا ہے جب ان کا پیش نظارہ نہیں کیا جاسکتا ہے۔ چیٹ پیش نظارہ کے ساتھ مل کر استعمال کریں" - }, - "friend_add_source": { - "name": "دوست شامل کریں ماخذ", - "description": "نوٹیفکیشن میں دوست کی درخواست کا ماخذ ظاہر کرتا ہے" - }, - "reply_button": { - "name": "جواب دیں بٹن", - "description": "نوٹیفکیشن میں جوابی بٹن شامل کرتا ہے" - }, - "smart_replies": { - "name": "ہوشیار جوابات", - "description": "اطلاعات (Android 10+) میں تجویز کردہ جوابات شامل کرتا ہے۔ جواب بٹن کے ساتھ مل کر استعمال کریں" - }, - "download_button": { - "name": "ڈاؤن لوڈ کے بٹن", - "description": "آپ کو نوٹیفکیشن سے میڈیا ڈاؤن لوڈ کرنے کی اجازت دیتا ہے" - }, - "mark_as_read_button": { - "name": "پڑھنے والے بٹن کے طور پر نشان زد کریں", - "description": "نوٹیفکیشن سے پڑھے گئے پیغام کو نشان زد کرنے کی اجازت دیتا ہے" - }, - "mark_as_read_and_save_in_chat": { - "name": "چیٹ میں پڑھنے اور محفوظ کریں کے طور پر نشان زد کریں", - "description": "نوٹیفیکیشن میں چیٹ کے بٹن میں پڑھنے اور محفوظ کرنے کے بطور ایک نشان شامل کرتا ہے" - } - } - }, - "notification_blacklist": { - "name": "نوٹیفکیشن بلیک لسٹ", - "description": "اطلاعات کا انتخاب کریں جو مسدود ہوجائیں" - }, - "message_logger": { - "name": "میسج لاگر", - "description": "پیغامات کو حذف ہونے سے روکتا ہے", - "properties": { - "keep_my_own_messages": { - "name": "میرے اپنے پیغامات رکھیں", - "description": "آپ کے اپنے پیغامات کو حذف ہونے سے روکتا ہے" - }, - "auto_purge": { - "name": "آٹو پرج", - "description": "خود بخود کیشڈ پیغامات کو حذف کردیتا ہے جو وقت کی مخصوص مقدار سے زیادہ پرانے ہیں" - }, - "message_filter": { - "name": "میسج فلٹر", - "description": "منتخب کریں کہ کون سے پیغامات لاگ ان ہوں (تمام پیغامات کے لئے خالی)" - }, - "deleted_message_color": { - "name": "حذف شدہ پیغام کا رنگ", - "description": "حذف شدہ پیغامات کا رنگ طے کرتا ہے" - } - } - }, - "auto_save_messages_in_conversations": { - "name": "آٹو محفوظ پیغامات", - "description": "گفتگو میں ہر پیغام کو خود بخود محفوظ کرتا ہے" - }, - "gallery_media_send_override": { - "name": "گیلری ، نگارخانہ میڈیا اوور رائڈ بھیجیں", - "description": "گیلری سے بھیجتے وقت میڈیا کے ذریعہ کو دھوکہ دیتا ہے" - }, - "strip_media_metadata": { - "name": "پٹی میڈیا میٹا ڈیٹا", - "description": "پیغام بھیجنے سے پہلے میڈیا کے میٹا ڈیٹا کو ہٹا دیتا ہے" - }, - "bypass_message_retention_policy": { - "name": "بائی پاس پیغام برقرار رکھنے کی پالیسی", - "description": "پیغامات کو دیکھنے کے بعد حذف ہونے سے روکتا ہے" - }, - "bypass_message_action_restrictions": { - "name": "بائی پاس میسج ایکشن پابندی", - "description": "آپ کو بغیر کسی سنیپ پر ردعمل ظاہر کرنے کی اجازت دیتا ہے اسے کھولے بغیر یا ناقابل قابل پیغام محفوظ کرنے کی اجازت دیتا ہے" - }, - "remove_groups_locked_status": { - "name": "گروپوں کو بند شدہ حیثیت سے ہٹا دیں", - "description": "لات مارنے کے بعد آپ کو گروپ کی معلومات دیکھنے کی اجازت دیتا ہے" - }, - "double_tap_chat_action": { - "name": "ڈبل نل چیٹ ایکشن", - "description": "چیٹ میں کسی پیغام کو ڈبل ٹیپ کرتے وقت کسٹم ایکشن انجام دیتا ہے" - }, - "double_tap_chat_action_custom_emoji": { - "name": "ڈبل نل چیٹ ایکشن کسٹم ایموجی رد عمل", - "description": "ڈبل نل چیٹ ایکشن کے لئے کسٹم ایموجی رد عمل کا تعین کرتا ہے" - } - } - }, - "global": { - "name": "عالمی", - "description": "گلوبل اسنیپ چیٹ کی ترتیبات کو موافقت دیں", - "properties": { - "better_location": { - "name": "بہتر مقام", - "description": "اسنیپ چیٹ کے مقام کو بڑھاتا ہے", - "properties": { - "spoof_location": { - "name": "اسپوف مقام", - "description": "اپنے مقام کو ایک مخصوص مقام پر گامزن کرتا ہے" - }, - "coordinates": { - "name": "کوآرڈینیٹ", - "description": "اسپوفڈ مقام کے نقاط مرتب کریں" - }, - "walk_radius": { - "name": "واک رداس", - "description": "تصادفی طور پر اس رداس (فٹ) کے اندر چہل قدمی کریں" - }, - "always_update_location": { - "name": "ہمیشہ مقام کو اپ ڈیٹ کریں", - "description": "اسنیپ چیٹ کو مقام کو اپ ڈیٹ کرنے پر مجبور کریں یہاں تک کہ اگر کوئی GPS ڈیٹا موصول نہیں ہوا ہے" - }, - "suspend_location_updates": { - "name": "مقام کی تازہ کاریوں کو معطل کریں", - "description": "آپ کے مقام کو اپ ڈیٹ ہونے سے روکتا ہے" - }, - "spoof_battery_level": { - "name": "دھڑکن بیٹری کی سطح", - "description": "نقشہ پر آپ کے آلے کی بیٹری کی سطح کو جکڑتا ہے\nقیمت 0 اور 100 کے درمیان ہونی چاہئے" - }, - "spoof_headphones": { - "name": "سپوف ہیڈ فون", - "description": "نقشہ پر موسیقی سننے کی حیثیت کو دھوکہ دیتا ہے" - }, - "show_battery_level": { - "name": "بیٹری کی سطح دکھائیں", - "description": "نقشے پر اپنے دوستوں کی بیٹری کی سطح کو ظاہر کرتا ہے" - } - } - }, - "snapchat_plus": { - "name": "اسنیپ چیٹ پلس", - "description": "اسنیپ چیٹ پلس خصوصیات کو قابل بناتا ہے\nکچھ سرور رخا خصوصیات کام نہیں کرسکتی ہیں" - }, - "media_upload_quality": { - "name": "میڈیا اپ لوڈ کا معیار", - "description": "میڈیا اپ لوڈ کے معیار کو اوور رائڈس", - "properties": { - "force_video_upload_source_quality": { - "name": "فورس ویڈیو اپ لوڈ ماخذ کے معیار کو", - "description": "ویڈیوز اپ لوڈ کرتے وقت سنیپ چیٹ کو سنیپ چیٹ استعمال کرنے پر مجبور کرتا ہے\nبراہ کرم نوٹ کریں کہ یہ میڈیا سے میٹا ڈیٹا کو نہیں ہٹا سکتا ہے" - }, - "disable_image_compression": { - "name": "تصویری کمپریشن کو غیر فعال کریں", - "description": "میڈیا کو اپ لوڈ کرتے وقت امیج کمپریشن کو غیر فعال کرتا ہے" - }, - "custom_image_upload_format": { - "name": "کسٹم امیج اپلوڈ فارمیٹ", - "description": "ایک کسٹم امیج اپ لوڈ کی شکل مرتب کرتا ہے\nبہترین معیار کے ل a ایک لچکدار فارمیٹ (جیسے PNG) منتخب کریں" - } - } - }, - "disable_confirmation_dialogs": { - "name": "تصدیق کے مکالمے کو غیر فعال کریں", - "description": "خود بخود منتخب کردہ اعمال کی تصدیق کرتا ہے" - }, - "auto_updater": { - "name": "آٹو اپڈیٹر", - "description": "نئی تازہ کاریوں کے لئے خود بخود جانچ پڑتال کریں" - }, - "disable_metrics": { - "name": "میٹرکس کو غیر فعال کریں", - "description": "اسنیپ چیٹ پر مخصوص تجزیاتی ڈیٹا بھیجنے والے بلاکس" - }, - "disable_story_sections": { - "name": "کہانی کے حصوں کو غیر فعال کریں", - "description": "کہانیوں کے صفحے سے حصوں کو ہٹا دیتا ہے\nمناسب طریقے سے کام کرنے کے لئے ریفریش کی ضرورت ہوسکتی ہے" - }, - "block_ads": { - "name": "بلاک اشتہارات", - "description": "اشتہارات کو ظاہر ہونے سے روکتا ہے" - }, - "disable_custom_tabs": { - "name": "کسٹم ٹیبز کو غیر فعال کریں", - "description": "ویب براؤزر کے بجائے تعاون یافتہ ایپلی کیشنز میں لنکس کھولتا ہے" - }, - "disable_permission_requests": { - "name": "اجازت کی درخواستوں کو غیر فعال کریں", - "description": "اسنیپ چیٹ کو مخصوص اجازت طلب کرنے سے روکتا ہے" - }, - "disable_memories_snap_feed": { - "name": "یادوں کو سنیپ فیڈ کو غیر فعال کریں", - "description": "جب آپ کیمرے میں سوائپ کرتے ہیں تو اسنیپ چیٹ کو حالیہ یادوں کو ظاہر کرنے سے روکتا ہے" - }, - "spotlight_comments_username": { - "name": "اسپاٹ لائٹ تبصرے صارف نام", - "description": "اسپاٹ لائٹ تبصروں میں مصنف کا صارف نام دکھاتا ہے" - }, - "bypass_video_length_restriction": { - "name": "ویڈیو لمبائی کی پابندیاں بائی پاس کریں", - "description": "سنگل: ایک ہی ویڈیو بھیجتا ہے\nتقسیم: ترمیم کے بعد سپلٹ ویڈیوز" - }, - "default_video_playback_rate": { - "name": "پہلے سے طے شدہ ویڈیو پلے بیک کی شرح", - "description": "ویڈیوز کے پلے بیک کے لئے پہلے سے طے شدہ رفتار طے کرتا ہے\nقیمت 0.1 اور 4.0 کے درمیان ہونی چاہئے" - }, - "video_playback_rate_slider": { - "name": "ویڈیو پلے بیک ریٹ سلائیڈر", - "description": "ویڈیو پلے بیک ریٹ کو تبدیل کرنے کے لئے اوپیرا سیاق و سباق کے مینو میں ایک سلائیڈر شامل کرتا ہے\nنوٹ: تبدیلیاں صرف بعد کے ویڈیوز پر لاگو ہوتی ہیں" - }, - "disable_google_play_dialogs": { - "name": "گوگل پلے سروسز ڈائیلاگ کو غیر فعال کریں", - "description": "گوگل پلے سروسز کی دستیابی کے مکالمے کو دکھائے جانے سے روکیں" - }, - "default_volume_controls": { - "name": "پہلے سے طے شدہ حجم کنٹرول", - "description": "سسٹم کے حجم کنٹرول کو استعمال کرنے کے لئے اسنیپ چیٹ کو مجبور کرتا ہے" - }, - "disable_telecom_framework": { - "name": "ٹیلی کام فریم ورک کو غیر فعال کریں", - "description": "اسنیپ چیٹ کو اینڈروئیڈ ٹیلی کام فریم ورک کے استعمال سے روکتا ہے\nیہ آپ کو کال کے دوران موسیقی سننے کی اجازت دیتا ہے" - }, - "hide_active_music": { - "name": "فعال موسیقی چھپائیں", - "description": "اسنیپ چیٹ کو یہ جاننے سے روکتا ہے کہ آپ موسیقی سن رہے ہیں\nاس سے آپ موسیقی کو سنتے وقت کنٹرول کے حجم کے بٹنوں کا استعمال کرتے ہوئے سنیپ لینے کی اجازت دیں گے" - }, - "disable_snap_splitting": { - "name": "اسنیپ تقسیم کو غیر فعال کریں", - "description": "سنیپ کو متعدد حصوں میں تقسیم ہونے سے روکتا ہے\nآپ جو تصاویر بھیجتے ہیں وہ ویڈیوز میں بدل جائیں گے" - } - } - }, - "rules": { - "name": "قواعد", - "description": "انفرادی لوگوں کے لئے خودکار خصوصیات کا نظم کریں" - }, - "camera": { - "name": "کیمرا", - "description": "کامل سنیپ کیلئے صحیح ترتیبات کو ایڈجسٹ کریں", - "properties": { - "disable_cameras": { - "name": "کیمرے کو غیر فعال کریں", - "description": "اسنیپ چیٹ کو منتخب کیمرے استعمال کرنے سے روکتا ہے" - }, - "black_photos": { - "name": "کالی تصاویر", - "description": "پکڑے گئے تصاویر کو سیاہ پس منظر سے تبدیل کرتا ہے\nویڈیوز متاثر نہیں ہوتے ہیں" - }, - "immersive_camera_preview": { - "name": "عمیق پیش نظارہ", - "description": "اسنیپ چیٹ کو کیمرہ پیش نظارہ کاٹنے سے روکتا ہے\nاس کی وجہ سے کیمرہ کچھ آلات پر ٹمٹمانے کا سبب بن سکتا ہے" - }, - "override_front_resolution": { - "name": "سامنے کی قرارداد کو اوور رائڈ کریں", - "description": "فرنٹ کیمرا کے لئے کیمرہ ریزولوشن کو اوور رائڈ کریں" - }, - "override_back_resolution": { - "name": "بیک ریزولوشن کو اوور رائڈ کریں", - "description": "پچھلے کیمرے کے لئے کیمرہ ریزولوشن کو اوور رائڈ کریں" - }, - "custom_resolution": { - "name": "کسٹم ریزولوشن", - "description": "ایک کسٹم کیمرہ ریزولوشن ، چوڑائی X اونچائی (جیسے 1920x1080) کا تعین کرتا ہے۔\nکسٹم ریزولوشن کو آپ کے آلے کے ذریعہ تعاون کرنا چاہئے" - }, - "front_custom_frame_rate": { - "name": "فرنٹ کسٹم فریم ریٹ", - "description": "فرنٹ کیمرا فریم ریٹ کو اوور رائڈ کریں" - }, - "back_custom_frame_rate": { - "name": "واپس کسٹم فریم ریٹ", - "description": "بیک کیمرا فریم ریٹ کو اوور رائڈس" - }, - "force_camera_source_encoding": { - "name": "فورس کیمرہ سورس انکوڈنگ", - "description": "کیمرہ سورس انکوڈنگ پر مجبور کرتا ہے" - }, - "startup_default_camera": { - "name": "اسٹارٹ اپ ڈیفالٹ کیمرا", - "description": "اسنیپ چیٹ کھولتے وقت ڈیفالٹ کیمرا سیٹ کرتا ہے" - }, - "hevc_recording": { - "name": "HEVC ریکارڈنگ", - "description": "ویڈیو ریکارڈنگ کے لئے HEVC (H.265) کوڈیک استعمال کرتا ہے" - } - } - }, - "streaks_reminder": { - "name": "اسٹریکس یاد دہانی", - "description": "وقتا فوقتا آپ کو اپنی لکیروں کے بارے میں مطلع کرتا ہے", - "properties": { - "interval": { - "name": "وقفہ", - "description": "ہر یاد دہانی کے درمیان وقفہ (گھنٹے)" - }, - "remaining_hours": { - "name": "باقی وقت", - "description": "نوٹیفکیشن سے پہلے باقی وقت (گھنٹے) دکھایا جاتا ہے" - }, - "group_notifications": { - "name": "گروپ اطلاعات", - "description": "ایک ایک میں گروپ اطلاعات" - } - } - }, - "experimental": { - "name": "تجرباتی", - "description": "تجرباتی خصوصیات", - "properties": { - "native_hooks": { - "name": "آبائی ہکس", - "description": "غیر محفوظ خصوصیات جو اسنیپ چیٹ کے آبائی کوڈ میں شامل ہیں", - "properties": { - "composer_hooks": { - "name": "کمپوزر ہکس", - "description": "کمپوزر کراس پلیٹ فارم UI فریم ورک میں کوڈ انجیکشن کریں", - "properties": { - "show_first_created_username": { - "name": "پہلے تخلیق کردہ صارف نام دکھائیں", - "description": "پروفائل صفحے میں موجودہ صارف نام کے آگے پہلا تیار کردہ صارف نام ظاہر کرتا ہے" - }, - "bypass_camera_roll_limit": { - "name": "بائی پاس کیمرا رول کی حد", - "description": "میڈیا کی زیادہ سے زیادہ مقدار میں اضافہ کرتا ہے جو آپ کیمرہ رول سے بھیج سکتے ہیں" - }, - "custom_self_destruct_snap_delay": { - "name": "کسٹم سیلف ڈسٹرکٹ اسنیپ میں تاخیر", - "description": "جب سنیپ بھیجتے ہو" - }, - "composer_console": { - "name": "کمپوزر کنسول", - "description": "آپ کو کمپوزر میں جاوا اسکرپٹ کوڈ پر عمل درآمد کرنے کی اجازت دیتا ہے (صرف ARM64)" - }, - "composer_logs": { - "name": "کمپوزر لاگ", - "description": "کمپوزر کے کنسول لاگز کو پورفیکٹسنیپ پر ری ڈائریکٹ کرتا ہے" - } - } - }, - "disable_bitmoji": { - "name": "بٹ موجی کو غیر فعال کریں", - "description": "دوستوں کے پروفائل بٹ موجی کو غیر فعال کرتا ہے" - }, - "custom_emoji_font": { - "name": "کسٹم ایموجی فونٹ", - "description": "آپ کو کسٹم ایموجی فونٹ استعمال کرنے کی اجازت دیتا ہے۔ صرف .TTF فونٹس کے ساتھ کام کرتا ہے" - }, - "custom_shared_library": { - "name": "کسٹم مشترکہ لائبریری", - "description": "ایک کسٹم مشترکہ لائبریری کو اسنیپ چیٹ میں لوڈ کرتا ہے۔ یہ خصوصیت صرف جانچ کے مقاصد کے لئے ہے" - } - } - }, - "spoof": { - "name": "سپوف", - "description": "آپ کے بارے میں مختلف معلومات کو جکڑیں", - "properties": { - "play_store_installer_package_name": { - "name": "اسٹور اسٹور انسٹالر پیکیج کا نام", - "description": "com.android.vending پر انسٹالر پیکیج کے نام کو اوور رائڈ کریں" - }, - "remove_vpn_transport_flag": { - "name": "وی پی این ٹرانسپورٹ پرچم کو ہٹا دیں", - "description": "سنیپ چیٹ کو VPNs کا پتہ لگانے سے روکتا ہے" - }, - "remove_mock_location_flag": { - "name": "مذاق کی جگہ پرچم کو ہٹا دیں", - "description": "سنیپ چیٹ کو مذاق کے مقام کا پتہ لگانے سے روکتا ہے" - } - } - }, - "convert_message_locally": { - "name": "مقامی طور پر پیغام کو تبدیل کریں", - "description": "بیرونی میڈیا کو مقامی طور پر چیٹ کرنے کے لئے سنیپ کو تبدیل کرتا ہے۔ یہ چیٹ ڈاؤن لوڈ سیاق و سباق کے مینو میں ظاہر ہوتا ہے" - }, - "media_file_picker": { - "name": "میڈیا فائل چننے والا", - "description": "آپ کو گیلری سے کوئی ویڈیو/آڈیو فائل منتخب کرنے کی اجازت دیتا ہے" - }, - "story_logger": { - "name": "اسٹوری لاگر", - "description": "دوستوں کی کہانیوں کی تاریخ فراہم کرتا ہے" - }, - "call_recorder": { - "name": "کال ریکارڈر", - "description": "خود بخود آڈیو کالز کو ریکارڈ کرتا ہے" - }, - "account_switcher": { - "name": "اکاؤنٹ سوئچر", - "description": "آپ کو لاگ آؤٹ کیے بغیر اکاؤنٹس کے مابین سوئچ کرنے کی اجازت دیتا ہے\nمینو کھولنے کے لئے اپنے بٹ موجی پروفائل کے ساتھ مل کر تلاش کے آئیکن پر لمبی دبائیں\nنوٹ: یہ خصوصیت تجرباتی ہے اور ممکنہ طور پر مستقبل میں تبدیل ہوجائے گی", - "properties": { - "auto_backup_current_account": { - "name": "آٹو بیک اپ کرنٹ اکاؤنٹ", - "description": "جب لاگ آؤٹ کرتے ہو یا اکاؤنٹس کو تبدیل کرتے ہو تو خود بخود کرنٹ اکاؤنٹ کی پشت پناہی کرتا ہے" - } - } - }, - "better_transcript": { - "name": "بہتر ٹرانسکرپٹ", - "description": "وائس نوٹ ٹرانسکرپٹ کو بہتر بناتا ہے", - "properties": { - "force_transcription": { - "name": "فورس وائس نوٹ ٹرانسکرپشن", - "description": "تمام صوتی نوٹوں کو نقل کرنے کی اجازت دیتا ہے" - }, - "preferred_transcription_lang": { - "name": "ترجیحی نقل کی زبان", - "description": "صوتی نوٹ ٹرانسکرپٹ کے لئے ترجیحی زبان (جیسے EN ، ES ، FR)" - }, - "notification_transcript": { - "name": "نوٹیفکیشن ٹرانسکرپٹ", - "description": "اطلاعات میں صوتی نوٹ کی نقل\nاس خصوصیت کے لئے بہتر اطلاعات میں چیٹ پیش نظارہ کی خصوصیت کو فعال کرنے کی ضرورت ہے" - } - } - }, - "voice_note_auto_play": { - "name": "صوتی نوٹ آٹو پلے", - "description": "موجودہ ختم ہونے کے بعد خود بخود اگلا وائس نوٹ ادا کرتا ہے" - }, - "friend_notes": { - "name": "دوست نوٹ", - "description": "آپ کو دوستوں کے پروفائلز میں نوٹ شامل کرنے کی اجازت دیتا ہے" - }, - "cof_experiments": { - "name": "COF تجربات", - "description": "غیر منقولہ/بیٹا اسنیپ چیٹ خصوصیات کو قابل بناتا ہے" - }, - "context_menu_fix": { - "name": "سیاق و سباق کا مینو ٹھیک ہے", - "description": "فرینڈ فیڈ مینو کی مرمت کرنے کی کوشش کریں جیسے ڈیوائس آف لائن ہے تو اسے صحیح طریقے سے ظاہر نہیں کیا جاسکتا ہے" - }, - "app_lock": { - "name": "ایپ لاک", - "description": "پاس کوڈ کے بغیر اسنیپ چیٹ تک رسائی کو روکتا ہے", - "properties": { - "lock_on_resume": { - "name": "تجربے کی فہرست پر لاک کریں", - "description": "جب اسے دوبارہ کھول دیا جاتا ہے تو ایپ کو لاک کرتا ہے" - } - } - }, - "infinite_story_boost": { - "name": "لامحدود کہانی کو فروغ دینا", - "description": "کہانی کو بڑھاوا دینے کی حد میں تاخیر کو نظرانداز کریں" - }, - "meo_passcode_bypass": { - "name": "میری آنکھیں صرف پاس کوڈ بائی پاس ہیں", - "description": "میری آنکھوں کو صرف پاس کوڈ کو نظرانداز کریں\nیہ تب ہی کام کرے گا جب پاس کوڈ سے پہلے صحیح طور پر داخل کیا گیا ہو" - }, - "no_friend_score_delay": { - "name": "کوئی دوست اسکور میں تاخیر نہیں ہے", - "description": "دوستوں کے اسکور کو دیکھتے وقت تاخیر کو دور کرتا ہے" - }, - "best_friend_pinning": { - "name": "بہترین دوست پننگ", - "description": "آپ کو اپنے دوست کو اپنے نمبر ایک بہترین دوست کی حیثیت سے پن کرنے کی اجازت دیتا ہے۔ نوٹ: صرف آپ اپنے پنڈے ہوئے بہترین دوست کو دیکھ سکتے ہیں" - }, - "e2ee": { - "name": "اختتام سے آخر میں خفیہ کاری", - "description": "مشترکہ خفیہ کلید کا استعمال کرتے ہوئے اپنے پیغامات کو AES کے ساتھ خفیہ کرتا ہے\nیقینی بنائیں کہ کہیں بھی اپنی کلید کو محفوظ بچائیں!", - "properties": { - "encrypted_message_indicator": { - "name": "خفیہ کردہ پیغام اشارے", - "description": "خفیہ کردہ پیغامات کے آگے ایک 🔒 ایموجی شامل کرتا ہے" - }, - "force_message_encryption": { - "name": "فورس میسج انکرپشن", - "description": "ان لوگوں کو خفیہ کردہ پیغامات بھیجنے سے روکتا ہے جن کے پاس E2E انکرپشن نہیں ہوتا ہے جب صرف ایک سے زیادہ گفتگو کا انتخاب کیا جاتا ہے۔" - } - } - }, - "add_friend_source_spoof": { - "name": "فرینڈ سورس جھاڑو ڈالیں", - "description": "دوست کی درخواست کے ماخذ کو جکڑتا ہے" - }, - "hidden_snapchat_plus_features": { - "name": "پوشیدہ اسنیپ چیٹ پلس خصوصیات", - "description": "غیر منقولہ/بیٹا اسنیپ چیٹ پلس خصوصیات کو قابل بناتا ہے\nشاید پرانے اسنیپ چیٹ ورژن پر کام نہ کریں" - }, - "custom_streaks_expiration_format": { - "name": "کسٹم اسٹریکس میعاد ختم ہونے کی شکل", - "description": "اسٹریکس کی میعاد ختم ہونے کی شکل کو اپنی مرضی کے مطابق بناتا ہے\n\nدستیاب متغیرات:\n - ٪ C: اسٹریکس گنتی\n - ٪ ای: ہورگلاس ایموجی\n - ٪ d: دن\n - ٪ H: گھنٹے\n - ٪ M: منٹ\n - ٪ s: سیکنڈ\n - ٪ ڈبلیو: باقی وقت" - }, - "prevent_forced_logout": { - "name": "جبری لاگ آؤٹ کو روکیں", - "description": "جب آپ کسی دوسرے آلے پر لاگ ان ہوتے ہیں تو اسنیپ چیٹ کو لاگ ان کرنے سے روکتا ہے" - }, - "snapscore_changes": { - "name": "سنیپسکور تبدیلیاں", - "description": "دوستوں کے سنیپ سکور میں تبدیلیوں کو ٹریک کرتا ہے\nاس خصوصیت کو صرف اسنیپ چیٹ کے نئے ورژن میں استعمال کریں" - } - } - }, - "scripting": { - "name": "اسکرپٹنگ", - "description": "purrfectsnap کو بڑھانے کے لئے کسٹم اسکرپٹ چلائیں", - "properties": { - "developer_mode": { - "name": "ڈویلپر وضع", - "description": "اسنیپ چیٹ کے UI پر ڈیبگ کی معلومات دکھاتا ہے" - }, - "module_folder": { - "name": "ماڈیول فولڈر", - "description": "وہ فولڈر جہاں اسکرپٹ واقع ہیں" - }, - "auto_reload": { - "name": "آٹو دوبارہ لوڈ", - "description": "جب وہ تبدیل ہوجاتے ہیں تو خود بخود اسکرپٹس کو دوبارہ لوڈ کرتے ہیں" - }, - "integrated_ui": { - "name": "انٹیگریٹڈ UI", - "description": "اسکرپٹ کو اسنیپ چیٹ میں اپنی مرضی کے مطابق UI اجزاء کو شامل کرنے کی اجازت دیتا ہے" - }, - "disable_log_anonymization": { - "name": "لاگ گمنامی کو غیر فعال کریں", - "description": "نوشتہ جات کی گمنامی کو غیر فعال کرتا ہے" - }, - "disable_optimization": { - "name": "اصلاح کو غیر فعال کریں", - "description": "اسکرپٹ کی اصلاح کو غیر فعال کرتا ہے۔ اس سے کارکردگی کے مسائل پیدا ہوسکتے ہیں۔" - } - } - }, - "friend_tracker": { - "name": "دوست ٹریکر", - "description": "اسنیپ چیٹ پر دوست کی سرگرمی کو ریکارڈ کرتا ہے", - "properties": { - "record_messaging_events": { - "name": "پیغام رسانی کے واقعات ریکارڈ کریں", - "description": "ریکارڈ کرتا ہے میسجنگ ایونٹس جیسے سنیپ کھولنا ، پیغام پڑھنا وغیرہ۔" - }, - "allow_running_in_background": { - "name": "پس منظر میں چلانے کی اجازت دیں", - "description": "ٹریکر کو پس منظر میں چلانے کی اجازت دیتا ہے۔ نوٹ: یہ آپ کی بیٹری کو نمایاں طور پر ختم کردے گا" - }, - "auto_purge": { - "name": "آٹو پرج", - "description": "خود بخود کیشڈ واقعات کو حذف کردیتا ہے جو وقت کی مخصوص مقدار سے زیادہ عمر کے ہوتے ہیں" - } - } - } - }, - "options": { - "app_appearance": { - "always_light": "ہمیشہ روشنی", - "always_dark": "ہمیشہ تاریک" - }, - "friend_feed_menu_buttons": { - "auto_download": "⬇ آٹو ڈاؤن لوڈ", - "auto_save": "💬 آٹو کو محفوظ کریں پیغامات", - "unsaveable_messages": "⬇ ناقابل قابل پیغامات", - "auto_open_snaps": "📷 آٹو اوپن سنیپس", - "stealth": "👻 اسٹیلتھ موڈ", - "mark_snaps_as_seen": "👀 جیسا کہ دیکھا گیا ہے اس کو نشان زد کریں", - "mark_stories_as_seen_locally": "👀 جیسا کہ مقامی طور پر دیکھا گیا کہانیاں نشان زد کریں", - "conversation_info": "👤 گفتگو کی معلومات", - "e2e_encryption": "E E2E انکرپشن کا استعمال کریں" - }, - "path_format": { - "create_author_folder": "ہر مصنف کے لئے فولڈر بنائیں", - "create_source_folder": "ہر میڈیا سورس کی قسم کے لئے فولڈر بنائیں", - "append_hash": "فائل کے نام میں ایک انوکھا ہیش شامل کریں", - "append_source": "میڈیا ماخذ کو فائل کے نام میں شامل کریں", - "append_username": "فائل کے نام میں صارف نام شامل کریں", - "append_date_time": "فائل کے نام میں تاریخ اور وقت شامل کریں" - }, - "auto_download_sources": { - "friend_snaps": "دوست سنیپ", - "friend_stories": "دوست کہانیاں", - "public_stories": "عوامی کہانیاں", - "spotlight": "اسپاٹ لائٹ" - }, - "logging": { - "started": "شروع ہوا", - "success": "کامیابی", - "progress": "پیشرفت", - "failure": "ناکامی" - }, - "notifications": { - "chat_screenshot": "اسکرین شاٹ", - "chat_screen_record": "اسکرین ریکارڈ", - "snap_replay": "سنیپ ری پلے", - "camera_roll_save": "کیمرا رول سیونگ", - "chat": "چیٹ", - "chat_reply": "چیٹ جواب", - "snap": "سنیپ", - "typing": "ٹائپنگ", - "stories": "کہانیاں", - "speaking": "بولنا", - "chat_reaction": "ڈی ایم رد عمل", - "group_chat_reaction": "گروپ رد عمل", - "initiate_audio": "آنے والی آڈیو کال", - "abandon_audio": "آڈیو کال سے محروم", - "initiate_video": "آنے والی ویڈیو کال", - "abandon_video": "یاد آیا ویڈیو کال", - "map_live_location": "نقشہ براہ راست مقام" - }, - "gallery_media_send_override": { - "always_ask": "ہمیشہ پوچھیں", - "ORIGINAL": "اصل میڈیا", - "NOTE": "آڈیو نوٹ", - "SNAP": "سنیپ", - "SAVEABLE_SNAP": "بچاؤ کے قابل سنیپ" - }, - "strip_media_metadata": { - "hide_caption_text": "عنوان کے متن کو چھپائیں", - "hide_snap_filters": "اسنیپ فلٹرز چھپائیں", - "hide_extras": "ایکسٹرا چھپائیں (جیسے تذکرے)", - "remove_audio_note_duration": "آڈیو نوٹ کی مدت کو ہٹا دیں", - "remove_audio_note_transcript_capability": "آڈیو نوٹ ٹرانسکرپٹ کی صلاحیت کو ہٹا دیں" - }, - "hide_ui_components": { - "hide_profile_call_buttons": "پروفائل کال بٹنوں کو ہٹا دیں", - "hide_chat_call_buttons": "چیٹ کال بٹنوں کو ہٹا دیں", - "hide_live_location_share_button": "براہ راست لوکیشن شیئر بٹن کو ہٹا دیں", - "hide_stickers_button": "اسٹیکرز کے بٹن کو ہٹا دیں", - "hide_voice_record_button": "وائس ریکارڈ بٹن کو ہٹا دیں", - "hide_unread_chat_hint": "غیر پڑھے ہوئے چیٹ کا اشارہ ہٹا دیں", - "hide_post_to_story_buttons": "سنیپ بھیجنے سے پہلے اسٹوری کے بٹنوں پر پوسٹ کو ہٹا دیں", - "hide_billboard_prompt": "دوستوں کے فیڈ میں بل بورڈ پرامپٹ کو ہٹا دیں", - "hide_snapchat_plus_gift_reminders": "گفتگو میں اسنیپ چیٹ کے علاوہ تحفے کی یاد دہانیوں کو ہٹا دیں", - "hide_map_reactions": "نقشہ کے رد عمل کو دور کریں" - }, - "hide_story_suggestions": { - "hide_suggested_friend_stories": "تجویز کردہ دوست کی کہانیاں چھپائیں", - "hide_my_stories": "میری کہانیاں چھپائیں" - }, - "home_tab": { - "map": "نقشہ", - "chat": "چیٹ", - "camera": "کیمرا", - "discover": "دریافت", - "spotlight": "اسپاٹ لائٹ" - }, - "add_friend_source_spoof": { - "added_by_username": "صارف نام کے ذریعہ", - "added_by_mention": "ذکر سے", - "added_by_group_chat": "گروپ چیٹ کے ذریعہ", - "added_by_qr_code": "بذریعہ QR کوڈ", - "added_by_community": "برادری کے ذریعہ", - "added_by_quick_add": "فوری اضافے کے ذریعہ (پابندی عائد ہونے کا زیادہ خطرہ)" - }, - "bypass_video_length_restriction": { - "single": "سنگل میڈیا", - "split": "تقسیم میڈیا" - }, - "old_bitmoji_selfie": { - "2d": "2 ڈی بٹ موجی", - "3d": "3D بٹ موجی" - }, - "disable_confirmation_dialogs": { - "erase_message": "مٹانے کا پیغام", - "remove_friend": "دوست کو ہٹا دیں", - "block_friend": "بلاک دوست", - "ignore_friend": "دوست کو نظرانداز کریں", - "hide_friend": "دوست چھپائیں", - "hide_conversation": "گفتگو چھپائیں", - "clear_conversation": "فرینڈ فیڈ سے واضح گفتگو" - }, - "auto_reload": { - "snapchat_only": "صرف اسنیپ چیٹ", - "all": "تمام (اسنیپ چیٹ + پورفیکٹسنیپ)" - }, - "edit_text_override": { - "multi_line_chat_input": "ملٹی لائن چیٹ ان پٹ", - "bypass_text_input_limit": "بائی پاس ٹیکسٹ ان پٹ کی حد" - }, - "auto_purge": { - "never": "کبھی نہیں", - "1_hour": "1 گھنٹہ", - "3_hours": "3 گھنٹے", - "6_hours": "6 گھنٹے", - "12_hours": "12 گھنٹے", - "1_day": "1 دن", - "3_days": "3 دن", - "1_week": "1 ہفتہ", - "2_weeks": "2 ہفتے", - "1_month": "1 مہینہ", - "3_months": "3 ماہ", - "6_months": "6 ماہ" - }, - "disable_story_sections": { - "friends": "دوستو", - "suggested_stories": "تجویز کردہ کہانیاں", - "following": "مندرجہ ذیل", - "discover": "دریافت" - }, - "disable_cameras": { - "front": "فرنٹ کیمرا", - "back": "بیک کیمرا" - }, - "disable_permission_requests": { - "notifications": "اطلاعات", - "read_media_images": "میڈیا کی تصاویر پڑھیں", - "read_media_video": "میڈیا ویڈیو پڑھیں", - "camera": "کیمرا", - "microphone": "مائکروفون", - "location": "مقام", - "read_contacts": "رابطے پڑھیں", - "nearby_devices": "قریبی آلات", - "phone_calls": "فون کالز" - }, - "message_indicators": { - "encryption_indicator": "ان پیغامات کے آگے ایک 🔒 آئیکن شامل کرتا ہے جو صرف آپ کو بھیجے گئے ہیں", - "platform_indicator": "پلیٹ فارم کا آئیکن شامل کرتا ہے جہاں سے میڈیا بھیجا گیا تھا (جیسے اینڈروئیڈ ، آئی او ایس ، ویب)", - "location_indicator": "جب وہ مقام کو فعال کے ساتھ بھیجا گیا ہے تو سنیپس میں ایک 📍 آئیکن شامل کرتا ہے", - "ovf_editor_indicator": "اس بات کی نشاندہی کرتا ہے کہ اگر او وی ایف ایڈیٹر کا استعمال کرتے ہوئے کوئی سنیپ بھیجا گیا ہے", - "director_mode_indicator": "جب وہ ڈائریکٹر وضع کا استعمال کرتے ہوئے بھیجے گئے ہیں تو سنیپس میں ایک ✏ آئیکن شامل کرتا ہے ، جسے گیلری کی تصاویر کو سنیپ کے طور پر بھیجنے کے لئے استعمال کیا جاسکتا ہے۔" - }, - "auto_mark_as_read": { - "conversation_read": "پیغام بھیجتے وقت گفتگو کو پڑھیں", - "snap_reply": "جب ان کا جواب دیتے ہو تو اس کو پڑھتے ہی نشان لگائیں", - "save_snap_in_chat": "اسٹیلتھ موڈ میں رہتے ہوئے چیٹ میں بچت کرتے وقت پڑھے جاتے ہی اس کی تصویر کو نشان زد کریں" - }, - "friend_mutation_notifier": { - "remove_friend": "مطلع کریں جب کوئی آپ کو دوست کی حیثیت سے ہٹاتا ہے", - "birthday_changes": "جب کوئی ان کی سالگرہ میں تبدیلی کرتا ہے تو مطلع کریں", - "bitmoji_selfie_changes": "مطلع کریں جب کوئی اپنی بٹ موجی سیلفی تبدیل کرتا ہے", - "bitmoji_avatar_changes": "مطلع کریں جب کوئی اپنے بٹ موجی اوتار کو تبدیل کرتا ہے", - "bitmoji_background_changes": "مطلع کریں جب کوئی اپنے بٹ موجی پس منظر کو تبدیل کرتا ہے", - "bitmoji_scene_changes": "جب کوئی اپنے بٹ موجی منظر کو تبدیل کرتا ہے تو مطلع کریں" - }, - "snapchat_plus": { - "not_subscribed": "سبسکرائب نہیں", - "basic": "بنیادی", - "ad_free": "مفت" - }, - "double_tap_chat_action": { - "like_message": "پیغام کی طرح", - "copy_text": "متن کو کلپ بورڈ میں کاپی کریں", - "delete_message": "پیغام کو حذف کریں", - "mark_as_read": "پڑھیں کے طور پر نشان زد کریں", - "custom_emoji_reaction": "کسٹم ایموجی رد عمل" - }, - "startup_default_camera": { - "front": "فرنٹ کیمرا", - "back": "بیک کیمرا" - } - } - }, - "friend_menu_option": { - "mark_snaps_as_seen": "جیسا کہ دیکھا گیا ہے مارک سنیپ", - "mark_stories_as_seen_locally": "کہانیوں کو نشان زد کریں جیسا کہ مقامی طور پر دیکھا گیا ہے", - "preview": "پیش نظارہ", - "stealth_mode": "اسٹیلتھ موڈ", - "auto_download_blacklist": "آٹو ڈاؤن لوڈ بلیک لسٹ", - "anti_auto_save": "اینٹی آٹو بچت" - }, - "content_type": { - "CHAT": "چیٹ", - "SNAP": "سنیپ", - "EXTERNAL_MEDIA": "بیرونی میڈیا", - "NOTE": "آڈیو نوٹ", - "STICKER": "اسٹیکر", - "SHARE": "بانٹیں", - "STATUS": "حیثیت", - "LOCATION": "مقام", - "STATUS_SAVE_TO_CAMERA_ROLL": "کیمرہ رول میں محفوظ", - "STATUS_CONVERSATION_CAPTURE_SCREENSHOT": "اسکرین شاٹ", - "STATUS_CONVERSATION_CAPTURE_RECORD": "اسکرین ریکارڈ", - "STATUS_CALL_MISSED_VIDEO": "ویڈیو کال چھوٹ گئی", - "STATUS_CALL_MISSED_AUDIO": "آڈیو کال سے محروم", - "LIVE_LOCATION_SHARE": "براہ راست مقام کا حصہ", - "CREATIVE_TOOL_ITEM": "تخلیقی ٹول آئٹم", - "FAMILY_CENTER_INVITE": "فیملی سینٹر دعوت نامہ", - "FAMILY_CENTER_ACCEPT": "فیملی سینٹر قبول کریں", - "FAMILY_CENTER_LEAVE": "فیملی سینٹر رخصت", - "STATUS_PLUS_GIFT": "حیثیت کے علاوہ تحفہ", - "TINY_SNAP": "چھوٹے سنیپ", - "STATUS_COUNTDOWN": "الٹی گنتی", - "MAP_REACTION": "نقشہ کا رد عمل" - }, - "media_download_source": { - "none": "کوئی نہیں", - "pending": "زیر التوا", - "chat_media": "چیٹ میڈیا", - "story": "کہانی", - "public_story": "عوامی کہانی", - "spotlight": "اسپاٹ لائٹ", - "profile_picture": "پروفائل تصویر", - "story_logger": "اسٹوری لاگر", - "message_logger": "میسج لاگر", - "merged": "ضم", - "voice_call": "صوتی کال" - }, - "chat_action_menu": { - "preview_button": "پیش نظارہ", - "download_button": "ڈاؤن لوڈ", - "delete_logged_message_button": "لاگ ان پیغام کو حذف کریں", - "show_chat_edit_history": "چیٹ میں ترمیم کی تاریخ دکھائیں", - "convert_message": "پیغام کو تبدیل کریں" - }, - "opera_context_menu": { - "download": "میڈیا ڈاؤن لوڈ کریں", - "sent_at": "__ placeholder_0__ پر بھیجا گیا", - "created_at": "__ placeholder_0__ پر تخلیق کیا گیا", - "expires_at": "__ پلیس ہولڈر_0 __ پر میعاد ختم ہوجاتا ہے", - "media_size": "میڈیا سائز: __ پلیس ہولڈر_0__", - "media_duration": "میڈیا کا دورانیہ: __ پلیس ہولڈر_0__ ایم ایس", - "show_debug_info": "ڈیبگ کی معلومات دکھائیں" - }, - "modal_option": { - "profile_info": "پروفائل کی معلومات", - "close": "بند کریں" - }, - "gallery_media_send_override": { - "multiple_media_toast": "آپ ایک وقت میں صرف ایک میڈیا بھیج سکتے ہیں" - }, - "mark_as_seen": { - "no_unseen_snaps_toast": "کوئی غیب سنیپ نہیں ملا!", - "seen_toast": "جیسا کہ دیکھا گیا ہے نشان زد!", - "unseen_toast": "غیب کے طور پر نشان زد!", - "already_seen_toast": "پہلے ہی دیکھا گیا ہے!", - "already_unseen_toast": "پہلے ہی غیب کے طور پر نشان زد کیا گیا ہے!" - }, - "conversation_preview": { - "streak_expiration": "__ placeholder_0__ دن __ پلیس ہولڈر_1__ گھنٹے __ __ پلیس ہولڈر_2 منٹ میں میعاد ختم ہوجاتی ہے", - "total_messages": "کل بھیجے/موصولہ پیغامات: __ پلیس ہولڈر_0__", - "title": "پیش نظارہ", - "unknown_user": "نامعلوم صارف", - "no_messages": "کوئی پیغامات نہیں ملے!" - }, - "profile_info": { - "title": "پروفائل کی معلومات", - "first_created_username": "پہلے صارف نام تخلیق کیا", - "mutable_username": "متغیر صارف نام", - "display_name": "نام ڈسپلے کریں", - "added_date": "شامل تاریخ", - "birthday": "سالگرہ: __ پلیس ہولڈر_0__ __ پلیس ہولڈر_1__", - "hidden_birthday": "سالگرہ: پوشیدہ", - "friendship": "دوستی", - "add_source": "ماخذ شامل کریں", - "snapchat_plus": "اسنیپ چیٹ پلس", - "snapchat_plus_state": { - "subscribed": "سبسکرائب", - "not_subscribed": "سبسکرائب نہیں" - } - }, - "friendship_link_type": { - "mutual": "باہمی", - "outgoing": "سبکدوش ہونے والا", - "blocked": "مسدود", - "deleted": "حذف", - "following": "مندرجہ ذیل", - "suggested": "تجویز کیا", - "incoming": "آنے والا", - "incoming_follower": "آنے والا پیروکار" - }, - "bulk_messaging_action": { - "choose_action_title": "ایک کارروائی کا انتخاب کریں", - "progress_status": "پروسیسنگ __ پلیس ہولڈر_0 __ __ پلیس ہولڈر_1__", - "selection_dialog_continue_button": "جاری رکھیں", - "confirmation_dialog": { - "title": "کیا آپ کو یقین ہے؟", - "message": "اس سے تمام منتخب دوستوں کو متاثر ہوگا۔ اس عمل کو ختم نہیں کیا جاسکتا۔" - }, - "actions": { - "remove_friends": "دوستوں کو ہٹا دیں", - "clear_conversations": "واضح گفتگو" - } - }, - "chat_export": { - "exporter_dialog": { - "select_conversations_title": "گفتگو کو منتخب کریں", - "text_field_selection": "__ پلیس ہولڈر_0__ منتخب کیا گیا", - "text_field_selection_all": "سب", - "export_file_format_title": "فائل فارمیٹ برآمد کریں", - "message_type_filter_title": "قسم کے لحاظ سے پیغامات کو فلٹر کریں", - "amount_of_messages_title": "پیغامات کی رقم (سب کے لئے اسے خالی چھوڑ دیں)", - "download_medias_title": "میڈیا کو ڈاؤن لوڈ کریں" - }, - "dialog_negative_button": "منسوخ کریں", - "dialog_positive_button": "برآمد", - "exported_to": "__ پلیس ہولڈر_0 کو برآمد کیا گیا", - "exporting_chats": "چیٹس برآمد کرنا ...", - "processing_chats": "پروسیسنگ __ پلیس ہولڈر_0__ گفتگو ...", - "export_fail": "گفتگو برآمد کرنے میں ناکام __ پلیس ہولڈر_0__", - "writing_output": "لکھنے کی پیداوار ...", - "finished": "کیا! اب آپ اس ڈائیلاگ کو بند کرسکتے ہیں۔", - "no_messages_found": "کوئی پیغامات نہیں ملے!", - "exporting_message": "__ پلیس ہولڈر_0 __..." - }, - "button": { - "ok": "ٹھیک ہے", - "positive": "ہاں", - "negative": "نہیں", - "cancel": "منسوخ کریں", - "open": "کھلا", - "download": "ڈاؤن لوڈ", - "send": "بھیجیں", - "restore_original": "اصل کو بحال کریں", - "convert_external_media": "بیرونی میڈیا کو تبدیل کریں", - "save": "بچت کریں" - }, - "tracker_events": { - "conversation_enter": "گفتگو داخل کریں", - "conversation_exit": "گفتگو سے باہر نکلیں", - "started_typing": "ٹائپ کرنا شروع کیا", - "stopped_typing": "ٹائپنگ بند کردی", - "started_speaking": "بولنے لگے", - "stopped_speaking": "بولنے سے رک گیا", - "started_peeking": "جھانکنا شروع کیا", - "stopped_peeking": "جھانکنا بند کردیا", - "message_read": "پیغام پڑھیں", - "message_deleted": "پیغام حذف ہوگیا", - "message_saved": "پیغام محفوظ ہوگیا", - "message_unsaved": "پیغام غیر محفوظ", - "message_edited": "پیغام میں ترمیم کی گئی", - "message_reaction_add": "پیغام کا رد عمل شامل کریں", - "message_reaction_remove": "پیغام کا رد عمل ہٹائیں", - "snap_opened": "سنیپ کھولی", - "snap_replayed": "سنیپ دوبارہ چلا گیا", - "snap_replayed_twice": "اسنیپ نے دو بار دوبارہ چلایا", - "snap_screenshot": "سنیپ اسکرین شاٹ", - "snap_screen_record": "سنیپ اسکرین ریکارڈ" - }, - "tracker_actions": { - "log": "لاگ", - "in_app_notification": "ایپ میں نوٹیفکیشن", - "push_notification": "نوٹیفیکیشن کو پش کریں", - "custom": "رواج" - }, - "better_notifications": { - "button": { - "reply": "جواب دیں", - "download": "ڈاؤن لوڈ", - "mark_as_read": "پڑھیں کے طور پر نشان زد کریں" - } - }, - "profile_picture_downloader": { - "button": "پروفائل تصویر ڈاؤن لوڈ کریں", - "title": "پروفائل تصویر ڈاؤن لوڈر", - "avatar_option": "اوتار", - "background_option": "پس منظر" - }, - "call_start_confirmation": { - "dialog_title": "کال شروع کریں", - "dialog_message": "کیا آپ واقعی کال شروع کرنا چاہتے ہیں؟" - }, - "half_swipe_notifier": { - "notification_channel_name": "آدھا سوائپ", - "notification_content_dm": "__ پلیس ہولڈر_0__ __ پلیس ہولڈر_1__ سیکنڈ کے لئے آپ کی چیٹ میں صرف آدھا سکیپ ہوا", - "notification_content_group": "__ پلیس ہولڈر_0__ __ پلیس ہولڈر_2__ سیکنڈ کے لئے __ پلیس ہولڈر_1__ میں صرف آدھا سوئپ کیا گیا" - }, - "download_processor": { - "attachment_type": { - "snap": "سنیپ", - "sticker": "اسٹیکر", - "gif": "gif", - "external_media": "بیرونی میڈیا", - "note": "نوٹ", - "original_story": "اصل کہانی" - }, - "select_attachments_title": "منسلکات کو منتخب کریں", - "download_started_toast": "ڈاؤن لوڈ شروع", - "unsupported_content_type_toast": "غیر تعاون یافتہ مواد کی قسم!", - "failed_no_longer_available_toast": "میڈیا اب دستیاب نہیں ہے", - "no_attachments_toast": "کوئی اٹیچمنٹ نہیں ملی!", - "already_queued_toast": "میڈیا پہلے ہی قطار میں ہے!", - "already_downloaded_toast": "میڈیا پہلے ہی ڈاؤن لوڈ ہوچکا ہے!", - "content_saved_toast": "بچایا!", - "download_toast": "ڈاؤن لوڈ کرنا __ پلیس ہولڈر_0 __...", - "processing_toast": "پروسیسنگ __ پلیس ہولڈر_0 __...", - "failed_generic_toast": "ڈاؤن لوڈ کرنے میں ناکام", - "failed_to_create_preview_toast": "پیش نظارہ بنانے میں ناکام", - "failed_processing_toast": "پروسیسنگ __ پلیس ہولڈر_0 __", - "failed_gallery_toast": "گیلری میں بچت میں ناکام __ پلیس ہولڈر_0__", - "dash_no_chapter": "کوئی باب نہیں ملا", - "dash_dialog": { - "title": "ڈیش میڈیا ڈاؤن لوڈ کریں", - "download_all": "سب ڈاؤن لوڈ کریں", - "segment_text": "طبقہ __ پلیس ہولڈر_0__ - __ پلیس ہولڈر_1__" - } - }, - "streaks_reminder": { - "notification_title": "لکیریں", - "notification_text": "آپ __ پلیس ہولڈر_0 __ میں __ پلیس ہولڈر_0 __ میں __ پلیس ہولڈر_0 __ کے ساتھ اپنا سلسلہ کھو دیں گے" - }, - "biometric_auth": { - "unlock_button": "غیر مقفل", - "title": "اسنیپ چیٹ انلاک کریں", - "subtitle": "براہ کرم اسنیپ چیٹ کو غیر مقفل کرنے کے لئے توثیق کریں" - }, - "end_to_end_encryption": { - "toolbox": { - "no_shared_key": "آپ کے پاس ابھی تک اس دوست کے ساتھ مشترکہ راز نہیں ہے۔ نیا شروع کرنے کے لئے نیچے کلک کریں۔", - "shared_key_fingerprint": "آپ کا فنگر پرنٹ یہ ہے:\n\n__ پلیس ہولڈر_0__\n\nاس بات کو یقینی بنائیں کہ آیا یہ آپ کے دوست کے فنگر پرنٹ سے مماثل ہے!", - "initiate_exchange_button": "کلیدی تبادلہ شروع کریں" - }, - "confirmation_dialogs": { - "title": "اختتام سے آخر میں خفیہ کاری", - "confirmation_1": "انتباہ: یہ آپ کی موجودہ کلید کو اوور رائٹ کرے گا۔ آپ اس دوست کے تمام خفیہ پیغامات تک رسائی کھو دیں گے۔ کیا آپ واقعی جاری رکھنا چاہتے ہیں؟", - "confirmation_2": "کیا آپ واقعی یقین رکھتے ہیں کہ آپ جاری رکھنا چاہتے ہیں؟ واپس آنے کا یہ آپ کا آخری موقع ہے۔" - }, - "unencrypted_conversation_send_failure_toast": "آپ خفیہ کردہ اور غیر خفیہ کردہ گفتگو دونوں کو خفیہ کردہ مواد نہیں بھیج سکتے ہیں!", - "native_hooks_send_failure_toast": "بھیجنے میں ناکام! براہ کرم ترتیبات میں مقامی ہکس کو فعال کریں۔", - "no_participants_to_encrypt_toast": "اس گفتگو میں آپ کے کوئی دوست نہیں ہیں جن کے ساتھ پیغامات کو خفیہ کریں۔", - "encryption_failed_toast": "پیغام کو خفیہ کرنے میں ناکام! مزید تفصیلات کے لئے لاگ کیٹ چیک کریں۔", - "accept_public_key_success_toast": "عوامی کلید کو کامیابی کے ساتھ قبول کیا گیا!", - "accept_secret_key_success_toast": "کیا! اب آپ اس دوست کے ساتھ خفیہ کردہ پیغامات بھیج سکتے اور وصول کرسکتے ہیں۔", - "accept_public_key_failure_toast": "عوامی کلید کو قبول کرنے میں ناکام", - "accept_secret_key_failure_toast": "خفیہ کلید قبول کرنے میں ناکام", - "accept_secret_button": "راز قبول کریں", - "accept_public_key_button": "عوامی کلید کو قبول کریں", - "outgoing_pk_message": "کلیدی تبادلہ کی درخواست", - "outgoing_secret_message": "کلیدی تبادلہ جواب", - "incoming_pk_message": "آپ کو ابھی ایک عوامی کلیدی درخواست موصول ہوئی ہے۔ اسے قبول کرنے کے لئے نیچے کلک کریں۔", - "incoming_secret_message": "آپ کے دوست نے ابھی آپ کی عوامی کلید کو قبول کیا۔ راز کو قبول کرنے کے لئے نیچے کلک کریں۔" - }, - "auto_open_snaps": { - "title": "آٹو اوپن سنیپس", - "notification_content": "__ پلیس ہولڈر_0 __ سنیپ کھل گئے" - }, - "friend_mutation_observer": { - "notification_channel_name": "دوست اتپریورتن مبصر", - "friend_removed": "__ پلیس ہولڈر_0__ نے آپ کو دوست کی حیثیت سے ہٹا دیا ہے", - "birthday_removed": "__ پلیس ہولڈر_0__ نے ان کی سالگرہ کو ہٹا دیا ہے (__ پلیس ہولڈر_1__)", - "birthday_added": "__ پلیس ہولڈر_0__ نے ان کی سالگرہ (__ پلیس ہولڈر_1__) شامل کی ہے", - "birthday_changed": "__ پلیس ہولڈر_0__ نے ان کی سالگرہ __ پلیس ہولڈر_1__ سے __ پلیس ہولڈر_2__ میں تبدیل کردی ہے۔", - "bitmoji_selfie_changed": "__ پلیس ہولڈر_0__ نے ان کی بٹ موجی سیلفی کو تبدیل کردیا ہے", - "bitmoji_avatar_changed": "__ پلیس ہولڈر_0__ نے ان کے بٹ موجی اوتار کو تبدیل کردیا ہے", - "bitmoji_background_changed": "__ پلیس ہولڈر_0__ نے ان کے بٹ موجی پس منظر کو تبدیل کردیا ہے", - "bitmoji_scene_changed": "__ پلیس ہولڈر_0__ نے ان کے بٹ موجی منظر کو تبدیل کردیا ہے" - }, - "material3_strings": { - "date_range_picker_start_headline": "سے", - "date_range_picker_end_headline": "to", - "date_range_picker_title": "تاریخ کی حد منتخب کریں", - "date_picker_switch_to_calendar_mode": "کیلنڈر", - "date_picker_switch_to_input_mode": "ان پٹ", - "date_range_picker_scroll_to_previous_month": "پچھلا مہینہ", - "date_range_picker_scroll_to_next_month": "اگلا مہینہ", - "date_picker_today_description": "آج", - "date_range_picker_day_in_range": "منتخب", - "date_input_invalid_for_pattern": "غلط تاریخ", - "date_input_invalid_year_range": "غلط سال", - "date_input_invalid_not_allowed": "غلط تاریخ", - "date_range_input_invalid_range_input": "غلط تاریخ کی حد" - }, - "send_override_dialog": { - "title": "میڈیا کو __ پلیس ہولڈر_0__ کے بطور بھیجیں", - "duration": "دورانیہ: __ پلیس ہولڈر_0__", - "saveable_snap_hint": "چیٹ میں اسنیپ کو بچانے کے قابل بنائیں", - "unlimited_duration": "لامحدود" - }, - "invalid_input_toast": "غلط ان پٹ! اس بات کو یقینی بنائیں کہ آپ نے ایک درست قدر درج کی ہے۔" -} \ No newline at end of file diff --git a/common/src/main/assets/lang/vi.json b/common/src/main/assets/lang/vi.json deleted file mode 100644 index 74c28284..00000000 --- a/common/src/main/assets/lang/vi.json +++ /dev/null @@ -1,2022 +0,0 @@ -{ - "setup": { - "dialogs": { - "select_language": "Chọn ngôn ngữ", - "save_folder": "PurrfectSnap yêu cầu quyền lưu trữ để tải xuống và lưu phương tiện từ Snapchat.\nVui lòng chọn vị trí nơi phương tiện sẽ được tải xuống.", - "select_save_folder_button": "Chọn thư mục" - }, - "mappings": { - "dialog": "Đang tạo Ánh xạ, quá trình này có thể mất một lúc ...", - "generate_failure_no_snapchat": "PurrfectSnap không thể phát hiện Snapchat, vui lòng thử cài đặt lại Snapchat.", - "generate_failure": "Đã xảy ra lỗi khi cố gắng tạo ánh xạ, vui lòng thử lại." - }, - "permissions": { - "dialog": "Để tiếp tục, bạn cần phải đáp ứng các yêu cầu sau:", - "notification_access": "Truy cập thông báo", - "battery_optimization": "Tối ưu hóa pin", - "display_over_other_apps": "Hiển thị trên các ứng dụng khác", - "request_button": "Lời yêu cầu" - } - }, - "scopes": { - "friend": "Bạn bè", - "group": "Nhóm" - }, - "manager": { - "routes": { - "tasks": "Nhiệm vụ", - "features": "Đặc trưng", - "manage_rule_feature": "Quản lý tính năng quy tắc", - "home": "Trang chủ", - "home_settings": "Cài đặt", - "home_logs": "Nhật ký", - "logger_history": "Lịch sử ghi nhật ký", - "logged_stories": "Câu chuyện đã đăng nhập", - "friend_tracker": "Theo dõi bạn bè", - "edit_rule": "Chỉnh sửa quy tắc", - "file_imports": "Nhập tệp", - "manage_repos": "Quản lý kho lưu trữ", - "social": "Xã hội", - "manage_scope": "Quản lý phạm vi", - "messaging_preview": "Xem trước", - "scripts": "Tập lệnh", - "better_location": "Vị trí tốt hơn" - }, - "sections": { - "home": { - "version_title": "v{versionName} · phân nhánh bởi Eternal", - "update_title": "Cập nhật PurrfectSnap", - "update_content": "Đã có phiên bản {version}!", - "update_button": "Tải xuống", - "debug_build_summary_title": "Bạn đang chạy bản dựng gỡ lỗi của PurrfectSnap", - "debug_build_summary_content": "Phiên bản {versionName} ({versionCode})", - "debug_build_summary_date": "Ngày xây dựng: {date} ({days} ngày trước)", - "quick_actions_title": "Thao tác nhanh", - "download_icon_description": "Tải xuống", - "completed_icon_description": "Hoàn thành", - "failed_icon_description": "Thất bại", - "manage_quick_actions_description": "Quản lý thao tác nhanh", - "quick_actions_icon_description": "Thao tác nhanh", - "add_quick_action_description": "Thêm hành động nhanh" - }, - "home_logs": { - "no_logs_hint": "Không có nhật ký nào", - "clear_logs_button": "Xóa nhật ký", - "export_logs_button": "Xuất nhật ký", - "saving_logs_toast": "Đang lưu nhật ký, quá trình này có thể mất một lúc...", - "saved_logs_success_toast": "Nhật ký được lưu thành công", - "saved_logs_failure_toast": "Không lưu được nhật ký" - }, - "home_settings": { - "actions_title": "hành động", - "message_logger_title": "Trình ghi tin nhắn", - "debug_title": "Gỡ lỗi", - "success_toast": "Xong!", - "message_logger_summary": "__giữ chỗ_0__ tin nhắn\n__giữ chỗ_1__ câu chuyện", - "export_button": "Xuất khẩu", - "clear_button": "Thông thoáng", - "view_logger_history_button": "Xem lịch sử ghi nhật ký", - "updates_title": "Cập nhật", - "auto_update_check": "Tự động kiểm tra các bản cập nhật", - "update_check_frequency": "Tần suất kiểm tra cập nhật", - "update_check_frequency_daily": "Hằng ngày", - "update_check_frequency_weekly": "hàng tuần", - "update_check_frequency_monthly": "hàng tháng", - "theme_icon_description": "chủ đề", - "app_theme_title": "Chủ đề ứng dụng", - "theme_mode_system": "Hệ thống", - "theme_mode_light": "Ánh sáng", - "theme_mode_dark": "Tối tăm", - "ui_settings_title": "Cài đặt giao diện người dùng", - "haptic_feedback_label": "Phản hồi xúc giác", - "test_mode_label": "Chế độ kiểm tra (CHỈ ĐỂ GỠ LỖI)", - "disable_feature_loading_label": "Tắt tải tính năng", - "disable_auto_mapper_label": "Tắt Trình ánh xạ tự động", - "disable_bypass_indicator_label": "Tắt chỉ báo trạng thái bỏ qua", - "update_notification_channel_name": "Cập nhật PurrfectSnap", - "update_notification_channel_description": "Thông báo về cập nhật PurrfectSnap", - "update_notification_title": "Đã có bản cập nhật PurrfectSnap", - "update_notification_text": "Hiện đã có phiên bản %s.", - "export_database_failed_toast": "Không xuất được cơ sở dữ liệu! __giữ chỗ_0__", - "clear_messages_failed_toast": "Không thể xóa tin nhắn! __giữ chỗ_0__", - "clear_file_failed_toast": "Không thể xóa tập tin! __giữ chỗ_0__", - "debug_file_config": "Cấu hình", - "debug_file_mappings": "Ánh xạ", - "debug_file_message_logger": "Trình ghi tin nhắn", - "debug_file_pinned_best_friend": "Đã ghim người bạn thân nhất", - "debug_file_native_sig_cache": "Bộ đệm chữ ký gốc" - }, - "tasks": { - "no_tasks": "Không có nhiệm vụ", - "merge_button": "Hợp nhất", - "failed_to_open_file": "Không mở được tập tin", - "merge_files_toast": "Hợp nhất các tệp {count}", - "remove_selected_tasks_title": "Bạn có chắc chắn muốn xóa các tác vụ đã chọn không?", - "remove_all_tasks_title": "Bạn có chắc chắn muốn xóa tất cả công việc không?", - "delete_files_option": "Đồng thời xóa các tập tin", - "remove_selected_tasks_confirm": "Xóa nhiệm vụ {count}?", - "remove_all_tasks_confirm": "Xóa tất cả việc cần làm?", - "clear_tasks_description": "Xóa nhiệm vụ", - "file_not_found_icon_description": "Không tìm thấy tập tin", - "image_icon_description": "Hình ảnh", - "video_icon_description": "Băng hình", - "audio_icon_description": "Âm thanh", - "file_icon_description": "Tài liệu", - "download_icon_description": "Tải xuống", - "chat_action_icon_description": "Hành động trò chuyện", - "cancel_icon_description": "Hủy bỏ", - "success_icon_description": "Thành công", - "failure_icon_description": "Sự thất bại", - "cancelled_icon_description": "Đã hủy", - "task_status_failure": "Sự thất bại", - "task_status_cancelled": "Đã hủy" - }, - "features": { - "disabled": "Tàn tật", - "export_option": "Xuất khẩu", - "import_option": "Nhập khẩu", - "reset_option": "Cài lại", - "config_export_success_toast": "Đã xuất cấu hình thành công", - "config_import_success_toast": "Cấu hình được nhập thành công", - "config_import_failure_toast": "Không nhập được cấu hình {error}", - "config_export_failure_toast": "Không xuất được cấu hình {error}", - "saved_config_snackbar": "Đã lưu cấu hình", - "older_required": "Tính năng này yêu cầu Snapchat v{version} trở lên để hoạt động chính xác", - "newer_required": "Tính năng này yêu cầu Snapchat v{version} hoặc mới hơn để hoạt động chính xác", - "search_button": "Tìm kiếm" - }, - "manage_rule_feature": { - "disable_state_option": "Tàn tật", - "disable_state_subtext": "Không có bạn bè/nhóm nào sẽ bị ảnh hưởng", - "whitelist_state_option": "Không ai ngoại trừ...", - "whitelist_state_subtext": "Chỉ {count} bạn bè/nhóm sẽ bị ảnh hưởng bởi quy tắc này", - "whitelist_state_button": "Chọn bạn bè/nhóm được phép", - "blacklist_state_option": "Tất cả mọi người ngoại trừ...", - "blacklist_state_subtext": "Mọi người ngoại trừ {count} bạn bè/nhóm sẽ bị ảnh hưởng bởi quy tắc này", - "blacklist_state_button": "Chọn bạn bè/nhóm bị loại trừ", - "clear_list_button": "Xóa danh sách bạn bè/nhóm", - "dialog_clear_confirmation_text": "Bạn có chắc chắn muốn xóa danh sách không?" - }, - "social": { - "friends_tab": "Bạn", - "groups_tab": "Nhóm", - "empty_hint": "(trống)", - "streaks_expiration_short": "__giữ chỗ_0__h" - }, - "manage_scope": { - "logged_stories_button": "Hiển thị các câu chuyện đã ghi", - "e2ee_title": "Mã hóa đầu cuối", - "rules_title": "Quy tắc", - "participants_text": "__giữ chỗ_0__ người tham gia", - "not_found": "Không tìm thấy", - "streaks_title": "Vệt", - "streaks_length_text": "Độ dài: {length}", - "streaks_expiration_text": "Hết hạn sau {eta}", - "streaks_expiration_text_expired": "Hết hạn", - "reminder_button": "Đặt lời nhắc", - "delete_scope_confirm_dialog_title": "Bạn có chắc chắn muốn xóa {scope} không?", - "notes_placeholder": "Bấm để thêm ghi chú", - "invalid_key_size_32_bytes": "Kích thước khóa không hợp lệ (phải là 32 byte)", - "successfully_imported_key": "Đã nhập khóa thành công", - "failed_to_import_key": "Không nhập được khóa: {message}", - "export_base64_button": "Xuất khẩu Base64", - "import_base64_button": "Cơ sở nhập khẩu64" - }, - "logged_stories": { - "story_failed_to_load": "Không tải được", - "no_stories": "Không tìm thấy câu chuyện nào", - "save_from_cache_button": "Lưu từ bộ nhớ đệm", - "downloaded_to_path": "Đã tải xuống {path}", - "download_failed": "Tải xuống không thành công: {message}", - "posted_at": "Đăng tại {date}", - "created_at": "Được tạo tại {date}", - "failed_to_open_file": "Không thể mở tập tin. Kiểm tra nhật ký để biết thêm thông tin", - "failed_to_get_file": "Không lấy được tập tin" - }, - "messaging_preview": { - "processed_messages_toast": "Đã xử lý {count} tin nhắn", - "processed_messages_text": "Đã xử lý {count} tin nhắn", - "close_button_description": "Đóng", - "bridge_connection_failed": "Không thể kết nối với cầu. Đảm bảo Snapchat đang chạy ở chế độ nền", - "bridge_init_failed": "Không khởi tạo được cầu nối nhắn tin. Đảm bảo Snapchat đang chạy ở chế độ nền", - "message_fetch_failed": "Không tìm nạp được tin nhắn", - "no_message_hint": "Không có tin nhắn", - "save_selection_option": "Lưu lựa chọn", - "save_all_option": "Lưu tất cả", - "unsave_selection_option": "Bỏ lưu lựa chọn", - "unsave_all_option": "Bỏ lưu tất cả", - "mark_selection_as_seen_option": "Đánh dấu chọn Snap là đã xem", - "mark_all_as_seen_option": "Đánh dấu tất cả Snaps là đã xem", - "delete_selection_option": "Xóa lựa chọn", - "delete_all_option": "Xóa tất cả" - }, - "logger_history": { - "download_started_toast": "Đã bắt đầu tải xuống!", - "download_success_toast": "Đã tải xuống {path}", - "download_failed_toast": "Không tải xuống được {message}", - "edited_at_text": "{message} (được chỉnh sửa tại {date})", - "download_button": "Tải xuống", - "select_conversation_placeholder": "Chọn một cuộc trò chuyện", - "close_button_description": "Đóng", - "search_button_description": "Tìm kiếm", - "list_friend_format": "Bạn bè __giữ chỗ_0__", - "list_group_format": "Nhóm __giữ chỗ_0__", - "no_more_messages": "Không còn tin nhắn nào nữa", - "reverse_order_checkbox": "Thứ tự ngược lại", - "chat_attachment": "Tệp đính kèm {index}", - "empty_message": "Tin nhắn trò chuyện trống", - "message_parse_failed": "Không thể phân tích tin nhắn", - "unknown_sender": "Người gửi không xác định", - "download_attachment_failed_toast": "Không tải được tệp đính kèm xuống", - "log_header_format": "{username} ({type}) - {date}" - }, - "file_imports": { - "import_file_button": "Nhập tệp", - "file_not_found": "Không tìm thấy tập tin", - "file_import_failed": "Không thể nhập tệp: {error}", - "file_imported": "Đã nhập tệp thành công", - "file_delete_failed": "Không thể xóa tập tin", - "no_files_hint": "Tại đây bạn có thể nhập tệp để sử dụng trong Snapchat. Nhấn nút bên dưới để nhập tập tin." - }, - "better_location": { - "spoofed_coordinates_title": "Vĩ độ {latitude}, Long {longitude}", - "save_coordinates_dialog_title": "Lưu tọa độ", - "saved_name_dialog_hint": "Tên đã lưu", - "latitude_dialog_hint": "Vĩ độ", - "longitude_dialog_hint": "Kinh độ", - "save_dialog_button": "Cứu", - "choose_location_button": "Chọn vị trí", - "teleport_to_friend_button": "Dịch chuyển đến bạn bè", - "spoof_location_toggle": "Vị trí giả mạo", - "suspend_location_updates": "Tạm dừng cập nhật vị trí", - "saved_coordinates_title": "Tọa độ đã lưu", - "no_saved_coordinates_hint": "Không có tọa độ nào được lưu", - "delete_dialog_title": "Xóa tọa độ đã lưu", - "delete_dialog_message": "Bạn có chắc chắn muốn xóa tọa độ đã lưu này không?", - "teleport_to_friend_title": "Dịch chuyển đến bạn bè", - "search_bar": "Tìm kiếm", - "no_friends_map": "Không có bạn bè trên bản đồ", - "no_friends_found": "Không tìm thấy bạn bè", - "edit_location_button_description": "Chỉnh sửa vị trí", - "add_icon_description": "Thêm vào", - "edit_icon_description": "Biên tập", - "delete_icon_description": "Xóa bỏ" - } - }, - "dialogs": { - "add_friend": { - "title": "Thêm bạn bè hoặc nhóm", - "search_hint": "Tìm kiếm", - "fetch_error": "Không thể tìm nạp dữ liệu", - "category_groups": "Nhóm", - "category_friends": "Bạn", - "participants_text": "__giữ chỗ_0__ người tham gia", - "search_icon_description": "Tìm kiếm" - }, - "scripting_warning": { - "title": "Cảnh báo", - "content": "PurrfectSnap bao gồm một công cụ tạo tập lệnh, cho phép thực thi mã do người dùng xác định trên thiết bị của bạn. Hãy hết sức thận trọng và chỉ cài đặt các mô-đun từ các nguồn đã biết, đáng tin cậy. Các mô-đun trái phép hoặc chưa được xác minh có thể gây ra rủi ro bảo mật cho hệ thống của bạn." - }, - "reset_config": { - "title": "Đặt lại cấu hình", - "content": "Bạn có chắc chắn muốn đặt lại cấu hình không?", - "success_toast": "Đặt lại cấu hình thành công" - }, - "export_config": { - "title": "Xuất dữ liệu nhạy cảm?", - "content": "Bạn có muốn xuất cấu hình có dữ liệu nhạy cảm không? (Chẳng hạn như tọa độ vị trí, v.v.)" - }, - "messaging_action": { - "title": "Chọn loại nội dung để xử lý", - "select_all_button": "Chọn tất cả" - }, - "file_imports": { - "no_files_settings_hint": "Không tìm thấy tập tin nào. Đảm bảo bạn đã nhập các tệp được yêu cầu trong phần Nhập tệp", - "settings_select_file_hint": "Chọn một tập tin đã nhập" - }, - "quick_actions_dialog": { - "title": "Chỉnh sửa thao tác nhanh", - "subtitle": "Chọn và kích thước các hành động nhanh chóng của bạn." - } - }, - "friend_tracker": { - "rules_tab": "Quy tắc", - "logs_tab": "Nhật ký", - "export_dialog_title": "Xuất khẩu", - "bulk_export_button": "Xuất số lượng lớn", - "individual_export_button": "Xuất riêng lẻ", - "invalid_import_type_dialog_title": "Loại nhập không hợp lệ", - "invalid_import_type_dialog_text": "Tệp đã chọn không tương thích với kiểu nhập này. Vui lòng chọn đúng loại nhập.", - "import_dialog_title": "Nhập khẩu", - "bulk_import_button": "Nhập số lượng lớn", - "individual_import_button": "Nhập khẩu riêng lẻ", - "import_button_description": "Nhập khẩu", - "export_button_description": "Xuất khẩu", - "export_button": "Xuất khẩu", - "delete_button_description": "Xóa bỏ", - "delete_button": "Xóa bỏ", - "catalog_button_description": "Danh mục", - "catalog_button": "Danh mục", - "add_rule_button_description": "Thêm quy tắc", - "add_rule_button": "Thêm quy tắc", - "no_rules_found": "Không tìm thấy quy tắc nào", - "empty_rule_name": "(trống)", - "events_suffix": "sự kiện", - "scopes_suffix": "phạm vi", - "select_rule_to_export_title": "Chọn quy tắc để xuất", - "deleted_logs_toast": "Đã xóa nhật ký {count}", - "delete_logs_dialog_title": "Xóa nhật ký?", - "deleting_logs_dialog_text": "Đang xóa nhật ký {count}...", - "delete_logs_dialog_confirm_text": "Thao tác này sẽ xóa nhật ký dựa trên bộ lọc hiện tại và truy vấn tìm kiếm. Không thể hoàn tác hành động này.", - "exported_logs_toast": "Nhật ký đã xuất!", - "export_logs_failed_toast": "Không thể xuất nhật ký. Kiểm tra logcat để biết thêm chi tiết.", - "export_logs_dialog_title": "Xuất nhật ký?", - "exporting_logs_dialog_text": "Đang xuất nhật ký...", - "export_logs_dialog_confirm_text": "Thao tác này sẽ xuất nhật ký dựa trên bộ lọc hiện tại và truy vấn tìm kiếm.", - "export_as_button": "Xuất dưới dạng {type}", - "filters_title": "Bộ lọc", - "search_by_label": "Tìm kiếm theo", - "newest_first_label": "Mới nhất đầu tiên", - "since_label": "Từ", - "until_label": "Cho đến khi", - "pick_a_date_button": "Chọn một ngày", - "search_placeholder": "Tìm kiếm", - "filter_button_description": "Lọc", - "clear_button_description": "Thông thoáng", - "no_logs_found": "Không tìm thấy nhật ký nào", - "log_event_format": "{event} trong {conversation}", - "condition_only_inside_conversation": "Chỉ khi tôi ở trong cuộc trò chuyện", - "condition_only_outside_conversation": "Chỉ khi tôi ở bên ngoài trò chuyện", - "condition_only_when_app_active": "Chỉ khi Snapchat hoạt động", - "condition_only_when_app_inactive": "Chỉ khi Snapchat không hoạt động", - "condition_no_push_notification_when_app_active": "Không có thông báo khi Snapchat hoạt động", - "add_event_dialog_title": "Thêm sự kiện", - "event_type_label": "Loại sự kiện", - "triggers_title": "Trình kích hoạt", - "conditions_title": "Điều kiện", - "add_button": "Thêm vào", - "default_rule_name": "Quy tắc tùy chỉnh", - "discard_changes_dialog_title": "Hủy thay đổi?", - "discard_changes_dialog_text": "Bạn có những thay đổi chưa được lưu. Bạn có chắc chắn muốn loại bỏ chúng không?", - "discard_button": "Loại bỏ", - "cannot_save_rule_dialog_title": "Không thể lưu quy tắc", - "cannot_save_rule_dialog_text": "Một quy tắc phải có ít nhất một sự kiện để lưu.", - "duplicate_rule_name_dialog_title": "Tên quy tắc trùng lặp", - "duplicate_rule_name_dialog_text": "Một quy tắc có tên này đã tồn tại. Vui lòng chọn một tên khác.", - "delete_rule_dialog_title": "Xóa quy tắc", - "delete_rule_dialog_text": "Bạn có chắc chắn muốn xóa quy tắc này không?", - "new_rule_title": "Quy tắc mới", - "edit_rule_title": "Chỉnh sửa quy tắc", - "back_button_description": "Mặt sau", - "save_button_description": "Cứu", - "general_section_title": "Tổng quan", - "rule_name_label": "Tên quy tắc", - "author_name_label": "Tên tác giả", - "scope_section_title": "Phạm vi", - "scope_all": "Tất cả", - "scope_whitelist": "Danh sách trắng", - "scope_blacklist": "Danh sách đen", - "select_friends_groups_button": "Chọn Bạn bè/Nhóm ({count})", - "events_section_title": "Sự kiện", - "add_event_button": "Thêm sự kiện", - "no_events_text": "Không có sự kiện" - }, - "friend_tracker_catalog": { - "download_failed": "Tải xuống không thành công: {code}", - "error": "Lỗi: {message}", - "no_repos_added": "Không có kho lưu trữ nào được thêm vào.", - "no_rules_available": "Không có quy tắc nào có sẵn từ bất kỳ repo nào.", - "by_author": "bởi {author}", - "imported_button": "Đã nhập", - "import_button": "Nhập khẩu", - "title": "Danh mục theo dõi bạn bè", - "manage_repos_description": "Quản lý kho lưu trữ" - }, - "friend_tracker_export": { - "title": "Quy tắc xuất khẩu", - "back_button_description": "Mặt sau", - "exported_toast": "Đã xuất quy tắc theo dõi bạn bè!", - "export_failed_toast": "Không xuất được quy tắc: {message}", - "save_button": "Cứu", - "expand_button_description": "Mở rộng" - }, - "friend_tracker_import": { - "title": "Quy tắc nhập khẩu", - "back_button_description": "Mặt sau", - "imported_toast": "Đã nhập quy tắc theo dõi bạn bè!", - "import_failed_toast": "Không thể nhập quy tắc: {message}", - "confirm_button": "Xác nhận", - "expand_button_description": "Mở rộng" - }, - "friend_tracker_repos": { - "invalid_repo_title": "Kho lưu trữ không hợp lệ", - "add_repo_button": "Thêm kho lưu trữ", - "add_repo_dialog_title": "Thêm URL kho lưu trữ", - "repo_url_label": "URL kho lưu trữ", - "repo_added_toast": "Đã thêm kho lưu trữ thành công!", - "invalid_repo_error": "Có vẻ như đây không phải là kho lưu trữ theo dõi bạn bè hợp lệ.", - "add_repo_failed_toast": "Không thêm được kho lưu trữ: {message}", - "add_button": "Thêm vào", - "no_repos_added": "Không có kho lưu trữ nào được thêm vào", - "remove_button": "Di dời", - "remove_repo_dialog_title": "Xóa kho lưu trữ", - "remove_repo_dialog_text": "Bạn có chắc chắn muốn xóa kho lưu trữ này không?" - }, - "navigation": { - "tracker_tab_label": "Trình theo dõi", - "customize_bottom_bar_title": "Tùy chỉnh thanh dưới cùng", - "customize_bottom_bar_subtitle": "Sắp xếp lại, thêm hoặc xóa các tab. Tối đa là năm.", - "shown_tabs_title": "Tab được hiển thị", - "no_tabs_selected_text": "Không có tab nào được chọn", - "available_tabs_title": "Các tab có sẵn", - "reset_button": "Cài lại", - "done_button": "Xong" - }, - "scripting": { - "script_already_installed": "Tập lệnh đã được cài đặt sẵn!", - "downloading_script": "Đang tải xuống tập lệnh...", - "script_downloaded": "Đã tải xuống tập lệnh {name}!", - "download_script_failed": "Không tải được tập lệnh xuống. Kiểm tra nhật ký để biết thêm chi tiết", - "import_script_from_url_title": "Nhập tập lệnh từ URL", - "import_script_warning": "Cảnh báo: Các tập lệnh đã nhập có thể gây hại cho thiết bị của bạn. Chỉ nhập tập lệnh từ các nguồn đáng tin cậy.", - "enter_url_label": "Nhập URL vào đây:", - "script_imported": "Đã nhập tập lệnh {name}!", - "import_failed": "Không thể nhập tập lệnh. __giữ chỗ_0__. Kiểm tra nhật ký để biết thêm chi tiết", - "import_button": "Nhập khẩu", - "update_module_button": "Mô-đun cập nhật", - "updating_script": "Đang cập nhật tập lệnh {name}...", - "module_not_found": "Không tìm thấy mô-đun", - "updated_script": "Đã cập nhật {name} lên phiên bản {version}", - "update_module_failed": "Không thể cập nhật mô-đun. Kiểm tra nhật ký để biết thêm chi tiết", - "edit_module_button": "Chỉnh sửa mô-đun", - "open_module_failed": "Không thể mở tập tin mô-đun. Kiểm tra nhật ký để biết thêm chi tiết", - "clear_module_data_button": "Xóa dữ liệu mô-đun", - "module_data_cleared": "Đã xóa dữ liệu mô-đun!", - "clear_module_data_failed": "Không thể xóa dữ liệu mô-đun. Kiểm tra nhật ký để biết thêm chi tiết", - "delete_module_button": "Xóa mô-đun", - "deleted_script": "Đã xóa tập lệnh {name}!", - "delete_module_failed": "Không thể xóa mô-đun. Kiểm tra nhật ký để biết thêm chi tiết", - "actions_title": "hành động", - "no_description": "Không có mô tả", - "update_available": "Đã có bản cập nhật: {version}", - "actions_button": "hành động", - "loaded_script": "Đã tải tập lệnh {name}", - "unloaded_script": "Tập lệnh đã được dỡ bỏ {name}", - "enable_script_failed": "Không bật được tập lệnh. Kiểm tra nhật ký để biết thêm chi tiết", - "disable_script_failed": "Không tắt được tập lệnh. Kiểm tra nhật ký để biết thêm chi tiết", - "select_scripts_folder_toast": "Vui lòng chọn thư mục tập lệnh của bạn!", - "manage_repos_button": "Quản lý kho lưu trữ", - "import_from_url_button": "Nhập từ URL", - "open_scripts_folder_button": "Mở thư mục tập lệnh", - "no_settings_for_module": "Mô-đun này không có bất kỳ cài đặt nào", - "installed_scripts_tab": "Tập lệnh đã cài đặt", - "catalog_tab": "Danh mục", - "no_scripts_folder_selected_title": "Không có thư mục tập lệnh nào được chọn", - "select_folder_button": "Chọn thư mục", - "no_scripts_found_title": "Không tìm thấy tập lệnh nào.", - "use_catalog_to_add_scripts": "Sử dụng tab danh mục để thêm tập lệnh!", - "ok_button_timeout": "Được rồi (__giữ chỗ_0__)", - "documentation_button": "Tài liệu", - "catalog": { - "script_already_installed": "Tập lệnh đã được cài đặt sẵn!", - "download_failed": "Tải xuống không thành công: {code}", - "script_downloaded": "Đã tải xuống tập lệnh!", - "could_not_create_file": "Không thể tạo tập tin.", - "no_scripts_folder_selected": "Không có thư mục tập lệnh nào được chọn.", - "error": "Lỗi: {message}", - "no_repos_added": "Không có kho lưu trữ nào được thêm vào.", - "repo_list_info": "Tại đây bạn có thể tìm thấy danh sách các kho lưu trữ:", - "link_text": "liên kết", - "no_scripts_available": "Không có tập lệnh nào có sẵn từ bất kỳ repo nào.", - "by_author": "bởi {author}", - "version": "Phiên bản: {version}", - "installed_button": "Đã cài đặt", - "download_button": "Tải xuống" - }, - "repos": { - "invalid_repo_title": "Kho lưu trữ không hợp lệ", - "add_repo_button": "Thêm kho lưu trữ", - "add_repo_dialog_title": "Thêm URL kho lưu trữ", - "repo_url_label": "URL kho lưu trữ", - "repo_added_toast": "Đã thêm kho lưu trữ thành công!", - "invalid_repo_error": "Đây dường như không phải là kho lưu trữ Script hợp lệ.", - "add_repo_failed_toast": "Không thêm được kho lưu trữ: {message}", - "add_button": "Thêm vào", - "no_repos_added": "Không có kho lưu trữ nào được thêm vào", - "remove_button": "Di dời", - "remove_repo_dialog_title": "Xóa kho lưu trữ", - "remove_repo_dialog_text": "Bạn có chắc chắn muốn xóa kho lưu trữ này không?" - } - }, - "features": { - "config_import": { - "title": "Xác nhận nhập", - "back_button_description": "Mặt sau", - "config_imported_toast": "Đã nhập cấu hình!", - "confirm_button": "Xác nhận", - "expand_button_description": "Mở rộng", - "enable_feature": "Bật tính năng", - "enabled": "Đã bật", - "disabled": "Tàn tật" - }, - "config_export": { - "title": "Xuất Tóm tắt", - "back_button_description": "Mặt sau", - "save_button": "Cứu", - "expand_button_description": "Mở rộng", - "enable_feature": "Bật tính năng", - "enabled": "Đã bật", - "disabled": "Tàn tật" - } - }, - "manage_repos": { - "title": "Quản lý kho lưu trữ {type}", - "add_repo_button": "Thêm kho lưu trữ", - "add_repo_dialog_title": "Thêm URL kho lưu trữ", - "repo_url_label": "URL kho lưu trữ", - "repo_added_successfully": "Đã thêm kho lưu trữ thành công!", - "add_repo_failed": "Không thêm được kho lưu trữ: {message}", - "add_button": "Thêm vào", - "no_repos_added": "Không có kho lưu trữ nào được thêm vào", - "remove_button": "Di dời" - } - }, - "rules": { - "toasts": { - "enabled": "Đã bật {ruleName}", - "disabled": "{ruleName} bị vô hiệu hóa" - }, - "modes": { - "blacklist": "Chế độ danh sách đen", - "whitelist": "Chế độ danh sách trắng" - }, - "properties": { - "auto_download": { - "name": "Tự động tải xuống", - "description": "Tự động tải xuống Snaps khi xem chúng", - "options": { - "blacklist": "Loại trừ khỏi Tự động tải xuống", - "whitelist": "Tự động tải xuống" - } - }, - "stealth": { - "name": "Chế độ tàng hình", - "description": "Ngăn không cho bất kỳ ai biết bạn đã mở Snap/Trò chuyện và cuộc trò chuyện của họ", - "options": { - "blacklist": "Loại trừ khỏi Chế độ ẩn", - "whitelist": "Chế độ tàng hình" - } - }, - "auto_save": { - "name": "Tự động lưu", - "description": "Lưu tin nhắn trò chuyện khi xem chúng", - "options": { - "blacklist": "Loại trừ khỏi Tự động lưu", - "whitelist": "Tự động lưu" - } - }, - "unsaveable_messages": { - "name": "Tin nhắn không thể lưu", - "description": "Ngăn người khác lưu tin nhắn trong cuộc trò chuyện", - "options": { - "blacklist": "Loại trừ khỏi tin nhắn không thể lưu", - "whitelist": "Tin nhắn không thể lưu" - } - }, - "auto_open_snaps": { - "name": "Tự động mở Snaps", - "description": "Tự động mở Snaps khi nhận được chúng", - "options": { - "blacklist": "Loại trừ khỏi Snaps tự động mở", - "whitelist": "Tự động mở Snaps" - } - }, - "hide_friend_feed": { - "name": "Ẩn khỏi Nguồn cấp dữ liệu của Bạn bè" - }, - "e2e_encryption": { - "name": "Sử dụng mã hóa E2E" - }, - "pin_conversation": { - "name": "Ghim cuộc trò chuyện" - }, - "exclude_message_logger": { - "name": "Loại trừ khỏi Trình ghi tin nhắn" - } - } - }, - "actions": { - "clean_snapchat_cache": { - "name": "Làm sạch bộ đệm Snapchat", - "description": "Làm sạch bộ đệm Snapchat" - }, - "manage_friend_list": { - "name": "Quản lý danh sách bạn bè", - "description": "Nhập/xuất danh sách bạn bè của bạn khi sao lưu" - }, - "export_chat_messages": { - "name": "Xuất tin nhắn trò chuyện", - "description": "Xuất tin nhắn hội thoại thành tệp JSON/HTML/TXT" - }, - "export_memories": { - "name": "Xuất ký ức", - "description": "Xuất ký ức thành tệp ZIP" - }, - "bulk_messaging_action": { - "name": "Hành động nhắn tin hàng loạt", - "description": "Thực hiện các thao tác như xóa bạn bè hoặc xóa hàng loạt cuộc trò chuyện" - }, - "regen_mappings": { - "name": "Tạo lại ánh xạ", - "description": "Tạo lại ánh xạ theo cách thủ công" - }, - "change_language": { - "name": "Thay đổi ngôn ngữ", - "description": "Thay đổi ngôn ngữ của PurrfectSnap" - }, - "file_imports": { - "name": "Nhập tệp", - "description": "Nhập tệp để sử dụng trong Snapchat" - }, - "friend_tracker": { - "name": "Theo dõi bạn bè", - "description": "Theo dõi bạn bè của bạn trên Snapchat" - }, - "logger_history": { - "name": "Lịch sử ghi nhật ký", - "description": "Xem lịch sử tin nhắn đã ghi" - } - }, - "features": { - "notices": { - "unstable": "⚠ Không ổn định", - "ban_risk": "⚠ Tính năng này có thể gây ra lệnh cấm", - "internal_behavior": "⚠ Điều này có thể phá vỡ hành vi nội bộ của Snapchat" - }, - "properties": { - "downloader": { - "name": "Trình tải xuống", - "description": "Tải xuống Snapchat Media", - "properties": { - "save_folder": { - "name": "Lưu thư mục", - "description": "Chọn thư mục mà tất cả phương tiện sẽ được tải xuống" - }, - "auto_download_sources": { - "name": "Nguồn tải xuống tự động", - "description": "Chọn các nguồn để tự động tải xuống từ" - }, - "prevent_self_auto_download": { - "name": "Ngăn chặn việc tự động tải xuống", - "description": "Ngăn chặn việc tải xuống Snaps của riêng bạn một cách tự động" - }, - "path_format": { - "name": "Định dạng đường dẫn", - "description": "Chỉ định định dạng đường dẫn tệp" - }, - "allow_duplicate": { - "name": "Cho phép trùng lặp", - "description": "Cho phép tải xuống cùng một phương tiện nhiều lần" - }, - "merge_overlays": { - "name": "Hợp nhất lớp phủ", - "description": "Kết hợp Văn bản và phương tiện của Snap vào một tệp duy nhất" - }, - "force_image_format": { - "name": "Buộc định dạng hình ảnh", - "description": "Buộc hình ảnh được lưu ở Định dạng được chỉ định" - }, - "force_voice_note_format": { - "name": "Buộc định dạng ghi chú giọng nói", - "description": "Buộc lưu Ghi chú bằng giọng nói ở Định dạng được chỉ định" - }, - "auto_download_voice_notes": { - "name": "Tự động tải xuống Ghi chú bằng giọng nói", - "description": "Tự động tải xuống ghi chú giọng nói khi phát chúng" - }, - "download_profile_pictures": { - "name": "Tải xuống ảnh hồ sơ", - "description": "Cho phép bạn tải xuống Ảnh hồ sơ từ trang hồ sơ" - }, - "opera_download_button": { - "name": "Nút tải xuống Opera", - "description": "Thêm nút tải xuống ở góc trên bên phải khi xem Snap.\nNhấn và giữ các nút sẽ buộc tải xuống" - }, - "download_context_menu": { - "name": "Trình đơn ngữ cảnh tải xuống", - "description": "Cho phép bạn tải xuống/xem trước tin nhắn từ một cuộc trò chuyện hoặc một câu chuyện bằng menu ngữ cảnh.\nNhấn và giữ các nút sẽ buộc tải xuống" - }, - "ffmpeg_options": { - "name": "Tùy chọn FFmpeg", - "description": "Chỉ định các tùy chọn FFmpeg bổ sung", - "properties": { - "threads": { - "name": "chủ đề", - "description": "Số lượng chủ đề sử dụng" - }, - "preset": { - "name": "cài sẵn", - "description": "Đặt tốc độ chuyển đổi" - }, - "constant_rate_factor": { - "name": "Hệ số tỷ lệ không đổi", - "description": "Đặt hệ số tốc độ không đổi cho bộ mã hóa video\nTừ 0 đến 51 cho libx264" - }, - "video_bitrate": { - "name": "Tốc độ bit của video", - "description": "Đặt tốc độ bit video (kbps)" - }, - "audio_bitrate": { - "name": "Tốc độ bit âm thanh", - "description": "Đặt tốc độ bit âm thanh (kbps)" - }, - "custom_video_codec": { - "name": "Bộ giải mã video tùy chỉnh", - "description": "Đặt Codec video tùy chỉnh (ví dụ: libx264)" - }, - "custom_audio_codec": { - "name": "Bộ giải mã âm thanh tùy chỉnh", - "description": "Đặt Codec âm thanh tùy chỉnh (ví dụ: AAC)" - } - } - }, - "logging": { - "name": "Ghi nhật ký", - "description": "Hiển thị chúc mừng khi phương tiện đang tải xuống" - }, - "custom_path_format": { - "name": "Định dạng đường dẫn tùy chỉnh", - "description": "Chỉ định định dạng đường dẫn tùy chỉnh cho phương tiện đã tải xuống\n\nCác biến có sẵn:\n - %tên người dùng%\n - %nguồn%\n - %băm%\n - %date_time%" - } - } - }, - "user_interface": { - "name": "Giao diện người dùng", - "description": "Thay đổi giao diện của Snapchat", - "properties": { - "enable_app_appearance": { - "name": "Bật cài đặt giao diện ứng dụng", - "description": "Bật cài đặt giao diện ứng dụng ẩn\nCó thể không bắt buộc trên các phiên bản Snapchat mới hơn" - }, - "friend_feed_message_preview": { - "name": "Xem trước tin nhắn trên nguồn cấp dữ liệu bạn bè", - "description": "Hiển thị bản xem trước của tin nhắn cuối cùng trong Nguồn cấp dữ liệu bạn bè", - "properties": { - "amount": { - "name": "Số lượng", - "description": "Số lượng tin nhắn được xem trước" - } - } - }, - "snap_preview": { - "name": "Xem trước nhanh", - "description": "Hiển thị một bản xem trước nhỏ bên cạnh các Snap chưa được xem trong cuộc trò chuyện" - }, - "bootstrap_override": { - "name": "Ghi đè Bootstrap", - "description": "Ghi đè cài đặt khởi động giao diện người dùng", - "properties": { - "app_appearance": { - "name": "Giao diện ứng dụng", - "description": "Đặt giao diện ứng dụng liên tục" - }, - "home_tab": { - "name": "Tab Trang chủ", - "description": "Ghi đè tab khởi động khi mở Snapchat" - } - } - }, - "force_amoled_theme": { - "name": "Chế độ tối Amoled", - "description": "Sử dụng nền đen thực sự cho chủ đề tối" - }, - "map_friend_nametags": { - "name": "Thẻ tên bản đồ bạn bè nâng cao", - "description": "Cải thiện Thẻ tên của bạn bè trên Snapmap" - }, - "prevent_message_list_auto_scroll": { - "name": "Ngăn danh sách tin nhắn tự động cuộn", - "description": "Ngăn danh sách tin nhắn cuộn xuống cuối khi gửi/nhận tin nhắn" - }, - "streak_expiration_info": { - "name": "Hiển thị thông tin hết hạn chuỗi", - "description": "Hiển thị bộ đếm thời gian hết hạn của vệt bên cạnh bộ đếm vệt" - }, - "hide_friend_feed_entry": { - "name": "Ẩn mục nhập nguồn cấp dữ liệu bạn bè", - "description": "Ẩn một người bạn cụ thể khỏi Nguồn cấp dữ liệu bạn bè\nSử dụng tab xã hội để quản lý tính năng này" - }, - "hide_streak_restore": { - "name": "Ẩn Khôi phục Chuỗi", - "description": "Ẩn nút Khôi phục trong nguồn cấp dữ liệu bạn bè" - }, - "hide_quick_add_suggestions": { - "name": "Ẩn đề xuất thêm nhanh", - "description": "Loại bỏ đề xuất thêm bạn bè nhanh chóng" - }, - "hide_story_suggestions": { - "name": "Ẩn gợi ý câu chuyện", - "description": "Xóa đề xuất khỏi trang Câu chuyện" - }, - "hide_ui_components": { - "name": "Ẩn thành phần giao diện người dùng", - "description": "Chọn thành phần giao diện người dùng nào cần ẩn" - }, - "opera_media_quick_info": { - "name": "Thông tin nhanh về Opera Media", - "description": "Hiển thị thông tin hữu ích của phương tiện như ngày tạo trong menu ngữ cảnh của trình xem opera" - }, - "old_bitmoji_selfie": { - "name": "Ảnh tự sướng Bitmoji cũ", - "description": "Mang lại ảnh tự chụp Bitmoji từ các phiên bản Snapchat cũ hơn" - }, - "disable_spotlight": { - "name": "Tắt tiêu điểm", - "description": "Tắt trang Spotlight" - }, - "friend_feed_menu_buttons": { - "name": "Nút menu nguồn cấp dữ liệu bạn bè", - "description": "Chọn nút nào sẽ hiển thị trong Menu Nguồn cấp dữ liệu Bạn bè" - }, - "auto_close_friend_feed_menu": { - "name": "Tự động đóng menu nguồn cấp dữ liệu bạn bè", - "description": "Tự động đóng Menu Nguồn cấp dữ liệu bạn bè sau khi nhấn nút cài đặt" - }, - "vertical_story_viewer": { - "name": "Trình xem câu chuyện dọc", - "description": "Cho phép trình xem câu chuyện dọc cho tất cả các câu chuyện" - }, - "enable_friend_feed_menu_bar": { - "name": "Thanh menu nguồn cấp dữ liệu bạn bè", - "description": "Kích hoạt Thanh menu Nguồn cấp dữ liệu Bạn bè mới" - }, - "message_indicators": { - "name": "Chỉ báo tin nhắn", - "description": "Thêm biểu tượng chỉ báo cụ thể vào tin nhắn\nLưu ý: Các chỉ số có thể không chính xác 100%" - }, - "stealth_mode_indicator": { - "name": "Chỉ báo chế độ ẩn", - "description": "Thêm biểu tượng cảm xúc 👻 bên cạnh cuộc trò chuyện ở chế độ ẩn" - }, - "edit_text_override": { - "name": "Chỉnh sửa ghi đè văn bản", - "description": "Ghi đè hành vi của trường văn bản" - }, - "prevent_forced_keyboard": { - "name": "Ngăn chặn bàn phím cưỡng bức", - "description": "Ngăn Snapchat tự động bật bàn phím khi bạn mở cuộc trò chuyện" - }, - "settings_menu": { - "name": "Trình đơn cài đặt", - "description": "Thay đổi cách bạn mở menu PurrfectSnap", - "options": { - "default": "Mặc định", - "legacy": "Di sản" - } - } - } - }, - "messaging": { - "name": "Nhắn tin", - "description": "Thay đổi cách bạn tương tác với bạn bè", - "properties": { - "bypass_screenshot_detection": { - "name": "Bỏ qua phát hiện ảnh chụp màn hình", - "description": "Ngăn Snapchat phát hiện khi bạn chụp ảnh màn hình" - }, - "anonymous_story_viewing": { - "name": "Xem câu chuyện ẩn danh", - "description": "Ngăn chặn bất cứ ai biết bạn đã xem câu chuyện của họ" - }, - "prevent_story_rewatch_indicator": { - "name": "Ngăn chặn chỉ báo xem lại câu chuyện", - "description": "Ngăn không cho người khác biết bạn đã xem lại câu chuyện của họ" - }, - "hide_peek_a_peek": { - "name": "Ẩn Nhìn trộm", - "description": "Ngăn thông báo được gửi khi bạn vuốt nửa chừng vào cuộc trò chuyện" - }, - "hide_bitmoji_presence": { - "name": "Ẩn sự hiện diện của Bitmoji", - "description": "Ngăn Bitmoji của bạn bật lên khi đang trò chuyện" - }, - "hide_typing_notifications": { - "name": "Ẩn thông báo gõ", - "description": "Ngăn không cho người khác biết bạn đang gõ tin nhắn" - }, - "unlimited_snap_view_time": { - "name": "Thời gian xem Snap không giới hạn", - "description": "Loại bỏ giới hạn thời gian để xem Snaps" - }, - "auto_mark_as_read": { - "name": "Tự động đánh dấu là đã đọc", - "description": "Tự động đánh dấu tin nhắn/ảnh chụp nhanh là đã đọc ngay cả khi bật Chế độ ẩn" - }, - "mark_snap_as_seen_button": { - "name": "Đánh dấu nút chụp là đã xem", - "description": "Thêm nút để đánh dấu một Snap là đã thấy khi xem nó.\nĐiều này sẽ hoạt động ngay cả khi Chế độ ẩn được bật" - }, - "skip_when_marking_as_seen": { - "name": "Bỏ qua khi đánh dấu là đã xem", - "description": "Tự động chuyển sang Snap tiếp theo khi đánh dấu một Snap là đã xem.\nSử dụng kết hợp với nút Mark Snap as Seen" - }, - "loop_media_playback": { - "name": "Phát lại phương tiện vòng lặp", - "description": "Lặp lại quá trình phát lại phương tiện khi xem Snaps / Stories" - }, - "disable_replay_in_ff": { - "name": "Vô hiệu hóa phát lại trong FF", - "description": "Vô hiệu hóa khả năng phát lại khi nhấn và giữ từ Nguồn cấp dữ liệu bạn bè" - }, - "half_swipe_notifier": { - "name": "Trình thông báo vuốt một nửa", - "description": "Thông báo cho bạn khi ai đó vuốt nhẹ vào cuộc trò chuyện", - "properties": { - "min_duration": { - "name": "Thời lượng tối thiểu", - "description": "Thời lượng tối thiểu của một nửa lần vuốt (tính bằng giây)" - }, - "max_duration": { - "name": "Thời lượng tối đa", - "description": "Thời lượng tối đa của một nửa lần vuốt (tính bằng giây)" - } - } - }, - "call_start_confirmation": { - "name": "Xác nhận bắt đầu cuộc gọi", - "description": "Hiển thị hộp thoại xác nhận khi bắt đầu cuộc gọi" - }, - "unlimited_conversation_pinning": { - "name": "Ghim cuộc trò chuyện không giới hạn", - "description": "Cho phép bạn ghim số lượng cuộc hội thoại không giới hạn cục bộ" - }, - "disable_snap_mode_restrictions": { - "name": "Vô hiệu hóa hạn chế chế độ chụp", - "description": "Cho phép bạn xem Snaps tự hủy mà không bị hạn chế" - }, - "prevent_message_sending": { - "name": "Ngăn chặn việc gửi tin nhắn", - "description": "Ngăn chặn gửi một số loại tin nhắn" - }, - "friend_mutation_notifier": { - "name": "Trình thông báo đột biến bạn bè", - "description": "Thông báo cho bạn khi có gì đó thay đổi trong hồ sơ của bạn bè" - }, - "better_notifications": { - "name": "Thông báo tốt hơn", - "description": "Thêm thông tin khác trong thông báo đã nhận", - "properties": { - "group_notifications": { - "name": "Thông báo nhóm", - "description": "Nhóm thông báo thành một thông báo duy nhất" - }, - "chat_preview": { - "name": "Xem trước cuộc trò chuyện", - "description": "Hiển thị bản xem trước của tin nhắn đã nhận trong thông báo" - }, - "media_preview": { - "name": "Xem trước phương tiện", - "description": "Hiển thị bản xem trước của các loại phương tiện đã chọn trong thông báo" - }, - "media_caption": { - "name": "Chú thích phương tiện", - "description": "Hiển thị chú thích đính kèm của phương tiện trong thông báo" - }, - "stacked_media_messages": { - "name": "Tin nhắn phương tiện xếp chồng", - "description": "Kết hợp nhiều tin nhắn đa phương tiện thành một thông báo văn bản khi không thể xem trước chúng. Sử dụng kết hợp với Chat Preview" - }, - "friend_add_source": { - "name": "Bạn bè Thêm nguồn", - "description": "Hiển thị nguồn của yêu cầu kết bạn trong thông báo" - }, - "reply_button": { - "name": "Nút trả lời", - "description": "Thêm nút trả lời vào thông báo" - }, - "smart_replies": { - "name": "Trả lời thông minh", - "description": "Thêm câu trả lời được đề xuất cho thông báo (Android 10+). Sử dụng kết hợp với Nút Trả lời" - }, - "download_button": { - "name": "Nút tải xuống", - "description": "Cho phép bạn tải xuống phương tiện từ thông báo" - }, - "mark_as_read_button": { - "name": "Nút đánh dấu là đã đọc", - "description": "Cho phép bạn đánh dấu tin nhắn là đã đọc từ thông báo" - }, - "mark_as_read_and_save_in_chat": { - "name": "Đánh dấu là đã đọc và lưu trong trò chuyện", - "description": "Thêm dấu là đã đọc và lưu trong nút trò chuyện vào thông báo" - } - } - }, - "notification_blacklist": { - "name": "Danh sách đen thông báo", - "description": "Chọn thông báo sẽ bị chặn" - }, - "message_logger": { - "name": "Trình ghi tin nhắn", - "description": "Ngăn chặn tin nhắn bị xóa", - "properties": { - "keep_my_own_messages": { - "name": "Giữ tin nhắn của riêng tôi", - "description": "Ngăn chặn tin nhắn của chính bạn bị xóa" - }, - "auto_purge": { - "name": "Tự động thanh lọc", - "description": "Tự động xóa các tin nhắn được lưu trong bộ nhớ cache cũ hơn khoảng thời gian được chỉ định" - }, - "message_filter": { - "name": "Bộ lọc tin nhắn", - "description": "Chọn tin nhắn nào sẽ được ghi lại (trống cho tất cả tin nhắn)" - }, - "deleted_message_color": { - "name": "Màu tin nhắn đã xóa", - "description": "Đặt màu của tin nhắn đã xóa" - } - } - }, - "auto_save_messages_in_conversations": { - "name": "Tự động lưu tin nhắn", - "description": "Tự động lưu mọi tin nhắn trong cuộc trò chuyện" - }, - "gallery_media_send_override": { - "name": "Ghi đè gửi phương tiện thư viện", - "description": "Giả mạo nguồn phương tiện khi gửi từ Thư viện" - }, - "strip_media_metadata": { - "name": "Dải siêu dữ liệu phương tiện", - "description": "Xóa siêu dữ liệu của phương tiện trước khi gửi dưới dạng tin nhắn" - }, - "bypass_message_retention_policy": { - "name": "Bỏ qua chính sách lưu giữ tin nhắn", - "description": "Ngăn chặn tin nhắn bị xóa sau khi xem chúng" - }, - "bypass_message_action_restrictions": { - "name": "Bỏ qua hạn chế hành động tin nhắn", - "description": "Cho phép bạn phản ứng với ảnh chụp nhanh mà không cần mở nó hoặc lưu tin nhắn không thể lưu" - }, - "remove_groups_locked_status": { - "name": "Xóa trạng thái khóa nhóm", - "description": "Cho phép xem thông tin nhóm sau khi bị đá" - }, - "double_tap_chat_action": { - "name": "Hành động trò chuyện nhấn đúp", - "description": "Thực hiện hành động tùy chỉnh khi nhấn đúp vào tin nhắn trong cuộc trò chuyện" - }, - "double_tap_chat_action_custom_emoji": { - "name": "Nhấn đúp vào hành động trò chuyện Phản ứng biểu tượng cảm xúc tùy chỉnh", - "description": "Đặt phản ứng biểu tượng cảm xúc tùy chỉnh cho hành động trò chuyện nhấn đúp" - } - } - }, - "global": { - "name": "Toàn cầu", - "description": "Tinh chỉnh cài đặt Snapchat toàn cầu", - "properties": { - "better_location": { - "name": "Vị trí tốt hơn", - "description": "Tăng cường vị trí Snapchat", - "properties": { - "spoof_location": { - "name": "Vị trí giả mạo", - "description": "Giả mạo vị trí của bạn đến một vị trí được chỉ định" - }, - "coordinates": { - "name": "tọa độ", - "description": "Đặt tọa độ của vị trí giả mạo" - }, - "walk_radius": { - "name": "Bán kính bước đi", - "description": "Đi bộ ngẫu nhiên trong bán kính này (ft)" - }, - "always_update_location": { - "name": "Luôn cập nhật vị trí", - "description": "Buộc Snapchat cập nhật vị trí ngay cả khi không nhận được dữ liệu GPS" - }, - "suspend_location_updates": { - "name": "Tạm dừng cập nhật vị trí", - "description": "Ngăn không cho cập nhật vị trí của bạn" - }, - "spoof_battery_level": { - "name": "Mức pin giả mạo", - "description": "Giả mạo mức pin của thiết bị của bạn trên bản đồ\nGiá trị phải nằm trong khoảng từ 0 đến 100" - }, - "spoof_headphones": { - "name": "Tai nghe giả mạo", - "description": "Giả mạo trạng thái nghe nhạc trên bản đồ" - }, - "show_battery_level": { - "name": "Hiển thị mức pin", - "description": "Hiển thị mức pin của bạn bè trên bản đồ" - } - } - }, - "snapchat_plus": { - "name": "Snapchat Plus", - "description": "Kích hoạt tính năng Snapchat Plus\nMột số tính năng phía Máy chủ có thể không hoạt động" - }, - "media_upload_quality": { - "name": "Chất lượng tải lên phương tiện", - "description": "Ghi đè chất lượng tải lên phương tiện", - "properties": { - "force_video_upload_source_quality": { - "name": "Buộc chất lượng nguồn tải lên video", - "description": "Buộc Snapchat sử dụng chất lượng nguồn khi tải video lên\nXin lưu ý rằng thao tác này có thể không xóa siêu dữ liệu khỏi phương tiện" - }, - "disable_image_compression": { - "name": "Vô hiệu hóa nén hình ảnh", - "description": "Vô hiệu hóa nén hình ảnh khi tải lên phương tiện" - }, - "custom_image_upload_format": { - "name": "Định dạng tải lên hình ảnh tùy chỉnh", - "description": "Đặt định dạng tải lên hình ảnh tùy chỉnh\nChọn định dạng lossless (như PNG) để có chất lượng tốt nhất" - } - } - }, - "disable_confirmation_dialogs": { - "name": "Tắt hộp thoại xác nhận", - "description": "Tự động xác nhận các hành động đã chọn" - }, - "auto_updater": { - "name": "Tự động cập nhật", - "description": "Tự động kiểm tra các bản cập nhật mới" - }, - "disable_metrics": { - "name": "Vô hiệu hóa số liệu", - "description": "Chặn gửi dữ liệu phân tích cụ thể tới Snapchat" - }, - "disable_story_sections": { - "name": "Tắt phần câu chuyện", - "description": "Xóa các phần khỏi trang Câu chuyện\nCó thể yêu cầu làm mới để hoạt động bình thường" - }, - "block_ads": { - "name": "Chặn quảng cáo", - "description": "Ngăn chặn quảng cáo được hiển thị" - }, - "disable_custom_tabs": { - "name": "Vô hiệu hóa các tab tùy chỉnh", - "description": "Mở liên kết trong các ứng dụng được hỗ trợ thay vì trong Trình duyệt Web" - }, - "disable_permission_requests": { - "name": "Vô hiệu hóa yêu cầu cấp phép", - "description": "Ngăn Snapchat yêu cầu các quyền cụ thể" - }, - "disable_memories_snap_feed": { - "name": "Tắt nguồn cấp dữ liệu Snap của kỷ niệm", - "description": "Ngăn Snapchat hiển thị những kỷ niệm gần đây khi bạn vuốt lên trong máy ảnh" - }, - "spotlight_comments_username": { - "name": "Bình luận tiêu điểm Tên người dùng", - "description": "Hiển thị tên người dùng tác giả trong nhận xét Spotlight" - }, - "bypass_video_length_restriction": { - "name": "Bỏ qua các hạn chế về độ dài video", - "description": "Single: gửi một video duy nhất\nSplit: chia nhỏ video sau khi chỉnh sửa" - }, - "default_video_playback_rate": { - "name": "Tốc độ phát lại video mặc định", - "description": "Đặt tốc độ mặc định để phát lại video\nGiá trị phải nằm trong khoảng từ 0,1 đến 4,0" - }, - "video_playback_rate_slider": { - "name": "Thanh trượt tốc độ phát lại video", - "description": "Thêm thanh trượt trong menu ngữ cảnh opera để thay đổi tốc độ phát lại video\nLưu ý: Thay đổi chỉ áp dụng cho các video tiếp theo" - }, - "disable_google_play_dialogs": { - "name": "Tắt hộp thoại Dịch vụ Google Play", - "description": "Ngăn không cho hiển thị hộp thoại về tính khả dụng của Dịch vụ Google Play" - }, - "default_volume_controls": { - "name": "Điều khiển âm lượng mặc định", - "description": "Buộc Snapchat sử dụng điều khiển âm lượng hệ thống" - }, - "disable_telecom_framework": { - "name": "Vô hiệu hóa khung viễn thông", - "description": "Ngăn Snapchat sử dụng khung Android Telecom\nĐiều này cho phép bạn nghe nhạc trong khi gọi điện" - }, - "hide_active_music": { - "name": "Ẩn nhạc đang hoạt động", - "description": "Ngăn Snapchat biết bạn đang nghe nhạc\nĐiều này sẽ cho phép bạn chụp ảnh nhanh bằng các nút điều khiển âm lượng trong khi nghe nhạc" - }, - "disable_snap_splitting": { - "name": "Tắt tính năng chia tách Snap", - "description": "Ngăn chặn việc chia Snap thành nhiều phần\nHình ảnh bạn gửi sẽ chuyển thành video" - } - } - }, - "rules": { - "name": "Quy tắc", - "description": "Quản lý các tính năng tự động cho từng người" - }, - "camera": { - "name": "Máy ảnh", - "description": "Điều chỉnh cài đặt phù hợp để có bức ảnh chụp hoàn hảo", - "properties": { - "disable_cameras": { - "name": "Vô hiệu hóa máy ảnh", - "description": "Ngăn Snapchat sử dụng các máy ảnh đã chọn" - }, - "black_photos": { - "name": "Ảnh đen", - "description": "Thay thế ảnh đã chụp bằng nền đen\nVideo không bị ảnh hưởng" - }, - "immersive_camera_preview": { - "name": "Xem trước phong phú", - "description": "Ngăn Snapchat cắt xén phần xem trước của máy ảnh\nĐiều này có thể khiến máy ảnh bị rung trên một số thiết bị" - }, - "override_front_resolution": { - "name": "Ghi đè độ phân giải phía trước", - "description": "Ghi đè độ phân giải camera cho camera trước" - }, - "override_back_resolution": { - "name": "Ghi đè độ phân giải quay lại", - "description": "Ghi đè độ phân giải camera cho camera sau" - }, - "custom_resolution": { - "name": "Độ phân giải tùy chỉnh", - "description": "Đặt độ phân giải camera tùy chỉnh, chiều rộng x chiều cao (ví dụ: 1920x1080).\nĐộ phân giải tùy chỉnh phải được thiết bị của bạn hỗ trợ" - }, - "front_custom_frame_rate": { - "name": "Tốc độ khung hình tùy chỉnh phía trước", - "description": "Ghi đè tốc độ khung hình của camera trước" - }, - "back_custom_frame_rate": { - "name": "Quay lại Tốc độ khung hình tùy chỉnh", - "description": "Ghi đè tốc độ khung hình của camera sau" - }, - "force_camera_source_encoding": { - "name": "Buộc mã hóa nguồn máy ảnh", - "description": "Buộc mã hóa nguồn camera" - }, - "startup_default_camera": { - "name": "Máy ảnh mặc định khởi động", - "description": "Đặt camera mặc định khi mở Snapchat" - }, - "hevc_recording": { - "name": "Ghi âm HEVC", - "description": "Sử dụng codec HEVC (H.265) để quay video" - } - } - }, - "streaks_reminder": { - "name": "Nhắc nhở vệt", - "description": "Thông báo định kỳ cho bạn về Chuỗi của bạn", - "properties": { - "interval": { - "name": "Khoảng thời gian", - "description": "Khoảng thời gian giữa mỗi lần nhắc nhở (giờ)" - }, - "remaining_hours": { - "name": "Thời gian còn lại", - "description": "Khoảng thời gian còn lại trước khi thông báo được hiển thị (giờ)" - }, - "group_notifications": { - "name": "Thông báo nhóm", - "description": "Nhóm thông báo thành một thông báo duy nhất" - } - } - }, - "experimental": { - "name": "thực nghiệm", - "description": "Tính năng thử nghiệm", - "properties": { - "native_hooks": { - "name": "Móc bản địa", - "description": "Các tính năng không an toàn gắn vào mã gốc của Snapchat", - "properties": { - "composer_hooks": { - "name": "Móc soạn nhạc", - "description": "Đưa mã vào khung giao diện người dùng đa nền tảng của Composer", - "properties": { - "show_first_created_username": { - "name": "Hiển thị tên người dùng được tạo đầu tiên", - "description": "Hiển thị tên người dùng được tạo đầu tiên bên cạnh tên người dùng hiện tại trong trang hồ sơ" - }, - "bypass_camera_roll_limit": { - "name": "Bỏ qua giới hạn cuộn camera", - "description": "Tăng lượng phương tiện tối đa bạn có thể gửi từ thư viện ảnh" - }, - "custom_self_destruct_snap_delay": { - "name": "Độ trễ chụp tự hủy tùy chỉnh", - "description": "Cung cấp thêm tùy chọn hẹn giờ tự hủy khi gửi Snap" - }, - "composer_console": { - "name": "Bảng điều khiển dành cho nhà soạn nhạc", - "description": "Cho phép bạn thực thi mã JavaScript trong Composer (chỉ arm64)" - }, - "composer_logs": { - "name": "Nhật ký soạn nhạc", - "description": "Chuyển hướng nhật ký bảng điều khiển của Composer sang PurrfectSnap" - } - } - }, - "disable_bitmoji": { - "name": "Tắt Bitmoji", - "description": "Vô hiệu hóa hồ sơ bạn bè Bitmoji" - }, - "custom_emoji_font": { - "name": "Phông chữ biểu tượng cảm xúc tùy chỉnh", - "description": "Cho phép bạn sử dụng phông chữ biểu tượng cảm xúc tùy chỉnh. Chỉ hoạt động với phông chữ .ttf" - }, - "custom_shared_library": { - "name": "Thư viện chia sẻ tùy chỉnh", - "description": "Tải thư viện chia sẻ tùy chỉnh vào Snapchat. Tính năng này chỉ dành cho mục đích thử nghiệm" - } - } - }, - "spoof": { - "name": "giả mạo", - "description": "Giả mạo nhiều thông tin khác nhau về bạn", - "properties": { - "play_store_installer_package_name": { - "name": "Tên gói trình cài đặt Cửa hàng Play", - "description": "Ghi đè tên gói cài đặt thành com.android.vending" - }, - "remove_vpn_transport_flag": { - "name": "Xóa cờ truyền tải VPN", - "description": "Ngăn Snapchat phát hiện VPN" - }, - "remove_mock_location_flag": { - "name": "Xóa cờ vị trí mô phỏng", - "description": "Ngăn Snapchat phát hiện vị trí giả" - } - } - }, - "convert_message_locally": { - "name": "Chuyển đổi tin nhắn cục bộ", - "description": "Chuyển đổi snaps để trò chuyện phương tiện bên ngoài cục bộ. Điều này xuất hiện trong menu ngữ cảnh tải xuống trò chuyện" - }, - "media_file_picker": { - "name": "Bộ chọn tệp phương tiện", - "description": "Cho phép bạn chọn bất kỳ tệp video/âm thanh nào từ thư viện" - }, - "story_logger": { - "name": "Trình ghi câu chuyện", - "description": "Cung cấp lịch sử câu chuyện của bạn bè" - }, - "call_recorder": { - "name": "Ghi âm cuộc gọi", - "description": "Tự động ghi lại cuộc gọi âm thanh" - }, - "account_switcher": { - "name": "Trình chuyển đổi tài khoản", - "description": "Cho phép bạn chuyển đổi giữa các tài khoản mà không cần đăng xuất\nNhấn và giữ biểu tượng tìm kiếm bên cạnh hồ sơ Bitmoji của bạn để mở menu\nLưu ý: Tính năng này đang thử nghiệm và có thể sẽ thay đổi trong tương lai", - "properties": { - "auto_backup_current_account": { - "name": "Tự động sao lưu tài khoản hiện tại", - "description": "Tự động sao lưu tài khoản hiện tại khi đăng xuất hoặc chuyển đổi tài khoản" - } - } - }, - "better_transcript": { - "name": "Bảng điểm tốt hơn", - "description": "Cải thiện bản ghi ghi chú bằng giọng nói", - "properties": { - "force_transcription": { - "name": "Buộc phiên âm ghi chú bằng giọng nói", - "description": "Cho phép ghi lại tất cả các ghi chú bằng giọng nói" - }, - "preferred_transcription_lang": { - "name": "Ngôn ngữ phiên âm ưa thích", - "description": "Ngôn ngữ ưu tiên cho bản ghi chú thoại (ví dụ: EN, ES, FR)" - }, - "notification_transcript": { - "name": "Bản ghi thông báo", - "description": "Phiên âm ghi chú giọng nói trong thông báo\nTính năng này yêu cầu bật tính năng Xem trước trò chuyện trong Thông báo tốt hơn" - } - } - }, - "voice_note_auto_play": { - "name": "Ghi chú bằng giọng nói Tự động phát", - "description": "Tự động phát ghi chú thoại tiếp theo sau khi ghi chú hiện tại kết thúc" - }, - "friend_notes": { - "name": "Ghi chú của bạn bè", - "description": "Cho phép bạn thêm ghi chú vào hồ sơ bạn bè" - }, - "cof_experiments": { - "name": "Thí nghiệm COF", - "description": "Kích hoạt các tính năng Snapchat chưa được phát hành/beta" - }, - "context_menu_fix": { - "name": "Sửa menu ngữ cảnh", - "description": "Cố gắng sửa lại Menu Friend Feed vì khi thiết bị ngoại tuyến không thể hiển thị chính xác" - }, - "app_lock": { - "name": "Khóa ứng dụng", - "description": "Ngăn chặn truy cập Snapchat mà không cần mật mã", - "properties": { - "lock_on_resume": { - "name": "Khóa khi tiếp tục", - "description": "Khóa ứng dụng khi mở lại" - } - } - }, - "infinite_story_boost": { - "name": "Tăng cường câu chuyện vô hạn", - "description": "Bỏ qua độ trễ Giới hạn tăng cường câu chuyện" - }, - "meo_passcode_bypass": { - "name": "My Eyes Only Bỏ qua mật mã", - "description": "Bỏ qua mật mã My Eyes Only\nĐiều này sẽ chỉ hoạt động nếu mật mã đã được nhập chính xác trước đó" - }, - "no_friend_score_delay": { - "name": "Không có sự chậm trễ về điểm bạn bè", - "description": "Loại bỏ độ trễ khi xem Điểm bạn bè" - }, - "best_friend_pinning": { - "name": "Ghim người bạn thân nhất", - "description": "Cho phép bạn ghim một người bạn làm người bạn thân số một của mình. Lưu ý: Chỉ bạn mới có thể nhìn thấy người bạn thân đã ghim của mình" - }, - "e2ee": { - "name": "Mã hóa đầu cuối", - "description": "Mã hóa tin nhắn của bạn bằng AES bằng khóa bí mật chung\nĐảm bảo lưu chìa khóa của bạn ở nơi nào đó an toàn!", - "properties": { - "encrypted_message_indicator": { - "name": "Chỉ báo tin nhắn được mã hóa", - "description": "Thêm biểu tượng cảm xúc 🔒 bên cạnh tin nhắn được mã hóa" - }, - "force_message_encryption": { - "name": "Buộc mã hóa tin nhắn", - "description": "Ngăn việc gửi tin nhắn được mã hóa tới những người không bật Mã hóa E2E chỉ khi chọn nhiều cuộc hội thoại" - } - } - }, - "add_friend_source_spoof": { - "name": "Thêm giả mạo nguồn bạn bè", - "description": "Giả mạo nguồn của Yêu cầu kết bạn" - }, - "hidden_snapchat_plus_features": { - "name": "Các tính năng ẩn của Snapchat Plus", - "description": "Kích hoạt các tính năng Snapchat Plus chưa được phát hành/beta\nCó thể không hoạt động trên các phiên bản Snapchat cũ hơn" - }, - "custom_streaks_expiration_format": { - "name": "Định dạng hết hạn của vệt tùy chỉnh", - "description": "Tùy chỉnh định dạng Hết hạn của Vệt\n\nCác biến có sẵn:\n - %c: Số lượng vệt\n - %e: Biểu tượng cảm xúc đồng hồ cát\n - %d: Ngày\n - %h: Số giờ\n - %m: Phút\n - %s: Giây\n - %w: Thời gian còn lại" - }, - "prevent_forced_logout": { - "name": "Ngăn chặn buộc phải đăng xuất", - "description": "Ngăn Snapchat đăng xuất bạn khi bạn đăng nhập trên thiết bị khác" - }, - "snapscore_changes": { - "name": "Thay đổi điểm nhanh", - "description": "Theo dõi những thay đổi trong Snapscore của bạn bè\nChỉ sử dụng tính năng này trong các phiên bản Snapchat mới hơn" - } - } - }, - "scripting": { - "name": "Viết kịch bản", - "description": "Chạy các tập lệnh tùy chỉnh để mở rộng PurrfectSnap", - "properties": { - "developer_mode": { - "name": "Chế độ nhà phát triển", - "description": "Hiển thị thông tin gỡ lỗi trên giao diện người dùng của Snapchat" - }, - "module_folder": { - "name": "Thư mục mô-đun", - "description": "Thư mục chứa script" - }, - "auto_reload": { - "name": "Tự động tải lại", - "description": "Tự động tải lại tập lệnh khi chúng thay đổi" - }, - "integrated_ui": { - "name": "Giao diện người dùng tích hợp", - "description": "Cho phép tập lệnh thêm các thành phần UI tùy chỉnh vào Snapchat" - }, - "disable_log_anonymization": { - "name": "Vô hiệu hóa ẩn danh nhật ký", - "description": "Tắt tính năng ẩn danh của nhật ký" - }, - "disable_optimization": { - "name": "Tắt tối ưu hóa", - "description": "Vô hiệu hóa việc tối ưu hóa các tập lệnh. Điều này có thể gây ra vấn đề về hiệu suất." - } - } - }, - "friend_tracker": { - "name": "Theo dõi bạn bè", - "description": "Ghi lại hoạt động của bạn bè trên Snapchat", - "properties": { - "record_messaging_events": { - "name": "Ghi lại sự kiện nhắn tin", - "description": "Ghi lại các sự kiện nhắn tin như mở snap, đọc tin nhắn, v.v." - }, - "allow_running_in_background": { - "name": "Cho phép chạy trong nền", - "description": "Cho phép trình theo dõi chạy ở chế độ nền. Lưu ý: Điều này sẽ làm hao pin đáng kể" - }, - "auto_purge": { - "name": "Tự động thanh lọc", - "description": "Tự động xóa các sự kiện được lưu trong bộ nhớ cache cũ hơn khoảng thời gian đã chỉ định" - } - } - } - }, - "options": { - "app_appearance": { - "always_light": "Luôn sáng", - "always_dark": "Luôn tối" - }, - "friend_feed_menu_buttons": { - "auto_download": "⬇️ Tự động tải xuống", - "auto_save": "💬 Tự động lưu tin nhắn", - "unsaveable_messages": "⬇️ Tin nhắn không thể lưu", - "auto_open_snaps": "📷 Tự động mở ảnh chụp nhanh", - "stealth": "👻 Chế độ ẩn", - "mark_snaps_as_seen": "👀 Đánh dấu Snaps là đã xem", - "mark_stories_as_seen_locally": "👀 Đánh dấu các câu chuyện là đã xem tại địa phương", - "conversation_info": "👤 Thông tin cuộc trò chuyện", - "e2e_encryption": "🔒 Sử dụng Mã hóa E2E" - }, - "path_format": { - "create_author_folder": "Tạo thư mục cho mỗi tác giả", - "create_source_folder": "Tạo thư mục cho từng loại nguồn phương tiện", - "append_hash": "Thêm một hàm băm duy nhất vào tên tệp", - "append_source": "Thêm nguồn phương tiện vào tên tệp", - "append_username": "Thêm tên người dùng vào tên tệp", - "append_date_time": "Thêm ngày và giờ vào tên tệp" - }, - "auto_download_sources": { - "friend_snaps": "Ảnh chụp bạn bè", - "friend_stories": "Câu chuyện bạn bè", - "public_stories": "Câu chuyện công khai", - "spotlight": "Điểm sáng" - }, - "logging": { - "started": "Đã bắt đầu", - "success": "Thành công", - "progress": "Tiến triển", - "failure": "Sự thất bại" - }, - "notifications": { - "chat_screenshot": "Ảnh chụp màn hình", - "chat_screen_record": "Bản ghi màn hình", - "snap_replay": "Phát lại nhanh", - "camera_roll_save": "Lưu cuộn camera", - "chat": "Trò chuyện", - "chat_reply": "Trò chuyện Trả lời", - "snap": "Chụp nhanh", - "typing": "đánh máy", - "stories": "Truyện", - "speaking": "Nói", - "chat_reaction": "Phản ứng DM", - "group_chat_reaction": "Phản ứng nhóm", - "initiate_audio": "Cuộc gọi âm thanh đến", - "abandon_audio": "Cuộc gọi âm thanh bị nhỡ", - "initiate_video": "Cuộc gọi video đến", - "abandon_video": "Cuộc gọi video bị nhỡ", - "map_live_location": "Bản đồ vị trí trực tiếp" - }, - "gallery_media_send_override": { - "always_ask": "Luôn hỏi", - "ORIGINAL": "Phương tiện gốc", - "NOTE": "Ghi chú âm thanh", - "SNAP": "Chụp nhanh", - "SAVEABLE_SNAP": "Ảnh chụp có thể lưu được" - }, - "strip_media_metadata": { - "hide_caption_text": "Ẩn văn bản chú thích", - "hide_snap_filters": "Ẩn bộ lọc chụp nhanh", - "hide_extras": "Ẩn phần bổ sung (ví dụ: đề cập)", - "remove_audio_note_duration": "Xóa thời lượng ghi chú âm thanh", - "remove_audio_note_transcript_capability": "Xóa khả năng ghi chú âm thanh" - }, - "hide_ui_components": { - "hide_profile_call_buttons": "Xóa nút gọi hồ sơ", - "hide_chat_call_buttons": "Xóa nút gọi trò chuyện", - "hide_live_location_share_button": "Xóa nút chia sẻ vị trí trực tiếp", - "hide_stickers_button": "Nút xóa nhãn dán", - "hide_voice_record_button": "Xóa nút ghi âm giọng nói", - "hide_unread_chat_hint": "Xóa gợi ý trò chuyện chưa đọc", - "hide_post_to_story_buttons": "Xóa nút Đăng lên Câu chuyện trước khi gửi Snap", - "hide_billboard_prompt": "Xóa lời nhắc trên bảng quảng cáo trong nguồn cấp dữ liệu bạn bè", - "hide_snapchat_plus_gift_reminders": "Xóa lời nhắc quà tặng Snapchat Plus trong cuộc trò chuyện", - "hide_map_reactions": "Xóa phản ứng trên bản đồ" - }, - "hide_story_suggestions": { - "hide_suggested_friend_stories": "Ẩn câu chuyện bạn bè được đề xuất", - "hide_my_stories": "Ẩn câu chuyện của tôi" - }, - "home_tab": { - "map": "Bản đồ", - "chat": "Trò chuyện", - "camera": "Máy ảnh", - "discover": "Phát hiện", - "spotlight": "Điểm sáng" - }, - "add_friend_source_spoof": { - "added_by_username": "Theo tên người dùng", - "added_by_mention": "Bằng cách đề cập", - "added_by_group_chat": "Bằng trò chuyện nhóm", - "added_by_qr_code": "Bằng mã QR", - "added_by_community": "Theo cộng đồng", - "added_by_quick_add": "Bằng Quick Add (nguy cơ bị cấm cao)" - }, - "bypass_video_length_restriction": { - "single": "Phương tiện đơn", - "split": "Chia phương tiện" - }, - "old_bitmoji_selfie": { - "2d": "Biểu tượng cảm xúc 2D", - "3d": "Bitmoji 3D" - }, - "disable_confirmation_dialogs": { - "erase_message": "Xóa tin nhắn", - "remove_friend": "Xóa bạn bè", - "block_friend": "Chặn bạn bè", - "ignore_friend": "Bỏ qua bạn bè", - "hide_friend": "Ẩn bạn bè", - "hide_conversation": "Ẩn cuộc trò chuyện", - "clear_conversation": "Xóa cuộc trò chuyện khỏi Nguồn cấp dữ liệu bạn bè" - }, - "auto_reload": { - "snapchat_only": "Chỉ Snapchat", - "all": "Tất cả (Snapchat + PurrfectSnap)" - }, - "edit_text_override": { - "multi_line_chat_input": "Đầu vào trò chuyện nhiều dòng", - "bypass_text_input_limit": "Bỏ qua giới hạn nhập văn bản" - }, - "auto_purge": { - "never": "Không bao giờ", - "1_hour": "1 giờ", - "3_hours": "3 giờ", - "6_hours": "6 giờ", - "12_hours": "12 giờ", - "1_day": "1 ngày", - "3_days": "3 ngày", - "1_week": "1 tuần", - "2_weeks": "2 tuần", - "1_month": "1 tháng", - "3_months": "3 tháng", - "6_months": "6 tháng" - }, - "disable_story_sections": { - "friends": "Bạn", - "suggested_stories": "Câu chuyện được đề xuất", - "following": "Tiếp theo", - "discover": "Phát hiện" - }, - "disable_cameras": { - "front": "Camera trước", - "back": "Camera lùi" - }, - "disable_permission_requests": { - "notifications": "Thông báo", - "read_media_images": "Đọc hình ảnh phương tiện", - "read_media_video": "Đọc video truyền thông", - "camera": "Máy ảnh", - "microphone": "Micrô", - "location": "Vị trí", - "read_contacts": "Đọc Danh bạ", - "nearby_devices": "Thiết bị lân cận", - "phone_calls": "Cuộc gọi điện thoại" - }, - "message_indicators": { - "encryption_indicator": "Thêm biểu tượng 🔒 bên cạnh các tin nhắn chỉ được gửi cho bạn", - "platform_indicator": "Thêm biểu tượng nền tảng mà phương tiện được gửi từ đó (ví dụ: Android, iOS, Web)", - "location_indicator": "Thêm biểu tượng 📍 vào ảnh chụp nhanh khi chúng được gửi với tính năng định vị được bật", - "ovf_editor_indicator": "Cho biết liệu ảnh chụp nhanh đã được gửi bằng OVF Editor hay chưa", - "director_mode_indicator": "Thêm biểu tượng ✏️ vào ảnh chụp nhanh khi chúng được gửi bằng Chế độ Giám đốc, có thể được sử dụng để gửi hình ảnh thư viện dưới dạng ảnh chụp nhanh" - }, - "auto_mark_as_read": { - "conversation_read": "Đánh dấu cuộc trò chuyện là đã đọc khi gửi tin nhắn", - "snap_reply": "Đánh dấu ảnh chụp nhanh là đã đọc khi trả lời chúng", - "save_snap_in_chat": "Đánh dấu ảnh chụp nhanh là đã đọc khi lưu chúng trong cuộc trò chuyện ở Chế độ ẩn" - }, - "friend_mutation_notifier": { - "remove_friend": "Thông báo khi ai đó xóa bạn khỏi danh sách bạn bè", - "birthday_changes": "Thông báo khi ai đó thay đổi ngày sinh của họ", - "bitmoji_selfie_changes": "Thông báo khi ai đó thay đổi ảnh selfie Bitmoji của họ", - "bitmoji_avatar_changes": "Thông báo khi ai đó thay đổi hình đại diện Bitmoji của họ", - "bitmoji_background_changes": "Thông báo khi ai đó thay đổi nền Bitmoji của họ", - "bitmoji_scene_changes": "Thông báo khi ai đó thay đổi cảnh Bitmoji của họ" - }, - "snapchat_plus": { - "not_subscribed": "Chưa đăng ký", - "basic": "Nền tảng", - "ad_free": "Quảng cáo miễn phí" - }, - "double_tap_chat_action": { - "like_message": "Thích tin nhắn", - "copy_text": "Sao chép văn bản vào Clipboard", - "delete_message": "Xóa tin nhắn", - "mark_as_read": "Đánh dấu là đã đọc", - "custom_emoji_reaction": "Phản ứng biểu tượng cảm xúc tùy chỉnh" - }, - "startup_default_camera": { - "front": "Camera trước", - "back": "Camera lùi" - } - } - }, - "friend_menu_option": { - "mark_snaps_as_seen": "Đánh dấu Snaps như đã thấy", - "mark_stories_as_seen_locally": "Đánh dấu các câu chuyện là đã được xem tại địa phương", - "preview": "Xem trước", - "stealth_mode": "Chế độ tàng hình", - "auto_download_blacklist": "Tự động tải xuống danh sách đen", - "anti_auto_save": "Chống tự động lưu" - }, - "content_type": { - "CHAT": "Trò chuyện", - "SNAP": "Chụp nhanh", - "EXTERNAL_MEDIA": "Phương tiện bên ngoài", - "NOTE": "Ghi chú âm thanh", - "STICKER": "Hình dán", - "SHARE": "Chia sẻ", - "STATUS": "Trạng thái", - "LOCATION": "Vị trí", - "STATUS_SAVE_TO_CAMERA_ROLL": "Đã lưu vào Thư viện ảnh", - "STATUS_CONVERSATION_CAPTURE_SCREENSHOT": "Ảnh chụp màn hình", - "STATUS_CONVERSATION_CAPTURE_RECORD": "Bản ghi màn hình", - "STATUS_CALL_MISSED_VIDEO": "Cuộc gọi video bị nhỡ", - "STATUS_CALL_MISSED_AUDIO": "Cuộc gọi âm thanh bị nhỡ", - "LIVE_LOCATION_SHARE": "Chia sẻ vị trí trực tiếp", - "CREATIVE_TOOL_ITEM": "Mục công cụ sáng tạo", - "FAMILY_CENTER_INVITE": "Lời mời của Trung tâm Gia đình", - "FAMILY_CENTER_ACCEPT": "Trung tâm gia đình", - "FAMILY_CENTER_LEAVE": "Nghỉ phép ở trung tâm gia đình", - "STATUS_PLUS_GIFT": "Quà tặng Status Plus", - "TINY_SNAP": "Ảnh chụp nhỏ", - "STATUS_COUNTDOWN": "Đếm ngược", - "MAP_REACTION": "Phản ứng bản đồ" - }, - "media_download_source": { - "none": "Không có", - "pending": "Chưa giải quyết", - "chat_media": "Phương tiện trò chuyện", - "story": "Câu chuyện", - "public_story": "Câu chuyện công khai", - "spotlight": "Điểm sáng", - "profile_picture": "Ảnh hồ sơ", - "story_logger": "Trình ghi câu chuyện", - "message_logger": "Trình ghi tin nhắn", - "merged": "Đã hợp nhất", - "voice_call": "Cuộc gọi thoại" - }, - "chat_action_menu": { - "preview_button": "Xem trước", - "download_button": "Tải xuống", - "delete_logged_message_button": "Xóa tin nhắn đã ghi", - "show_chat_edit_history": "Hiển thị lịch sử chỉnh sửa trò chuyện", - "convert_message": "Chuyển đổi tin nhắn" - }, - "opera_context_menu": { - "download": "Tải xuống phương tiện", - "sent_at": "Đã gửi tại {date}", - "created_at": "Được tạo tại {date}", - "expires_at": "Hết hạn lúc {date}", - "media_size": "Kích thước phương tiện: {size}", - "media_duration": "Thời lượng phương tiện: {duration} ms", - "show_debug_info": "Hiển thị thông tin gỡ lỗi" - }, - "modal_option": { - "profile_info": "Thông tin hồ sơ", - "close": "Đóng" - }, - "gallery_media_send_override": { - "multiple_media_toast": "Bạn chỉ có thể gửi một phương tiện tại một thời điểm" - }, - "mark_as_seen": { - "no_unseen_snaps_toast": "Không tìm thấy Snap nào chưa được nhìn thấy!", - "seen_toast": "Đánh dấu là đã thấy!", - "unseen_toast": "Đã đánh dấu là chưa thấy!", - "already_seen_toast": "Đã được đánh dấu là đã thấy!", - "already_unseen_toast": "Đã được đánh dấu là chưa nhìn thấy!" - }, - "conversation_preview": { - "streak_expiration": "hết hạn sau {day} ngày {hour} giờ {minute} phút", - "total_messages": "Tổng số tin nhắn đã gửi/nhận: {count}", - "title": "Xem trước", - "unknown_user": "Người dùng không xác định", - "no_messages": "Không tìm thấy tin nhắn nào!" - }, - "profile_info": { - "title": "Thông tin hồ sơ", - "first_created_username": "Tên người dùng được tạo lần đầu", - "mutable_username": "Tên người dùng có thể thay đổi", - "display_name": "Tên hiển thị", - "added_date": "Ngày thêm", - "birthday": "Ngày sinh : {month} {day}", - "hidden_birthday": "Ngày sinh: Ẩn", - "friendship": "Tình bạn", - "add_source": "Thêm nguồn", - "snapchat_plus": "Snapchat Plus", - "snapchat_plus_state": { - "subscribed": "Đã đăng ký", - "not_subscribed": "Chưa đăng ký" - } - }, - "friendship_link_type": { - "mutual": "Qua lại", - "outgoing": "Hướng ngoại", - "blocked": "Bị chặn", - "deleted": "Đã xóa", - "following": "Tiếp theo", - "suggested": "được đề xuất", - "incoming": "Đang đến", - "incoming_follower": "Người theo dõi sắp tới" - }, - "bulk_messaging_action": { - "choose_action_title": "Chọn một hành động", - "progress_status": "Đang xử lý {index} trong số {total}", - "selection_dialog_continue_button": "Tiếp tục", - "confirmation_dialog": { - "title": "Bạn có chắc không?", - "message": "Điều này sẽ ảnh hưởng đến tất cả bạn bè đã chọn. Không thể hoàn tác hành động này." - }, - "actions": { - "remove_friends": "Xóa bạn bè", - "clear_conversations": "Xóa cuộc trò chuyện" - } - }, - "chat_export": { - "exporter_dialog": { - "select_conversations_title": "Chọn cuộc trò chuyện", - "text_field_selection": "__giữ chỗ_0__ đã chọn", - "text_field_selection_all": "Tất cả", - "export_file_format_title": "Xuất định dạng tệp", - "message_type_filter_title": "Lọc tin nhắn theo loại", - "amount_of_messages_title": "Số lượng tin nhắn (để trống cho tất cả)", - "download_medias_title": "Tải xuống phương tiện" - }, - "dialog_negative_button": "Hủy bỏ", - "dialog_positive_button": "Xuất khẩu", - "exported_to": "Đã xuất sang {path}", - "exporting_chats": "Đang xuất cuộc trò chuyện...", - "processing_chats": "Đang xử lý {amount} cuộc hội thoại...", - "export_fail": "Không xuất được cuộc trò chuyện {conversation}", - "writing_output": "Viết đầu ra...", - "finished": "Xong! Bây giờ bạn có thể đóng hộp thoại này.", - "no_messages_found": "Không tìm thấy tin nhắn nào!", - "exporting_message": "Đang xuất {conversation}..." - }, - "button": { - "ok": "ĐƯỢC RỒI", - "positive": "Đúng", - "negative": "KHÔNG", - "cancel": "Hủy bỏ", - "open": "Mở", - "download": "Tải xuống", - "send": "Gửi", - "restore_original": "Khôi phục bản gốc", - "convert_external_media": "Chuyển đổi phương tiện bên ngoài", - "save": "Cứu" - }, - "tracker_events": { - "conversation_enter": "Cuộc trò chuyện Nhập", - "conversation_exit": "Thoát cuộc trò chuyện", - "started_typing": "Đã bắt đầu nhập", - "stopped_typing": "Đã dừng gõ", - "started_speaking": "Bắt đầu nói", - "stopped_speaking": "ngừng nói", - "started_peeking": "Bắt đầu nhìn trộm", - "stopped_peeking": "Đã ngừng nhìn trộm", - "message_read": "Tin nhắn đã đọc", - "message_deleted": "Đã xóa tin nhắn", - "message_saved": "Đã lưu tin nhắn", - "message_unsaved": "Tin nhắn chưa được lưu", - "message_edited": "Tin nhắn đã được chỉnh sửa", - "message_reaction_add": "Phản ứng tin nhắn Thêm", - "message_reaction_remove": "Phản hồi tin nhắn Xóa", - "snap_opened": "Đã mở nhanh", - "snap_replayed": "Đã phát lại ảnh chụp nhanh", - "snap_replayed_twice": "Snap được phát lại hai lần", - "snap_screenshot": "Chụp ảnh màn hình", - "snap_screen_record": "Ghi màn hình chụp nhanh" - }, - "tracker_actions": { - "log": "Nhật ký", - "in_app_notification": "Thông báo trong ứng dụng", - "push_notification": "Thông báo đẩy", - "custom": "Phong tục" - }, - "better_notifications": { - "button": { - "reply": "Hồi đáp", - "download": "Tải xuống", - "mark_as_read": "Đánh dấu là đã đọc" - } - }, - "profile_picture_downloader": { - "button": "Tải xuống ảnh hồ sơ", - "title": "Trình tải ảnh hồ sơ", - "avatar_option": "Hình đại diện", - "background_option": "Lý lịch" - }, - "call_start_confirmation": { - "dialog_title": "Bắt đầu cuộc gọi", - "dialog_message": "Bạn có chắc chắn muốn bắt đầu cuộc gọi không?" - }, - "half_swipe_notifier": { - "notification_channel_name": "Vuốt một nửa", - "notification_content_dm": "{friend} vừa vuốt một nửa vào cuộc trò chuyện của bạn trong {duration} giây", - "notification_content_group": "{friend} vừa vuốt một nửa vào {group} trong {duration} giây" - }, - "download_processor": { - "attachment_type": { - "snap": "Chụp nhanh", - "sticker": "Hình dán", - "gif": "GIF", - "external_media": "Phương tiện bên ngoài", - "note": "Ghi chú", - "original_story": "Câu chuyện gốc" - }, - "select_attachments_title": "Chọn tệp đính kèm", - "download_started_toast": "Đã bắt đầu tải xuống", - "unsupported_content_type_toast": "Loại nội dung không được hỗ trợ!", - "failed_no_longer_available_toast": "Phương tiện không còn khả dụng", - "no_attachments_toast": "Không tìm thấy tệp đính kèm nào!", - "already_queued_toast": "Phương tiện đã được xếp hàng!", - "already_downloaded_toast": "Phương tiện đã được tải xuống!", - "content_saved_toast": "Đã lưu!", - "download_toast": "Đang tải xuống {path}...", - "processing_toast": "Đang xử lý {path}...", - "failed_generic_toast": "Không thể tải xuống", - "failed_to_create_preview_toast": "Không tạo được bản xem trước", - "failed_processing_toast": "Xử lý không thành công {error}", - "failed_gallery_toast": "Không lưu được vào thư viện {error}", - "dash_no_chapter": "Không tìm thấy chương", - "dash_dialog": { - "title": "Tải xuống phương tiện dash", - "download_all": "Tải xuống tất cả", - "segment_text": "Phân đoạn {from} - {to}" - } - }, - "streaks_reminder": { - "notification_title": "Vệt", - "notification_text": "Bạn sẽ mất Chuỗi của mình với {friend} sau {hoursLeft} giờ" - }, - "biometric_auth": { - "unlock_button": "Mở khóa", - "title": "Mở khóa Snapchat", - "subtitle": "Vui lòng xác thực để mở khóa Snapchat" - }, - "end_to_end_encryption": { - "toolbox": { - "no_shared_key": "Bạn chưa có bí mật nào được chia sẻ với người bạn này. Nhấp vào bên dưới để bắt đầu một cái mới.", - "shared_key_fingerprint": "Dấu vân tay của bạn là:\n\n__giữ chỗ_0__\n\nHãy chắc chắn kiểm tra xem nó có khớp với dấu vân tay của bạn bè bạn không!", - "initiate_exchange_button": "Bắt đầu trao đổi khóa" - }, - "confirmation_dialogs": { - "title": "Mã hóa đầu cuối", - "confirmation_1": "CẢNH BÁO: Thao tác này sẽ ghi đè khóa hiện có của bạn. Bạn sẽ mất quyền truy cập vào tất cả các tin nhắn được mã hóa từ người bạn này. Bạn có chắc chắn muốn tiếp tục không?", - "confirmation_2": "Bạn có THỰC SỰ chắc chắn muốn tiếp tục không? Đây là cơ hội cuối cùng để bạn rút lui." - }, - "unencrypted_conversation_send_failure_toast": "Bạn không thể gửi nội dung được mã hóa tới cả cuộc trò chuyện được mã hóa và không được mã hóa!", - "native_hooks_send_failure_toast": "Không gửi được! Vui lòng bật Móc gốc trong cài đặt.", - "no_participants_to_encrypt_toast": "Bạn không có bạn bè nào trong cuộc trò chuyện này để mã hóa tin nhắn!", - "encryption_failed_toast": "Không thể mã hóa tin nhắn! Kiểm tra logcat để biết thêm chi tiết.", - "accept_public_key_success_toast": "Khóa công khai được chấp nhận thành công!", - "accept_secret_key_success_toast": "Xong! Bây giờ bạn có thể gửi và nhận tin nhắn được mã hóa với người bạn này.", - "accept_public_key_failure_toast": "Không thể chấp nhận khóa công khai", - "accept_secret_key_failure_toast": "Không thể chấp nhận khóa bí mật", - "accept_secret_button": "Chấp nhận bí mật", - "accept_public_key_button": "Chấp nhận khóa công khai", - "outgoing_pk_message": "Yêu cầu trao đổi khóa", - "outgoing_secret_message": "Phản hồi trao đổi khóa", - "incoming_pk_message": "Bạn vừa nhận được yêu cầu khóa công khai. Bấm vào bên dưới để chấp nhận nó.", - "incoming_secret_message": "Bạn của bạn vừa chấp nhận khóa công khai của bạn. Nhấp vào bên dưới để chấp nhận bí mật." - }, - "auto_open_snaps": { - "title": "Tự động mở Snaps", - "notification_content": "{count} Đã mở phần đính kèm" - }, - "friend_mutation_observer": { - "notification_channel_name": "Người quan sát đột biến bạn bè", - "friend_removed": "{username} đã xóa bạn khỏi danh sách bạn bè", - "birthday_removed": "{username} đã xóa ngày sinh của họ ({birthday})", - "birthday_added": "{username} đã thêm ngày sinh của họ ({birthday})", - "birthday_changed": "{username} đã thay đổi ngày sinh của họ từ {oldBirthday} thành {newBirthday}", - "bitmoji_selfie_changed": "{username} đã thay đổi ảnh selfie Bitmoji của họ", - "bitmoji_avatar_changed": "{username} đã thay đổi hình đại diện Bitmoji của họ", - "bitmoji_background_changed": "{username} đã thay đổi nền Bitmoji của họ", - "bitmoji_scene_changed": "{username} đã thay đổi cảnh Bitmoji của họ" - }, - "material3_strings": { - "date_range_picker_start_headline": "Từ", - "date_range_picker_end_headline": "ĐẾN", - "date_range_picker_title": "Chọn phạm vi ngày", - "date_picker_switch_to_calendar_mode": "Lịch", - "date_picker_switch_to_input_mode": "đầu vào", - "date_range_picker_scroll_to_previous_month": "Tháng trước", - "date_range_picker_scroll_to_next_month": "Tháng tiếp theo", - "date_picker_today_description": "Hôm nay", - "date_range_picker_day_in_range": "Đã chọn", - "date_input_invalid_for_pattern": "Ngày không hợp lệ", - "date_input_invalid_year_range": "Năm không hợp lệ", - "date_input_invalid_not_allowed": "Ngày không hợp lệ", - "date_range_input_invalid_range_input": "Phạm vi ngày không hợp lệ" - }, - "send_override_dialog": { - "title": "Gửi phương tiện dưới dạng {type}", - "duration": "Thời lượng: {duration}", - "saveable_snap_hint": "Làm cho Snap có thể lưu được trong cuộc trò chuyện", - "unlimited_duration": "Không giới hạn" - }, - "invalid_input_toast": "Đầu vào không hợp lệ! Đảm bảo bạn đã nhập một giá trị hợp lệ." -} \ No newline at end of file diff --git a/common/src/main/assets/lang/wep.json b/common/src/main/assets/lang/wep.json new file mode 100644 index 00000000..c49f6a3f --- /dev/null +++ b/common/src/main/assets/lang/wep.json @@ -0,0 +1,1389 @@ +{ + "setup": { + "dialogs": { + "select_language": "Sprach uswähle", + "save_folder": "SnapEnhance benötigt Speicherberächtigunge zum Abelade und Speicher vo Medie vo Snapchat.\nBitte wähled Sie de Ort us wo d Medie sölled abeglade werde.", + "select_save_folder_button": "Ordner wählen" + }, + "mappings": { + "dialog": "Mappings werden generiert, dies könnte ein bisschen dauern ...", + "generate_failure_no_snapchat": "SnapEnhance konnte Snapchat nicht finden, bitte versuchen Sie Snapchat neu zu installieren.", + "generate_failure": "Beim Generieren der Zuordnungen ist ein Fehler aufgetreten. Bitte versuchen Sie es erneut." + }, + "permissions": { + "battery_optimization": "Batterieoptimierung", + "dialog": "Um fortfahren zu können, müssen Sie diese Anforderungen erfüllen:", + "notification_access": "Zugriff auf Benachrichtigungen", + "display_over_other_apps": "Über anderen Apps einblenden", + "request_button": "Anfordern" + } + }, + "manager": { + "sections": { + "social": { + "friends_tab": "Freunde", + "groups_tab": "Gruppen", + "empty_hint": "(leer)", + "streaks_expiration_short": "{hours}h" + }, + "manage_scope": { + "reminder_button": "Erinnerung erstellen", + "logged_stories_button": "Aufgezeichnete Stories anschauen", + "e2ee_title": "Ende-zu-Ende Verschlüsselung", + "rules_title": "Regeln", + "participants_text": "{count} Teilnehmer", + "not_found": "Nicht gefunden", + "streaks_title": "Streaks", + "streaks_length_text": "Länge: {length}", + "streaks_expiration_text": "Läuft ab in {eta}", + "streaks_expiration_text_expired": "Abgelaufen", + "delete_scope_confirm_dialog_title": "Sind Sie sicher, dass Sie ein {scope} löschen wollen?" + }, + "home": { + "update_title": "SnapEnhance Update", + "update_content": "Version {version} ist verfügbar!", + "update_button": "Herunterladen" + }, + "home_logs": { + "no_logs_hint": "Keine Protokolle verfügbar", + "clear_logs_button": "Protokolle löschen", + "export_logs_button": "Protokolle exportieren", + "saving_logs_toast": "Speichern von Protokollen, das kann eine Weile dauern ...", + "saved_logs_success_toast": "Protokolle erfolgreich gespeichert", + "saved_logs_failure_toast": "Speichern von Protokollen fehlgeschlagen" + }, + "home_settings": { + "actions_title": "Aktionen", + "message_logger_title": "Nachrichtenaufzeichner", + "debug_title": "Debuggen", + "success_toast": "Erledigt!", + "message_logger_summary": "{messageCount} Nachrichten\n{storyCount} Stories", + "export_button": "Exportieren", + "clear_button": "Löschen", + "view_logger_history_button": "Historie des Nachrichtenaufzeichners ansehen" + }, + "tasks": { + "no_tasks": "Keine Aufgaben", + "merge_files_toast": "Zusammenführen von {count} Dateien", + "remove_selected_tasks_title": "Sind Sie sicher, dass Sie die ausgewählten Aufgaben entfernen möchten?", + "remove_all_tasks_title": "Sind Sie sicher, dass Sie alle Aufgaben entfernen möchten?", + "delete_files_option": "Auch Dateien löschen", + "remove_selected_tasks_confirm": "{count} Aufgaben entfernen?", + "remove_all_tasks_confirm": "Alle Aufgaben entfernen?" + }, + "features": { + "disabled": "Deaktiviert", + "export_option": "Exportieren", + "import_option": "Importieren", + "reset_option": "Zurücksetzen", + "config_export_success_toast": "Einstellungen erfolgreich exportiert", + "config_import_success_toast": "Einstellungen erfolgreich importiert", + "config_import_failure_toast": "Einstellungen konnten nicht importiert werden. {error}", + "saved_config_snackbar": "Einstellungen gespeichert" + }, + "logged_stories": { + "story_failed_to_load": "Laden fehlgeschlagen", + "no_stories": "Keine Stories gefunden", + "save_from_cache_button": "Aus Zwischenspeicher speichern" + }, + "messaging_preview": { + "bridge_connection_failed": "Verbindung zu Snapchat über den Brückendienst fehlgeschlagen", + "bridge_init_failed": "Initialisierung der Nachrichtenbrücke fehlgeschlagen", + "message_fetch_failed": "Fehler beim Abrufen der Nachrichten", + "no_message_hint": "Keine Nachricht", + "save_selection_option": "Auswahl speichern", + "save_all_option": "Alles speichern", + "unsave_selection_option": "Auswahl nicht mehr speichern", + "unsave_all_option": "Alles nicht mehr speichern", + "mark_selection_as_seen_option": "Ausgewählten Snap als gesehen markieren", + "mark_all_as_seen_option": "Alle Snaps als gesehen markieren", + "delete_selection_option": "Auswahl löschen", + "delete_all_option": "Alles löschen" + }, + "logger_history": { + "list_friend_format": "Freund {name}", + "list_group_format": "Gruppe {name}", + "no_more_messages": "Keine weiteren Nachrichten", + "reverse_order_checkbox": "Umgekehrte Reihenfolge", + "chat_attachment": "Anhang {index}", + "empty_message": "Leere Chatnachricht", + "message_parse_failed": "Nachricht konnte nicht verarbeitet werden", + "unknown_sender": "Unbekannter Absender", + "download_attachment_failed_toast": "Fehler beim Herunterladen des Anhangs" + } + }, + "dialogs": { + "add_friend": { + "search_hint": "Suchen", + "title": "Freund oder Gruppe hinzufügen", + "fetch_error": "Fehler beim Abrufen der Daten", + "category_groups": "Gruppen", + "category_friends": "Freunde" + }, + "reset_config": { + "title": "Einstellungen zurücksetzen", + "content": "Bist Du sicher, dass Du die Einstellungen zurücksetzen möchtest?", + "success_toast": "Einstellungen erfolgreich zurückgesetzt" + }, + "scripting_warning": { + "title": "Warnung", + "content": "SnapEnhance enthält ein Skripting-Tool, das die Ausführung von benutzerdefinierten Code auf Ihrem Gerät ermöglicht. Seien Sie äußerst vorsichtig und installieren Sie nur Module aus bekannten, zuverlässigen Quellen. Unautorisierte oder ungeprüfte Module können Sicherheitsrisiken für Ihr System darstellen." + }, + "messaging_action": { + "title": "Wählen Sie die zu verarbeitenden Inhaltstypen um fortzufahren", + "select_all_button": "Alle auswählen" + } + }, + "routes": { + "tasks": "Aufgaben", + "features": "Funktionen", + "home": "Startseite", + "home_settings": "Einstellungen", + "home_logs": "Logs", + "logger_history": "Logs Verlauf", + "logged_stories": "Geloggte Storys", + "friend_tracker": "Freundtracker:in", + "edit_rule": "Regel bearbeiten", + "social": "Sozial", + "manage_scope": "Verwalte Scope", + "messaging_preview": "Vorschau", + "scripts": "Skripte" + } + }, + "features": { + "properties": { + "scripting": { + "properties": { + "integrated_ui": { + "name": "Integrierte Benutzeroberfläche", + "description": "Erlaubt Skripten, benutzerdefinierte UI-Komponenten zu Snapchat hinzuzufügen" + }, + "developer_mode": { + "name": "Entwickler:innenmodus", + "description": "Zeigt Debug-Informationen auf Snapchat's UI" + }, + "module_folder": { + "name": "Modulordner", + "description": "Der Ordner, in dem sich die Skripte befinden" + }, + "auto_reload": { + "name": "Automatisches Neuladen", + "description": "Automatisches Neuladen von Skripten, wenn diese sich ändern" + }, + "disable_log_anonymization": { + "name": "Log-Anonymisierung deaktivieren", + "description": "Deaktiviert die Anonymisierung von Logs" + } + }, + "name": "Scripting", + "description": "Benutzerdefinierte Skripte ausführen, um SnapEnhance zu erweitern" + }, + "downloader": { + "name": "Downloader", + "description": "Snapchat Medien herunterladen", + "properties": { + "save_folder": { + "name": "Speicherverzeichnis", + "description": "Wähle das Verzeichnis, in das alle Medien heruntergeladen werden sollen" + }, + "auto_download_sources": { + "name": "Quellen automatisch herunterladen", + "description": "Wähle die Quellen, von denen automatisch herunterzuladen ist" + }, + "prevent_self_auto_download": { + "name": "Selbst-Auto-Download verhindern", + "description": "Verhindert, dass eigene Snaps automatisch heruntergeladen werden" + }, + "path_format": { + "name": "Pfadformat", + "description": "Gib das Dateiformat an" + }, + "allow_duplicate": { + "name": "Duplikate erlauben", + "description": "Ermöglicht es, dass dieselben Medien mehrmals heruntergeladen werden" + }, + "merge_overlays": { + "name": "Overlays zusammenführen", + "description": "Kombiniert den Text und die Medien eines Snaps in eine Datei" + }, + "force_image_format": { + "name": "Bildformat erzwingen", + "description": "Erzwingt das Speichern von Bildern in einem bestimmten Format" + }, + "force_voice_note_format": { + "name": "Sprachnotiz Format erzwingen", + "description": "Erzwingt das Speichern von Sprachnotizen in einem bestimmten Format" + }, + "download_profile_pictures": { + "name": "Profilbilder herunterladen", + "description": "Ermöglicht das Herunterladen von Profilbildern von einer Profilseite" + }, + "opera_download_button": { + "name": "Schwebender Download Button", + "description": "Fügt einen Download-Button in der oberen rechten Ecke hinzu, wenn ein Snap angezeigt wird.\nGedrückt halten um einen Download zu starten" + }, + "download_context_menu": { + "name": "Download Kontext Menü", + "description": "Ermöglicht es, Nachrichten oder eine Story herunterzuladen/vorher anzuschauen mithilfe des Kontext Menüs.\nLanges Drücken des Knopfes erzwingt den Download" + }, + "ffmpeg_options": { + "name": "FFmpeg-Optionen", + "description": "Zusätzliche FFmpeg-Optionen angeben", + "properties": { + "threads": { + "name": "Threads", + "description": "Die Anzahl Threads, welche zu gebrauchen ist" + }, + "preset": { + "name": "Voreinstellungen", + "description": "Geschwindigkeit der Konvertierung festlegen" + }, + "constant_rate_factor": { + "name": "Konstanter Rate-Faktor", + "description": "Setze den Constant Rate Factor für den Video-Encoder\nvon 0 bis 51 für libx264" + }, + "video_bitrate": { + "name": "Videobitrate", + "description": "Video-Bitrate (kbps) festlegen" + }, + "audio_bitrate": { + "name": "Audiobitrate", + "description": "Audio-Bitrate (kbps) festlegen" + }, + "custom_video_codec": { + "name": "Benutzerdefinierter Video-Codec", + "description": "Wähle einen benutzerdefinierten Video-Codec (z.B. libx264)" + }, + "custom_audio_codec": { + "name": "Benutzerdefinierter Audio-Codec", + "description": "Wähle einen benutzerdefinierten Audio-Codec (z.B. AAC)" + } + } + }, + "logging": { + "name": "Logging", + "description": "Zeigt Toasts, wenn Medien heruntergeladen werden" + }, + "custom_path_format": { + "name": "Benutzerdefiniertes Pfadformat", + "description": "Legen Sie ein benutzerdefiniertes Pfadformat für heruntergeladene Medien fest\n\nVerfügbare Variablen:\n - %username%\n - %source%\n - %hash%\n - %date_time%" + } + } + }, + "user_interface": { + "name": "Benutzeroberfläche", + "description": "Ändere das Aussehen von Snapchat", + "properties": { + "enable_app_appearance": { + "name": "Aktiviert die App Darstellungseinstellungen", + "description": "Aktiviert die versteckte App-Erscheinungsbild Einstellung,\nbei neueren Snapchat-Versionen möglicherweise nicht erforderlich" + }, + "friend_feed_message_preview": { + "name": "Freund Feed Nachrichten Vorschau", + "description": "Zeigt eine Vorschau der letzten Nachrichten im Freundes-Feed", + "properties": { + "amount": { + "name": "Anzahl", + "description": "Die Anzahl der Nachrichten, die in der Vorschau angezeigt werden" + } + } + }, + "snap_preview": { + "name": "Snap-Vorschau", + "description": "Zeigt eine kleine Vorschau neben ungesehenen Snaps im Chat an" + }, + "bootstrap_override": { + "name": "Bootstrap Überschreibung", + "description": "Bootstrap-Einstellungen der Benutzeroberfläche überschreiben", + "properties": { + "app_appearance": { + "name": "App-Erscheinungsbild", + "description": "Legt eine dauerhafte App-Darstellung fest" + }, + "home_tab": { + "name": "Home Registerkarte", + "description": "Überschreibt den Start-Tab beim Öffnen von Snapchat" + } + } + }, + "map_friend_nametags": { + "name": "Verbesserte Karten-Namensschilder von Freunden", + "description": "Verbessert die Namensschilder von Freunden auf der Snapmap" + }, + "prevent_message_list_auto_scroll": { + "name": "Automatisches Scrollen der Nachrichtenliste verhindern", + "description": "Verhindert, dass die Nachrichtenliste beim Senden/Empfangen einer Nachricht nach unten scrollt" + }, + "streak_expiration_info": { + "name": "Informationen zum Flammen-Ablauf anzeigen", + "description": "Zeigt einen Flammen-Ablauf-Timer neben dem Flammen-Zähler" + }, + "hide_friend_feed_entry": { + "name": "Freund Feed Eintrag ausblenden", + "description": "Versteckt einen bestimmten Freund aus dem Freundes-Feed,\nBenutze den sozialen Tab um diese Funktion zu verwalten" + }, + "hide_streak_restore": { + "name": "Flammen-Wiederherstellung verstecken", + "description": "Versteckt den Wiederherstellen-Button im Freundesfeed" + }, + "hide_story_suggestions": { + "name": "Story Vorschläge ausblenden", + "description": "Entfernt Empfehlungen von der Story‐Seite" + }, + "hide_ui_components": { + "name": "UI-Komponenten ausblenden", + "description": "Wähle aus welche UI-Elemente ausgeblendet werden sollen" + }, + "opera_media_quick_info": { + "name": "Medien Schnellinfo", + "description": "Zeigt nützliche Informationen zu Medien wie das Erstellungsdatum im Kontextmenü der Snap-Ansicht an" + }, + "old_bitmoji_selfie": { + "name": "Altes Bitmoji-Selfie", + "description": "Bringt die Bitmoji-Selfies aus früheren Snapchat-Versionen zurück" + }, + "disable_spotlight": { + "name": "Spotlight deaktivieren", + "description": "Deaktiviert die Spotlight Seite" + }, + "friend_feed_menu_buttons": { + "name": "Schaltflächen für das Freunde-Feed Menü", + "description": "Wähle aus welche Schaltflächen in der Freunde Feed Menüleiste angezeigt werden sollen" + }, + "vertical_story_viewer": { + "name": "Vertikale Story Ansicht", + "description": "Aktiviert die vertikale Story Ansicht für alle Storys" + }, + "enable_friend_feed_menu_bar": { + "name": "Freunde Feed Menüleiste", + "description": "Aktiviert die neue Freunde Feed Menüleiste" + }, + "message_indicators": { + "name": "Nachrichtenindikatoren", + "description": "Fügt Nachrichten spezifische Anzeigesymbole hinzu\nHinweis: Die Symbole sind möglicherweise nicht 100 % genau" + }, + "stealth_mode_indicator": { + "name": "Diebstahl Modus Indikator", + "description": "Fügt den Konversationen im Stealth-Modus ein 👻-Emoji hinzu" + }, + "edit_text_override": { + "name": "Textfeld-Verhalten überschreiben", + "description": "Überschreibt das Verhalten von Textfeldern" + } + } + }, + "messaging": { + "name": "Mitteilungen", + "description": "Ändern wie mit Freunden interagiert wird", + "properties": { + "bypass_screenshot_detection": { + "name": "Umgehen der Screenshot-Erkennung", + "description": "Verhindert, dass Snapchat erkennt, wenn du einen Screenshot machst" + }, + "anonymous_story_viewing": { + "name": "Anonyme Story Ansicht", + "description": "Verhindert, dass jemand erfährt, dass du seine Story gesehen hast" + }, + "prevent_story_rewatch_indicator": { + "name": "Wiederholungs-Indikator bei Stories verhindern", + "description": "Verhindert, dass andere wissen, dass Sie ihre Story noch einmal angeschaut haben" + }, + "hide_peek_a_peek": { + "name": "Vorschau Benachrichtigung verhindern", + "description": "Verhindert, dass eine Benachrichtigung gesendet wird, wenn Sie halb in einen Chat swipen" + }, + "hide_bitmoji_presence": { + "name": "Bitmoji Präsenz verstecken", + "description": "Verhindert, dass dein Bitmoji im Chat auftaucht" + }, + "hide_typing_notifications": { + "name": "Tippen-Benachrichtigungen verbergen", + "description": "Verhindert, dass jemand erfährt, dass du eine Nachricht tippst" + }, + "unlimited_snap_view_time": { + "name": "Unbegrenzte Zeit zum Ansehen von Snaps", + "description": "Entfernt das Zeitlimit für die Anzeige von Snaps" + }, + "auto_mark_as_read": { + "name": "Automatisch als gelesen markieren", + "description": "Markiert Nachrichten bzw. Snaps automatisch als gelesen wenn der Stealth Mode aktiviert ist" + }, + "loop_media_playback": { + "name": "Medien Wiedergabe Wiederholen", + "description": "Wiederholt Snaps & Stories beim ansehen in einer Schleife" + }, + "disable_replay_in_ff": { + "name": "Replay in FF deaktivieren", + "description": "Deaktiviert die Möglichkeit, mit einem langen Drücken vom Freundes-Feed zu wiederholen" + }, + "half_swipe_notifier": { + "name": "Über Half-Swipes informieren", + "description": "Benachrichtigt Sie, wenn jemand halb in ihren Chat swiped", + "properties": { + "min_duration": { + "name": "Mindestdauer", + "description": "Die Mindestdauer der halben Swipes (in Sekunden)" + }, + "max_duration": { + "name": "Maximale Dauer", + "description": "Die maximale Dauer des halben Swipes (in Sekunden)" + } + } + }, + "call_start_confirmation": { + "name": "Bestätigung des Starts eines Anrufs", + "description": "Zeigt einen Bestätigungsdialog beim Starten eines Anrufs an" + }, + "unlimited_conversation_pinning": { + "name": "Unlimitiertes Anpinnen von Konversationen", + "description": "Erlaubt dir eine unlimitierte Anzahl von Konversationen lokal anzupinnen" + }, + "prevent_message_sending": { + "name": "Nachrichtenversand verhindern", + "description": "Verhindert das Versenden bestimmter Nachrichten" + }, + "friend_mutation_notifier": { + "name": "Freund-Mutationsbenachrichtigung", + "description": "Benachrichtigt Sie, wenn sich etwas im Profil eines Freundes ändert" + }, + "better_notifications": { + "name": "Bessere Benachrichtigungen", + "description": "Zeige weitere Informationen in Benachrichtigungen an" + }, + "notification_blacklist": { + "name": "Benachrichtigungs Blacklist", + "description": "Wählen Sie Benachrichtigungen aus, die blockiert werden sollen" + }, + "message_logger": { + "name": "Nachrichten Logger", + "description": "Verhindert, dass Nachrichten gelöscht werden", + "properties": { + "keep_my_own_messages": { + "name": "Eigene Nachrichten behalten", + "description": "Verhindert, dass Ihre eigenen Nachrichten gelöscht werden" + }, + "auto_purge": { + "name": "Automatische Bereinigung", + "description": "Löscht automatisch zwischengespeicherte Nachrichten, die älter als die angegebene Zeit sind" + }, + "message_filter": { + "name": "Nachrichtenfilter", + "description": "Wählen Sie aus, welche Nachrichten behalten werden sollen (leer für alle Nachrichten)" + } + } + }, + "auto_save_messages_in_conversations": { + "name": "Automatisches Speichern von Nachrichten", + "description": "Speichert automatisch jede Nachricht in Unterhaltungen" + }, + "gallery_media_send_override": { + "name": "Galerie-Medien senden Überschreiben", + "description": "Fälscht die Medienquelle, wenn etwas von der Galerie gesendet wird" + }, + "strip_media_metadata": { + "name": "Medien-Metadaten entfernen", + "description": "Entfernt Metadaten von Medien vor dem Versand als Nachricht" + }, + "bypass_message_retention_policy": { + "name": "Umgehung der Richtlinie zur Aufbewahrung von Nachrichten", + "description": "Verhindert, dass Nachrichten nach dem Anzeigen gelöscht werden" + }, + "bypass_message_action_restrictions": { + "name": "Umgehung von Nachrichtenaktionsbeschränkungen", + "description": "Ermöglicht es Ihnen, auf einen Snap zu reagieren, ohne ihn geöffnet zu haben, oder eine nicht speicherbare Nachricht zu speichern" + }, + "remove_groups_locked_status": { + "name": "Entfernen des Gruppen-Sperrstatus", + "description": "Ermöglicht es Ihnen, nach dem Rauswurf Gruppeninformationen anzuzeigen" + } + } + }, + "global": { + "name": "Global", + "description": "Globale Snapchat-Einstellungen anpassen", + "properties": { + "better_location": { + "name": "Besserer Ort", + "description": "Erweitert den Snapchat-Ort", + "properties": { + "spoof_location": { + "name": "Täusche den Ort", + "description": "Täuscht Ihren Standort auf einen bestimmten Ort vor" + }, + "coordinates": { + "name": "Koordinaten", + "description": "Wähle die Koordinaten des getäuschten Standorts" + }, + "walk_radius": { + "name": "Radius", + "description": "Laufe zufälligerweise in diesem Radium (ft) herum" + }, + "always_update_location": { + "name": "Aktualisiere den Ort immer", + "description": "Zwingt Snapchat dazu, die den Standort zu aktualisieren, auch wenn es kein GPS Signal erhält" + }, + "suspend_location_updates": { + "name": "Stoppe die Aktualisierung des Standortes", + "description": "Fügt in den Karteneinstellungen eine Schaltfläche hinzu, um Standortaktualisierungen auszusetzen" + }, + "spoof_battery_level": { + "name": "­Täusche den Akkustand vor", + "description": "Verfälscht den Akkustand Ihres Geräts auf der Karte\nDer Wert muss zwischen 0 und 100 liegen" + }, + "spoof_headphones": { + "name": "Simuliere Kopfhörer", + "description": "Verfälscht den Status des Musikhörens auf der Karte" + } + } + }, + "snapchat_plus": { + "name": "Snapchat Plus", + "description": "Aktiviert Snapchat Plus Funktionen\nEinige serverseitige Funktionen funktionieren möglicherweise nicht" + }, + "media_upload_quality": { + "name": "Qualität", + "description": "Überschreibt die Medienuploadqualität", + "properties": { + "force_video_upload_source_quality": { + "name": "Erzwingen Sie die Qualität der Video-Upload-Quelle", + "description": "Erzwing Snapchat die Quellenqualität zu nutzen, wenn Videos hochgelden werden\nBitte merkte, dass dies eventuell die Metadaten von Medien nicht entfernt" + }, + "disable_image_compression": { + "name": "Deaktiviert Bildkompression", + "description": "Deaktiviert Bildkompression, wenn Medien hochgeladen werden" + }, + "custom_image_upload_format": { + "name": "Benutzerdefiniertes Bild-Upload-Format", + "description": "Setzt ein benutzerdefiniertes Bildhochladformat\nWähle ein verlustfreies Format (wie PNG) für die beste Qualität" + } + } + }, + "disable_confirmation_dialogs": { + "name": "Bestätigungsdialoge deaktivieren", + "description": "Bestätigt automatisch ausgewählte Aktionen" + }, + "auto_updater": { + "name": "Auto Updater", + "description": "Automatisch auf Updates prüfen" + }, + "disable_metrics": { + "name": "Metriken deaktivieren", + "description": "Verhindert das Senden von analytischen Daten an Snapchat" + }, + "disable_story_sections": { + "name": "Story Sektion deaktivieren", + "description": "Entfernt Sektionen von der Story-Seite\nErfordert möglicherweise eine Aktualisierung, um richtig zu funktionieren" + }, + "disable_custom_tabs": { + "description": "Öffnet Links in unterstützen Applikationen, anstatt dem Webbrowser", + "name": "Deaktivieren Sie benutzerdefinierte Registerkarten" + }, + "block_ads": { + "name": "Werbung blockieren", + "description": "Verhindert die Anzeige von Werbung" + }, + "disable_permission_requests": { + "name": "Berechtigungsanfragen deaktivieren", + "description": "Verhindert, dass Snapchat nach bestimmten Berechtigungen fragt" + }, + "bypass_video_length_restriction": { + "name": "Umgeht Videolängenbeschränkungen", + "description": "Einzel: sendet ein einzelnes Video\nSplitt: Videos nach Bearbeitung aufteilen" + }, + "disable_memories_snap_feed": { + "name": "Memories Snap Feed deaktivieren", + "description": "Verhindert, dass Snapchat aktuelle Erinnerungen anzeigt, wenn Sie in der Kamera nach oben wischen" + }, + "spotlight_comments_username": { + "name": "Spotlight Kommentare Benutzername", + "description": "Zeigt den Benutzernamen des Autors in Spotlight-Kommentaren an" + }, + "default_video_playback_rate": { + "name": "Standardmäßige Videowiedergaberate", + "description": "Legt die Standardgeschwindigkeit für die Wiedergabe von Videos fest\n\tDer Wert muss zwischen 0,1 und 4,0 liegen" + }, + "video_playback_rate_slider": { + "name": "Schieberegler für die Videowiedergaberate", + "description": "Fügt einen Schieberegler im Opera-Kontextmenü hinzu, um die Videowiedergabegeschwindigkeit zu ändern\nHinweis: Änderungen gelten nur für nachfolgende Videos" + }, + "disable_google_play_dialogs": { + "name": "Google Play-Service Dialog deaktivieren", + "description": "Verfügbarkeitsdialog für Google Play Services nicht anzeigen" + }, + "default_volume_controls": { + "name": "Standard Lautstärkekontrolle", + "description": "Zwinge Snapchat die Systemlautstärke zu nutzen" + }, + "hide_active_music": { + "name": "Aktive Musik ausblenden", + "description": "Verhindert, dass Snapchat erkennt, dass Sie Musik hören.\nSo können Sie mithilfe der Lautstärketasten Snaps aufnehmen, während Sie Musik hören" + }, + "disable_snap_splitting": { + "name": "Snap-Aufteilung deaktivieren", + "description": "Verhindert, dass Snaps in mehrere Teile aufgeteilt werden\nBilder werden in Videos umgewandelt" + } + } + }, + "rules": { + "name": "Regeln", + "description": "Automatische Funktionen für einzelne Personen verwalten" + }, + "camera": { + "name": "Kamera", + "description": "Pass die richtigen Einstellungen für den perfekten Snap an", + "properties": { + "disable_cameras": { + "name": "Kameras deaktivieren", + "description": "Verhindert, dass Snapchat die gewählten Kameras nutzt" + }, + "black_photos": { + "name": "Schwarze Fotos", + "description": "Ersetzt die aufgenommenen Fotos durch einen schwarzen Hintergrund\nVideos sind davon nicht betroffen" + }, + "immersive_camera_preview": { + "name": "Immersive Vorschau", + "description": "Verhindert das Beschneiden der Kameravorschau\nDas kann dazu führen, dass die Kamera auf einigen Geräten flickert" + }, + "override_front_resolution": { + "name": "Überschreiben der Frontauflösung", + "description": "Überschreibt die Kameraauflösung für die Selfie-Kamera" + }, + "override_back_resolution": { + "name": "Hauptkamera Auflösung überschreiben", + "description": "Überschreibt die Kameraauflösung der Hauptkamera" + }, + "custom_resolution": { + "name": "Benutzerdefinierte Auflösung", + "description": "Legt eine benutzerdefinierte Kameraauflösung (Breite x Höhe) fest (z. B. 1920x1080).\nDie benutzerdefinierte Auflösung muss von Ihrem Gerät unterstützt werden" + }, + "front_custom_frame_rate": { + "name": "Benutzerdefinierte Frame-Rate Selfie-Kamera", + "description": "Überschreibt die Frame-Rate der Selfie-Kamera" + }, + "back_custom_frame_rate": { + "name": "Benutzerdefinierte Frame-Rate Haupt-Kamera", + "description": "Überschreibt die Frame-Rate der Haupt-Kamera" + }, + "force_camera_source_encoding": { + "name": "Kodierung der Kameraquelle erzwingen", + "description": "Erzwingt die Kodierung der Kameraquelle" + }, + "hevc_recording": { + "name": "HEVC Aufnahme", + "description": "Verwendet HEVC (H.265) Codec für die Videoaufzeichnung" + } + } + }, + "streaks_reminder": { + "name": "Flammen-Erinnerung", + "description": "Benachrichtigt dich regelmäßig über deine Flammen", + "properties": { + "interval": { + "name": "Intervall", + "description": "Das Intervall zwischen jeder Erinnerung (Stunden)" + }, + "remaining_hours": { + "name": "Verbleibende Zeit", + "description": "Die verbleibende Zeit, bevor die Benachrichtigung angezeigt wird (in Stunden)" + }, + "group_notifications": { + "name": "Gruppierte Benachrichtigungen", + "description": "Benachrichtigungen in eine einzelne gruppieren" + } + } + }, + "experimental": { + "name": "Experimentell", + "description": "Experimentelle Funktionen", + "properties": { + "native_hooks": { + "name": "Native Hooks", + "description": "Unsichere Funktionen, welche sich in Snapchats nativen Code einhängen", + "properties": { + "composer_hooks": { + "name": "Composer Haken", + "description": "Injiziert Code in das Composer UI-Framework (nur arm64)", + "properties": { + "show_first_created_username": { + "name": "Zeige erstgewählten Benutzernamen", + "description": "Zeige den erstgewählten Benutzernamen neben dem jetzigen Benutzernamen in der Profileseite" + }, + "bypass_camera_roll_limit": { + "name": "Umgeht das Kamerarollenlimit", + "description": "Erhöht die maximale Anzahl von Medien, die Sie aus der Kamerarolle senden können" + }, + "composer_console": { + "name": "Composer-Konsole", + "description": "Ermöglicht das Ausführen von JavaScript-Code in Composer (nur arm64)" + }, + "composer_logs": { + "name": "Composer-Protokolle", + "description": "Leitet Konsolenprotokolle von Composer zu SnapEnhance um" + } + } + }, + "disable_bitmoji": { + "name": "Bitmojis deaktivieren", + "description": "Deaktiviert das Bitmoji des Freund:innenprofil" + } + } + }, + "spoof": { + "name": "Simulieren", + "description": "Verschiedene Informationen über dich vortäuschen", + "properties": { + "play_store_installer_package_name": { + "name": "Goolge Play Installationsname des Paketes", + "description": "Überschreibt den Namen des Installationspakets auf com.android.vending_machine" + }, + "remove_vpn_transport_flag": { + "name": "VPN-Transport-Flagge entfernen", + "description": "Hindert Snapchat daran, VPNs zu erkennen" + }, + "remove_mock_location_flag": { + "name": "Kennzeichnung für den gefälschten Standort entfernen", + "description": "Verhindert, dass Snapchat gefälschte Standorte erkennt" + } + } + }, + "convert_message_locally": { + "name": "Nachricht lokal umwandeln", + "description": "Konvertiert Snaps lokal in externe Chat-Medien. Dies erscheint im Kontextmenü für den Chat-Download" + }, + "media_file_picker": { + "name": "Mediendatei-Auswahl", + "description": "Ermöglicht es beliebige Video und Audio Dateien von der Gallerie auszuwählen" + }, + "story_logger": { + "name": "Geschichtenprotokollierer", + "description": "Liefert eine Historie der Stories von Freund:innen" + }, + "call_recorder": { + "name": "Anrufaufzeichner", + "description": "Zeichnet automatisch Audioanrufe auf" + }, + "account_switcher": { + "name": "­Accountwechsler", + "properties": { + "auto_backup_current_account": { + "name": "Automatisches Backup des aktuellen Accounts", + "description": "Automatisch wird das aktuelle Konto gesichert, wenn Sie sich ausloggen oder zwischen Konten wechseln" + } + }, + "description": "Ermöglicht es Ihnen, zwischen Konten zu wechseln, ohne sich auszuloggen\nHalten Sie lange auf das Suchsymbol neben Ihrem Bitmoji-Profil, um das Menü zu öffnen\nHinweis: Diese Funktion ist experimentell und wird wahrscheinlich in Zukunft geändert" + }, + "edit_message": { + "name": "Nachrichten bearbeiten", + "description": "Ermöglicht es Nachrichten in Konversationen zu bearbeiten" + }, + "app_lock": { + "name": "App-Sperre", + "description": "Verhindert den Zugriff auf Snapchat ohne einen passcode", + "properties": { + "lock_on_resume": { + "name": "Sperren beim fortsetzen", + "description": "Sperrt die App wenn sie wieder geöffnet wird" + } + } + }, + "infinite_story_boost": { + "name": "Unendlicher Story Boost", + "description": "Story Boost Limit Verzögerung umgehen" + }, + "meo_passcode_bypass": { + "name": "Passwortumgehung für privaten Bereich", + "description": "Umgeht das Passwort für den privaten Bereich\nFunktioniert nur, wenn das korrekte Passwort schon einmal eingegeben wurde" + }, + "no_friend_score_delay": { + "name": "Keine Friend Score Verzögerung", + "description": "Entfernt die Verzögerung beim Betrachten einer Friends Score" + }, + "best_friend_pinning": { + "name": "Bester Freund Pinning", + "description": "Erlaubt einen Freund als besten Freund Nummer 1 anzupinnen. Notiz: Nur du kannst deinen gepinnten besten Freund sehen" + }, + "e2ee": { + "name": "Ende-zu-Ende-Verschlüsselung", + "description": "Verschlüsselt deine Nachrichten mit AES unter Verwendung eines freigegebenen geheimen Schlüssels\nAchte darauf, dass du deinen Schlüssel an einem sicheren Ort aufbewahrst!", + "properties": { + "encrypted_message_indicator": { + "name": "Anzeige für verschlüsselte Nachrichten", + "description": "Fügt einen 🔒 Emoji neben verschlüsselten Nachrichten hinzu" + }, + "force_message_encryption": { + "name": "Nachrichtenverschlüsselung erzwingen", + "description": "Verhindert das Senden von verschlüsselten Nachrichten an Personen, die keine E2E-Verschlüsselung aktiviert haben, wenn mehrere Unterhaltungen ausgewählt sind" + } + } + }, + "add_friend_source_spoof": { + "name": "Freundesquellen-Änderung hinzufügen", + "description": "Verfälscht die Quelle einer Freundschaftsanfrage" + }, + "hidden_snapchat_plus_features": { + "name": "Verborgene Snapchat Plus-Funktionen", + "description": "Aktiviert unveröffentlichte/beta Snapchat Plus Funktionen\nKönnte auf älteren Snapchat-Versionen nicht funktionieren" + }, + "custom_streaks_expiration_format": { + "name": "Benutzerdefiniertes Ablaufdatum für Serien", + "description": "Passt das Ablaufdatumformat für Serien an\n\nVerfügbare Variablen:\n- %c: Anzahl der Serien\n- %e: Sanduhr-Emoji\n- %d: Tage\n- %h: Stunden\n- %m: Minuten\n- %s: Sekunden\n- %w: Verbleibende Zeit" + }, + "prevent_forced_logout": { + "name": "Erzwungenen Logout verhindern", + "description": "Verhindert, dass Snapchat dich abmeldet, wenn du dich auf einem anderen Gerät anmeldest" + } + } + }, + "friend_tracker": { + "name": "Freundestracker", + "description": "Die Aktivität der Freunde aufzeichnen", + "properties": { + "record_messaging_events": { + "name": "Nachrichtenevents aufzeichnen", + "description": "Zeichnet Nachrichtenereignisse wie das Öffnen eines Snaps, das Lesen einer Nachricht usw. auf." + }, + "allow_running_in_background": { + "name": "Hintergrundnutzung erlauben", + "description": "Ermöglicht die Ausführung des Trackers im Hintergrund. Hinweis: Dadurch wird Ihr Akku erheblich entladen" + } + } + } + }, + "options": { + "auto_reload": { + "snapchat_only": "Nur Snapchat", + "all": "Alles (Snapchat + SnapEnhance)" + }, + "auto_purge": { + "12_hours": "12 Stunden", + "1_day": "1 Tag", + "3_days": "3 Tage", + "3_months": "3 Monate", + "6_months": "6 Monate", + "never": "Nie", + "1_hour": "1 Stunde", + "3_hours": "3 Stunden", + "6_hours": "6 Stunden", + "1_week": "1 Woche", + "2_weeks": "2 Wochen", + "1_month": "1 Monat" + }, + "disable_story_sections": { + "friends": "Freunde", + "following": "Folge Ich", + "discover": "Entdecken" + }, + "disable_cameras": { + "front": "Selfie Kamera", + "back": "Hauptkamera" + }, + "disable_permission_requests": { + "read_contacts": "Kontakte lesen", + "nearby_devices": "In der Nähe befindliche Geräte", + "notifications": "Benachrichtigungen", + "read_media_images": "Medienbilder lesen", + "read_media_video": "Medienvideos lesen", + "camera": "Kamera", + "microphone": "Mikrofon", + "location": "Standort", + "phone_calls": "Telefonanrufe" + }, + "auto_mark_as_read": { + "snap_reply": "Markiert Snaps als gelesen sobald auf sie geantwortet wird", + "conversation_read": "Markiert Konversation als gelesen sobald eine Narchicht gesendet wird" + }, + "gallery_media_send_override": { + "NOTE": "Audio-Notiz", + "SNAP": "Snap", + "always_ask": "Immer Fragen", + "ORIGINAL": "Original" + }, + "strip_media_metadata": { + "hide_caption_text": "Bildunterschriftstext ausblenden", + "hide_snap_filters": "Snap Filter ausblenden", + "hide_extras": "Extras ausblenden (z. B. Erwähnungen)", + "remove_audio_note_duration": "Dauer der Sprachnachricht entfernen", + "remove_audio_note_transcript_capability": "Sprachnachricht-Transkriptionsfunktion entfernen" + }, + "app_appearance": { + "always_light": "Immer hell", + "always_dark": "Immer dunkel" + }, + "friend_feed_menu_buttons": { + "auto_download": "⬇️ Auto-Download", + "auto_save": "💬 Auto-Nachricht-Speichern", + "unsaveable_messages": "⬇️ Nicht speicherbare Nachrichten", + "mark_snaps_as_seen": "👀 Snaps als gesehen markieren", + "mark_stories_as_seen_locally": "👀 Stories als lokal gesehen markieren", + "auto_open_snaps": "📷 Automatisches Öffnen von Snaps", + "stealth": "👻 Heimlicher Modus", + "conversation_info": "👤 Gesprächsinformationen", + "e2e_encryption": "🔒 E2E-Verschlüsselung verwenden" + }, + "path_format": { + "create_author_folder": "Erzeuge ein Verzeichnis für jeden Benutzer", + "create_source_folder": "Ordner für jeden Medienquellentyp erstellen", + "append_hash": "Fügt jedem Dateinamen einen einzigartigen Hash hinzu", + "append_source": "Füge die Medienquelle zum Dateinamen hinzu", + "append_username": "Füge den Benutzernamen zum Dateinamen hinzu", + "append_date_time": "Füge Datum und Uhrzeit zum Dateinamen hinzu" + }, + "auto_download_sources": { + "friend_snaps": "Freund-Snaps", + "friend_stories": "Freund-Stories", + "public_stories": "Öffentliche Stories", + "spotlight": "Spotlight" + }, + "logging": { + "started": "Gestartet", + "success": "Erfolgreich", + "progress": "Fortschritt", + "failure": "Fehler" + }, + "notifications": { + "chat_screenshot": "Screenshot", + "chat_screen_record": "Bildschirmaufnahme", + "snap_replay": "Snap Wiederholung", + "camera_roll_save": "In Aufnahmen gespeichert", + "chat": "Chat", + "chat_reply": "Chat Antwort", + "snap": "Snap", + "typing": "Schreiben", + "stories": "Stories", + "speaking": "Sprache", + "chat_reaction": "DM-Reaktion", + "group_chat_reaction": "Gruppenreaktion", + "initiate_audio": "Eingehender Audioanruf", + "abandon_audio": "Verpasster Audioanruf", + "initiate_video": "Eingehender Videoanruf", + "abandon_video": "Verpasster Videoanruf" + }, + "hide_ui_components": { + "hide_profile_call_buttons": "Entferne Anruf Tasten", + "hide_chat_call_buttons": "Entferne Anruf Tasten im Chat", + "hide_live_location_share_button": "Schaltfläche Live-Standortfreigabe entfernen", + "hide_stickers_button": "Entferne Stickers Taste", + "hide_voice_record_button": "Knopf für Sprachaufzeichnung entfernen", + "hide_unread_chat_hint": "Hinweis auf ungelesene Chats entfernen" + }, + "hide_story_suggestions": { + "hide_suggested_friend_stories": "Empfohlene Stories von Freunden ausblenden", + "hide_my_stories": "Meine Stories verbergen" + }, + "home_tab": { + "map": "Karte", + "chat": "Chat", + "camera": "Kamera", + "discover": "Entdecken", + "spotlight": "Spotlight" + }, + "add_friend_source_spoof": { + "added_by_username": "Nach Benutzername", + "added_by_mention": "Durch Erwähnung", + "added_by_group_chat": "Per Gruppenchat", + "added_by_qr_code": "Per QR-Code", + "added_by_community": "Per Community" + }, + "bypass_video_length_restriction": { + "single": "Einzelnes Medium", + "split": "Medien aufteilen" + }, + "old_bitmoji_selfie": { + "2d": "2D Bitmoji", + "3d": "3D Bitmoji" + }, + "disable_confirmation_dialogs": { + "erase_message": "Nachricht löschen", + "remove_friend": "Freund entfernen", + "block_friend": "Freund blockieren", + "ignore_friend": "Freund ignorieren", + "hide_friend": "Freund ausblenden", + "hide_conversation": "Konversation ausblenden", + "clear_conversation": "Konversation aus dem Freundes-Feed löschen" + }, + "edit_text_override": { + "multi_line_chat_input": "Mehrzeiliges Chat-Eingabefeld", + "bypass_text_input_limit": "Umgehen des Limits für die Texteingabe" + }, + "message_indicators": { + "encryption_indicator": "Fügt neben Nachrichten, die nur an Sie gesendet wurden, ein 🔒-Symbol hinzu", + "platform_indicator": "Fügt das Plattformsymbol hinzu, von der aus ein Medium gesendet wurde (z. B. Android, iOS, Web)", + "location_indicator": "Fügt Snaps ein 📍-Symbol hinzu, wenn sie mit aktivierter Standortfunktion gesendet wurden", + "ovf_editor_indicator": "Kennzeichnet, ob ein Snap mit dem OVF-Editor gesendet wurde", + "director_mode_indicator": "Fügt Snaps ein ✏️-Symbol hinzu, wenn sie mit dem Director-Modus gesendet wurden, der verwendet werden kann, um Galeriebilder als Snaps zu senden" + }, + "friend_mutation_notifier": { + "remove_friend": "Benachrichtige, wenn dich jemand als Freund entfernt", + "birthday_changes": "Benachrichtige, wenn jemand sein Geburtsdatum ändert", + "bitmoji_selfie_changes": "Benachrichtigen, wenn jemand sein Bitmoji-Selfie ändert", + "bitmoji_avatar_changes": "Benachrichtige, wenn jemand sein Bitmoji-Avatar ändert", + "bitmoji_background_changes": "Benachrichtige, wenn jemand den Hintergrund seines Bitmoji ändert", + "bitmoji_scene_changes": "Benachrichtige, wenn jemand seine Bitmoji-Szene ändert" + } + }, + "notices": { + "unstable": "⚠ Instabil", + "ban_risk": "⚠ Dieses Feature kann zu Bans führen", + "internal_behavior": "⚠ Dies kann das interne Verhalten von Snapchat stören" + } + }, + "content_type": { + "CHAT": "Chat", + "STATUS_CALL_MISSED_VIDEO": "Verpasster Videoanruf", + "STATUS_CALL_MISSED_AUDIO": "Verpasster Sprachanruf", + "LIVE_LOCATION_SHARE": "Live-Standort teilen", + "CREATIVE_TOOL_ITEM": "Kreativ-Werkzeug Element", + "STATUS_COUNTDOWN": "Countdown", + "MAP_REACTION": "Kartenreaktion", + "SNAP": "Snap", + "EXTERNAL_MEDIA": "Externe Medien", + "NOTE": "Sprachnachricht", + "STICKER": "Sticker", + "STATUS": "Status", + "LOCATION": "Standort", + "STATUS_SAVE_TO_CAMERA_ROLL": "In Camera Roll gespeichert", + "STATUS_CONVERSATION_CAPTURE_SCREENSHOT": "Screenshot", + "STATUS_CONVERSATION_CAPTURE_RECORD": "Bildschirmaufnahme", + "FAMILY_CENTER_INVITE": "Family Center einladen", + "FAMILY_CENTER_ACCEPT": "Family Center akzeptieren", + "FAMILY_CENTER_LEAVE": "Family Center verlassen", + "STATUS_PLUS_GIFT": "Status Plus Geschenk", + "TINY_SNAP": "Winziger Snap" + }, + "media_download_source": { + "public_story": "Öffentliche Story", + "merged": "Zusammengeführt", + "none": "Keine", + "pending": "Ausstehend", + "chat_media": "Chat-Medium", + "story": "Story", + "spotlight": "Spotlight", + "profile_picture": "Profilbild", + "story_logger": "Story Logger", + "message_logger": "Nachrichtenprotokollierung", + "voice_call": "Sprachanruf" + }, + "profile_info": { + "added_date": "Datum hinzugefügt", + "title": "Profil Info", + "first_created_username": "Erster Benutzername", + "display_name": "Anzeigename", + "mutable_username": "Änderbarer Benutzername", + "birthday": "Geburtstag: {month} {day}", + "hidden_birthday": "Geburtstag : Versteckt", + "friendship": "Freundschaft", + "add_source": "Quelle hinzufügen", + "snapchat_plus": "Snapchat Plus", + "snapchat_plus_state": { + "subscribed": "Abonniert", + "not_subscribed": "Nicht abonniert" + } + }, + "chat_export": { + "exported_to": "Exportiert zu {path}", + "exporting_chats": "Chats exportieren...", + "exporter_dialog": { + "download_medias_title": "Medien herunterladen", + "select_conversations_title": "Konversationen auswählen", + "text_field_selection": "{amount} ausgewählt", + "text_field_selection_all": "Alle", + "export_file_format_title": "Dateiformat für den Export", + "message_type_filter_title": "Nachrichten nach Typ filtern", + "amount_of_messages_title": "Anzahl der Nachrichten (für alle leer lassen)" + }, + "writing_output": "Ausgabe schreiben...", + "finished": "Fertig! Du kannst diesen Dialog jetzt schließen.", + "no_messages_found": "Keine Nachrichten gefunden!", + "dialog_negative_button": "Abbrechen", + "dialog_positive_button": "Exportieren", + "processing_chats": "{amount} Konversationen werden verarbeitet...", + "export_fail": "Konversation {conversation} konnte nicht exportiert werden", + "exporting_message": "{conversation} wird exportiert..." + }, + "download_processor": { + "attachment_type": { + "original_story": "Originale Story", + "snap": "Snap", + "sticker": "Sticker", + "gif": "GIF", + "external_media": "Externe Medien", + "note": "Notiz" + }, + "select_attachments_title": "Anhänge auswählen", + "download_started_toast": "Download gestartet", + "no_attachments_toast": "Keine Anhänge gefunden!", + "download_toast": "{path} wird heruntergeladen...", + "processing_toast": "Verarbeite {path}...", + "failed_generic_toast": "Download fehlgeschlagen", + "failed_to_create_preview_toast": "Fehler beim Erstellen der Vorschau", + "failed_processing_toast": "Fehler beim Verarbeiten {error}", + "failed_gallery_toast": "Speichern in der Galerie fehlgeschlagen {error}", + "dash_no_chapter": "Kein Abschnitt gefunden", + "unsupported_content_type_toast": "Nicht unterstützter Content-Typ!", + "failed_no_longer_available_toast": "Datei ist nicht mehr verfügbar", + "already_queued_toast": "Datei wird bereits bearbeitet!", + "already_downloaded_toast": "Datei wurde bereits heruntergeladen!", + "dash_dialog": { + "title": "Dash-Medium herunterladen", + "download_all": "Alle herunterladen", + "segment_text": "Segment {from} - {to}" + } + }, + "friend_mutation_observer": { + "bitmoji_background_changed": "{username} hat den Hintergrund seines/ ihres Bitmojis geändert", + "bitmoji_scene_changed": "{username} hat seine/ ihre Bitmoji-Szene geändert", + "notification_channel_name": "Freund-Mutationsbeobachter", + "friend_removed": "{username} hat dich als Freund:in entfernt", + "birthday_removed": "{username} hat sein/ ihr Geburtsdatum ({birthday}) entfernt", + "birthday_added": "{username} hat sein/ ihr Geburtsdatum ({birthday}) hinzugefügt", + "birthday_changed": "{username} hat sein/ ihr Geburtsdatum von {oldBirthday} auf {newBirthday} geändert", + "bitmoji_selfie_changed": "{username} hat sein/ ihr Bitmoji-Selfie geändert", + "bitmoji_avatar_changed": "{username} hat sein/ ihr Bitmoji-Avatar geändert" + }, + "material3_strings": { + "date_range_picker_start_headline": "Von", + "date_range_picker_end_headline": "Bis", + "date_range_picker_title": "Wähle einen Zeitraum", + "date_picker_switch_to_calendar_mode": "Kalender", + "date_picker_switch_to_input_mode": "Eingabe", + "date_range_picker_scroll_to_previous_month": "Vorheriger Monat", + "date_range_picker_scroll_to_next_month": "Nächster Monat", + "date_picker_today_description": "Heute", + "date_range_picker_day_in_range": "Gewählt", + "date_input_invalid_for_pattern": "Invalides Datum", + "date_input_invalid_year_range": "Invalides Jahr", + "date_input_invalid_not_allowed": "Invalides Datum", + "date_range_input_invalid_range_input": "Ungültiger Zeitraum" + }, + "friend_menu_option": { + "mark_snaps_as_seen": "Snaps als gesehen markieren", + "mark_stories_as_seen_locally": "Stories als lokal gesehen markieren", + "preview": "Vorschau", + "stealth_mode": "Inkognitomodus", + "auto_download_blacklist": "Blacklist für automatische Downloads", + "anti_auto_save": "Anti-Auto-Speichern" + }, + "opera_context_menu": { + "media_size": "Mediengröße: {size}", + "media_duration": "Mediendauer: {duration} ms", + "show_debug_info": "Debug-Informationen anzeigen", + "download": "Medien herunterladen", + "sent_at": "Gesendet am {date}", + "created_at": "Erstellt am {date}", + "expires_at": "Läuft am {date} ab" + }, + "modal_option": { + "profile_info": "Profil Info", + "close": "Schließen" + }, + "conversation_preview": { + "unknown_user": "Unbekannter Benutzer", + "streak_expiration": "läuft in {day} Tagen, {hour} Stunden, {minute} Minuten ab", + "total_messages": "Insgesamt gesendete/empfangene Nachrichten: {count}", + "title": "Vorschau" + }, + "scopes": { + "friend": "Freund:in", + "group": "Gruppe" + }, + "rules": { + "toasts": { + "enabled": "{ruleName} aktiviert", + "disabled": "{ruleName} deaktiviert" + }, + "modes": { + "blacklist": "Blacklist Modus", + "whitelist": "Whitlist Modus" + }, + "properties": { + "auto_download": { + "name": "Auto-Download", + "description": "Snaps beim Ansehen automatisch herunterladen", + "options": { + "blacklist": "Vom Auto-Download ausschließen", + "whitelist": "Auto-Download" + } + }, + "stealth": { + "name": "Heimlicher Modus", + "description": "Verhindert, dass jemand weiß, dass du seine Snaps/Chats oder Konversationen geöffnet hast", + "options": { + "blacklist": "Vom Heimlichen Modus ausschließen", + "whitelist": "Heimlicher Modus" + } + }, + "auto_save": { + "name": "Automatisches speichern", + "description": "Speichert Chat-Nachrichten beim Ansehen", + "options": { + "blacklist": "Vom automatischen Speichern ausschließen", + "whitelist": "Automatisch speichern" + } + }, + "unsaveable_messages": { + "name": "Nicht speicherbare Nachrichten", + "description": "Verhindert, dass Nachrichten im Chat von anderen Personen gespeichert werden können", + "options": { + "blacklist": "Von nicht speicherbaren Nachrichten ausschließen", + "whitelist": "Nicht speicherbare Nachrichten" + } + }, + "auto_open_snaps": { + "name": "Automatisches Öffnen von Snaps", + "description": "Öffnet Snaps automatisch beim Empfang", + "options": { + "blacklist": "Von der automatischen Snap-Öffnung ausschließen", + "whitelist": "Auto-Öffnen von Snaps" + } + }, + "hide_friend_feed": { + "name": "Vom Freundes-Feed ausblenden" + }, + "e2e_encryption": { + "name": "E2E-Verschlüsselung verwenden" + }, + "pin_conversation": { + "name": "Unterhaltung anheften" + } + } + }, + "actions": { + "clean_snapchat_cache": { + "name": "Leere den Snapchat Cache", + "description": "Leert den Snapchat Cache" + }, + "manage_friend_list": { + "name": "Freundesliste verwalten", + "description": "Im-/ex- portiere deine Freundesliste beim Backup" + }, + "export_chat_messages": { + "name": "Exportiere die Chatnachrichten", + "description": "Exportiert Chat-Nachrichten in eine JSON/HTML/TXT Datei" + }, + "export_memories": { + "name": "Exportiere die Memories", + "description": "Exportiere die Memories in eine ZIP-Datei" + }, + "bulk_messaging_action": { + "name": "Massen Nachrichten Aktion", + "description": "Führt Operationen wie das Löschen von Freunden oder amassenlöschung von Konversationen durch" + }, + "regen_mappings": { + "name": "Erneuere die Mappings", + "description": "Erneuere die Mappings manuell" + }, + "change_language": { + "name": "Sprache ändern", + "description": "Ändere die Sprache von SnapEnhance" + } + }, + "chat_action_menu": { + "preview_button": "Vorschau", + "download_button": "Download", + "delete_logged_message_button": "Gespeicherte Nachrichten löschen", + "convert_message": "Nachricht konvertieren", + "edit_message": "Nachricht bearbeiten" + }, + "gallery_media_send_override": { + "multiple_media_toast": "Du kannst nur eine Datei auf einmal senden" + }, + "mark_as_seen": { + "no_unseen_snaps_toast": "Es wurden keine ungesehenen Snaps gefunden!", + "seen_toast": "Markiert als gesehen!", + "unseen_toast": "Markiert als ungesehen!", + "already_seen_toast": "Bereits markiert als gesehen!", + "already_unseen_toast": "Schon als ungelesen markiert!" + }, + "friendship_link_type": { + "mutual": "Gegenseitig", + "outgoing": "Ausgehend", + "blocked": "Blockiert", + "deleted": "Gelöscht", + "following": "Folge Ich", + "suggested": "Empfohlen", + "incoming": "Eingehend", + "incoming_follower": "Eingehender Follower" + }, + "bulk_messaging_action": { + "choose_action_title": "Wähle eine Aktion", + "progress_status": "Verarbeite {index} von {total}", + "selection_dialog_continue_button": "Weiter", + "confirmation_dialog": { + "title": "Sind Sie sicher?", + "message": "Das betrifft alle ausgewählten Freunde. Diese Aktion kann nicht rückgängig gemacht werden." + }, + "actions": { + "remove_friends": "Freunde entfernen", + "clear_conversations": "Lösche Konversationen" + } + }, + "button": { + "ok": "OK", + "positive": "Ja", + "negative": "Nein", + "cancel": "Abbrechen", + "open": "Öffnen", + "download": "Download" + }, + "better_notifications": { + "button": { + "reply": "Antwort", + "download": "Herunterladen", + "mark_as_read": "Als gelesen markieren" + } + }, + "profile_picture_downloader": { + "button": "Profilbilder herunterladen", + "title": "Profilbild-Downloader", + "avatar_option": "Avatar", + "background_option": "Hintergrund" + }, + "call_start_confirmation": { + "dialog_title": "Anruf starten", + "dialog_message": "Sind Sie sicher, dass Sie einen Anruf starten wollen?" + }, + "half_swipe_notifier": { + "notification_channel_name": "Halb-Swipe", + "notification_content_dm": "{friend} hat gerade für {duration} Sekunden halb in deinen Chat geswiped", + "notification_content_group": "{friend} hat gerade halb in {group} für {duration} Sekunden geswiped" + }, + "streaks_reminder": { + "notification_title": "Flammen", + "notification_text": "Du wirst deine Flammen mit {friend} in {hoursLeft} Stunden verlieren" + }, + "biometric_auth": { + "unlock_button": "Entsperren", + "title": "Entsperre Snapchat", + "subtitle": "Bitte authentifizieren Sie sich um Snapchat zu entsperren" + }, + "end_to_end_encryption": { + "toolbox": { + "no_shared_key": "Sie haben noch kein gemeinsames Geheimnis mit diesem Freund. Klicken Sie unten, um ein neues zu erstellen.", + "shared_key_fingerprint": "Dein Fingerabdruck ist:\n\n{fingerprint}\n\nSieh nach, ob er mit dem Fingerabdruck deines Freundes übereinstimmt!", + "initiate_exchange_button": "Schlüsselaustausch einleiten" + }, + "confirmation_dialogs": { + "title": "Ende-zu-Ende Verschlüsselung", + "confirmation_1": "WARNUNG: Dadurch wird Ihr vorhandener Schlüssel überschrieben. Sie werden den Zugang zu allen verschlüsselten Nachrichten dieses Freundes verlieren. Sind Sie sicher, dass Sie fortfahren möchten?", + "confirmation_2": "Sind Sie WIRKLICH sicher, dass Sie weitermachen wollen? Dies ist Ihre letzte Chance, einen Rückzieher zu machen." + }, + "unencrypted_conversation_send_failure_toast": "Sie können keine verschlüsselten Inhalte zu verschlüsselten und unverschlüsselten Gesprächen gleichzeitig senden!", + "native_hooks_send_failure_toast": "Senden fehlgeschlagen! Bitte aktivieren Sie die nativen Hooks in den Einstellungen.", + "no_participants_to_encrypt_toast": "Sie haben in diesem Gespräch keine Freunde, mit denen Sie Nachrichten verschlüsseln können!", + "encryption_failed_toast": "Nachricht konnte nicht verschlüsselt werden! Prüfen Sie logcat für weitere Details.", + "accept_public_key_success_toast": "Öffentlicher Schlüssel erfolgreich akzeptiert!", + "accept_secret_key_success_toast": "Geschafft! Sie können nun verschlüsselte Nachrichten an diesen Freund senden und empfangen.", + "accept_public_key_failure_toast": "Akzeptieren des öffentlichen Schlüssels fehlgeschlagen", + "accept_secret_key_failure_toast": "Akzeptieren des geheimen Schlüssels fehlgeschlagen", + "accept_secret_button": "Geheimnis akzeptieren", + "accept_public_key_button": "Öffentlichen Schlüssel akzeptieren", + "outgoing_pk_message": "Schlüsselaustausch-Anfrage", + "outgoing_secret_message": "Schlüsselaustausch-Antwort", + "incoming_pk_message": "Sie haben gerade eine Anfrage für einen öffentlichen Schlüssel erhalten. Klicken Sie unten, um sie anzunehmen.", + "incoming_secret_message": "Ihr Freund hat gerade Ihren öffentlichen Schlüssel akzeptiert. Klicken Sie unten, um das Passwort zu akzeptieren." + }, + "auto_open_snaps": { + "title": "Auto-Öffnen von Snaps", + "notification_content": "{count} Snaps geöffnet" + } +} diff --git a/common/src/main/assets/lang/zh_CN.json b/common/src/main/assets/lang/zh_CN.json deleted file mode 100644 index 1642dfe0..00000000 --- a/common/src/main/assets/lang/zh_CN.json +++ /dev/null @@ -1,2026 +0,0 @@ -{ - "setup": { - "dialogs": { - "select_language": "选择语言", - "save_folder": "PurrfectSnap 需要存储权限才能从 Snapchat 下载和保存媒体。\\n请选择媒体应下载到的位置。", - "select_save_folder_button": "选择文件夹" - }, - "mappings": { - "dialog": "正在生成映射,这可能需要一些时间...", - "generate_failure_no_snapchat": "PurrfectSnap 无法检测到 Snapchat,请尝试重新安装 Snapchat。", - "generate_failure": "生成映射时出错,请重试。" - }, - "permissions": { - "dialog": "要继续,您需要满足以下要求:", - "notification_access": "通知访问权限", - "battery_optimization": "电池优化", - "display_over_other_apps": "在其他应用上显示", - "request_button": "请求" - } - }, - "scopes": { - "friend": "朋友", - "group": "群组" - }, - "manager": { - "routes": { - "tasks": "任务", - "features": "功能", - "manage_rule_feature": "管理规则功能", - "home": "主页", - "home_settings": "设置", - "home_logs": "日志", - "logger_history": "日志历史", - "logged_stories": "已记录的故事", - "friend_tracker": "好友追踪器", - "edit_rule": "编辑规则", - "file_imports": "文件导入", - "manage_repos": "管理存储库", - "social": "社交", - "manage_scope": "管理范围", - "messaging_preview": "预览", - "scripts": "脚本", - "better_location": "更好的位置" - }, - "sections": { - "home": { - "version_title": "v{versionName} · Eternal 分支", - "update_title": "PurrfectSnap 更新", - "update_content": "版本 {version} 可用!", - "update_button": "下载", - "debug_build_summary_title": "您正在运行 PurrfectSnap 的调试版本", - "debug_build_summary_content": "版本 {versionName} ({versionCode})", - "debug_build_summary_date": "构建日期:{date}({days} 天前)", - "quick_actions_title": "快速操作", - "download_icon_description": "下载", - "completed_icon_description": "已完成", - "failed_icon_description": "失败", - "manage_quick_actions_description": "管理快速操作", - "quick_actions_icon_description": "快速操作", - "add_quick_action_description": "添加快速操作" - }, - "home_logs": { - "no_logs_hint": "无可用日志", - "clear_logs_button": "清除日志", - "export_logs_button": "导出日志", - "saving_logs_toast": "正在保存日志,这可能需要一些时间...", - "saved_logs_success_toast": "日志保存成功", - "saved_logs_failure_toast": "保存日志失败" - }, - "home_settings": { - "actions_title": "操作", - "message_logger_title": "消息记录器", - "debug_title": "调试", - "success_toast": "完成!", - "message_logger_summary": "{messageCount} 条消息\\n{storyCount} 个故事", - "export_button": "导出", - "clear_button": "清除", - "view_logger_history_button": "查看日志历史", - "updates_title": "更新", - "auto_update_check": "自动检查更新", - "update_check_frequency": "更新检查频率", - "update_check_frequency_daily": "每日", - "update_check_frequency_weekly": "每周", - "update_check_frequency_monthly": "每月", - "theme_icon_description": "主题", - "app_theme_title": "应用主题", - "theme_mode_system": "系统", - "theme_mode_light": "浅色", - "theme_mode_dark": "深色", - "ui_settings_title": "UI 设置", - "haptic_feedback_label": "触觉反馈", - "test_mode_label": "测试模式(仅供调试)", - "disable_feature_loading_label": "禁用功能加载", - "disable_auto_mapper_label": "禁用自动映射器", - "disable_bypass_indicator_label": "禁用绕过状态指示器", - "update_notification_channel_name": "PurrfectSnap 更新", - "update_notification_channel_description": "PurrfectSnap 更新通知", - "update_notification_title": "PurrfectSnap 有可用更新", - "update_notification_text": "版本 %s 现已可用。", - "export_database_failed_toast": "导出数据库失败!{message}", - "clear_messages_failed_toast": "清除消息失败!{message}", - "clear_file_failed_toast": "清除文件失败!{message}", - "debug_file_config": "配置", - "debug_file_mappings": "映射", - "debug_file_message_logger": "消息记录器", - "debug_file_pinned_best_friend": "置顶好友", - "debug_file_native_sig_cache": "原生签名缓存" - }, - "tasks": { - "no_tasks": "无任务", - "merge_button": "合并", - "failed_to_open_file": "打开文件失败", - "merge_files_toast": "正在合并 {count} 个文件", - "remove_selected_tasks_title": "您确定要删除所选任务吗?", - "remove_all_tasks_title": "您确定要删除所有任务吗?", - "delete_files_option": "同时删除文件", - "remove_selected_tasks_confirm": "删除 {count} 个任务?", - "remove_all_tasks_confirm": "删除所有任务?", - "clear_tasks_description": "清除任务", - "file_not_found_icon_description": "未找到文件", - "image_icon_description": "图片", - "video_icon_description": "视频", - "audio_icon_description": "音频", - "file_icon_description": "文件", - "download_icon_description": "下载", - "chat_action_icon_description": "聊天操作", - "cancel_icon_description": "取消", - "success_icon_description": "成功", - "failure_icon_description": "失败", - "cancelled_icon_description": "已取消", - "task_status_failure": "失败", - "task_status_cancelled": "已取消" - }, - "features": { - "disabled": "已禁用", - "export_option": "导出", - "import_option": "导入", - "reset_option": "重置", - "config_export_success_toast": "配置导出成功", - "config_import_success_toast": "配置导入成功", - "config_import_failure_toast": "导入配置失败 {error}", - "config_export_failure_toast": "导出配置失败 {error}", - "saved_config_snackbar": "配置已保存", - "older_required": "此功能需要 Snapchat v{version} 或更早版本才能正常工作", - "newer_required": "此功能需要 Snapchat v{version} 或更新版本才能正常工作", - "search_button": "搜索" - }, - "manage_rule_feature": { - "disable_state_option": "已禁用", - "disable_state_subtext": "不会影响任何朋友/群组", - "whitelist_state_option": "除了 ... 之外没有人", - "whitelist_state_subtext": "只有 {count} 个朋友/群组会受此规则影响", - "whitelist_state_button": "选择允许的朋友/群组", - "blacklist_state_option": "除了 ... 之外的所有人", - "blacklist_state_subtext": "除了 {count} 个朋友/群组之外的所有人都会受此规则影响", - "blacklist_state_button": "选择排除的朋友/群组", - "clear_list_button": "清除朋友/群组列表", - "dialog_clear_confirmation_text": "您确定要清除列表吗?" - }, - "social": { - "friends_tab": "朋友", - "groups_tab": "群组", - "empty_hint": "(空)", - "streaks_expiration_short": "{hours}小时" - }, - "manage_scope": { - "logged_stories_button": "显示已记录的故事", - "e2ee_title": "端到端加密", - "rules_title": "规则", - "participants_text": "{count} 名参与者", - "not_found": "未找到", - "streaks_title": "连拍", - "streaks_length_text": "长度:{length}", - "streaks_expiration_text": "在 {eta} 后过期", - "streaks_expiration_text_expired": "已过期", - "reminder_button": "设置提醒", - "delete_scope_confirm_dialog_title": "您确定要删除一个 {scope} 吗?", - "notes_placeholder": "点击添加备注", - "invalid_key_size_32_bytes": "无效的密钥大小(必须为 32 字节)", - "successfully_imported_key": "成功导入密钥", - "failed_to_import_key": "导入密钥失败:{message}", - "export_base64_button": "导出 Base64", - "import_base64_button": "导入 Base64" - }, - "logged_stories": { - "story_failed_to_load": "加载失败", - "no_stories": "未找到故事", - "save_from_cache_button": "从缓存保存", - "downloaded_to_path": "已下载到 {path}", - "download_failed": "下载失败:{message}", - "posted_at": "发布于 {date}", - "created_at": "创建于 {date}", - "failed_to_open_file": "打开文件失败。请检查日志了解更多信息", - "failed_to_get_file": "获取文件失败" - }, - "messaging_preview": { - "processed_messages_toast": "已处理 {count} 条消息", - "processed_messages_text": "已处理 {count} 条消息", - "close_button_description": "关闭", - "bridge_connection_failed": "连接到桥接失败。请确保 Snapchat 在后台运行", - "bridge_init_failed": "初始化消息桥接失败。请确保 Snapchat 在后台运行", - "message_fetch_failed": "获取消息失败", - "no_message_hint": "无消息", - "save_selection_option": "保存选择", - "save_all_option": "全部保存", - "unsave_selection_option": "取消保存选择", - "unsave_all_option": "全部取消保存", - "mark_selection_as_seen_option": "将所选 Snap 标记为已读", - "mark_all_as_seen_option": "将所有 Snap 标记为已读", - "delete_selection_option": "删除选择", - "delete_all_option": "全部删除" - }, - "logger_history": { - "download_started_toast": "下载已开始!", - "download_success_toast": "已下载到 {path}", - "download_failed_toast": "下载失败 {message}", - "edited_at_text": "{message}(编辑于 {date})", - "download_button": "下载", - "select_conversation_placeholder": "选择一个对话", - "close_button_description": "关闭", - "search_button_description": "搜索", - "list_friend_format": "朋友 {name}", - "list_group_format": "群组 {name}", - "no_more_messages": "没有更多消息", - "reverse_order_checkbox": "倒序", - "chat_attachment": "附件 {index}", - "empty_message": "空聊天消息", - "message_parse_failed": "解析消息失败", - "unknown_sender": "未知发件人", - "download_attachment_failed_toast": "下载附件失败", - "log_header_format": "{username} ({type}) - {date}" - }, - "file_imports": { - "import_file_button": "导入文件", - "file_not_found": "未找到文件", - "file_import_failed": "导入文件失败:{error}", - "file_imported": "文件导入成功", - "file_delete_failed": "删除文件失败", - "no_files_hint": "您可以在此处导入文件以在 Snapchat 中使用。按下面的按钮导入文件。" - }, - "better_location": { - "spoofed_coordinates_title": "纬度 {latitude},经度 {longitude}", - "save_coordinates_dialog_title": "保存坐标", - "saved_name_dialog_hint": "已保存名称", - "latitude_dialog_hint": "纬度", - "longitude_dialog_hint": "经度", - "save_dialog_button": "保存", - "choose_location_button": "选择位置", - "teleport_to_friend_button": "传送到朋友", - "spoof_location_toggle": "伪造位置", - "suspend_location_updates": "暂停位置更新", - "saved_coordinates_title": "已保存坐标", - "no_saved_coordinates_hint": "无已保存坐标", - "delete_dialog_title": "删除已保存坐标", - "delete_dialog_message": "您确定要删除此已保存坐标吗?", - "teleport_to_friend_title": "传送到朋友", - "search_bar": "搜索", - "no_friends_map": "地图上没有朋友", - "no_friends_found": "未找到朋友", - "edit_location_button_description": "编辑位置", - "add_icon_description": "添加", - "edit_icon_description": "编辑", - "delete_icon_description": "删除" - } - }, - "dialogs": { - "add_friend": { - "title": "添加朋友或群组", - "search_hint": "搜索", - "fetch_error": "获取数据失败", - "category_groups": "群组", - "category_friends": "朋友", - "participants_text": "{count} 名参与者", - "search_icon_description": "搜索" - }, - "scripting_warning": { - "title": "警告", - "content": "PurrfectSnap 包含一个脚本工具,允许在您的设备上执行用户定义的代码。请格外小心,仅从已知、可靠的来源安装模块。未经授权或未经验证的模块可能会对您的系统构成安全风险。" - }, - "reset_config": { - "title": "重置配置", - "content": "您确定要重置配置吗?", - "success_toast": "配置重置成功" - }, - "export_config": { - "title": "导出敏感数据?", - "content": "您要导出包含敏感数据的配置吗?(例如位置坐标等)" - }, - "messaging_action": { - "title": "选择要处理的内容类型", - "select_all_button": "全选" - }, - "file_imports": { - "no_files_settings_hint": "未找到文件。请确保您已在“文件导入”部分导入所需文件", - "settings_select_file_hint": "选择一个导入的文件" - }, - "quick_actions_dialog": { - "title": "编辑快速操作", - "subtitle": "选择并调整您的快速操作的大小。" - } - }, - "friend_tracker": { - "rules_tab": "规则", - "logs_tab": "日志", - "export_dialog_title": "导出", - "bulk_export_button": "批量导出", - "individual_export_button": "单独导出", - "invalid_import_type_dialog_title": "无效的导入类型", - "invalid_import_type_dialog_text": "所选文件与此导入类型不兼容。请选择正确的导入类型。", - "import_dialog_title": "导入", - "bulk_import_button": "批量导入", - "individual_import_button": "单独导入", - "import_button_description": "导入", - "export_button_description": "导出", - "export_button": "导出", - "delete_button_description": "删除", - "delete_button": "删除", - "catalog_button_description": "目录", - "catalog_button": "目录", - "add_rule_button_description": "添加规则", - "add_rule_button": "添加规则", - "no_rules_found": "未找到规则", - "empty_rule_name": "(空)", - "events_suffix": "事件", - "scopes_suffix": "范围", - "select_rule_to_export_title": "选择要导出的规则", - "deleted_logs_toast": "已删除 {count} 个日志", - "delete_logs_dialog_title": "删除日志?", - "deleting_logs_dialog_text": "正在删除 {count} 个日志...", - "delete_logs_dialog_confirm_text": "这将根据当前筛选器和搜索查询删除日志。此操作无法撤消。", - "exported_logs_toast": "已导出日志!", - "export_logs_failed_toast": "导出日志失败。请检查 logcat 了解更多详情。", - "export_logs_dialog_title": "导出日志?", - "exporting_logs_dialog_text": "正在导出日志...", - "export_logs_dialog_confirm_text": "这将根据当前筛选器和搜索查询导出日志。", - "export_as_button": "导出为 {type}", - "filters_title": "筛选器", - "search_by_label": "搜索方式", - "newest_first_label": "最新优先", - "since_label": "自", - "until_label": "至", - "pick_a_date_button": "选择日期", - "search_placeholder": "搜索", - "filter_button_description": "筛选", - "clear_button_description": "清除", - "no_logs_found": "未找到日志", - "log_event_format": "{event} 在 {conversation} 中", - "condition_only_inside_conversation": "仅当我在对话中时", - "condition_only_outside_conversation": "仅当我不在对话中时", - "condition_only_when_app_active": "仅当 Snapchat 处于活动状态时", - "condition_only_when_app_inactive": "仅当 Snapchat 处于非活动状态时", - "condition_no_push_notification_when_app_active": "当 Snapchat 处于活动状态时无通知", - "add_event_dialog_title": "添加事件", - "event_type_label": "事件类型", - "triggers_title": "触发器", - "conditions_title": "条件", - "add_button": "添加", - "default_rule_name": "自定义规则", - "discard_changes_dialog_title": "放弃更改?", - "discard_changes_dialog_text": "您有未保存的更改。您确定要放弃它们吗?", - "discard_button": "放弃", - "cannot_save_rule_dialog_title": "无法保存规则", - "cannot_save_rule_dialog_text": "规则必须至少有一个事件才能保存。", - "duplicate_rule_name_dialog_title": "重复的规则名称", - "duplicate_rule_name_dialog_text": "已存在具有此名称的规则。请选择其他名称。", - "delete_rule_dialog_title": "删除规则", - "delete_rule_dialog_text": "您确定要删除此规则吗?", - "new_rule_title": "新规则", - "edit_rule_title": "编辑规则", - "back_button_description": "返回", - "save_button_description": "保存", - "general_section_title": "常规", - "rule_name_label": "规则名称", - "author_name_label": "作者姓名", - "scope_section_title": "范围", - "scope_all": "全部", - "scope_whitelist": "白名单", - "scope_blacklist": "黑名单", - "select_friends_groups_button": "选择朋友/群组 ({count})", - "events_section_title": "事件", - "add_event_button": "添加事件", - "no_events_text": "无事件" - }, - "friend_tracker_catalog": { - "download_failed": "下载失败:{code}", - "error": "错误:{message}", - "no_repos_added": "未添加存储库。", - "no_rules_available": "任何存储库中均无可用规则。", - "by_author": "作者:{author}", - "imported_button": "已导入", - "import_button": "导入", - "title": "好友追踪器目录", - "manage_repos_description": "管理存储库" - }, - "friend_tracker_export": { - "title": "导出规则", - "back_button_description": "返回", - "exported_toast": "好友追踪器规则已导出!", - "export_failed_toast": "导出规则失败:{message}", - "save_button": "保存", - "expand_button_description": "展开" - }, - "friend_tracker_import": { - "title": "导入规则", - "back_button_description": "返回", - "imported_toast": "好友追踪器规则已导入!", - "import_failed_toast": "导入规则失败:{message}", - "confirm_button": "确认", - "expand_button_description": "展开" - }, - "friend_tracker_repos": { - "invalid_repo_title": "无效的存储库", - "add_repo_button": "添加存储库", - "add_repo_dialog_title": "添加存储库 URL", - "repo_url_label": "存储库 URL", - "repo_added_toast": "存储库添加成功!", - "invalid_repo_error": "这似乎不是一个有效的好友追踪器存储库。", - "add_repo_failed_toast": "添加存储库失败:{message}", - "add_button": "添加", - "no_repos_added": "未添加存储库", - "remove_button": "删除", - "remove_repo_dialog_title": "删除存储库", - "remove_repo_dialog_text": "您确定要删除此存储库吗?" - }, - "navigation": { - "tracker_tab_label": "追踪器", - "customize_bottom_bar_title": "自定义底部栏", - "customize_bottom_bar_subtitle": "重新排序、添加或删除选项卡。最多五个。", - "shown_tabs_title": "显示的选项卡", - "no_tabs_selected_text": "未选择任何选项卡", - "available_tabs_title": "可用的选项卡", - "reset_button": "重置", - "done_button": "完成" - }, - "scripting": { - "script_already_installed": "脚本已安装!", - "downloading_script": "正在下载脚本...", - "script_downloaded": "脚本 {name} 已下载!", - "download_script_failed": "下载脚本失败。请检查日志了解更多详情", - "import_script_from_url_title": "从 URL 导入脚本", - "import_script_warning": "警告:导入的脚本可能对您的设备有害。仅从受信任的来源导入脚本。", - "enter_url_label": "在此处输入 URL:", - "script_imported": "脚本 {name} 已导入!", - "import_failed": "导入脚本失败。{message}。请检查日志了解更多详情", - "import_button": "导入", - "update_module_button": "更新模块", - "updating_script": "正在更新脚本 {name}...", - "module_not_found": "未找到模块", - "updated_script": "已将 {name} 更新到版本 {version}", - "update_module_failed": "更新模块失败。请检查日志了解更多详情", - "edit_module_button": "编辑模块", - "open_module_failed": "打开模块文件失败。请检查日志了解更多详情", - "clear_module_data_button": "清除模块数据", - "module_data_cleared": "模块数据已清除!", - "clear_module_data_failed": "清除模块数据失败。请检查日志了解更多详情", - "delete_module_button": "删除模块", - "deleted_script": "已删除脚本 {name}!", - "delete_module_failed": "删除模块失败。请检查日志了解更多详情", - "actions_title": "操作", - "no_description": "无描述", - "update_available": "有可用更新:{version}", - "actions_button": "操作", - "loaded_script": "已加载脚本 {name}", - "unloaded_script": "已卸载脚本 {name}", - "enable_script_failed": "启用脚本失败。请检查日志了解更多详情", - "disable_script_failed": "禁用脚本失败。请检查日志了解更多详情", - "select_scripts_folder_toast": "请选择您的脚本文件夹!", - "manage_repos_button": "管理存储库", - "import_from_url_button": "从 URL 导入", - "open_scripts_folder_button": "打开脚本文件夹", - "no_settings_for_module": "此模块没有任何设置", - "installed_scripts_tab": "已安装脚本", - "catalog_tab": "目录", - "no_scripts_folder_selected_title": "未选择脚本文件夹", - "select_folder_button": "选择文件夹", - "no_scripts_found_title": "未找到脚本。", - "use_catalog_to_add_scripts": "使用目录选项卡添加脚本!", - "ok_button_timeout": "确定 ({timeout})", - "documentation_button": "文档", - "catalog": { - "script_already_installed": "脚本已安装!", - "download_failed": "下载失败:{code}", - "script_downloaded": "脚本已下载!", - "could_not_create_file": "无法创建文件。", - "no_scripts_folder_selected": "未选择脚本文件夹。", - "error": "错误:{message}", - "no_repos_added": "未添加存储库。", - "repo_list_info": "您可以在此处找到存储库列表:", - "link_text": "链接", - "no_scripts_available": "任何存储库中均无可用脚本。", - "by_author": "作者:{author}", - "version": "版本:{version}", - "installed_button": "已安装", - "download_button": "下载" - }, - "repos": { - "invalid_repo_title": "无效的存储库", - "add_repo_button": "添加存储库", - "add_repo_dialog_title": "添加存储库 URL", - "repo_url_label": "存储库 URL", - "repo_added_toast": "存储库添加成功!", - "invalid_repo_error": "这似乎不是一个有效的脚本存储库。", - "add_repo_failed_toast": "添加存储库失败:{message}", - "add_button": "添加", - "no_repos_added": "未添加存储库", - "remove_button": "删除", - "remove_repo_dialog_title": "删除存储库", - "remove_repo_dialog_text": "您确定要删除此存储库吗?" - } - }, - "features": { - "config_import": { - "title": "确认导入", - "back_button_description": "返回", - "config_imported_toast": "配置已导入!", - "confirm_button": "确认", - "expand_button_description": "展开", - "enable_feature": "启用功能", - "enabled": "已启用", - "disabled": "已禁用" - }, - "config_export": { - "title": "导出摘要", - "back_button_description": "返回", - "save_button": "保存", - "expand_button_description": "展开", - "enable_feature": "启用功能", - "enabled": "已启用", - "disabled": "已禁用" - } - }, - "manage_repos": { - "title": "管理 {type} 存储库", - "add_repo_button": "添加存储库", - "add_repo_dialog_title": "添加存储库 URL", - "repo_url_label": "存储库 URL", - "repo_added_successfully": "存储库添加成功!", - "add_repo_failed": "添加存储库失败:{message}", - "add_button": "添加", - "no_repos_added": "未添加存储库", - "remove_button": "删除" - } - }, - "rules": { - "toasts": { - "enabled": "{ruleName} 已启用", - "disabled": "{ruleName} 已禁用" - }, - "modes": { - "blacklist": "黑名单模式", - "whitelist": "白名单模式" - }, - "properties": { - "auto_download": { - "name": "自动下载", - "description": "查看快照时自动下载", - "options": { - "blacklist": "从自动下载中排除", - "whitelist": "自动下载" - } - }, - "stealth": { - "name": "隐身模式", - "description": "防止任何人知道您已打开他们的快照/聊天和对话", - "options": { - "blacklist": "从隐身模式中排除", - "whitelist": "隐身模式" - } - }, - "auto_save": { - "name": "自动保存", - "description": "查看聊天消息时保存", - "options": { - "blacklist": "从自动保存中排除", - "whitelist": "自动保存" - } - }, - "unsaveable_messages": { - "name": "不可保存的消息", - "description": "防止其他人保存聊天中的消息", - "options": { - "blacklist": "从不可保存的消息中排除", - "whitelist": "不可保存的消息" - } - }, - "auto_open_snaps": { - "name": "自动打开快照", - "description": "收到快照时自动打开", - "options": { - "blacklist": "从自动打开快照中排除", - "whitelist": "自动打开快照" - } - }, - "hide_friend_feed": { - "name": "从好友动态中隐藏" - }, - "e2e_encryption": { - "name": "使用端到端加密" - }, - "pin_conversation": { - "name": "置顶对话" - }, - "exclude_message_logger": { - "name": "从消息记录器中排除" - } - } - }, - "actions": { - "clean_snapchat_cache": { - "name": "清理 Snapchat 缓存", - "description": "清理 Snapchat 缓存" - }, - "manage_friend_list": { - "name": "管理好友列表", - "description": "备份时导入/导出您的好友列表" - }, - "export_chat_messages": { - "name": "导出聊天消息", - "description": "将对话消息导出为 JSON/HTML/TXT 文件" - }, - "export_memories": { - "name": "导出回忆", - "description": "将回忆导出为 ZIP 文件" - }, - "bulk_messaging_action": { - "name": "批量消息操作", - "description": "执行删除好友或批量删除对话等操作" - }, - "regen_mappings": { - "name": "重新生成映射", - "description": "手动重新生成映射" - }, - "change_language": { - "name": "更改语言", - "description": "更改 PurrfectSnap 的语言" - }, - "file_imports": { - "name": "文件导入", - "description": "导入文件以在 Snapchat 中使用" - }, - "friend_tracker": { - "name": "好友追踪器", - "description": "在 Snapchat 上追踪您的好友" - }, - "logger_history": { - "name": "日志历史", - "description": "查看已记录消息的历史记录" - } - }, - "features": { - "notices": { - "unstable": "⚠ 不稳定", - "ban_risk": "⚠ 此功能可能会导致封禁", - "internal_behavior": "⚠ 这可能会破坏 Snapchat 的内部行为" - }, - "properties": { - "downloader": { - "name": "下载器", - "description": "下载 Snapchat 媒体", - "properties": { - "save_folder": { - "name": "保存文件夹", - "description": "选择所有媒体应下载到的目录" - }, - "auto_download_sources": { - "name": "自动下载来源", - "description": "选择要自动下载的来源" - }, - "prevent_self_auto_download": { - "name": "防止自我自动下载", - "description": "防止您自己的快照被自动下载" - }, - "path_format": { - "name": "路径格式", - "description": "指定文件路径格式" - }, - "allow_duplicate": { - "name": "允许重复", - "description": "允许多次下载相同的媒体" - }, - "merge_overlays": { - "name": "合并叠加层", - "description": "将快照的文本和媒体合并到一个文件中" - }, - "force_image_format": { - "name": "强制图像格式", - "description": "强制图像以指定格式保存" - }, - "force_voice_note_format": { - "name": "强制语音备忘录格式", - "description": "强制语音备忘录以指定格式保存" - }, - "auto_download_voice_notes": { - "name": "自动下载语音备忘录", - "description": "播放语音备忘录时自动下载" - }, - "download_profile_pictures": { - "name": "下载个人资料图片", - "description": "允许您从个人资料页面下载个人资料图片" - }, - "opera_download_button": { - "name": "Opera 下载按钮", - "description": "在查看快照时,在右上角添加一个下载按钮。\\n长按按钮将强制下载" - }, - "download_context_menu": { - "name": "下载上下文菜单", - "description": "允许您使用上下文菜单从对话或故事中下载/预览消息。\\n长按按钮将强制下载" - }, - "ffmpeg_options": { - "name": "FFmpeg 选项", - "description": "指定其他 FFmpeg 选项", - "properties": { - "threads": { - "name": "线程", - "description": "要使用的线程数" - }, - "preset": { - "name": "预设", - "description": "设置转换速度" - }, - "constant_rate_factor": { - "name": "恒定速率因子", - "description": "设置视频编码器的恒定速率因子\\n对于 libx264,从 0 到 51" - }, - "video_bitrate": { - "name": "视频比特率", - "description": "设置视频比特率 (kbps)" - }, - "audio_bitrate": { - "name": "音频比特率", - "description": "设置音频比特率 (kbps)" - }, - "custom_video_codec": { - "name": "自定义视频编解码器", - "description": "设置自定义视频编解码器(例如 libx264)" - }, - "custom_audio_codec": { - "name": "自定义音频编解码器", - "description": "设置自定义音频编解码器(例如 AAC)" - } - } - }, - "logging": { - "name": "日志记录", - "description": "媒体下载时显示提示" - }, - "custom_path_format": { - "name": "自定义路径格式", - "description": "为下载的媒体指定自定义路径格式\\n\\n可用变量:\\n - %username%\\n - %source%\\n - %hash%\\n - %date_time%" - } - } - }, - "user_interface": { - "name": "用户界面", - "description": "更改 Snapchat 的外观和感觉", - "properties": { - "enable_app_appearance": { - "name": "启用应用外观设置", - "description": "启用隐藏的应用外观设置\\n在较新的 Snapchat 版本上可能不需要" - }, - "friend_feed_message_preview": { - "name": "好友动态消息预览", - "description": "在好友动态中显示最后一条消息的预览", - "properties": { - "amount": { - "name": "数量", - "description": "要预览的消息数量" - } - } - }, - "snap_preview": { - "name": "快照预览", - "description": "在聊天中未读快照旁边显示一个小预览" - }, - "bootstrap_override": { - "name": "引导覆盖", - "description": "覆盖用户界面引导设置", - "properties": { - "app_appearance": { - "name": "应用外观", - "description": "设置持久的应用外观" - }, - "home_tab": { - "name": "主页选项卡", - "description": "打开 Snapchat 时覆盖启动选项卡" - } - } - }, - "force_amoled_theme": { - "name": "Amoled 深色模式", - "description": "为深色主题使用纯黑色背景" - }, - "map_friend_nametags": { - "name": "增强的好友地图名牌", - "description": "改进 Snapmap 上好友的名牌" - }, - "prevent_message_list_auto_scroll": { - "name": "防止消息列表自动滚动", - "description": "防止在发送/接收消息时消息列表滚动到底部" - }, - "streak_expiration_info": { - "name": "显示连拍过期信息", - "description": "在连拍计数器旁边显示连拍过期计时器" - }, - "hide_friend_feed_entry": { - "name": "隐藏好友动态条目", - "description": "从好友动态中隐藏特定好友\\n使用社交选项卡管理此功能" - }, - "hide_streak_restore": { - "name": "隐藏连拍恢复", - "description": "隐藏好友动态中的恢复按钮" - }, - "hide_quick_add_suggestions": { - "name": "隐藏快速添加建议", - "description": "删除快速添加好友建议" - }, - "hide_story_suggestions": { - "name": "隐藏故事建议", - "description": "从故事页面删除建议" - }, - "hide_ui_components": { - "name": "隐藏 UI 组件", - "description": "选择要隐藏的 UI 组件" - }, - "opera_media_quick_info": { - "name": "Opera 媒体快速信息", - "description": "在 opera 查看器上下文菜单中显示媒体的有用信息,例如创建日期" - }, - "old_bitmoji_selfie": { - "name": "旧版 Bitmoji 自拍", - "description": "带回旧版 Snapchat 的 Bitmoji 自拍" - }, - "disable_spotlight": { - "name": "禁用 Spotlight", - "description": "禁用 Spotlight 页面" - }, - "friend_feed_menu_buttons": { - "name": "好友动态菜单按钮", - "description": "选择要在好友动态菜单中显示的按钮" - }, - "auto_close_friend_feed_menu": { - "name": "自动关闭好友动态菜单", - "description": "按下设置按钮后自动关闭好友动态菜单" - }, - "vertical_story_viewer": { - "name": "垂直故事查看器", - "description": "为所有故事启用垂直故事查看器" - }, - "enable_friend_feed_menu_bar": { - "name": "好友动态菜单栏", - "description": "启用新的好友动态菜单栏" - }, - "message_indicators": { - "name": "消息指示器", - "description": "向消息添加特定的指示器图标\\n注意:指示器可能不是 100% 准确" - }, - "stealth_mode_indicator": { - "name": "隐身模式指示器", - "description": "在隐身模式下的对话旁边添加一个 👻 表情符号" - }, - "edit_text_override": { - "name": "编辑文本覆盖", - "description": "覆盖文本字段行为" - }, - "prevent_forced_keyboard": { - "name": "防止强制键盘", - "description": "防止 Snapchat 在您打开对话时自动弹出键盘" - }, - "settings_menu": { - "name": "设置菜单", - "description": "更改您打开 PurrfectSnap 菜单的方式", - "options": { - "default": "默认", - "legacy": "旧版" - } - } - } - }, - "messaging": { - "name": "消息", - "description": "更改您与朋友互动的方式", - "properties": { - "bypass_screenshot_detection": { - "name": "绕过屏幕截图检测", - "description": "防止 Snapchat 检测到您截屏" - }, - "anonymous_story_viewing": { - "name": "匿名故事查看", - "description": "防止任何人知道您已看过他们的故事" - }, - "prevent_story_rewatch_indicator": { - "name": "防止故事重看指示器", - "description": "防止任何人知道您已重看过他们的故事" - }, - "hide_peek_a_peek": { - "name": "隐藏 Peek-a-Peek", - "description": "防止在您半滑入聊天时发送通知" - }, - "hide_bitmoji_presence": { - "name": "隐藏 Bitmoji 状态", - "description": "防止您的 Bitmoji 在聊天中弹出" - }, - "hide_typing_notifications": { - "name": "隐藏输入通知", - "description": "防止任何人知道您正在输入消息" - }, - "unlimited_snap_view_time": { - "name": "无限快照查看时间", - "description": "取消查看快照的时间限制" - }, - "auto_mark_as_read": { - "name": "自动标记为已读", - "description": "即使启用隐身模式,也会自动将消息/快照标记为已读" - }, - "mark_snap_as_seen_button": { - "name": "将快照标记为已读按钮", - "description": "在查看快照时添加一个按钮以将其标记为已读。\\n即使启用隐身模式,此功能也有效" - }, - "skip_when_marking_as_seen": { - "name": "标记为已读时跳过", - "description": "在将快照标记为已读时自动跳到下一个快照。\\n与“将快照标记为已读按钮”结合使用" - }, - "loop_media_playback": { - "name": "循环媒体播放", - "description": "在查看快照/故事时循环播放媒体" - }, - "disable_replay_in_ff": { - "name": "在 FF 中禁用重播", - "description": "禁用从好友动态长按重播的功能" - }, - "half_swipe_notifier": { - "name": "半滑通知器", - "description": "当有人半滑入对话时通知您", - "properties": { - "min_duration": { - "name": "最短持续时间", - "description": "半滑的最短持续时间(秒)" - }, - "max_duration": { - "name": "最长持续时间", - "description": "半滑的最长持续时间(秒)" - } - } - }, - "call_start_confirmation": { - "name": "通话开始确认", - "description": "开始通话时显示确认对话框" - }, - "unlimited_conversation_pinning": { - "name": "无限对话置顶", - "description": "允许您在本地置顶无限数量的对话" - }, - "disable_snap_mode_restrictions": { - "name": "禁用快照模式限制", - "description": "允许您不受限制地查看自毁快照" - }, - "prevent_message_sending": { - "name": "阻止消息发送", - "description": "阻止发送某些类型的消息" - }, - "friend_mutation_notifier": { - "name": "好友变动通知器", - "description": "当好友个人资料中发生变化时通知您" - }, - "better_notifications": { - "name": "更好的通知", - "description": "在收到的通知中添加更多信息", - "properties": { - "group_notifications": { - "name": "群组通知", - "description": "将群组通知分组到一个" - }, - "chat_preview": { - "name": "聊天预览", - "description": "在通知中显示收到的消息预览" - }, - "media_preview": { - "name": "媒体预览", - "description": "在通知中显示所选媒体类型的预览" - }, - "media_caption": { - "name": "媒体标题", - "description": "在通知中显示媒体的附加标题" - }, - "stacked_media_messages": { - "name": "堆叠媒体消息", - "description": "当无法预览时,将多个媒体消息合并为一个文本通知。与聊天预览结合使用" - }, - "friend_add_source": { - "name": "好友添加来源", - "description": "在通知中显示好友请求的来源" - }, - "reply_button": { - "name": "回复按钮", - "description": "向通知添加回复按钮" - }, - "smart_replies": { - "name": "智能回复", - "description": "向通知添加建议回复(Android 10+)。与回复按钮结合使用" - }, - "download_button": { - "name": "下载按钮", - "description": "允许您从通知中下载媒体" - }, - "mark_as_read_button": { - "name": "标记为已读按钮", - "description": "允许您从通知中将消息标记为已读" - }, - "mark_as_read_and_save_in_chat": { - "name": "标记为已读并在聊天中保存", - "description": "向通知添加一个标记为已读并在聊天中保存的按钮" - } - } - }, - "notification_blacklist": { - "name": "通知黑名单", - "description": "选择应被阻止的通知" - }, - "message_logger": { - "name": "消息记录器", - "description": "防止消息被删除", - "properties": { - "keep_my_own_messages": { - "name": "保留我自己的消息", - "description": "防止您自己的消息被删除" - }, - "auto_purge": { - "name": "自动清除", - "description": "自动删除超过指定时间的缓存消息" - }, - "message_filter": { - "name": "消息筛选器", - "description": "选择应记录的消息(空则为所有消息)" - }, - "deleted_message_color": { - "name": "已删除消息颜色", - "description": "设置已删除消息的颜色" - } - } - }, - "auto_save_messages_in_conversations": { - "name": "自动保存在对话中的消息", - "description": "自动保存在对话中的每条消息" - }, - "gallery_media_send_override": { - "name": "图库媒体发送覆盖", - "description": "从图库发送时伪造媒体来源" - }, - "strip_media_metadata": { - "name": "剥离媒体元数据", - "description": "在作为消息发送前删除媒体的元数据" - }, - "bypass_message_retention_policy": { - "name": "绕过消息保留策略", - "description": "防止在查看消息后删除消息" - }, - "bypass_message_action_restrictions": { - "name": "绕过消息操作限制", - "description": "允许您在未打开快照的情况下对其做出反应,或保存不可保存的消息" - }, - "remove_groups_locked_status": { - "name": "删除群组锁定状态", - "description": "允许您在被踢出后查看群组信息" - }, - "double_tap_chat_action": { - "name": "双击聊天操作", - "description": "在聊天中双击消息时执行自定义操作" - }, - "double_tap_chat_action_custom_emoji": { - "name": "双击聊天操作自定义表情符号反应", - "description": "为双击聊天操作设置自定义表情符号反应" - } - } - }, - "global": { - "name": "全局", - "description": "调整全局 Snapchat 设置", - "properties": { - "better_location": { - "name": "更好的位置", - "description": "增强 Snapchat 位置", - "properties": { - "spoof_location": { - "name": "伪造位置", - "description": "将您的位置伪造为指定位置" - }, - "coordinates": { - "name": "坐标", - "description": "设置伪造位置的坐标" - }, - "walk_radius": { - "name": "步行半径", - "description": "在此半径内随机行走(英尺)" - }, - "always_update_location": { - "name": "始终更新位置", - "description": "即使未收到 GPS 数据,也强制 Snapchat 更新位置" - }, - "suspend_location_updates": { - "name": "暂停位置更新", - "description": "防止您的位置被更新" - }, - "spoof_battery_level": { - "name": "伪造电池电量", - "description": "在地图上伪造您设备的电池电量\\n值必须在 0 到 100 之间" - }, - "spoof_headphones": { - "name": "伪造耳机", - "description": "在地图上伪造正在听音乐的状态" - }, - "show_battery_level": { - "name": "显示电池电量", - "description": "在地图上显示您朋友的电池电量" - } - } - }, - "snapchat_plus": { - "name": "Snapchat Plus", - "description": "启用 Snapchat Plus 功能\\n某些服务器端功能可能无法使用" - }, - "media_upload_quality": { - "name": "媒体上传质量", - "description": "覆盖媒体上传质量", - "properties": { - "force_video_upload_source_quality": { - "name": "强制视频上传源质量", - "description": "强制 Snapchat 在上传视频时使用源质量\\n请注意,这可能不会从媒体中删除元数据" - }, - "disable_image_compression": { - "name": "禁用图像压缩", - "description": "上传媒体时禁用图像压缩" - }, - "custom_image_upload_format": { - "name": "自定义图像上传格式", - "description": "设置自定义图像上传格式\\n选择无损格式(如 PNG)以获得最佳质量" - } - } - }, - "disable_confirmation_dialogs": { - "name": "禁用确认对话框", - "description": "自动确认所选操作" - }, - "auto_updater": { - "name": "自动更新器", - "description": "自动检查新更新" - }, - "disable_metrics": { - "name": "禁用指标", - "description": "阻止向 Snapchat 发送特定的分析数据" - }, - "disable_story_sections": { - "name": "禁用故事部分", - "description": "从故事页面删除部分\\n可能需要刷新才能正常工作" - }, - "block_ads": { - "name": "屏蔽广告", - "description": "阻止显示广告" - }, - "disable_custom_tabs": { - "name": "禁用自定义选项卡", - "description": "在支持的应用程序中打开链接,而不是在 Web 浏览器中" - }, - "disable_permission_requests": { - "name": "禁用权限请求", - "description": "阻止 Snapchat 请求特定权限" - }, - "disable_memories_snap_feed": { - "name": "禁用回忆快照动态", - "description": "阻止 Snapchat 在相机中向上滑动时显示最近的回忆" - }, - "spotlight_comments_username": { - "name": "Spotlight 评论用户名", - "description": "在 Spotlight 评论中显示作者用户名" - }, - "bypass_video_length_restriction": { - "name": "绕过视频长度限制", - "description": "单个:发送单个视频\\n拆分:编辑后拆分视频" - }, - "default_video_playback_rate": { - "name": "默认视频播放速率", - "description": "设置视频播放的默认速度\\n值必须在 0.1 到 4.0 之间" - }, - "video_playback_rate_slider": { - "name": "视频播放速率滑块", - "description": "在 opera 上下文菜单中添加一个滑块以更改视频播放速率\\n注意:更改仅适用于后续视频" - }, - "disable_google_play_dialogs": { - "name": "禁用 Google Play 服务对话框", - "description": "阻止显示 Google Play 服务可用性对话框" - }, - "default_volume_controls": { - "name": "默认音量控制", - "description": "强制 Snapchat 使用系统音量控制" - }, - "disable_telecom_framework": { - "name": "禁用电信框架", - "description": "阻止 Snapchat 使用 Android 电信框架\\n这允许您在通话时听音乐" - }, - "hide_active_music": { - "name": "隐藏活动音乐", - "description": "阻止 Snapchat 知道您正在听音乐\\n这将允许您在听音乐时使用控制音量按钮拍摄快照" - }, - "disable_snap_splitting": { - "name": "禁用快照拆分", - "description": "阻止快照被拆分为多个部分\\n您发送的图片将变为视频" - } - } - }, - "rules": { - "name": "规则", - "description": "管理针对个人的自动功能" - }, - "camera": { - "name": "相机", - "description": "调整正确的设置以获得完美的快照", - "properties": { - "disable_cameras": { - "name": "禁用相机", - "description": "阻止 Snapchat 使用所选相机" - }, - "black_photos": { - "name": "黑色照片", - "description": "用黑色背景替换拍摄的照片\\n视频不受影响" - }, - "immersive_camera_preview": { - "name": "沉浸式预览", - "description": "阻止 Snapchat 裁剪相机预览\\n这可能会导致某些设备上的相机闪烁" - }, - "override_front_resolution": { - "name": "覆盖前置分辨率", - "description": "覆盖前置相机的相机分辨率" - }, - "override_back_resolution": { - "name": "覆盖后置分辨率", - "description": "覆盖后置相机的相机分辨率" - }, - "custom_resolution": { - "name": "自定义分辨率", - "description": "设置自定义相机分辨率,宽 x 高(例如 1920x1080)。\\n自定义分辨率必须受您的设备支持" - }, - "front_custom_frame_rate": { - "name": "前置自定义帧率", - "description": "覆盖前置相机帧率" - }, - "back_custom_frame_rate": { - "name": "后置自定义帧率", - "description": "覆盖后置相机帧率" - }, - "force_camera_source_encoding": { - "name": "强制相机源编码", - "description": "强制相机源编码" - }, - "startup_default_camera": { - "name": "启动默认相机", - "description": "设置打开 Snapchat 时的默认相机" - }, - "hevc_recording": { - "name": "HEVC 录制", - "description": "使用 HEVC (H.265) 编解码器进行视频录制" - } - } - }, - "streaks_reminder": { - "name": "连拍提醒", - "description": "定期通知您有关您的连拍", - "properties": { - "interval": { - "name": "间隔", - "description": "每个提醒之间的间隔(小时)" - }, - "remaining_hours": { - "name": "剩余时间", - "description": "通知显示前的剩余时间(小时)" - }, - "group_notifications": { - "name": "群组通知", - "description": "将通知分组到一个" - } - } - }, - "experimental": { - "name": "实验性", - "description": "实验性功能", - "properties": { - "native_hooks": { - "name": "原生挂钩", - "description": "挂钩到 Snapchat 原生代码的不安全功能", - "properties": { - "composer_hooks": { - "name": "Composer 挂钩", - "description": "将代码注入 Composer 跨平台 UI 框架", - "properties": { - "show_first_created_username": { - "name": "显示第一个创建的用户名", - "description": "在个人资料页面当前用户名旁边显示第一个创建的用户名" - }, - "bypass_camera_roll_limit": { - "name": "绕过相机胶卷限制", - "description": "增加您可以从相机胶卷发送的最大媒体数量" - }, - "custom_self_destruct_snap_delay": { - "name": "自定义自毁快照延迟", - "description": "发送快照时为自毁计时器提供更多选项" - }, - "composer_console": { - "name": "Composer 控制台", - "description": "允许您在 Composer 中执行 JavaScript 代码(仅限 arm64)" - }, - "composer_logs": { - "name": "Composer 日志", - "description": "将 Composer 的控制台日志重定向到 PurrfectSnap" - } - } - }, - "disable_bitmoji": { - "name": "禁用 Bitmoji", - "description": "禁用好友个人资料 Bitmoji" - }, - "custom_emoji_font": { - "name": "自定义表情符号字体", - "description": "允许您使用自定义表情符号字体。仅适用于 .ttf 字体" - }, - "custom_shared_library": { - "name": "自定义共享库", - "description": "将自定义共享库加载到 Snapchat 中。此功能仅用于测试目的" - } - } - }, - "spoof": { - "name": "伪造", - "description": "伪造有关您的各种信息", - "properties": { - "play_store_installer_package_name": { - "name": "Play 商店安装程序包名称", - "description": "将安装程序包名称覆盖为 com.android.vending" - }, - "remove_vpn_transport_flag": { - "name": "删除 VPN 传输标志", - "description": "阻止 Snapchat 检测 VPN" - }, - "remove_mock_location_flag": { - "name": "删除模拟位置标志", - "description": "阻止 Snapchat 检测模拟位置" - } - } - }, - "convert_message_locally": { - "name": "在本地转换消息", - "description": "将快照转换为聊天外部媒体。这会出现在聊天下载上下文菜单中" - }, - "media_file_picker": { - "name": "媒体文件选择器", - "description": "允许您从图库中选择任何视频/音频文件" - }, - "story_logger": { - "name": "故事记录器", - "description": "提供好友故事的历史记录" - }, - "call_recorder": { - "name": "通话录音机", - "description": "自动录制音频通话" - }, - "account_switcher": { - "name": "帐户切换器", - "description": "允许您在不注销的情况下切换帐户\\n长按 Bitmoji 个人资料旁边的搜索图标以打开菜单\\n注意:此功能是实验性的,将来可能会发生变化", - "properties": { - "auto_backup_current_account": { - "name": "自动备份当前帐户", - "description": "注销或切换帐户时自动备份当前帐户" - } - } - }, - "better_transcript": { - "name": "更好的转录", - "description": "改进语音备忘录转录", - "properties": { - "force_transcription": { - "name": "强制语音备忘录转录", - "description": "允许转录所有语音备忘录" - }, - "preferred_transcription_lang": { - "name": "首选转录语言", - "description": "语音备忘录转录的首选语言(例如 EN、ES、FR)" - }, - "notification_transcript": { - "name": "通知转录", - "description": "在通知中转录语音备忘录\\n此功能需要启用“更好的通知”中的“聊天预览”功能" - } - } - }, - "voice_note_auto_play": { - "name": "语音备忘录自动播放", - "description": "当前语音备忘录结束后自动播放下一个" - }, - "friend_notes": { - "name": "好友备注", - "description": "允许您向好友个人资料添加备注" - }, - "cof_experiments": { - "name": "COF 实验", - "description": "启用未发布/测试版 Snapchat 功能" - }, - "context_menu_fix": { - "name": "上下文菜单修复", - "description": "尝试修复好友动态菜单,因为当设备离线时无法正确显示" - }, - "app_lock": { - "name": "应用锁", - "description": "阻止在没有密码的情况下访问 Snapchat", - "properties": { - "lock_on_resume": { - "name": "恢复时锁定", - "description": "重新打开应用时锁定应用" - } - } - }, - "infinite_story_boost": { - "name": "无限故事助推", - "description": "绕过故事助推限制延迟" - }, - "meo_passcode_bypass": { - "name": "我的眼睛只有密码绕过", - "description": "绕过我的眼睛只有密码\\n这仅在之前正确输入密码时才有效" - }, - "no_friend_score_delay": { - "name": "无好友分数延迟", - "description": "查看好友分数时取消延迟" - }, - "best_friend_pinning": { - "name": "置顶好友", - "description": "允许您将好友置顶为您的头号好友。注意:只有您可以看到您置顶的好友" - }, - "e2ee": { - "name": "端到端加密", - "description": "使用共享密钥通过 AES 加密您的消息\\n请务必将您的密钥保存在安全的地方!", - "properties": { - "encrypted_message_indicator": { - "name": "加密消息指示器", - "description": "在加密消息旁边添加一个 🔒 表情符号" - }, - "force_message_encryption": { - "name": "强制消息加密", - "description": "仅当选择多个对话时,才阻止向未启用端到端加密的人发送加密消息" - } - } - }, - "add_friend_source_spoof": { - "name": "添加好友来源伪造", - "description": "伪造好友请求的来源" - }, - "hidden_snapchat_plus_features": { - "name": "隐藏的 Snapchat Plus 功能", - "description": "启用未发布/测试版 Snapchat Plus 功能\\n在较旧的 Snapchat 版本上可能无法使用" - }, - "custom_streaks_expiration_format": { - "name": "自定义连拍过期格式", - "description": "自定义连拍过期格式\\n\\n可用变量:\\n - %c:连拍计数\\n - %e:沙漏表情符号\\n - %d:天\\n - %h:小时\\n - %m:分钟\\n - %s:秒\\n - %w:剩余时间" - }, - "prevent_forced_logout": { - "name": "防止强制注销", - "description": "阻止 Snapchat 在您在另一台设备上登录时将您注销" - }, - "snapscore_changes": { - "name": "Snapscore 更改", - "description": "追踪好友 Snapscore 的变化\\n仅在较新版本的 Snapchat 中使用此功能" - } - } - }, - "scripting": { - "name": "脚本", - "description": "运行自定义脚本以扩展 PurrfectSnap", - "properties": { - "developer_mode": { - "name": "开发者模式", - "description": "在 Snapchat 的 UI 上显示调试信息" - }, - "module_folder": { - "name": "模块文件夹", - "description": "脚本所在的文件夹" - }, - "auto_reload": { - "name": "自动重新加载", - "description": "脚本更改时自动重新加载", - "options": { - "snapchat_only": "仅 Snapchat", - "all": "全部 (Snapchat + PurrfectSnap)" - } - }, - "integrated_ui": { - "name": "集成 UI", - "description": "允许脚本向 Snapchat 添加自定义 UI 组件" - }, - "disable_log_anonymization": { - "name": "禁用日志匿名化", - "description": "禁用日志的匿名化" - }, - "disable_optimization": { - "name": "禁用优化", - "description": "禁用脚本的优化。这可能会导致性能问题。" - } - } - }, - "friend_tracker": { - "name": "好友追踪器", - "description": "记录好友在 Snapchat 上的活动", - "properties": { - "record_messaging_events": { - "name": "记录消息事件", - "description": "记录消息事件,例如打开快照、阅读消息等。" - }, - "allow_running_in_background": { - "name": "允许在后台运行", - "description": "允许追踪器在后台运行。注意:这将显着消耗您的电池" - }, - "auto_purge": { - "name": "自动清除", - "description": "自动删除超过指定时间的缓存事件" - } - } - } - }, - "options": { - "app_appearance": { - "always_light": "始终浅色", - "always_dark": "始终深色" - }, - "friend_feed_menu_buttons": { - "auto_download": "⬇️ 自动下载", - "auto_save": "💬 自动保存消息", - "unsaveable_messages": "⬇️ 不可保存的消息", - "auto_open_snaps": "📷 自动打开快照", - "stealth": "👻 隐身模式", - "mark_snaps_as_seen": "👀 将快照标记为已读", - "mark_stories_as_seen_locally": "👀 在本地将故事标记为已读", - "conversation_info": "👤 对话信息", - "e2e_encryption": "🔒 使用端到端加密" - }, - "path_format": { - "create_author_folder": "为每个作者创建文件夹", - "create_source_folder": "为每种媒体源类型创建文件夹", - "append_hash": "向文件名添加唯一哈希值", - "append_source": "向文件名添加媒体源", - "append_username": "向文件名添加用户名", - "append_date_time": "向文件名添加日期和时间" - }, - "auto_download_sources": { - "friend_snaps": "好友快照", - "friend_stories": "好友故事", - "public_stories": "公共故事", - "spotlight": "Spotlight" - }, - "logging": { - "started": "已开始", - "success": "成功", - "progress": "进行中", - "failure": "失败" - }, - "notifications": { - "chat_screenshot": "屏幕截图", - "chat_screen_record": "屏幕录制", - "snap_replay": "快照重播", - "camera_roll_save": "相机胶卷保存", - "chat": "聊天", - "chat_reply": "聊天回复", - "snap": "快照", - "typing": "正在输入", - "stories": "故事", - "speaking": "正在说话", - "chat_reaction": "私信反应", - "group_chat_reaction": "群组反应", - "initiate_audio": "来电音频", - "abandon_audio": "未接音频通话", - "initiate_video": "来电视频", - "abandon_video": "未接视频通话", - "map_live_location": "地图实时位置" - }, - "gallery_media_send_override": { - "always_ask": "总是询问", - "ORIGINAL": "原始媒体", - "NOTE": "音频备忘录", - "SNAP": "快照", - "SAVEABLE_SNAP": "可保存的快照" - }, - "strip_media_metadata": { - "hide_caption_text": "隐藏标题文本", - "hide_snap_filters": "隐藏快照滤镜", - "hide_extras": "隐藏附加内容(例如提及)", - "remove_audio_note_duration": "删除音频备忘录持续时间", - "remove_audio_note_transcript_capability": "删除音频备忘录转录功能" - }, - "hide_ui_components": { - "hide_profile_call_buttons": "删除个人资料通话按钮", - "hide_chat_call_buttons": "删除聊天通话按钮", - "hide_live_location_share_button": "删除实时位置共享按钮", - "hide_stickers_button": "删除贴纸按钮", - "hide_voice_record_button": "删除语音录制按钮", - "hide_unread_chat_hint": "删除未读聊天提示", - "hide_post_to_story_buttons": "在发送快照前删除发布到故事的按钮", - "hide_billboard_prompt": "删除好友动态中的广告牌提示", - "hide_snapchat_plus_gift_reminders": "删除对话中的 Snapchat Plus 礼物提醒", - "hide_map_reactions": "删除地图反应" - }, - "hide_story_suggestions": { - "hide_suggested_friend_stories": "隐藏建议的好友故事", - "hide_my_stories": "隐藏我的故事" - }, - "home_tab": { - "map": "地图", - "chat": "聊天", - "camera": "相机", - "discover": "发现", - "spotlight": "Spotlight" - }, - "add_friend_source_spoof": { - "added_by_username": "按用户名", - "added_by_mention": "按提及", - "added_by_group_chat": "按群聊", - "added_by_qr_code": "按二维码", - "added_by_community": "按社区", - "added_by_quick_add": "按快速添加(被封禁的风险很高)" - }, - "bypass_video_length_restriction": { - "single": "单个媒体", - "split": "拆分媒体" - }, - "old_bitmoji_selfie": { - "2d": "2D Bitmoji", - "3d": "3D Bitmoji" - }, - "disable_confirmation_dialogs": { - "erase_message": "删除消息", - "remove_friend": "删除好友", - "block_friend": "拉黑好友", - "ignore_friend": "忽略好友", - "hide_friend": "隐藏好友", - "hide_conversation": "隐藏对话", - "clear_conversation": "从好友动态中清除对话" - }, - "auto_reload": { - "snapchat_only": "仅 Snapchat", - "all": "全部 (Snapchat + PurrfectSnap)" - }, - "edit_text_override": { - "multi_line_chat_input": "多行聊天输入", - "bypass_text_input_limit": "绕过文本输入限制" - }, - "auto_purge": { - "never": "从不", - "1_hour": "1 小时", - "3_hours": "3 小时", - "6_hours": "6 小时", - "12_hours": "12 小时", - "1_day": "1 天", - "3_days": "3 天", - "1_week": "1 周", - "2_weeks": "2 周", - "1_month": "1 个月", - "3_months": "3 个月", - "6_months": "6 个月" - }, - "disable_story_sections": { - "friends": "好友", - "suggested_stories": "建议的故事", - "following": "关注", - "discover": "发现" - }, - "disable_cameras": { - "front": "前置摄像头", - "back": "后置摄像头" - }, - "disable_permission_requests": { - "notifications": "通知", - "read_media_images": "读取媒体图像", - "read_media_video": "读取媒体视频", - "camera": "相机", - "microphone": "麦克风", - "location": "位置", - "read_contacts": "读取联系人", - "nearby_devices": "附近的设备", - "phone_calls": "电话" - }, - "message_indicators": { - "encryption_indicator": "在仅发送给您的消息旁边添加一个 🔒 图标", - "platform_indicator": "添加发送媒体的平台图标(例如 Android、iOS、Web)", - "location_indicator": "在启用位置发送的快照旁边添加一个 📍 图标", - "ovf_editor_indicator": "指示是否使用 OVF 编辑器发送了快照", - "director_mode_indicator": "在使用导演模式发送快照时,在快照旁边添加一个 ✏️ 图标,该模式可用于将图库图像作为快照发送" - }, - "auto_mark_as_read": { - "conversation_read": "发送消息时将对话标记为已读", - "snap_reply": "回复快照时将其标记为已读", - "save_snap_in_chat": "在隐身模式下在聊天中保存快照时将其标记为已读" - }, - "friend_mutation_notifier": { - "remove_friend": "当有人将您从好友中删除时通知您", - "birthday_changes": "当有人更改生日时通知您", - "bitmoji_selfie_changes": "当有人更改其 Bitmoji 自拍时通知您", - "bitmoji_avatar_changes": "当有人更改其 Bitmoji 头像时通知您", - "bitmoji_background_changes": "当有人更改其 Bitmoji 背景时通知您", - "bitmoji_scene_changes": "当有人更改其 Bitmoji 场景时通知您" - }, - "snapchat_plus": { - "not_subscribed": "未订阅", - "basic": "基本", - "ad_free": "无广告" - }, - "double_tap_chat_action": { - "like_message": "点赞消息", - "copy_text": "将文本复制到剪贴板", - "delete_message": "删除消息", - "mark_as_read": "标记为已读", - "custom_emoji_reaction": "自定义表情符号反应" - }, - "startup_default_camera": { - "front": "前置摄像头", - "back": "后置摄像头" - } - } - }, - "friend_menu_option": { - "mark_snaps_as_seen": "将快照标记为已读", - "mark_stories_as_seen_locally": "在本地将故事标记为已读", - "preview": "预览", - "stealth_mode": "隐身模式", - "auto_download_blacklist": "自动下载黑名单", - "anti_auto_save": "反自动保存" - }, - "content_type": { - "CHAT": "聊天", - "SNAP": "快照", - "EXTERNAL_MEDIA": "外部媒体", - "NOTE": "音频备忘录", - "STICKER": "贴纸", - "SHARE": "分享", - "STATUS": "状态", - "LOCATION": "位置", - "STATUS_SAVE_TO_CAMERA_ROLL": "已保存到相机胶卷", - "STATUS_CONVERSATION_CAPTURE_SCREENSHOT": "屏幕截图", - "STATUS_CONVERSATION_CAPTURE_RECORD": "屏幕录制", - "STATUS_CALL_MISSED_VIDEO": "未接视频通话", - "STATUS_CALL_MISSED_AUDIO": "未接音频通话", - "LIVE_LOCATION_SHARE": "实时位置共享", - "CREATIVE_TOOL_ITEM": "创意工具项", - "FAMILY_CENTER_INVITE": "家庭中心邀请", - "FAMILY_CENTER_ACCEPT": "家庭中心接受", - "FAMILY_CENTER_LEAVE": "家庭中心离开", - "STATUS_PLUS_GIFT": "状态 Plus 礼物", - "TINY_SNAP": "小快照", - "STATUS_COUNTDOWN": "倒计时", - "MAP_REACTION": "地图反应" - }, - "media_download_source": { - "none": "无", - "pending": "待定", - "chat_media": "聊天媒体", - "story": "故事", - "public_story": "公共故事", - "spotlight": "Spotlight", - "profile_picture": "个人资料图片", - "story_logger": "故事记录器", - "message_logger": "消息记录器", - "merged": "已合并", - "voice_call": "语音通话" - }, - "chat_action_menu": { - "preview_button": "预览", - "download_button": "下载", - "delete_logged_message_button": "删除已记录消息", - "show_chat_edit_history": "显示聊天编辑历史", - "convert_message": "转换消息" - }, - "opera_context_menu": { - "download": "下载媒体", - "sent_at": "发送于 {date}", - "created_at": "创建于 {date}", - "expires_at": "过期于 {date}", - "media_size": "媒体大小:{size}", - "media_duration": "媒体持续时间:{duration} 毫秒", - "show_debug_info": "显示调试信息" - }, - "modal_option": { - "profile_info": "个人资料信息", - "close": "关闭" - }, - "gallery_media_send_override": { - "multiple_media_toast": "一次只能发送一个媒体" - }, - "mark_as_seen": { - "no_unseen_snaps_toast": "未找到未读快照!", - "seen_toast": "已标记为已读!", - "unseen_toast": "已标记为未读!", - "already_seen_toast": "已标记为已读!", - "already_unseen_toast": "已标记为未读!" - }, - "conversation_preview": { - "streak_expiration": "在 {day} 天 {hour} 小时 {minute} 分钟后过期", - "total_messages": "总发送/接收消息数:{count}", - "title": "预览", - "unknown_user": "未知用户", - "no_messages": "未找到消息!" - }, - "profile_info": { - "title": "个人资料信息", - "first_created_username": "第一个创建的用户名", - "mutable_username": "可变用户名", - "display_name": "显示名称", - "added_date": "添加日期", - "birthday": "生日:{month} {day}", - "hidden_birthday": "生日:隐藏", - "friendship": "友谊", - "add_source": "添加来源", - "snapchat_plus": "Snapchat Plus", - "snapchat_plus_state": { - "subscribed": "已订阅", - "not_subscribed": "未订阅" - } - }, - "friendship_link_type": { - "mutual": "相互", - "outgoing": "传出", - "blocked": "已拉黑", - "deleted": "已删除", - "following": "关注", - "suggested": "建议", - "incoming": "传入", - "incoming_follower": "传入关注者" - }, - "bulk_messaging_action": { - "choose_action_title": "选择一个操作", - "progress_status": "正在处理 {index} / {total}", - "selection_dialog_continue_button": "继续", - "confirmation_dialog": { - "title": "您确定吗?", - "message": "这将影响所有选定的朋友。此操作无法撤消。" - }, - "actions": { - "remove_friends": "删除好友", - "clear_conversations": "清除对话" - } - }, - "chat_export": { - "exporter_dialog": { - "select_conversations_title": "选择对话", - "text_field_selection": "{amount} 已选择", - "text_field_selection_all": "全部", - "export_file_format_title": "导出文件格式", - "message_type_filter_title": "按类型筛选消息", - "amount_of_messages_title": "消息数量(留空则为全部)", - "download_medias_title": "下载媒体" - }, - "dialog_negative_button": "取消", - "dialog_positive_button": "导出", - "exported_to": "已导出到 {path}", - "exporting_chats": "正在导出聊天...", - "processing_chats": "正在处理 {amount} 个对话...", - "export_fail": "导出对话 {conversation} 失败", - "writing_output": "正在写入输出...", - "finished": "完成!您现在可以关闭此对话框。", - "no_messages_found": "未找到消息!", - "exporting_message": "正在导出 {conversation}..." - }, - "button": { - "ok": "确定", - "positive": "是", - "negative": "否", - "cancel": "取消", - "open": "打开", - "download": "下载", - "send": "发送", - "restore_original": "恢复原始", - "convert_external_media": "转换外部媒体", - "save": "保存" - }, - "tracker_events": { - "conversation_enter": "进入对话", - "conversation_exit": "退出对话", - "started_typing": "开始输入", - "stopped_typing": "停止输入", - "started_speaking": "开始说话", - "stopped_speaking": "停止说话", - "started_peeking": "开始偷看", - "stopped_peeking": "停止偷看", - "message_read": "消息已读", - "message_deleted": "消息已删除", - "message_saved": "消息已保存", - "message_unsaved": "消息未保存", - "message_edited": "消息已编辑", - "message_reaction_add": "消息反应添加", - "message_reaction_remove": "消息反应删除", - "snap_opened": "快照已打开", - "snap_replayed": "快照已重播", - "snap_replayed_twice": "快照已重播两次", - "snap_screenshot": "快照屏幕截图", - "snap_screen_record": "快照屏幕录制" - }, - "tracker_actions": { - "log": "日志", - "in_app_notification": "应用内通知", - "push_notification": "推送通知", - "custom": "自定义" - }, - "better_notifications": { - "button": { - "reply": "回复", - "download": "下载", - "mark_as_read": "标记为已读" - } - }, - "profile_picture_downloader": { - "button": "下载个人资料图片", - "title": "个人资料图片下载器", - "avatar_option": "头像", - "background_option": "背景" - }, - "call_start_confirmation": { - "dialog_title": "开始通话", - "dialog_message": "您确定要开始通话吗?" - }, - "half_swipe_notifier": { - "notification_channel_name": "半滑", - "notification_content_dm": "{friend} 刚刚半滑入您的聊天 {duration} 秒", - "notification_content_group": "{friend} 刚刚半滑入 {group} {duration} 秒" - }, - "download_processor": { - "attachment_type": { - "snap": "快照", - "sticker": "贴纸", - "gif": "GIF", - "external_media": "外部媒体", - "note": "备忘录", - "original_story": "原始故事" - }, - "select_attachments_title": "选择附件", - "download_started_toast": "下载已开始", - "unsupported_content_type_toast": "不支持的内容类型!", - "failed_no_longer_available_toast": "媒体不再可用", - "no_attachments_toast": "未找到附件!", - "already_queued_toast": "媒体已在队列中!", - "already_downloaded_toast": "媒体已下载!", - "content_saved_toast": "已保存!", - "download_toast": "正在下载 {path}...", - "processing_toast": "正在处理 {path}...", - "failed_generic_toast": "下载失败", - "failed_to_create_preview_toast": "创建预览失败", - "failed_processing_toast": "处理失败 {error}", - "failed_gallery_toast": "保存到图库失败 {error}", - "dash_no_chapter": "未找到章节", - "dash_dialog": { - "title": "下载 dash 媒体", - "download_all": "全部下载", - "segment_text": "片段 {from} - {to}" - } - }, - "streaks_reminder": { - "notification_title": "连拍", - "notification_text": "您将在 {hoursLeft} 小时后与 {friend} 失去连拍" - }, - "biometric_auth": { - "unlock_button": "解锁", - "title": "解锁 Snapchat", - "subtitle": "请进行身份验证以解锁 Snapchat" - }, - "end_to_end_encryption": { - "toolbox": { - "no_shared_key": "您还没有与此好友共享密钥。点击下方以发起一个新的密钥。", - "shared_key_fingerprint": "您的指纹是:\\n\\n{fingerprint}\\n\\n请务必检查它是否与您好友的指纹匹配!", - "initiate_exchange_button": "发起密钥交换" - }, - "confirmation_dialogs": { - "title": "端到端加密", - "confirmation_1": "警告:这将覆盖您现有的密钥。您将无法访问此好友的所有加密消息。您确定要继续吗?", - "confirmation_2": "您真的确定要继续吗?这是您最后一次退出的机会。" - }, - "unencrypted_conversation_send_failure_toast": "您不能同时向加密和未加密的对话发送加密内容!", - "native_hooks_send_failure_toast": "发送失败!请在设置中启用原生挂钩。", - "no_participants_to_encrypt_toast": "此对话中没有任何好友可以加密消息!", - "encryption_failed_toast": "加密消息失败!请检查 logcat 了解更多详情。", - "accept_public_key_success_toast": "公钥接受成功!", - "accept_secret_key_success_toast": "完成!您现在可以与此好友发送和接收加密消息。", - "accept_public_key_failure_toast": "接受公钥失败", - "accept_secret_key_failure_toast": "接受密钥失败", - "accept_secret_button": "接受密钥", - "accept_public_key_button": "接受公钥", - "outgoing_pk_message": "密钥交换请求", - "outgoing_secret_message": "密钥交换响应", - "incoming_pk_message": "您刚刚收到一个公钥请求。点击下方以接受它。", - "incoming_secret_message": "您的好友刚刚接受了您的公钥。点击下方以接受密钥。" - }, - "auto_open_snaps": { - "title": "自动打开快照", - "notification_content": "{count} 个快照已打开" - }, - "friend_mutation_observer": { - "notification_channel_name": "好友变动观察者", - "friend_removed": "{username} 已将您从好友中删除", - "birthday_removed": "{username} 已删除其生日 ({birthday})", - "birthday_added": "({username} 已添加其生日 ({birthday})", - "birthday_changed": "{username} 已将其生日从 {oldBirthday} 更改为 {newBirthday}", - "bitmoji_selfie_changed": "{username} 已更改其 Bitmoji 自拍", - "bitmoji_avatar_changed": "{username} 已更改其 Bitmoji 头像", - "bitmoji_background_changed": "{username} 已更改其 Bitmoji 背景", - "bitmoji_scene_changed": "{username} 已更改其 Bitmoji 场景" - }, - "material3_strings": { - "date_range_picker_start_headline": "从", - "date_range_picker_end_headline": "到", - "date_range_picker_title": "选择日期范围", - "date_picker_switch_to_calendar_mode": "日历", - "date_picker_switch_to_input_mode": "输入", - "date_range_picker_scroll_to_previous_month": "上个月", - "date_range_picker_scroll_to_next_month": "下个月", - "date_picker_today_description": "今天", - "date_range_picker_day_in_range": "已选择", - "date_input_invalid_for_pattern": "无效日期", - "date_input_invalid_year_range": "无效年份", - "date_input_invalid_not_allowed": "无效日期", - "date_range_input_invalid_range_input": "无效日期范围" - }, - "send_override_dialog": { - "title": "将媒体发送为 {type}", - "duration": "持续时间:{duration}", - "saveable_snap_hint": "在聊天中将快照设为可保存", - "unlimited_duration": "无限" - }, - "invalid_input_toast": "输入无效!请确保您输入了有效值。" -} \ No newline at end of file diff --git a/common/src/main/assets/lang/zh_SIMPLIFIED.json b/common/src/main/assets/lang/zh_SIMPLIFIED.json new file mode 100644 index 00000000..755cda2b --- /dev/null +++ b/common/src/main/assets/lang/zh_SIMPLIFIED.json @@ -0,0 +1,416 @@ +{ + "setup": { + "dialogs": { + "select_language": "选择语言", + "save_folder": "SnapEnhance 需要存储权限才能从 Snapchat 下载和保存媒体。\n请选择媒体下载的位置。", + "select_save_folder_button": "选择文件夹" + }, + "mappings": { + "dialog": "生成映射,这可能需要一段时间......", + "generate_failure_no_snapchat": "SnapEnhance 无法检测到 Snapchat,请尝试重新安装 Snapchat", + "generate_failure": "尝试生成映射时出错,请重试。" + }, + "permissions": { + "dialog": "要继续,您需要满足以下要求:", + "notification_access": "通知访问", + "battery_optimization": "电池优化", + "display_over_other_apps": "显示在其他应用程序之上", + "request_button": "要求" + } + }, + "friend_menu_option": { + "preview": "预览", + "stealth_mode": "隐身模式", + "auto_download_blacklist": "自动下载黑名单", + "anti_auto_save": "自动保存" + }, + "chat_action_menu": { + "preview_button": "预览", + "download_button": "下载", + "delete_logged_message_button": "删除已记录的消息" + }, + "opera_context_menu": { + "download": "下载媒体" + }, + "modal_option": { + "profile_info": "配置信息", + "close": "关闭" + }, + "conversation_preview": { + "streak_expiration": "在 {day} 天 {hour} 小时 {minute} 分钟", + "title": "预览", + "unknown_user": "未知用户" + }, + "profile_info": { + "title": "配置信息", + "display_name": "显示姓名 ", + "added_date": "添加日期", + "birthday": "生日: {month} {day}" + }, + "chat_export": { + "dialog_negative_button": "取消", + "dialog_positive_button": "导出", + "exported_to": "导出到 {path}", + "exporting_chats": "正在导出聊天...", + "processing_chats": "正在处理 {amount} 个对话...", + "export_fail": "导出对话 {conversation} 失败", + "writing_output": "正在写入输出...", + "finished": "完成了!您现在可以关闭此对话框。", + "no_messages_found": "未找到消息!", + "exporting_message": "正在导出 {conversation}..." + }, + "button": { + "ok": "确定", + "positive": "是", + "negative": "否", + "cancel": "取消", + "open": "打开" + }, + "scopes": { + "friend": "朋友", + "group": "团体" + }, + "manager": { + "routes": { + "tasks": "任务", + "features": "特征", + "home_logs": "日志", + "logger_history": "记录器历史记录", + "logged_stories": "记录的故事", + "manage_scope": "管理范围", + "social": "社会的", + "messaging_preview": "预览", + "scripts": "脚本", + "home": "家", + "home_settings": "设置", + "friend_tracker": "好友追踪器", + "edit_rule": "编辑规则", + "better_location": "更好的位置", + "manage_rule_feature": "管理规则功能", + "manage_repos": "管理资源库", + "file_imports": "导入文件", + "theming": "外观", + "edit_theme": "自定义外观" + }, + "sections": { + "home": { + "update_button": "下载", + "update_content": "版本 {version} 可用!", + "update_title": "SnapEnhance 更新", + "version_title": "v{versionName} 作者:eternal", + "debug_build_summary_title": "你正在使用SnapEnhance的一个测试版", + "debug_build_summary_content": "版本 {versionName} ({versionCode})", + "debug_build_summary_date": "版本发布时间: {date} ({days} days ago)", + "quick_actions_title": "快捷操作" + }, + "home_logs": { + "no_logs_hint": "没有可用的日志", + "export_logs_button": "导出日志", + "clear_logs_button": "清除日志", + "saving_logs_toast": "保存日志,这可能需要一段时间...", + "saved_logs_success_toast": "日志保存成功", + "saved_logs_failure_toast": "保存日志失败" + }, + "home_settings": { + "debug_title": "调试", + "message_logger_title": "消息记录器", + "success_toast": "完毕", + "clear_button": "清除", + "view_logger_history_button": "查看记录器历史记录", + "actions_title": "行动", + "message_logger_summary": "{messageCount} 条消息\n{storyCount} 个故事", + "export_button": "出口" + }, + "features": { + "config_export_success_toast": "配置导出成功", + "export_option": "出口", + "import_option": "进口", + "saved_config_snackbar": "配置已保存", + "config_import_failure_toast": "导入配置失败 {error}", + "disabled": "残疾人", + "config_import_success_toast": "配置导入成功", + "reset_option": "重置", + "config_export_failure_toast": "导出设置失败 {error}", + "older_required": "这个功能需要 Snapchat v{version} 或更老版本的 Snapchat", + "newer_required": "这个功能需要 Snapchat v{version} 或更新版本的 Snapchat", + "search_button": "搜索" + }, + "tasks": { + "no_tasks": "没有任务", + "merge_files_toast": "合并 {count} 个文件", + "remove_all_tasks_title": "您确定要删除所有任务吗?", + "remove_selected_tasks_title": "您确定要删除选定的任务吗?", + "remove_selected_tasks_confirm": "删除 {count} 个任务?", + "remove_all_tasks_confirm": "删除所有任务?", + "delete_files_option": "也删除文件", + "failed_to_open_file": "打开文件失败", + "merge_button": "合并" + }, + "social": { + "streaks_expiration_short": "{hours}小时", + "friends_tab": "朋友们", + "groups_tab": "团体", + "empty_hint": "(空的)" + }, + "manage_scope": { + "streaks_expiration_text": "过期日期在 {eta}", + "streaks_expiration_text_expired": "已到期", + "reminder_button": "设置提醒", + "participants_text": "{count} 名参与者", + "logged_stories_button": "显示记录的故事", + "e2ee_title": "端到端加密", + "rules_title": "规则", + "not_found": "未找到", + "streaks_title": "条纹", + "streaks_length_text": "长度: {length}", + "delete_scope_confirm_dialog_title": "您确定要删除 {scope}?", + "notes_placeholder": "点击以添加笔记" + }, + "messaging_preview": { + "no_message_hint": "没有消息", + "bridge_init_failed": "消息网络初始化失败 请确保Snapchat正在后台运行", + "save_selection_option": "保存选择", + "save_all_option": "保存全部", + "mark_selection_as_seen_option": "将选定的快照标记为可见", + "mark_all_as_seen_option": "将所有快照标记为已看到", + "unsave_all_option": "全部取消保存", + "bridge_connection_failed": "连接网桥失败。请确保 Snapchat 正在后台运行", + "unsave_selection_option": "取消保存选择", + "delete_selection_option": "删除选择", + "delete_all_option": "删除所有", + "message_fetch_failed": "获取消息失败" + }, + "logger_history": { + "chat_attachment": "依恋 {index}", + "empty_message": "空聊天消息", + "list_group_format": "团体 {name}", + "no_more_messages": "没有更多消息了", + "reverse_order_checkbox": "相反的顺序", + "list_friend_format": "朋友 {name}", + "unknown_sender": "未知发件人", + "download_attachment_failed_toast": "附件下载失败", + "message_parse_failed": "解析消息失败" + }, + "logged_stories": { + "story_failed_to_load": "加载失败", + "no_stories": "没有找到故事", + "save_from_cache_button": "从缓存中保存" + }, + "better_location": { + "saved_name_dialog_hint": "保存的名称", + "save_coordinates_dialog_title": "保存坐标", + "teleport_to_friend_title": "传送至朋友", + "search_bar": "搜索", + "latitude_dialog_hint": "纬度", + "delete_dialog_title": "删除已保存的坐标", + "save_dialog_button": "保存", + "saved_coordinates_title": "已保存的坐标", + "no_saved_coordinates_hint": "没有已保存的坐标", + "suspend_location_updates": "停止位置更新", + "no_friends_found": "没有找到好友", + "no_friends_map": "没有朋友在地图上", + "longitude_dialog_hint": "经度", + "choose_location_button": "选择位置", + "teleport_to_friend_button": "传送至好友", + "spoof_location_toggle": "虚拟位置", + "delete_dialog_message": "你确定要删除这个坐标吗?", + "spoofed_coordinates_title": "纬度 {latitude}, 经度 {longitude}" + }, + "file_imports": { + "file_import_failed": "文件导入失败: {error}", + "file_not_found": "文件不存在", + "import_file_button": "导入文件", + "file_imported": "文件导入成功", + "file_delete_failed": "删除文件失败", + "no_files_hint": "你可以在这里导入文件供 Snapchat 使用。按下方按钮以导入文件。" + }, + "manage_rule_feature": { + "whitelist_state_subtext": "只有 {count} 个好友或群组会被此规则影响", + "disable_state_option": "关闭", + "disable_state_subtext": "没有好友或群组会被影响", + "whitelist_state_option": "除了...", + "whitelist_state_button": "选择好友或群组", + "blacklist_state_option": "所有人除了...", + "blacklist_state_subtext": "除 {count} 个好友和群组以外的所有人都会被此规则影响", + "blacklist_state_button": "选择要排除的好友或群组", + "clear_list_button": "清空好友/群组列表", + "dialog_clear_confirmation_text": "你确定要清空此列表吗?" + }, + "theming": { + "no_themes_hint": "没有任何外观" + } + }, + "dialogs": { + "add_friend": { + "search_hint": "搜索", + "fetch_error": "获取数据失败", + "category_groups": "群组", + "category_friends": "好友", + "title": "添加好友或群组", + "participants_text": "{count} 个成员" + }, + "reset_config": { + "content": "您确定要重置配置吗?", + "success_toast": "配置重置成功", + "title": "重置配置" + }, + "messaging_action": { + "title": "选择要处理的内容类型", + "select_all_button": "全选" + }, + "scripting_warning": { + "content": "SnapEnhance 包含一个脚本工具,允许在您的设备上执行用户自定义的代码。请格外小心,仅安装来自已知且可靠来源的模块。未经授权或未经验证的模块可能会给您的系统带来安全风险。", + "title": "警告" + }, + "file_imports": { + "no_files_settings_hint": "未找到文件。请确保已在文件导入部分导入所需文件", + "settings_select_file_hint": "选择已导入的文件" + }, + "export_config": { + "content": "您想导出包含敏感数据的配置吗?(如位置坐标等)", + "title": "导出敏感信息?" + } + } + }, + "rules": { + "toasts": { + "enabled": "{ruleName} 已启用", + "disabled": "{ruleName} 已禁用" + }, + "properties": { + "auto_download": { + "name": "自动下载", + "description": "当查看时自动下载快照", + "options": { + "blacklist": "从自动下载中排除", + "whitelist": "自动下载" + } + }, + "stealth": { + "name": "隐身模式", + "description": "不让任何人知道您已打开他们的 Snap, 聊天框或对话", + "options": { + "blacklist": "从隐身模式中排除", + "whitelist": "隐身模式" + } + }, + "unsaveable_messages": { + "name": "无法保存的消息", + "description": "防止您的消息在聊天中被其他人保存", + "options": { + "whitelist": "无法保存的消息", + "blacklist": "从无法保存的消息中排除" + } + }, + "auto_open_snaps": { + "options": { + "whitelist": "自动打开地图", + "blacklist": "从自动打开地图中排除" + }, + "description": "在收到Snap消息时自动打开", + "name": "自动打开Snap消息" + }, + "auto_save": { + "name": "自动保存", + "description": "当查看时自动保存消息", + "options": { + "blacklist": "从自动保存中排除", + "whitelist": "自动保存" + } + }, + "e2e_encryption": { + "name": "使用E2E加密" + }, + "pin_conversation": { + "name": "置顶聊天" + }, + "hide_friend_feed": { + "name": "从朋友圈中隐藏" + } + }, + "modes": { + "blacklist": "黑名单模式", + "whitelist": "白名单模式" + } + }, + "actions": { + "export_chat_messages": { + "name": "导出聊天记录", + "description": "用JSON/HTML/TXT格式导出聊天记录" + }, + "export_memories": { + "description": "使用ZIP格式的压缩包导出回忆", + "name": "导出回忆" + }, + "change_language": { + "description": "切换 SnapEnhance 使用的语言", + "name": "切换语言" + }, + "regen_mappings": { + "name": "重新生成映射", + "description": "手动重新生成映射" + }, + "file_imports": { + "description": "导入给 Snapchat 使用的文件", + "name": "文件导入" + }, + "manage_friend_list": { + "name": "管理好友列表", + "description": "在备份时导入/导出你的好友列表" + }, + "security_features": { + "description": "修改安全设置", + "name": "安全功能" + }, + "clean_snapchat_cache": { + "name": "清理 Snapchat 临时文件", + "description": "清理 Snapchat 临时文件" + }, + "bulk_messaging_action": { + "description": "执行删除好友或批量删除对话等操作", + "name": "批量发送" + }, + "friend_tracker": { + "name": "好友追踪", + "description": "追踪你的 Snapchat 好友" + }, + "logger_history": { + "description": "查看信息历史记录", + "name": "历史日志" + }, + "theming": { + "name": "外观", + "description": "自定义 Snapchat" + } + }, + "features": { + "properties": { + "downloader": { + "properties": { + "path_format": { + "name": "路径格式" + }, + "prevent_self_auto_download": { + "description": "防止自动下载你自己的Snaps", + "name": "防止自动下载" + }, + "save_folder": { + "name": "保存文件夹", + "description": "选择所有媒体保存的位置" + }, + "auto_download_sources": { + "description": "选择启用自动下载的源", + "name": "自动下载源" + } + }, + "description": "下载 Snapchat 媒体文件", + "name": "下载器" + } + }, + "notices": { + "unstable": "⚠ 不稳定", + "internal_behavior": "⚠ 这个功能可能破坏 Snapchat 的正常功能", + "ban_risk": "⚠ 这个功能可能会导致账号封禁" + } + } +} diff --git a/common/src/main/kotlin/me/rhunk/snapenhance/common/Constants.kt b/common/src/main/kotlin/me/eternal/purrfectsnap/common/Constants.kt similarity index 87% rename from common/src/main/kotlin/me/rhunk/snapenhance/common/Constants.kt rename to common/src/main/kotlin/me/eternal/purrfectsnap/common/Constants.kt index 9f0afefb..50d7c19c 100644 --- a/common/src/main/kotlin/me/rhunk/snapenhance/common/Constants.kt +++ b/common/src/main/kotlin/me/eternal/purrfectsnap/common/Constants.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.common +package me.eternal.purrfectsnap.common object Constants { val SNAPCHAT_PACKAGE_NAME get() = "com.snapchat.android" diff --git a/common/src/main/kotlin/me/rhunk/snapenhance/common/ReceiversConfig.kt b/common/src/main/kotlin/me/eternal/purrfectsnap/common/ReceiversConfig.kt similarity index 61% rename from common/src/main/kotlin/me/rhunk/snapenhance/common/ReceiversConfig.kt rename to common/src/main/kotlin/me/eternal/purrfectsnap/common/ReceiversConfig.kt index db81a6c1..0a5470c2 100644 --- a/common/src/main/kotlin/me/rhunk/snapenhance/common/ReceiversConfig.kt +++ b/common/src/main/kotlin/me/eternal/purrfectsnap/common/ReceiversConfig.kt @@ -1,7 +1,7 @@ -package me.rhunk.snapenhance.common +package me.eternal.purrfectsnap.common object ReceiversConfig { - const val BRIDGE_SYNC_ACTION = "me.rhunk.snapenhance.core.bridge.SYNC" + const val BRIDGE_SYNC_ACTION = "me.eternal.purrfectsnap.core.bridge.SYNC" const val DOWNLOAD_REQUEST_EXTRA = "request" const val DOWNLOAD_METADATA_EXTRA = "metadata" const val MESSAGING_PREVIEW_EXTRA = "messaging_preview" diff --git a/common/src/main/kotlin/me/rhunk/snapenhance/common/action/EnumAction.kt b/common/src/main/kotlin/me/eternal/purrfectsnap/common/action/EnumAction.kt similarity index 95% rename from common/src/main/kotlin/me/rhunk/snapenhance/common/action/EnumAction.kt rename to common/src/main/kotlin/me/eternal/purrfectsnap/common/action/EnumAction.kt index 079ac2be..df112764 100644 --- a/common/src/main/kotlin/me/rhunk/snapenhance/common/action/EnumAction.kt +++ b/common/src/main/kotlin/me/eternal/purrfectsnap/common/action/EnumAction.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.common.action +package me.eternal.purrfectsnap.common.action import androidx.compose.material.icons.Icons import androidx.compose.material.icons.automirrored.filled.Chat diff --git a/common/src/main/kotlin/me/rhunk/snapenhance/common/bridge/BridgeFiles.kt b/common/src/main/kotlin/me/eternal/purrfectsnap/common/bridge/BridgeFiles.kt similarity index 87% rename from common/src/main/kotlin/me/rhunk/snapenhance/common/bridge/BridgeFiles.kt rename to common/src/main/kotlin/me/eternal/purrfectsnap/common/bridge/BridgeFiles.kt index cef54557..9a1f8e73 100644 --- a/common/src/main/kotlin/me/rhunk/snapenhance/common/bridge/BridgeFiles.kt +++ b/common/src/main/kotlin/me/eternal/purrfectsnap/common/bridge/BridgeFiles.kt @@ -1,14 +1,14 @@ -package me.rhunk.snapenhance.common.bridge +package me.eternal.purrfectsnap.common.bridge import android.content.Context import android.os.ParcelFileDescriptor import android.os.ParcelFileDescriptor.AutoCloseInputStream import android.os.ParcelFileDescriptor.AutoCloseOutputStream -import me.rhunk.snapenhance.bridge.storage.FileHandle -import me.rhunk.snapenhance.common.bridge.FileHandleScope.entries -import me.rhunk.snapenhance.common.bridge.InternalFileHandleType.entries -import me.rhunk.snapenhance.common.util.LazyBridgeValue -import me.rhunk.snapenhance.common.util.lazyBridge +import me.eternal.purrfectsnap.bridge.storage.FileHandle +import me.eternal.purrfectsnap.common.bridge.FileHandleScope.entries +import me.eternal.purrfectsnap.common.bridge.InternalFileHandleType.entries +import me.eternal.purrfectsnap.common.util.LazyBridgeValue +import me.eternal.purrfectsnap.common.util.lazyBridge import java.io.File diff --git a/common/src/main/kotlin/me/rhunk/snapenhance/common/bridge/InternalFileWrapper.kt b/common/src/main/kotlin/me/eternal/purrfectsnap/common/bridge/InternalFileWrapper.kt similarity index 71% rename from common/src/main/kotlin/me/rhunk/snapenhance/common/bridge/InternalFileWrapper.kt rename to common/src/main/kotlin/me/eternal/purrfectsnap/common/bridge/InternalFileWrapper.kt index 46904700..8c577c11 100644 --- a/common/src/main/kotlin/me/rhunk/snapenhance/common/bridge/InternalFileWrapper.kt +++ b/common/src/main/kotlin/me/eternal/purrfectsnap/common/bridge/InternalFileWrapper.kt @@ -1,8 +1,8 @@ -package me.rhunk.snapenhance.common.bridge +package me.eternal.purrfectsnap.common.bridge -import me.rhunk.snapenhance.bridge.storage.FileHandleManager -import me.rhunk.snapenhance.common.util.LazyBridgeValue -import me.rhunk.snapenhance.common.util.lazyBridge +import me.eternal.purrfectsnap.bridge.storage.FileHandleManager +import me.eternal.purrfectsnap.common.util.LazyBridgeValue +import me.eternal.purrfectsnap.common.util.lazyBridge open class InternalFileWrapper( fileHandleManager: LazyBridgeValue, diff --git a/common/src/main/kotlin/me/rhunk/snapenhance/common/bridge/wrapper/LocaleWrapper.kt b/common/src/main/kotlin/me/eternal/purrfectsnap/common/bridge/wrapper/LocaleWrapper.kt similarity index 86% rename from common/src/main/kotlin/me/rhunk/snapenhance/common/bridge/wrapper/LocaleWrapper.kt rename to common/src/main/kotlin/me/eternal/purrfectsnap/common/bridge/wrapper/LocaleWrapper.kt index 9d1080c2..3eede19f 100644 --- a/common/src/main/kotlin/me/rhunk/snapenhance/common/bridge/wrapper/LocaleWrapper.kt +++ b/common/src/main/kotlin/me/eternal/purrfectsnap/common/bridge/wrapper/LocaleWrapper.kt @@ -1,14 +1,14 @@ -package me.rhunk.snapenhance.common.bridge.wrapper +package me.eternal.purrfectsnap.common.bridge.wrapper import android.content.Context import android.os.ParcelFileDescriptor import android.os.ParcelFileDescriptor.AutoCloseInputStream import com.google.gson.JsonObject import com.google.gson.JsonParser -import me.rhunk.snapenhance.bridge.storage.FileHandleManager -import me.rhunk.snapenhance.common.bridge.FileHandleScope -import me.rhunk.snapenhance.common.logger.AbstractLogger -import me.rhunk.snapenhance.common.util.LazyBridgeValue +import me.eternal.purrfectsnap.bridge.storage.FileHandleManager +import me.eternal.purrfectsnap.common.bridge.FileHandleScope +import me.eternal.purrfectsnap.common.logger.AbstractLogger +import me.eternal.purrfectsnap.common.util.LazyBridgeValue import java.util.Locale @@ -35,9 +35,9 @@ class LocaleWrapper( private fun load(locale: String, pfd: ParcelFileDescriptor) { loadedLocale = if (locale.contains("_")) { val split = locale.split("_") - Locale(split[0], split[1]) + Locale.Builder().setLanguage(split[0]).setRegion(split[1]).build() } else { - Locale(locale) + Locale.Builder().setLanguage(locale).build() } val translations = AutoCloseInputStream(pfd).use { @@ -84,7 +84,7 @@ class LocaleWrapper( translationMap.clear() load() if (isSetup) return - context.sendBroadcast(android.content.Intent("me.rhunk.snapenhance.RESTART")) + context.sendBroadcast(android.content.Intent("me.eternal.purrfectsnap.RESTART")) } operator fun get(key: String) = getOrNull(key) ?: key.also { AbstractLogger.directDebug("Missing translation for $key") } @@ -106,4 +106,4 @@ class LocaleWrapper( it.translationMap.putAll(this.translationMap) } } -} \ No newline at end of file +} diff --git a/common/src/main/kotlin/me/rhunk/snapenhance/common/bridge/wrapper/LoggerWrapper.kt b/common/src/main/kotlin/me/eternal/purrfectsnap/common/bridge/wrapper/LoggerWrapper.kt similarity index 96% rename from common/src/main/kotlin/me/rhunk/snapenhance/common/bridge/wrapper/LoggerWrapper.kt rename to common/src/main/kotlin/me/eternal/purrfectsnap/common/bridge/wrapper/LoggerWrapper.kt index d9b82455..d72f3dac 100644 --- a/common/src/main/kotlin/me/rhunk/snapenhance/common/bridge/wrapper/LoggerWrapper.kt +++ b/common/src/main/kotlin/me/eternal/purrfectsnap/common/bridge/wrapper/LoggerWrapper.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.common.bridge.wrapper +package me.eternal.purrfectsnap.common.bridge.wrapper import android.content.ContentValues import android.content.Context @@ -7,18 +7,18 @@ import android.net.Uri import com.google.gson.GsonBuilder import com.google.gson.JsonObject import kotlinx.coroutines.* -import me.rhunk.snapenhance.bridge.logger.BridgeLoggedMessage -import me.rhunk.snapenhance.bridge.logger.LoggedChatEdit -import me.rhunk.snapenhance.bridge.logger.LoggerInterface -import me.rhunk.snapenhance.common.bridge.InternalFileHandleType -import me.rhunk.snapenhance.common.data.StoryData -import me.rhunk.snapenhance.common.logger.AbstractLogger -import me.rhunk.snapenhance.common.util.SQLiteDatabaseHelper -import me.rhunk.snapenhance.common.util.ktx.getBlobOrNull -import me.rhunk.snapenhance.common.util.ktx.getIntOrNull -import me.rhunk.snapenhance.common.util.ktx.getLongOrNull -import me.rhunk.snapenhance.common.util.ktx.getStringOrNull -import me.rhunk.snapenhance.common.util.protobuf.ProtoReader +import me.eternal.purrfectsnap.bridge.logger.BridgeLoggedMessage +import me.eternal.purrfectsnap.bridge.logger.LoggedChatEdit +import me.eternal.purrfectsnap.bridge.logger.LoggerInterface +import me.eternal.purrfectsnap.common.bridge.InternalFileHandleType +import me.eternal.purrfectsnap.common.data.StoryData +import me.eternal.purrfectsnap.common.logger.AbstractLogger +import me.eternal.purrfectsnap.common.util.SQLiteDatabaseHelper +import me.eternal.purrfectsnap.common.util.ktx.getBlobOrNull +import me.eternal.purrfectsnap.common.util.ktx.getIntOrNull +import me.eternal.purrfectsnap.common.util.ktx.getLongOrNull +import me.eternal.purrfectsnap.common.util.ktx.getStringOrNull +import me.eternal.purrfectsnap.common.util.protobuf.ProtoReader import java.io.File import java.util.UUID @@ -499,4 +499,4 @@ class LoggerWrapper( } return messages } -} \ No newline at end of file +} diff --git a/common/src/main/kotlin/me/rhunk/snapenhance/common/bridge/wrapper/MappingsWrapper.kt b/common/src/main/kotlin/me/eternal/purrfectsnap/common/bridge/wrapper/MappingsWrapper.kt similarity index 82% rename from common/src/main/kotlin/me/rhunk/snapenhance/common/bridge/wrapper/MappingsWrapper.kt rename to common/src/main/kotlin/me/eternal/purrfectsnap/common/bridge/wrapper/MappingsWrapper.kt index 427024a0..28353821 100644 --- a/common/src/main/kotlin/me/rhunk/snapenhance/common/bridge/wrapper/MappingsWrapper.kt +++ b/common/src/main/kotlin/me/eternal/purrfectsnap/common/bridge/wrapper/MappingsWrapper.kt @@ -1,18 +1,18 @@ -package me.rhunk.snapenhance.common.bridge.wrapper +package me.eternal.purrfectsnap.common.bridge.wrapper import android.content.Context import com.google.gson.JsonParser import kotlinx.coroutines.runBlocking -import me.rhunk.snapenhance.bridge.storage.FileHandleManager -import me.rhunk.snapenhance.common.BuildConfig -import me.rhunk.snapenhance.common.Constants -import me.rhunk.snapenhance.common.bridge.FileHandleScope -import me.rhunk.snapenhance.common.bridge.InternalFileHandleType -import me.rhunk.snapenhance.common.bridge.InternalFileWrapper -import me.rhunk.snapenhance.common.logger.AbstractLogger -import me.rhunk.snapenhance.common.util.LazyBridgeValue -import me.rhunk.snapenhance.mapper.AbstractClassMapper -import me.rhunk.snapenhance.mapper.ClassMapper +import me.eternal.purrfectsnap.bridge.storage.FileHandleManager +import me.eternal.purrfectsnap.common.BuildConfig +import me.eternal.purrfectsnap.common.Constants +import me.eternal.purrfectsnap.common.bridge.FileHandleScope +import me.eternal.purrfectsnap.common.bridge.InternalFileHandleType +import me.eternal.purrfectsnap.common.bridge.InternalFileWrapper +import me.eternal.purrfectsnap.common.logger.AbstractLogger +import me.eternal.purrfectsnap.common.util.LazyBridgeValue +import me.eternal.purrfectsnap.mapper.AbstractClassMapper +import me.eternal.purrfectsnap.mapper.ClassMapper import kotlin.reflect.KClass class MappingsWrapper( diff --git a/common/src/main/kotlin/me/rhunk/snapenhance/common/config/ConfigConstants.kt b/common/src/main/kotlin/me/eternal/purrfectsnap/common/config/ConfigConstants.kt similarity index 89% rename from common/src/main/kotlin/me/rhunk/snapenhance/common/config/ConfigConstants.kt rename to common/src/main/kotlin/me/eternal/purrfectsnap/common/config/ConfigConstants.kt index fa9d0aa4..3f26ef72 100644 --- a/common/src/main/kotlin/me/rhunk/snapenhance/common/config/ConfigConstants.kt +++ b/common/src/main/kotlin/me/eternal/purrfectsnap/common/config/ConfigConstants.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.common.config +package me.eternal.purrfectsnap.common.config /* Due to recent resource obfuscation, some UI features will no longer work because it depends on non obfuscated resources diff --git a/common/src/main/kotlin/me/rhunk/snapenhance/common/config/ConfigContainer.kt b/common/src/main/kotlin/me/eternal/purrfectsnap/common/config/ConfigContainer.kt similarity index 95% rename from common/src/main/kotlin/me/rhunk/snapenhance/common/config/ConfigContainer.kt rename to common/src/main/kotlin/me/eternal/purrfectsnap/common/config/ConfigContainer.kt index ce446b96..f2e58cd2 100644 --- a/common/src/main/kotlin/me/rhunk/snapenhance/common/config/ConfigContainer.kt +++ b/common/src/main/kotlin/me/eternal/purrfectsnap/common/config/ConfigContainer.kt @@ -1,8 +1,8 @@ -package me.rhunk.snapenhance.common.config +package me.eternal.purrfectsnap.common.config import android.content.Context import com.google.gson.JsonObject -import me.rhunk.snapenhance.common.logger.AbstractLogger +import me.eternal.purrfectsnap.common.logger.AbstractLogger import kotlin.reflect.KProperty typealias ConfigParamsBuilder = ConfigParams.() -> Unit @@ -78,7 +78,7 @@ open class ConfigContainer( val json = JsonObject() properties.forEach { (propertyKey, propertyValue) -> if (!exportSensitiveData && propertyKey.params.flags.contains(ConfigFlag.SENSITIVE)) return@forEach - val serializedValue = propertyValue.getNullable()?.let { propertyKey.dataType.serializeAny(it, exportSensitiveData) } + val serializedValue = propertyValue.getRaw()?.let { propertyKey.dataType.serializeAny(it, exportSensitiveData) } json.add(propertyKey.name, serializedValue) } return json @@ -109,4 +109,4 @@ open class ConfigContainer( operator fun getValue(t: Any?, property: KProperty<*>) = this.globalState operator fun setValue(t: Any?, property: KProperty<*>, t1: Boolean?) { this.globalState = t1 } -} \ No newline at end of file +} diff --git a/common/src/main/kotlin/me/rhunk/snapenhance/common/config/ConfigObjects.kt b/common/src/main/kotlin/me/eternal/purrfectsnap/common/config/ConfigObjects.kt similarity index 97% rename from common/src/main/kotlin/me/rhunk/snapenhance/common/config/ConfigObjects.kt rename to common/src/main/kotlin/me/eternal/purrfectsnap/common/config/ConfigObjects.kt index 6feae66e..5cf9a2a1 100644 --- a/common/src/main/kotlin/me/rhunk/snapenhance/common/config/ConfigObjects.kt +++ b/common/src/main/kotlin/me/eternal/purrfectsnap/common/config/ConfigObjects.kt @@ -1,7 +1,7 @@ -package me.rhunk.snapenhance.common.config +package me.eternal.purrfectsnap.common.config import androidx.compose.ui.graphics.vector.ImageVector -import me.rhunk.snapenhance.common.bridge.wrapper.LocaleWrapper +import me.eternal.purrfectsnap.common.bridge.wrapper.LocaleWrapper import kotlin.reflect.KProperty data class PropertyPair( @@ -113,6 +113,7 @@ class PropertyValue( fun getNullable() = value?.takeIf { it != "null" } fun isEmpty() = value == null || value == "null" || value.toString().isEmpty() fun get() = getNullable() ?: throw IllegalStateException("Property is not set") + fun getRaw() = value fun set(value: T?) { setAny(value) } @Suppress("UNCHECKED_CAST") fun setAny(value: Any?) { this.value = value as T? } diff --git a/common/src/main/kotlin/me/rhunk/snapenhance/common/config/DataProcessors.kt b/common/src/main/kotlin/me/eternal/purrfectsnap/common/config/DataProcessors.kt similarity index 98% rename from common/src/main/kotlin/me/rhunk/snapenhance/common/config/DataProcessors.kt rename to common/src/main/kotlin/me/eternal/purrfectsnap/common/config/DataProcessors.kt index 9b6f747e..9aa87e67 100644 --- a/common/src/main/kotlin/me/rhunk/snapenhance/common/config/DataProcessors.kt +++ b/common/src/main/kotlin/me/eternal/purrfectsnap/common/config/DataProcessors.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.common.config +package me.eternal.purrfectsnap.common.config import com.google.gson.JsonArray import com.google.gson.JsonElement diff --git a/common/src/main/kotlin/me/rhunk/snapenhance/common/config/ModConfig.kt b/common/src/main/kotlin/me/eternal/purrfectsnap/common/config/ModConfig.kt similarity index 90% rename from common/src/main/kotlin/me/rhunk/snapenhance/common/config/ModConfig.kt rename to common/src/main/kotlin/me/eternal/purrfectsnap/common/config/ModConfig.kt index 0f7c3951..3debd893 100644 --- a/common/src/main/kotlin/me/rhunk/snapenhance/common/config/ModConfig.kt +++ b/common/src/main/kotlin/me/eternal/purrfectsnap/common/config/ModConfig.kt @@ -1,17 +1,17 @@ -package me.rhunk.snapenhance.common.config +package me.eternal.purrfectsnap.common.config import android.content.Context import com.google.gson.Gson import com.google.gson.GsonBuilder import com.google.gson.JsonObject -import me.rhunk.snapenhance.bridge.ConfigStateListener -import me.rhunk.snapenhance.bridge.storage.FileHandleManager -import me.rhunk.snapenhance.common.bridge.InternalFileHandleType -import me.rhunk.snapenhance.common.bridge.InternalFileWrapper -import me.rhunk.snapenhance.common.bridge.wrapper.LocaleWrapper -import me.rhunk.snapenhance.common.config.impl.RootConfig -import me.rhunk.snapenhance.common.logger.AbstractLogger -import me.rhunk.snapenhance.common.util.LazyBridgeValue +import me.eternal.purrfectsnap.bridge.ConfigStateListener +import me.eternal.purrfectsnap.bridge.storage.FileHandleManager +import me.eternal.purrfectsnap.common.bridge.InternalFileHandleType +import me.eternal.purrfectsnap.common.bridge.InternalFileWrapper +import me.eternal.purrfectsnap.common.bridge.wrapper.LocaleWrapper +import me.eternal.purrfectsnap.common.config.impl.RootConfig +import me.eternal.purrfectsnap.common.logger.AbstractLogger +import me.eternal.purrfectsnap.common.util.LazyBridgeValue import kotlin.properties.Delegates class ModConfig( diff --git a/common/src/main/kotlin/me/rhunk/snapenhance/common/config/impl/Camera.kt b/common/src/main/kotlin/me/eternal/purrfectsnap/common/config/impl/Camera.kt similarity index 94% rename from common/src/main/kotlin/me/rhunk/snapenhance/common/config/impl/Camera.kt rename to common/src/main/kotlin/me/eternal/purrfectsnap/common/config/impl/Camera.kt index 52d920e7..40f44691 100644 --- a/common/src/main/kotlin/me/rhunk/snapenhance/common/config/impl/Camera.kt +++ b/common/src/main/kotlin/me/eternal/purrfectsnap/common/config/impl/Camera.kt @@ -1,11 +1,11 @@ -package me.rhunk.snapenhance.common.config.impl +package me.eternal.purrfectsnap.common.config.impl import android.content.Context import android.hardware.camera2.CameraCharacteristics import android.hardware.camera2.CameraManager -import me.rhunk.snapenhance.common.Constants -import me.rhunk.snapenhance.common.config.* -import me.rhunk.snapenhance.common.logger.AbstractLogger +import me.eternal.purrfectsnap.common.Constants +import me.eternal.purrfectsnap.common.config.* +import me.eternal.purrfectsnap.common.logger.AbstractLogger class Camera : ConfigContainer() { companion object { diff --git a/common/src/main/kotlin/me/rhunk/snapenhance/common/config/impl/DownloaderConfig.kt b/common/src/main/kotlin/me/eternal/purrfectsnap/common/config/impl/DownloaderConfig.kt similarity index 91% rename from common/src/main/kotlin/me/rhunk/snapenhance/common/config/impl/DownloaderConfig.kt rename to common/src/main/kotlin/me/eternal/purrfectsnap/common/config/impl/DownloaderConfig.kt index 15b8e0c9..e84f40ac 100644 --- a/common/src/main/kotlin/me/rhunk/snapenhance/common/config/impl/DownloaderConfig.kt +++ b/common/src/main/kotlin/me/eternal/purrfectsnap/common/config/impl/DownloaderConfig.kt @@ -1,8 +1,8 @@ -package me.rhunk.snapenhance.common.config.impl +package me.eternal.purrfectsnap.common.config.impl -import me.rhunk.snapenhance.common.config.ConfigContainer -import me.rhunk.snapenhance.common.config.ConfigFlag -import me.rhunk.snapenhance.common.config.FeatureNotice +import me.eternal.purrfectsnap.common.config.ConfigContainer +import me.eternal.purrfectsnap.common.config.ConfigFlag +import me.eternal.purrfectsnap.common.config.FeatureNotice class DownloaderConfig : ConfigContainer() { inner class FFMpegOptions : ConfigContainer() { diff --git a/common/src/main/kotlin/me/rhunk/snapenhance/common/config/impl/Experimental.kt b/common/src/main/kotlin/me/eternal/purrfectsnap/common/config/impl/Experimental.kt similarity index 94% rename from common/src/main/kotlin/me/rhunk/snapenhance/common/config/impl/Experimental.kt rename to common/src/main/kotlin/me/eternal/purrfectsnap/common/config/impl/Experimental.kt index 16aba133..69f2d25f 100644 --- a/common/src/main/kotlin/me/rhunk/snapenhance/common/config/impl/Experimental.kt +++ b/common/src/main/kotlin/me/eternal/purrfectsnap/common/config/impl/Experimental.kt @@ -1,11 +1,12 @@ -package me.rhunk.snapenhance.common.config.impl +package me.eternal.purrfectsnap.common.config.impl import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Fingerprint import androidx.compose.material.icons.filled.Memory -import me.rhunk.snapenhance.common.config.ConfigContainer -import me.rhunk.snapenhance.common.config.ConfigFlag -import me.rhunk.snapenhance.common.config.FeatureNotice +import androidx.compose.material.icons.filled.Security +import me.eternal.purrfectsnap.common.config.ConfigContainer +import me.eternal.purrfectsnap.common.config.ConfigFlag +import me.eternal.purrfectsnap.common.config.FeatureNotice class Experimental : ConfigContainer() { companion object { @@ -36,7 +37,6 @@ class Experimental : ConfigContainer() { val disableBitmoji = boolean("disable_bitmoji") val customEmojiFont = string("custom_emoji_font") { requireRestart() - addNotices(FeatureNotice.UNSTABLE) addFlags(ConfigFlag.USER_IMPORT) filenameFilter = { it.endsWith(".ttf") } } @@ -91,7 +91,8 @@ class Experimental : ConfigContainer() { "added_by_qr_code", "added_by_community", "added_by_quick_add", + "added_by_spotlight", ) { addNotices(FeatureNotice.BAN_RISK) } val preventForcedLogout = boolean("prevent_forced_logout") { requireRestart(); addNotices(FeatureNotice.BAN_RISK, FeatureNotice.INTERNAL_BEHAVIOR); } val snapScoreChanges = boolean("snapscore_changes") { requireRestart() } -} \ No newline at end of file +} diff --git a/common/src/main/kotlin/me/rhunk/snapenhance/common/config/impl/FriendTrackerConfig.kt b/common/src/main/kotlin/me/eternal/purrfectsnap/common/config/impl/FriendTrackerConfig.kt similarity index 59% rename from common/src/main/kotlin/me/rhunk/snapenhance/common/config/impl/FriendTrackerConfig.kt rename to common/src/main/kotlin/me/eternal/purrfectsnap/common/config/impl/FriendTrackerConfig.kt index b7af216c..d99bb979 100644 --- a/common/src/main/kotlin/me/rhunk/snapenhance/common/config/impl/FriendTrackerConfig.kt +++ b/common/src/main/kotlin/me/eternal/purrfectsnap/common/config/impl/FriendTrackerConfig.kt @@ -1,9 +1,9 @@ -package me.rhunk.snapenhance.common.config.impl +package me.eternal.purrfectsnap.common.config.impl -import me.rhunk.snapenhance.common.config.ConfigContainer -import me.rhunk.snapenhance.common.util.PURGE_DISABLED_KEY -import me.rhunk.snapenhance.common.util.PURGE_VALUES -import me.rhunk.snapenhance.common.util.PURGE_TRANSLATION_KEY +import me.eternal.purrfectsnap.common.config.ConfigContainer +import me.eternal.purrfectsnap.common.util.PURGE_DISABLED_KEY +import me.eternal.purrfectsnap.common.util.PURGE_VALUES +import me.eternal.purrfectsnap.common.util.PURGE_TRANSLATION_KEY class FriendTrackerConfig: ConfigContainer(hasGlobalState = true) { val recordMessagingEvents = boolean("record_messaging_events", false) diff --git a/common/src/main/kotlin/me/rhunk/snapenhance/common/config/impl/Global.kt b/common/src/main/kotlin/me/eternal/purrfectsnap/common/config/impl/Global.kt similarity index 93% rename from common/src/main/kotlin/me/rhunk/snapenhance/common/config/impl/Global.kt rename to common/src/main/kotlin/me/eternal/purrfectsnap/common/config/impl/Global.kt index 862cf68d..3eba6223 100644 --- a/common/src/main/kotlin/me/rhunk/snapenhance/common/config/impl/Global.kt +++ b/common/src/main/kotlin/me/eternal/purrfectsnap/common/config/impl/Global.kt @@ -1,8 +1,8 @@ -package me.rhunk.snapenhance.common.config.impl +package me.eternal.purrfectsnap.common.config.impl -import me.rhunk.snapenhance.common.config.ConfigContainer -import me.rhunk.snapenhance.common.config.ConfigFlag -import me.rhunk.snapenhance.common.config.FeatureNotice +import me.eternal.purrfectsnap.common.config.ConfigContainer +import me.eternal.purrfectsnap.common.config.ConfigFlag +import me.eternal.purrfectsnap.common.config.FeatureNotice class Global : ConfigContainer() { companion object { @@ -47,6 +47,7 @@ class Global : ConfigContainer() { val disablePermissionRequests = multiple("disable_permission_requests", *permissionMap.values.toTypedArray()) { requireRestart(); addNotices(FeatureNotice.UNSTABLE) } val disableMemoriesSnapFeed = boolean("disable_memories_snap_feed") val spotlightCommentsUsername = boolean("spotlight_comments_username") { requireRestart() } + val spotlightCommentsUsernameIcon = string("spotlight_comments_username_icon", "[👤]") { requireRestart() } val bypassVideoLengthRestriction = unique("bypass_video_length_restriction", "split", "single") { addNotices( FeatureNotice.BAN_RISK); requireRestart() } val defaultVideoPlaybackRate = float("default_video_playback_rate", 1.0F) { requireRestart(); inputCheck = { (it.toFloatOrNull() ?: 1.0F) in 0.1F..4.0F} } diff --git a/common/src/main/kotlin/me/eternal/purrfectsnap/common/config/impl/MessagingTweaks.kt b/common/src/main/kotlin/me/eternal/purrfectsnap/common/config/impl/MessagingTweaks.kt new file mode 100644 index 00000000..bdcb5db7 --- /dev/null +++ b/common/src/main/kotlin/me/eternal/purrfectsnap/common/config/impl/MessagingTweaks.kt @@ -0,0 +1,288 @@ +package me.eternal.purrfectsnap.common.config.impl + +import me.eternal.purrfectsnap.common.config.ConfigContainer +import me.eternal.purrfectsnap.common.config.ConfigFlag +import me.eternal.purrfectsnap.common.config.FeatureNotice +import me.eternal.purrfectsnap.common.config.PropertyValue +import me.eternal.purrfectsnap.common.data.NotificationType +import me.eternal.purrfectsnap.common.util.PURGE_DISABLED_KEY +import me.eternal.purrfectsnap.common.util.PURGE_TRANSLATION_KEY +import me.eternal.purrfectsnap.common.util.PURGE_VALUES + +class MessagingTweaks : ConfigContainer() { + companion object { + const val DELETED_MESSAGE_COLOR = 0x6Eb71c1c; + } + + inner class HalfSwipeNotifierConfig : ConfigContainer(hasGlobalState = true) { + val minDuration: PropertyValue = integer("min_duration", defaultValue = 0) { + inputCheck = { it.toIntOrNull()?.coerceAtLeast(0) != null && maxDuration.get() >= it.toInt() } + } + val maxDuration: PropertyValue = integer("max_duration", defaultValue = 20) { + inputCheck = { it.toIntOrNull()?.coerceAtLeast(0) != null && minDuration.get() <= it.toInt() } + } + } + + inner class MessageLoggerConfig : ConfigContainer(hasGlobalState = true) { + val keepMyOwnMessages = boolean("keep_my_own_messages") + val autoPurge = unique("auto_purge", *PURGE_VALUES) { + customOptionTranslationPath = PURGE_TRANSLATION_KEY + disabledKey = PURGE_DISABLED_KEY + }.apply { set("3_days") } + val messageFilter = multiple("message_filter", "CHAT", + "SNAP", + "NOTE", + "EXTERNAL_MEDIA", + "STICKER" + ) { + customOptionTranslationPath = "content_type" + } + val deletedMessageColor = color("deleted_message_color", DELETED_MESSAGE_COLOR) + } + + class BetterNotifications: ConfigContainer() { + val groupNotifications = boolean("group_notifications") + val chatPreview = boolean("chat_preview") + val mediaPreview = multiple("media_preview", "SNAP", "EXTERNAL_MEDIA", "STICKER", "SHARE", "TINY_SNAP", "MAP_REACTION") { + customOptionTranslationPath = "content_type" + } + val mediaCaption = boolean("media_caption") + val stackedMediaMessages = boolean("stacked_media_messages") + val friendAddSource = boolean("friend_add_source") + val replyButton = boolean("reply_button") { addNotices(FeatureNotice.UNSTABLE) } + val smartReplies = boolean("smart_replies") + val downloadButton = boolean("download_button") + val markAsReadButton = boolean("mark_as_read_button") { addNotices(FeatureNotice.UNSTABLE) } + val markAsReadAndSaveInChat = boolean("mark_as_read_and_save_in_chat") { addNotices(FeatureNotice.UNSTABLE) } + } + + class AutoReplyConfig : ConfigContainer(hasGlobalState = true) { + val allowRunningInBackground = boolean("allow_running_in_background", false) + val cooldownSeconds = integer("cooldown_seconds", defaultValue = 30) { + inputCheck = { it.toIntOrNull()?.coerceAtLeast(0) != null } + } + val messageAgeThreshold = integer("message_age_threshold", defaultValue = 15) { + inputCheck = { it.toIntOrNull()?.coerceAtLeast(1) != null } + } + + inner class AiConfig : ConfigContainer(hasGlobalState = false) { + val enableAiReplies = boolean("enable_ai_replies", false) + val aiProvider = unique("ai_provider", "gemini", "deepseek", "openai") { + customOptionTranslationPath = "ai_provider" + }.apply { set("gemini") } + val aiModel = string("ai_model", defaultValue = "gemini-2.5-flash") { + inputCheck = { it.isNotBlank() } + } + val aiApiKey = string("ai_api_key", defaultValue = "") { + inputCheck = { true } + } + val aiSystemPrompt = string("ai_system_prompt", defaultValue = "You are a helpful and friendly assistant responding to messages on Snapchat. Keep responses natural, casual, and conversational. Avoid being overly formal or robotic. Respond as if you're a real person having a normal conversation.") { + inputCheck = { it.isNotBlank() } + } + val aiMaxTokens = integer("ai_max_tokens", defaultValue = 150) { + inputCheck = { it.toIntOrNull()?.coerceIn(10, 1000) != null } + } + val aiTemperature = string("ai_temperature", defaultValue = "0.7") { + inputCheck = { it.toDoubleOrNull()?.coerceIn(0.0, 2.0) != null } + } + val aiContextLength = integer("ai_context_length", defaultValue = 5) { + inputCheck = { it.toIntOrNull()?.coerceIn(1, 20) != null } + } + val aiPersonalityTraits = string("ai_personality_traits", defaultValue = "friendly, casual, helpful, empathetic") { + inputCheck = { it.isNotBlank() } + } + val aiResponseStyle = unique("ai_response_style", "casual", "formal", "friendly", "humorous", "empathetic", "toxic", "busy") { + customOptionTranslationPath = "ai_response_style" + }.apply { set("casual") } + val aiUseConversationHistory = boolean("ai_use_conversation_history", true) + val aiIncludeFriendInfo = boolean("ai_include_friend_info", true) + val aiFallbackToTemplate = boolean("ai_fallback_to_template", true) + val aiRequestTimeout = integer("ai_request_timeout", defaultValue = 10) { + inputCheck = { it.toIntOrNull()?.coerceIn(5, 60) != null } + } + val aiRetryAttempts = integer("ai_retry_attempts", defaultValue = 2) { + inputCheck = { it.toIntOrNull()?.coerceIn(0, 5) != null } + } + val aiResponseLanguage = unique("ai_response_language", "auto", "en", "es", "fr", "de", "it", "pt", "ru", "ja", "ko", "zh", "ar", "hi", "tr", "pl", "nl", "sv", "da", "no", "fi") { + customOptionTranslationPath = "ai_response_language" + }.apply { set("auto") } + } + + inner class AutoTriggerConfig : ConfigContainer(hasGlobalState = false) { + val friendSpecificGreeting = boolean("friendSpecificGreeting") + val friendGreeting = string("friendGreeting", defaultValue = "Hey") { + inputCheck = { it.isNotBlank() } + } + + val autoReplyContentTypes = multiple("auto_reply_content_types", + "chat_messages", + "snap_messages", + "story_share_messages", + "story_reply_messages", + "external_media_messages", + "voice_note_messages", + "sticker_messages", + "tiny_snap_messages", + "map_reaction_messages", + "half_swipes" + ) { + customOptionTranslationPath = "content_type" + }.apply { + set(mutableListOf( + "chat_messages", + "snap_messages", + "story_share_messages", + "story_reply_messages", + "external_media_messages", + "voice_note_messages", + "sticker_messages", + "tiny_snap_messages", + "map_reaction_messages", + "half_swipes" + )) + } + + val chatMessages = string("chat_messages", defaultValue = "Hello! How are you?") + val snapMessages = string("snap_messages", defaultValue = "Thanks for the snap!") + val storyShareMessages = string("story_share_messages", defaultValue = "Thanks for sharing!") + val storyReplyMessages = string("story_reply_messages", defaultValue = "Thanks for the story reply!") + val externalMediaMessages = string("external_media_messages", defaultValue = "Nice media!") + val voiceNoteMessages = string("voice_note_messages", defaultValue = "Thanks for the voice note!") + val stickerMessages = string("sticker_messages", defaultValue = "Cool sticker!") + val tinySnapMessages = string("tiny_snap_messages", defaultValue = "Thanks for the tiny snap!") + val mapReactionMessages = string("map_reaction_messages", defaultValue = "Thanks for the map reaction!") + val halfSwipeMessages = string("half_swipe_messages", defaultValue = "[\"I noticed you half-swiped! I'll respond soon.\"]") + } + + val aiConfig = container("ai_config", AiConfig()) + val autoTriggerConfig = container("auto_trigger_config", AutoTriggerConfig()) + } + + class AutoOpenSnapsConfig : ConfigContainer(hasGlobalState = true) { + init { + globalState = false + } + + val allowRunningInBackground = boolean("allow_running_in_background", false) + val minDelay = integer("min_delay", defaultValue = 50) { + inputCheck = { it.toIntOrNull()?.coerceAtLeast(0) != null } + } + val maxDelayMs = integer("max_delay_ms", defaultValue = 100) { + inputCheck = { it.toIntOrNull()?.coerceAtLeast(0) != null && it.toInt() > minDelay.get() } + } + val queueSize = integer("queue_size", defaultValue = 10) { + inputCheck = { it.toIntOrNull()?.coerceAtLeast(1) != null } + } + val retryAttempts = integer("retry_attempts", defaultValue = 5) { + inputCheck = { it.toIntOrNull()?.coerceAtLeast(1) != null } + } + val retryDelay = integer("retry_delay", defaultValue = 3000) { + inputCheck = { it.toIntOrNull()?.coerceAtLeast(1000) != null } + } + + } + + class AutoDeleteSentMessagesConfig : ConfigContainer(hasGlobalState = true) { + val allowRunningInBackground = boolean("allow_running_in_background", false) + val deleteAfterValue = integer("delete_after_value", defaultValue = 10) { + inputCheck = { it.toIntOrNull()?.coerceAtLeast(1) != null } + } + val deleteAfterUnit = unique("delete_after_unit", "seconds", "minutes", "hours") { + customOptionTranslationPath = "features.options.delete_after_unit" + addFlags(ConfigFlag.NO_DISABLE_KEY) + }.apply { set("seconds") } + val messageTypes = multiple("message_types", "CHAT", "SNAP", "NOTE", "EXTERNAL_MEDIA", "STICKER") { + customOptionTranslationPath = "content_type" + }.apply { + set(mutableListOf("CHAT")) + } + val showCountdown = boolean("show_countdown", defaultValue = true) + val showNotification = boolean("show_notification", defaultValue = true) + } + + val bypassScreenshotDetection = boolean("bypass_screenshot_detection") { requireRestart() } + val anonymousStoryViewing = boolean("anonymous_story_viewing") + val preventStoryRewatchIndicator = boolean("prevent_story_rewatch_indicator") { requireRestart() } + val hidePeekAPeek = boolean("hide_peek_a_peek") + val hideBitmojiPresence = boolean("hide_bitmoji_presence") + val hideTypingNotifications = boolean("hide_typing_notifications") + val unlimitedSnapViewTime = boolean("unlimited_snap_view_time") + val autoMarkAsRead = multiple("auto_mark_as_read", "snap_reply", "conversation_read", "save_snap_in_chat") { requireRestart() } + val markSnapAsSeenButton = boolean("mark_snap_as_seen_button") { requireRestart() } + val skipWhenMarkingAsSeen = boolean("skip_when_marking_as_seen") { requireRestart() } + val loopMediaPlayback = boolean("loop_media_playback") { requireRestart() } + val disableReplayInFF = boolean("disable_replay_in_ff") + val halfSwipeNotifier = container("half_swipe_notifier", HalfSwipeNotifierConfig()) { requireRestart()} + val callStartConfirmation = boolean("call_start_confirmation") { requireRestart() } + val unlimitedConversationPinning = boolean("unlimited_conversation_pinning") { requireRestart() } + val disableSnapModeRestrictions = boolean("disable_snap_mode_restrictions") { requireRestart() } + val autoSaveMessagesInConversations = multiple("auto_save_messages_in_conversations", + "CHAT", + "SNAP", + "NOTE", + "EXTERNAL_MEDIA", + "STICKER" + ) { requireRestart(); customOptionTranslationPath = "content_type" } + val preventMessageSending = multiple("prevent_message_sending", *NotificationType.getOutgoingValues().map { it.key }.toTypedArray()) { + customOptionTranslationPath = "features.options.notifications" + } + val friendMutationNotifier = multiple("friend_mutation_notifier", + "remove_friend", + "birthday_changes", + "bitmoji_selfie_changes", + "bitmoji_avatar_changes", + "bitmoji_background_changes", + "bitmoji_scene_changes", + ) { requireRestart() } + val betterNotifications = container("better_notifications", BetterNotifications()) { requireRestart() } + val notificationBlacklist = multiple("notification_blacklist", *NotificationType.getIncomingValues().map { it.key }.toTypedArray()) { + customOptionTranslationPath = "features.options.notifications" + } + val messageLogger = container("message_logger", MessageLoggerConfig()) { requireRestart() } + val galleryMediaSendOverride = unique("gallery_media_send_override", "always_ask", "SNAP", "NOTE", "SAVEABLE_SNAP") { requireRestart() } + val scheduledSendAllowRunningInBackground = boolean("scheduled_send_allow_running_in_background", false) + val stripMediaMetadata = multiple("strip_media_metadata", "hide_caption_text", "hide_snap_filters", "hide_extras", "remove_audio_note_duration", "remove_audio_note_transcript_capability") { requireRestart() } + val bypassMessageRetentionPolicy = boolean("bypass_message_retention_policy") { addNotices(FeatureNotice.UNSTABLE); requireRestart() } + val bypassMessageActionRestrictions = boolean("bypass_message_action_restrictions") { requireRestart() } + val removeGroupsLockedStatus = boolean("remove_groups_locked_status") { requireRestart() } + val doubleTapChatAction = unique("double_tap_chat_action", "like_message", "copy_text", "delete_message", "mark_as_read", "custom_emoji_reaction") { requireRestart() } + val doubleTapChatActionCustomEmoji = string("double_tap_chat_action_custom_emoji") { + inputCheck = { it.length == 2 && it.toByteArray(Charsets.UTF_8).size >= 4 } } + val autoReply = container("auto_reply", AutoReplyConfig()) { requireRestart() } + val autoOpenSnaps = container("auto_open_snaps", AutoOpenSnapsConfig()) { requireRestart(); addNotices(FeatureNotice.BAN_RISK, FeatureNotice.UNSTABLE) } + val autoDeleteSentMessages = container("auto_delete_sent_messages", AutoDeleteSentMessagesConfig()) { requireRestart() } + + class InstantTranslationConfig : ConfigContainer(hasGlobalState = true) { + val enabled = boolean("enabled", false) + val sourceLanguage = string("source_language", defaultValue = "auto") { + inputCheck = { it.isNotBlank() } + } + val targetLanguage = string("target_language", defaultValue = "en") { + inputCheck = { it.isNotBlank() } + } + val showOriginal = boolean("show_original", defaultValue = true) + val showTranslation = boolean("show_translation", defaultValue = true) + val translationPosition = unique("translation_position", "above", "below", "inline") { + customOptionTranslationPath = "translation_position" + }.apply { set("below") } + val autoTranslate = boolean("auto_translate", defaultValue = true) + val translateOnTap = boolean("translate_on_tap", defaultValue = false) + val pauseOnError = boolean("pause_on_error", defaultValue = true) + val maxRetries = integer("max_retries", defaultValue = 3) { + inputCheck = { it.toIntOrNull()?.coerceIn(1, 10) != null } + } + val retryDelay = integer("retry_delay", defaultValue = 1000) { + inputCheck = { it.toIntOrNull()?.coerceAtLeast(500) != null } + } + + val supportedLanguages = multiple("supported_languages", + "en", "es", "fr", "de", "it", "pt", "ru", "ja", "ko", "zh", "ar", "hi", "tr", "nl", "pl", "sv", "da", "no", "fi", "cs", "hu", "ro", "bg", "hr", "sk", "sl", "et", "lv", "lt", "mt", "ga", "cy" + ) { + customOptionTranslationPath = "language_codes" + }.apply { + set(mutableListOf("en", "es", "fr", "de", "it", "pt", "ru", "ja", "ko", "zh", "ar", "hi", "tr")) + } + } + + val instantTranslation = container("instant_translation", InstantTranslationConfig()) { requireRestart() } +} diff --git a/common/src/main/kotlin/me/rhunk/snapenhance/common/config/impl/RootConfig.kt b/common/src/main/kotlin/me/eternal/purrfectsnap/common/config/impl/RootConfig.kt similarity index 88% rename from common/src/main/kotlin/me/rhunk/snapenhance/common/config/impl/RootConfig.kt rename to common/src/main/kotlin/me/eternal/purrfectsnap/common/config/impl/RootConfig.kt index d258af9a..824ec620 100644 --- a/common/src/main/kotlin/me/rhunk/snapenhance/common/config/impl/RootConfig.kt +++ b/common/src/main/kotlin/me/eternal/purrfectsnap/common/config/impl/RootConfig.kt @@ -1,11 +1,11 @@ -package me.rhunk.snapenhance.common.config.impl +package me.eternal.purrfectsnap.common.config.impl import androidx.compose.material.icons.Icons import androidx.compose.material.icons.automirrored.filled.Rule import androidx.compose.material.icons.automirrored.filled.Send import androidx.compose.material.icons.filled.* -import me.rhunk.snapenhance.common.config.ConfigContainer -import me.rhunk.snapenhance.common.config.FeatureNotice +import me.eternal.purrfectsnap.common.config.ConfigContainer +import me.eternal.purrfectsnap.common.config.FeatureNotice class RootConfig : ConfigContainer() { val downloader = container("downloader", DownloaderConfig()) { icon = Icons.Default.Download } diff --git a/common/src/main/kotlin/me/rhunk/snapenhance/common/config/impl/Rules.kt b/common/src/main/kotlin/me/eternal/purrfectsnap/common/config/impl/Rules.kt similarity index 72% rename from common/src/main/kotlin/me/rhunk/snapenhance/common/config/impl/Rules.kt rename to common/src/main/kotlin/me/eternal/purrfectsnap/common/config/impl/Rules.kt index 3cf65f40..4f50b9dc 100644 --- a/common/src/main/kotlin/me/rhunk/snapenhance/common/config/impl/Rules.kt +++ b/common/src/main/kotlin/me/eternal/purrfectsnap/common/config/impl/Rules.kt @@ -1,9 +1,9 @@ -package me.rhunk.snapenhance.common.config.impl +package me.eternal.purrfectsnap.common.config.impl -import me.rhunk.snapenhance.common.config.ConfigContainer -import me.rhunk.snapenhance.common.config.PropertyValue -import me.rhunk.snapenhance.common.data.MessagingRuleType -import me.rhunk.snapenhance.common.data.RuleState +import me.eternal.purrfectsnap.common.config.ConfigContainer +import me.eternal.purrfectsnap.common.config.PropertyValue +import me.eternal.purrfectsnap.common.data.MessagingRuleType +import me.eternal.purrfectsnap.common.data.RuleState class Rules : ConfigContainer() { diff --git a/common/src/main/kotlin/me/rhunk/snapenhance/common/config/impl/Scripting.kt b/common/src/main/kotlin/me/eternal/purrfectsnap/common/config/impl/Scripting.kt similarity index 77% rename from common/src/main/kotlin/me/rhunk/snapenhance/common/config/impl/Scripting.kt rename to common/src/main/kotlin/me/eternal/purrfectsnap/common/config/impl/Scripting.kt index 793c3653..8e263696 100644 --- a/common/src/main/kotlin/me/rhunk/snapenhance/common/config/impl/Scripting.kt +++ b/common/src/main/kotlin/me/eternal/purrfectsnap/common/config/impl/Scripting.kt @@ -1,7 +1,7 @@ -package me.rhunk.snapenhance.common.config.impl +package me.eternal.purrfectsnap.common.config.impl -import me.rhunk.snapenhance.common.config.ConfigContainer -import me.rhunk.snapenhance.common.config.ConfigFlag +import me.eternal.purrfectsnap.common.config.ConfigContainer +import me.eternal.purrfectsnap.common.config.ConfigFlag class Scripting : ConfigContainer() { val developerMode = boolean("developer_mode", false) { requireRestart() } diff --git a/common/src/main/kotlin/me/eternal/purrfectsnap/common/config/impl/Spoof.kt b/common/src/main/kotlin/me/eternal/purrfectsnap/common/config/impl/Spoof.kt new file mode 100644 index 00000000..2204b423 --- /dev/null +++ b/common/src/main/kotlin/me/eternal/purrfectsnap/common/config/impl/Spoof.kt @@ -0,0 +1,26 @@ +package me.eternal.purrfectsnap.common.config.impl + +import me.eternal.purrfectsnap.common.config.ConfigContainer +import me.eternal.purrfectsnap.common.config.ConfigFlag + +class Spoof : ConfigContainer(hasGlobalState = true) { + val overridePlayStoreInstallerPackageName = boolean("play_store_installer_package_name") { requireRestart() } + val removeVpnTransportFlag = boolean("remove_vpn_transport_flag") { requireRestart() } + val removeMockLocationFlag = boolean("remove_mock_location_flag") { requireRestart() } + val forceWifiTransportFlag = boolean("force_wifi_transport_flag") { requireRestart() } + val spoofAndroidId = boolean("spoof_android_id") { requireRestart() } + val customAndroidId = string("custom_android_id") { + requireRestart() + inputCheck = { it.isEmpty() || (it.length == 16 && it.all { c -> c in '0'..'9' || c in 'a'..'f' || c in 'A'..'F' }) } + } + val spoofDevice = boolean("spoof_device") { requireRestart() } + val deviceModel = unique("device_model", + "samsung_s25_ultra", + "google_pixel_10_pro", + "oneplus_13", + "xiaomi_15_ultra" + ) { + requireRestart() + customOptionTranslationPath = "features.options.device_model" + } +} diff --git a/common/src/main/kotlin/me/rhunk/snapenhance/common/config/impl/StreaksReminderConfig.kt b/common/src/main/kotlin/me/eternal/purrfectsnap/common/config/impl/StreaksReminderConfig.kt similarity index 68% rename from common/src/main/kotlin/me/rhunk/snapenhance/common/config/impl/StreaksReminderConfig.kt rename to common/src/main/kotlin/me/eternal/purrfectsnap/common/config/impl/StreaksReminderConfig.kt index 9c9c0dce..225114d9 100644 --- a/common/src/main/kotlin/me/rhunk/snapenhance/common/config/impl/StreaksReminderConfig.kt +++ b/common/src/main/kotlin/me/eternal/purrfectsnap/common/config/impl/StreaksReminderConfig.kt @@ -1,6 +1,6 @@ -package me.rhunk.snapenhance.common.config.impl +package me.eternal.purrfectsnap.common.config.impl -import me.rhunk.snapenhance.common.config.ConfigContainer +import me.eternal.purrfectsnap.common.config.ConfigContainer class StreaksReminderConfig : ConfigContainer(hasGlobalState = true) { val interval = integer("interval", 1) diff --git a/common/src/main/kotlin/me/rhunk/snapenhance/common/config/impl/UserInterfaceTweaks.kt b/common/src/main/kotlin/me/eternal/purrfectsnap/common/config/impl/UserInterfaceTweaks.kt similarity index 92% rename from common/src/main/kotlin/me/rhunk/snapenhance/common/config/impl/UserInterfaceTweaks.kt rename to common/src/main/kotlin/me/eternal/purrfectsnap/common/config/impl/UserInterfaceTweaks.kt index f6ffa525..57d50a31 100644 --- a/common/src/main/kotlin/me/rhunk/snapenhance/common/config/impl/UserInterfaceTweaks.kt +++ b/common/src/main/kotlin/me/eternal/purrfectsnap/common/config/impl/UserInterfaceTweaks.kt @@ -1,9 +1,9 @@ -package me.rhunk.snapenhance.common.config.impl +package me.eternal.purrfectsnap.common.config.impl -import me.rhunk.snapenhance.common.config.ConfigContainer -import me.rhunk.snapenhance.common.config.FeatureNotice -import me.rhunk.snapenhance.common.config.RES_OBF_VERSION_CHECK -import me.rhunk.snapenhance.common.data.MessagingRuleType +import me.eternal.purrfectsnap.common.config.ConfigContainer +import me.eternal.purrfectsnap.common.config.FeatureNotice +import me.eternal.purrfectsnap.common.config.RES_OBF_VERSION_CHECK +import me.eternal.purrfectsnap.common.data.MessagingRuleType class UserInterfaceTweaks : ConfigContainer() { class BootstrapOverride : ConfigContainer() { diff --git a/common/src/main/kotlin/me/rhunk/snapenhance/common/data/ExportType.kt b/common/src/main/kotlin/me/eternal/purrfectsnap/common/data/ExportType.kt similarity index 52% rename from common/src/main/kotlin/me/rhunk/snapenhance/common/data/ExportType.kt rename to common/src/main/kotlin/me/eternal/purrfectsnap/common/data/ExportType.kt index daa6bdcf..5e399bb4 100644 --- a/common/src/main/kotlin/me/rhunk/snapenhance/common/data/ExportType.kt +++ b/common/src/main/kotlin/me/eternal/purrfectsnap/common/data/ExportType.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.common.data +package me.eternal.purrfectsnap.common.data enum class ExportType { BULK, diff --git a/common/src/main/kotlin/me/rhunk/snapenhance/common/data/ExportedTrackerData.kt b/common/src/main/kotlin/me/eternal/purrfectsnap/common/data/ExportedTrackerData.kt similarity index 67% rename from common/src/main/kotlin/me/rhunk/snapenhance/common/data/ExportedTrackerData.kt rename to common/src/main/kotlin/me/eternal/purrfectsnap/common/data/ExportedTrackerData.kt index b487ad10..8dc9594a 100644 --- a/common/src/main/kotlin/me/rhunk/snapenhance/common/data/ExportedTrackerData.kt +++ b/common/src/main/kotlin/me/eternal/purrfectsnap/common/data/ExportedTrackerData.kt @@ -1,6 +1,6 @@ -package me.rhunk.snapenhance.common.data +package me.eternal.purrfectsnap.common.data data class ExportedTrackerData( val type: ExportType, val rules: List -) +) \ No newline at end of file diff --git a/common/src/main/kotlin/me/rhunk/snapenhance/common/data/FileType.kt b/common/src/main/kotlin/me/eternal/purrfectsnap/common/data/FileType.kt similarity index 98% rename from common/src/main/kotlin/me/rhunk/snapenhance/common/data/FileType.kt rename to common/src/main/kotlin/me/eternal/purrfectsnap/common/data/FileType.kt index 805cc465..81a82180 100644 --- a/common/src/main/kotlin/me/rhunk/snapenhance/common/data/FileType.kt +++ b/common/src/main/kotlin/me/eternal/purrfectsnap/common/data/FileType.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.common.data +package me.eternal.purrfectsnap.common.data import java.io.File import java.io.InputStream diff --git a/common/src/main/kotlin/me/rhunk/snapenhance/common/data/MessagingCoreObjects.kt b/common/src/main/kotlin/me/eternal/purrfectsnap/common/data/MessagingCoreObjects.kt similarity index 84% rename from common/src/main/kotlin/me/rhunk/snapenhance/common/data/MessagingCoreObjects.kt rename to common/src/main/kotlin/me/eternal/purrfectsnap/common/data/MessagingCoreObjects.kt index a8c2fbfd..a41547f9 100644 --- a/common/src/main/kotlin/me/rhunk/snapenhance/common/data/MessagingCoreObjects.kt +++ b/common/src/main/kotlin/me/eternal/purrfectsnap/common/data/MessagingCoreObjects.kt @@ -1,18 +1,19 @@ -package me.rhunk.snapenhance.common.data +package me.eternal.purrfectsnap.common.data import android.database.Cursor import android.os.Parcelable import androidx.compose.material.icons.Icons import androidx.compose.material.icons.automirrored.filled.Message +import androidx.compose.material.icons.automirrored.outlined.Reply import androidx.compose.material.icons.outlined.* import androidx.compose.ui.graphics.vector.ImageVector import kotlinx.parcelize.Parcelize -import me.rhunk.snapenhance.common.config.FeatureNotice -import me.rhunk.snapenhance.common.data.download.toKeyPair -import me.rhunk.snapenhance.common.util.ktx.getIntOrNull -import me.rhunk.snapenhance.common.util.ktx.getInteger -import me.rhunk.snapenhance.common.util.ktx.getLongOrNull -import me.rhunk.snapenhance.common.util.ktx.getStringOrNull +import me.eternal.purrfectsnap.common.config.FeatureNotice +import me.eternal.purrfectsnap.common.data.download.toKeyPair +import me.eternal.purrfectsnap.common.util.ktx.getIntOrNull +import me.eternal.purrfectsnap.common.util.ktx.getInteger +import me.eternal.purrfectsnap.common.util.ktx.getLongOrNull +import me.eternal.purrfectsnap.common.util.ktx.getStringOrNull import kotlin.time.Duration.Companion.hours @@ -56,7 +57,10 @@ enum class MessagingRuleType( HIDE_FRIEND_FEED("hide_friend_feed", false, Icons.Outlined.VisibilityOff, showInFriendMenu = false), E2E_ENCRYPTION("e2e_encryption", false, Icons.Outlined.Lock), PIN_CONVERSATION("pin_conversation", false, Icons.Outlined.PushPin, showInFriendMenu = false), - MESSAGE_LOGGER("message_logger", true, Icons.AutoMirrored.Filled.Message, showInFriendMenu = true); + MESSAGE_LOGGER("message_logger", true, Icons.AutoMirrored.Filled.Message, showInFriendMenu = true), + AUTO_READ("auto_read", true, Icons.Outlined.DoneAll, defaultValue = "whitelist"), + AUTO_REPLY("auto_reply", true, Icons.AutoMirrored.Outlined.Reply, defaultValue = "blacklist"), + AUTO_DELETE_SENT_MESSAGES("auto_delete_sent_messages", true, Icons.Outlined.DeleteSweep, defaultValue = "blacklist"); fun translateOptionKey(optionKey: String): String { return if (listMode) "rules.properties.$key.options.$optionKey" else "rules.properties.$key.name" @@ -136,4 +140,4 @@ class StoryData( val iv: ByteArray? ) { fun getEncryptionKeyPair() = key?.let { (it to (iv ?: return@let null)) }?.toKeyPair() -} \ No newline at end of file +} diff --git a/common/src/main/kotlin/me/rhunk/snapenhance/common/data/SessionEventsData.kt b/common/src/main/kotlin/me/eternal/purrfectsnap/common/data/SessionEventsData.kt similarity index 97% rename from common/src/main/kotlin/me/rhunk/snapenhance/common/data/SessionEventsData.kt rename to common/src/main/kotlin/me/eternal/purrfectsnap/common/data/SessionEventsData.kt index 35636266..83744bfb 100644 --- a/common/src/main/kotlin/me/rhunk/snapenhance/common/data/SessionEventsData.kt +++ b/common/src/main/kotlin/me/eternal/purrfectsnap/common/data/SessionEventsData.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.common.data +package me.eternal.purrfectsnap.common.data import android.os.Parcelable import kotlinx.parcelize.Parcelize @@ -43,6 +43,7 @@ enum class SessionEventType( SNAP_REPLAYED_TWICE("snap_replayed_twice"), SNAP_SCREENSHOT("snap_screenshot"), SNAP_SCREEN_RECORD("snap_screen_record"), + I_CAN_SEE_YOU("i_can_see_you"), } enum class TrackerEventType( @@ -71,6 +72,7 @@ enum class TrackerEventType( SNAP_REPLAYED_TWICE("snap_replayed_twice"), SNAP_SCREENSHOT("snap_screenshot"), SNAP_SCREEN_RECORD("snap_screen_record"), + I_CAN_SEE_YOU("i_can_see_you"), } diff --git a/common/src/main/kotlin/me/rhunk/snapenhance/common/data/SnapEnums.kt b/common/src/main/kotlin/me/eternal/purrfectsnap/common/data/SnapEnums.kt similarity index 88% rename from common/src/main/kotlin/me/rhunk/snapenhance/common/data/SnapEnums.kt rename to common/src/main/kotlin/me/eternal/purrfectsnap/common/data/SnapEnums.kt index 5294fd44..7c0defc6 100644 --- a/common/src/main/kotlin/me/rhunk/snapenhance/common/data/SnapEnums.kt +++ b/common/src/main/kotlin/me/eternal/purrfectsnap/common/data/SnapEnums.kt @@ -1,14 +1,14 @@ -package me.rhunk.snapenhance.common.data +package me.eternal.purrfectsnap.common.data -import me.rhunk.snapenhance.common.data.ContentType.entries -import me.rhunk.snapenhance.common.data.FriendAddSource.entries -import me.rhunk.snapenhance.common.data.FriendLinkType.entries -import me.rhunk.snapenhance.common.data.MixerStoryType.entries -import me.rhunk.snapenhance.common.data.NotificationType.entries -import me.rhunk.snapenhance.common.util.protobuf.ProtoReader +import me.eternal.purrfectsnap.common.data.ContentType.entries +import me.eternal.purrfectsnap.common.data.FriendAddSource.entries +import me.eternal.purrfectsnap.common.data.FriendLinkType.entries +import me.eternal.purrfectsnap.common.data.MixerStoryType.entries +import me.eternal.purrfectsnap.common.data.NotificationType.entries +import me.eternal.purrfectsnap.common.util.protobuf.ProtoReader enum class MessageState { - PREPARING, SENDING, COMMITTED, FAILED, CANCELING + PREPARING, SENDING, COMMITTED, FAILED, CANCELING, PENDING_DECRYPTION } enum class NotificationType ( @@ -87,7 +87,12 @@ enum class ContentType(val id: Int) { PROMPT_LENS_RESPONSE(25), TINY_SNAP(26), STATUS_COUNTDOWN(27), - MAP_REACTION(28); + MAP_REACTION(28), + STORY_REPLY(29), + MY_AI_SPECTACLES_BOT_RESPONSE(30), + STATUS_SNAP_REMIX_CAPTURE(31), + STATUS_STICKER_CUTOUT(32), + STATUS_FRIEND_PLACE_ALERT(33); companion object { fun fromId(i: Int): ContentType { @@ -105,7 +110,7 @@ enum class ContentType(val id: Int) { contains(3) -> EXTERNAL_MEDIA contains(4) -> STICKER contains(5) -> SHARE - contains(7) -> EXTERNAL_MEDIA // story replies + contains(7) -> STORY_REPLY // story replies contains(20) -> MAP_REACTION else -> null } diff --git a/common/src/main/kotlin/me/rhunk/snapenhance/common/data/ThemingObjects.kt b/common/src/main/kotlin/me/eternal/purrfectsnap/common/data/ThemingObjects.kt similarity index 98% rename from common/src/main/kotlin/me/rhunk/snapenhance/common/data/ThemingObjects.kt rename to common/src/main/kotlin/me/eternal/purrfectsnap/common/data/ThemingObjects.kt index c95d4a61..21756666 100644 --- a/common/src/main/kotlin/me/rhunk/snapenhance/common/data/ThemingObjects.kt +++ b/common/src/main/kotlin/me/eternal/purrfectsnap/common/data/ThemingObjects.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.common.data +package me.eternal.purrfectsnap.common.data import android.os.Parcelable import com.google.gson.annotations.SerializedName diff --git a/common/src/main/kotlin/me/rhunk/snapenhance/common/data/TrackerDataManager.kt b/common/src/main/kotlin/me/eternal/purrfectsnap/common/data/TrackerDataManager.kt similarity index 82% rename from common/src/main/kotlin/me/rhunk/snapenhance/common/data/TrackerDataManager.kt rename to common/src/main/kotlin/me/eternal/purrfectsnap/common/data/TrackerDataManager.kt index 2d7c9875..15b1287c 100644 --- a/common/src/main/kotlin/me/rhunk/snapenhance/common/data/TrackerDataManager.kt +++ b/common/src/main/kotlin/me/eternal/purrfectsnap/common/data/TrackerDataManager.kt @@ -1,7 +1,7 @@ -package me.rhunk.snapenhance.common.data +package me.eternal.purrfectsnap.common.data interface TrackerDataManager { fun getExportedTrackerData(): ExportedTrackerData fun getExportedTrackerData(ruleId: Int): ExportedTrackerData? fun importTrackerData(data: ExportedTrackerData) -} +} \ No newline at end of file diff --git a/common/src/main/kotlin/me/rhunk/snapenhance/common/data/download/DownloadMediaType.kt b/common/src/main/kotlin/me/eternal/purrfectsnap/common/data/download/DownloadMediaType.kt similarity index 90% rename from common/src/main/kotlin/me/rhunk/snapenhance/common/data/download/DownloadMediaType.kt rename to common/src/main/kotlin/me/eternal/purrfectsnap/common/data/download/DownloadMediaType.kt index ede7c0e8..b42492ad 100644 --- a/common/src/main/kotlin/me/rhunk/snapenhance/common/data/download/DownloadMediaType.kt +++ b/common/src/main/kotlin/me/eternal/purrfectsnap/common/data/download/DownloadMediaType.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.common.data.download +package me.eternal.purrfectsnap.common.data.download import android.net.Uri diff --git a/common/src/main/kotlin/me/rhunk/snapenhance/common/data/download/DownloadMetadata.kt b/common/src/main/kotlin/me/eternal/purrfectsnap/common/data/download/DownloadMetadata.kt similarity index 77% rename from common/src/main/kotlin/me/rhunk/snapenhance/common/data/download/DownloadMetadata.kt rename to common/src/main/kotlin/me/eternal/purrfectsnap/common/data/download/DownloadMetadata.kt index 29a97c58..ea9b78a7 100644 --- a/common/src/main/kotlin/me/rhunk/snapenhance/common/data/download/DownloadMetadata.kt +++ b/common/src/main/kotlin/me/eternal/purrfectsnap/common/data/download/DownloadMetadata.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.common.data.download +package me.eternal.purrfectsnap.common.data.download data class DownloadMetadata( val mediaIdentifier: String, diff --git a/common/src/main/kotlin/me/rhunk/snapenhance/common/data/download/DownloadRequest.kt b/common/src/main/kotlin/me/eternal/purrfectsnap/common/data/download/DownloadRequest.kt similarity index 96% rename from common/src/main/kotlin/me/rhunk/snapenhance/common/data/download/DownloadRequest.kt rename to common/src/main/kotlin/me/eternal/purrfectsnap/common/data/download/DownloadRequest.kt index 3dec97b7..534479fb 100644 --- a/common/src/main/kotlin/me/rhunk/snapenhance/common/data/download/DownloadRequest.kt +++ b/common/src/main/kotlin/me/eternal/purrfectsnap/common/data/download/DownloadRequest.kt @@ -1,6 +1,6 @@ -package me.rhunk.snapenhance.common.data.download +package me.eternal.purrfectsnap.common.data.download -import me.rhunk.snapenhance.common.config.impl.RootConfig +import me.eternal.purrfectsnap.common.config.impl.RootConfig import java.text.SimpleDateFormat import java.util.Locale diff --git a/common/src/main/kotlin/me/rhunk/snapenhance/common/data/download/DownloadStage.kt b/common/src/main/kotlin/me/eternal/purrfectsnap/common/data/download/DownloadStage.kt similarity index 81% rename from common/src/main/kotlin/me/rhunk/snapenhance/common/data/download/DownloadStage.kt rename to common/src/main/kotlin/me/eternal/purrfectsnap/common/data/download/DownloadStage.kt index 674e7a37..6c939ad4 100644 --- a/common/src/main/kotlin/me/rhunk/snapenhance/common/data/download/DownloadStage.kt +++ b/common/src/main/kotlin/me/eternal/purrfectsnap/common/data/download/DownloadStage.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.common.data.download +package me.eternal.purrfectsnap.common.data.download enum class DownloadStage( val isFinalStage: Boolean = false, diff --git a/common/src/main/kotlin/me/rhunk/snapenhance/common/data/download/MediaDownloadSource.kt b/common/src/main/kotlin/me/eternal/purrfectsnap/common/data/download/MediaDownloadSource.kt similarity index 90% rename from common/src/main/kotlin/me/rhunk/snapenhance/common/data/download/MediaDownloadSource.kt rename to common/src/main/kotlin/me/eternal/purrfectsnap/common/data/download/MediaDownloadSource.kt index e9525293..030c6e9b 100644 --- a/common/src/main/kotlin/me/rhunk/snapenhance/common/data/download/MediaDownloadSource.kt +++ b/common/src/main/kotlin/me/eternal/purrfectsnap/common/data/download/MediaDownloadSource.kt @@ -1,6 +1,6 @@ -package me.rhunk.snapenhance.common.data.download +package me.eternal.purrfectsnap.common.data.download -import me.rhunk.snapenhance.common.bridge.wrapper.LocaleWrapper +import me.eternal.purrfectsnap.common.bridge.wrapper.LocaleWrapper enum class MediaDownloadSource( val key: String, diff --git a/common/src/main/kotlin/me/rhunk/snapenhance/common/data/download/MediaEncryptionKeyPair.kt b/common/src/main/kotlin/me/eternal/purrfectsnap/common/data/download/MediaEncryptionKeyPair.kt similarity index 95% rename from common/src/main/kotlin/me/rhunk/snapenhance/common/data/download/MediaEncryptionKeyPair.kt rename to common/src/main/kotlin/me/eternal/purrfectsnap/common/data/download/MediaEncryptionKeyPair.kt index 5adbdb6d..96059373 100644 --- a/common/src/main/kotlin/me/rhunk/snapenhance/common/data/download/MediaEncryptionKeyPair.kt +++ b/common/src/main/kotlin/me/eternal/purrfectsnap/common/data/download/MediaEncryptionKeyPair.kt @@ -1,5 +1,5 @@ -package me.rhunk.snapenhance.common.data.download +package me.eternal.purrfectsnap.common.data.download import java.io.InputStream import javax.crypto.Cipher diff --git a/common/src/main/kotlin/me/rhunk/snapenhance/common/data/download/SplitMediaAssetType.kt b/common/src/main/kotlin/me/eternal/purrfectsnap/common/data/download/SplitMediaAssetType.kt similarity index 52% rename from common/src/main/kotlin/me/rhunk/snapenhance/common/data/download/SplitMediaAssetType.kt rename to common/src/main/kotlin/me/eternal/purrfectsnap/common/data/download/SplitMediaAssetType.kt index 8c6d33e3..87a44063 100644 --- a/common/src/main/kotlin/me/rhunk/snapenhance/common/data/download/SplitMediaAssetType.kt +++ b/common/src/main/kotlin/me/eternal/purrfectsnap/common/data/download/SplitMediaAssetType.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.common.data.download +package me.eternal.purrfectsnap.common.data.download enum class SplitMediaAssetType { ORIGINAL, OVERLAY diff --git a/common/src/main/kotlin/me/rhunk/snapenhance/common/database/DatabaseObject.kt b/common/src/main/kotlin/me/eternal/purrfectsnap/common/database/DatabaseObject.kt similarity index 65% rename from common/src/main/kotlin/me/rhunk/snapenhance/common/database/DatabaseObject.kt rename to common/src/main/kotlin/me/eternal/purrfectsnap/common/database/DatabaseObject.kt index dcd70f9b..db7cc174 100644 --- a/common/src/main/kotlin/me/rhunk/snapenhance/common/database/DatabaseObject.kt +++ b/common/src/main/kotlin/me/eternal/purrfectsnap/common/database/DatabaseObject.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.common.database +package me.eternal.purrfectsnap.common.database import android.database.Cursor diff --git a/common/src/main/kotlin/me/rhunk/snapenhance/common/database/impl/ConversationMessage.kt b/common/src/main/kotlin/me/eternal/purrfectsnap/common/database/impl/ConversationMessage.kt similarity index 76% rename from common/src/main/kotlin/me/rhunk/snapenhance/common/database/impl/ConversationMessage.kt rename to common/src/main/kotlin/me/eternal/purrfectsnap/common/database/impl/ConversationMessage.kt index 62844282..7d8527b6 100644 --- a/common/src/main/kotlin/me/rhunk/snapenhance/common/database/impl/ConversationMessage.kt +++ b/common/src/main/kotlin/me/eternal/purrfectsnap/common/database/impl/ConversationMessage.kt @@ -1,13 +1,13 @@ -package me.rhunk.snapenhance.common.database.impl +package me.eternal.purrfectsnap.common.database.impl import android.annotation.SuppressLint import android.database.Cursor -import me.rhunk.snapenhance.common.database.DatabaseObject -import me.rhunk.snapenhance.common.util.ktx.getBlobOrNull -import me.rhunk.snapenhance.common.util.ktx.getInteger -import me.rhunk.snapenhance.common.util.ktx.getLong -import me.rhunk.snapenhance.common.util.ktx.getLongOrNull -import me.rhunk.snapenhance.common.util.ktx.getStringOrNull +import me.eternal.purrfectsnap.common.database.DatabaseObject +import me.eternal.purrfectsnap.common.util.ktx.getBlobOrNull +import me.eternal.purrfectsnap.common.util.ktx.getInteger +import me.eternal.purrfectsnap.common.util.ktx.getLong +import me.eternal.purrfectsnap.common.util.ktx.getLongOrNull +import me.eternal.purrfectsnap.common.util.ktx.getStringOrNull @Suppress("ArrayInDataClass") data class ConversationMessage( diff --git a/common/src/main/kotlin/me/rhunk/snapenhance/common/database/impl/FriendFeedEntry.kt b/common/src/main/kotlin/me/eternal/purrfectsnap/common/database/impl/FriendFeedEntry.kt similarity index 87% rename from common/src/main/kotlin/me/rhunk/snapenhance/common/database/impl/FriendFeedEntry.kt rename to common/src/main/kotlin/me/eternal/purrfectsnap/common/database/impl/FriendFeedEntry.kt index d17e3867..8f670ba2 100644 --- a/common/src/main/kotlin/me/rhunk/snapenhance/common/database/impl/FriendFeedEntry.kt +++ b/common/src/main/kotlin/me/eternal/purrfectsnap/common/database/impl/FriendFeedEntry.kt @@ -1,12 +1,12 @@ -package me.rhunk.snapenhance.common.database.impl +package me.eternal.purrfectsnap.common.database.impl import android.annotation.SuppressLint import android.database.Cursor -import me.rhunk.snapenhance.common.database.DatabaseObject -import me.rhunk.snapenhance.common.util.ktx.getBlobOrNull -import me.rhunk.snapenhance.common.util.ktx.getIntOrNull -import me.rhunk.snapenhance.common.util.ktx.getLongOrNull -import me.rhunk.snapenhance.common.util.ktx.getStringOrNull +import me.eternal.purrfectsnap.common.database.DatabaseObject +import me.eternal.purrfectsnap.common.util.ktx.getBlobOrNull +import me.eternal.purrfectsnap.common.util.ktx.getIntOrNull +import me.eternal.purrfectsnap.common.util.ktx.getLongOrNull +import me.eternal.purrfectsnap.common.util.ktx.getStringOrNull import java.nio.ByteBuffer import java.util.UUID diff --git a/common/src/main/kotlin/me/rhunk/snapenhance/common/database/impl/FriendInfo.kt b/common/src/main/kotlin/me/eternal/purrfectsnap/common/database/impl/FriendInfo.kt similarity index 89% rename from common/src/main/kotlin/me/rhunk/snapenhance/common/database/impl/FriendInfo.kt rename to common/src/main/kotlin/me/eternal/purrfectsnap/common/database/impl/FriendInfo.kt index 9a1a0bd8..0e5c037d 100644 --- a/common/src/main/kotlin/me/rhunk/snapenhance/common/database/impl/FriendInfo.kt +++ b/common/src/main/kotlin/me/eternal/purrfectsnap/common/database/impl/FriendInfo.kt @@ -1,12 +1,12 @@ -package me.rhunk.snapenhance.common.database.impl +package me.eternal.purrfectsnap.common.database.impl import android.annotation.SuppressLint import android.database.Cursor -import me.rhunk.snapenhance.common.database.DatabaseObject -import me.rhunk.snapenhance.common.util.ktx.getIntOrNull -import me.rhunk.snapenhance.common.util.ktx.getInteger -import me.rhunk.snapenhance.common.util.ktx.getLong -import me.rhunk.snapenhance.common.util.ktx.getStringOrNull +import me.eternal.purrfectsnap.common.database.DatabaseObject +import me.eternal.purrfectsnap.common.util.ktx.getIntOrNull +import me.eternal.purrfectsnap.common.util.ktx.getInteger +import me.eternal.purrfectsnap.common.util.ktx.getLong +import me.eternal.purrfectsnap.common.util.ktx.getStringOrNull data class FriendInfo( var id: Int = 0, diff --git a/common/src/main/kotlin/me/rhunk/snapenhance/common/database/impl/StoryEntry.kt b/common/src/main/kotlin/me/eternal/purrfectsnap/common/database/impl/StoryEntry.kt similarity index 72% rename from common/src/main/kotlin/me/rhunk/snapenhance/common/database/impl/StoryEntry.kt rename to common/src/main/kotlin/me/eternal/purrfectsnap/common/database/impl/StoryEntry.kt index 7f90fca2..50706f02 100644 --- a/common/src/main/kotlin/me/rhunk/snapenhance/common/database/impl/StoryEntry.kt +++ b/common/src/main/kotlin/me/eternal/purrfectsnap/common/database/impl/StoryEntry.kt @@ -1,10 +1,10 @@ -package me.rhunk.snapenhance.common.database.impl +package me.eternal.purrfectsnap.common.database.impl import android.annotation.SuppressLint import android.database.Cursor -import me.rhunk.snapenhance.common.database.DatabaseObject -import me.rhunk.snapenhance.common.util.ktx.getInteger -import me.rhunk.snapenhance.common.util.ktx.getStringOrNull +import me.eternal.purrfectsnap.common.database.DatabaseObject +import me.eternal.purrfectsnap.common.util.ktx.getInteger +import me.eternal.purrfectsnap.common.util.ktx.getStringOrNull data class StoryEntry( var id: Int = 0, diff --git a/common/src/main/kotlin/me/rhunk/snapenhance/common/database/impl/StorySnapEntry.kt b/common/src/main/kotlin/me/eternal/purrfectsnap/common/database/impl/StorySnapEntry.kt similarity index 75% rename from common/src/main/kotlin/me/rhunk/snapenhance/common/database/impl/StorySnapEntry.kt rename to common/src/main/kotlin/me/eternal/purrfectsnap/common/database/impl/StorySnapEntry.kt index 0bc4d89d..e59ec026 100644 --- a/common/src/main/kotlin/me/rhunk/snapenhance/common/database/impl/StorySnapEntry.kt +++ b/common/src/main/kotlin/me/eternal/purrfectsnap/common/database/impl/StorySnapEntry.kt @@ -1,8 +1,8 @@ -package me.rhunk.snapenhance.common.database.impl +package me.eternal.purrfectsnap.common.database.impl import android.database.Cursor -import me.rhunk.snapenhance.common.database.DatabaseObject -import me.rhunk.snapenhance.common.util.ktx.getStringOrNull +import me.eternal.purrfectsnap.common.database.DatabaseObject +import me.eternal.purrfectsnap.common.util.ktx.getStringOrNull data class StorySnapEntry( var rawSnapId: String? = null, diff --git a/common/src/main/kotlin/me/rhunk/snapenhance/common/database/impl/UserConversationLink.kt b/common/src/main/kotlin/me/eternal/purrfectsnap/common/database/impl/UserConversationLink.kt similarity index 69% rename from common/src/main/kotlin/me/rhunk/snapenhance/common/database/impl/UserConversationLink.kt rename to common/src/main/kotlin/me/eternal/purrfectsnap/common/database/impl/UserConversationLink.kt index 9865c657..8c6a71cb 100644 --- a/common/src/main/kotlin/me/rhunk/snapenhance/common/database/impl/UserConversationLink.kt +++ b/common/src/main/kotlin/me/eternal/purrfectsnap/common/database/impl/UserConversationLink.kt @@ -1,10 +1,10 @@ -package me.rhunk.snapenhance.common.database.impl +package me.eternal.purrfectsnap.common.database.impl import android.annotation.SuppressLint import android.database.Cursor -import me.rhunk.snapenhance.common.database.DatabaseObject -import me.rhunk.snapenhance.common.util.ktx.getInteger -import me.rhunk.snapenhance.common.util.ktx.getStringOrNull +import me.eternal.purrfectsnap.common.database.DatabaseObject +import me.eternal.purrfectsnap.common.util.ktx.getInteger +import me.eternal.purrfectsnap.common.util.ktx.getStringOrNull class UserConversationLink( var userId: String? = null, diff --git a/common/src/main/kotlin/me/rhunk/snapenhance/common/logger/AbstractLogger.kt b/common/src/main/kotlin/me/eternal/purrfectsnap/common/logger/AbstractLogger.kt similarity index 91% rename from common/src/main/kotlin/me/rhunk/snapenhance/common/logger/AbstractLogger.kt rename to common/src/main/kotlin/me/eternal/purrfectsnap/common/logger/AbstractLogger.kt index 1de33266..628f89ad 100644 --- a/common/src/main/kotlin/me/rhunk/snapenhance/common/logger/AbstractLogger.kt +++ b/common/src/main/kotlin/me/eternal/purrfectsnap/common/logger/AbstractLogger.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.common.logger +package me.eternal.purrfectsnap.common.logger import android.app.Notification import android.app.NotificationChannel @@ -14,7 +14,7 @@ abstract class AbstractLogger( companion object { - private const val TAG = "SnapEnhanceCommon" + private const val TAG = "PurrfectSnapCommon" fun directDebug(message: Any?, tag: String = TAG) { Log.println(Log.DEBUG, tag, message.toString()) @@ -50,7 +50,7 @@ fun Context.fatalCrash(throwable: Throwable) { notify( 0, Notification.Builder(this@fatalCrash, "default") - .setContentTitle("Failed to load SnapEnhance") + .setContentTitle("Failed to load PurrfectSnap") .setStyle(Notification.BigTextStyle().bigText(throwable.message + "\n" + throwable.stackTraceToString())) .setSmallIcon(android.R.drawable.stat_notify_error) .build() diff --git a/common/src/main/kotlin/me/rhunk/snapenhance/common/logger/LogChannel.kt b/common/src/main/kotlin/me/eternal/purrfectsnap/common/logger/LogChannel.kt similarity index 58% rename from common/src/main/kotlin/me/rhunk/snapenhance/common/logger/LogChannel.kt rename to common/src/main/kotlin/me/eternal/purrfectsnap/common/logger/LogChannel.kt index 0d9696e5..67ed8f69 100644 --- a/common/src/main/kotlin/me/rhunk/snapenhance/common/logger/LogChannel.kt +++ b/common/src/main/kotlin/me/eternal/purrfectsnap/common/logger/LogChannel.kt @@ -1,14 +1,14 @@ -package me.rhunk.snapenhance.common.logger +package me.eternal.purrfectsnap.common.logger enum class LogChannel( val channel: String, val shortName: String ) { - CORE("SnapEnhanceCore", "core"), - COMMON("SnapEnhanceCommon", "common"), + CORE("PurrfectSnapCore", "core"), + COMMON("PurrfectSnapCommon", "common"), SCRIPTING("Scripting", "scripting"), - NATIVE("SnapEnhanceNative", "native"), - MANAGER("SnapEnhanceManager", "manager"), + NATIVE("PurrfectSnapNative", "native"), + MANAGER("PurrfectSnapManager", "manager"), XPOSED("LSPosed-Bridge", "xposed"); companion object { diff --git a/common/src/main/kotlin/me/rhunk/snapenhance/common/logger/LogLevel.kt b/common/src/main/kotlin/me/eternal/purrfectsnap/common/logger/LogLevel.kt similarity index 94% rename from common/src/main/kotlin/me/rhunk/snapenhance/common/logger/LogLevel.kt rename to common/src/main/kotlin/me/eternal/purrfectsnap/common/logger/LogLevel.kt index b20c78a2..70679402 100644 --- a/common/src/main/kotlin/me/rhunk/snapenhance/common/logger/LogLevel.kt +++ b/common/src/main/kotlin/me/eternal/purrfectsnap/common/logger/LogLevel.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.common.logger +package me.eternal.purrfectsnap.common.logger import android.util.Log diff --git a/common/src/main/kotlin/me/rhunk/snapenhance/common/messaging/MessagingTask.kt b/common/src/main/kotlin/me/eternal/purrfectsnap/common/messaging/MessagingTask.kt similarity index 94% rename from common/src/main/kotlin/me/rhunk/snapenhance/common/messaging/MessagingTask.kt rename to common/src/main/kotlin/me/eternal/purrfectsnap/common/messaging/MessagingTask.kt index 7b019a17..b8eb0f89 100644 --- a/common/src/main/kotlin/me/rhunk/snapenhance/common/messaging/MessagingTask.kt +++ b/common/src/main/kotlin/me/eternal/purrfectsnap/common/messaging/MessagingTask.kt @@ -1,10 +1,10 @@ -package me.rhunk.snapenhance.common.messaging +package me.eternal.purrfectsnap.common.messaging import androidx.compose.runtime.MutableIntState import kotlinx.coroutines.delay -import me.rhunk.snapenhance.bridge.snapclient.MessagingBridge -import me.rhunk.snapenhance.bridge.snapclient.types.Message -import me.rhunk.snapenhance.common.data.ContentType +import me.eternal.purrfectsnap.bridge.snapclient.MessagingBridge +import me.eternal.purrfectsnap.bridge.snapclient.types.Message +import me.eternal.purrfectsnap.common.data.ContentType import kotlin.random.Random diff --git a/common/src/main/kotlin/me/rhunk/snapenhance/common/scripting/JSModule.kt b/common/src/main/kotlin/me/eternal/purrfectsnap/common/scripting/JSModule.kt similarity index 93% rename from common/src/main/kotlin/me/rhunk/snapenhance/common/scripting/JSModule.kt rename to common/src/main/kotlin/me/eternal/purrfectsnap/common/scripting/JSModule.kt index f0e7c0cd..51c62580 100644 --- a/common/src/main/kotlin/me/rhunk/snapenhance/common/scripting/JSModule.kt +++ b/common/src/main/kotlin/me/eternal/purrfectsnap/common/scripting/JSModule.kt @@ -1,20 +1,20 @@ -package me.rhunk.snapenhance.common.scripting +package me.eternal.purrfectsnap.common.scripting import android.os.Handler import android.widget.Toast import kotlinx.coroutines.* -import me.rhunk.snapenhance.common.scripting.bindings.AbstractBinding -import me.rhunk.snapenhance.common.scripting.bindings.BindingsContext -import me.rhunk.snapenhance.common.scripting.impl.JavaInterfaces -import me.rhunk.snapenhance.common.scripting.impl.Networking -import me.rhunk.snapenhance.common.scripting.impl.Protobuf -import me.rhunk.snapenhance.common.scripting.ktx.contextScope -import me.rhunk.snapenhance.common.scripting.ktx.putFunction -import me.rhunk.snapenhance.common.scripting.ktx.scriptable -import me.rhunk.snapenhance.common.scripting.ktx.scriptableObject -import me.rhunk.snapenhance.common.scripting.type.ModuleInfo -import me.rhunk.snapenhance.common.scripting.type.Permissions -import me.rhunk.snapenhance.common.scripting.ui.InterfaceManager +import me.eternal.purrfectsnap.common.scripting.bindings.AbstractBinding +import me.eternal.purrfectsnap.common.scripting.bindings.BindingsContext +import me.eternal.purrfectsnap.common.scripting.impl.JavaInterfaces +import me.eternal.purrfectsnap.common.scripting.impl.Networking +import me.eternal.purrfectsnap.common.scripting.impl.Protobuf +import me.eternal.purrfectsnap.common.scripting.ktx.contextScope +import me.eternal.purrfectsnap.common.scripting.ktx.putFunction +import me.eternal.purrfectsnap.common.scripting.ktx.scriptable +import me.eternal.purrfectsnap.common.scripting.ktx.scriptableObject +import me.eternal.purrfectsnap.common.scripting.type.ModuleInfo +import me.eternal.purrfectsnap.common.scripting.type.Permissions +import me.eternal.purrfectsnap.common.scripting.ui.InterfaceManager import org.mozilla.javascript.Function import org.mozilla.javascript.ScriptableObject import org.mozilla.javascript.Undefined diff --git a/common/src/main/kotlin/me/rhunk/snapenhance/common/scripting/PrimitiveUtil.kt b/common/src/main/kotlin/me/eternal/purrfectsnap/common/scripting/PrimitiveUtil.kt similarity index 96% rename from common/src/main/kotlin/me/rhunk/snapenhance/common/scripting/PrimitiveUtil.kt rename to common/src/main/kotlin/me/eternal/purrfectsnap/common/scripting/PrimitiveUtil.kt index 366d2467..3934028d 100644 --- a/common/src/main/kotlin/me/rhunk/snapenhance/common/scripting/PrimitiveUtil.kt +++ b/common/src/main/kotlin/me/eternal/purrfectsnap/common/scripting/PrimitiveUtil.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.common.scripting +package me.eternal.purrfectsnap.common.scripting fun Any?.toPrimitiveValue(type: Lazy) = when (this) { is Number -> when (type.value) { diff --git a/common/src/main/kotlin/me/rhunk/snapenhance/common/scripting/ScriptRuntime.kt b/common/src/main/kotlin/me/eternal/purrfectsnap/common/scripting/ScriptRuntime.kt similarity index 83% rename from common/src/main/kotlin/me/rhunk/snapenhance/common/scripting/ScriptRuntime.kt rename to common/src/main/kotlin/me/eternal/purrfectsnap/common/scripting/ScriptRuntime.kt index 035f6cef..5c3ea2c1 100644 --- a/common/src/main/kotlin/me/rhunk/snapenhance/common/scripting/ScriptRuntime.kt +++ b/common/src/main/kotlin/me/eternal/purrfectsnap/common/scripting/ScriptRuntime.kt @@ -1,12 +1,12 @@ -package me.rhunk.snapenhance.common.scripting +package me.eternal.purrfectsnap.common.scripting import android.content.Context import android.os.ParcelFileDescriptor -import me.rhunk.snapenhance.bridge.scripting.IScripting -import me.rhunk.snapenhance.common.BuildConfig -import me.rhunk.snapenhance.common.config.impl.RootConfig -import me.rhunk.snapenhance.common.logger.AbstractLogger -import me.rhunk.snapenhance.common.scripting.type.readModuleInfo +import me.eternal.purrfectsnap.bridge.scripting.IScripting +import me.eternal.purrfectsnap.common.BuildConfig +import me.eternal.purrfectsnap.common.config.impl.RootConfig +import me.eternal.purrfectsnap.common.logger.AbstractLogger +import me.eternal.purrfectsnap.common.scripting.type.readModuleInfo import org.mozilla.javascript.ScriptableObject import java.io.InputStream @@ -59,7 +59,7 @@ open class ScriptRuntime( val moduleInfo = bufferedReader.readModuleInfo() if (moduleInfo.minSEVersion != null && moduleInfo.minSEVersion > BuildConfig.VERSION_CODE) { - throw Exception("Module requires a newer version of SnapEnhance (min version: ${moduleInfo.minSEVersion})") + throw Exception("Module requires a newer version of PurrfectSnap (min version: ${moduleInfo.minSEVersion})") } return JSModule( diff --git a/common/src/main/kotlin/me/rhunk/snapenhance/common/scripting/ScriptingLogger.kt b/common/src/main/kotlin/me/eternal/purrfectsnap/common/scripting/ScriptingLogger.kt similarity index 83% rename from common/src/main/kotlin/me/rhunk/snapenhance/common/scripting/ScriptingLogger.kt rename to common/src/main/kotlin/me/eternal/purrfectsnap/common/scripting/ScriptingLogger.kt index f9406095..e6337c98 100644 --- a/common/src/main/kotlin/me/rhunk/snapenhance/common/scripting/ScriptingLogger.kt +++ b/common/src/main/kotlin/me/eternal/purrfectsnap/common/scripting/ScriptingLogger.kt @@ -1,7 +1,7 @@ -package me.rhunk.snapenhance.common.scripting +package me.eternal.purrfectsnap.common.scripting -import me.rhunk.snapenhance.common.logger.AbstractLogger -import me.rhunk.snapenhance.common.logger.LogChannel +import me.eternal.purrfectsnap.common.logger.AbstractLogger +import me.eternal.purrfectsnap.common.logger.LogChannel class ScriptingLogger( private val logger: AbstractLogger diff --git a/common/src/main/kotlin/me/rhunk/snapenhance/common/scripting/bindings/AbstractBinding.kt b/common/src/main/kotlin/me/eternal/purrfectsnap/common/scripting/bindings/AbstractBinding.kt similarity index 88% rename from common/src/main/kotlin/me/rhunk/snapenhance/common/scripting/bindings/AbstractBinding.kt rename to common/src/main/kotlin/me/eternal/purrfectsnap/common/scripting/bindings/AbstractBinding.kt index 2558fa39..385e443a 100644 --- a/common/src/main/kotlin/me/rhunk/snapenhance/common/scripting/bindings/AbstractBinding.kt +++ b/common/src/main/kotlin/me/eternal/purrfectsnap/common/scripting/bindings/AbstractBinding.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.common.scripting.bindings +package me.eternal.purrfectsnap.common.scripting.bindings abstract class AbstractBinding( val name: String, diff --git a/common/src/main/kotlin/me/rhunk/snapenhance/common/scripting/bindings/BindingSide.kt b/common/src/main/kotlin/me/eternal/purrfectsnap/common/scripting/bindings/BindingSide.kt similarity index 82% rename from common/src/main/kotlin/me/rhunk/snapenhance/common/scripting/bindings/BindingSide.kt rename to common/src/main/kotlin/me/eternal/purrfectsnap/common/scripting/bindings/BindingSide.kt index 2ab8c971..83af1562 100644 --- a/common/src/main/kotlin/me/rhunk/snapenhance/common/scripting/bindings/BindingSide.kt +++ b/common/src/main/kotlin/me/eternal/purrfectsnap/common/scripting/bindings/BindingSide.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.common.scripting.bindings +package me.eternal.purrfectsnap.common.scripting.bindings enum class BindingSide( val key: String diff --git a/common/src/main/kotlin/me/eternal/purrfectsnap/common/scripting/bindings/BindingsContext.kt b/common/src/main/kotlin/me/eternal/purrfectsnap/common/scripting/bindings/BindingsContext.kt new file mode 100644 index 00000000..8724802c --- /dev/null +++ b/common/src/main/kotlin/me/eternal/purrfectsnap/common/scripting/bindings/BindingsContext.kt @@ -0,0 +1,11 @@ +package me.eternal.purrfectsnap.common.scripting.bindings + +import me.eternal.purrfectsnap.common.scripting.JSModule +import me.eternal.purrfectsnap.common.scripting.ScriptRuntime +import me.eternal.purrfectsnap.common.scripting.type.ModuleInfo + +class BindingsContext( + val moduleInfo: ModuleInfo, + val runtime: ScriptRuntime, + val module: JSModule +) \ No newline at end of file diff --git a/common/src/main/kotlin/me/rhunk/snapenhance/common/scripting/impl/ConfigInterface.kt b/common/src/main/kotlin/me/eternal/purrfectsnap/common/scripting/impl/ConfigInterface.kt similarity index 94% rename from common/src/main/kotlin/me/rhunk/snapenhance/common/scripting/impl/ConfigInterface.kt rename to common/src/main/kotlin/me/eternal/purrfectsnap/common/scripting/impl/ConfigInterface.kt index a0069c1b..b57a4e4f 100644 --- a/common/src/main/kotlin/me/rhunk/snapenhance/common/scripting/impl/ConfigInterface.kt +++ b/common/src/main/kotlin/me/eternal/purrfectsnap/common/scripting/impl/ConfigInterface.kt @@ -1,7 +1,7 @@ -package me.rhunk.snapenhance.common.scripting.impl +package me.eternal.purrfectsnap.common.scripting.impl -import me.rhunk.snapenhance.common.scripting.bindings.AbstractBinding -import me.rhunk.snapenhance.common.scripting.bindings.BindingSide +import me.eternal.purrfectsnap.common.scripting.bindings.AbstractBinding +import me.eternal.purrfectsnap.common.scripting.bindings.BindingSide import org.mozilla.javascript.annotations.JSFunction diff --git a/common/src/main/kotlin/me/rhunk/snapenhance/common/scripting/impl/IPCInterface.kt b/common/src/main/kotlin/me/eternal/purrfectsnap/common/scripting/impl/IPCInterface.kt similarity index 81% rename from common/src/main/kotlin/me/rhunk/snapenhance/common/scripting/impl/IPCInterface.kt rename to common/src/main/kotlin/me/eternal/purrfectsnap/common/scripting/impl/IPCInterface.kt index 4be46454..b32b3c36 100644 --- a/common/src/main/kotlin/me/rhunk/snapenhance/common/scripting/impl/IPCInterface.kt +++ b/common/src/main/kotlin/me/eternal/purrfectsnap/common/scripting/impl/IPCInterface.kt @@ -1,7 +1,7 @@ -package me.rhunk.snapenhance.common.scripting.impl +package me.eternal.purrfectsnap.common.scripting.impl -import me.rhunk.snapenhance.common.scripting.bindings.AbstractBinding -import me.rhunk.snapenhance.common.scripting.bindings.BindingSide +import me.eternal.purrfectsnap.common.scripting.bindings.AbstractBinding +import me.eternal.purrfectsnap.common.scripting.bindings.BindingSide import org.mozilla.javascript.annotations.JSFunction typealias Listener = (List) -> Unit diff --git a/common/src/main/kotlin/me/rhunk/snapenhance/common/scripting/impl/JavaInterfaces.kt b/common/src/main/kotlin/me/eternal/purrfectsnap/common/scripting/impl/JavaInterfaces.kt similarity index 82% rename from common/src/main/kotlin/me/rhunk/snapenhance/common/scripting/impl/JavaInterfaces.kt rename to common/src/main/kotlin/me/eternal/purrfectsnap/common/scripting/impl/JavaInterfaces.kt index 457d8f5d..a816b8d5 100644 --- a/common/src/main/kotlin/me/rhunk/snapenhance/common/scripting/impl/JavaInterfaces.kt +++ b/common/src/main/kotlin/me/eternal/purrfectsnap/common/scripting/impl/JavaInterfaces.kt @@ -1,10 +1,10 @@ -package me.rhunk.snapenhance.common.scripting.impl +package me.eternal.purrfectsnap.common.scripting.impl -import me.rhunk.snapenhance.common.scripting.bindings.AbstractBinding -import me.rhunk.snapenhance.common.scripting.bindings.BindingSide -import me.rhunk.snapenhance.common.scripting.ktx.contextScope -import me.rhunk.snapenhance.common.scripting.ktx.putFunction -import me.rhunk.snapenhance.common.scripting.ktx.scriptableObject +import me.eternal.purrfectsnap.common.scripting.bindings.AbstractBinding +import me.eternal.purrfectsnap.common.scripting.bindings.BindingSide +import me.eternal.purrfectsnap.common.scripting.ktx.contextScope +import me.eternal.purrfectsnap.common.scripting.ktx.putFunction +import me.eternal.purrfectsnap.common.scripting.ktx.scriptableObject import java.lang.reflect.Proxy import kotlin.concurrent.thread diff --git a/common/src/main/kotlin/me/rhunk/snapenhance/common/scripting/impl/Networking.kt b/common/src/main/kotlin/me/eternal/purrfectsnap/common/scripting/impl/Networking.kt similarity index 96% rename from common/src/main/kotlin/me/rhunk/snapenhance/common/scripting/impl/Networking.kt rename to common/src/main/kotlin/me/eternal/purrfectsnap/common/scripting/impl/Networking.kt index 8a497bf8..b3071e49 100644 --- a/common/src/main/kotlin/me/rhunk/snapenhance/common/scripting/impl/Networking.kt +++ b/common/src/main/kotlin/me/eternal/purrfectsnap/common/scripting/impl/Networking.kt @@ -1,8 +1,8 @@ -package me.rhunk.snapenhance.common.scripting.impl +package me.eternal.purrfectsnap.common.scripting.impl -import me.rhunk.snapenhance.common.scripting.bindings.AbstractBinding -import me.rhunk.snapenhance.common.scripting.bindings.BindingSide -import me.rhunk.snapenhance.common.scripting.ktx.contextScope +import me.eternal.purrfectsnap.common.scripting.bindings.AbstractBinding +import me.eternal.purrfectsnap.common.scripting.bindings.BindingSide +import me.eternal.purrfectsnap.common.scripting.ktx.contextScope import okhttp3.OkHttpClient import okhttp3.Request import okhttp3.RequestBody.Companion.toRequestBody diff --git a/common/src/main/kotlin/me/rhunk/snapenhance/common/scripting/impl/Protobuf.kt b/common/src/main/kotlin/me/eternal/purrfectsnap/common/scripting/impl/Protobuf.kt similarity index 82% rename from common/src/main/kotlin/me/rhunk/snapenhance/common/scripting/impl/Protobuf.kt rename to common/src/main/kotlin/me/eternal/purrfectsnap/common/scripting/impl/Protobuf.kt index da8aa678..a0dd33d3 100644 --- a/common/src/main/kotlin/me/rhunk/snapenhance/common/scripting/impl/Protobuf.kt +++ b/common/src/main/kotlin/me/eternal/purrfectsnap/common/scripting/impl/Protobuf.kt @@ -1,10 +1,10 @@ -package me.rhunk.snapenhance.common.scripting.impl +package me.eternal.purrfectsnap.common.scripting.impl -import me.rhunk.snapenhance.common.scripting.bindings.AbstractBinding -import me.rhunk.snapenhance.common.scripting.bindings.BindingSide -import me.rhunk.snapenhance.common.scripting.ktx.putFunction -import me.rhunk.snapenhance.common.scripting.ktx.scriptableObject -import me.rhunk.snapenhance.common.util.protobuf.* +import me.eternal.purrfectsnap.common.scripting.bindings.AbstractBinding +import me.eternal.purrfectsnap.common.scripting.bindings.BindingSide +import me.eternal.purrfectsnap.common.scripting.ktx.putFunction +import me.eternal.purrfectsnap.common.scripting.ktx.scriptableObject +import me.eternal.purrfectsnap.common.util.protobuf.* import org.mozilla.javascript.NativeArray import java.io.InputStream diff --git a/common/src/main/kotlin/me/rhunk/snapenhance/common/scripting/ktx/RhinoKtx.kt b/common/src/main/kotlin/me/eternal/purrfectsnap/common/scripting/ktx/RhinoKtx.kt similarity index 97% rename from common/src/main/kotlin/me/rhunk/snapenhance/common/scripting/ktx/RhinoKtx.kt rename to common/src/main/kotlin/me/eternal/purrfectsnap/common/scripting/ktx/RhinoKtx.kt index cee4018a..83f89a6e 100644 --- a/common/src/main/kotlin/me/rhunk/snapenhance/common/scripting/ktx/RhinoKtx.kt +++ b/common/src/main/kotlin/me/eternal/purrfectsnap/common/scripting/ktx/RhinoKtx.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.common.scripting.ktx +package me.eternal.purrfectsnap.common.scripting.ktx import com.faendir.rhino_android.RhinoAndroidHelper import org.mozilla.javascript.* diff --git a/common/src/main/kotlin/me/rhunk/snapenhance/common/scripting/type/ModuleInfo.kt b/common/src/main/kotlin/me/eternal/purrfectsnap/common/scripting/type/ModuleInfo.kt similarity index 97% rename from common/src/main/kotlin/me/rhunk/snapenhance/common/scripting/type/ModuleInfo.kt rename to common/src/main/kotlin/me/eternal/purrfectsnap/common/scripting/type/ModuleInfo.kt index 8bb4e456..9d9a6489 100644 --- a/common/src/main/kotlin/me/rhunk/snapenhance/common/scripting/type/ModuleInfo.kt +++ b/common/src/main/kotlin/me/eternal/purrfectsnap/common/scripting/type/ModuleInfo.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.common.scripting.type +package me.eternal.purrfectsnap.common.scripting.type import java.io.BufferedReader diff --git a/common/src/main/kotlin/me/rhunk/snapenhance/common/scripting/type/Permissions.kt b/common/src/main/kotlin/me/eternal/purrfectsnap/common/scripting/type/Permissions.kt similarity index 64% rename from common/src/main/kotlin/me/rhunk/snapenhance/common/scripting/type/Permissions.kt rename to common/src/main/kotlin/me/eternal/purrfectsnap/common/scripting/type/Permissions.kt index 811b832b..98df938f 100644 --- a/common/src/main/kotlin/me/rhunk/snapenhance/common/scripting/type/Permissions.kt +++ b/common/src/main/kotlin/me/eternal/purrfectsnap/common/scripting/type/Permissions.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.common.scripting.type +package me.eternal.purrfectsnap.common.scripting.type enum class Permissions( val key: String, diff --git a/common/src/main/kotlin/me/rhunk/snapenhance/common/scripting/ui/EnumScriptInterface.kt b/common/src/main/kotlin/me/eternal/purrfectsnap/common/scripting/ui/EnumScriptInterface.kt similarity index 69% rename from common/src/main/kotlin/me/rhunk/snapenhance/common/scripting/ui/EnumScriptInterface.kt rename to common/src/main/kotlin/me/eternal/purrfectsnap/common/scripting/ui/EnumScriptInterface.kt index 6a10f02d..134fd234 100644 --- a/common/src/main/kotlin/me/rhunk/snapenhance/common/scripting/ui/EnumScriptInterface.kt +++ b/common/src/main/kotlin/me/eternal/purrfectsnap/common/scripting/ui/EnumScriptInterface.kt @@ -1,6 +1,6 @@ -package me.rhunk.snapenhance.common.scripting.ui +package me.eternal.purrfectsnap.common.scripting.ui -import me.rhunk.snapenhance.common.scripting.bindings.BindingSide +import me.eternal.purrfectsnap.common.scripting.bindings.BindingSide enum class EnumScriptInterface( val key: String, diff --git a/common/src/main/kotlin/me/rhunk/snapenhance/common/scripting/ui/InterfaceManager.kt b/common/src/main/kotlin/me/eternal/purrfectsnap/common/scripting/ui/InterfaceManager.kt similarity index 84% rename from common/src/main/kotlin/me/rhunk/snapenhance/common/scripting/ui/InterfaceManager.kt rename to common/src/main/kotlin/me/eternal/purrfectsnap/common/scripting/ui/InterfaceManager.kt index 977ac253..cebbd7e9 100644 --- a/common/src/main/kotlin/me/rhunk/snapenhance/common/scripting/ui/InterfaceManager.kt +++ b/common/src/main/kotlin/me/eternal/purrfectsnap/common/scripting/ui/InterfaceManager.kt @@ -1,19 +1,19 @@ -package me.rhunk.snapenhance.common.scripting.ui +package me.eternal.purrfectsnap.common.scripting.ui import android.app.Activity import android.app.AlertDialog import androidx.compose.runtime.remember -import me.rhunk.snapenhance.common.scripting.bindings.AbstractBinding -import me.rhunk.snapenhance.common.scripting.bindings.BindingSide -import me.rhunk.snapenhance.common.scripting.ktx.contextScope -import me.rhunk.snapenhance.common.scripting.ktx.scriptableObject -import me.rhunk.snapenhance.common.scripting.ui.components.Node -import me.rhunk.snapenhance.common.scripting.ui.components.NodeType -import me.rhunk.snapenhance.common.scripting.ui.components.impl.ActionNode -import me.rhunk.snapenhance.common.scripting.ui.components.impl.ActionType -import me.rhunk.snapenhance.common.scripting.ui.components.impl.RowColumnNode -import me.rhunk.snapenhance.common.scripting.ui.components.impl.TextInputNode -import me.rhunk.snapenhance.common.ui.createComposeAlertDialog +import me.eternal.purrfectsnap.common.scripting.bindings.AbstractBinding +import me.eternal.purrfectsnap.common.scripting.bindings.BindingSide +import me.eternal.purrfectsnap.common.scripting.ktx.contextScope +import me.eternal.purrfectsnap.common.scripting.ktx.scriptableObject +import me.eternal.purrfectsnap.common.scripting.ui.components.Node +import me.eternal.purrfectsnap.common.scripting.ui.components.NodeType +import me.eternal.purrfectsnap.common.scripting.ui.components.impl.ActionNode +import me.eternal.purrfectsnap.common.scripting.ui.components.impl.ActionType +import me.eternal.purrfectsnap.common.scripting.ui.components.impl.RowColumnNode +import me.eternal.purrfectsnap.common.scripting.ui.components.impl.TextInputNode +import me.eternal.purrfectsnap.common.ui.createComposeAlertDialog import org.mozilla.javascript.Function import org.mozilla.javascript.annotations.JSFunction diff --git a/common/src/main/kotlin/me/rhunk/snapenhance/common/scripting/ui/ScriptInterface.kt b/common/src/main/kotlin/me/eternal/purrfectsnap/common/scripting/ui/ScriptInterface.kt similarity index 95% rename from common/src/main/kotlin/me/rhunk/snapenhance/common/scripting/ui/ScriptInterface.kt rename to common/src/main/kotlin/me/eternal/purrfectsnap/common/scripting/ui/ScriptInterface.kt index 27745b43..37cf67ea 100644 --- a/common/src/main/kotlin/me/rhunk/snapenhance/common/scripting/ui/ScriptInterface.kt +++ b/common/src/main/kotlin/me/eternal/purrfectsnap/common/scripting/ui/ScriptInterface.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.common.scripting.ui +package me.eternal.purrfectsnap.common.scripting.ui import androidx.compose.animation.AnimatedVisibility import androidx.compose.foundation.layout.* @@ -14,11 +14,11 @@ import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import kotlinx.coroutines.launch -import me.rhunk.snapenhance.common.logger.AbstractLogger -import me.rhunk.snapenhance.common.scripting.ui.components.Node -import me.rhunk.snapenhance.common.scripting.ui.components.NodeType -import me.rhunk.snapenhance.common.scripting.ui.components.impl.ActionNode -import me.rhunk.snapenhance.common.scripting.ui.components.impl.ActionType +import me.eternal.purrfectsnap.common.logger.AbstractLogger +import me.eternal.purrfectsnap.common.scripting.ui.components.Node +import me.eternal.purrfectsnap.common.scripting.ui.components.NodeType +import me.eternal.purrfectsnap.common.scripting.ui.components.impl.ActionNode +import me.eternal.purrfectsnap.common.scripting.ui.components.impl.ActionType import kotlin.math.abs diff --git a/common/src/main/kotlin/me/rhunk/snapenhance/common/scripting/ui/components/Node.kt b/common/src/main/kotlin/me/eternal/purrfectsnap/common/scripting/ui/components/Node.kt similarity index 95% rename from common/src/main/kotlin/me/rhunk/snapenhance/common/scripting/ui/components/Node.kt rename to common/src/main/kotlin/me/eternal/purrfectsnap/common/scripting/ui/components/Node.kt index c7a01c78..6efd00a8 100644 --- a/common/src/main/kotlin/me/rhunk/snapenhance/common/scripting/ui/components/Node.kt +++ b/common/src/main/kotlin/me/eternal/purrfectsnap/common/scripting/ui/components/Node.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.common.scripting.ui.components +package me.eternal.purrfectsnap.common.scripting.ui.components @Suppress("MemberVisibilityCanBePrivate") open class Node( diff --git a/common/src/main/kotlin/me/rhunk/snapenhance/common/scripting/ui/components/NodeType.kt b/common/src/main/kotlin/me/eternal/purrfectsnap/common/scripting/ui/components/NodeType.kt similarity index 67% rename from common/src/main/kotlin/me/rhunk/snapenhance/common/scripting/ui/components/NodeType.kt rename to common/src/main/kotlin/me/eternal/purrfectsnap/common/scripting/ui/components/NodeType.kt index 21b97136..f0c22551 100644 --- a/common/src/main/kotlin/me/rhunk/snapenhance/common/scripting/ui/components/NodeType.kt +++ b/common/src/main/kotlin/me/eternal/purrfectsnap/common/scripting/ui/components/NodeType.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.common.scripting.ui.components +package me.eternal.purrfectsnap.common.scripting.ui.components enum class NodeType { ROW, diff --git a/common/src/main/kotlin/me/eternal/purrfectsnap/common/scripting/ui/components/impl/ActionNode.kt b/common/src/main/kotlin/me/eternal/purrfectsnap/common/scripting/ui/components/impl/ActionNode.kt new file mode 100644 index 00000000..4c585451 --- /dev/null +++ b/common/src/main/kotlin/me/eternal/purrfectsnap/common/scripting/ui/components/impl/ActionNode.kt @@ -0,0 +1,15 @@ +package me.eternal.purrfectsnap.common.scripting.ui.components.impl + +import me.eternal.purrfectsnap.common.scripting.ui.components.Node +import me.eternal.purrfectsnap.common.scripting.ui.components.NodeType + +enum class ActionType { + LAUNCHED, + DISPOSE +} + +class ActionNode( + val actionType: ActionType, + val key: Any = Unit, + val callback: () -> Unit +): Node(NodeType.ACTION) \ No newline at end of file diff --git a/common/src/main/kotlin/me/rhunk/snapenhance/common/scripting/ui/components/impl/RowColumnNode.kt b/common/src/main/kotlin/me/eternal/purrfectsnap/common/scripting/ui/components/impl/RowColumnNode.kt similarity index 87% rename from common/src/main/kotlin/me/rhunk/snapenhance/common/scripting/ui/components/impl/RowColumnNode.kt rename to common/src/main/kotlin/me/eternal/purrfectsnap/common/scripting/ui/components/impl/RowColumnNode.kt index 131d8ecc..348d92b4 100644 --- a/common/src/main/kotlin/me/rhunk/snapenhance/common/scripting/ui/components/impl/RowColumnNode.kt +++ b/common/src/main/kotlin/me/eternal/purrfectsnap/common/scripting/ui/components/impl/RowColumnNode.kt @@ -1,9 +1,9 @@ -package me.rhunk.snapenhance.common.scripting.ui.components.impl +package me.eternal.purrfectsnap.common.scripting.ui.components.impl import androidx.compose.foundation.layout.Arrangement import androidx.compose.ui.Alignment -import me.rhunk.snapenhance.common.scripting.ui.components.Node -import me.rhunk.snapenhance.common.scripting.ui.components.NodeType +import me.eternal.purrfectsnap.common.scripting.ui.components.Node +import me.eternal.purrfectsnap.common.scripting.ui.components.NodeType class RowColumnNode( diff --git a/common/src/main/kotlin/me/rhunk/snapenhance/common/scripting/ui/components/impl/TextInputNode.kt b/common/src/main/kotlin/me/eternal/purrfectsnap/common/scripting/ui/components/impl/TextInputNode.kt similarity index 78% rename from common/src/main/kotlin/me/rhunk/snapenhance/common/scripting/ui/components/impl/TextInputNode.kt rename to common/src/main/kotlin/me/eternal/purrfectsnap/common/scripting/ui/components/impl/TextInputNode.kt index 300f173e..ca109abf 100644 --- a/common/src/main/kotlin/me/rhunk/snapenhance/common/scripting/ui/components/impl/TextInputNode.kt +++ b/common/src/main/kotlin/me/eternal/purrfectsnap/common/scripting/ui/components/impl/TextInputNode.kt @@ -1,7 +1,7 @@ -package me.rhunk.snapenhance.common.scripting.ui.components.impl +package me.eternal.purrfectsnap.common.scripting.ui.components.impl -import me.rhunk.snapenhance.common.scripting.ui.components.Node -import me.rhunk.snapenhance.common.scripting.ui.components.NodeType +import me.eternal.purrfectsnap.common.scripting.ui.components.Node +import me.eternal.purrfectsnap.common.scripting.ui.components.NodeType class TextInputNode : Node(NodeType.TEXT_INPUT) { fun placeholder(text: String): TextInputNode { diff --git a/common/src/main/kotlin/me/rhunk/snapenhance/common/ui/AsyncMutableState.kt b/common/src/main/kotlin/me/eternal/purrfectsnap/common/ui/AsyncMutableState.kt similarity index 98% rename from common/src/main/kotlin/me/rhunk/snapenhance/common/ui/AsyncMutableState.kt rename to common/src/main/kotlin/me/eternal/purrfectsnap/common/ui/AsyncMutableState.kt index 6fd21488..a55333a4 100644 --- a/common/src/main/kotlin/me/rhunk/snapenhance/common/ui/AsyncMutableState.kt +++ b/common/src/main/kotlin/me/eternal/purrfectsnap/common/ui/AsyncMutableState.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.common.ui +package me.eternal.purrfectsnap.common.ui import androidx.compose.runtime.* import androidx.compose.runtime.snapshots.SnapshotStateList diff --git a/common/src/main/kotlin/me/rhunk/snapenhance/common/ui/Components.kt b/common/src/main/kotlin/me/eternal/purrfectsnap/common/ui/Components.kt similarity index 95% rename from common/src/main/kotlin/me/rhunk/snapenhance/common/ui/Components.kt rename to common/src/main/kotlin/me/eternal/purrfectsnap/common/ui/Components.kt index 962d9054..38e4ee08 100644 --- a/common/src/main/kotlin/me/rhunk/snapenhance/common/ui/Components.kt +++ b/common/src/main/kotlin/me/eternal/purrfectsnap/common/ui/Components.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.common.ui +package me.eternal.purrfectsnap.common.ui import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Row @@ -19,7 +19,7 @@ import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp -import me.rhunk.snapenhance.common.bridge.wrapper.LocaleWrapper +import me.eternal.purrfectsnap.common.bridge.wrapper.LocaleWrapper @Composable @@ -72,4 +72,4 @@ fun TopBarActionButton( Text(text = text, overflow = TextOverflow.Ellipsis) } } -} \ No newline at end of file +} diff --git a/common/src/main/kotlin/me/rhunk/snapenhance/common/ui/ComposeViewFactory.kt b/common/src/main/kotlin/me/eternal/purrfectsnap/common/ui/ComposeViewFactory.kt similarity index 94% rename from common/src/main/kotlin/me/rhunk/snapenhance/common/ui/ComposeViewFactory.kt rename to common/src/main/kotlin/me/eternal/purrfectsnap/common/ui/ComposeViewFactory.kt index b44376c3..fa319841 100644 --- a/common/src/main/kotlin/me/rhunk/snapenhance/common/ui/ComposeViewFactory.kt +++ b/common/src/main/kotlin/me/eternal/purrfectsnap/common/ui/ComposeViewFactory.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.common.ui +package me.eternal.purrfectsnap.common.ui import android.app.AlertDialog import android.content.Context @@ -9,14 +9,12 @@ import android.view.WindowManager import androidx.activity.OnBackPressedDispatcher import androidx.activity.OnBackPressedDispatcherOwner import androidx.activity.setViewTreeOnBackPressedDispatcherOwner +import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Surface import androidx.compose.runtime.Composable import androidx.compose.runtime.Recomposer import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.clip import androidx.compose.ui.platform.AndroidUiDispatcher import androidx.compose.ui.platform.ComposeView import androidx.compose.ui.platform.ViewCompositionStrategy @@ -79,12 +77,10 @@ fun createComposeAlertDialog(context: Context, builder: AlertDialog.Builder.() - return AlertDialog.Builder(context) .apply(builder) .setView(createComposeView(context) { - Surface( + Box( modifier = Modifier .fillMaxWidth() .padding(8.dp) - .clip(MaterialTheme.shapes.large), - color = MaterialTheme.colorScheme.surface ) { content(alertDialog) } @@ -122,4 +118,4 @@ private class OverlayLifecycleOwner : SavedStateRegistryOwner { fun performSave(outBundle: Bundle) { mSavedStateRegistryController.performSave(outBundle) } -} \ No newline at end of file +} diff --git a/common/src/main/kotlin/me/rhunk/snapenhance/common/ui/Keyboard.kt b/common/src/main/kotlin/me/eternal/purrfectsnap/common/ui/Keyboard.kt similarity index 97% rename from common/src/main/kotlin/me/rhunk/snapenhance/common/ui/Keyboard.kt rename to common/src/main/kotlin/me/eternal/purrfectsnap/common/ui/Keyboard.kt index 561ff46c..a954ddcc 100644 --- a/common/src/main/kotlin/me/rhunk/snapenhance/common/ui/Keyboard.kt +++ b/common/src/main/kotlin/me/eternal/purrfectsnap/common/ui/Keyboard.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.common.ui +package me.eternal.purrfectsnap.common.ui import android.view.ViewTreeObserver diff --git a/common/src/main/kotlin/me/rhunk/snapenhance/common/ui/OverlayType.kt b/common/src/main/kotlin/me/eternal/purrfectsnap/common/ui/OverlayType.kt similarity index 85% rename from common/src/main/kotlin/me/rhunk/snapenhance/common/ui/OverlayType.kt rename to common/src/main/kotlin/me/eternal/purrfectsnap/common/ui/OverlayType.kt index a8ff8899..41f75376 100644 --- a/common/src/main/kotlin/me/rhunk/snapenhance/common/ui/OverlayType.kt +++ b/common/src/main/kotlin/me/eternal/purrfectsnap/common/ui/OverlayType.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.common.ui +package me.eternal.purrfectsnap.common.ui enum class OverlayType( val key: String diff --git a/common/src/main/kotlin/me/rhunk/snapenhance/common/ui/TextFieldColors.kt b/common/src/main/kotlin/me/eternal/purrfectsnap/common/ui/TextFieldColors.kt similarity index 93% rename from common/src/main/kotlin/me/rhunk/snapenhance/common/ui/TextFieldColors.kt rename to common/src/main/kotlin/me/eternal/purrfectsnap/common/ui/TextFieldColors.kt index 6500125b..64119197 100644 --- a/common/src/main/kotlin/me/rhunk/snapenhance/common/ui/TextFieldColors.kt +++ b/common/src/main/kotlin/me/eternal/purrfectsnap/common/ui/TextFieldColors.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.common.ui +package me.eternal.purrfectsnap.common.ui import androidx.compose.material3.MaterialTheme import androidx.compose.material3.TextFieldDefaults diff --git a/common/src/main/kotlin/me/rhunk/snapenhance/common/ui/Theme.kt b/common/src/main/kotlin/me/eternal/purrfectsnap/common/ui/Theme.kt similarity index 99% rename from common/src/main/kotlin/me/rhunk/snapenhance/common/ui/Theme.kt rename to common/src/main/kotlin/me/eternal/purrfectsnap/common/ui/Theme.kt index 1c5e2914..691f7a60 100644 --- a/common/src/main/kotlin/me/rhunk/snapenhance/common/ui/Theme.kt +++ b/common/src/main/kotlin/me/eternal/purrfectsnap/common/ui/Theme.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.common.ui +package me.eternal.purrfectsnap.common.ui import android.os.Build import androidx.compose.foundation.isSystemInDarkTheme diff --git a/common/src/main/kotlin/me/rhunk/snapenhance/common/ui/ThemeChooserDialog.kt b/common/src/main/kotlin/me/eternal/purrfectsnap/common/ui/ThemeChooserDialog.kt similarity index 98% rename from common/src/main/kotlin/me/rhunk/snapenhance/common/ui/ThemeChooserDialog.kt rename to common/src/main/kotlin/me/eternal/purrfectsnap/common/ui/ThemeChooserDialog.kt index e1d5831a..f8b3e55c 100644 --- a/common/src/main/kotlin/me/rhunk/snapenhance/common/ui/ThemeChooserDialog.kt +++ b/common/src/main/kotlin/me/eternal/purrfectsnap/common/ui/ThemeChooserDialog.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.common.ui +package me.eternal.purrfectsnap.common.ui import androidx.compose.foundation.background import androidx.compose.foundation.clickable diff --git a/common/src/main/kotlin/me/rhunk/snapenhance/common/ui/ThemeMode.kt b/common/src/main/kotlin/me/eternal/purrfectsnap/common/ui/ThemeMode.kt similarity index 76% rename from common/src/main/kotlin/me/rhunk/snapenhance/common/ui/ThemeMode.kt rename to common/src/main/kotlin/me/eternal/purrfectsnap/common/ui/ThemeMode.kt index fac76473..c56c2c43 100644 --- a/common/src/main/kotlin/me/rhunk/snapenhance/common/ui/ThemeMode.kt +++ b/common/src/main/kotlin/me/eternal/purrfectsnap/common/ui/ThemeMode.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.common.ui +package me.eternal.purrfectsnap.common.ui enum class ThemeMode(val displayName: String) { SYSTEM("System Default"), diff --git a/common/src/main/kotlin/me/rhunk/snapenhance/common/ui/ThemePreferences.kt b/common/src/main/kotlin/me/eternal/purrfectsnap/common/ui/ThemePreferences.kt similarity index 95% rename from common/src/main/kotlin/me/rhunk/snapenhance/common/ui/ThemePreferences.kt rename to common/src/main/kotlin/me/eternal/purrfectsnap/common/ui/ThemePreferences.kt index fc68f753..a3c3ff74 100644 --- a/common/src/main/kotlin/me/rhunk/snapenhance/common/ui/ThemePreferences.kt +++ b/common/src/main/kotlin/me/eternal/purrfectsnap/common/ui/ThemePreferences.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.common.ui +package me.eternal.purrfectsnap.common.ui import android.content.Context import androidx.datastore.preferences.core.edit diff --git a/common/src/main/kotlin/me/rhunk/snapenhance/common/util/LazyBridge.kt b/common/src/main/kotlin/me/eternal/purrfectsnap/common/util/LazyBridge.kt similarity index 96% rename from common/src/main/kotlin/me/rhunk/snapenhance/common/util/LazyBridge.kt rename to common/src/main/kotlin/me/eternal/purrfectsnap/common/util/LazyBridge.kt index 0750ac85..852672f5 100644 --- a/common/src/main/kotlin/me/rhunk/snapenhance/common/util/LazyBridge.kt +++ b/common/src/main/kotlin/me/eternal/purrfectsnap/common/util/LazyBridge.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.common.util +package me.eternal.purrfectsnap.common.util import android.os.IInterface diff --git a/common/src/main/kotlin/me/rhunk/snapenhance/common/util/ParcelableExt.kt b/common/src/main/kotlin/me/eternal/purrfectsnap/common/util/ParcelableExt.kt similarity index 95% rename from common/src/main/kotlin/me/rhunk/snapenhance/common/util/ParcelableExt.kt rename to common/src/main/kotlin/me/eternal/purrfectsnap/common/util/ParcelableExt.kt index bca51c4e..749ec5d8 100644 --- a/common/src/main/kotlin/me/rhunk/snapenhance/common/util/ParcelableExt.kt +++ b/common/src/main/kotlin/me/eternal/purrfectsnap/common/util/ParcelableExt.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.common.util +package me.eternal.purrfectsnap.common.util import android.os.Parcelable import kotlinx.parcelize.parcelableCreator diff --git a/common/src/main/kotlin/me/rhunk/snapenhance/common/util/Purge.kt b/common/src/main/kotlin/me/eternal/purrfectsnap/common/util/Purge.kt similarity index 94% rename from common/src/main/kotlin/me/rhunk/snapenhance/common/util/Purge.kt rename to common/src/main/kotlin/me/eternal/purrfectsnap/common/util/Purge.kt index 3807b4c4..8d756017 100644 --- a/common/src/main/kotlin/me/rhunk/snapenhance/common/util/Purge.kt +++ b/common/src/main/kotlin/me/eternal/purrfectsnap/common/util/Purge.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.common.util +package me.eternal.purrfectsnap.common.util val PURGE_VALUES = arrayOf("1_hour", "3_hours", "6_hours", "12_hours", "1_day", "3_days", "1_week", "2_weeks", "1_month", "3_months", "6_months") const val PURGE_TRANSLATION_KEY = "features.options.auto_purge" diff --git a/common/src/main/kotlin/me/rhunk/snapenhance/common/util/SQLiteDatabaseHelper.kt b/common/src/main/kotlin/me/eternal/purrfectsnap/common/util/SQLiteDatabaseHelper.kt similarity index 92% rename from common/src/main/kotlin/me/rhunk/snapenhance/common/util/SQLiteDatabaseHelper.kt rename to common/src/main/kotlin/me/eternal/purrfectsnap/common/util/SQLiteDatabaseHelper.kt index 7b50e202..f44ac55f 100644 --- a/common/src/main/kotlin/me/rhunk/snapenhance/common/util/SQLiteDatabaseHelper.kt +++ b/common/src/main/kotlin/me/eternal/purrfectsnap/common/util/SQLiteDatabaseHelper.kt @@ -1,8 +1,8 @@ -package me.rhunk.snapenhance.common.util +package me.eternal.purrfectsnap.common.util import android.annotation.SuppressLint import android.database.sqlite.SQLiteDatabase -import me.rhunk.snapenhance.common.logger.AbstractLogger +import me.eternal.purrfectsnap.common.logger.AbstractLogger object SQLiteDatabaseHelper { @SuppressLint("Range") @@ -28,4 +28,4 @@ object SQLiteDatabaseHelper { sqLiteDatabase.execSQL("CREATE TABLE IF NOT EXISTS $tableName (${columns.joinToString(", ")})") } } -} \ No newline at end of file +} diff --git a/common/src/main/kotlin/me/rhunk/snapenhance/common/util/ktx/AndroidCompatExtensions.kt b/common/src/main/kotlin/me/eternal/purrfectsnap/common/util/ktx/AndroidCompatExtensions.kt similarity index 97% rename from common/src/main/kotlin/me/rhunk/snapenhance/common/util/ktx/AndroidCompatExtensions.kt rename to common/src/main/kotlin/me/eternal/purrfectsnap/common/util/ktx/AndroidCompatExtensions.kt index 984b1705..048fb368 100644 --- a/common/src/main/kotlin/me/rhunk/snapenhance/common/util/ktx/AndroidCompatExtensions.kt +++ b/common/src/main/kotlin/me/eternal/purrfectsnap/common/util/ktx/AndroidCompatExtensions.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.common.util.ktx +package me.eternal.purrfectsnap.common.util.ktx import android.content.ClipData import android.content.Context diff --git a/common/src/main/kotlin/me/rhunk/snapenhance/common/util/ktx/DbCursorExt.kt b/common/src/main/kotlin/me/eternal/purrfectsnap/common/util/ktx/DbCursorExt.kt similarity index 96% rename from common/src/main/kotlin/me/rhunk/snapenhance/common/util/ktx/DbCursorExt.kt rename to common/src/main/kotlin/me/eternal/purrfectsnap/common/util/ktx/DbCursorExt.kt index 8a671592..9dd22a3c 100644 --- a/common/src/main/kotlin/me/rhunk/snapenhance/common/util/ktx/DbCursorExt.kt +++ b/common/src/main/kotlin/me/eternal/purrfectsnap/common/util/ktx/DbCursorExt.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.common.util.ktx +package me.eternal.purrfectsnap.common.util.ktx import android.database.Cursor diff --git a/common/src/main/kotlin/me/rhunk/snapenhance/common/util/ktx/JavaExt.kt b/common/src/main/kotlin/me/eternal/purrfectsnap/common/util/ktx/JavaExt.kt similarity index 96% rename from common/src/main/kotlin/me/rhunk/snapenhance/common/util/ktx/JavaExt.kt rename to common/src/main/kotlin/me/eternal/purrfectsnap/common/util/ktx/JavaExt.kt index efbe8e28..fb06efcc 100644 --- a/common/src/main/kotlin/me/rhunk/snapenhance/common/util/ktx/JavaExt.kt +++ b/common/src/main/kotlin/me/eternal/purrfectsnap/common/util/ktx/JavaExt.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.common.util.ktx +package me.eternal.purrfectsnap.common.util.ktx import java.lang.reflect.Field import java.lang.reflect.ParameterizedType diff --git a/common/src/main/kotlin/me/rhunk/snapenhance/common/util/ktx/OkHttp.kt b/common/src/main/kotlin/me/eternal/purrfectsnap/common/util/ktx/OkHttp.kt similarity index 94% rename from common/src/main/kotlin/me/rhunk/snapenhance/common/util/ktx/OkHttp.kt rename to common/src/main/kotlin/me/eternal/purrfectsnap/common/util/ktx/OkHttp.kt index 1560c39b..537a3063 100644 --- a/common/src/main/kotlin/me/rhunk/snapenhance/common/util/ktx/OkHttp.kt +++ b/common/src/main/kotlin/me/eternal/purrfectsnap/common/util/ktx/OkHttp.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.common.util.ktx +package me.eternal.purrfectsnap.common.util.ktx import kotlinx.coroutines.CompletionHandler import kotlinx.coroutines.suspendCancellableCoroutine diff --git a/common/src/main/kotlin/me/rhunk/snapenhance/common/util/protobuf/GrpcReader.kt b/common/src/main/kotlin/me/eternal/purrfectsnap/common/util/protobuf/GrpcReader.kt similarity index 97% rename from common/src/main/kotlin/me/rhunk/snapenhance/common/util/protobuf/GrpcReader.kt rename to common/src/main/kotlin/me/eternal/purrfectsnap/common/util/protobuf/GrpcReader.kt index 10d79c76..03d8a434 100644 --- a/common/src/main/kotlin/me/rhunk/snapenhance/common/util/protobuf/GrpcReader.kt +++ b/common/src/main/kotlin/me/eternal/purrfectsnap/common/util/protobuf/GrpcReader.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.common.util.protobuf +package me.eternal.purrfectsnap.common.util.protobuf import org.mozilla.javascript.annotations.JSFunction diff --git a/common/src/main/kotlin/me/rhunk/snapenhance/common/util/protobuf/GrpcWriter.kt b/common/src/main/kotlin/me/eternal/purrfectsnap/common/util/protobuf/GrpcWriter.kt similarity index 95% rename from common/src/main/kotlin/me/rhunk/snapenhance/common/util/protobuf/GrpcWriter.kt rename to common/src/main/kotlin/me/eternal/purrfectsnap/common/util/protobuf/GrpcWriter.kt index 0b5b9b65..3e597952 100644 --- a/common/src/main/kotlin/me/rhunk/snapenhance/common/util/protobuf/GrpcWriter.kt +++ b/common/src/main/kotlin/me/eternal/purrfectsnap/common/util/protobuf/GrpcWriter.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.common.util.protobuf +package me.eternal.purrfectsnap.common.util.protobuf import org.mozilla.javascript.annotations.JSFunction import java.io.ByteArrayOutputStream diff --git a/common/src/main/kotlin/me/rhunk/snapenhance/common/util/protobuf/ProtoEditor.kt b/common/src/main/kotlin/me/eternal/purrfectsnap/common/util/protobuf/ProtoEditor.kt similarity index 98% rename from common/src/main/kotlin/me/rhunk/snapenhance/common/util/protobuf/ProtoEditor.kt rename to common/src/main/kotlin/me/eternal/purrfectsnap/common/util/protobuf/ProtoEditor.kt index 15821da9..a6096b9b 100644 --- a/common/src/main/kotlin/me/rhunk/snapenhance/common/util/protobuf/ProtoEditor.kt +++ b/common/src/main/kotlin/me/eternal/purrfectsnap/common/util/protobuf/ProtoEditor.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.common.util.protobuf +package me.eternal.purrfectsnap.common.util.protobuf import org.mozilla.javascript.annotations.JSFunction diff --git a/common/src/main/kotlin/me/rhunk/snapenhance/common/util/protobuf/ProtoReader.kt b/common/src/main/kotlin/me/eternal/purrfectsnap/common/util/protobuf/ProtoReader.kt similarity index 99% rename from common/src/main/kotlin/me/rhunk/snapenhance/common/util/protobuf/ProtoReader.kt rename to common/src/main/kotlin/me/eternal/purrfectsnap/common/util/protobuf/ProtoReader.kt index abbf9d46..d8e97a06 100644 --- a/common/src/main/kotlin/me/rhunk/snapenhance/common/util/protobuf/ProtoReader.kt +++ b/common/src/main/kotlin/me/eternal/purrfectsnap/common/util/protobuf/ProtoReader.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.common.util.protobuf +package me.eternal.purrfectsnap.common.util.protobuf import org.mozilla.javascript.annotations.JSFunction import java.nio.ByteBuffer diff --git a/common/src/main/kotlin/me/rhunk/snapenhance/common/util/protobuf/ProtoWriter.kt b/common/src/main/kotlin/me/eternal/purrfectsnap/common/util/protobuf/ProtoWriter.kt similarity index 98% rename from common/src/main/kotlin/me/rhunk/snapenhance/common/util/protobuf/ProtoWriter.kt rename to common/src/main/kotlin/me/eternal/purrfectsnap/common/util/protobuf/ProtoWriter.kt index b8201704..e95ea69d 100644 --- a/common/src/main/kotlin/me/rhunk/snapenhance/common/util/protobuf/ProtoWriter.kt +++ b/common/src/main/kotlin/me/eternal/purrfectsnap/common/util/protobuf/ProtoWriter.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.common.util.protobuf +package me.eternal.purrfectsnap.common.util.protobuf import org.mozilla.javascript.annotations.JSFunction import java.io.ByteArrayOutputStream diff --git a/common/src/main/kotlin/me/rhunk/snapenhance/common/util/protobuf/WireType.kt b/common/src/main/kotlin/me/eternal/purrfectsnap/common/util/protobuf/WireType.kt similarity index 82% rename from common/src/main/kotlin/me/rhunk/snapenhance/common/util/protobuf/WireType.kt rename to common/src/main/kotlin/me/eternal/purrfectsnap/common/util/protobuf/WireType.kt index 09f39dce..9870096f 100644 --- a/common/src/main/kotlin/me/rhunk/snapenhance/common/util/protobuf/WireType.kt +++ b/common/src/main/kotlin/me/eternal/purrfectsnap/common/util/protobuf/WireType.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.common.util.protobuf; +package me.eternal.purrfectsnap.common.util.protobuf; enum class WireType(val value: Int) { VARINT(0), diff --git a/common/src/main/kotlin/me/rhunk/snapenhance/common/util/snap/BitmojiSelfie.kt b/common/src/main/kotlin/me/eternal/purrfectsnap/common/util/snap/BitmojiSelfie.kt similarity index 94% rename from common/src/main/kotlin/me/rhunk/snapenhance/common/util/snap/BitmojiSelfie.kt rename to common/src/main/kotlin/me/eternal/purrfectsnap/common/util/snap/BitmojiSelfie.kt index 98de28f6..573c80e2 100644 --- a/common/src/main/kotlin/me/rhunk/snapenhance/common/util/snap/BitmojiSelfie.kt +++ b/common/src/main/kotlin/me/eternal/purrfectsnap/common/util/snap/BitmojiSelfie.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.common.util.snap +package me.eternal.purrfectsnap.common.util.snap object BitmojiSelfie { enum class BitmojiSelfieType( diff --git a/common/src/main/kotlin/me/rhunk/snapenhance/common/util/snap/MediaDownloaderHelper.kt b/common/src/main/kotlin/me/eternal/purrfectsnap/common/util/snap/MediaDownloaderHelper.kt similarity index 88% rename from common/src/main/kotlin/me/rhunk/snapenhance/common/util/snap/MediaDownloaderHelper.kt rename to common/src/main/kotlin/me/eternal/purrfectsnap/common/util/snap/MediaDownloaderHelper.kt index 6e9d206f..3a90ce3a 100644 --- a/common/src/main/kotlin/me/rhunk/snapenhance/common/util/snap/MediaDownloaderHelper.kt +++ b/common/src/main/kotlin/me/eternal/purrfectsnap/common/util/snap/MediaDownloaderHelper.kt @@ -1,7 +1,7 @@ -package me.rhunk.snapenhance.common.util.snap +package me.eternal.purrfectsnap.common.util.snap -import me.rhunk.snapenhance.common.data.FileType -import me.rhunk.snapenhance.common.data.download.SplitMediaAssetType +import me.eternal.purrfectsnap.common.data.FileType +import me.eternal.purrfectsnap.common.data.download.SplitMediaAssetType import java.io.BufferedInputStream import java.io.InputStream import java.util.zip.ZipEntry diff --git a/common/src/main/kotlin/me/rhunk/snapenhance/common/util/snap/RemoteMediaResolver.kt b/common/src/main/kotlin/me/eternal/purrfectsnap/common/util/snap/RemoteMediaResolver.kt similarity index 93% rename from common/src/main/kotlin/me/rhunk/snapenhance/common/util/snap/RemoteMediaResolver.kt rename to common/src/main/kotlin/me/eternal/purrfectsnap/common/util/snap/RemoteMediaResolver.kt index f2c89600..6554a033 100644 --- a/common/src/main/kotlin/me/rhunk/snapenhance/common/util/snap/RemoteMediaResolver.kt +++ b/common/src/main/kotlin/me/eternal/purrfectsnap/common/util/snap/RemoteMediaResolver.kt @@ -1,7 +1,7 @@ -package me.rhunk.snapenhance.common.util.snap +package me.eternal.purrfectsnap.common.util.snap -import me.rhunk.snapenhance.common.Constants -import me.rhunk.snapenhance.common.util.ktx.await +import me.eternal.purrfectsnap.common.Constants +import me.eternal.purrfectsnap.common.util.ktx.await import okhttp3.Headers import okhttp3.OkHttpClient import okhttp3.Request diff --git a/common/src/main/kotlin/me/rhunk/snapenhance/common/util/snap/SnapWidgetBroadcastReceiverHelper.kt b/common/src/main/kotlin/me/eternal/purrfectsnap/common/util/snap/SnapWidgetBroadcastReceiverHelper.kt similarity index 88% rename from common/src/main/kotlin/me/rhunk/snapenhance/common/util/snap/SnapWidgetBroadcastReceiverHelper.kt rename to common/src/main/kotlin/me/eternal/purrfectsnap/common/util/snap/SnapWidgetBroadcastReceiverHelper.kt index f0b5a65b..114209cf 100644 --- a/common/src/main/kotlin/me/rhunk/snapenhance/common/util/snap/SnapWidgetBroadcastReceiverHelper.kt +++ b/common/src/main/kotlin/me/eternal/purrfectsnap/common/util/snap/SnapWidgetBroadcastReceiverHelper.kt @@ -1,7 +1,7 @@ -package me.rhunk.snapenhance.common.util.snap +package me.eternal.purrfectsnap.common.util.snap import android.content.Intent -import me.rhunk.snapenhance.common.Constants +import me.eternal.purrfectsnap.common.Constants object SnapWidgetBroadcastReceiverHelper { private const val ACTION_WIDGET_UPDATE = "com.snap.android.WIDGET_APP_START_UPDATE_ACTION" diff --git a/common/src/main/kotlin/me/rhunk/snapenhance/common/config/impl/MessagingTweaks.kt b/common/src/main/kotlin/me/rhunk/snapenhance/common/config/impl/MessagingTweaks.kt deleted file mode 100644 index 63e1acdb..00000000 --- a/common/src/main/kotlin/me/rhunk/snapenhance/common/config/impl/MessagingTweaks.kt +++ /dev/null @@ -1,104 +0,0 @@ -package me.rhunk.snapenhance.common.config.impl - -import me.rhunk.snapenhance.common.config.ConfigContainer -import me.rhunk.snapenhance.common.config.FeatureNotice -import me.rhunk.snapenhance.common.config.PropertyValue -import me.rhunk.snapenhance.common.data.NotificationType -import me.rhunk.snapenhance.common.util.PURGE_DISABLED_KEY -import me.rhunk.snapenhance.common.util.PURGE_TRANSLATION_KEY -import me.rhunk.snapenhance.common.util.PURGE_VALUES - -class MessagingTweaks : ConfigContainer() { - companion object { - const val DELETED_MESSAGE_COLOR = 0x6Eb71c1c; - } - - inner class HalfSwipeNotifierConfig : ConfigContainer(hasGlobalState = true) { - val minDuration: PropertyValue = integer("min_duration", defaultValue = 0) { - inputCheck = { it.toIntOrNull()?.coerceAtLeast(0) != null && maxDuration.get() >= it.toInt() } - } - val maxDuration: PropertyValue = integer("max_duration", defaultValue = 20) { - inputCheck = { it.toIntOrNull()?.coerceAtLeast(0) != null && minDuration.get() <= it.toInt() } - } - } - - inner class MessageLoggerConfig : ConfigContainer(hasGlobalState = true) { - val keepMyOwnMessages = boolean("keep_my_own_messages") - val autoPurge = unique("auto_purge", *PURGE_VALUES) { - customOptionTranslationPath = PURGE_TRANSLATION_KEY - disabledKey = PURGE_DISABLED_KEY - }.apply { set("3_days") } - val messageFilter = multiple("message_filter", "CHAT", - "SNAP", - "NOTE", - "EXTERNAL_MEDIA", - "STICKER" - ) { - customOptionTranslationPath = "content_type" - } - val deletedMessageColor = color("deleted_message_color", DELETED_MESSAGE_COLOR) - } - - class BetterNotifications: ConfigContainer() { - val groupNotifications = boolean("group_notifications") - val chatPreview = boolean("chat_preview") - val mediaPreview = multiple("media_preview", "SNAP", "EXTERNAL_MEDIA", "STICKER", "SHARE", "TINY_SNAP", "MAP_REACTION") { - customOptionTranslationPath = "content_type" - } - val mediaCaption = boolean("media_caption") - val stackedMediaMessages = boolean("stacked_media_messages") - val friendAddSource = boolean("friend_add_source") - val replyButton = boolean("reply_button") { addNotices(FeatureNotice.UNSTABLE) } - val smartReplies = boolean("smart_replies") - val downloadButton = boolean("download_button") - val markAsReadButton = boolean("mark_as_read_button") { addNotices(FeatureNotice.UNSTABLE) } - val markAsReadAndSaveInChat = boolean("mark_as_read_and_save_in_chat") { addNotices(FeatureNotice.UNSTABLE) } - } - - val bypassScreenshotDetection = boolean("bypass_screenshot_detection") { requireRestart() } - val anonymousStoryViewing = boolean("anonymous_story_viewing") - val preventStoryRewatchIndicator = boolean("prevent_story_rewatch_indicator") { requireRestart() } - val hidePeekAPeek = boolean("hide_peek_a_peek") - val hideBitmojiPresence = boolean("hide_bitmoji_presence") - val unlimitedSnapViewTime = boolean("unlimited_snap_view_time") - val autoMarkAsRead = multiple("auto_mark_as_read", "snap_reply", "conversation_read", "save_snap_in_chat") { requireRestart() } - val markSnapAsSeenButton = boolean("mark_snap_as_seen_button") { requireRestart() } - val skipWhenMarkingAsSeen = boolean("skip_when_marking_as_seen") { requireRestart() } - val loopMediaPlayback = boolean("loop_media_playback") { requireRestart() } - val disableReplayInFF = boolean("disable_replay_in_ff") - val halfSwipeNotifier = container("half_swipe_notifier", HalfSwipeNotifierConfig()) { requireRestart()} - val callStartConfirmation = boolean("call_start_confirmation") { requireRestart() } - val unlimitedConversationPinning = boolean("unlimited_conversation_pinning") { requireRestart() } - val disableSnapModeRestrictions = boolean("disable_snap_mode_restrictions") { requireRestart() } - val autoSaveMessagesInConversations = multiple("auto_save_messages_in_conversations", - "CHAT", - "SNAP", - "NOTE", - "EXTERNAL_MEDIA", - "STICKER" - ) { requireRestart(); customOptionTranslationPath = "content_type" } - val preventMessageSending = multiple("prevent_message_sending", *NotificationType.getOutgoingValues().map { it.key }.toTypedArray()) { - customOptionTranslationPath = "features.options.notifications" - } - val friendMutationNotifier = multiple("friend_mutation_notifier", - "remove_friend", - "birthday_changes", - "bitmoji_selfie_changes", - "bitmoji_avatar_changes", - "bitmoji_background_changes", - "bitmoji_scene_changes", - ) { requireRestart() } - val betterNotifications = container("better_notifications", BetterNotifications()) { requireRestart() } - val notificationBlacklist = multiple("notification_blacklist", *NotificationType.getIncomingValues().map { it.key }.toTypedArray()) { - customOptionTranslationPath = "features.options.notifications" - } - val messageLogger = container("message_logger", MessageLoggerConfig()) { requireRestart() } - val galleryMediaSendOverride = unique("gallery_media_send_override", "always_ask", "SNAP", "NOTE", "SAVEABLE_SNAP") { requireRestart() } - val stripMediaMetadata = multiple("strip_media_metadata", "hide_caption_text", "hide_snap_filters", "hide_extras", "remove_audio_note_duration", "remove_audio_note_transcript_capability") { requireRestart() } - val bypassMessageRetentionPolicy = boolean("bypass_message_retention_policy") { addNotices(FeatureNotice.UNSTABLE); requireRestart() } - val bypassMessageActionRestrictions = boolean("bypass_message_action_restrictions") { requireRestart() } - val removeGroupsLockedStatus = boolean("remove_groups_locked_status") { requireRestart() } - val doubleTapChatAction = unique("double_tap_chat_action", "like_message", "copy_text", "delete_message", "mark_as_read", "custom_emoji_reaction") { requireRestart() } - val doubleTapChatActionCustomEmoji = string("double_tap_chat_action_custom_emoji") { - inputCheck = { it.length == 2 && it.toByteArray(Charsets.UTF_8).size >= 4 } } -} \ No newline at end of file diff --git a/common/src/main/kotlin/me/rhunk/snapenhance/common/config/impl/Spoof.kt b/common/src/main/kotlin/me/rhunk/snapenhance/common/config/impl/Spoof.kt deleted file mode 100644 index e75e2ae9..00000000 --- a/common/src/main/kotlin/me/rhunk/snapenhance/common/config/impl/Spoof.kt +++ /dev/null @@ -1,10 +0,0 @@ -package me.rhunk.snapenhance.common.config.impl - -import me.rhunk.snapenhance.common.config.ConfigContainer -import me.rhunk.snapenhance.common.config.ConfigFlag - -class Spoof : ConfigContainer(hasGlobalState = true) { - val overridePlayStoreInstallerPackageName = boolean("play_store_installer_package_name") { requireRestart() } - val removeVpnTransportFlag = boolean("remove_vpn_transport_flag") { requireRestart() } - val removeMockLocationFlag = boolean("remove_mock_location_flag") { requireRestart() } -} \ No newline at end of file diff --git a/common/src/main/kotlin/me/rhunk/snapenhance/common/scripting/bindings/BindingsContext.kt b/common/src/main/kotlin/me/rhunk/snapenhance/common/scripting/bindings/BindingsContext.kt deleted file mode 100644 index a9308ecf..00000000 --- a/common/src/main/kotlin/me/rhunk/snapenhance/common/scripting/bindings/BindingsContext.kt +++ /dev/null @@ -1,11 +0,0 @@ -package me.rhunk.snapenhance.common.scripting.bindings - -import me.rhunk.snapenhance.common.scripting.JSModule -import me.rhunk.snapenhance.common.scripting.ScriptRuntime -import me.rhunk.snapenhance.common.scripting.type.ModuleInfo - -class BindingsContext( - val moduleInfo: ModuleInfo, - val runtime: ScriptRuntime, - val module: JSModule -) \ No newline at end of file diff --git a/common/src/main/kotlin/me/rhunk/snapenhance/common/scripting/ui/components/impl/ActionNode.kt b/common/src/main/kotlin/me/rhunk/snapenhance/common/scripting/ui/components/impl/ActionNode.kt deleted file mode 100644 index 6a02ea8b..00000000 --- a/common/src/main/kotlin/me/rhunk/snapenhance/common/scripting/ui/components/impl/ActionNode.kt +++ /dev/null @@ -1,15 +0,0 @@ -package me.rhunk.snapenhance.common.scripting.ui.components.impl - -import me.rhunk.snapenhance.common.scripting.ui.components.Node -import me.rhunk.snapenhance.common.scripting.ui.components.NodeType - -enum class ActionType { - LAUNCHED, - DISPOSE -} - -class ActionNode( - val actionType: ActionType, - val key: Any = Unit, - val callback: () -> Unit -): Node(NodeType.ACTION) \ No newline at end of file diff --git a/compare_translations.ipynb b/compare_translations.ipynb deleted file mode 100644 index 21c26798..00000000 --- a/compare_translations.ipynb +++ /dev/null @@ -1,10 +0,0 @@ -{ - "cells": [], - "metadata": { - "language_info": { - "name": "python" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} diff --git a/composer/build.gradle.kts b/composer/build.gradle.kts index 66e0ac05..a1c6b257 100644 --- a/composer/build.gradle.kts +++ b/composer/build.gradle.kts @@ -15,26 +15,22 @@ android { } tasks.register("installTypeScript", org.gradle.api.tasks.Exec::class) { + val tscScriptPath = layout.projectDirectory.file("node_modules/.bin/tsc").asFile if (Os.isFamily(Os.FAMILY_WINDOWS)) { commandLine("npm.cmd", "install", "typescript") } else { commandLine("npm", "install", "typescript") } doLast { - if (!Os.isFamily(Os.FAMILY_WINDOWS)) { - val tscScript = project.file("node_modules/.bin/tsc") - if (tscScript.exists()) { - tscScript.setExecutable(true) - } + if (!Os.isFamily(Os.FAMILY_WINDOWS) && tscScriptPath.exists()) { + tscScriptPath.setExecutable(true) } } } tasks.register("compileTsc", org.gradle.api.tasks.Exec::class) { dependsOn("installTypeScript") - val existingNodeOptions = System.getenv("NODE_OPTIONS")?.takeIf { it.isNotBlank() } - val nodeOptions = listOfNotNull(existingNodeOptions, "--max-old-space-size=4096").joinToString(" ") - environment("NODE_OPTIONS", nodeOptions) + environment("NODE_OPTIONS", "--max-old-space-size=4096") if (Os.isFamily(Os.FAMILY_WINDOWS)) { commandLine("npx.cmd", "--yes", "tsc", "--project", "tsconfig.json") } else { @@ -44,9 +40,7 @@ tasks.register("compileTsc", org.gradle.api.tasks.Exec::class) { tasks.register("compileRollup", org.gradle.api.tasks.Exec::class) { dependsOn("compileTsc") - val existingNodeOptions = System.getenv("NODE_OPTIONS")?.takeIf { it.isNotBlank() } - val nodeOptions = listOfNotNull(existingNodeOptions, "--max-old-space-size=4096").joinToString(" ") - environment("NODE_OPTIONS", nodeOptions) + environment("NODE_OPTIONS", "--max-old-space-size=4096") if (Os.isFamily(Os.FAMILY_WINDOWS)) { commandLine("npx.cmd", "--yes", "rollup", "--config", "rollup.config.js", "--bundleConfigAsCjs") } else { diff --git a/composer/src/main/ts/imports.ts b/composer/src/main/ts/imports.ts index 8ec5701b..023a7bee 100644 --- a/composer/src/main/ts/imports.ts +++ b/composer/src/main/ts/imports.ts @@ -1,13 +1,24 @@ import { Config } from "./types"; declare var _getImportsFunctionName: string; -declare var _runtimeName: boolean; +declare var _runtimeName: string; export const runtimeName = _runtimeName; -const remoteImports = require(_runtimeName + '_core/DeviceBridge')[_getImportsFunctionName](); +let remoteImports: any = null; +try { + remoteImports = require(_runtimeName + "_core/DeviceBridge")?.[_getImportsFunctionName]?.(); +} catch { + remoteImports = null; +} function callRemoteFunction(method: string, ...args: any[]): any | null { - return remoteImports[method](...args); + try { + const fn = remoteImports?.[method]; + if (typeof fn !== "function") return null; + return fn(...args); + } catch { + return null; + } } @@ -19,4 +30,4 @@ export const downloadLastOperaMedia = (isLongPress: boolean) => callRemoteFuncti export function getFriendOriginalUsername(username: string): string | null { return callRemoteFunction("getFriendOriginalUsername", username); -} +} \ No newline at end of file diff --git a/config/config.json b/config/config.json new file mode 100644 index 00000000..4a51436d --- /dev/null +++ b/config/config.json @@ -0,0 +1,23 @@ +{ + "allowed_eps_active": [ + "/messagingcoreservice.MessagingCoreService/", + "/GetSnapchatterPublicInfo", + "/UserRecentlyActive", + "/socialsms.SocialSms/UpdateLink", + "/com.snapchat.atlas.gw.AtlasGw/SyncFriendData", + "/com.snapchat.atlas.gw.AtlasGw/GetFriendsUserScore", + "/com.snapchat.atlas.gw.AtlasGw/GetUserRecentlyActive", + "/snapchat.friending.server.FriendAction/", + "/snapchat.friending.server.FriendRequests/", + "/snapchat.music.music_service.MusicService/", + "/com.snapchat.ads.notification.ProfileNotificationCRUDService/", + "ClientIntegrityService", + "/ClientIntegrityService", + "/ClientIntegrityService/", + "/GetAttestationHeaders", + "/AttestationHeaders", + "/getAttestationHeaders", + "/GetAttestationPayload", + "/AttestationPayload" + ] +} diff --git a/core/build.gradle.kts b/core/build.gradle.kts index c9d264fb..95d1418f 100644 --- a/core/build.gradle.kts +++ b/core/build.gradle.kts @@ -9,10 +9,12 @@ android { defaultConfig { minSdk = 28 + buildConfigField("String", "NATIVE_KEY", "\"${System.getenv("NATIVE_KEY") ?: ""}\"") } buildFeatures { compose = true + buildConfig = true } compileOptions { @@ -32,7 +34,7 @@ dependencies { implementation(project(":common")) implementation(project(":mapper")) - implementation(project(":native")) + implementation(project(":native")) implementation(project(":composer")) implementation(libs.androidx.activity.ktx) @@ -43,5 +45,4 @@ dependencies { implementation(libs.androidx.material.icons.extended) implementation(libs.androidx.material3) implementation(libs.hiddenapibypass) - implementation(libs.bcprov.jdk18on) -} +} \ No newline at end of file diff --git a/core/src/main/assets/xposed_init b/core/src/main/assets/xposed_init index 46ffe14b..90425a98 100644 --- a/core/src/main/assets/xposed_init +++ b/core/src/main/assets/xposed_init @@ -1 +1 @@ -me.rhunk.snapenhance.core.XposedLoader \ No newline at end of file +me.eternal.purrfectsnap.core.XposedLoader \ No newline at end of file diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/DownloadManagerClient.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/DownloadManagerClient.kt similarity index 90% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/DownloadManagerClient.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/DownloadManagerClient.kt index ab08d89f..aaf30b68 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/DownloadManagerClient.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/DownloadManagerClient.kt @@ -1,11 +1,11 @@ -package me.rhunk.snapenhance.core +package me.eternal.purrfectsnap.core import android.content.Intent import android.os.Bundle -import me.rhunk.snapenhance.bridge.DownloadCallback -import me.rhunk.snapenhance.common.ReceiversConfig -import me.rhunk.snapenhance.common.data.download.* -import me.rhunk.snapenhance.core.features.impl.downloader.decoder.AttachmentType +import me.eternal.purrfectsnap.bridge.DownloadCallback +import me.eternal.purrfectsnap.common.ReceiversConfig +import me.eternal.purrfectsnap.common.data.download.* +import me.eternal.purrfectsnap.core.features.impl.downloader.decoder.AttachmentType class DownloadManagerClient ( private val context: ModContext, diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/ModContext.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/ModContext.kt similarity index 77% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/ModContext.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/ModContext.kt index e686fadb..a5ec2ad7 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/ModContext.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/ModContext.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.core +package me.eternal.purrfectsnap.core import android.app.Activity import android.content.Context @@ -13,40 +13,41 @@ import com.google.gson.GsonBuilder import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch -import me.rhunk.snapenhance.common.Constants -import me.rhunk.snapenhance.common.bridge.wrapper.LocaleWrapper -import me.rhunk.snapenhance.common.bridge.wrapper.MappingsWrapper -import me.rhunk.snapenhance.common.config.ModConfig -import me.rhunk.snapenhance.common.util.lazyBridge -import me.rhunk.snapenhance.core.action.ActionManager -import me.rhunk.snapenhance.core.bridge.BridgeClient -import me.rhunk.snapenhance.core.database.DatabaseAccess -import me.rhunk.snapenhance.core.event.EventBus -import me.rhunk.snapenhance.core.event.EventDispatcher -import me.rhunk.snapenhance.core.features.Feature -import me.rhunk.snapenhance.core.features.FeatureManager -import me.rhunk.snapenhance.core.features.impl.experiments.getCustomEmojiFontPath -import me.rhunk.snapenhance.core.logger.CoreLogger -import me.rhunk.snapenhance.core.messaging.CoreMessagingBridge -import me.rhunk.snapenhance.core.messaging.MessageSender -import me.rhunk.snapenhance.core.scripting.CoreScriptRuntime -import me.rhunk.snapenhance.core.ui.InAppOverlay -import me.rhunk.snapenhance.core.ui.UserInterface -import me.rhunk.snapenhance.core.util.media.HttpServer -import me.rhunk.snapenhance.nativelib.NativeConfig -import me.rhunk.snapenhance.nativelib.NativeLib +import me.eternal.purrfectsnap.common.Constants +import me.eternal.purrfectsnap.common.bridge.wrapper.LocaleWrapper +import me.eternal.purrfectsnap.common.bridge.wrapper.MappingsWrapper +import me.eternal.purrfectsnap.common.config.ModConfig +import me.eternal.purrfectsnap.common.util.lazyBridge +import me.eternal.purrfectsnap.core.action.ActionManager +import me.eternal.purrfectsnap.core.bridge.BridgeClient +import me.eternal.purrfectsnap.core.database.DatabaseAccess +import me.eternal.purrfectsnap.core.event.EventBus +import me.eternal.purrfectsnap.core.event.EventDispatcher +import me.eternal.purrfectsnap.core.features.Feature +import me.eternal.purrfectsnap.core.features.FeatureManager +import me.eternal.purrfectsnap.core.features.impl.experiments.getCustomEmojiFontPath +import me.eternal.purrfectsnap.core.logger.CoreLogger +import me.eternal.purrfectsnap.core.messaging.CoreMessagingBridge +import me.eternal.purrfectsnap.core.messaging.MessageSender +import me.eternal.purrfectsnap.core.scripting.CoreScriptRuntime +import me.eternal.purrfectsnap.core.ui.InAppOverlay +import me.eternal.purrfectsnap.core.ui.UserInterface +import me.eternal.purrfectsnap.core.util.media.HttpServer +import me.eternal.purrfectsnap.nativelib.NativeConfig +import me.eternal.purrfectsnap.nativelib.NativeLib import kotlin.reflect.KClass import kotlin.system.exitProcess class ModContext( - val androidContext: Context + val androidContext: Context, + val purrfectSnap: PurrfectSnap ) { val coroutineScope = CoroutineScope(Dispatchers.IO) lateinit var bridgeClient: BridgeClient var mainActivity: Activity? = null - val classCache get() = SnapEnhance.classCache + val classCache get() = PurrfectSnap.classCache val resources: Resources get() = androidContext.resources val gson: Gson = GsonBuilder().create() @@ -171,4 +172,4 @@ class ModContext( } fun isLoggedIn() = androidContext.getSharedPreferences("user_session_shared_pref", 0).getString("key_user_id", null) != null -} \ No newline at end of file +} diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/SnapEnhance.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/PurrfectSnap.kt similarity index 74% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/SnapEnhance.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/PurrfectSnap.kt index d1374018..7e922c9b 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/SnapEnhance.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/PurrfectSnap.kt @@ -1,7 +1,8 @@ -package me.rhunk.snapenhance.core +package me.eternal.purrfectsnap.core import android.app.Activity import android.content.Context +import android.content.Intent import android.content.res.Resources import android.os.Build import androidx.compose.material.icons.Icons @@ -10,35 +11,35 @@ import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import kotlinx.coroutines.runBlocking -import me.rhunk.snapenhance.bridge.ConfigStateListener -import me.rhunk.snapenhance.bridge.SyncCallback -import me.rhunk.snapenhance.common.Constants -import me.rhunk.snapenhance.common.ReceiversConfig -import me.rhunk.snapenhance.common.action.EnumAction -import me.rhunk.snapenhance.common.bridge.FileHandleScope -import me.rhunk.snapenhance.common.bridge.InternalFileHandleType -import me.rhunk.snapenhance.common.bridge.toWrapper -import me.rhunk.snapenhance.common.data.FriendStreaks -import me.rhunk.snapenhance.common.data.MessagingFriendInfo -import me.rhunk.snapenhance.common.data.MessagingGroupInfo -import me.rhunk.snapenhance.common.util.toSerialized -import me.rhunk.snapenhance.core.bridge.BridgeClient -import me.rhunk.snapenhance.core.data.SnapClassCache -import me.rhunk.snapenhance.core.event.events.impl.NativeUnaryCallEvent -import me.rhunk.snapenhance.core.event.events.impl.SnapWidgetBroadcastReceiveEvent -import me.rhunk.snapenhance.core.ui.InAppOverlay -import me.rhunk.snapenhance.core.util.LSPatchUpdater -import me.rhunk.snapenhance.core.util.hook.HookAdapter -import me.rhunk.snapenhance.core.util.hook.HookStage -import me.rhunk.snapenhance.core.util.hook.findRestrictedMethod -import me.rhunk.snapenhance.core.util.hook.hook -import me.rhunk.snapenhance.mapper.impl.PlatformClientAttestationMapper +import me.eternal.purrfectsnap.bridge.ConfigStateListener +import me.eternal.purrfectsnap.bridge.SyncCallback +import me.eternal.purrfectsnap.common.Constants +import me.eternal.purrfectsnap.common.ReceiversConfig +import me.eternal.purrfectsnap.common.action.EnumAction +import me.eternal.purrfectsnap.common.bridge.FileHandleScope +import me.eternal.purrfectsnap.common.bridge.InternalFileHandleType +import me.eternal.purrfectsnap.common.bridge.toWrapper +import me.eternal.purrfectsnap.common.data.FriendStreaks +import me.eternal.purrfectsnap.common.data.MessagingFriendInfo +import me.eternal.purrfectsnap.common.data.MessagingGroupInfo +import me.eternal.purrfectsnap.common.util.toSerialized +import me.eternal.purrfectsnap.core.bridge.BridgeClient +import me.eternal.purrfectsnap.core.data.SnapClassCache +import me.eternal.purrfectsnap.core.event.events.impl.NativeUnaryCallEvent +import me.eternal.purrfectsnap.core.event.events.impl.SnapWidgetBroadcastReceiveEvent +import me.eternal.purrfectsnap.core.ui.InAppOverlay +import me.eternal.purrfectsnap.core.util.LSPatchUpdater +import me.eternal.purrfectsnap.core.util.hook.HookAdapter +import me.eternal.purrfectsnap.core.util.hook.HookStage +import me.eternal.purrfectsnap.core.util.hook.findRestrictedMethod +import me.eternal.purrfectsnap.core.util.hook.hook +import me.eternal.purrfectsnap.mapper.impl.PlatformClientAttestationMapper import kotlin.reflect.KClass import kotlin.system.exitProcess import kotlin.system.measureTimeMillis -class SnapEnhance { +class PurrfectSnap { companion object { lateinit var classLoader: ClassLoader private set @@ -59,7 +60,8 @@ class SnapEnhance { fun init(context: Context) { appContext = ModContext( - androidContext = context.also { classLoader = it.classLoader } + androidContext = context.also { classLoader = it.classLoader }, + purrfectSnap = this ) appContext.apply { bridgeClient = BridgeClient(this) @@ -82,15 +84,15 @@ class SnapEnhance { if (canLoad == null) { InAppOverlay.showCrashOverlay( buildString { - append("Snapchat timed out while trying to connect to SnapEnhance\n\n") + append("Snapchat timed out while trying to connect to PurrfectSnap\n\n") append("Make sure you:\n") - append(" - Have installed the latest SnapEnhance version (https://github.com/rhunk/SnapEnhance)\n") + append(" - Have installed the latest PurrfectSnap version (https://github.com/particle-box/PurrfectSnap)\n") append(" - Disabled battery optimizations\n") - append(" - Excluded SnapEnhance and Snapchat in HideMyApplist") + append(" - Excluded PurrfectSnap and Snapchat in HideMyApplist") }, throwable ) - appContext.logCritical("Cannot connect to the SnapEnhance app") + appContext.logCritical("Cannot connect to the PurrfectSnap app") return@runBlocking } if (!canLoad) exitProcess(1) @@ -164,17 +166,76 @@ class SnapEnhance { database.init() eventDispatcher.init() userInterface.init() + + // Check mappings status with detailed logging + log.verbose("Checking mappings status...") + log.verbose("Mappings loaded: ${mappings.isMappingsLoaded}") + log.verbose("Mappings outdated: ${mappings.isMappingsOutdated()}") + //if mappings aren't loaded, we can't initialize features - if (!mappings.isMappingsLoaded) return - features.init() - scriptRuntime.init() - scriptRuntime.eachModule { callFunction("module.onSnapApplicationLoad", androidContext) } + if (!mappings.isMappingsLoaded) { + log.warn("Mappings not loaded, skipping features initialization") + log.warn("Mappings file exists: ${mappings.exists()}") + log.warn("Generated build number: ${mappings.getGeneratedBuildNumber()}") + // Trigger auto-generation by launching manager app + triggerMappingsGeneration() + return + } + + // Also check if mappings are outdated and trigger regeneration + if (mappings.isMappingsOutdated()) { + log.warn("Mappings are outdated, triggering auto-generation check") + triggerMappingsGeneration() + } + + log.verbose("Initializing features...") + runCatching { + features.init() + log.verbose("Features initialized successfully") + }.onFailure { throwable -> + log.error("Failed to initialize features", throwable) + longToast("Failed to initialize features! Some functionality may not work properly.") + // Continue with other initializations even if features fail + } + + log.verbose("Initializing script runtime...") + runCatching { + scriptRuntime.init() + scriptRuntime.eachModule { callFunction("module.onSnapApplicationLoad", androidContext) } + log.verbose("Script runtime initialized successfully") + }.onFailure { throwable -> + log.error("Failed to initialize script runtime", throwable) + longToast("Failed to initialize script runtime!") + } } } private var safeMode = false + private fun triggerMappingsGeneration() { + runCatching { + val autoGen = appContext.bridgeClient.getDebugProp("auto_generate_mappings", "true") + if (autoGen != "true") { + appContext.log.verbose("Auto-generation disabled via debug prop") + return + } + + val intent = Intent().apply { + setClassName(Constants.SE_PACKAGE_NAME, "${Constants.SE_PACKAGE_NAME}.ui.setup.SetupActivity") + addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + putExtra("requirements", 4) // Requirements.MAPPINGS = 4 + } + appContext.androidContext.startActivity(intent) + appContext.log.verbose("Triggered mappings generation via SetupActivity") + }.onFailure { + appContext.log.verbose("Could not trigger mappings generation: ${it.message}") + } + } + private fun onActivityCreate(activity: Activity) { + if (!appContext.native.verifyKey(BuildConfig.NATIVE_KEY)) { + safeMode = true + } measureTimeMillis { with(appContext) { features.onActivityCreate(activity) @@ -182,7 +243,8 @@ class SnapEnhance { scriptRuntime.eachModule { callFunction("module.onSnapMainActivityCreate", activity) } actionManager.onActivityCreate() - if (safeMode) { + val isTestModeEnabled = appContext.bridgeClient.getDebugProp("test_mode", "false") == "true" + if (safeMode && !isTestModeEnabled) { appContext.inAppOverlay.showStatusToast( Icons.Outlined.Cancel, "Failed to load security features! Snapchat may not work properly.", @@ -206,6 +268,7 @@ class SnapEnhance { } val lateInit = appContext.native.initOnce { + verifyKey(BuildConfig.NATIVE_KEY) nativeUnaryCallCallback = { request -> appContext.event.post(NativeUnaryCallEvent(request.uri, request.buffer)) { request.buffer = buffer @@ -396,4 +459,4 @@ class SnapEnhance { param.setResult(appContext.translation.getOrNull("material3_strings.${name}") ?: "") } } -} \ No newline at end of file +} diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/SecurityFeatures.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/SecurityFeatures.kt similarity index 67% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/SecurityFeatures.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/SecurityFeatures.kt index 6c7ba1e7..574aa883 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/SecurityFeatures.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/SecurityFeatures.kt @@ -1,53 +1,39 @@ -package me.rhunk.snapenhance.core +package me.eternal.purrfectsnap.core import android.system.Os import android.view.ViewGroup -import androidx.compose.animation.core.* -import androidx.compose.foundation.background -import androidx.compose.foundation.border import androidx.compose.foundation.layout.* -import androidx.compose.foundation.shape.CircleShape -import androidx.compose.ui.draw.blur -import androidx.compose.ui.draw.rotate -import androidx.compose.ui.graphics.Brush -import androidx.compose.ui.graphics.graphicsLayer import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Check -import androidx.compose.material.icons.filled.Close -import androidx.compose.material.icons.filled.Security +import androidx.compose.material.icons.outlined.Cancel import androidx.compose.material.icons.rounded.NotInterested import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Surface import androidx.compose.material3.Text -import androidx.compose.runtime.* +import androidx.compose.runtime.LaunchedEffect import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.alpha -import androidx.compose.ui.draw.scale import androidx.compose.ui.graphics.Color -import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp import kotlinx.coroutines.delay -import me.rhunk.snapenhance.common.bridge.FileHandleScope -import me.rhunk.snapenhance.common.bridge.toWrapper -import me.rhunk.snapenhance.common.config.MOD_DETECTION_VERSION_CHECK -import me.rhunk.snapenhance.common.config.VersionRequirement -import me.rhunk.snapenhance.common.ui.createComposeView -import me.rhunk.snapenhance.core.event.events.impl.UnaryCallEvent -import me.rhunk.snapenhance.core.ui.CustomComposable -import me.rhunk.snapenhance.core.util.dataBuilder -import me.rhunk.snapenhance.core.util.hook.HookStage -import me.rhunk.snapenhance.core.util.hook.hook -import me.rhunk.snapenhance.core.util.hook.hookConstructor -import me.rhunk.snapenhance.core.util.ktx.getObjectField -import me.rhunk.snapenhance.mapper.impl.CallbackMapper -import me.rhunk.snapenhance.mapper.impl.PlatformClientAttestationMapper +import me.eternal.purrfectsnap.common.bridge.FileHandleScope +import me.eternal.purrfectsnap.common.bridge.toWrapper +import me.eternal.purrfectsnap.common.config.MOD_DETECTION_VERSION_CHECK +import me.eternal.purrfectsnap.common.config.VersionRequirement +import me.eternal.purrfectsnap.common.ui.createComposeView +import me.eternal.purrfectsnap.core.event.events.impl.UnaryCallEvent +import me.eternal.purrfectsnap.core.ui.CustomComposable +import me.eternal.purrfectsnap.core.util.dataBuilder +import me.eternal.purrfectsnap.core.util.hook.HookStage +import me.eternal.purrfectsnap.core.util.hook.hook +import me.eternal.purrfectsnap.core.util.hook.hookConstructor +import me.eternal.purrfectsnap.core.util.ktx.getObjectField +import me.eternal.purrfectsnap.mapper.impl.CallbackMapper +import me.eternal.purrfectsnap.mapper.impl.PlatformClientAttestationMapper import java.io.IOException import java.lang.reflect.Method -import kotlin.system.exitProcess class SecurityFeatures( private val context: ModContext @@ -62,52 +48,9 @@ class SecurityFeatures( transact(this, 0)?.toString(2)?.padStart(32, '0')?.count { it == '1' } } - private fun showBypassStatusIndicator(isWorking: Boolean) { - if (context.bridgeClient.getDebugProp("disable_bypass_indicator", "false") == "true") { - return - } - - lateinit var composable: CustomComposable - composable = { - Row( - modifier = Modifier - .padding(16.dp) - .align(Alignment.TopCenter) - .offset(y = (-8).dp) - .background( - color = Color.Black.copy(alpha = 0.8f), - shape = androidx.compose.foundation.shape.RoundedCornerShape(8.dp) - ) - .padding(horizontal = 12.dp, vertical = 8.dp), - verticalAlignment = Alignment.CenterVertically - ) { - Icon( - imageVector = if (isWorking) Icons.Filled.Check else Icons.Filled.Close, - contentDescription = null, - tint = if (isWorking) Color.Green else Color.Red, - modifier = Modifier.size(16.dp) - ) - Spacer(modifier = Modifier.width(8.dp)) - Text( - text = if (isWorking) "Bypass Active" else "Bypass Inactive", - color = Color.White, - fontSize = 14.sp - ) - } - - LaunchedEffect(Unit) { - delay(3000) - context.inAppOverlay.removeCustomComposable(composable) - } - } - - context.inAppOverlay.addCustomComposable(composable) - } - fun init() { val snapchatVersionCode = context.androidContext.packageManager?.getPackageInfo(context.androidContext.packageName, 0)?.longVersionCode ?: throw IllegalStateException("Failed to get version code") var shouldDisablePlugin = MOD_DETECTION_VERSION_CHECK.checkVersion(snapchatVersionCode)?.second == VersionRequirement.OLDER_REQUIRED - var usingCustomSharedLibrary = false // load user shared library context.config.experimental.nativeHooks.customSharedLibrary.get().takeIf { it.isNotEmpty() }?.let { @@ -117,7 +60,6 @@ class SecurityFeatures( ) context.log.verbose("loaded custom shared library") shouldDisablePlugin = false - usingCustomSharedLibrary = true lateinit var composable: CustomComposable composable = { @@ -141,22 +83,28 @@ class SecurityFeatures( } } - if (context.bridgeClient.getDebugProp("test_mode", "false") == "true") { + val isTestModeEnabled = context.bridgeClient.getDebugProp("test_mode", "false") == "true" + if (isTestModeEnabled) { shouldDisablePlugin = false } context.disablePlugin = shouldDisablePlugin - context.log.verbose("disablePlugin=${context.disablePlugin}") - // Show bypass status indicator only when not using custom shared library - if (!usingCustomSharedLibrary) { - showBypassStatusIndicator(context.disablePlugin) + if (context.disablePlugin && !isTestModeEnabled) { + // Defer showing toast until an activity is available + context.features.addActivityCreateListener { activity -> + context.inAppOverlay.showStatusToast( + Icons.Outlined.Cancel, + "Failed to enable security features. Some features may not work properly.", + durationMs = 3000 + ) + } } + if (!context.disablePlugin) return val allowedEPs = listOf( "/messagingcoreservice.MessagingCoreService/", - "/GetConvoSafetyPrompt", "/GetSnapchatterPublicInfo", "/UserRecentlyActive", "/socialsms.SocialSms/UpdateLink", // Direct link sharing @@ -165,7 +113,6 @@ class SecurityFeatures( context.event.subscribe(UnaryCallEvent::class) { event -> val callOptions = event.adapter.arg(2).let { it.javaClass.getMethod("build").invoke(it) } ?: return@subscribe if (callOptions.getObjectField("mAttestation") != null || event.uri.endsWith("/IncomingFriendSync")) { - context.log.verbose("blocked ep ${event.adapter.arg(0)}", "UnaryCallEvent") event.canceled = true val eventHandler = event.adapter.arg(3) eventHandler.javaClass.methods.first { it.name == "onEvent" }.also { method -> @@ -196,8 +143,7 @@ class SecurityFeatures( headers.isEmpty() || headers.mapNotNull { it.getObjectField("mKey")?.toString()?.lowercase() }.any { it != "x-snap-access-token" } ) { - context.log.error("invalid headers ${headers.size}") - exitProcess(139) + // Intentionally do nothing to avoid terminating the host process. } } loadClass("com.snapchat.client.duplex.DuplexClient\$CppProxy").hook("registerHandler", @@ -217,11 +163,9 @@ class SecurityFeatures( if (authContextRequest.getObjectField("mAttestationRequired") == true) { if (allowedEPs.any { requestPath.contains(it) }) { - context.log.verbose("ep $requestPath", "AuthContextDelegate") return@hook } - context.log.verbose("blocked ep $requestPath", "AuthContextDelegate") param.setResult(null) } } ?: error("AuthContextDelegate not found in mappings") @@ -231,7 +175,6 @@ class SecurityFeatures( apiInvocationHandler.getAsClass()?.hook("invoke", HookStage.BEFORE) { param -> val method = param.arg(1) if (method.annotations.any { it.toString().contains("attestation") }) { - context.log.verbose("blocked call ${method.declaringClass.name}.${method.name}(...)") if (method.returnType.name.endsWith("Single")) { param.setResult( method.returnType.methods.first { @@ -269,7 +212,7 @@ class SecurityFeatures( Icon(Icons.Rounded.NotInterested, contentDescription = null, tint = MaterialTheme.colorScheme.onSurface, modifier = Modifier.size(110.dp)) Spacer(Modifier.height(50.dp)) Text( - "SnapEnhance can't be used to login or signup because your Snapchat version isn't the recommended one. Please downgrade to Snapchat v${MOD_DETECTION_VERSION_CHECK.maxVersion?.first ?: "0.0.0"} or disable SnapEnhance in LSPosed to continue.\n\nFor more details, join t.me/snapenhance_chat", + "PurrfectSnap can't be used to login or signup because your Snapchat version isn't the recommended one. Please downgrade to Snapchat v${MOD_DETECTION_VERSION_CHECK.maxVersion?.first ?: "0.0.0"} or disable PurrfectSnap in LSPosed to continue.\n\nFor more details, join t.me/purrfectsnap_official", color = MaterialTheme.colorScheme.onSurface, textAlign = TextAlign.Center, ) diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/XposedLoader.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/XposedLoader.kt similarity index 56% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/XposedLoader.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/XposedLoader.kt index 5d3e5dac..fe576a46 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/XposedLoader.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/XposedLoader.kt @@ -1,22 +1,22 @@ -package me.rhunk.snapenhance.core +package me.eternal.purrfectsnap.core import android.app.Application import de.robv.android.xposed.IXposedHookLoadPackage import de.robv.android.xposed.XposedBridge import de.robv.android.xposed.callbacks.XC_LoadPackage -import me.rhunk.snapenhance.common.BuildConfig -import me.rhunk.snapenhance.common.Constants -import me.rhunk.snapenhance.core.util.hook.HookStage -import me.rhunk.snapenhance.core.util.hook.hook +import me.eternal.purrfectsnap.common.BuildConfig +import me.eternal.purrfectsnap.common.Constants +import me.eternal.purrfectsnap.core.util.hook.HookStage +import me.eternal.purrfectsnap.core.util.hook.hook class XposedLoader : IXposedHookLoadPackage { override fun handleLoadPackage(p0: XC_LoadPackage.LoadPackageParam) { if (p0.packageName != Constants.SNAPCHAT_PACKAGE_NAME) return // prevent loading in sub-processes if (p0.processName.contains(":")) return - XposedBridge.log("Loading SnapEnhance v${BuildConfig.VERSION_NAME}#${BuildConfig.GIT_HASH} (package: ${BuildConfig.APPLICATION_ID})") + XposedBridge.log("Loading PurrfectSnap v${BuildConfig.VERSION_NAME}#${BuildConfig.GIT_HASH} (package: ${BuildConfig.APPLICATION_ID})") Application::class.java.hook("attach", HookStage.BEFORE) { param -> - SnapEnhance().init(param.arg(0)) + PurrfectSnap().init(param.arg(0)) } } } \ No newline at end of file diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/action/AbstractAction.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/action/AbstractAction.kt similarity index 85% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/action/AbstractAction.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/action/AbstractAction.kt index 0effa7f1..fbc27e86 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/action/AbstractAction.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/action/AbstractAction.kt @@ -1,6 +1,6 @@ -package me.rhunk.snapenhance.core.action +package me.eternal.purrfectsnap.core.action -import me.rhunk.snapenhance.core.ModContext +import me.eternal.purrfectsnap.core.ModContext import java.io.File abstract class AbstractAction{ diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/action/ActionManager.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/action/ActionManager.kt similarity index 71% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/action/ActionManager.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/action/ActionManager.kt index 8db4583f..2bbde807 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/action/ActionManager.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/action/ActionManager.kt @@ -1,13 +1,13 @@ -package me.rhunk.snapenhance.core.action +package me.eternal.purrfectsnap.core.action import android.content.Intent -import me.rhunk.snapenhance.common.action.EnumAction -import me.rhunk.snapenhance.core.ModContext -import me.rhunk.snapenhance.core.action.impl.BulkMessagingAction -import me.rhunk.snapenhance.core.action.impl.CleanCache -import me.rhunk.snapenhance.core.action.impl.ExportChatMessages -import me.rhunk.snapenhance.core.action.impl.ExportMemories -import me.rhunk.snapenhance.core.action.impl.ManageFriendList +import me.eternal.purrfectsnap.common.action.EnumAction +import me.eternal.purrfectsnap.core.ModContext +import me.eternal.purrfectsnap.core.action.impl.BulkMessagingAction +import me.eternal.purrfectsnap.core.action.impl.CleanCache +import me.eternal.purrfectsnap.core.action.impl.ExportChatMessages +import me.eternal.purrfectsnap.core.action.impl.ExportMemories +import me.eternal.purrfectsnap.core.action.impl.ManageFriendList class ActionManager( private val modContext: ModContext, diff --git a/core/src/main/kotlin/me/eternal/purrfectsnap/core/action/impl/BulkMessagingAction.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/action/impl/BulkMessagingAction.kt new file mode 100644 index 00000000..2aa0e4dd --- /dev/null +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/action/impl/BulkMessagingAction.kt @@ -0,0 +1,1392 @@ +package me.eternal.purrfectsnap.core.action.impl + +import android.content.Context +import android.graphics.Bitmap +import android.graphics.BitmapFactory +import android.view.Gravity +import android.view.View +import android.widget.LinearLayout +import android.widget.ProgressBar +import android.widget.TextView +import androidx.compose.foundation.BorderStroke +import androidx.compose.foundation.ExperimentalFoundationApi +import androidx.compose.foundation.Image +import androidx.compose.foundation.background +import androidx.compose.foundation.border +import androidx.compose.foundation.clickable +import androidx.compose.foundation.gestures.detectTapGestures +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.text.BasicTextField +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items +import androidx.compose.material3.* +import androidx.compose.runtime.* +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.SolidColor +import androidx.compose.ui.graphics.asImageBitmap +import androidx.compose.ui.graphics.Brush +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.ui.input.pointer.pointerInput +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.platform.LocalFocusManager +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.text.style.TextOverflow +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.delay +import kotlinx.coroutines.launch +import kotlinx.coroutines.suspendCancellableCoroutine +import kotlinx.coroutines.withContext +import me.eternal.purrfectsnap.common.data.ContentType +import me.eternal.purrfectsnap.common.data.FriendLinkType +import me.eternal.purrfectsnap.common.database.impl.ConversationMessage +import me.eternal.purrfectsnap.common.database.impl.FriendInfo +import me.eternal.purrfectsnap.common.database.impl.FriendFeedEntry +import me.eternal.purrfectsnap.common.messaging.MessagingConstraints +import me.eternal.purrfectsnap.common.messaging.MessagingTask +import me.eternal.purrfectsnap.common.messaging.MessagingTaskType +import me.eternal.purrfectsnap.common.ui.createComposeAlertDialog +import me.eternal.purrfectsnap.common.ui.rememberAsyncMutableState +import me.eternal.purrfectsnap.common.util.ktx.copyToClipboard +import me.eternal.purrfectsnap.common.util.snap.BitmojiSelfie +import me.eternal.purrfectsnap.common.util.snap.RemoteMediaResolver +import me.eternal.purrfectsnap.core.action.AbstractAction +import me.eternal.purrfectsnap.core.features.impl.experiments.AddFriendSourceSpoof +import me.eternal.purrfectsnap.core.features.impl.experiments.BetterLocation +import me.eternal.purrfectsnap.core.features.impl.messaging.Messaging +import me.eternal.purrfectsnap.core.ui.ViewAppearanceHelper +import me.eternal.purrfectsnap.core.util.EvictingMap +import me.eternal.purrfectsnap.core.util.dataBuilder +import me.eternal.purrfectsnap.mapper.impl.FriendRelationshipChangerMapper +import java.text.DateFormat +import java.util.Date +import kotlin.coroutines.resume +import kotlin.random.Random + +class BulkMessagingAction : AbstractAction() { + private var followingLogCount = 0 + + enum class SortBy { + NONE, + USERNAME, + ADDED_TIMESTAMP, + SNAP_SCORE, + STREAK_LENGTH, + MOST_MESSAGES_SENT, + MOST_RECENT_MESSAGE, + NEAREST_LOCATION + } + + enum class Filter { + ALL, + MY_FRIENDS, + BLOCKED, + REMOVED_ME, + DELETED, + SUGGESTED, + BUSINESS_ACCOUNTS, + STREAKS, + NON_STREAKS, + FOLLOWING, + LOCATION_ON_MAP + } + + enum class ConversationType { + FRIENDS_ONLY, + GROUPS_ONLY, + BOTH + } + + private val translation by lazy { context.translation.getCategory("bulk_messaging_action") } + private val betterLocation by lazy { context.feature(BetterLocation::class) } + + private object BulkMessagingPalette { + val background = Brush.verticalGradient( + listOf( + Color(0xFF261F58), + Color(0xFF302A6D), + Color(0xFF241F52) + ) + ) + val cardOverlay = Brush.linearGradient( + listOf( + Color(0xFF2A2452).copy(alpha = 0.95f), + Color(0xFF1A143A).copy(alpha = 0.92f) + ) + ) + val glowStroke = Brush.linearGradient( + listOf( + Color(0xFF8C7BFF), + Color(0xFF5FD8FF) + ) + ) + val glowPrimary = Color(0xFF8C7BFF) + val glowSecondary = Color(0xFF5FD8FF) + val textPrimary = Color.White + val textSecondary = Color(0xFFD9D3FF) + val surface = Color(0xFF1E1A44) + val faintSurface = Color.White.copy(alpha = 0.06f) + val outline = Color.White.copy(alpha = 0.12f) + } + + private fun removeAction( + ctx: Context, + ids: List, + delay: Pair, + action: suspend (id: String, setDialogMessage: (String) -> Unit) -> Unit = { _, _ -> } + ) = context.coroutineScope.launch { + val statusTextView = TextView(ctx) + val dialog = withContext(Dispatchers.Main) { + ViewAppearanceHelper.newAlertDialogBuilder(ctx) + .setTitle("...") + .setView(LinearLayout(ctx).apply { + orientation = LinearLayout.VERTICAL + gravity = Gravity.CENTER + addView(statusTextView.apply { + layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT) + textAlignment = View.TEXT_ALIGNMENT_CENTER + }) + addView(ProgressBar(ctx)) + }) + .setCancelable(false) + .show() + } + + ids.forEachIndexed { index, id -> + launch(Dispatchers.Main) { + dialog.setTitle( + translation.format("progress_status", "index" to (index + 1).toString(), "total" to ids.size.toString()) + ) + } + runCatching { + action(id) { + launch(Dispatchers.Main) { + statusTextView.text = it + } + } + }.onFailure { + context.log.error("Failed to process $it", it) + context.shortToast(translation.format("failed_to_process", "id" to id)) + } + delay(Random.nextLong(delay.first, delay.second)) + } + withContext(Dispatchers.Main) { + dialog.dismiss() + } + } + + @Composable + private fun ConfirmationDialog( + onConfirm: () -> Unit, + onCancel: () -> Unit, + ) { + AlertDialog( + onDismissRequest = onCancel, + title = { Text(text = translation["confirmation_dialog.title"]) }, + text = { Text(text = translation["confirmation_dialog.message"]) }, + confirmButton = { + TextButton(onClick = onConfirm) { + Text(text = context.translation["button.positive"]) + } + }, + dismissButton = { + TextButton(onClick = onCancel) { + Text(text = context.translation["button.negative"]) + } + } + ) + } + + private fun filterFriends(friends: List, filter: Filter, nameFilter: String): List { + val userIdBlacklist = arrayOf( + context.database.myUserId, + "b42f1f70-5a8b-4c53-8c25-34e7ec9e6781", // myai + "84ee8839-3911-492d-8b94-72dd80f3713a", // teamsnapchat + ) + + if (filter == Filter.FOLLOWING) { + val uniqueLinkTypes = friends.map { it.friendLinkType }.distinct().sorted() + context.log.verbose("BulkMessaging: All unique friendLinkType values in database: $uniqueLinkTypes") + context.log.verbose("BulkMessaging: FOLLOWING enum value: ${FriendLinkType.FOLLOWING.value}") + } + + if (filter == Filter.FOLLOWING) followingLogCount = 0 + + val result = friends.filter { friend -> + friend.userId !in userIdBlacklist && when (filter) { + Filter.ALL -> true + Filter.MY_FRIENDS -> friend.friendLinkType == FriendLinkType.MUTUAL.value && friend.addedTimestamp > 0 + Filter.BLOCKED -> friend.friendLinkType == FriendLinkType.BLOCKED.value + Filter.REMOVED_ME -> friend.friendLinkType == FriendLinkType.OUTGOING.value && friend.addedTimestamp > 0 && friend.businessCategory == 0 + Filter.SUGGESTED -> friend.friendLinkType == FriendLinkType.SUGGESTED.value + Filter.DELETED -> friend.friendLinkType == FriendLinkType.DELETED.value + Filter.BUSINESS_ACCOUNTS -> friend.businessCategory > 0 + Filter.STREAKS -> friend.friendLinkType == FriendLinkType.MUTUAL.value && friend.addedTimestamp > 0 && friend.streakLength != 0 + Filter.NON_STREAKS -> friend.friendLinkType == FriendLinkType.MUTUAL.value&& friend.addedTimestamp > 0 && friend.streakLength == 0 + Filter.FOLLOWING -> { + val isFollowing = friend.friendLinkType == FriendLinkType.FOLLOWING.value || + (friend.friendLinkType == FriendLinkType.OUTGOING.value && + (friend.businessCategory > 0 || friend.addedTimestamp <= 0)) + if (isFollowing) { + when { + followingLogCount < 5 -> context.log.verbose("BulkMessaging: Friend ${friend.mutableUsername} (${friend.userId}) - LinkType=${friend.friendLinkType}, BusinessCategory=${friend.businessCategory}, Match=true") + followingLogCount == 5 -> context.log.verbose("BulkMessaging: Additional following entries truncated") + } + followingLogCount++ + } + isFollowing + } + Filter.LOCATION_ON_MAP -> betterLocation.locationHistory.contains(friend.userId) + } && nameFilter.takeIf { it.isNotBlank() }?.let { name -> + friend.mutableUsername?.contains( + name, + ignoreCase = true + ) == true || friend.displayName?.contains(name, ignoreCase = true) == true + } ?: true + } + + if (filter == Filter.FOLLOWING) { + context.log.verbose("BulkMessaging: FOLLOWING filter returned ${result.size} friends") + } + + return result + } + + private fun getDMLastMessage(userId: String?): ConversationMessage? { + return context.database.getDMConversationId(userId ?: return null)?.let { + context.database.getMessagesFromConversationId(it, 1) + }?.firstOrNull() + } + + @OptIn(ExperimentalMaterial3Api::class, ExperimentalFoundationApi::class) + @Composable + private fun BulkMessagingDialog() { + val coroutineScope = rememberCoroutineScope { Dispatchers.IO } + var sortBy by remember { mutableStateOf(SortBy.USERNAME) } + var filter by remember { mutableStateOf(Filter.REMOVED_ME) } + var conversationType by remember { mutableStateOf(ConversationType.FRIENDS_ONLY) } + var sortReverseOrder by remember { mutableStateOf(false) } + val selectedFriends = remember { mutableStateListOf() } + val selectedGroups = remember { mutableStateListOf() } + val friends = remember { mutableStateListOf() } + val groups = remember { mutableStateListOf() } + val hiddenFriendIds = remember { mutableStateListOf() } + val hiddenConversationIds = remember { mutableStateListOf() } + val bitmojiCache = remember { EvictingMap(50) } + val noBitmojiBitmap = remember { BitmapFactory.decodeResource(context.resources, android.R.drawable.ic_menu_report_image).asImageBitmap() } + + val focusManager = LocalFocusManager.current + var nameFilter by remember { mutableStateOf("") } + + suspend fun refreshList(clearSelected: Boolean = true) { + val myLocation = betterLocation.locationHistory[context.database.myUserId] + + withContext(Dispatchers.IO) { + // Load friends if needed + val newFriends = if (conversationType == ConversationType.FRIENDS_ONLY || conversationType == ConversationType.BOTH) { + context.database.getAllFriends().let { friends -> + filterFriends(friends, filter, nameFilter) + }.filter { it.userId?.let { id -> !hiddenFriendIds.contains(id) } == true }.toMutableList() + } else mutableListOf() + + val newGroups = if (conversationType == ConversationType.GROUPS_ONLY || conversationType == ConversationType.BOTH) { + runCatching { + context.database.getFeedEntries(Int.MAX_VALUE).filter { + it.conversationType == 1 && (nameFilter.isBlank() || it.feedDisplayName?.contains(nameFilter, ignoreCase = true) == true) && it.key?.let { key -> !hiddenConversationIds.contains(key) } == true + }.toMutableList() + }.getOrElse { + context.log.warn("Failed to load group feed entries: ${it.message}") + mutableListOf() + } + } else mutableListOf() + + when (sortBy) { + SortBy.NONE -> {} + SortBy.USERNAME -> { + newFriends.sortBy { it.mutableUsername } + newGroups.sortBy { it.feedDisplayName } + } + SortBy.ADDED_TIMESTAMP -> newFriends.sortBy { it.addedTimestamp } + SortBy.SNAP_SCORE -> newFriends.sortBy { it.snapScore } + SortBy.STREAK_LENGTH -> newFriends.sortBy { it.streakLength } + SortBy.MOST_MESSAGES_SENT -> newFriends.sortByDescending { + getDMLastMessage(it.userId)?.serverMessageId ?: 0 + } + SortBy.MOST_RECENT_MESSAGE -> { + newFriends.sortByDescending { + getDMLastMessage(it.userId)?.creationTimestamp + } + newGroups.sortByDescending { it.lastInteractionTimestamp } + } + SortBy.NEAREST_LOCATION -> { + if (myLocation != null) { + newFriends.sortBy { + betterLocation.locationHistory[it.userId]?.distanceTo(myLocation) + ?: Double.MAX_VALUE + } + } + } + } + if (sortReverseOrder) { + newFriends.reverse() + newGroups.reverse() + } + withContext(Dispatchers.Main) { + if (clearSelected) { + selectedFriends.clear() + selectedGroups.clear() + } + friends.clear() + friends.addAll(newFriends) + groups.clear() + groups.addAll(newGroups) + } + } + } + + fun markRemoval(friendId: String? = null, conversationId: String? = null) { + coroutineScope.launch(Dispatchers.Main) { + conversationId?.let { + if (!hiddenConversationIds.contains(it)) hiddenConversationIds.add(it) + selectedGroups.remove(it) + groups.removeAll { entry -> entry.key == it } + } + friendId?.let { + if (!hiddenFriendIds.contains(it)) hiddenFriendIds.add(it) + selectedFriends.remove(it) + friends.removeAll { info -> info.userId == it } + } + } + } + + Box( + modifier = Modifier + .fillMaxWidth() + .background(BulkMessagingPalette.background) + .padding(horizontal = 10.dp, vertical = 8.dp) + ) { + Surface( + modifier = Modifier + .fillMaxWidth() + .widthIn(max = 760.dp), + shape = RoundedCornerShape(26.dp), + color = Color.Transparent, + tonalElevation = 0.dp, + shadowElevation = 18.dp, + border = BorderStroke(1.dp, BulkMessagingPalette.glowStroke) + ) { + Column( + modifier = Modifier + .background(BulkMessagingPalette.cardOverlay) + .padding(horizontal = 12.dp, vertical = 10.dp), + verticalArrangement = Arrangement.spacedBy(12.dp), + horizontalAlignment = Alignment.CenterHorizontally + ) { + Column( + modifier = Modifier.fillMaxWidth(), + verticalArrangement = Arrangement.spacedBy(4.dp), + horizontalAlignment = Alignment.CenterHorizontally + ) { + Text( + text = "Bulk messaging", + style = MaterialTheme.typography.titleLarge, + color = BulkMessagingPalette.textPrimary, + fontWeight = FontWeight.SemiBold + ) + Text( + text = translation["conversation_types.${conversationType.name.lowercase()}"], + style = MaterialTheme.typography.bodyMedium, + color = BulkMessagingPalette.textSecondary, + textAlign = TextAlign.Center + ) + } + // Top tabs: Friends Only | Groups Only | Friends & Groups + val tabs = remember { + listOf( + ConversationType.FRIENDS_ONLY to translation["conversation_types.friends_only"], + ConversationType.GROUPS_ONLY to translation["conversation_types.groups_only"], + ConversationType.BOTH to translation["conversation_types.both"], + ) + } + ElevatedCard( + modifier = Modifier + .fillMaxWidth() + .border(BorderStroke(1.dp, BulkMessagingPalette.outline), RoundedCornerShape(18.dp)), + shape = RoundedCornerShape(18.dp), + colors = CardDefaults.elevatedCardColors(containerColor = Color.Transparent), + elevation = CardDefaults.elevatedCardElevation(defaultElevation = 0.dp) + ) { + Row( + modifier = Modifier + .fillMaxWidth() + .background(BulkMessagingPalette.faintSurface, RoundedCornerShape(18.dp)) + .padding(6.dp), + horizontalArrangement = Arrangement.spacedBy(8.dp) + ) { + tabs.forEach { (type, title) -> + val selected = conversationType == type + val label = when (type) { + ConversationType.FRIENDS_ONLY -> translation["conversation_types.friends_only"] + ConversationType.GROUPS_ONLY -> translation["conversation_types.groups_only"].replace(" ", "\n") + ConversationType.BOTH -> translation["conversation_types.both"].replace(" & ", "\n") + } + Box( + modifier = Modifier + .weight(1f) + .border( + BorderStroke(1.dp, if (selected) BulkMessagingPalette.glowPrimary else BulkMessagingPalette.outline), + RoundedCornerShape(14.dp) + ) + .background( + if (selected) BulkMessagingPalette.glowPrimary.copy(alpha = 0.12f) else Color.Transparent, + RoundedCornerShape(14.dp) + ) + .clickable { + if (!selected) { + conversationType = type + coroutineScope.launch { refreshList() } + } + } + .padding(vertical = 10.dp), + contentAlignment = Alignment.Center + ) { + Text( + text = label, + color = if (selected) BulkMessagingPalette.textPrimary else BulkMessagingPalette.textSecondary, + fontWeight = if (selected) FontWeight.SemiBold else FontWeight.Normal, + textAlign = TextAlign.Center + ) + } + } + } + } + + + ElevatedCard( + modifier = Modifier + .fillMaxWidth() + .border(BorderStroke(1.dp, BulkMessagingPalette.outline), RoundedCornerShape(18.dp)), + shape = RoundedCornerShape(18.dp), + colors = CardDefaults.elevatedCardColors(containerColor = Color.Transparent), + elevation = CardDefaults.elevatedCardElevation(defaultElevation = 0.dp) + ) { + Column( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 12.dp, vertical = 10.dp), + verticalArrangement = Arrangement.spacedBy(10.dp) + ) { + val searchShape = RoundedCornerShape(14.dp) + BasicTextField( + value = nameFilter, + onValueChange = { + nameFilter = it + coroutineScope.launch { refreshList(clearSelected = false) } + }, + singleLine = true, + textStyle = MaterialTheme.typography.bodyMedium.copy( + color = BulkMessagingPalette.textPrimary + ), + cursorBrush = SolidColor(BulkMessagingPalette.glowPrimary), + modifier = Modifier.fillMaxWidth() + ) { innerTextField -> + Box( + modifier = Modifier + .fillMaxWidth() + .border(1.dp, BulkMessagingPalette.outline, searchShape) + .background(Color.Transparent, searchShape) + .padding(horizontal = 12.dp, vertical = 10.dp) + ) { + if (nameFilter.isEmpty()) { + Text( + text = translation["search_by_name"], + color = BulkMessagingPalette.textSecondary + ) + } + innerTextField() + } + } + + Row( + modifier = Modifier.fillMaxWidth(), + verticalAlignment = Alignment.CenterVertically + ) { + var filterMenuExpanded by remember { mutableStateOf(false) } + ExposedDropdownMenuBox( + expanded = filterMenuExpanded, + onExpandedChange = { filterMenuExpanded = it }, + ) { + ElevatedCard( + modifier = Modifier + .menuAnchor(MenuAnchorType.PrimaryNotEditable) + .border(BorderStroke(1.dp, BulkMessagingPalette.outline), RoundedCornerShape(14.dp)), + shape = RoundedCornerShape(14.dp), + colors = CardDefaults.elevatedCardColors(containerColor = Color.Transparent) + ) { + Text( + text = translation["filters.${filter.name.lowercase()}"], + modifier = Modifier.padding(horizontal = 10.dp, vertical = 6.dp), + color = BulkMessagingPalette.textPrimary + ) + } + + DropdownMenu( + expanded = filterMenuExpanded, + onDismissRequest = { filterMenuExpanded = false }, + containerColor = BulkMessagingPalette.surface + ) { + Filter.entries.forEach { entry -> + DropdownMenuItem( + onClick = { + filter = entry + filterMenuExpanded = false + }, + text = { + Text( + text = translation["filters.${entry.name.lowercase()}"], + fontWeight = if (entry == filter) FontWeight.Bold else FontWeight.Normal, + color = if (entry == filter) BulkMessagingPalette.glowPrimary else BulkMessagingPalette.textPrimary + ) + } + ) + } + } + } + + Spacer(Modifier.width(8.dp)) + + var sortMenuExpanded by remember { mutableStateOf(false) } + ExposedDropdownMenuBox( + expanded = sortMenuExpanded, + onExpandedChange = { sortMenuExpanded = it }, + ) { + ElevatedCard( + modifier = Modifier + .menuAnchor(MenuAnchorType.PrimaryNotEditable) + .border(BorderStroke(1.dp, BulkMessagingPalette.outline), RoundedCornerShape(14.dp)), + shape = RoundedCornerShape(14.dp), + colors = CardDefaults.elevatedCardColors(containerColor = Color.Transparent) + ) { + Text( + text = translation["sort_by"], + modifier = Modifier.padding(horizontal = 10.dp, vertical = 6.dp), + color = BulkMessagingPalette.textPrimary + ) + } + + DropdownMenu( + expanded = sortMenuExpanded, + onDismissRequest = { sortMenuExpanded = false }, + containerColor = BulkMessagingPalette.surface + ) { + SortBy.entries.forEach { entry -> + DropdownMenuItem( + onClick = { + sortBy = entry + sortMenuExpanded = false + }, + text = { + Text( + text = translation["sort_options.${entry.name.lowercase()}"], + fontWeight = if (entry == sortBy) FontWeight.Bold else FontWeight.Normal, + color = if (entry == sortBy) BulkMessagingPalette.glowPrimary else BulkMessagingPalette.textPrimary + ) + } + ) + } + } + } + + Spacer(modifier = Modifier.weight(1f)) + + Text( + text = context.translation["manager.dialogs.messaging_action.select_all_button"], + fontSize = 14.sp, + color = BulkMessagingPalette.textSecondary + ) + + Checkbox( + checked = { + val totalItems = when (conversationType) { + ConversationType.FRIENDS_ONLY -> friends.size + ConversationType.GROUPS_ONLY -> groups.size + ConversationType.BOTH -> friends.size + groups.size + } + val selectedItems = when (conversationType) { + ConversationType.FRIENDS_ONLY -> selectedFriends.size + ConversationType.GROUPS_ONLY -> selectedGroups.size + ConversationType.BOTH -> selectedFriends.size + selectedGroups.size + } + totalItems > 0 && selectedItems == totalItems + }(), + onCheckedChange = { state -> + if (state) { + when (conversationType) { + ConversationType.FRIENDS_ONLY -> { + friends.mapNotNull { it.userId }.forEach { userId -> + if (!selectedFriends.contains(userId)) { + selectedFriends.add(userId) + } + } + } + ConversationType.GROUPS_ONLY -> { + groups.mapNotNull { it.key }.forEach { conversationId -> + if (!selectedGroups.contains(conversationId)) { + selectedGroups.add(conversationId) + } + } + } + ConversationType.BOTH -> { + friends.mapNotNull { it.userId }.forEach { userId -> + if (!selectedFriends.contains(userId)) { + selectedFriends.add(userId) + } + } + groups.mapNotNull { it.key }.forEach { conversationId -> + if (!selectedGroups.contains(conversationId)) { + selectedGroups.add(conversationId) + } + } + } + } + } else { + when (conversationType) { + ConversationType.FRIENDS_ONLY -> { + if (nameFilter.isNotBlank()) { + filterFriends(friends, filter, nameFilter).mapNotNull { it.userId }.forEach { userId -> + selectedFriends.remove(userId) + } + } else { + selectedFriends.clear() + } + } + ConversationType.GROUPS_ONLY -> { + if (nameFilter.isNotBlank()) { + groups.filter { it.feedDisplayName?.contains(nameFilter, ignoreCase = true) == true } + .mapNotNull { it.key }.forEach { conversationId -> + selectedGroups.remove(conversationId) + } + } else { + selectedGroups.clear() + } + } + ConversationType.BOTH -> { + if (nameFilter.isNotBlank()) { + filterFriends(friends, filter, nameFilter).mapNotNull { it.userId }.forEach { userId -> + selectedFriends.remove(userId) + } + groups.filter { it.feedDisplayName?.contains(nameFilter, ignoreCase = true) == true } + .mapNotNull { it.key }.forEach { conversationId -> + selectedGroups.remove(conversationId) + } + } else { + selectedFriends.clear() + selectedGroups.clear() + } + } + } + } + }, + colors = CheckboxDefaults.colors( + checkedColor = BulkMessagingPalette.glowPrimary, + uncheckedColor = BulkMessagingPalette.outline, + checkmarkColor = BulkMessagingPalette.textPrimary + ) + ) + } + } + } + + ElevatedCard( + modifier = Modifier + .fillMaxWidth() + .border(BorderStroke(1.dp, BulkMessagingPalette.outline), RoundedCornerShape(18.dp)), + shape = RoundedCornerShape(18.dp), + colors = CardDefaults.elevatedCardColors(containerColor = Color.Transparent), + elevation = CardDefaults.elevatedCardElevation(defaultElevation = 0.dp) + ) { + LazyColumn( + modifier = Modifier + .fillMaxWidth() + .weight(1f) + .heightIn(min = 200.dp) + .padding(horizontal = 8.dp, vertical = 6.dp), + verticalArrangement = Arrangement.spacedBy(8.dp) + ) { + item { + val isEmpty = when (conversationType) { + ConversationType.FRIENDS_ONLY -> friends.isEmpty() + ConversationType.GROUPS_ONLY -> groups.isEmpty() + ConversationType.BOTH -> friends.isEmpty() && groups.isEmpty() + } + if (isEmpty) { + Text(text = when (conversationType) { + ConversationType.FRIENDS_ONLY -> translation["no_friends_found"] + ConversationType.GROUPS_ONLY -> translation["no_groups_found"] + ConversationType.BOTH -> translation["no_friends_or_groups_found"] + }, fontSize = 12.sp, fontWeight = FontWeight.Light, modifier = Modifier.fillMaxWidth(), textAlign = TextAlign.Center) + } + } + items(friends, key = { it.userId!! }) { friendInfo -> + var bitmojiBitmap by remember(friendInfo) { mutableStateOf(bitmojiCache[friendInfo.bitmojiAvatarId]) } + + fun selectFriend(state: Boolean) { + friendInfo.userId?.let { + if (state) { + selectedFriends.add(it) + } else { + selectedFriends.remove(it) + } + } + } + + ElevatedCard( + modifier = Modifier + .fillMaxWidth() + .border(BorderStroke(1.dp, BulkMessagingPalette.outline), RoundedCornerShape(14.dp)), + colors = CardDefaults.elevatedCardColors(containerColor = BulkMessagingPalette.surface), + shape = RoundedCornerShape(14.dp) + ) { + Row( + modifier = Modifier + .fillMaxWidth() + .background(Color.Transparent) + .clickable { + selectFriend(!selectedFriends.contains(friendInfo.userId)) + }.pointerInput(Unit) { + detectTapGestures( + onLongPress = { context.androidContext.copyToClipboard(friendInfo.mutableUsername.toString()) } + ) + } + .padding(horizontal = 10.dp, vertical = 8.dp), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(10.dp) + ) { + LaunchedEffect(friendInfo) { + withContext(Dispatchers.IO) { + if (bitmojiBitmap != null || friendInfo.bitmojiAvatarId == null || friendInfo.bitmojiSelfieId == null) return@withContext + + val bitmojiUrl = BitmojiSelfie.getBitmojiSelfie(friendInfo.bitmojiSelfieId, friendInfo.bitmojiAvatarId, BitmojiSelfie.BitmojiSelfieType.NEW_THREE_D) ?: return@withContext + + runCatching { + RemoteMediaResolver.downloadMedia(bitmojiUrl) { inputStream, length -> + bitmojiCache[friendInfo.bitmojiAvatarId ?: return@withContext] = BitmapFactory.decodeStream(inputStream).also { + bitmojiBitmap = it + } + } + } + } + } + + Image( + bitmap = remember (bitmojiBitmap) { bitmojiBitmap?.asImageBitmap() ?: noBitmojiBitmap }, + contentDescription = null, + modifier = Modifier.size(35.dp) + ) + + Column( + modifier = Modifier.weight(1f), + ) { + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.spacedBy(3.dp), + verticalAlignment = Alignment.CenterVertically + ){ + Text(text = (friendInfo.displayName ?: friendInfo.mutableUsername).toString(), fontSize = 16.sp, fontWeight = FontWeight.Bold, overflow = TextOverflow.Ellipsis, maxLines = 1, lineHeight = 10.sp, color = BulkMessagingPalette.textPrimary) + Text(text = friendInfo.mutableUsername.toString(), fontSize = 10.sp, fontWeight = FontWeight.Light, overflow = TextOverflow.Ellipsis, maxLines = 1, lineHeight = 10.sp, color = BulkMessagingPalette.textSecondary) + } + val lastMessage by rememberAsyncMutableState(defaultValue = null) { + getDMLastMessage(friendInfo.userId) + } + + val userInfo = remember(friendInfo, lastMessage) { + buildString { + append(translation["relationship"]) + append(context.translation["friendship_link_type.${FriendLinkType.fromValue(friendInfo.friendLinkType).shortName}"]) + friendInfo.addedTimestamp.takeIf { it > 0L }?.let { + append("\nAdded ${DateFormat.getDateTimeInstance().format(Date(it))}") + } + friendInfo.snapScore.takeIf { it > 0 }?.let { + append("\nSnap Score: $it") + } + friendInfo.streakLength.takeIf { it > 0 }?.let { + append("\nStreaks length: $it") + } + lastMessage?.let { + append("\nSent messages: ${it.serverMessageId}") + append("\nLast message: ${DateFormat.getDateTimeInstance().format(Date(it.creationTimestamp))}") + } + betterLocation.locationHistory[context.database.myUserId]?.let { myLocation -> + betterLocation.locationHistory[friendInfo.userId]?.let { + append("\n${myLocation.distanceTo(it).let { distance -> + if (distance < 1) "${(distance * 1000).toInt()} m" else "${distance.toInt()} km" + } } away") + } + } + } + } + Text(text = userInfo, fontSize = 12.sp, fontWeight = FontWeight.Light, lineHeight = 12.sp, overflow = TextOverflow.Ellipsis, color = BulkMessagingPalette.textSecondary) + } + + Checkbox( + checked = selectedFriends.contains(friendInfo.userId), + onCheckedChange = { selectFriend(it) }, + colors = CheckboxDefaults.colors( + checkedColor = BulkMessagingPalette.glowPrimary, + uncheckedColor = BulkMessagingPalette.outline, + checkmarkColor = BulkMessagingPalette.textPrimary + ) + ) + } + } + } + + // Group items + items(groups, key = { it.key!! }) { groupInfo -> + fun selectGroup(state: Boolean) { + groupInfo.key?.let { + if (state) { + selectedGroups.add(it) + } else { + selectedGroups.remove(it) + } + } + } + + ElevatedCard( + modifier = Modifier + .fillMaxWidth() + .border(BorderStroke(1.dp, BulkMessagingPalette.outline), RoundedCornerShape(14.dp)), + colors = CardDefaults.elevatedCardColors(containerColor = BulkMessagingPalette.surface), + shape = RoundedCornerShape(14.dp) + ) { + Row( + modifier = Modifier + .fillMaxWidth() + .background(Color.Transparent) + .clickable { + selectGroup(!selectedGroups.contains(groupInfo.key)) + }.pointerInput(Unit) { + detectTapGestures( + onLongPress = { context.androidContext.copyToClipboard(groupInfo.feedDisplayName.toString()) } + ) + } + .padding(horizontal = 10.dp, vertical = 8.dp), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(10.dp) + ) { + // Group icon placeholder + Image( + bitmap = noBitmojiBitmap, + contentDescription = null, + modifier = Modifier.size(35.dp) + ) + + Column( + modifier = Modifier.weight(1f), + ) { + Text( + text = groupInfo.feedDisplayName?.toString() ?: translation["unknown_group"], + fontSize = 16.sp, + fontWeight = FontWeight.Bold, + overflow = TextOverflow.Ellipsis, + maxLines = 1, + lineHeight = 10.sp, + color = BulkMessagingPalette.textPrimary + ) + + val groupInfo = remember(groupInfo) { + buildString { + append(translation["type_group_chat"]) + groupInfo.lastInteractionTimestamp.takeIf { it > 0L }?.let { + append("\nLast interaction: ${DateFormat.getDateTimeInstance().format(Date(it))}") + } + } + } + Text(text = groupInfo, fontSize = 12.sp, fontWeight = FontWeight.Light, lineHeight = 12.sp, overflow = TextOverflow.Ellipsis, color = BulkMessagingPalette.textSecondary) + } + + Checkbox( + checked = selectedGroups.contains(groupInfo.key), + onCheckedChange = { selectGroup(it) }, + colors = CheckboxDefaults.colors( + checkedColor = BulkMessagingPalette.glowPrimary, + uncheckedColor = BulkMessagingPalette.outline, + checkmarkColor = BulkMessagingPalette.textPrimary + ) + ) + } + } + } + } + + var showConfirmationDialog by remember { mutableStateOf(false) } + var action by remember { mutableStateOf({}) } + + if (showConfirmationDialog) { + ConfirmationDialog( + onConfirm = { + action() + action = {} + showConfirmationDialog = false + }, + onCancel = { + action = {} + showConfirmationDialog = false + } + ) + } + + val ctx = LocalContext.current + + val actions = remember(selectedFriends.size, selectedGroups.size, conversationType, filter) { + val following = filter == Filter.FOLLOWING + buildMap<() -> String, () -> Unit> { + val messagingFeature = context.feature(Messaging::class) + fun fetchConversations(ids: List, errorKey: String, block: (Map) -> Unit) { + if (ids.isEmpty()) { + block(emptyMap()) + return + } + fun run(map: Map) = block(map) + messagingFeature.conversationManager?.getOneOnOneConversationIds(ids, onError = { error -> + context.shortToast(translation.format(errorKey, "error" to error)) + run(emptyMap()) + }, onSuccess = { conversations -> + run(conversations.toMap()) + }) ?: run(emptyMap()) + } + fun MutableMap<() -> String, () -> Unit>.addUnfollowActions(errorKey: String) { + if (selectedFriends.isEmpty()) return + put({ "${translation["unfollow"]} (${selectedFriends.size})" }) { + val ids = selectedFriends.toList() + selectedFriends.clear() + fetchConversations(ids, errorKey) { conversations -> + removeAction(ctx, ids, 500L to 1200L) { userId, setDialogMessage -> + unfollowUser(userId) + conversations[userId]?.let { conversationId -> + clearConversationFeed(conversationId, setDialogMessage, onFailure = { + setDialogMessage(translation["actions.unfollow"]) + }, onSuccess = { + markRemoval(userId, conversationId) + }) + } ?: setDialogMessage(translation["actions.unfollow"]) + }.invokeOnCompletion { coroutineScope.launch { refreshList() } } + } + } + put({ "${translation["unfollow"]} & ${translation.format("clean_conversations", "count" to selectedFriends.size.toString())}" }) { + val ids = selectedFriends.toList() + selectedFriends.clear() + fetchConversations(ids, errorKey) { conversations -> + val reverse = conversations.entries.associate { it.value to it.key } + removeAction(ctx, conversations.values.distinct(), 500L to 1200L) { conversationId, setDialogMessage -> + cleanConversation(conversationId, setDialogMessage) + reverse[conversationId]?.let { unfollowUser(it) } + clearConversationFeed(conversationId, setDialogMessage, onSuccess = { + reverse[conversationId]?.let { markRemoval(it, conversationId) } + }) + }.invokeOnCompletion { coroutineScope.launch { refreshList() } } + } + } + } + when (conversationType) { + ConversationType.FRIENDS_ONLY -> if (following) { + addUnfollowActions("failed_to_fetch_conversations") + } else { + put({ translation.format("clean_conversations", "count" to selectedFriends.size.toString()) }) { + context.feature(Messaging::class).conversationManager?.getOneOnOneConversationIds(selectedFriends.toList().also { selectedFriends.clear() }, onError = { error -> + context.shortToast(translation.format("failed_to_fetch_conversations", "error" to error)) + }, onSuccess = { conversations -> + removeAction(ctx, conversations.map { it.second }.distinct(), 10L to 40L) { conversationId, setDialogMessage -> + cleanConversation(conversationId, setDialogMessage) + }.invokeOnCompletion { coroutineScope.launch { refreshList() } } + }) + } + put({ translation.format("clear_friend_feed", "count" to selectedFriends.size.toString()) }) { + val ids = selectedFriends.toList() + fetchConversations(ids, "failed_to_fetch_conversations") { conversations -> + val conversationIds = conversations.values.distinct() + if (conversationIds.isEmpty()) { + selectedFriends.clear() + coroutineScope.launch { refreshList() } + return@fetchConversations + } + removeAction(ctx, conversationIds, 10L to 40L) { conversationId, setDialogMessage -> + clearConversationFeed(conversationId, setDialogMessage, onSuccess = { + markRemoval(conversationId = conversationId) + coroutineScope.launch { refreshList(clearSelected = false) } + }) + }.invokeOnCompletion { + selectedFriends.clear() + coroutineScope.launch { refreshList() } + } + } + } + put({ translation.format("remove_friends", "count" to selectedFriends.size.toString()) }) { + val ids = selectedFriends.toList() + selectedFriends.clear() + fetchConversations(ids, "failed_to_fetch_conversations") { conversations -> + removeAction(ctx, ids, 500L to 1200L) { userId, setDialogMessage -> + removeFriend(userId) + conversations[userId]?.let { conversationId -> + clearConversationFeed(conversationId, setDialogMessage, onFailure = { + setDialogMessage(translation["actions.remove"]) + }, onSuccess = { + markRemoval(userId, conversationId) + }) + } ?: setDialogMessage(translation["actions.remove"]) + }.invokeOnCompletion { coroutineScope.launch { refreshList() } } + } + } + put({ translation.format("clean_conversations_and_remove_friends", "count" to selectedFriends.size.toString()) }) { + context.feature(Messaging::class).conversationManager?.getOneOnOneConversationIds(selectedFriends.toList().also { selectedFriends.clear() }, onError = { error -> + context.shortToast(translation.format("failed_to_fetch_conversations", "error" to error)) + }, onSuccess = { conversations -> + removeAction(ctx, conversations.map { it.second }.distinct(), 500L to 1200L) { conversationId, setDialogMessage -> + cleanConversation(conversationId, setDialogMessage) + conversations.firstOrNull { it.second == conversationId }?.first?.let { friendId -> + removeFriend(friendId) + clearConversationFeed(conversationId, setDialogMessage, onSuccess = { + markRemoval(friendId, conversationId) + }) + } + }.invokeOnCompletion { coroutineScope.launch { refreshList() } } + }) + } + } + ConversationType.GROUPS_ONLY -> if (!following) { + put({ translation.format("clean_group_conversations", "count" to selectedGroups.size.toString()) }) { + removeAction(ctx, selectedGroups.toList().also { selectedGroups.clear() }, 10L to 40L) { conversationId, setDialogMessage -> + cleanConversation(conversationId, setDialogMessage) + }.invokeOnCompletion { coroutineScope.launch { refreshList() } } + } + put({ translation.format("clear_group_feed", "count" to selectedGroups.size.toString()) }) { + val ids = selectedGroups.toList() + if (ids.isEmpty()) { + selectedGroups.clear() + coroutineScope.launch { refreshList() } + } else { + removeAction(ctx, ids, 10L to 40L) { conversationId, setDialogMessage -> + clearConversationFeed(conversationId, setDialogMessage, onSuccess = { + markRemoval(conversationId = conversationId) + coroutineScope.launch { refreshList(clearSelected = false) } + }) + }.invokeOnCompletion { + selectedGroups.clear() + coroutineScope.launch { refreshList() } + } + } + } + } + ConversationType.BOTH -> if (following) { + addUnfollowActions("failed_to_fetch_friend_conversations") + } else { + put({ translation.format("clean_all_conversations", "count" to (selectedFriends.size + selectedGroups.size).toString()) }) { + if (selectedFriends.isNotEmpty()) { + context.feature(Messaging::class).conversationManager?.getOneOnOneConversationIds(selectedFriends.toList(), onError = { error -> + context.shortToast(translation.format("failed_to_fetch_friend_conversations", "error" to error)) + }, onSuccess = { conversations -> + removeAction(ctx, conversations.map { it.second }.distinct(), 10L to 40L) { conversationId, setDialogMessage -> + cleanConversation(conversationId, setDialogMessage) + }.invokeOnCompletion { + if (selectedGroups.isNotEmpty()) { + removeAction(ctx, selectedGroups.toList(), 10L to 40L) { conversationId, setDialogMessage -> + cleanConversation(conversationId, setDialogMessage) + }.invokeOnCompletion { + selectedFriends.clear() + selectedGroups.clear() + coroutineScope.launch { refreshList() } + } + } else { + selectedFriends.clear() + coroutineScope.launch { refreshList() } + } + } + }) + } else if (selectedGroups.isNotEmpty()) { + removeAction(ctx, selectedGroups.toList().also { selectedGroups.clear() }, 10L to 40L) { conversationId, setDialogMessage -> + cleanConversation(conversationId, setDialogMessage) + }.invokeOnCompletion { coroutineScope.launch { refreshList() } } + } + } + put({ translation.format("clear_all_feed", "count" to (selectedFriends.size + selectedGroups.size).toString()) }) { + val friendIds = selectedFriends.toList() + val groupIds = selectedGroups.toList() + fun finish() { + selectedFriends.clear() + selectedGroups.clear() + coroutineScope.launch { refreshList() } + } + fetchConversations(friendIds, "failed_to_fetch_friend_conversations") { conversations -> + val conversationIds = conversations.values.distinct() + when { + conversationIds.isNotEmpty() -> removeAction(ctx, conversationIds, 10L to 40L) { conversationId, setDialogMessage -> + clearConversationFeed(conversationId, setDialogMessage, onSuccess = { + markRemoval(conversationId = conversationId) + coroutineScope.launch { refreshList(clearSelected = false) } + }) + }.invokeOnCompletion { + if (groupIds.isNotEmpty()) { + removeAction(ctx, groupIds, 10L to 40L) { conversationId, setDialogMessage -> + clearConversationFeed(conversationId, setDialogMessage, onSuccess = { + markRemoval(conversationId = conversationId) + coroutineScope.launch { refreshList(clearSelected = false) } + }) + }.invokeOnCompletion { finish() } + } else finish() + } + groupIds.isNotEmpty() -> removeAction(ctx, groupIds, 10L to 40L) { conversationId, setDialogMessage -> + clearConversationFeed(conversationId, setDialogMessage, onSuccess = { + markRemoval(conversationId = conversationId) + coroutineScope.launch { refreshList(clearSelected = false) } + }) + }.invokeOnCompletion { finish() } + else -> finish() + } + } + } + put({ translation.format("remove_friends", "count" to selectedFriends.size.toString()) }) { + val ids = selectedFriends.toList() + selectedFriends.clear() + fetchConversations(ids, "failed_to_fetch_friend_conversations") { conversations -> + removeAction(ctx, ids, 500L to 1200L) { userId, setDialogMessage -> + removeFriend(userId) + conversations[userId]?.let { conversationId -> + clearConversationFeed(conversationId, setDialogMessage, onFailure = { + setDialogMessage(translation["actions.remove"]) + }, onSuccess = { + markRemoval(userId, conversationId) + }) + } ?: setDialogMessage(translation["actions.remove"]) + }.invokeOnCompletion { coroutineScope.launch { refreshList() } } + } + } + } + } + } + } + + ElevatedCard( + modifier = Modifier + .fillMaxWidth() + .border(BorderStroke(1.dp, BulkMessagingPalette.outline), RoundedCornerShape(18.dp)), + shape = RoundedCornerShape(18.dp), + colors = CardDefaults.elevatedCardColors(containerColor = Color.Transparent), + elevation = CardDefaults.elevatedCardElevation(defaultElevation = 0.dp) + ) { + Column( + modifier = Modifier + .fillMaxWidth() + .padding(8.dp), + verticalArrangement = Arrangement.spacedBy(6.dp), + horizontalAlignment = Alignment.CenterHorizontally + ) { + Text( + text = "Choose an action", + style = MaterialTheme.typography.titleMedium, + color = BulkMessagingPalette.textPrimary, + fontWeight = FontWeight.SemiBold, + textAlign = TextAlign.Center + ) + var actionsMenuExpanded by remember { mutableStateOf(false) } + val actionsList = actions.toList() + Button( + onClick = { actionsMenuExpanded = true }, + enabled = when (conversationType) { + ConversationType.FRIENDS_ONLY -> selectedFriends.isNotEmpty() + ConversationType.GROUPS_ONLY -> selectedGroups.isNotEmpty() + ConversationType.BOTH -> selectedFriends.isNotEmpty() || selectedGroups.isNotEmpty() + }, + colors = ButtonDefaults.buttonColors( + containerColor = BulkMessagingPalette.glowPrimary, + contentColor = BulkMessagingPalette.textPrimary + ) + ) { + Text(text = translation["actions.title"]) + } + DropdownMenu( + expanded = actionsMenuExpanded, + onDismissRequest = { actionsMenuExpanded = false }, + containerColor = BulkMessagingPalette.surface + ) { + actionsList.forEach { (textBuilder, actionFunction) -> + DropdownMenuItem( + text = { Text(text = remember(selectedFriends.size, selectedGroups.size) { textBuilder() }) }, + onClick = { + actionsMenuExpanded = false + showConfirmationDialog = true + action = actionFunction + } + ) + } + } + } + } + + } + } + } + + LaunchedEffect(sortBy, sortReverseOrder) { + coroutineScope.launch { + refreshList(clearSelected = false) + } + focusManager.clearFocus() + } + + LaunchedEffect(filter) { + coroutineScope.launch { + if (filter == Filter.FOLLOWING) { + kotlinx.coroutines.delay(50) + } + refreshList() + } + focusManager.clearFocus() + } + + LaunchedEffect(conversationType) { + coroutineScope.launch { + refreshList() + } + focusManager.clearFocus() + } + } + + } + + override fun run() { + context.coroutineScope.launch(Dispatchers.Main) { + createComposeAlertDialog(context.mainActivity!!) { + BulkMessagingDialog() + }.apply { + setCanceledOnTouchOutside(false) + show() + } + } + } + + private fun removeFriend(userId: String) { + context.mappings.useMapper(FriendRelationshipChangerMapper::class) { + val friendRelationshipChangerInstance = context.feature(AddFriendSourceSpoof::class).friendRelationshipChangerInstance!! + val runFriendDurableJobMethod = classReference.getAsClass()?.methods?.first { + it.name == runFriendDurableJob.getAsString() + } ?: throw Exception("Failed to find runFriendDurableJobMethod method") + + val removeFriendDurableJob = context.androidContext.classLoader.loadClass("com.snap.identity.job.snapchatter.RemoveFriendDurableJob") + .constructors.firstOrNull { + it.parameterTypes.size == 1 + }?.run { + newInstance( + parameterTypes[0].dataBuilder { + set("a", userId) + set("b", "DELETED_BY_MY_FRIENDS") + set("f", "") + } + ) + } ?: throw Exception("Failed to create RemoveFriendDurableJob instance") + + val completable = runFriendDurableJobMethod.invoke(null, + friendRelationshipChangerInstance, + userId, + removeFriendDurableJob, + 0x5, + "DELETED_BY_MY_FRIENDS", + )!! + completable::class.java.methods.first { + it.name == "subscribe" && it.parameterTypes.isEmpty() + }.invoke(completable) + } + } + + private fun unfollowUser(userId: String) { + context.mappings.useMapper(FriendRelationshipChangerMapper::class) { + val friendRelationshipChangerInstance = context.feature(AddFriendSourceSpoof::class).friendRelationshipChangerInstance!! + val runFriendDurableJobMethod = classReference.getAsClass()?.methods?.first { + it.name == runFriendDurableJob.getAsString() + } ?: throw Exception("Failed to find runFriendDurableJobMethod method") + + val unfollowJobClass = runCatching { + context.androidContext.classLoader.loadClass("com.snap.identity.job.snapchatter.UnfollowFriendDurableJob") + }.getOrNull() ?: run { + context.log.warn("Unfollow job unavailable, removing friend instead") + removeFriend(userId) + return@useMapper + } + + val unfollowFriendDurableJob = unfollowJobClass.constructors.firstOrNull { + it.parameterTypes.size == 1 + }?.run { + newInstance( + parameterTypes[0].dataBuilder { + set("a", userId) + } + ) + } ?: run { + context.log.warn("Failed to create unfollow job instance, removing friend instead") + removeFriend(userId) + return@useMapper + } + + val completable = runFriendDurableJobMethod.invoke(null, + friendRelationshipChangerInstance, + userId, + unfollowFriendDurableJob, + 0x6, + null, + )!! + completable::class.java.methods.first { + it.name == "subscribe" && it.parameterTypes.isEmpty() + }.invoke(completable) + } + } + + private suspend fun cleanConversation( + conversationId: String, + setDialogMessage: (String) -> Unit + ) { + val messageCount = mutableIntStateOf(0) + MessagingTask( + context.messagingBridge, + conversationId, + taskType = MessagingTaskType.DELETE, + constraints = listOf(MessagingConstraints.MY_USER_ID(context.messagingBridge), { + contentType != ContentType.STATUS.id + }), + processedMessageCount = messageCount, + onSuccess = { + setDialogMessage(translation.format("deleted_messages", "count" to messageCount.intValue.toString())) + }, + ).run() + } + + private suspend fun clearConversationFeed( + conversationId: String, + setDialogMessage: (String) -> Unit, + onFailure: (() -> Unit)? = null, + onSuccess: (() -> Unit)? = null + ) = suspendCancellableCoroutine { continuation -> + fun resume() { + if (!continuation.isCompleted) continuation.resume(Unit) + } + runCatching { + context.feature(Messaging::class).clearConversationFromFeed(conversationId, onError = { + context.log.error("Failed to clear feed $conversationId: $it") + onFailure?.invoke() + resume() + }, onSuccess = { + setDialogMessage(translation["cleared_from_feed"]) + onSuccess?.invoke() + resume() + }) + }.onFailure { + context.log.error("Failed to clear feed $conversationId", it) + onFailure?.invoke() + resume() + } + } +} + diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/action/impl/CleanCache.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/action/impl/CleanCache.kt similarity index 92% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/action/impl/CleanCache.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/action/impl/CleanCache.kt index 9482a945..14d85341 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/action/impl/CleanCache.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/action/impl/CleanCache.kt @@ -1,6 +1,6 @@ -package me.rhunk.snapenhance.core.action.impl +package me.eternal.purrfectsnap.core.action.impl -import me.rhunk.snapenhance.core.action.AbstractAction +import me.eternal.purrfectsnap.core.action.AbstractAction import java.io.File class CleanCache : AbstractAction() { diff --git a/core/src/main/kotlin/me/eternal/purrfectsnap/core/action/impl/ExportChatMessages.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/action/impl/ExportChatMessages.kt new file mode 100644 index 00000000..27ee8ea2 --- /dev/null +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/action/impl/ExportChatMessages.kt @@ -0,0 +1,840 @@ +package me.eternal.purrfectsnap.core.action.impl + +import android.app.AlertDialog +import android.content.DialogInterface +import android.os.Environment +import androidx.compose.animation.AnimatedVisibility +import androidx.compose.animation.core.animateFloatAsState +import androidx.compose.animation.core.tween +import androidx.compose.foundation.background +import androidx.compose.foundation.border +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.foundation.text.BasicText +import androidx.compose.foundation.text.BasicTextField +import androidx.compose.foundation.text.KeyboardActions +import androidx.compose.foundation.text.KeyboardOptions +import androidx.compose.foundation.verticalScroll +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.outlined.Close +import androidx.compose.material.icons.rounded.Check +import androidx.compose.runtime.* +import androidx.compose.ui.Alignment +import androidx.compose.ui.ExperimentalComposeUiApi +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.draw.alpha +import androidx.compose.ui.graphics.Brush +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.SolidColor +import androidx.compose.ui.graphics.vector.rememberVectorPainter +import androidx.compose.ui.platform.LocalConfiguration +import androidx.compose.ui.platform.LocalFocusManager +import androidx.compose.ui.platform.LocalSoftwareKeyboardController +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.input.ImeAction +import androidx.compose.ui.text.input.KeyboardType +import androidx.compose.ui.text.style.TextOverflow +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import androidx.compose.ui.window.Popup +import androidx.compose.ui.window.PopupProperties +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Surface +import androidx.compose.material3.Icon +import androidx.compose.material3.Text +import kotlinx.coroutines.* +import me.eternal.purrfectsnap.common.data.ContentType +import me.eternal.purrfectsnap.common.database.impl.FriendFeedEntry +import me.eternal.purrfectsnap.common.ui.createComposeAlertDialog +import me.eternal.purrfectsnap.common.ui.rememberAsyncMutableState +import me.eternal.purrfectsnap.core.action.AbstractAction +import me.eternal.purrfectsnap.core.features.impl.messaging.Messaging +import me.eternal.purrfectsnap.core.logger.CoreLogger +import me.eternal.purrfectsnap.core.messaging.ConversationExporter +import me.eternal.purrfectsnap.core.messaging.ExportFormat +import me.eternal.purrfectsnap.core.messaging.ExportParams +import me.eternal.purrfectsnap.core.ui.ViewAppearanceHelper +import me.eternal.purrfectsnap.core.wrapper.impl.Message +import java.io.File +import kotlin.math.absoluteValue + +class ExportChatMessages : AbstractAction() { + private val translation by lazy { context.translation.getCategory("chat_export") } + private val dialogLogs = mutableListOf() + private var currentActionDialog: AlertDialog? = null + private val dialogBackground = Brush.verticalGradient( + listOf( + Color(0xFF1D1538), + Color(0xFF130F2A) + ) + ) + private val panelOverlay = Brush.linearGradient( + listOf( + Color(0xFF2C2551), + Color(0xFF1B1636) + ) + ) + private val accentGradient = Brush.horizontalGradient( + listOf( + Color(0xFF8C7BFF), + Color(0xFF5FD8FF) + ) + ) + + private fun logDialog(message: String) { + context.runOnUiThread { + if (dialogLogs.size > 10) dialogLogs.removeAt(0) + dialogLogs.add(message) + context.log.debug("dialog: $message", "ExportChatMessages") + currentActionDialog!!.setMessage(dialogLogs.joinToString("\n")) + } + } + + private fun setStatus(message: String) { + context.runOnUiThread { + currentActionDialog!!.setTitle(message) + } + } + + @OptIn(ExperimentalComposeUiApi::class) + @Composable + private fun ExporterDialog( + getDialog: () -> AlertDialog? = { null } + ) { + fun t(key: String) = translation["exporter_dialog.$key"] + + var feedEntries by remember { mutableStateOf(emptyList()) } + var exportType by remember { mutableStateOf(ExportFormat.HTML) } + val selectedFeedEntries = remember { mutableStateListOf() } + val messageTypeFilter = remember { mutableStateListOf() } + var amountOfMessages by remember { mutableIntStateOf(-1) } + var downloadMedias by remember { mutableStateOf(false) } + var showConversationPicker by remember { mutableStateOf(false) } + var showFormatPicker by remember { mutableStateOf(false) } + var showMessageTypePicker by remember { mutableStateOf(false) } + val allFriends by rememberAsyncMutableState(null) { context.database.getAllFriends().associateBy { it.userId!! } } + val myUserId = context.database.myUserId + val focusManager = LocalFocusManager.current + val keyboard = LocalSoftwareKeyboardController.current + val accent = MaterialTheme.colorScheme.primary + + Box( + modifier = Modifier + .fillMaxWidth() + .background(dialogBackground) + .padding(12.dp) + ) { + Box( + modifier = Modifier + .matchParentSize() + .padding(top = 6.dp) + ) { + Box( + modifier = Modifier + .size(220.dp) + .align(Alignment.TopEnd) + .offset(x = 40.dp, y = (-40).dp) + .background( + Brush.radialGradient( + listOf(Color(0xFF8C7BFF).copy(alpha = 0.36f), Color.Transparent) + ) + ) + ) + Box( + modifier = Modifier + .size(240.dp) + .align(Alignment.BottomStart) + .offset(x = (-60).dp, y = 30.dp) + .background( + Brush.radialGradient( + listOf(Color(0xFF5FD8FF).copy(alpha = 0.32f), Color.Transparent) + ) + ) + ) + } + Surface( + modifier = Modifier + .fillMaxWidth() + .align(Alignment.Center) + .border(1.2.dp, accentGradient, RoundedCornerShape(28.dp)), + shape = RoundedCornerShape(28.dp), + tonalElevation = 0.dp, + color = Color.White.copy(alpha = 0.04f) + ) { + Column( + modifier = Modifier + .fillMaxWidth() + .background(panelOverlay) + .verticalScroll(rememberScrollState()) + .padding(horizontal = 18.dp, vertical = 18.dp), + verticalArrangement = Arrangement.spacedBy(16.dp) + ) { + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.spacedBy(14.dp), + verticalAlignment = Alignment.CenterVertically + ) { + Box( + modifier = Modifier + .size(56.dp) + .clip(RoundedCornerShape(18.dp)) + .background(Color.White.copy(alpha = 0.08f)) + .border(1.dp, Color.White.copy(alpha = 0.12f), RoundedCornerShape(18.dp)) + .padding(12.dp) + ) { + Icon( + imageVector = Icons.Rounded.Check, + tint = Color.White, + modifier = Modifier + .align(Alignment.Center) + .size(28.dp), + contentDescription = null + ) + } + Column(modifier = Modifier.weight(1f)) { + Text( + text = "Export conversations", + style = MaterialTheme.typography.titleLarge.copy( + color = Color.White, + fontWeight = FontWeight.ExtraBold, + fontSize = 22.sp + ) + ) + Text( + text = t("select_conversations_title"), + style = MaterialTheme.typography.bodyMedium.copy( + color = Color(0xFFD9D3FF), + fontSize = 14.sp + ) + ) + } + Text( + text = exportType.extension.uppercase(), + color = Color.White, + fontSize = 12.sp, + modifier = Modifier + .clip(RoundedCornerShape(12.dp)) + .background(Color.White.copy(alpha = 0.12f)) + .padding(horizontal = 12.dp, vertical = 6.dp) + ) + } + + SectionLabel(t("select_conversations_title")) + GlassField( + value = selectedFeedEntries + .takeIf { it.isNotEmpty() } + ?.let { translation.format("exporter_dialog.text_field_selection", "amount" to it.size.toString()) } + ?: t("text_field_selection_all"), + onClick = { showConversationPicker = true }, + tint = MaterialTheme.colorScheme.surfaceVariant + ) + + SectionLabel(t("export_file_format_title")) + GlassField( + value = exportType.extension.uppercase(), + onClick = { showFormatPicker = true }, + tint = MaterialTheme.colorScheme.surfaceVariant + ) + + SectionLabel(t("message_type_filter_title")) + GlassField( + value = messageTypeFilter.takeIf { it.isNotEmpty() }?.let { + translation.format("exporter_dialog.text_field_selection", "amount" to it.size.toString()) + } ?: t("text_field_selection_all"), + onClick = { showMessageTypePicker = true }, + tint = MaterialTheme.colorScheme.surfaceVariant + ) + + SectionLabel(t("amount_of_messages_title")) + GlassTextField( + value = amountOfMessages.takeIf { it != -1 }?.toString() ?: "", + onValueChange = { amountOfMessages = it.toIntOrNull()?.absoluteValue ?: -1 }, + placeholder = "Unlimited", + onImeDone = { + focusManager.clearFocus() + keyboard?.hide() + }, + tint = MaterialTheme.colorScheme.surfaceVariant + ) + + SectionLabel(t("download_medias_title")) + NeonToggle( + checked = downloadMedias, + onCheckedChange = { downloadMedias = it }, + label = if (downloadMedias) translation["exporter_dialog.download_medias_title"] else translation["exporter_dialog.download_medias_title"], + accent = accent + ) + + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.spacedBy(12.dp) + ) { + SecondaryButton( + text = translation["dialog_negative_button"], + modifier = Modifier.weight(1f), + onClick = { getDialog()?.dismiss() } + ) + PrimaryButton( + text = translation["dialog_positive_button"], + modifier = Modifier.weight(1f), + enabled = selectedFeedEntries.isNotEmpty(), + onClick = { + exportChatForConversations( + selectedFeedEntries, + ExportParams( + exportFormat = exportType, + messageTypeFilter = messageTypeFilter.takeIf { it.isNotEmpty() }, + amountOfMessages = amountOfMessages.takeIf { it != -1 }, + downloadMedias = downloadMedias + ) + ) + } + ) + } + + LaunchedEffect(Unit) { + withContext(Dispatchers.IO) { + feedEntries = context.database.getFeedEntries(500) + } + } + } + } + + if (showConversationPicker) { + Box( + modifier = Modifier + .fillMaxSize() + .background(Color.Black.copy(alpha = 0.55f)) + .clickable { showConversationPicker = false } + ) + SelectorPopup( + title = t("select_conversations_title"), + onDismiss = { showConversationPicker = false } + ) { + LazyColumn( + modifier = Modifier + .fillMaxWidth() + .heightIn(max = (LocalConfiguration.current.screenHeightDp.dp * 0.65f)) + ) { + items(feedEntries, key = { it.key!! }) { feedEntry -> + val isSelected = selectedFeedEntries.contains(feedEntry) + SelectorRow( + title = remember(feedEntry) { + (if (feedEntry.conversationType == 1) feedEntry.feedDisplayName else feedEntry.participants?.filter { it != myUserId }?.firstOrNull()?.let { userId -> + allFriends?.get(userId)?.let { friend -> friend.displayName?.let { "$it (${friend.mutableUsername})" } ?: friend.mutableUsername } + }) ?: "Unknown" + }, + subtitle = feedEntry.takeIf { it.conversationType == 1 }?.let { + "${feedEntry.participantsSize} participants" + }, + checked = isSelected, + onToggle = { + if (isSelected) selectedFeedEntries -= feedEntry else selectedFeedEntries += feedEntry + } + ) + } + } + } + } + + if (showFormatPicker) { + Box( + modifier = Modifier + .fillMaxSize() + .background(Color.Black.copy(alpha = 0.55f)) + .clickable { showFormatPicker = false } + ) + SelectorPopup( + title = t("export_file_format_title"), + onDismiss = { showFormatPicker = false } + ) { + ExportFormat.entries.forEach { exportFormat -> + SelectorRow( + title = exportFormat.name, + subtitle = exportFormat.extension.uppercase(), + checked = exportType == exportFormat, + onToggle = { + exportType = exportFormat + showFormatPicker = false + } + ) + } + } + } + + if (showMessageTypePicker) { + Box( + modifier = Modifier + .fillMaxSize() + .background(Color.Black.copy(alpha = 0.55f)) + .clickable { showMessageTypePicker = false } + ) + SelectorPopup( + title = t("message_type_filter_title"), + onDismiss = { showMessageTypePicker = false } + ) { + arrayOf( + ContentType.CHAT, + ContentType.SNAP, + ContentType.EXTERNAL_MEDIA, + ContentType.NOTE, + ContentType.STICKER + ).forEach { contentType -> + val isSelected = messageTypeFilter.contains(contentType) + SelectorRow( + title = contentType.name.lowercase().replaceFirstChar { it.uppercase() }, + subtitle = null, + checked = isSelected, + onToggle = { + if (isSelected) messageTypeFilter -= contentType else messageTypeFilter += contentType + } + ) + } + SecondaryButton( + text = t("text_field_selection_all"), + modifier = Modifier.fillMaxWidth(), + onClick = { + messageTypeFilter.clear() + showMessageTypePicker = false + } + ) + } + } + } + } + + @Composable + private fun SectionLabel(text: String) { + BasicText( + text = text, + modifier = Modifier.fillMaxWidth(), + style = TextStyle( + fontSize = 13.sp, + color = Color(0xFFD9D3FF), + fontWeight = FontWeight.SemiBold, + letterSpacing = 0.3.sp, + textAlign = TextAlign.Start + ) + ) + } + + @Composable + private fun GlassField( + value: String, + onClick: () -> Unit, + tint: Color + ) { + Box( + modifier = Modifier + .fillMaxWidth() + .clip(RoundedCornerShape(18.dp)) + .background(tint.copy(alpha = 0.18f)) + .border(1.dp, accentGradient, RoundedCornerShape(18.dp)) + .clickable(onClick = onClick) + .padding(horizontal = 16.dp, vertical = 14.dp) + ) { + BasicText( + text = value, + modifier = Modifier.fillMaxWidth(), + style = TextStyle(fontSize = 14.sp, color = Color.White, textAlign = TextAlign.Start, fontWeight = FontWeight.Medium) + ) + } + } + + @Composable + private fun GlassTextField( + value: String, + onValueChange: (String) -> Unit, + placeholder: String, + onImeDone: () -> Unit, + tint: Color + ) { + BasicTextField( + value = value, + onValueChange = onValueChange, + singleLine = true, + textStyle = TextStyle(color = Color.White, fontSize = 14.sp), + cursorBrush = SolidColor(Color(0xFF8EF0F3)), + keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done, keyboardType = KeyboardType.Number), + keyboardActions = KeyboardActions(onDone = { onImeDone() }), + decorationBox = { inner -> + Box( + modifier = Modifier + .fillMaxWidth() + .clip(RoundedCornerShape(18.dp)) + .background(tint.copy(alpha = 0.16f)) + .border(1.dp, accentGradient, RoundedCornerShape(18.dp)) + .padding(horizontal = 16.dp, vertical = 13.dp) + ) { + if (value.isEmpty()) { + BasicText( + text = placeholder, + style = TextStyle(color = Color(0xFFB1B4D7), fontSize = 14.sp) + ) + } + inner() + } + } + ) + } + + @Composable + private fun NeonToggle( + checked: Boolean, + onCheckedChange: (Boolean) -> Unit, + label: String, + accent: Color + ) { + val knobOffset by animateFloatAsState(targetValue = if (checked) 20f else 0f, animationSpec = tween(220), label = "toggle") + Row( + modifier = Modifier + .fillMaxWidth() + .clip(RoundedCornerShape(14.dp)) + .background(Color.White.copy(alpha = 0.07f)) + .border(1.dp, accentGradient, RoundedCornerShape(14.dp)) + .clickable { onCheckedChange(!checked) } + .padding(horizontal = 12.dp, vertical = 12.dp), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(10.dp) + ) { + Box( + modifier = Modifier + .size(width = 50.dp, height = 26.dp) + .clip(RoundedCornerShape(40.dp)) + .background(Color(0xFF10192B)) + .border(1.dp, Color.White.copy(alpha = 0.12f), RoundedCornerShape(40.dp)) + .padding(3.dp) + ) { + Box( + modifier = Modifier + .size(20.dp) + .offset(x = knobOffset.dp) + .clip(RoundedCornerShape(50)) + .background(Brush.linearGradient(listOf(accent, Color(0xFF6C7CFF)))) + ) + } + Column { + BasicText( + text = label, + style = TextStyle(color = Color.White, fontSize = 14.sp, fontWeight = FontWeight.Medium) + ) + BasicText( + text = if (checked) "Media files included" else "Only text content", + style = TextStyle(color = Color(0xFFB1B4D7), fontSize = 12.sp) + ) + } + } + } + + @Composable + private fun PrimaryButton( + text: String, + modifier: Modifier = Modifier, + enabled: Boolean = true, + onClick: () -> Unit + ) { + Box( + modifier = modifier + .clip(RoundedCornerShape(16.dp)) + .alpha(if (enabled) 1f else 0.6f) + .background(accentGradient) + .clickable(enabled = enabled, onClick = onClick) + .padding(vertical = 12.dp), + contentAlignment = Alignment.Center + ) { + BasicText( + text = text, + style = TextStyle(color = Color(0xFF0A0F1D), fontSize = 15.sp, fontWeight = FontWeight.Bold) + ) + } + } + + @Composable + private fun SecondaryButton( + text: String, + modifier: Modifier = Modifier, + onClick: () -> Unit + ) { + Box( + modifier = modifier + .clip(RoundedCornerShape(16.dp)) + .border(1.dp, Color.White.copy(alpha = 0.16f), RoundedCornerShape(16.dp)) + .background(Color.White.copy(alpha = 0.05f)) + .clickable(onClick = onClick) + .padding(vertical = 12.dp), + contentAlignment = Alignment.Center + ) { + BasicText( + text = text, + style = TextStyle(color = Color.White, fontSize = 15.sp, fontWeight = FontWeight.SemiBold) + ) + } + } + + @Composable + private fun SelectorPopup( + title: String, + onDismiss: () -> Unit, + content: @Composable ColumnScope.() -> Unit + ) { + Popup( + alignment = Alignment.Center, + properties = PopupProperties(focusable = true, dismissOnClickOutside = false, dismissOnBackPress = true), + onDismissRequest = onDismiss + ) { + Column( + modifier = Modifier + .widthIn(max = 520.dp) + .clip(RoundedCornerShape(22.dp)) + .background(panelOverlay) + .border(1.2.dp, accentGradient, RoundedCornerShape(22.dp)) + .padding(18.dp), + verticalArrangement = Arrangement.spacedBy(12.dp) + ) { + Row( + modifier = Modifier.fillMaxWidth(), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.SpaceBetween + ) { + BasicText( + text = title, + style = TextStyle(color = Color(0xFFE6ECFF), fontSize = 16.sp, fontWeight = FontWeight.Bold) + ) + androidx.compose.foundation.Image( + painter = rememberVectorPainter(Icons.Outlined.Close), + contentDescription = "Close", + modifier = Modifier + .size(22.dp) + .clickable(onClick = onDismiss) + .background(Color.White.copy(alpha = 0.08f), RoundedCornerShape(12.dp)) + ) + } + content() + } + } + } + + @Composable + private fun SelectorRow( + title: String, + subtitle: String?, + checked: Boolean, + onToggle: () -> Unit + ) { + Row( + modifier = Modifier + .fillMaxWidth() + .clip(RoundedCornerShape(14.dp)) + .background(Color.White.copy(alpha = 0.05f)) + .border(1.dp, accentGradient, RoundedCornerShape(14.dp)) + .clickable(onClick = onToggle) + .padding(horizontal = 12.dp, vertical = 12.dp), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(12.dp) + ) { + GlassCheckbox(checked = checked, accent = Color(0xFF8EF0F3)) + Column( + verticalArrangement = Arrangement.spacedBy(2.dp) + ) { + BasicText( + text = title, + style = TextStyle(color = Color.White, fontSize = 14.sp, fontWeight = FontWeight.SemiBold), + maxLines = 1, + overflow = TextOverflow.Ellipsis + ) + subtitle?.let { + BasicText( + text = it, + style = TextStyle(color = Color(0xFFB1B4D7), fontSize = 12.sp), + maxLines = 1, + overflow = TextOverflow.Ellipsis + ) + } + } + } + } + + @Composable + private fun GlassCheckbox(checked: Boolean, accent: Color) { + val animatedAlpha by animateFloatAsState(targetValue = if (checked) 1f else 0f, animationSpec = tween(200), label = "checkbox") + Box( + modifier = Modifier + .size(22.dp) + .clip(RoundedCornerShape(6.dp)) + .border(1.2.dp, Color.White.copy(alpha = 0.25f), RoundedCornerShape(6.dp)) + .background(Color.White.copy(alpha = 0.08f)), + contentAlignment = Alignment.Center + ) { + AnimatedVisibility(visible = checked) { + androidx.compose.foundation.Image( + painter = rememberVectorPainter(Icons.Rounded.Check), + contentDescription = "Checked", + modifier = Modifier + .size(18.dp) + .clip(RoundedCornerShape(5.dp)) + .background(accent.copy(alpha = animatedAlpha)) + .padding(2.dp) + ) + } + } + } + + override fun run() { + context.coroutineScope.launch(Dispatchers.Main) { + createComposeAlertDialog(context.mainActivity!!) { alertDialog -> + ExporterDialog { alertDialog } + }.apply { + setCanceledOnTouchOutside(false) + show() + } + } + } + + private suspend fun fetchMessagesPaginated(conversationId: String, lastMessageId: Long, amount: Int): List = runBlocking { + for (i in 0..5) { + val messages: List? = suspendCancellableCoroutine { continuation -> + context.feature(Messaging::class).conversationManager?.fetchConversationWithMessagesPaginated(conversationId, + lastMessageId, + amount, onSuccess = { messages -> + continuation.resumeWith(Result.success(messages)) + }, onError = { + continuation.resumeWith(Result.success(null)) + }) ?: continuation.resumeWith(Result.success(null)) + } + if (messages != null) return@runBlocking messages + logDialog("Retrying in 1 second...") + delay(1000) + } + logDialog("Failed to fetch messages") + emptyList() + } + + private fun exportChatForConversations( + conversations: List, + exportParams: ExportParams, + ) { + dialogLogs.clear() + val jobs = mutableListOf() + + currentActionDialog = ViewAppearanceHelper.newAlertDialogBuilder(context.mainActivity) + .setTitle(translation["exporting_chats"]) + .setCancelable(false) + .setMessage("") + .create() + + val conversationSize = translation.format("processing_chats", "amount" to conversations.size.toString()) + + logDialog(conversationSize) + + context.coroutineScope.launch { + conversations.forEach { conversation -> + launch { + runCatching { + exportFullConversation(conversation, exportParams) + }.onFailure { + logDialog(translation.format("export_fail", "conversation" to conversation.key.toString())) + logDialog(it.stackTraceToString()) + CoreLogger.xposedLog(it) + } + }.also { jobs.add(it) } + } + jobs.joinAll() + logDialog(translation["finished"]) + }.also { + currentActionDialog?.setButton(DialogInterface.BUTTON_POSITIVE, translation["dialog_negative_button"]) { dialog, _ -> + it.cancel() + jobs.forEach { it.cancel() } + dialog.dismiss() + } + } + + currentActionDialog!!.also { + it.setCanceledOnTouchOutside(false) + }.show() + } + + private suspend fun exportFullConversation( + feedEntry: FriendFeedEntry, + exportParams: ExportParams, + ) { + //first fetch the first message + val conversationId = feedEntry.key!! + val conversationParticipants = context.database.getConversationParticipants(feedEntry.key!!, useCache = false) + ?.mapNotNull { + context.database.getFriendInfo(it) + }?.associateBy { it.userId!! } ?: emptyMap() + + val conversationName = feedEntry.feedDisplayName ?: conversationParticipants.values.take(3).joinToString("_") { it.mutableUsername ?: "" } + + val publicFolder = File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), "PurrfectSnap").also { if (!it.exists()) it.mkdirs() } + val outputFile = publicFolder.resolve("conversation_${conversationName}_${System.currentTimeMillis()}.${exportParams.exportFormat.extension}") + + logDialog(translation.format("exporting_message", "conversation" to conversationName)) + + val conversationExporter = ConversationExporter( + context = context, + friendFeedEntry = feedEntry, + conversationParticipants = conversationParticipants, + exportParams = exportParams, + cacheFolder = publicFolder.resolve("cache").also { if (!it.exists()) it.mkdirs() }, + outputFile = outputFile, + ).apply { init(); printLog = { + logDialog(it.toString()) + } } + + var foundMessageCount = 0 + + var lastMessageId = fetchMessagesPaginated(conversationId, Long.MAX_VALUE, amount = 1).firstOrNull()?.also { + conversationExporter.readMessage(it) + foundMessageCount++ + }?.messageDescriptor?.messageId ?: run { + logDialog(translation["no_messages_found"]) + return + } + + while (true) { + val fetchedMessages = fetchMessagesPaginated(conversationId, lastMessageId, amount = 500).toMutableList() + if (fetchedMessages.isEmpty()) break + + fetchedMessages.firstOrNull()?.let { + lastMessageId = it.messageDescriptor!!.messageId!! + } + + exportParams.messageTypeFilter?.let { filter -> + fetchedMessages.removeIf { message -> + !filter.contains(message.messageContent?.contentType ?: return@removeIf false) + } + } + + foundMessageCount += fetchedMessages.size + + if (exportParams.amountOfMessages != null && foundMessageCount >= exportParams.amountOfMessages) { + fetchedMessages.reversed().subList(0, exportParams.amountOfMessages - (foundMessageCount - fetchedMessages.size)).forEach { message -> + conversationExporter.readMessage(message) + } + break + } + + fetchedMessages.reversed().forEach { message -> + conversationExporter.readMessage(message) + } + + setStatus("Exporting (found ${foundMessageCount})") + } + + if (exportParams.exportFormat == ExportFormat.HTML) conversationExporter.awaitDownload() + conversationExporter.close() + logDialog(translation["writing_output"]) + dialogLogs.clear() + logDialog("\n" + translation.format("exported_to", + "path" to outputFile.absolutePath.toString() + ) + "\n") + } +} diff --git a/core/src/main/kotlin/me/eternal/purrfectsnap/core/action/impl/ExportMemories.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/action/impl/ExportMemories.kt new file mode 100644 index 00000000..5031cfbd --- /dev/null +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/action/impl/ExportMemories.kt @@ -0,0 +1,823 @@ +package me.eternal.purrfectsnap.core.action.impl + +import android.database.sqlite.SQLiteDatabase +import android.database.sqlite.SQLiteDatabase.OpenParams +import android.os.Environment +import androidx.compose.animation.core.animateFloatAsState +import androidx.compose.animation.core.tween +import androidx.compose.foundation.background +import androidx.compose.foundation.border +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.foundation.text.BasicText +import androidx.compose.foundation.text.selection.LocalTextSelectionColors +import androidx.compose.foundation.text.selection.TextSelectionColors +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Close +import androidx.compose.material.icons.filled.Download +import androidx.compose.material3.OutlinedTextFieldDefaults +import androidx.compose.material3.DatePickerDefaults +import androidx.compose.material3.DateRangePicker +import androidx.compose.material3.DisplayMode +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.Icon +import androidx.compose.material3.Surface +import androidx.compose.material3.Text +import androidx.compose.material3.rememberDateRangePickerState +import androidx.compose.runtime.* +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.Brush +import androidx.compose.ui.graphics.Color +import androidx.compose.foundation.layout.offset +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.text.style.TextOverflow +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import androidx.compose.ui.window.Popup +import androidx.compose.ui.window.PopupProperties +import kotlinx.coroutines.* +import me.eternal.purrfectsnap.common.data.FileType +import me.eternal.purrfectsnap.common.ui.createComposeAlertDialog +import me.eternal.purrfectsnap.common.util.ktx.getLongOrNull +import me.eternal.purrfectsnap.common.util.ktx.getStringOrNull +import me.eternal.purrfectsnap.core.action.AbstractAction +import okhttp3.OkHttpClient +import java.io.File +import java.io.FileOutputStream +import java.nio.file.attribute.FileTime +import java.time.Instant +import java.time.OffsetDateTime +import java.time.ZoneOffset +import java.time.format.DateTimeFormatter +import java.util.zip.ZipEntry +import java.util.zip.ZipOutputStream +import javax.crypto.Cipher +import javax.crypto.CipherInputStream +import javax.crypto.spec.IvParameterSpec +import javax.crypto.spec.SecretKeySpec +import kotlin.io.encoding.Base64 +import kotlin.io.encoding.ExperimentalEncodingApi +import kotlin.math.absoluteValue + +class ExportMemories : AbstractAction() { + private val translation by lazy { context.translation.getCategory("memories") } + private val dialogBackground = Brush.verticalGradient( + listOf( + Color(0xFF1D1538), + Color(0xFF130F2A) + ) + ) + private val panelOverlay = Brush.linearGradient( + listOf( + Color(0xFF2C2551), + Color(0xFF1B1636) + ) + ) + private val accentGradient = Brush.horizontalGradient( + listOf( + Color(0xFF8C7BFF), + Color(0xFF5FD8FF) + ) + ) + private val rangeFormatter = DateTimeFormatter.ofPattern("MMM d, yyyy") + data class TimeRange( + val start: Long?, + val end: Long?, + ) + + data class MemoriesEntry( + val storyTitle: String, + val createTime: Long, + val mediaKey: String?, + val mediaIv: String?, + val downloadUrl: String + ) { + val folderName: String + get() = storyTitle.replace(Regex("[^a-zA-Z0-9\\s]"), "").trim().replace(Regex("\\s+"), "_") + } + + @OptIn(ExperimentalCoroutinesApi::class, ExperimentalEncodingApi::class) + private suspend fun exportMemories( + scope: CoroutineScope = context.coroutineScope, + database: SQLiteDatabase, + timeRange: TimeRange?, + includeMEO: Boolean, + folders: Boolean, + progress: (Int, Int) -> Unit + ) { + val downloadContext = Dispatchers.IO.limitedParallelism(10) + val writeToZipContext = Dispatchers.IO.limitedParallelism(1) + val outputZip = File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS), "memories_" + System.currentTimeMillis() + ".zip").also { + if (it.exists()) it.delete() + } + val okHttpClient = OkHttpClient.Builder().build() + val outputZipFile = withContext(Dispatchers.IO) { + ZipOutputStream(FileOutputStream(outputZip)).apply { + setComment("Exported from PurrfectSnap") + setMethod(ZipOutputStream.DEFLATED) + } + } + var totalCount = 0 + var currentCount = 0 + var failed = 0 + + fun updateProgress() { + progress((currentCount.toFloat() / totalCount.toFloat() * 100f).toInt(), failed) + } + + val jobs = mutableListOf() + + val meoMasterKeyPair = if (includeMEO) { + runCatching { + database.rawQuery("SELECT * FROM memories_meo_confidential", null).use { cursor -> + if (cursor.moveToNext()) { + cursor.getStringOrNull("master_key")!!.trim() to cursor.getStringOrNull("master_key_iv")!!.trim() + } else null + } + }.getOrNull() + } else null + + database.rawQuery("SELECT memories_entry.title as story_title, memories_snap.create_time, " + + "memories_snap.media_key, memories_snap.media_iv, memories_snap.encrypted_media_key, memories_snap.encrypted_media_iv, " + + "memories_media.download_url FROM memories_snap " + + "INNER JOIN memories_entry ON memories_snap.memories_entry_id = memories_entry._id " + + "INNER JOIN memories_media ON memories_snap.media_id = memories_media._id " + + "WHERE memories_snap.create_time >= ? AND memories_snap.create_time <= ? " + + "ORDER BY memories_snap.create_time ASC", arrayOf(timeRange?.start?.toString() ?: "-1", timeRange?.end?.toString() ?: Long.MAX_VALUE.toString()) + ).use { cursor -> + while (cursor.moveToNext()) { + val encryptedMediaKey = cursor.getStringOrNull("encrypted_media_key")?.trim() + val encryptedMediaIv = cursor.getStringOrNull("encrypted_media_iv")?.trim() + var mediaKey = cursor.getStringOrNull("media_key")?.trim() + var mediaIv = cursor.getStringOrNull("media_iv")?.trim() + + if (!includeMEO && encryptedMediaKey != null && encryptedMediaIv != null) continue + + meoMasterKeyPair.takeIf { encryptedMediaKey != null && encryptedMediaIv != null }?.let { keyPair -> + val cipher = Cipher.getInstance("AES/CBC/PKCS5Padding") + runCatching { + cipher.init(Cipher.DECRYPT_MODE, SecretKeySpec(Base64.decode(keyPair.first), "AES"), IvParameterSpec(Base64.decode(keyPair.second))) + mediaKey = Base64.encode(cipher.doFinal(Base64.decode(encryptedMediaKey ?: return@let))) + mediaIv = Base64.encode(cipher.doFinal(Base64.decode(encryptedMediaIv ?: return@let))) + context.log.verbose("decrypted meo $mediaKey/$mediaIv") + }.onFailure { + context.log.error("failed to decrypt meo", it) + } + } + + if (mediaKey == null || mediaIv == null) { + context.log.error("missing media key or iv for ${cursor.getStringOrNull("download_url")}") + failed++ + updateProgress() + continue + } + + val entry = MemoriesEntry( + storyTitle = cursor.getStringOrNull("story_title") ?: "unknown", + createTime = cursor.getLongOrNull("create_time") ?: -1L, + mediaKey = mediaKey, + mediaIv = mediaIv, + downloadUrl = cursor.getStringOrNull("download_url") ?: continue + ) + + totalCount++ + + scope.launch(downloadContext) { + var downloadedFile = File.createTempFile("memories", ".tmp", context.androidContext.cacheDir) + + runCatching { + okHttpClient.newCall( + okhttp3.Request.Builder() + .url(entry.downloadUrl) + .build() + ).execute().use { response -> + val inputStream = response.body.byteStream().let { + if (entry.mediaKey != null && entry.mediaIv != null) { + val cipher = Cipher.getInstance("AES/CBC/PKCS5Padding") + cipher.init(Cipher.DECRYPT_MODE, SecretKeySpec(Base64.decode(entry.mediaKey), "AES"), IvParameterSpec(Base64.decode(entry.mediaIv))) + CipherInputStream(it, cipher) + } else it + } + + downloadedFile.outputStream().use { outputStream -> + inputStream.use { inputStream -> + inputStream.copyTo(outputStream) + } + } + + val fileType = FileType.fromFile(downloadedFile) + + downloadedFile = File( + downloadedFile.parentFile, + "${entry.createTime}-${entry.downloadUrl.hashCode().absoluteValue.toString(16)}.${fileType.fileExtension}" + ).also { + downloadedFile.renameTo(it) + } + + withContext(writeToZipContext) { + val zipEntry = ZipEntry("${if (folders) entry.folderName + "/" else entry.folderName}${downloadedFile.name}") + FileTime.fromMillis(entry.createTime).let { + zipEntry.lastModifiedTime = it + zipEntry.lastAccessTime = it + zipEntry.creationTime = it + } + outputZipFile.apply { + putNextEntry(zipEntry) + downloadedFile.inputStream().use { it.copyTo(outputZipFile) } + closeEntry() + flush() + } + currentCount++ + updateProgress() + } + } + }.onFailure { + context.log.error("failed to download ${entry.downloadUrl}", it) + failed++ + updateProgress() + } + downloadedFile.delete() + }.also { jobs.add(it) } + } + } + + jobs.joinAll() + withContext(Dispatchers.IO) { + outputZipFile.close() + } + context.longToast("Exported to ${outputZip.absolutePath}") + } + + @OptIn(ExperimentalMaterial3Api::class) + @Composable + fun ExporterDialog(database: SQLiteDatabase, onDismiss: () -> Unit) { + var exportJob by remember { mutableStateOf(null as Job?) } + var exportFinished by remember { mutableStateOf(false) } + var exportProgress by remember { mutableStateOf(Pair(0, 0)) } // progress, failed + + var dateRangeFilter by remember { mutableStateOf(false) } + var sortByFolder by remember { mutableStateOf(false) } + var includeMEO by remember { mutableStateOf(false) } + val dateRangePickerState = rememberDateRangePickerState( + initialSelectedStartDateMillis = OffsetDateTime.now().minusDays(8).toInstant().toEpochMilli(), + initialSelectedEndDateMillis = Instant.now().toEpochMilli(), + initialDisplayMode = DisplayMode.Picker + ) + + val totalCount = remember(dateRangePickerState.selectedStartDateMillis, dateRangePickerState.selectedEndDateMillis, dateRangeFilter) { + val timeRange = dateRangePickerState.takeIf { dateRangeFilter }?.let { + TimeRange(it.selectedStartDateMillis, it.selectedEndDateMillis) + } + + database.rawQuery("SELECT COUNT(*) FROM memories_snap WHERE create_time >= ? AND create_time <= ? ", arrayOf(timeRange?.start?.toString() ?: "-1", timeRange?.end?.toString() ?: Long.MAX_VALUE.toString())).use { + it.moveToFirst() + it.getInt(0) + } + } + + Box( + modifier = Modifier + .fillMaxWidth() + .background(dialogBackground) + .padding(12.dp) + ) { + Box( + modifier = Modifier + .matchParentSize() + .padding(6.dp) + ) { + Box( + modifier = Modifier + .size(220.dp) + .align(Alignment.TopEnd) + .offset(x = 46.dp, y = (-38).dp) + .background( + Brush.radialGradient( + listOf(Color(0xFF8C7BFF).copy(alpha = 0.35f), Color.Transparent) + ) + ) + ) + Box( + modifier = Modifier + .size(240.dp) + .align(Alignment.BottomStart) + .offset(x = (-60).dp, y = 32.dp) + .background( + Brush.radialGradient( + listOf(Color(0xFF5FD8FF).copy(alpha = 0.32f), Color.Transparent) + ) + ) + ) + } + Surface( + modifier = Modifier + .fillMaxWidth() + .align(Alignment.Center) + .border(1.2.dp, accentGradient, RoundedCornerShape(28.dp)), + shape = RoundedCornerShape(28.dp), + tonalElevation = 0.dp, + color = Color.White.copy(alpha = 0.04f) + ) { + Column( + modifier = Modifier + .fillMaxWidth() + .background(panelOverlay) + .padding(18.dp), + verticalArrangement = Arrangement.spacedBy(10.dp) + ) { + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.spacedBy(14.dp), + verticalAlignment = Alignment.CenterVertically + ) { + Box( + modifier = Modifier + .size(56.dp) + .clip(RoundedCornerShape(18.dp)) + .background(Color.White.copy(alpha = 0.08f)) + .border(1.dp, Color.White.copy(alpha = 0.12f), RoundedCornerShape(18.dp)) + .padding(12.dp) + ) { + Icon( + imageVector = Icons.Filled.Download, + tint = Color.White, + modifier = Modifier + .align(Alignment.Center) + .size(28.dp), + contentDescription = null + ) + } + Column(modifier = Modifier.weight(1f)) { + Text( + text = translation.get("export_title"), + color = Color.White, + fontSize = 21.sp, + fontWeight = FontWeight.ExtraBold + ) + Text( + text = translation.get("total_memories").replace("{count}", totalCount.toString()), + color = Color(0xFFD9D3FF), + fontSize = 14.sp + ) + } + Text( + text = "ZIP", + color = Color.White, + fontSize = 12.sp, + modifier = Modifier + .clip(RoundedCornerShape(12.dp)) + .background(Color.White.copy(alpha = 0.12f)) + .padding(horizontal = 12.dp, vertical = 6.dp) + ) + } + + if (exportJob != null) { + BasicText( + text = translation.get("exporting_memories").replace("{failed}", exportProgress.second.toString()), + modifier = Modifier.fillMaxWidth(), + style = androidx.compose.ui.text.TextStyle(color = Color.White, fontSize = 14.sp, textAlign = TextAlign.Start) + ) + ProgressBar(progress = exportProgress.first / 100f) + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.spacedBy(12.dp) + ) { + SecondaryButton(text = translation.get("quit"), modifier = Modifier.weight(1f)) { + exportJob?.cancel() + exportJob = null + onDismiss() + } + if (exportFinished) { + PrimaryButton(text = translation.get("done"), modifier = Modifier.weight(1f)) { + exportJob = null + onDismiss() + } + } + } + } else { + var dateRangeDialog by remember { mutableStateOf(false) } + + Column( + modifier = Modifier.fillMaxWidth(), + verticalArrangement = Arrangement.spacedBy(10.dp) + ) { + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.CenterVertically + ) { + Text( + text = translation.get("date_range"), + color = Color(0xFFD9D3FF), + fontSize = 13.sp, + fontWeight = FontWeight.Medium, + modifier = Modifier.weight(1f) + ) + BareToggle( + checked = dateRangeFilter, + onCheckedChange = { dateRangeFilter = it }, + accent = Color(0xFF8EF0F3) + ) + } + val formattedRange = remember( + dateRangePickerState.selectedStartDateMillis, + dateRangePickerState.selectedEndDateMillis + ) { + formatRange( + dateRangePickerState.selectedStartDateMillis, + dateRangePickerState.selectedEndDateMillis + ) + } + Text( + text = formattedRange, + color = Color(0xFFD9D3FF), + fontSize = 11.sp, + maxLines = 1, + overflow = TextOverflow.Ellipsis, + modifier = Modifier + .fillMaxWidth() + .clip(RoundedCornerShape(12.dp)) + .border(1.dp, accentGradient, RoundedCornerShape(12.dp)) + .background(Color.White.copy(alpha = 0.08f)) + .padding(horizontal = 12.dp, vertical = 8.dp) + ) + PrimaryButton( + text = translation.get("select"), + modifier = Modifier.fillMaxWidth(), + onClick = { dateRangeDialog = true } + ) + } + + LaunchedEffect(dateRangeFilter) { + if (dateRangeFilter) dateRangeDialog = true + } + + if (dateRangeDialog) { + Box( + modifier = Modifier + .fillMaxSize() + .background(Color.Black.copy(alpha = 0.55f)) + .clickable { dateRangeDialog = false } + ) + GlassPopup(onDismiss = { dateRangeDialog = false }) { + Column( + modifier = Modifier + .fillMaxWidth(), + verticalArrangement = Arrangement.spacedBy(16.dp) + ) { + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.CenterVertically + ) { + Text( + text = translation.get("date_range"), + color = Color.White, + fontWeight = FontWeight.ExtraBold, + fontSize = 16.sp + ) + Icon( + imageVector = Icons.Filled.Close, + contentDescription = null, + tint = Color.White.copy(alpha = 0.8f), + modifier = Modifier + .size(22.dp) + .clickable { dateRangeDialog = false } + ) + } + CompositionLocalProvider( + LocalTextSelectionColors provides TextSelectionColors( + handleColor = Color(0xFF8EF0F3), + backgroundColor = Color(0x338EF0F3) + ) + ) { + Box( + modifier = Modifier + .fillMaxWidth() + .clip(RoundedCornerShape(20.dp)) + .background( + Brush.radialGradient( + listOf( + Color(0xFF8C7BFF).copy(alpha = 0.22f), + Color.Transparent + ), + radius = 520f + ) + ) + .border(1.dp, accentGradient, RoundedCornerShape(20.dp)) + .padding(10.dp) + ) { + DateRangePicker( + state = dateRangePickerState, + modifier = Modifier + .fillMaxWidth() + .background(Color.White.copy(alpha = 0.03f), RoundedCornerShape(16.dp)), + showModeToggle = true, + colors = DatePickerDefaults.colors( + containerColor = Color.Transparent, + titleContentColor = Color.White, + headlineContentColor = Color.White, + weekdayContentColor = Color.White.copy(alpha = 0.9f), + subheadContentColor = Color(0xFFD9D3FF), + selectedDayContainerColor = Color(0xFF8C7BFF).copy(alpha = 0.6f), + selectedDayContentColor = Color(0xFF0A0F1D), + todayContentColor = Color.White, + todayDateBorderColor = Color(0xFF5FD8FF), + dayContentColor = Color.White.copy(alpha = 0.95f), + disabledDayContentColor = Color.White.copy(alpha = 0.35f), + dividerColor = Color.White.copy(alpha = 0.16f), + navigationContentColor = Color.White, + dateTextFieldColors = OutlinedTextFieldDefaults.colors( + focusedContainerColor = Color(0xFF0E1221), + unfocusedContainerColor = Color(0xFF0E1221), + disabledContainerColor = Color(0x330E1221), + cursorColor = Color(0xFF8EF0F3), + focusedLabelColor = Color(0xFF8EF0F3), + unfocusedLabelColor = Color(0xFFD9D3FF), + focusedBorderColor = Color.Transparent, + unfocusedBorderColor = Color.Transparent, + disabledBorderColor = Color.Transparent, + focusedTextColor = Color.White, + unfocusedTextColor = Color.White + ) + ) + ) + } + } + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.spacedBy(10.dp) + ) { + SecondaryButton( + text = translation.get("cancel"), + modifier = Modifier.weight(1f) + ) { + dateRangePickerState.setSelection( + startDateMillis = null, + endDateMillis = null + ) + dateRangeDialog = false + } + PrimaryButton( + text = translation.get("ok"), + modifier = Modifier.weight(1f) + ) { + dateRangeDialog = false + } + } + } + } + } + + SectionLabel(translation.get("sort_by_folder")) + NeonToggle( + checked = sortByFolder, + onCheckedChange = { sortByFolder = it }, + label = translation.get("sort_by_folder"), + accent = Color(0xFF9EF88F) + ) + + SectionLabel(translation.get("include_my_eyes_only")) + NeonToggle( + checked = includeMEO, + onCheckedChange = { includeMEO = it }, + label = translation.get("include_my_eyes_only"), + accent = Color(0xFFE6B8FF) + ) + + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.spacedBy(12.dp) + ) { + SecondaryButton(text = translation.get("cancel"), modifier = Modifier.weight(1f), onClick = onDismiss) + PrimaryButton(text = translation.get("export"), modifier = Modifier.weight(1f)) { + context.coroutineScope.launch { + exportMemories( + scope = this, + database = database, + timeRange = dateRangePickerState.takeIf { dateRangeFilter }?.let { + TimeRange(it.selectedStartDateMillis, it.selectedEndDateMillis) + }, + folders = sortByFolder, + includeMEO = includeMEO, + ) { progress, failed -> + exportProgress = Pair(progress, failed) + } + }.also { exportJob = it }.invokeOnCompletion { + exportFinished = true + } + } + } + } + } + } + } + } + + @Composable + private fun ProgressBar(progress: Float) { + val clamped = progress.coerceIn(0f, 1f) + Box( + modifier = Modifier + .fillMaxWidth() + .height(10.dp) + .clip(RoundedCornerShape(50)) + .background(Color.White.copy(alpha = 0.08f)) + ) { + Box( + modifier = Modifier + .fillMaxWidth(fraction = clamped) + .fillMaxHeight() + .background(accentGradient) + ) + } + } + + @Composable + private fun GlassPopup(onDismiss: () -> Unit, content: @Composable ColumnScope.() -> Unit) { + Popup( + alignment = Alignment.Center, + properties = PopupProperties(focusable = true, dismissOnClickOutside = true, dismissOnBackPress = true), + onDismissRequest = onDismiss + ) { + Column( + modifier = Modifier + .widthIn(max = 520.dp) + .clip(RoundedCornerShape(20.dp)) + .background(panelOverlay) + .border(1.2.dp, accentGradient, RoundedCornerShape(20.dp)) + .padding(16.dp), + verticalArrangement = Arrangement.spacedBy(8.dp) + ) { + content() + } + } + } + + @Composable + private fun SectionLabel(text: String) { + BasicText( + text = text, + modifier = Modifier.fillMaxWidth(), + style = androidx.compose.ui.text.TextStyle( + color = Color(0xFFD9D3FF), + fontSize = 13.sp, + textAlign = TextAlign.Start + ) + ) + } + + @Composable + private fun BareToggle( + checked: Boolean, + onCheckedChange: (Boolean) -> Unit, + accent: Color + ) { + val knobOffset by animateFloatAsState(targetValue = if (checked) 18f else 0f, animationSpec = tween(180), label = "bareToggle") + Box( + modifier = Modifier + .width(44.dp) + .height(24.dp) + .clip(RoundedCornerShape(50)) + .border(1.dp, accent.copy(alpha = 0.6f), RoundedCornerShape(50)) + .background(Color.White.copy(alpha = 0.04f)) + .clickable { onCheckedChange(!checked) } + .padding(3.dp) + ) { + Box( + modifier = Modifier + .fillMaxHeight() + .width(18.dp) + .offset(x = knobOffset.dp) + .clip(RoundedCornerShape(50)) + .background(Brush.horizontalGradient(listOf(accent, Color(0xFF6C7CFF)))) + ) + } + } + + @Composable + private fun NeonToggle( + checked: Boolean, + onCheckedChange: (Boolean) -> Unit, + label: String, + accent: Color + ) { + Row( + modifier = Modifier + .fillMaxWidth() + .clip(RoundedCornerShape(14.dp)) + .background(Color.White.copy(alpha = 0.07f)) + .border(1.dp, accentGradient, RoundedCornerShape(14.dp)) + .clickable { onCheckedChange(!checked) } + .padding(12.dp), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(10.dp) + ) { + Box( + modifier = Modifier + .size(40.dp, 22.dp) + .clip(RoundedCornerShape(50)) + .background(Color(0xFF0F1727)) + .border(1.dp, Color.White.copy(alpha = 0.14f), RoundedCornerShape(50)) + .padding(3.dp) + ) { + Box( + modifier = Modifier + .fillMaxHeight() + .width(16.dp) + .offset(x = if (checked) 18.dp else 0.dp) + .clip(RoundedCornerShape(50)) + .background(Brush.horizontalGradient(listOf(accent, Color(0xFF6C7CFF)))) + ) + } + Column { + BasicText( + text = label, + style = androidx.compose.ui.text.TextStyle(color = Color.White, fontSize = 14.sp) + ) + BasicText( + text = if (checked) "On" else "Off", + style = androidx.compose.ui.text.TextStyle(color = Color(0xFFB1B4D7), fontSize = 11.sp) + ) + } + } + } + + @Composable + private fun PrimaryButton( + text: String, + modifier: Modifier = Modifier, + onClick: () -> Unit + ) { + Box( + modifier = modifier + .clip(RoundedCornerShape(14.dp)) + .background(accentGradient) + .clickable(onClick = onClick) + .padding(vertical = 12.dp), + contentAlignment = Alignment.Center + ) { + BasicText( + text = text, + style = androidx.compose.ui.text.TextStyle(color = Color(0xFF0A0F1D), fontSize = 14.sp, fontWeight = FontWeight.SemiBold) + ) + } + } + + @Composable + private fun SecondaryButton( + text: String, + modifier: Modifier = Modifier, + onClick: () -> Unit + ) { + Box( + modifier = modifier + .clip(RoundedCornerShape(14.dp)) + .border(1.dp, Color.White.copy(alpha = 0.16f), RoundedCornerShape(14.dp)) + .background(Color.White.copy(alpha = 0.06f)) + .clickable(onClick = onClick) + .padding(vertical = 12.dp), + contentAlignment = Alignment.Center + ) { + BasicText( + text = text, + style = androidx.compose.ui.text.TextStyle(color = Color.White, fontSize = 14.sp, fontWeight = FontWeight.SemiBold) + ) + } + } + + private fun formatRange(start: Long?, end: Long?): String { + fun fmt(millis: Long?): String = millis?.let { + Instant.ofEpochMilli(it).atZone(ZoneOffset.UTC).toLocalDate().format(rangeFormatter) + } ?: "Not set" + return "${fmt(start)} - ${fmt(end)}" + } + + override fun run() { + context.coroutineScope.launch(Dispatchers.Main) { + val database = runCatching { + SQLiteDatabase.openDatabase( + context.androidContext.getDatabasePath("memories.db"), + OpenParams.Builder().setOpenFlags(SQLiteDatabase.OPEN_READONLY).build() + ) + }.getOrNull() + + if (database == null) { + context.longToast("Failed to open memories database") + return@launch + } + + createComposeAlertDialog(context.mainActivity!!) { alertDialog -> + ExporterDialog(database) { alertDialog.dismiss() } + }.apply { + setOnDismissListener { database.close() } + setCanceledOnTouchOutside(false) + show() + } + } + } +} diff --git a/core/src/main/kotlin/me/eternal/purrfectsnap/core/action/impl/ManageFriendList.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/action/impl/ManageFriendList.kt new file mode 100644 index 00000000..3925d7b6 --- /dev/null +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/action/impl/ManageFriendList.kt @@ -0,0 +1,685 @@ +package me.eternal.purrfectsnap.core.action.impl + +import android.content.Intent +import android.net.Uri +import androidx.compose.foundation.BorderStroke +import androidx.compose.foundation.Image +import androidx.compose.foundation.background +import androidx.compose.foundation.border +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.foundation.text.BasicText +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.automirrored.filled.ArrowBack +import androidx.compose.material.icons.filled.People +import androidx.compose.material3.CircularProgressIndicator +import androidx.compose.material3.Icon +import androidx.compose.material3.Surface +import androidx.compose.material3.Text +import androidx.compose.runtime.* +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.draw.alpha +import androidx.compose.ui.graphics.Brush +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.Job +import kotlinx.coroutines.delay +import kotlinx.coroutines.launch +import kotlinx.coroutines.withTimeout +import me.eternal.purrfectsnap.common.data.FriendLinkType +import me.eternal.purrfectsnap.common.ui.createComposeAlertDialog +import me.eternal.purrfectsnap.core.action.AbstractAction +import me.eternal.purrfectsnap.core.event.events.impl.ActivityResultEvent +import me.eternal.purrfectsnap.core.features.impl.experiments.AddFriendSourceSpoof +import me.eternal.purrfectsnap.core.features.impl.messaging.Messaging +import me.eternal.purrfectsnap.core.wrapper.impl.Snapchatter +import kotlin.random.Random + +class ManageFriendList : AbstractAction() { + private val translation by lazy { context.translation.getCategory("friend_list") } + private val dialogBackground = Brush.verticalGradient( + listOf( + Color(0xFF1D1538), + Color(0xFF130F2A) + ) + ) + private val panelOverlay = Brush.linearGradient( + listOf( + Color(0xFF2C2551), + Color(0xFF1B1636) + ) + ) + private val accentGradient = Brush.horizontalGradient( + listOf( + Color(0xFF8C7BFF), + Color(0xFF5FD8FF) + ) + ) + private var pendingPickerAction: Pair Unit>? = null + + private val uuidRegex by lazy { + Regex("[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}") + } + + private fun loadStaticDefaultField(classLoader: ClassLoader, className: String, fieldName: String): Any? { + return try { + val clazz = classLoader.loadClass(className) + try { + val field = clazz.getDeclaredField(fieldName) + field.isAccessible = true + field.get(null) + } catch (e: Exception) { + clazz.declaredFields + .filter { java.lang.reflect.Modifier.isStatic(it.modifiers) } + .firstOrNull() + ?.apply { isAccessible = true } + ?.get(null) + } + } catch (e: Exception) { + context.log.warn("Could not load $className: ${e.message}") + null + } + } + + private fun addFriend(userId: String) { + val friendRelationshipChangerInstance = context.feature(AddFriendSourceSpoof::class).friendRelationshipChangerInstance + if (friendRelationshipChangerInstance == null) { + context.log.error("friendRelationshipChangerInstance is null") + context.longToast("Failed to add friend: FriendRelationshipChanger instance not available") + return + } + + runCatching { + val classLoader = context.androidContext.classLoader + + val classNamesToTry = listOf("EnumC3559qC", "qC", "com.snapchat.android.EnumC3559qC", "LC", "EnumC0886LC", "EnumC1539TC", "TC") + + val enumC3559qCClass = classNamesToTry.firstNotNullOfOrNull { className -> + try { + classLoader.loadClass(className).takeIf { it.isEnum }?.also { + context.log.verbose("Successfully loaded enum class: $className") + } + } catch (e: Exception) { + null + } + } + + if (enumC3559qCClass == null) { + context.log.error("Friend source enum class not found after trying: ${classNamesToTry.joinToString()}") + context.longToast("Failed to add friend: Required enum class not found") + return@runCatching + } + + val enumConstants = enumC3559qCClass.enumConstants + ?: enumC3559qCClass.getMethod("values").invoke(null) as? Array<*> + ?: run { + context.log.error("Could not retrieve enum constants from ${enumC3559qCClass.name}") + context.longToast("Failed to add friend: Enum constants not accessible") + return@runCatching + } + + context.log.verbose("Found ${enumConstants.size} enum constants") + + val addedByUsername = enumConstants.firstOrNull { it.toString() == "ADDED_BY_USERNAME" } + ?: enumConstants.firstOrNull { it.toString().contains("USERNAME", ignoreCase = true) } + ?: enumConstants.firstOrNull() + ?: run { + context.log.error("No enum constants available") + context.longToast("Failed to add friend: No valid enum constant found") + return@runCatching + } + + context.log.verbose("Using enum constant: $addedByUsername") + + val sQ7Default = loadStaticDefaultField(classLoader, "sQ7", "f288251e0") + val zQ7Default = loadStaticDefaultField(classLoader, "ZQ7", "f159958F0") + + val iBgClass = try { + classLoader.loadClass("iBg") + } catch (e: Exception) { + context.log.error("Could not load iBg class: ${e.message}") + null + } + + if (iBgClass == null) { + context.log.error("iBg class not found") + return@runCatching + } + + val m51157aMethod = iBgClass.declaredMethods.firstOrNull { it.name == "m51157a" } + ?: iBgClass.methods.firstOrNull { it.name == "m51157a" } + ?: iBgClass.declaredMethods.firstOrNull { method -> + java.lang.reflect.Modifier.isStatic(method.modifiers) && + method.parameterTypes.size == 14 && + method.parameterTypes[0].isAssignableFrom(friendRelationshipChangerInstance.javaClass) && + method.parameterTypes[1] == String::class.java && + method.parameterTypes[2] == enumC3559qCClass + } + + if (m51157aMethod == null) { + context.log.error("Could not find iBg.m51157a method") + context.log.error("Available static methods with 14 params:") + iBgClass.declaredMethods.filter { + java.lang.reflect.Modifier.isStatic(it.modifiers) && it.parameterTypes.size == 14 + }.forEach { method -> + context.log.error(" ${method.name}: ${method.parameterTypes.joinToString { it.simpleName }}") + } + return@runCatching + } + m51157aMethod.isAccessible = true + + try { + m51157aMethod.invoke( + null, + friendRelationshipChangerInstance, + userId, + addedByUsername, + sQ7Default, + zQ7Default, + null, + null, + null, + null, + null, + null, + null, + null, + 4064 + )?.also { result -> + result.javaClass.methods + .find { it.name == "subscribe" && it.parameterCount == 0 } + ?.apply { isAccessible = true } + ?.invoke(result) + } + } catch (e: Exception) { + context.log.error("Exception during method invocation: ${e.javaClass.name}: ${e.message}") + e.cause?.let { cause -> + context.log.error("Cause: ${cause.javaClass.name}: ${cause.message}") + cause.stackTrace?.take(5)?.forEach { + context.log.error(" at $it") + } + } + throw e + } + }.onFailure { + context.log.error("Failed to add friend $userId", it) + context.longToast("Failed to add friend: ${it.message}") + } + } + + override fun onActivityCreate() { + context.event.subscribe(ActivityResultEvent::class) { event -> + if (event.requestCode == pendingPickerAction?.first) { + val pendingAction = pendingPickerAction ?: return@subscribe + this.pendingPickerAction = null + event.canceled = true + pendingAction.second(event.intent.data!!) + } + } + } + + private fun exportFriends( + userIds: List + ) { + pendingPickerAction = Random.nextInt(0, 65535) to { data -> + context.androidContext.contentResolver.openOutputStream(data).use { output -> + output?.bufferedWriter()?.use { writer -> + userIds.forEach { + writer.write(it) + writer.newLine() + } + } + context.longToast("Exported ${userIds.size} friends!") + } + } + context.mainActivity?.startActivityForResult( + Intent.createChooser( + Intent(Intent.ACTION_CREATE_DOCUMENT).apply { + type = "text/plain" + putExtra(Intent.EXTRA_TITLE, "my_friends.txt") + }, + "Select a location to save the file" + ), + pendingPickerAction!!.first + ) + } + + private val userIdToSnapchatter = mutableMapOf() + + @Composable + private fun ManagerDialog() { + val pendingFriendRequests = remember { mutableStateMapOf() } + var fetchedFriends by remember { mutableStateOf?>(null) } + val coroutineScope = rememberCoroutineScope() + + Box( + modifier = Modifier + .fillMaxWidth() + .background(dialogBackground) + .padding(12.dp) + ) { + Box( + modifier = Modifier + .matchParentSize() + .padding(6.dp) + ) { + Box( + modifier = Modifier + .size(220.dp) + .align(Alignment.TopEnd) + .offset(x = 44.dp, y = (-36).dp) + .background( + Brush.radialGradient( + listOf(Color(0xFF8C7BFF).copy(alpha = 0.32f), Color.Transparent) + ) + ) + ) + Box( + modifier = Modifier + .size(240.dp) + .align(Alignment.BottomStart) + .offset(x = (-60).dp, y = 28.dp) + .background( + Brush.radialGradient( + listOf(Color(0xFF5FD8FF).copy(alpha = 0.3f), Color.Transparent) + ) + ) + ) + } + + Surface( + modifier = Modifier + .fillMaxWidth() + .align(Alignment.Center) + .heightIn(min = 260.dp) + .border(1.2.dp, accentGradient, RoundedCornerShape(28.dp)), + shape = RoundedCornerShape(28.dp), + tonalElevation = 0.dp, + color = Color.White.copy(alpha = 0.04f) + ) { + if (fetchedFriends == null) { + Column( + modifier = Modifier + .fillMaxWidth() + .background(panelOverlay) + .padding(18.dp), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.spacedBy(16.dp) + ) { + Row( + modifier = Modifier.fillMaxWidth(), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(14.dp) + ) { + Box( + modifier = Modifier + .size(56.dp) + .clip(RoundedCornerShape(18.dp)) + .background(Color.White.copy(alpha = 0.08f)) + .border(1.dp, Color.White.copy(alpha = 0.12f), RoundedCornerShape(18.dp)) + .padding(12.dp) + ) { + Icon( + imageVector = Icons.Filled.People, + contentDescription = null, + tint = Color.White, + modifier = Modifier + .align(Alignment.Center) + .size(28.dp) + ) + } + Column(modifier = Modifier.weight(1f)) { + Text( + translation.get("manage_title"), + color = Color.White, + fontSize = 21.sp, + fontWeight = FontWeight.ExtraBold + ) + Text( + text = translation.get("export_description"), + color = Color(0xFFD9D3FF), + fontSize = 14.sp + ) + } + } + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.spacedBy(12.dp) + ) { + PrimaryButton( + text = translation.get("export_friends"), + modifier = Modifier.weight(1f) + ) { + exportFriends(context.database.getAllFriends().filter { it.friendLinkType == FriendLinkType.MUTUAL.value && it.addedTimestamp > 0L }.mapNotNull { it.userId }) + } + SecondaryButton( + text = translation.get("import_from_file"), + modifier = Modifier.weight(1f) + ) { + pendingPickerAction = Random.nextInt(0, 65535) to { data -> + runCatching { + fetchedFriends = null + context.androidContext.contentResolver.openInputStream(data).use { input -> + fetchedFriends = input?.bufferedReader()?.readLines()?.filter { + it.matches(uuidRegex) + }?.map { it.trim() }?.toMutableList() ?: mutableListOf() + } + }.onFailure { + context.log.error("Failed to import friends", it) + context.longToast("Failed to import friends: ${it.message}") + } + } + context.mainActivity?.startActivityForResult( + Intent.createChooser( + Intent(Intent.ACTION_GET_CONTENT).apply { type = "*/*" }, + "Select a file" + ), + pendingPickerAction!!.first + ) + } + } + } + } else { + Column( + modifier = Modifier + .fillMaxWidth() + .heightIn(min = 360.dp) + .background(panelOverlay) + .padding(horizontal = 16.dp, vertical = 14.dp), + verticalArrangement = Arrangement.spacedBy(12.dp) + ) { + Row( + modifier = Modifier.fillMaxWidth(), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(12.dp) + ) { + Box( + modifier = Modifier + .size(46.dp) + .clip(RoundedCornerShape(14.dp)) + .background(Color.White.copy(alpha = 0.08f)) + .border(1.dp, Color.White.copy(alpha = 0.14f), RoundedCornerShape(14.dp)) + .clickable { fetchedFriends = null }, + contentAlignment = Alignment.Center + ) { + Image( + imageVector = Icons.AutoMirrored.Default.ArrowBack, + contentDescription = context.translation["common.back"], + modifier = Modifier.size(22.dp) + ) + } + Column( + modifier = Modifier.weight(1f), + horizontalAlignment = Alignment.CenterHorizontally + ) { + Text( + text = translation.get("manage_title"), + color = Color.White, + fontSize = 18.sp, + fontWeight = FontWeight.ExtraBold + ) + Text( + text = translation.get("export_description"), + color = Color(0xFFD9D3FF), + fontSize = 12.sp, + textAlign = TextAlign.Center, + modifier = Modifier.fillMaxWidth() + ) + } + Spacer(modifier = Modifier.size(46.dp)) + } + + Surface( + modifier = Modifier + .fillMaxWidth() + .weight(1f), + shape = RoundedCornerShape(20.dp), + tonalElevation = 0.dp, + color = Color.White.copy(alpha = 0.04f), + border = BorderStroke(1.dp, Color.White.copy(alpha = 0.12f)) + ) { + LazyColumn( + modifier = Modifier + .fillMaxSize() + .padding(12.dp) + ) { + item { + if (fetchedFriends?.isEmpty() == true) { + BasicText( + context.translation["common.no_friends_found"], + style = androidx.compose.ui.text.TextStyle(color = Color(0xFFA8B5D1), fontSize = 13.sp), + modifier = Modifier.padding(8.dp) + ) + } + } + items(fetchedFriends ?: emptyList()) { userId -> + fun fetchLocalLinkType(): FriendLinkType? { + return context.database.getFriendInfo(userId)?.friendLinkType?.let { FriendLinkType.fromValue(it) } + } + + fun isActuallyAdded(): Boolean { + val friendInfo = context.database.getFriendInfo(userId) + return friendInfo != null && + (friendInfo.friendLinkType == FriendLinkType.MUTUAL.value || + friendInfo.friendLinkType == FriendLinkType.OUTGOING.value) && + friendInfo.addedTimestamp > 0L + } + + var friendSnapchatter by remember(userId) { mutableStateOf(null) } + var failedToFetch by remember(userId) { mutableStateOf(false) } + var friendLinkType by remember(userId) { mutableStateOf(fetchLocalLinkType()) } + var actuallyAdded by remember(userId) { mutableStateOf(isActuallyAdded()) } + + LaunchedEffect(userId) { + launch(Dispatchers.IO) { + friendSnapchatter = userIdToSnapchatter.getOrPut(userId) { + context.feature(Messaging::class).fetchSnapchatterInfos(listOf(userId)).firstOrNull() ?: run { + failedToFetch = true + return@launch + } + } + } + + // Polling loop to keep status in sync (like FriendList.kt) + while (true) { + delay(2000) + val newLinkType = fetchLocalLinkType() + if (newLinkType != friendLinkType) { + friendLinkType = newLinkType + } + val newActuallyAdded = isActuallyAdded() + if (newActuallyAdded != actuallyAdded) { + actuallyAdded = newActuallyAdded + } + } + } + + Row( + modifier = Modifier + .fillMaxWidth() + .padding(vertical = 8.dp, horizontal = 6.dp) + .clip(RoundedCornerShape(14.dp)) + .background(Color.White.copy(alpha = 0.05f)) + .border(1.dp, accentGradient, RoundedCornerShape(14.dp)) + .padding(12.dp), + verticalAlignment = Alignment.CenterVertically + ) { + Column( + modifier = Modifier.weight(1f), + verticalArrangement = Arrangement.spacedBy(4.dp) + ) { + BasicText( + friendSnapchatter?.let { snapchatter -> + snapchatter.displayName?.let { "$it (${snapchatter.username}) " } ?: snapchatter.username ?: context.translation["common.unknown"] + } ?: userId, + style = androidx.compose.ui.text.TextStyle(color = Color.White, fontSize = 14.sp, fontWeight = FontWeight.SemiBold) + ) + BasicText( + userId, + style = androidx.compose.ui.text.TextStyle(color = Color(0xFFB1B4D7), fontSize = 12.sp) + ) + Row(horizontalArrangement = Arrangement.spacedBy(6.dp)) { + friendLinkType?.let { type -> + StatusPill( + text = type.name.lowercase().replaceFirstChar { it.uppercase() }, + color = if (type == FriendLinkType.MUTUAL) Color(0xFF8EF0F3) else Color(0xFFD9D3FF) + ) + } + if (failedToFetch) { + StatusPill( + text = translation.get("failed_to_fetch") ?: "Fetch failed", + color = Color(0xFFF4B4B4) + ) + } + } + } + + if (friendSnapchatter != null) { + val isPending = pendingFriendRequests.containsKey(userId) && pendingFriendRequests[userId]?.isActive != false + val isFollowing = friendLinkType == FriendLinkType.FOLLOWING + + PrimaryButton( + text = when { + isFollowing -> "Following" + actuallyAdded -> context.translation["common.added"] + isPending -> translation.get("adding") ?: "Adding..." + else -> translation.get("add") + }, + modifier = Modifier.widthIn(min = 110.dp), + enabled = !actuallyAdded && !isPending && !isFollowing + ) { + if (actuallyAdded || isPending || isFollowing) return@PrimaryButton + + val job = coroutineScope.launch { + try { + addFriend(userId) + delay(300) + actuallyAdded = true + withTimeout(3000) { + var attempts = 0 + while (attempts < 12) { + val currentLinkType = fetchLocalLinkType() + if (currentLinkType == FriendLinkType.MUTUAL || + currentLinkType == FriendLinkType.FOLLOWING || + currentLinkType == FriendLinkType.OUTGOING) { + friendLinkType = currentLinkType + actuallyAdded = true + break + } + attempts++ + delay(250) + } + } + } catch (e: Exception) { + context.log.error("Failed to add friend or verify status: ${e.message}") + actuallyAdded = true + } + }.apply { + invokeOnCompletion { + pendingFriendRequests.remove(userId) + friendLinkType = fetchLocalLinkType() + actuallyAdded = isActuallyAdded() || actuallyAdded + } + } + pendingFriendRequests[userId] = job + } + if (isPending) { + Spacer(modifier = Modifier.width(8.dp)) + CircularProgressIndicator( + modifier = Modifier.size(18.dp), + strokeWidth = 2.dp, + color = Color(0xFF8EF0F3) + ) + } + } + } + } + } + } + } + } + } + } + } + + @Composable + private fun PrimaryButton( + text: String, + modifier: Modifier = Modifier, + enabled: Boolean = true, + onClick: () -> Unit + ) { + val shape = RoundedCornerShape(14.dp) + Box( + modifier = modifier + .clip(shape) + .alpha(if (enabled) 1f else 0.6f) + .background(accentGradient) + .clickable(enabled = enabled, onClick = onClick) + .padding(vertical = 10.dp, horizontal = 12.dp), + contentAlignment = Alignment.Center + ) { + BasicText( + text = text, + style = androidx.compose.ui.text.TextStyle(color = Color(0xFF0A0F1D), fontSize = 14.sp, fontWeight = FontWeight.SemiBold) + ) + } + } + + @Composable + private fun SecondaryButton( + text: String, + modifier: Modifier = Modifier, + onClick: () -> Unit + ) { + val shape = RoundedCornerShape(14.dp) + Box( + modifier = modifier + .clip(shape) + .border(1.dp, Color.White.copy(alpha = 0.16f), shape) + .background(Color.White.copy(alpha = 0.06f)) + .clickable(onClick = onClick) + .padding(vertical = 10.dp, horizontal = 12.dp), + contentAlignment = Alignment.Center + ) { + BasicText( + text = text, + style = androidx.compose.ui.text.TextStyle(color = Color(0xFFE6ECFF), fontSize = 14.sp, fontWeight = FontWeight.SemiBold) + ) + } + } + + @Composable + private fun StatusPill(text: String, color: Color) { + Text( + text = text, + color = color, + fontSize = 12.sp, + fontWeight = FontWeight.Medium, + modifier = Modifier + .clip(RoundedCornerShape(50)) + .background(color.copy(alpha = 0.14f)) + .padding(horizontal = 10.dp, vertical = 6.dp) + ) + } + + override fun run() { + context.coroutineScope.launch(Dispatchers.Main) { + createComposeAlertDialog(context.mainActivity!!) { + ManagerDialog() + }.apply { + setCanceledOnTouchOutside(false) + show() + } + } + } +} diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/bridge/BridgeClient.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/bridge/BridgeClient.kt similarity index 87% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/bridge/BridgeClient.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/bridge/BridgeClient.kt index 6a325a9a..1f80fa0c 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/bridge/BridgeClient.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/bridge/BridgeClient.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.core.bridge +package me.eternal.purrfectsnap.core.bridge import android.content.ComponentName @@ -13,22 +13,23 @@ import kotlinx.coroutines.suspendCancellableCoroutine import kotlinx.coroutines.sync.Semaphore import kotlinx.coroutines.sync.withPermit import kotlinx.coroutines.withTimeoutOrNull -import me.rhunk.snapenhance.bridge.* -import me.rhunk.snapenhance.bridge.e2ee.E2eeInterface -import me.rhunk.snapenhance.bridge.location.LocationManager -import me.rhunk.snapenhance.bridge.logger.LoggerInterface -import me.rhunk.snapenhance.bridge.logger.TrackerInterface -import me.rhunk.snapenhance.bridge.scripting.IScripting -import me.rhunk.snapenhance.bridge.snapclient.MessagingBridge -import me.rhunk.snapenhance.bridge.storage.FileHandleManager -import me.rhunk.snapenhance.common.Constants -import me.rhunk.snapenhance.common.data.MessagingFriendInfo -import me.rhunk.snapenhance.common.data.MessagingGroupInfo -import me.rhunk.snapenhance.common.data.MessagingRuleType -import me.rhunk.snapenhance.common.data.SocialScope -import me.rhunk.snapenhance.common.ui.OverlayType -import me.rhunk.snapenhance.common.util.toSerialized -import me.rhunk.snapenhance.core.ModContext +import me.eternal.purrfectsnap.bridge.* +import me.eternal.purrfectsnap.bridge.e2ee.E2eeInterface +import me.eternal.purrfectsnap.bridge.location.LocationManager +import me.eternal.purrfectsnap.bridge.logger.LoggerInterface +import me.eternal.purrfectsnap.bridge.logger.TrackerInterface +import me.eternal.purrfectsnap.bridge.task.TaskInterface +import me.eternal.purrfectsnap.bridge.scripting.IScripting +import me.eternal.purrfectsnap.bridge.snapclient.MessagingBridge +import me.eternal.purrfectsnap.bridge.storage.FileHandleManager +import me.eternal.purrfectsnap.common.Constants +import me.eternal.purrfectsnap.common.data.MessagingFriendInfo +import me.eternal.purrfectsnap.common.data.MessagingGroupInfo +import me.eternal.purrfectsnap.common.data.MessagingRuleType +import me.eternal.purrfectsnap.common.data.SocialScope +import me.eternal.purrfectsnap.common.ui.OverlayType +import me.eternal.purrfectsnap.common.util.toSerialized +import me.eternal.purrfectsnap.core.ModContext import java.util.concurrent.Executors import kotlin.coroutines.Continuation import kotlin.coroutines.resume @@ -42,7 +43,7 @@ class BridgeClient( private lateinit var service: BridgeInterface private val onConnectedCallbacks = mutableListOf Unit>() - private var cacheSnapEnhanceApkPath: String? = null + private var cachePurrfectSnapApkPath: String? = null fun addOnConnectedCallback(initNow: Boolean = false, callback: suspend () -> Unit) { synchronized(onConnectedCallbacks) { @@ -83,14 +84,14 @@ class BridgeClient( //ensure the remote process is running runCatching { startActivity(Intent() - .setClassName(Constants.SE_PACKAGE_NAME, "me.rhunk.snapenhance.bridge.ForceStartActivity") + .setClassName(Constants.SE_PACKAGE_NAME, "me.eternal.purrfectsnap.bridge.ForceStartActivity") .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_MULTIPLE_TASK) ) } runCatching { val intent = Intent() - .setClassName(Constants.SE_PACKAGE_NAME, "me.rhunk.snapenhance.bridge.BridgeService") + .setClassName(Constants.SE_PACKAGE_NAME, "me.eternal.purrfectsnap.bridge.BridgeService") runCatching { if (this@BridgeClient::service.isInitialized) { unbindService(this@BridgeClient) @@ -141,9 +142,9 @@ class BridgeClient( } } } - cacheSnapEnhanceApkPath = this.service.applicationApkPath.also { - if (cacheSnapEnhanceApkPath != null && cacheSnapEnhanceApkPath != it) { - context.log.verbose("Restarting Snapchat due to SnapEnhance update") + cachePurrfectSnapApkPath = this.service.applicationApkPath.also { + if (cachePurrfectSnapApkPath != null && cachePurrfectSnapApkPath != it) { + context.log.verbose("Restarting Snapchat due to PurrfectSnap update") context.softRestartApp() return } @@ -273,6 +274,8 @@ class BridgeClient( fun getLocationManager(): LocationManager = safeServiceCall { service.locationManager } + fun getTaskInterface(): TaskInterface = safeServiceCall { service.taskInterface } + fun registerMessagingBridge(bridge: MessagingBridge) = safeServiceCall { service.registerMessagingBridge(bridge) } fun openOverlay(type: OverlayType) = safeServiceCall { service.openOverlay(type.key) } diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/data/SnapClassCache.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/data/SnapClassCache.kt similarity index 77% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/data/SnapClassCache.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/data/SnapClassCache.kt index 822d2fff..2a7b7f7a 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/data/SnapClassCache.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/data/SnapClassCache.kt @@ -1,9 +1,10 @@ -package me.rhunk.snapenhance.core.data +package me.eternal.purrfectsnap.core.data class SnapClassCache ( private val classLoader: ClassLoader ) { val snapUUID by lazy { findClass("com.snapchat.client.messaging.UUID") } + val snapShimsUUID by lazy { runCatching { classLoader.loadClass("com.snapchat.client.shims.UUID") }.getOrNull() } val snapManager by lazy { findClass("com.snapchat.client.messaging.SnapManager\$CppProxy") } val conversationManager by lazy { findClass("com.snapchat.client.messaging.ConversationManager\$CppProxy") } val presenceSession by lazy { findClass("com.snapchat.talkcorev3.PresenceSession\$CppProxy") } @@ -18,10 +19,10 @@ class SnapClassCache ( val conversation by lazy { findClass("com.snapchat.client.messaging.Conversation") } val feedManager by lazy { findClass("com.snapchat.client.messaging.FeedManager\$CppProxy") } val nativeBridge by lazy { runCatching { findClass("com.snapchat.client.valdi.NativeBridge") }.getOrNull() ?: findClass("com.snapchat.client.composer.NativeBridge") } - val composerView by lazy { findClass("com.snap.composer.views.ComposerView") } - val composerAction by lazy { findClass("com.snap.composer.actions.ComposerAction") } - val composerFunctionActionAdapter by lazy { findClass("com.snap.composer.callable.ComposerFunctionActionAdapter") } - + val composerView by lazy { runCatching { findClass("com.snap.composer.views.ComposerView") }.getOrNull() } + val composerAction by lazy { runCatching { findClass("com.snap.composer.actions.ComposerAction") }.getOrNull() } + val composerFunctionActionAdapter by lazy { runCatching { findClass("com.snap.composer.callable.ComposerFunctionActionAdapter") }.getOrNull() } + private fun findClass(className: String): Class<*> { return try { classLoader.loadClass(className) @@ -29,4 +30,4 @@ class SnapClassCache ( throw RuntimeException("Failed to find class $className", e) } } -} \ No newline at end of file +} diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/database/DatabaseAccess.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/database/DatabaseAccess.kt similarity index 94% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/database/DatabaseAccess.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/database/DatabaseAccess.kt index 085e3079..dd620ac6 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/database/DatabaseAccess.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/database/DatabaseAccess.kt @@ -1,20 +1,20 @@ -package me.rhunk.snapenhance.core.database +package me.eternal.purrfectsnap.core.database import android.content.ContentValues import android.database.Cursor import android.database.sqlite.SQLiteDatabase import android.database.sqlite.SQLiteDatabase.OpenParams import android.database.sqlite.SQLiteDatabaseCorruptException -import me.rhunk.snapenhance.common.database.DatabaseObject -import me.rhunk.snapenhance.common.database.impl.* -import me.rhunk.snapenhance.common.util.ktx.getBlobOrNull -import me.rhunk.snapenhance.common.util.ktx.getIntOrNull -import me.rhunk.snapenhance.common.util.ktx.getInteger -import me.rhunk.snapenhance.common.util.ktx.getStringOrNull -import me.rhunk.snapenhance.common.util.protobuf.ProtoReader -import me.rhunk.snapenhance.core.ModContext -import me.rhunk.snapenhance.core.wrapper.impl.toSnapUUID -import me.rhunk.snapenhance.nativelib.NativeLib +import me.eternal.purrfectsnap.common.database.DatabaseObject +import me.eternal.purrfectsnap.common.database.impl.* +import me.eternal.purrfectsnap.common.util.ktx.getBlobOrNull +import me.eternal.purrfectsnap.common.util.ktx.getIntOrNull +import me.eternal.purrfectsnap.common.util.ktx.getInteger +import me.eternal.purrfectsnap.common.util.ktx.getStringOrNull +import me.eternal.purrfectsnap.common.util.protobuf.ProtoReader +import me.eternal.purrfectsnap.core.ModContext +import me.eternal.purrfectsnap.core.wrapper.impl.toSnapUUID +import me.eternal.purrfectsnap.nativelib.NativeLib enum class DatabaseType( @@ -39,6 +39,14 @@ class DatabaseAccess( } == true } + private val hasMainFriendsFeedView by lazy { + useDatabase(DatabaseType.MAIN)?.performOperation { + safeRawQuery("SELECT name FROM sqlite_master WHERE name = 'FriendsFeedView'")?.use { query -> + query.moveToFirst() && query.getStringOrNull("name") == "FriendsFeedView" + } + } == true + } + private fun useDatabase(database: DatabaseType, writeMode: Boolean = false): SQLiteDatabase? { // only cache read-only databases if (!writeMode && openedDatabases.containsKey(database) && openedDatabases[database]?.isOpen == true) { @@ -218,14 +226,16 @@ class DatabaseAccess( "client_conversation_id = ?", arrayOf(conversationId) ) - } ?: useDatabase(DatabaseType.MAIN)?.performOperation { - readDatabaseObject( - FriendFeedEntry(), - "FriendsFeedView", - "key = ?", - arrayOf(conversationId) - ) - } + } ?: if (hasMainFriendsFeedView) { + useDatabase(DatabaseType.MAIN)?.performOperation { + readDatabaseObject( + FriendFeedEntry(), + "FriendsFeedView", + "key = ?", + arrayOf(conversationId) + ) + } + } else null } fun getFriendInfo(userId: String): FriendInfo? { diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/event/EventBus.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/event/EventBus.kt similarity index 96% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/event/EventBus.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/event/EventBus.kt index 5d74b370..0a63d47a 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/event/EventBus.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/event/EventBus.kt @@ -1,6 +1,6 @@ -package me.rhunk.snapenhance.core.event +package me.eternal.purrfectsnap.core.event -import me.rhunk.snapenhance.core.ModContext +import me.eternal.purrfectsnap.core.ModContext import java.util.concurrent.ConcurrentHashMap import kotlin.reflect.KClass diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/event/EventDispatcher.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/event/EventDispatcher.kt similarity index 87% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/event/EventDispatcher.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/event/EventDispatcher.kt index dd7770de..16809046 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/event/EventDispatcher.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/event/EventDispatcher.kt @@ -1,26 +1,26 @@ -package me.rhunk.snapenhance.core.event +package me.eternal.purrfectsnap.core.event import android.app.Activity import android.content.Intent import android.view.LayoutInflater import android.view.View import android.view.ViewGroup -import me.rhunk.snapenhance.common.util.snap.SnapWidgetBroadcastReceiverHelper -import me.rhunk.snapenhance.core.ModContext -import me.rhunk.snapenhance.core.event.events.impl.* -import me.rhunk.snapenhance.core.util.hook.HookStage -import me.rhunk.snapenhance.core.util.hook.Hooker -import me.rhunk.snapenhance.core.util.hook.findRestrictedMethod -import me.rhunk.snapenhance.core.util.hook.hook -import me.rhunk.snapenhance.core.util.hook.hookConstructor -import me.rhunk.snapenhance.core.util.ktx.getObjectField -import me.rhunk.snapenhance.core.util.ktx.setObjectField -import me.rhunk.snapenhance.core.wrapper.impl.Message -import me.rhunk.snapenhance.core.wrapper.impl.MessageContent -import me.rhunk.snapenhance.core.wrapper.impl.MessageDestinations -import me.rhunk.snapenhance.core.wrapper.impl.SnapUUID -import me.rhunk.snapenhance.mapper.impl.CallbackMapper -import me.rhunk.snapenhance.mapper.impl.ViewBinderMapper +import me.eternal.purrfectsnap.common.util.snap.SnapWidgetBroadcastReceiverHelper +import me.eternal.purrfectsnap.core.ModContext +import me.eternal.purrfectsnap.core.event.events.impl.* +import me.eternal.purrfectsnap.core.util.hook.HookStage +import me.eternal.purrfectsnap.core.util.hook.Hooker +import me.eternal.purrfectsnap.core.util.hook.findRestrictedMethod +import me.eternal.purrfectsnap.core.util.hook.hook +import me.eternal.purrfectsnap.core.util.hook.hookConstructor +import me.eternal.purrfectsnap.core.util.ktx.getObjectField +import me.eternal.purrfectsnap.core.util.ktx.setObjectField +import me.eternal.purrfectsnap.core.wrapper.impl.Message +import me.eternal.purrfectsnap.core.wrapper.impl.MessageContent +import me.eternal.purrfectsnap.core.wrapper.impl.MessageDestinations +import me.eternal.purrfectsnap.core.wrapper.impl.SnapUUID +import me.eternal.purrfectsnap.mapper.impl.CallbackMapper +import me.eternal.purrfectsnap.mapper.impl.ViewBinderMapper import java.nio.ByteBuffer class EventDispatcher( @@ -119,15 +119,21 @@ class EventDispatcher( index = param.arg(1), layoutParams = param.arg(2) ).apply { - adapter = param - } - ) { - with(param) { - setArg(0, view) - setArg(1, index) - setArg(2, layoutParams) - } - postHookEvent() + adapter = param + } + ) { + val normalizedIndex = when { + index < 0 -> -1 + index > parent.childCount -> parent.childCount + else -> index + } + index = normalizedIndex + with(param) { + setArg(0, view) + setArg(1, normalizedIndex) + setArg(2, layoutParams) + } + postHookEvent() } } @@ -302,4 +308,4 @@ class EventDispatcher( hookViewBinder() } -} \ No newline at end of file +} diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/event/events/AbstractHookEvent.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/event/events/AbstractHookEvent.kt similarity index 79% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/event/events/AbstractHookEvent.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/event/events/AbstractHookEvent.kt index 04ee553a..a285da94 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/event/events/AbstractHookEvent.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/event/events/AbstractHookEvent.kt @@ -1,7 +1,7 @@ -package me.rhunk.snapenhance.core.event.events +package me.eternal.purrfectsnap.core.event.events -import me.rhunk.snapenhance.core.event.Event -import me.rhunk.snapenhance.core.util.hook.HookAdapter +import me.eternal.purrfectsnap.core.event.Event +import me.eternal.purrfectsnap.core.util.hook.HookAdapter abstract class AbstractHookEvent : Event() { lateinit var adapter: HookAdapter diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/event/events/impl/ActivityResultEvent.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/event/events/impl/ActivityResultEvent.kt similarity index 63% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/event/events/impl/ActivityResultEvent.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/event/events/impl/ActivityResultEvent.kt index 11412403..6f0d77c7 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/event/events/impl/ActivityResultEvent.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/event/events/impl/ActivityResultEvent.kt @@ -1,8 +1,8 @@ -package me.rhunk.snapenhance.core.event.events.impl +package me.eternal.purrfectsnap.core.event.events.impl import android.app.Activity import android.content.Intent -import me.rhunk.snapenhance.core.event.events.AbstractHookEvent +import me.eternal.purrfectsnap.core.event.events.AbstractHookEvent class ActivityResultEvent( val activity: Activity, diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/event/events/impl/AddViewEvent.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/event/events/impl/AddViewEvent.kt similarity index 68% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/event/events/impl/AddViewEvent.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/event/events/impl/AddViewEvent.kt index b82c1504..a76957eb 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/event/events/impl/AddViewEvent.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/event/events/impl/AddViewEvent.kt @@ -1,8 +1,8 @@ -package me.rhunk.snapenhance.core.event.events.impl +package me.eternal.purrfectsnap.core.event.events.impl import android.view.View import android.view.ViewGroup -import me.rhunk.snapenhance.core.event.events.AbstractHookEvent +import me.eternal.purrfectsnap.core.event.events.AbstractHookEvent class AddViewEvent( val parent: ViewGroup, diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/event/events/impl/BindViewEvent.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/event/events/impl/BindViewEvent.kt similarity index 87% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/event/events/impl/BindViewEvent.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/event/events/impl/BindViewEvent.kt index 9bb56ed7..75969d2d 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/event/events/impl/BindViewEvent.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/event/events/impl/BindViewEvent.kt @@ -1,10 +1,10 @@ -package me.rhunk.snapenhance.core.event.events.impl +package me.eternal.purrfectsnap.core.event.events.impl import android.view.View import android.view.ViewGroup import android.widget.LinearLayout -import me.rhunk.snapenhance.common.database.impl.ConversationMessage -import me.rhunk.snapenhance.core.event.Event +import me.eternal.purrfectsnap.common.database.impl.ConversationMessage +import me.eternal.purrfectsnap.core.event.Event class BindViewEvent( val prevModel: Any, diff --git a/core/src/main/kotlin/me/eternal/purrfectsnap/core/event/events/impl/BuildMessageEvent.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/event/events/impl/BuildMessageEvent.kt new file mode 100644 index 00000000..41dfd547 --- /dev/null +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/event/events/impl/BuildMessageEvent.kt @@ -0,0 +1,8 @@ +package me.eternal.purrfectsnap.core.event.events.impl + +import me.eternal.purrfectsnap.core.event.Event +import me.eternal.purrfectsnap.core.wrapper.impl.Message + +class BuildMessageEvent( + val message: Message +): Event() \ No newline at end of file diff --git a/core/src/main/kotlin/me/eternal/purrfectsnap/core/event/events/impl/ConversationUpdateEvent.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/event/events/impl/ConversationUpdateEvent.kt new file mode 100644 index 00000000..3ae05843 --- /dev/null +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/event/events/impl/ConversationUpdateEvent.kt @@ -0,0 +1,10 @@ +package me.eternal.purrfectsnap.core.event.events.impl + +import me.eternal.purrfectsnap.core.event.events.AbstractHookEvent +import me.eternal.purrfectsnap.core.wrapper.impl.Message + +class ConversationUpdateEvent( + val conversationId: String, + val conversation: Any?, + val messages: List +) : AbstractHookEvent() \ No newline at end of file diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/event/events/impl/LayoutInflateEvent.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/event/events/impl/LayoutInflateEvent.kt similarity index 59% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/event/events/impl/LayoutInflateEvent.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/event/events/impl/LayoutInflateEvent.kt index 55c1283a..37341af3 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/event/events/impl/LayoutInflateEvent.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/event/events/impl/LayoutInflateEvent.kt @@ -1,8 +1,8 @@ -package me.rhunk.snapenhance.core.event.events.impl +package me.eternal.purrfectsnap.core.event.events.impl import android.view.View import android.view.ViewGroup -import me.rhunk.snapenhance.core.event.events.AbstractHookEvent +import me.eternal.purrfectsnap.core.event.events.AbstractHookEvent class LayoutInflateEvent( val layoutId: Int, diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/event/events/impl/MediaUploadEvent.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/event/events/impl/MediaUploadEvent.kt similarity index 62% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/event/events/impl/MediaUploadEvent.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/event/events/impl/MediaUploadEvent.kt index 29ba42e3..4efb5fb9 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/event/events/impl/MediaUploadEvent.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/event/events/impl/MediaUploadEvent.kt @@ -1,8 +1,8 @@ -package me.rhunk.snapenhance.core.event.events.impl +package me.eternal.purrfectsnap.core.event.events.impl -import me.rhunk.snapenhance.core.event.events.AbstractHookEvent -import me.rhunk.snapenhance.core.wrapper.impl.MessageContent -import me.rhunk.snapenhance.core.wrapper.impl.MessageDestinations +import me.eternal.purrfectsnap.core.event.events.AbstractHookEvent +import me.eternal.purrfectsnap.core.wrapper.impl.MessageContent +import me.eternal.purrfectsnap.core.wrapper.impl.MessageDestinations class MediaUploadEvent( val localMessageContent: MessageContent, diff --git a/core/src/main/kotlin/me/eternal/purrfectsnap/core/event/events/impl/NativeUnaryCallEvent.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/event/events/impl/NativeUnaryCallEvent.kt new file mode 100644 index 00000000..4a58ad03 --- /dev/null +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/event/events/impl/NativeUnaryCallEvent.kt @@ -0,0 +1,8 @@ +package me.eternal.purrfectsnap.core.event.events.impl + +import me.eternal.purrfectsnap.core.event.events.AbstractHookEvent + +class NativeUnaryCallEvent( + val uri: String, + var buffer: ByteArray +) : AbstractHookEvent() \ No newline at end of file diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/event/events/impl/NetworkApiRequestEvent.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/event/events/impl/NetworkApiRequestEvent.kt similarity index 92% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/event/events/impl/NetworkApiRequestEvent.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/event/events/impl/NetworkApiRequestEvent.kt index d19e018b..2bd865d1 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/event/events/impl/NetworkApiRequestEvent.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/event/events/impl/NetworkApiRequestEvent.kt @@ -1,9 +1,9 @@ -package me.rhunk.snapenhance.core.event.events.impl +package me.eternal.purrfectsnap.core.event.events.impl -import me.rhunk.snapenhance.core.event.events.AbstractHookEvent -import me.rhunk.snapenhance.core.util.hook.HookAdapter -import me.rhunk.snapenhance.core.util.hook.HookStage -import me.rhunk.snapenhance.core.util.hook.Hooker +import me.eternal.purrfectsnap.core.event.events.AbstractHookEvent +import me.eternal.purrfectsnap.core.util.hook.HookAdapter +import me.eternal.purrfectsnap.core.util.hook.HookStage +import me.eternal.purrfectsnap.core.util.hook.Hooker import java.nio.ByteBuffer class NetworkApiRequestEvent( diff --git a/core/src/main/kotlin/me/eternal/purrfectsnap/core/event/events/impl/OnSnapInteractionEvent.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/event/events/impl/OnSnapInteractionEvent.kt new file mode 100644 index 00000000..7fdf9696 --- /dev/null +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/event/events/impl/OnSnapInteractionEvent.kt @@ -0,0 +1,10 @@ +package me.eternal.purrfectsnap.core.event.events.impl + +import me.eternal.purrfectsnap.core.event.events.AbstractHookEvent +import me.eternal.purrfectsnap.core.wrapper.impl.SnapUUID + +class OnSnapInteractionEvent( + val interactionType: String, + val conversationId: SnapUUID, + val messageId: Long +) : AbstractHookEvent() \ No newline at end of file diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/event/events/impl/SendMessageWithContentEvent.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/event/events/impl/SendMessageWithContentEvent.kt similarity index 55% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/event/events/impl/SendMessageWithContentEvent.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/event/events/impl/SendMessageWithContentEvent.kt index 2b7f8e00..61135a4d 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/event/events/impl/SendMessageWithContentEvent.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/event/events/impl/SendMessageWithContentEvent.kt @@ -1,10 +1,10 @@ -package me.rhunk.snapenhance.core.event.events.impl +package me.eternal.purrfectsnap.core.event.events.impl -import me.rhunk.snapenhance.core.event.events.AbstractHookEvent -import me.rhunk.snapenhance.core.util.hook.HookStage -import me.rhunk.snapenhance.core.util.hook.Hooker -import me.rhunk.snapenhance.core.wrapper.impl.MessageContent -import me.rhunk.snapenhance.core.wrapper.impl.MessageDestinations +import me.eternal.purrfectsnap.core.event.events.AbstractHookEvent +import me.eternal.purrfectsnap.core.util.hook.HookStage +import me.eternal.purrfectsnap.core.util.hook.Hooker +import me.eternal.purrfectsnap.core.wrapper.impl.MessageContent +import me.eternal.purrfectsnap.core.wrapper.impl.MessageDestinations class SendMessageWithContentEvent( val destinations: MessageDestinations, diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/event/events/impl/SnapWidgetBroadcastReceiveEvent.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/event/events/impl/SnapWidgetBroadcastReceiveEvent.kt similarity index 62% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/event/events/impl/SnapWidgetBroadcastReceiveEvent.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/event/events/impl/SnapWidgetBroadcastReceiveEvent.kt index 737a18e3..2d833f28 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/event/events/impl/SnapWidgetBroadcastReceiveEvent.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/event/events/impl/SnapWidgetBroadcastReceiveEvent.kt @@ -1,8 +1,8 @@ -package me.rhunk.snapenhance.core.event.events.impl +package me.eternal.purrfectsnap.core.event.events.impl import android.content.Context import android.content.Intent -import me.rhunk.snapenhance.core.event.events.AbstractHookEvent +import me.eternal.purrfectsnap.core.event.events.AbstractHookEvent class SnapWidgetBroadcastReceiveEvent( val androidContext: Context, diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/event/events/impl/UnaryCallEvent.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/event/events/impl/UnaryCallEvent.kt similarity index 69% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/event/events/impl/UnaryCallEvent.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/event/events/impl/UnaryCallEvent.kt index 26245ed0..5eb431b8 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/event/events/impl/UnaryCallEvent.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/event/events/impl/UnaryCallEvent.kt @@ -1,6 +1,6 @@ -package me.rhunk.snapenhance.core.event.events.impl +package me.eternal.purrfectsnap.core.event.events.impl -import me.rhunk.snapenhance.core.event.events.AbstractHookEvent +import me.eternal.purrfectsnap.core.event.events.AbstractHookEvent class UnaryCallEvent( val uri: String, diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/BridgeFileFeature.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/BridgeFileFeature.kt similarity index 84% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/features/BridgeFileFeature.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/features/BridgeFileFeature.kt index cc6ce27a..09273abf 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/BridgeFileFeature.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/BridgeFileFeature.kt @@ -1,10 +1,10 @@ -package me.rhunk.snapenhance.core.features +package me.eternal.purrfectsnap.core.features -import me.rhunk.snapenhance.common.bridge.FileHandleScope -import me.rhunk.snapenhance.common.bridge.InternalFileHandleType -import me.rhunk.snapenhance.common.bridge.toWrapper -import me.rhunk.snapenhance.common.util.LazyBridgeValue -import me.rhunk.snapenhance.common.util.mappedLazyBridge +import me.eternal.purrfectsnap.common.bridge.FileHandleScope +import me.eternal.purrfectsnap.common.bridge.InternalFileHandleType +import me.eternal.purrfectsnap.common.bridge.toWrapper +import me.eternal.purrfectsnap.common.util.LazyBridgeValue +import me.eternal.purrfectsnap.common.util.mappedLazyBridge import java.io.BufferedReader import java.io.InputStreamReader import java.nio.charset.StandardCharsets diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/Feature.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/Feature.kt similarity index 91% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/features/Feature.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/features/Feature.kt index aa02cd1c..7a7de781 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/Feature.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/Feature.kt @@ -1,8 +1,8 @@ -package me.rhunk.snapenhance.core.features +package me.eternal.purrfectsnap.core.features import android.app.Activity import kotlinx.coroutines.launch -import me.rhunk.snapenhance.core.ModContext +import me.eternal.purrfectsnap.core.ModContext abstract class Feature( val key: String diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/FeatureLoadParams.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/FeatureLoadParams.kt similarity index 82% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/features/FeatureLoadParams.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/features/FeatureLoadParams.kt index e951de83..38cb6ee6 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/FeatureLoadParams.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/FeatureLoadParams.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.core.features +package me.eternal.purrfectsnap.core.features object FeatureLoadParams { const val NO_INIT = 0 diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/FeatureManager.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/FeatureManager.kt similarity index 82% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/features/FeatureManager.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/features/FeatureManager.kt index 8b0b088c..703e48ca 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/FeatureManager.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/FeatureManager.kt @@ -1,24 +1,24 @@ -package me.rhunk.snapenhance.core.features +package me.eternal.purrfectsnap.core.features import android.app.Activity import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import kotlinx.coroutines.runBlocking -import me.rhunk.snapenhance.core.ModContext -import me.rhunk.snapenhance.core.features.impl.* -import me.rhunk.snapenhance.core.features.impl.downloader.MediaDownloader -import me.rhunk.snapenhance.core.features.impl.downloader.ProfilePictureDownloader -import me.rhunk.snapenhance.core.features.impl.experiments.* -import me.rhunk.snapenhance.core.features.impl.global.* -import me.rhunk.snapenhance.core.features.impl.messaging.* -import me.rhunk.snapenhance.core.features.impl.spying.FriendTracker -import me.rhunk.snapenhance.core.features.impl.spying.HalfSwipeNotifier -import me.rhunk.snapenhance.core.features.impl.spying.MessageLogger -import me.rhunk.snapenhance.core.features.impl.spying.StealthMode -import me.rhunk.snapenhance.core.features.impl.tweaks.* -import me.rhunk.snapenhance.core.features.impl.ui.* -import me.rhunk.snapenhance.core.logger.CoreLogger -import me.rhunk.snapenhance.core.ui.menu.MenuViewInjector +import me.eternal.purrfectsnap.core.ModContext +import me.eternal.purrfectsnap.core.features.impl.* +import me.eternal.purrfectsnap.core.features.impl.downloader.MediaDownloader +import me.eternal.purrfectsnap.core.features.impl.downloader.ProfilePictureDownloader +import me.eternal.purrfectsnap.core.features.impl.experiments.* +import me.eternal.purrfectsnap.core.features.impl.global.* +import me.eternal.purrfectsnap.core.features.impl.messaging.* +import me.eternal.purrfectsnap.core.features.impl.spying.FriendTracker +import me.eternal.purrfectsnap.core.features.impl.spying.HalfSwipeNotifier +import me.eternal.purrfectsnap.core.features.impl.spying.MessageLogger +import me.eternal.purrfectsnap.core.features.impl.spying.StealthMode +import me.eternal.purrfectsnap.core.features.impl.tweaks.* +import me.eternal.purrfectsnap.core.features.impl.ui.* +import me.eternal.purrfectsnap.core.logger.CoreLogger +import me.eternal.purrfectsnap.core.ui.menu.MenuViewInjector import kotlin.reflect.KClass import kotlin.system.measureTimeMillis @@ -71,6 +71,7 @@ class FeatureManager( Messaging(), FriendMutationObserver(), AutoMarkAsRead(), + AutoRead(), MediaDownloader(), StealthMode(), MenuViewInjector(), @@ -78,10 +79,11 @@ class FeatureManager( ConvertMessageLocally(), SnapchatPlus(), DisableMetrics(), + EndpointsBlocker(), PreventMessageSending(), Notifications(), AutoSave(), - HideTypingIndicator(), + AutoReply(), UITweaks(), ConfigurationOverride(), COFOverride(), @@ -140,12 +142,15 @@ class FeatureManager( DisableTelecomFramework(), BetterTranscript(), VoiceNoteOverride(), + AutoDeleteSentMessages(), FriendNotes(), DoubleTapChatAction(), SnapScoreChanges(), DisableSnapModeRestrictions(), + MessageTranslator(), PreventForcedKeyboard(), CustomTheming(), + HideTypingIndicator(), ) features.values.toList().forEach { feature -> diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/MessagingRuleFeature.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/MessagingRuleFeature.kt similarity index 84% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/features/MessagingRuleFeature.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/features/MessagingRuleFeature.kt index 9b4ae5f0..bfb72516 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/MessagingRuleFeature.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/MessagingRuleFeature.kt @@ -1,7 +1,7 @@ -package me.rhunk.snapenhance.core.features +package me.eternal.purrfectsnap.core.features -import me.rhunk.snapenhance.common.data.MessagingRuleType -import me.rhunk.snapenhance.common.data.RuleState +import me.eternal.purrfectsnap.common.data.MessagingRuleType +import me.eternal.purrfectsnap.common.data.RuleState abstract class MessagingRuleFeature(name: String, val ruleType: MessagingRuleType) : Feature(name) { private val listeners = mutableListOf<(String, Boolean) -> Unit>() @@ -27,10 +27,11 @@ abstract class MessagingRuleFeature(name: String, val ruleType: MessagingRuleTyp ).contains(ruleType) && getRuleState() != null fun canUseRule(conversationId: String): Boolean { + if (getRuleState() == null) return false val state = getState(conversationId) if (context.config.rules.getRuleState(ruleType) == RuleState.BLACKLIST) { return !state } return state } -} \ No newline at end of file +} diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/COFOverride.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/COFOverride.kt similarity index 74% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/COFOverride.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/COFOverride.kt index 5f628109..03dc9add 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/COFOverride.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/COFOverride.kt @@ -1,12 +1,12 @@ -package me.rhunk.snapenhance.core.features.impl +package me.eternal.purrfectsnap.core.features.impl -import me.rhunk.snapenhance.core.features.Feature +import me.eternal.purrfectsnap.core.features.Feature -import me.rhunk.snapenhance.core.util.dataBuilder -import me.rhunk.snapenhance.core.util.hook.HookStage -import me.rhunk.snapenhance.core.util.hook.hook -import me.rhunk.snapenhance.core.util.ktx.getObjectField -import me.rhunk.snapenhance.mapper.impl.COFObservableMapper +import me.eternal.purrfectsnap.core.util.dataBuilder +import me.eternal.purrfectsnap.core.util.hook.HookStage +import me.eternal.purrfectsnap.core.util.hook.hook +import me.eternal.purrfectsnap.core.util.ktx.getObjectField +import me.eternal.purrfectsnap.mapper.impl.COFObservableMapper import java.lang.reflect.Method class COFOverride : Feature("COF Override") { diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/ConfigurationOverride.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/ConfigurationOverride.kt similarity index 94% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/ConfigurationOverride.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/ConfigurationOverride.kt index fbd501a9..cb507aa8 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/ConfigurationOverride.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/ConfigurationOverride.kt @@ -1,14 +1,14 @@ -package me.rhunk.snapenhance.core.features.impl +package me.eternal.purrfectsnap.core.features.impl import de.robv.android.xposed.XposedHelpers -import me.rhunk.snapenhance.core.features.Feature +import me.eternal.purrfectsnap.core.features.Feature -import me.rhunk.snapenhance.core.util.hook.HookStage -import me.rhunk.snapenhance.core.util.hook.Hooker -import me.rhunk.snapenhance.core.util.hook.hook -import me.rhunk.snapenhance.core.util.ktx.getObjectField -import me.rhunk.snapenhance.core.util.ktx.setObjectField -import me.rhunk.snapenhance.mapper.impl.CompositeConfigurationProviderMapper +import me.eternal.purrfectsnap.core.util.hook.HookStage +import me.eternal.purrfectsnap.core.util.hook.Hooker +import me.eternal.purrfectsnap.core.util.hook.hook +import me.eternal.purrfectsnap.core.util.ktx.getObjectField +import me.eternal.purrfectsnap.core.util.ktx.setObjectField +import me.eternal.purrfectsnap.mapper.impl.CompositeConfigurationProviderMapper data class ConfigKeyInfo( val category: String?, diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/Debug.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/Debug.kt similarity index 74% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/Debug.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/Debug.kt index ebc45aba..c2e715d5 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/Debug.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/Debug.kt @@ -1,8 +1,8 @@ -package me.rhunk.snapenhance.core.features.impl +package me.eternal.purrfectsnap.core.features.impl import android.widget.TextView -import me.rhunk.snapenhance.core.event.events.impl.AddViewEvent -import me.rhunk.snapenhance.core.features.Feature +import me.eternal.purrfectsnap.core.event.events.impl.AddViewEvent +import me.eternal.purrfectsnap.core.features.Feature class Debug : Feature("Debug") { override fun init() { diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/FriendMutationObserver.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/FriendMutationObserver.kt similarity index 95% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/FriendMutationObserver.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/FriendMutationObserver.kt index 9061cf76..efb4c4f4 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/FriendMutationObserver.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/FriendMutationObserver.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.core.features.impl +package me.eternal.purrfectsnap.core.features.impl import android.app.Notification import android.app.NotificationChannel @@ -6,12 +6,12 @@ import android.app.NotificationManager import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.WarningAmber import com.google.gson.JsonObject -import me.rhunk.snapenhance.common.data.FriendLinkType -import me.rhunk.snapenhance.common.database.impl.FriendInfo -import me.rhunk.snapenhance.core.event.events.impl.NetworkApiRequestEvent -import me.rhunk.snapenhance.core.features.Feature +import me.eternal.purrfectsnap.common.data.FriendLinkType +import me.eternal.purrfectsnap.common.database.impl.FriendInfo +import me.eternal.purrfectsnap.core.event.events.impl.NetworkApiRequestEvent +import me.eternal.purrfectsnap.core.features.Feature -import me.rhunk.snapenhance.core.util.EvictingMap +import me.eternal.purrfectsnap.core.util.EvictingMap import java.io.InputStreamReader import java.util.Calendar diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/MixerStories.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/MixerStories.kt similarity index 94% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/MixerStories.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/MixerStories.kt index 2c0fc868..1649089f 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/MixerStories.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/MixerStories.kt @@ -1,12 +1,12 @@ -package me.rhunk.snapenhance.core.features.impl +package me.eternal.purrfectsnap.core.features.impl import kotlinx.coroutines.launch import kotlinx.coroutines.runBlocking -import me.rhunk.snapenhance.common.data.MixerStoryType -import me.rhunk.snapenhance.common.data.StoryData -import me.rhunk.snapenhance.common.util.protobuf.ProtoEditor -import me.rhunk.snapenhance.core.event.events.impl.NetworkApiRequestEvent -import me.rhunk.snapenhance.core.features.Feature +import me.eternal.purrfectsnap.common.data.MixerStoryType +import me.eternal.purrfectsnap.common.data.StoryData +import me.eternal.purrfectsnap.common.util.protobuf.ProtoEditor +import me.eternal.purrfectsnap.core.event.events.impl.NetworkApiRequestEvent +import me.eternal.purrfectsnap.core.features.Feature import java.nio.ByteBuffer import kotlin.coroutines.suspendCoroutine diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/OperaViewerParamsOverride.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/OperaViewerParamsOverride.kt similarity index 90% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/OperaViewerParamsOverride.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/OperaViewerParamsOverride.kt index 6798a1a3..c0fadb44 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/OperaViewerParamsOverride.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/OperaViewerParamsOverride.kt @@ -1,10 +1,10 @@ -package me.rhunk.snapenhance.core.features.impl +package me.eternal.purrfectsnap.core.features.impl -import me.rhunk.snapenhance.core.features.Feature -import me.rhunk.snapenhance.core.util.hook.HookStage -import me.rhunk.snapenhance.core.util.hook.hookConstructor -import me.rhunk.snapenhance.core.wrapper.impl.media.opera.ParamMap -import me.rhunk.snapenhance.mapper.impl.OperaViewerParamsMapper +import me.eternal.purrfectsnap.core.features.Feature +import me.eternal.purrfectsnap.core.util.hook.HookStage +import me.eternal.purrfectsnap.core.util.hook.hookConstructor +import me.eternal.purrfectsnap.core.wrapper.impl.media.opera.ParamMap +import me.eternal.purrfectsnap.mapper.impl.OperaViewerParamsMapper import java.util.concurrent.ConcurrentHashMap class OperaViewerParamsOverride : Feature("OperaViewerParamsOverride") { diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/ScopeSync.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/ScopeSync.kt similarity index 81% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/ScopeSync.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/ScopeSync.kt index 7a8ec6fa..c2c3c83b 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/ScopeSync.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/ScopeSync.kt @@ -1,12 +1,12 @@ -package me.rhunk.snapenhance.core.features.impl +package me.eternal.purrfectsnap.core.features.impl import kotlinx.coroutines.Job import kotlinx.coroutines.delay import kotlinx.coroutines.launch -import me.rhunk.snapenhance.common.data.ContentType -import me.rhunk.snapenhance.common.data.SocialScope -import me.rhunk.snapenhance.core.event.events.impl.SendMessageWithContentEvent -import me.rhunk.snapenhance.core.features.Feature +import me.eternal.purrfectsnap.common.data.ContentType +import me.eternal.purrfectsnap.common.data.SocialScope +import me.eternal.purrfectsnap.core.event.events.impl.SendMessageWithContentEvent +import me.eternal.purrfectsnap.core.features.Feature class ScopeSync : Feature("Scope Sync") { companion object { diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/downloader/MediaDownloader.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/downloader/MediaDownloader.kt similarity index 93% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/downloader/MediaDownloader.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/downloader/MediaDownloader.kt index 8361ca92..f5a4a816 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/downloader/MediaDownloader.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/downloader/MediaDownloader.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.core.features.impl.downloader +package me.eternal.purrfectsnap.core.features.impl.downloader import android.annotation.SuppressLint import android.graphics.Bitmap @@ -14,39 +14,39 @@ import androidx.compose.material.icons.Icons import androidx.compose.material.icons.outlined.* import kotlinx.coroutines.launch import kotlinx.coroutines.runBlocking -import me.rhunk.snapenhance.bridge.DownloadCallback -import me.rhunk.snapenhance.common.data.FileType -import me.rhunk.snapenhance.common.data.MessagingRuleType -import me.rhunk.snapenhance.common.data.download.* -import me.rhunk.snapenhance.common.database.impl.ConversationMessage -import me.rhunk.snapenhance.common.database.impl.FriendInfo -import me.rhunk.snapenhance.common.util.ktx.copyToClipboard -import me.rhunk.snapenhance.common.util.ktx.longHashCode -import me.rhunk.snapenhance.common.util.protobuf.ProtoReader -import me.rhunk.snapenhance.common.util.snap.BitmojiSelfie -import me.rhunk.snapenhance.common.util.snap.MediaDownloaderHelper -import me.rhunk.snapenhance.common.util.snap.RemoteMediaResolver -import me.rhunk.snapenhance.core.DownloadManagerClient -import me.rhunk.snapenhance.core.SnapEnhance -import me.rhunk.snapenhance.core.features.MessagingRuleFeature -import me.rhunk.snapenhance.core.features.impl.downloader.decoder.DecodedAttachment -import me.rhunk.snapenhance.core.features.impl.downloader.decoder.MessageDecoder -import me.rhunk.snapenhance.core.features.impl.messaging.Messaging -import me.rhunk.snapenhance.core.features.impl.spying.MessageLogger -import me.rhunk.snapenhance.core.ui.ViewAppearanceHelper -import me.rhunk.snapenhance.core.ui.debugEditText -import me.rhunk.snapenhance.core.util.hook.HookStage -import me.rhunk.snapenhance.core.util.hook.hook -import me.rhunk.snapenhance.core.util.ktx.getObjectField -import me.rhunk.snapenhance.core.util.media.PreviewUtils -import me.rhunk.snapenhance.core.wrapper.impl.SnapUUID -import me.rhunk.snapenhance.core.wrapper.impl.media.MediaInfo -import me.rhunk.snapenhance.core.wrapper.impl.media.dash.LongformVideoPlaylistItem -import me.rhunk.snapenhance.core.wrapper.impl.media.dash.SnapPlaylistItem -import me.rhunk.snapenhance.core.wrapper.impl.media.opera.Layer -import me.rhunk.snapenhance.core.wrapper.impl.media.opera.ParamMap -import me.rhunk.snapenhance.core.wrapper.impl.media.toKeyPair -import me.rhunk.snapenhance.mapper.impl.OperaPageViewControllerMapper +import me.eternal.purrfectsnap.bridge.DownloadCallback +import me.eternal.purrfectsnap.common.data.FileType +import me.eternal.purrfectsnap.common.data.MessagingRuleType +import me.eternal.purrfectsnap.common.data.download.* +import me.eternal.purrfectsnap.common.database.impl.ConversationMessage +import me.eternal.purrfectsnap.common.database.impl.FriendInfo +import me.eternal.purrfectsnap.common.util.ktx.copyToClipboard +import me.eternal.purrfectsnap.common.util.ktx.longHashCode +import me.eternal.purrfectsnap.common.util.protobuf.ProtoReader +import me.eternal.purrfectsnap.common.util.snap.BitmojiSelfie +import me.eternal.purrfectsnap.common.util.snap.MediaDownloaderHelper +import me.eternal.purrfectsnap.common.util.snap.RemoteMediaResolver +import me.eternal.purrfectsnap.core.DownloadManagerClient +import me.eternal.purrfectsnap.core.PurrfectSnap +import me.eternal.purrfectsnap.core.features.MessagingRuleFeature +import me.eternal.purrfectsnap.core.features.impl.downloader.decoder.DecodedAttachment +import me.eternal.purrfectsnap.core.features.impl.downloader.decoder.MessageDecoder +import me.eternal.purrfectsnap.core.features.impl.messaging.Messaging +import me.eternal.purrfectsnap.core.features.impl.spying.MessageLogger +import me.eternal.purrfectsnap.core.ui.ViewAppearanceHelper +import me.eternal.purrfectsnap.core.ui.debugEditText +import me.eternal.purrfectsnap.core.util.hook.HookStage +import me.eternal.purrfectsnap.core.util.hook.hook +import me.eternal.purrfectsnap.core.util.ktx.getObjectField +import me.eternal.purrfectsnap.core.util.media.PreviewUtils +import me.eternal.purrfectsnap.core.wrapper.impl.SnapUUID +import me.eternal.purrfectsnap.core.wrapper.impl.media.MediaInfo +import me.eternal.purrfectsnap.core.wrapper.impl.media.dash.LongformVideoPlaylistItem +import me.eternal.purrfectsnap.core.wrapper.impl.media.dash.SnapPlaylistItem +import me.eternal.purrfectsnap.core.wrapper.impl.media.opera.Layer +import me.eternal.purrfectsnap.core.wrapper.impl.media.opera.ParamMap +import me.eternal.purrfectsnap.core.wrapper.impl.media.toKeyPair +import me.eternal.purrfectsnap.mapper.impl.OperaPageViewControllerMapper import java.nio.file.Paths import java.util.UUID import kotlin.coroutines.suspendCoroutine @@ -171,7 +171,7 @@ class MediaDownloader : MessagingRuleFeature("MediaDownloader", MessagingRuleTyp context.runOnUiThread { val mediaInfoText = lastSeenMapParams?.concurrentHashMap?.map { (key, value) -> val transformedValue = value.let { - if (it::class.java == SnapEnhance.classCache.snapUUID) { + if (it::class.java == PurrfectSnap.classCache.snapUUID) { SnapUUID(it).toString() } it @@ -499,6 +499,7 @@ class MediaDownloader : MessagingRuleFeature("MediaDownloader", MessagingRuleTyp } override fun init() { + if (getRuleState() == null) return onNextActivityCreate { context.mappings.useMapper(OperaPageViewControllerMapper::class) { arrayOf(onDisplayStateChange, onDisplayStateChangeGesture).forEach { methodName -> diff --git a/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/downloader/ProfilePictureDownloader.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/downloader/ProfilePictureDownloader.kt new file mode 100644 index 00000000..521089e3 --- /dev/null +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/downloader/ProfilePictureDownloader.kt @@ -0,0 +1,223 @@ +package me.eternal.purrfectsnap.core.features.impl.downloader + +import android.annotation.SuppressLint +import android.graphics.Color +import android.graphics.drawable.GradientDrawable +import android.widget.ImageButton +import android.widget.ImageView +import android.widget.RelativeLayout +import androidx.compose.foundation.BorderStroke +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.outlined.AccountCircle +import androidx.compose.material.icons.outlined.Download +import androidx.compose.material.icons.outlined.Image +import androidx.compose.material3.Icon +import androidx.compose.material3.Surface +import androidx.compose.material3.Text +import androidx.compose.runtime.remember +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Brush +import androidx.compose.ui.graphics.Color as ComposeColor +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import me.eternal.purrfectsnap.common.util.protobuf.ProtoReader +import me.eternal.purrfectsnap.common.ui.createComposeAlertDialog +import me.eternal.purrfectsnap.core.event.events.impl.AddViewEvent +import me.eternal.purrfectsnap.core.event.events.impl.NetworkApiRequestEvent +import me.eternal.purrfectsnap.core.features.Feature +import me.eternal.purrfectsnap.core.ui.PurrfectGlassCard +import me.eternal.purrfectsnap.core.ui.PurrfectOverlayPalette +import me.eternal.purrfectsnap.core.ui.PurrfectOverlayTheme + +class ProfilePictureDownloader : Feature("ProfilePictureDownloader") { + @SuppressLint("SetTextI18n") + override fun init() { + if (!context.config.downloader.downloadProfilePictures.get()) return + + var friendUsername: String? = null + var backgroundUrl: String? = null + var avatarUrl: String? = null + + onNextActivityCreate(defer = true) { + context.event.subscribe(AddViewEvent::class) { event -> + if (event.view::class.java.name != "com.snap.unifiedpublicprofile.UnifiedPublicProfileView") return@subscribe + + event.parent.addView(ImageButton(event.parent.context).apply { + val label = this@ProfilePictureDownloader.context.translation["profile_picture_downloader.button"] + val density = resources.displayMetrics.density + val sizePx = (44f * density).toInt() + contentDescription = label + setImageResource(android.R.drawable.stat_sys_download) + setColorFilter(Color.WHITE) + scaleType = ImageView.ScaleType.CENTER_INSIDE + background = GradientDrawable().apply { + shape = GradientDrawable.OVAL + setColor(Color.parseColor("#332A2452")) + setStroke(3, Color.parseColor("#66AFA3FF")) + } + setPadding(0, 0, 0, 0) + layoutParams = RelativeLayout.LayoutParams( + sizePx, + sizePx + ).apply { + setMargins(0, 200, 0, 0) + } + setOnClickListener { + val activity = this@ProfilePictureDownloader.context.mainActivity ?: return@setOnClickListener + val translation = this@ProfilePictureDownloader.context.translation + val options = buildList { + backgroundUrl?.let { add("background_option" to it) } + avatarUrl?.let { add("avatar_option" to it) } + } + createComposeAlertDialog(activity) { alertDialog -> + PurrfectOverlayTheme { + val dialogTitle = translation["profile_picture_downloader.title"] + ?: "Profile Picture Downloader" + val subtitle = friendUsername ?: translation["profile_picture_downloader.subtitle"] + ?: "Choose which image to download" + val border = remember { + Brush.linearGradient( + listOf( + PurrfectOverlayPalette.glowPrimary.copy(alpha = 0.55f), + PurrfectOverlayPalette.glowSecondary.copy(alpha = 0.35f) + ) + ) + } + val shape = RoundedCornerShape(26.dp) + Surface( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 18.dp), + shape = shape, + color = ComposeColor.Transparent, + tonalElevation = 0.dp, + shadowElevation = 18.dp, + border = BorderStroke(1.dp, border) + ) { + Column( + modifier = Modifier + .background(PurrfectOverlayPalette.cardOverlay, shape) + .padding(horizontal = 18.dp, vertical = 16.dp), + verticalArrangement = Arrangement.spacedBy(12.dp) + ) { + Row( + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(12.dp) + ) { + Surface( + shape = RoundedCornerShape(14.dp), + color = ComposeColor.White.copy(alpha = 0.08f) + ) { + Icon( + Icons.Outlined.Download, + contentDescription = null, + tint = ComposeColor.White, + modifier = Modifier.padding(8.dp) + ) + } + Column { + Text( + text = dialogTitle, + color = ComposeColor.White, + fontSize = 18.sp, + fontWeight = FontWeight.ExtraBold + ) + Text( + text = subtitle, + color = PurrfectOverlayPalette.textSecondary, + fontSize = 12.sp + ) + } + } + if (options.isEmpty()) { + Text( + text = translation["profile_picture_downloader.no_images"] + ?: "No profile images found.", + color = ComposeColor.White.copy(alpha = 0.8f), + fontSize = 13.sp + ) + } else { + options.forEach { (key, url) -> + val labelText = translation["profile_picture_downloader.$key"] + val icon = if (key == "background_option") { + Icons.Outlined.Image + } else { + Icons.Outlined.AccountCircle + } + Surface( + onClick = { + runCatching { + this@ProfilePictureDownloader.context.feature(MediaDownloader::class).downloadProfilePicture( + url, + friendUsername!! + ) + }.onFailure { + this@ProfilePictureDownloader.context.log.error("Failed to download profile picture", it) + } + alertDialog.dismiss() + }, + shape = RoundedCornerShape(16.dp), + color = ComposeColor.White.copy(alpha = 0.05f), + border = BorderStroke(1.dp, ComposeColor.White.copy(alpha = 0.12f)) + ) { + Row( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 14.dp, vertical = 12.dp), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(10.dp) + ) { + Surface( + shape = RoundedCornerShape(12.dp), + color = ComposeColor.White.copy(alpha = 0.08f) + ) { + Icon( + icon, + contentDescription = null, + tint = ComposeColor.White, + modifier = Modifier.padding(8.dp) + ) + } + Text( + text = labelText ?: key, + color = ComposeColor.White, + fontWeight = FontWeight.SemiBold, + fontSize = 14.sp + ) + } + } + } + } + } + } + } + }.show() + } + }) + } + + + context.event.subscribe(NetworkApiRequestEvent::class) { event -> + if (!event.url.endsWith("/rpc/getPublicProfile")) return@subscribe + event.onSuccess { buffer -> + ProtoReader(buffer ?: return@onSuccess).followPath(1, 1, 2) { + friendUsername = getString(2) ?: return@followPath + followPath(4) { + backgroundUrl = getString(2) + avatarUrl = getString(100) + } + } + } + } + } + } +} diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/downloader/decoder/AttachmentInfo.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/downloader/decoder/AttachmentInfo.kt similarity index 70% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/downloader/decoder/AttachmentInfo.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/downloader/decoder/AttachmentInfo.kt index 96b30c5b..39ea3a44 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/downloader/decoder/AttachmentInfo.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/downloader/decoder/AttachmentInfo.kt @@ -1,6 +1,6 @@ -package me.rhunk.snapenhance.core.features.impl.downloader.decoder +package me.eternal.purrfectsnap.core.features.impl.downloader.decoder -import me.rhunk.snapenhance.common.data.download.MediaEncryptionKeyPair +import me.eternal.purrfectsnap.common.data.download.MediaEncryptionKeyPair data class BitmojiSticker( val reference: String, diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/downloader/decoder/AttachmentType.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/downloader/decoder/AttachmentType.kt similarity index 74% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/downloader/decoder/AttachmentType.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/downloader/decoder/AttachmentType.kt index 5391ad99..9395cfae 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/downloader/decoder/AttachmentType.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/downloader/decoder/AttachmentType.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.core.features.impl.downloader.decoder +package me.eternal.purrfectsnap.core.features.impl.downloader.decoder enum class AttachmentType( val key: String, diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/downloader/decoder/MessageDecoder.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/downloader/decoder/MessageDecoder.kt similarity index 95% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/downloader/decoder/MessageDecoder.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/downloader/decoder/MessageDecoder.kt index 41b1b7ef..8d213e34 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/downloader/decoder/MessageDecoder.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/downloader/decoder/MessageDecoder.kt @@ -1,15 +1,15 @@ -package me.rhunk.snapenhance.core.features.impl.downloader.decoder +package me.eternal.purrfectsnap.core.features.impl.downloader.decoder import com.google.gson.GsonBuilder import com.google.gson.JsonElement import com.google.gson.JsonObject -import me.rhunk.snapenhance.common.data.download.DownloadMediaType -import me.rhunk.snapenhance.common.data.download.InputMedia -import me.rhunk.snapenhance.common.data.download.MediaEncryptionKeyPair -import me.rhunk.snapenhance.common.data.download.toKeyPair -import me.rhunk.snapenhance.common.util.protobuf.ProtoReader -import me.rhunk.snapenhance.common.util.snap.RemoteMediaResolver -import me.rhunk.snapenhance.core.wrapper.impl.MessageContent +import me.eternal.purrfectsnap.common.data.download.DownloadMediaType +import me.eternal.purrfectsnap.common.data.download.InputMedia +import me.eternal.purrfectsnap.common.data.download.MediaEncryptionKeyPair +import me.eternal.purrfectsnap.common.data.download.toKeyPair +import me.eternal.purrfectsnap.common.util.protobuf.ProtoReader +import me.eternal.purrfectsnap.common.util.snap.RemoteMediaResolver +import me.eternal.purrfectsnap.core.wrapper.impl.MessageContent import java.io.InputStream import java.net.URL import kotlin.io.encoding.Base64 diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/experiments/AccountSwitcher.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/experiments/AccountSwitcher.kt similarity index 77% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/experiments/AccountSwitcher.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/experiments/AccountSwitcher.kt index 9bc3a7b0..75c460b9 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/experiments/AccountSwitcher.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/experiments/AccountSwitcher.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.core.features.impl.experiments +package me.eternal.purrfectsnap.core.features.impl.experiments import android.annotation.SuppressLint import android.app.Activity @@ -6,35 +6,41 @@ import android.content.Intent import android.database.sqlite.SQLiteDatabase import android.net.Uri import android.os.ParcelFileDescriptor +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.* +import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Delete import androidx.compose.material.icons.filled.SaveAlt +import androidx.compose.material.icons.filled.AccountCircle import androidx.compose.material3.* import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.Color import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import kotlinx.coroutines.withContext -import me.rhunk.snapenhance.common.data.FileType -import me.rhunk.snapenhance.common.ui.AppMaterialTheme -import me.rhunk.snapenhance.common.ui.createComposeAlertDialog -import me.rhunk.snapenhance.common.util.ktx.toParcelFileDescriptor -import me.rhunk.snapenhance.common.util.snap.MediaDownloaderHelper -import me.rhunk.snapenhance.core.event.events.impl.ActivityResultEvent -import me.rhunk.snapenhance.core.event.events.impl.AddViewEvent -import me.rhunk.snapenhance.core.features.Feature -import me.rhunk.snapenhance.core.ui.CustomComposable -import me.rhunk.snapenhance.core.util.hook.HookStage -import me.rhunk.snapenhance.core.util.hook.hook -import me.rhunk.snapenhance.core.util.ktx.getId -import me.rhunk.snapenhance.core.util.ktx.vibrateLongPress +import me.eternal.purrfectsnap.common.data.FileType +import me.eternal.purrfectsnap.common.ui.AppMaterialTheme +import me.eternal.purrfectsnap.common.ui.createComposeAlertDialog +import me.eternal.purrfectsnap.common.util.ktx.toParcelFileDescriptor +import me.eternal.purrfectsnap.common.util.snap.MediaDownloaderHelper +import me.eternal.purrfectsnap.core.event.events.impl.ActivityResultEvent +import me.eternal.purrfectsnap.core.event.events.impl.AddViewEvent +import me.eternal.purrfectsnap.core.features.Feature +import me.eternal.purrfectsnap.core.ui.CustomComposable +import me.eternal.purrfectsnap.core.util.hook.HookStage +import me.eternal.purrfectsnap.core.util.hook.hook +import me.eternal.purrfectsnap.core.util.ktx.getId +import me.eternal.purrfectsnap.core.util.ktx.vibrateLongPress import java.io.File import java.util.zip.ZipEntry import java.util.zip.ZipInputStream @@ -266,25 +272,48 @@ class AccountSwitcher: Feature("Account Switcher") { return } + val dataDir = context.androidContext.dataDir arrayOf( context.androidContext.filesDir, context.androidContext.cacheDir, - context.androidContext.dataDir.resolve("databases"), - ).forEach { dir -> dir.listFiles()?.forEach { it.deleteRecursively() } } + dataDir.resolve("databases"), + dataDir.resolve("shared_prefs"), + ).forEach { dir -> + runCatching { + if (dir.exists() && dir.isDirectory) { + dir.listFiles()?.forEach { it.deleteRecursively() } + } + }.onFailure { + context.log.verbose("Failed to clean directory $dir: ${it.message}") + } + } - val zipInputStream = ZipInputStream(accountData.inputStream()) - var entry: ZipEntry? - while (zipInputStream.nextEntry.also { entry = it } != null) { - val file = context.androidContext.dataDir.resolve(entry!!.name) - if (file.exists()) { - file.delete() - } else { - file.parentFile?.mkdirs() - } - context.log.debug("Extracting ${file.absolutePath}") - file.outputStream().use { - zipInputStream.copyTo(it) + try { + val zipInputStream = ZipInputStream(accountData.inputStream()) + var entry: ZipEntry? + while (zipInputStream.nextEntry.also { entry = it } != null) { + runCatching { + val entryName = entry!!.name + val file = dataDir.resolve(entryName) + + if (file.exists()) { + file.delete() + } else { + file.parentFile?.mkdirs() + } + context.log.debug("Extracting ${file.absolutePath}") + file.outputStream().buffered().use { + zipInputStream.copyTo(it, bufferSize = 8192) + } + }.onFailure { + context.log.verbose("Failed to extract ${entry!!.name}: ${it.message}") + } } + zipInputStream.close() + } catch (e: Exception) { + context.log.error("Failed to restore account data", e) + context.shortToast("Failed to restore account data") + return } context.log.debug("Account data restored") @@ -296,42 +325,59 @@ class AccountSwitcher: Feature("Account Switcher") { val pfd = ParcelFileDescriptor.createPipe() context.coroutineScope.launch(Dispatchers.IO) { - val zipOutputStream = ZipOutputStream(ParcelFileDescriptor.AutoCloseOutputStream(pfd[1])) + var zipOutputStream: ZipOutputStream? = null + try { + zipOutputStream = ZipOutputStream(ParcelFileDescriptor.AutoCloseOutputStream(pfd[1])) + val dataDir = context.androidContext.dataDir + val maxFileSize = 5 * 1024 * 1024 - fun addFile(path: String, file: File) { - file.takeIf { it.exists() }?.inputStream()?.use { - context.log.verbose("Adding $file to zip") - zipOutputStream.putNextEntry(ZipEntry(path)) - it.copyTo(zipOutputStream) - zipOutputStream.closeEntry() + fun addFile(path: String, file: File): Boolean { + return try { + if (!file.exists() || !file.isFile || !file.canRead()) return false + val fileSize = file.length() + if (fileSize > maxFileSize || fileSize == 0L) return false + file.inputStream().buffered().use { input -> + zipOutputStream!!.putNextEntry(ZipEntry(path)) + input.copyTo(zipOutputStream!!, bufferSize = 8192) + zipOutputStream!!.closeEntry() + } + true + } catch (e: Exception) { + context.log.verbose("Failed to add file $file: ${e.message}") + false + } } - } - for (path in arrayOf( - "databases/main.db", - "databases/main.db-shm", - "databases/main.db-wal", - "databases/core.db", - "databases/core.db-wal", - "databases/core.db-shm", - "databases/fidelius_database.db", - "databases/fidelius_database.db-wal", - "databases/fidelius_database.db-shm", - "shared_prefs/user_session_shared_pref.xml", - "shared_prefs/user_device_identity_keys.xml", - "shared_prefs/com.google.android.gms.appid.xml", - )) { - addFile(path, context.androidContext.dataDir.resolve(path)) - } + val databasesDir = dataDir.resolve("databases") + if (databasesDir.exists() && databasesDir.isDirectory) { + databasesDir.listFiles()?.forEach { file -> + if (file.isFile && file.name.endsWith(".db") && !file.name.endsWith(".db-wal") && !file.name.endsWith(".db-shm")) { + addFile("databases/${file.name}", file) + } + } + } - context.androidContext.dataDir.resolve("databases").listFiles()?.filter { - it.name.contains("_fidelius.db") - }?.forEach { - addFile("databases/${it.name}", it) - } + val sharedPrefsDir = dataDir.resolve("shared_prefs") + if (sharedPrefsDir.exists() && sharedPrefsDir.isDirectory) { + sharedPrefsDir.listFiles()?.forEach { file -> + if (file.isFile && file.name.endsWith(".xml") && file.canRead()) { + addFile("shared_prefs/${file.name}", file) + } + } + } - zipOutputStream.flush() - zipOutputStream.close() + zipOutputStream.flush() + zipOutputStream.close() + zipOutputStream = null + } catch (e: Exception) { + context.log.error("Backup failed", e) + try { + zipOutputStream?.close() + } catch (_: Exception) {} + try { + pfd[1].close() + } catch (_: Exception) {} + } } return pfd[0] @@ -512,11 +558,19 @@ class AccountSwitcher: Feature("Account Switcher") { .fillMaxWidth() .align(Alignment.TopStart), ) { - Button( - onClick = { showManagementPopup() }, - modifier = Modifier.padding(16.dp) + Box( + modifier = Modifier + .padding(16.dp) + .size(45.dp) + .clip(CircleShape) + .background(Color.White) + .clickable { showManagementPopup() } ) { - Text("Switch Account") + Icon( + Icons.Default.AccountCircle, + contentDescription = "Switch Account", + modifier = Modifier.size(45.dp) + ) } } } @@ -529,4 +583,4 @@ class AccountSwitcher: Feature("Account Switcher") { } } } -} \ No newline at end of file +} diff --git a/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/experiments/AddFriendSourceSpoof.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/experiments/AddFriendSourceSpoof.kt new file mode 100644 index 00000000..9edbb3a1 --- /dev/null +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/experiments/AddFriendSourceSpoof.kt @@ -0,0 +1,74 @@ +package me.eternal.purrfectsnap.core.features.impl.experiments + +import me.eternal.purrfectsnap.common.data.FriendAddSource +import me.eternal.purrfectsnap.common.util.protobuf.ProtoEditor +import me.eternal.purrfectsnap.common.util.protobuf.ProtoReader +import me.eternal.purrfectsnap.core.event.events.impl.UnaryCallEvent +import me.eternal.purrfectsnap.core.features.Feature +import me.eternal.purrfectsnap.core.util.hook.HookStage +import me.eternal.purrfectsnap.core.util.hook.hookConstructor +import me.eternal.purrfectsnap.mapper.impl.FriendRelationshipChangerMapper + +class AddFriendSourceSpoof : Feature("AddFriendSourceSpoof") { + var friendRelationshipChangerInstance: Any? = null + private set + + override fun init() { + onNextActivityCreate { + context.mappings.useMapper(FriendRelationshipChangerMapper::class) { + classReference.get()?.hookConstructor(HookStage.AFTER) { param -> + friendRelationshipChangerInstance = param.thisObject() + } + } + + context.event.subscribe(UnaryCallEvent::class) { event -> + if (event.uri != "/snapchat.friending.server.FriendAction/AddFriends") return@subscribe + val spoofedSource = context.config.experimental.addFriendSourceSpoof.getNullable() ?: return@subscribe + + event.buffer = ProtoEditor(event.buffer).apply { + edit { + fun setPage(value: String) { + remove(1) + addString(1, value) + } + + fun setSource(source: FriendAddSource) { + val field2Exists = getOrNull(2) != null + + if (field2Exists) { + editEach(2) { + val field1Data = getOrNull(1) + clear() + if (field1Data != null) { + field1Data.forEach { wire -> + addWire(wire) + } + } + addVarInt(2, source.id) + } + } else { + add(2) { addVarInt(2, source.id) } + } + } + + val mapping: Map> = mapOf( + "added_by_group_chat" to Pair("group_profile", FriendAddSource.GROUP_CHAT), + "added_by_username" to Pair("search", FriendAddSource.USERNAME), + "added_by_qr_code" to Pair("scan_snapcode", FriendAddSource.QR_CODE), + "added_by_mention" to Pair("context_card", FriendAddSource.MENTION), + "added_by_community" to Pair("profile", FriendAddSource.COMMUNITY), + "added_by_quick_add" to Pair("add_friends_button_on_top_bar_on_friends_feed", FriendAddSource.SUGGESTED), + "added_by_spotlight" to Pair("spotlight", FriendAddSource.SPOTLIGHT), + ) + mapping[spoofedSource]?.let { (page, source) -> + page?.let { setPage(it) } + setSource(source) + } + + remove(3) + } + }.toByteArray() + } + } + } +} diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/experiments/AppLock.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/experiments/AppLock.kt similarity index 89% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/experiments/AppLock.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/experiments/AppLock.kt index 74b83638..d1eb8d4b 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/experiments/AppLock.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/experiments/AppLock.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.core.features.impl.experiments +package me.eternal.purrfectsnap.core.features.impl.experiments import android.app.Activity import android.content.ComponentName @@ -26,16 +26,16 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.ColorFilter import androidx.compose.ui.unit.dp -import me.rhunk.snapenhance.common.Constants -import me.rhunk.snapenhance.common.ui.AppMaterialTheme -import me.rhunk.snapenhance.common.ui.createComposeView -import me.rhunk.snapenhance.core.event.events.impl.ActivityResultEvent -import me.rhunk.snapenhance.core.features.Feature -import me.rhunk.snapenhance.core.ui.addForegroundDrawable -import me.rhunk.snapenhance.core.ui.children -import me.rhunk.snapenhance.core.ui.removeForegroundDrawable -import me.rhunk.snapenhance.core.util.hook.HookStage -import me.rhunk.snapenhance.core.util.hook.hook +import me.eternal.purrfectsnap.common.Constants +import me.eternal.purrfectsnap.common.ui.AppMaterialTheme +import me.eternal.purrfectsnap.common.ui.createComposeView +import me.eternal.purrfectsnap.core.event.events.impl.ActivityResultEvent +import me.eternal.purrfectsnap.core.features.Feature +import me.eternal.purrfectsnap.core.ui.addForegroundDrawable +import me.eternal.purrfectsnap.core.ui.children +import me.eternal.purrfectsnap.core.ui.removeForegroundDrawable +import me.eternal.purrfectsnap.core.util.hook.HookStage +import me.eternal.purrfectsnap.core.util.hook.hook import kotlin.random.Random class AppLock : Feature("AppLock") { @@ -56,7 +56,7 @@ class AppLock : Feature("AppLock") { private fun requestUnlock() { isUnlockRequested = true context.mainActivity!!.startActivityForResult(Intent().apply { - component = ComponentName(Constants.SE_PACKAGE_NAME, "me.rhunk.snapenhance.bridge.BiometricPromptActivity") + component = ComponentName(Constants.SE_PACKAGE_NAME, "me.eternal.purrfectsnap.bridge.BiometricPromptActivity") }, requestCode) } diff --git a/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/experiments/AutoOpenSnaps.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/experiments/AutoOpenSnaps.kt new file mode 100644 index 00000000..23ff6bc3 --- /dev/null +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/experiments/AutoOpenSnaps.kt @@ -0,0 +1,662 @@ +package me.eternal.purrfectsnap.core.features.impl.experiments + +import android.app.Notification +import android.app.NotificationChannel +import android.app.NotificationManager +import android.app.PendingIntent +import android.content.BroadcastReceiver +import android.content.Context +import android.content.Intent +import android.content.IntentFilter +import android.os.Build +import kotlinx.coroutines.CoroutineStart +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.delay +import kotlinx.coroutines.flow.MutableSharedFlow +import kotlinx.coroutines.launch +import me.eternal.purrfectsnap.common.data.ContentType +import me.eternal.purrfectsnap.common.data.MessageUpdate +import me.eternal.purrfectsnap.common.data.MessagingRuleType +import me.eternal.purrfectsnap.core.event.events.impl.BuildMessageEvent +import me.eternal.purrfectsnap.core.features.MessagingRuleFeature +import me.eternal.purrfectsnap.core.features.impl.messaging.Messaging +import me.eternal.purrfectsnap.core.util.hook.HookStage +import me.eternal.purrfectsnap.core.util.hook.hook +import me.eternal.purrfectsnap.core.util.hook.hookConstructor +import java.util.concurrent.atomic.AtomicInteger +import java.util.concurrent.atomic.AtomicBoolean +import java.util.concurrent.atomic.AtomicLong +import kotlin.coroutines.resume +import kotlin.coroutines.suspendCoroutine +import kotlin.random.Random + +class AutoOpenSnaps: MessagingRuleFeature("Auto Open Snaps", MessagingRuleType.AUTO_OPEN_SNAPS) { + companion object { + const val ACTION_PAUSE_RESUME = "me.eternal.purrfectsnap.AUTO_OPEN_SNAPS_PAUSE_RESUME" + const val ACTION_CLEAR_QUEUE = "me.eternal.purrfectsnap.AUTO_OPEN_SNAPS_CLEAR_QUEUE" + } + + data class SnapQueueItem( + val conversationId: String, + val messageId: Long, + val senderInfo: String, + val conversationType: String, + val contentType: String, + val timestamp: Long = System.currentTimeMillis() + ) + + private val snapQueue = MutableSharedFlow() + private var snapQueueSize = AtomicInteger(0) + private val openedSnaps = mutableListOf() + private val isPaused = AtomicBoolean(false) + private val queuedSnaps = mutableListOf() + private var totalProcessed = AtomicInteger(0) + + private var sessionStartTime = System.currentTimeMillis() + private var lastResetTime = System.currentTimeMillis() + + private var currentBatchSize = AtomicInteger(0) + private var currentBatchProcessed = AtomicInteger(0) + + private val config by lazy { context.config.messaging.autoOpenSnaps } + + private val notificationManager by lazy { + context.androidContext.getSystemService(NotificationManager::class.java) + } + private val statusNotificationId by lazy { Random.nextInt() } + + private val baseChannelId = "auto_open_snaps" + private val priorityChannelId = "auto_open_snaps_priority" + + private var lastNotificationUpdate = AtomicLong(0) + private val notificationUpdateDelay = 1000L + private var pendingNotificationUpdate = AtomicBoolean(false) + + private var lastTempNotificationTime = AtomicLong(0) + private val tempNotificationDelay = 2000L + private val activeNotificationIds = mutableSetOf() + + private val actionReceiver = object : BroadcastReceiver() { + override fun onReceive(context: Context?, intent: Intent?) { + when (intent?.action) { + ACTION_PAUSE_RESUME -> { + val wasPaused = isPaused.get() + isPaused.set(!wasPaused) + + val feedbackTitle = if (wasPaused) { + this@AutoOpenSnaps.context.translation["auto_open_snaps.resumed_feedback"] + } else { + this@AutoOpenSnaps.context.translation["auto_open_snaps.paused_feedback"] + } + + val feedbackContent = if (wasPaused) { + this@AutoOpenSnaps.context.translation["auto_open_snaps.resumed_message"] + } else { + this@AutoOpenSnaps.context.translation["auto_open_snaps.paused_message"].replace("{count}", snapQueueSize.get().toString()) + } + + showTemporaryNotification(feedbackTitle, feedbackContent) + updateStatusNotification() + + + if (wasPaused && snapQueueSize.get() > 0) { + this@AutoOpenSnaps.context.log.debug("Resumed with ${snapQueueSize.get()} snaps in queue") + } + } + ACTION_CLEAR_QUEUE -> { + val queueSize = snapQueueSize.get() + val processedCount = totalProcessed.get() + + clearQueue(resetTotalCount = true, showNotification = false) + + val feedbackTitle = this@AutoOpenSnaps.context.translation["auto_open_snaps.queue_cleared_reset"] + val feedbackContent = if (queueSize > 0) { + this@AutoOpenSnaps.context.translation["auto_open_snaps.queue_cleared_feedback"] + .replace("{count}", queueSize.toString()) + .replace("{processed}", processedCount.toString()) + } else { + this@AutoOpenSnaps.context.translation["auto_open_snaps.queue_cleared_feedback_simple"] + .replace("{processed}", processedCount.toString()) + } + + showTemporaryNotification(feedbackTitle, feedbackContent) + } + } + } + } + + private fun createNotificationChannels() { + notificationManager.createNotificationChannel( + NotificationChannel(baseChannelId, + context.translation["auto_open_snaps.title"], + NotificationManager.IMPORTANCE_LOW).apply { + description = context.translation["auto_open_snaps.channel_description"] + setShowBadge(false) + setSound(null, null) + enableVibration(false) + } + ) + + notificationManager.createNotificationChannel( + NotificationChannel(priorityChannelId, + context.translation["auto_open_snaps.priority_title"], + NotificationManager.IMPORTANCE_DEFAULT).apply { + description = context.translation["auto_open_snaps.priority_channel_description"] + setShowBadge(true) + setSound(null, null) + enableVibration(false) + } + ) + + + } + + private fun createPendingIntent(action: String): PendingIntent { + val intent = Intent(action).apply { + setPackage(context.androidContext.packageName) + } + return PendingIntent.getBroadcast( + context.androidContext, + action.hashCode(), + intent, + PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE + ) + } + + private fun verifyQueueSync(): Boolean { + return synchronized(queuedSnaps) { + val actualSize = queuedSnaps.size + val atomicSize = snapQueueSize.get() + + val currentTime = System.currentTimeMillis() + val timeoutMs = 5 * 60 * 1000L + val originalSize = queuedSnaps.size + + val removed = mutableListOf() + queuedSnaps.removeAll { item -> + val stuck = (currentTime - item.timestamp) > timeoutMs + if (stuck) removed.add(item.messageId) + stuck + } + + if (removed.isNotEmpty()) { + context.log.warn("Cleaned up ${removed.size} stuck items") + } + + if (actualSize != atomicSize) { + context.log.warn("Queue size mismatch! Actual: $actualSize, Atomic: $atomicSize") + snapQueueSize.set(queuedSnaps.size) + + val uniqueItems = queuedSnaps.distinctBy { it.messageId }.toMutableList() + if (uniqueItems.size != queuedSnaps.size) { + context.log.warn("Found ${queuedSnaps.size - uniqueItems.size} duplicate items") + queuedSnaps.clear() + queuedSnaps.addAll(uniqueItems) + snapQueueSize.set(queuedSnaps.size) + } + return@synchronized false + } else { + snapQueueSize.set(queuedSnaps.size) + } + + return@synchronized true + } + } + + private fun updateStatusNotification() { + val currentTime = System.currentTimeMillis() + val lastUpdate = lastNotificationUpdate.get() + + // Throttle notification updates to prevent spam + if ((currentTime - lastUpdate) < notificationUpdateDelay) { + if (pendingNotificationUpdate.compareAndSet(false, true)) { + context.coroutineScope.launch { + delay(notificationUpdateDelay - (currentTime - lastUpdate)) + pendingNotificationUpdate.set(false) + updateStatusNotificationInternal() + } + } + return + } + + lastNotificationUpdate.set(currentTime) + updateStatusNotificationInternal() + } + + private fun updateStatusNotificationInternal() { + verifyQueueSync() + + val queueCount = snapQueueSize.get() + val processed = totalProcessed.get() + + if (queueCount <= 0 && processed <= 0) { + notificationManager.cancel(statusNotificationId) + return + } + + val channelId = if (queueCount > config.queueSize.get() * 0.8) { + priorityChannelId + } else { + baseChannelId + } + + val notificationBuilder = Notification.Builder(context.androidContext, channelId) + .setSmallIcon(if (isPaused.get()) android.R.drawable.ic_media_pause else android.R.drawable.ic_media_play) + .setOngoing(queueCount > 0) + .setAutoCancel(false) + + val statusText = if (isPaused.get()) { + context.translation["auto_open_snaps.status_paused"] + } else if (queueCount > 0) { + "Processing: $queueCount queued" + } else { + context.translation["auto_open_snaps.status_monitoring"] + } + + notificationBuilder + .setContentTitle(context.translation["auto_open_snaps.title"]) + .setContentText(statusText) + + if (queueCount > 0) { + val batchSize = currentBatchSize.get() + val batchProcessed = currentBatchProcessed.get() + val progressMax = maxOf(batchSize, queueCount + batchProcessed) + val progressCurrent = batchProcessed + + notificationBuilder.setProgress(progressMax, progressCurrent, false) + + val progressPercent = if (progressMax > 0) ((progressCurrent * 100) / progressMax) else 0 + notificationBuilder.setSubText("Progress: $progressPercent% • Queue: $queueCount") + } else { + notificationBuilder.setSubText("") + } + + val pauseResumeText = if (isPaused.get()) { + context.translation["auto_open_snaps.action_resume"] + } else { + context.translation["auto_open_snaps.action_pause"] + } + notificationBuilder.addAction( + Notification.Action.Builder( + null, + pauseResumeText, + createPendingIntent(ACTION_PAUSE_RESUME) + ).build() + ) + + if (queueCount > 0 || processed > 0) { + val clearText = if (queueCount > 0) { + context.translation["auto_open_snaps.action_clear"] + } else { + context.translation["auto_open_snaps.action_reset"] + } + notificationBuilder.addAction( + Notification.Action.Builder( + null, + clearText, + createPendingIntent(ACTION_CLEAR_QUEUE) + ).build() + ) + } + + val recentSnaps = queuedSnaps.takeLast(5) + val bigTextStyle = Notification.BigTextStyle() + + val detailText = buildString { + append("${context.translation["auto_open_snaps.notification_status"]}: ") + if (isPaused.get()) { + append("${context.translation["auto_open_snaps.status_paused"]}\n\n") + } else if (queueCount > 0) { + append("${context.translation["auto_open_snaps.status_active"]}\n\n") + } else { + append("${context.translation["auto_open_snaps.status_monitoring"]}\n\n") + } + + append("${context.translation["auto_open_snaps.notification_statistics"]}:\n") + append("├─ ${context.translation["auto_open_snaps.notification_queue_size"]}: $queueCount snaps\n") + append("└─ ${context.translation["auto_open_snaps.notification_total_opened"]}: $processed snaps\n\n") + + if (queueCount > 0) { + append("${context.translation["auto_open_snaps.notification_queue_preview"]}:\n") + recentSnaps.forEachIndexed { index, snap -> + val statusIcon = when { + index == recentSnaps.size - 1 -> ">" + else -> "-" + } + + append("$statusIcon ${snap.senderInfo}\n") + append(" ${snap.contentType} • ${snap.conversationType}\n") + if (index < recentSnaps.size - 1) append("\n") + } + append("\n${context.translation["auto_open_snaps.notification_processing_continue"]}") + } else { + append(context.translation["auto_open_snaps.notification_no_snaps_queue"]) + } + } + + bigTextStyle.bigText(detailText) + bigTextStyle.setBigContentTitle(context.translation["auto_open_snaps.title"]) + + if (queueCount > 0) { + bigTextStyle.setSummaryText("Queue: $queueCount | ${if (isPaused.get()) context.translation["auto_open_snaps.status_paused"] else context.translation["auto_open_snaps.status_active"]}") + } else { + bigTextStyle.setSummaryText("") + } + + notificationBuilder.setStyle(bigTextStyle) + + notificationManager.notify(statusNotificationId, notificationBuilder.build()) + } + + private fun clearQueue(resetTotalCount: Boolean = false, showNotification: Boolean = true) { + val clearedCount = synchronized(queuedSnaps) { + val count = queuedSnaps.size + queuedSnaps.clear() + snapQueueSize.set(0) + count + } + + synchronized(openedSnaps) { + openedSnaps.clear() + } + + if (resetTotalCount) { + totalProcessed.set(0) + lastResetTime = System.currentTimeMillis() + } + + currentBatchSize.set(0) + currentBatchProcessed.set(0) + + verifyQueueSync() + + notificationManager.cancel(statusNotificationId) + + if (showNotification) { + val message = if (resetTotalCount) { + context.translation["auto_open_snaps.queue_cleared"] + } else { + context.translation["auto_open_snaps.notification_queue_cleared_opened"].replace("{opened}", totalProcessed.get().toString()) + } + showTemporaryNotification(context.translation["auto_open_snaps.queue_cleared_title"], message) + } + } + + + + private fun showTemporaryNotification(title: String, content: String) { + val currentTime = System.currentTimeMillis() + val lastTempTime = lastTempNotificationTime.get() + + if ((currentTime - lastTempTime) < tempNotificationDelay) { + return + } + + lastTempNotificationTime.set(currentTime) + + // Cancel any existing temporary notifications + synchronized(activeNotificationIds) { + activeNotificationIds.forEach { id -> + notificationManager.cancel(id) + } + activeNotificationIds.clear() + } + + val tempNotificationId = Random.nextInt() + + val icon = when { + title.contains("cleared", ignoreCase = true) -> android.R.drawable.ic_menu_delete + title.contains("reset", ignoreCase = true) -> android.R.drawable.ic_menu_revert + title.contains("paused", ignoreCase = true) -> android.R.drawable.ic_media_pause + title.contains("resumed", ignoreCase = true) -> android.R.drawable.ic_media_play + else -> android.R.drawable.ic_dialog_info + } + + val notificationBuilder = Notification.Builder(context.androidContext, baseChannelId) + .setSmallIcon(icon) + .setContentTitle(title) + .setContentText(content) + .setAutoCancel(true) + .setTimeoutAfter(4000) + .setCategory(Notification.CATEGORY_STATUS) + + synchronized(activeNotificationIds) { + activeNotificationIds.add(tempNotificationId) + } + + notificationManager.notify(tempNotificationId, notificationBuilder.build()) + + context.coroutineScope.launch { + delay(4000) + synchronized(activeNotificationIds) { + activeNotificationIds.remove(tempNotificationId) + } + } + } + + override fun init() { + if (getRuleState() == null) return + if (config.globalState != true) return + val messaging = context.feature(Messaging::class) + + sessionStartTime = System.currentTimeMillis() + + if (config.allowRunningInBackground.get()) { + findClass("com.snapchat.client.duplex.DuplexClient\$CppProxy").apply { + hook("appStateChanged", HookStage.BEFORE) { param -> + if (param.arg(0).toString() == "INACTIVE") param.setResult(null) + } + hookConstructor(HookStage.AFTER) { param -> + methods.first { it.name == "appStateChanged" }.let { method -> + method.invoke(param.thisObject(), method.parameterTypes[0].enumConstants!!.first { it.toString() == "ACTIVE" }) + } + } + } + } + + val intentFilter = IntentFilter().apply { + addAction(ACTION_PAUSE_RESUME) + addAction(ACTION_CLEAR_QUEUE) + } + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + context.androidContext.registerReceiver( + actionReceiver, + intentFilter, + Context.RECEIVER_NOT_EXPORTED + ) + } else { + context.androidContext.registerReceiver(actionReceiver, intentFilter) + } + + createNotificationChannels() + + context.coroutineScope.launch(Dispatchers.Default) { + while (true) { + delay(30000) + verifyQueueSync() + } + } + + context.coroutineScope.launch(Dispatchers.Default, CoroutineStart.UNDISPATCHED) { + snapQueue.collect { snapItem -> + verifyQueueSync() + + var wasAddedToPausedQueue = false + while (isPaused.get()) { + if (!wasAddedToPausedQueue) { + synchronized(queuedSnaps) { + if (!queuedSnaps.any { it.messageId == snapItem.messageId }) { + queuedSnaps.add(snapItem) + snapQueueSize.set(queuedSnaps.size) + wasAddedToPausedQueue = true + updateStatusNotification() + } + } + } + delay(2000) + } + + val queueSizeAfterRemoval = synchronized(queuedSnaps) { + queuedSnaps.removeAll { it.messageId == snapItem.messageId } + snapQueueSize.set(queuedSnaps.size) + queuedSnaps.size + } + + val minDelayMs = config.minDelay.get().toLong() + val maxDelayMs = config.maxDelayMs.get().toLong() + val delayMs = if (maxDelayMs > minDelayMs) { + Random.nextLong(minDelayMs, maxDelayMs) + } else { + minDelayMs + } + delay(delayMs) + var result: String? = null + var lastError = "" + + for (i in 0 until config.retryAttempts.get()) { + while ((!config.allowRunningInBackground.get() && context.isMainActivityPaused) || messaging.conversationManager == null) { + delay(2000) + } + + result = suspendCoroutine { continuation -> + runCatching { + messaging.conversationManager?.updateMessage(snapItem.conversationId, snapItem.messageId, MessageUpdate.READ) { result -> + continuation.resume(result) + } + }.getOrNull() ?: continuation.resume("ConversationManager is null") + } + + if (result == null || result == "DUPLICATEREQUEST") { + break + } + + lastError = result + if (i < config.retryAttempts.get() - 1) { + delay(config.retryDelay.get().toLong()) + } + } + + if (result == null || result == "DUPLICATEREQUEST") { + totalProcessed.incrementAndGet() + currentBatchProcessed.incrementAndGet() + } else { + context.log.error("Failed to open ${snapItem.contentType} from ${snapItem.senderInfo}: $lastError") + } + + val finalQueueSize = snapQueueSize.get() + + if (finalQueueSize <= 0) { + currentBatchSize.set(0) + currentBatchProcessed.set(0) + } + + updateStatusNotification() + } + } + + context.event.subscribe(BuildMessageEvent::class, priority = 103) { event -> + if (event.message.senderId?.toString() == context.database.myUserId) return@subscribe + val conversationId = event.message.messageDescriptor?.conversationId?.toString() ?: return@subscribe + val clientMessageId = event.message.messageDescriptor?.messageId ?: return@subscribe + + val contentType = event.message.messageContent?.contentType + + if (contentType != ContentType.SNAP && contentType != ContentType.EXTERNAL_MEDIA) { + return@subscribe + } + + if (event.message.messageMetadata?.openedBy?.any { it.toString() == context.database.myUserId } == true) { + return@subscribe + } + + context.coroutineScope.launch(Dispatchers.Default) { + if (!canUseRule(conversationId)) return@launch + synchronized(openedSnaps) { + if (openedSnaps.contains(clientMessageId)) { + return@launch + } + openedSnaps.add(clientMessageId) + } + + val senderId = event.message.senderId?.toString() ?: context.translation["auto_open_snaps.unknown_sender"] + val senderInfo = getSenderDisplayName(senderId) + val conversationType = getConversationType(conversationId, senderId) + val contentType = getSnapContentType(event.message.messageContent?.contentType) + + val snapItem = SnapQueueItem( + conversationId = conversationId, + messageId = clientMessageId, + senderInfo = senderInfo, + conversationType = conversationType, + contentType = contentType + ) + + val actualQueueSize = synchronized(queuedSnaps) { + val existingItem = queuedSnaps.find { it.messageId == snapItem.messageId } + if (existingItem != null) { + return@launch + } + + if (queuedSnaps.size >= config.queueSize.get()) { + queuedSnaps.removeFirstOrNull() + } + + queuedSnaps.add(snapItem) + snapQueueSize.set(queuedSnaps.size) + + val newSize = queuedSnaps.size + currentBatchSize.set(maxOf(currentBatchSize.get(), newSize)) + + queuedSnaps.size + } + + updateStatusNotification() + + snapQueue.emit(snapItem) + } + } + } + + private fun getSenderDisplayName(senderId: String): String { + return try { + val friendInfo = context.database.getFriendInfo(senderId) + friendInfo?.displayName ?: friendInfo?.mutableUsername ?: context.translation["auto_open_snaps.unknown_user"] + } catch (e: Exception) { + context.translation["auto_open_snaps.unknown_user"] + } + } + + private fun getSnapContentType(contentType: ContentType?): String { + return when (contentType) { + ContentType.SNAP -> context.translation["auto_open_snaps.content_type_photo_video_snap"] + ContentType.EXTERNAL_MEDIA -> context.translation["auto_open_snaps.content_type_external_media"] + else -> context.translation["auto_open_snaps.content_type_snap"] + } + } + + private fun getConversationType(conversationId: String, senderId: String): String { + return try { + val dmParticipant = context.database.getDMOtherParticipant(conversationId) + + if (dmParticipant != null) { + val friendInfo = context.database.getFriendInfo(senderId) + return when { + friendInfo != null -> context.translation["auto_open_snaps.conversation_type_friend_dm"] + else -> context.translation["auto_open_snaps.conversation_type_dm"] + } + } else { + val feedEntry = context.database.getFeedEntryByConversationId(conversationId) + val groupName = feedEntry?.feedDisplayName?.takeIf { it.isNotBlank() } + + return if (groupName != null) { + context.translation["auto_open_snaps.conversation_type_group_with_name"].replace("{name}", groupName) + } else { + context.translation["auto_open_snaps.conversation_type_group_chat"] + } + } + } catch (e: Exception) { + context.translation["auto_open_snaps.conversation_type_chat"] + } + } +} diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/experiments/BestFriendPinning.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/experiments/BestFriendPinning.kt similarity index 88% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/experiments/BestFriendPinning.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/experiments/BestFriendPinning.kt index 32b6889a..2220ee42 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/experiments/BestFriendPinning.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/experiments/BestFriendPinning.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.core.features.impl.experiments +package me.eternal.purrfectsnap.core.features.impl.experiments import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.FavoriteBorder @@ -7,12 +7,12 @@ import com.google.gson.JsonObject import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.delay import kotlinx.coroutines.launch -import me.rhunk.snapenhance.common.bridge.InternalFileHandleType -import me.rhunk.snapenhance.common.util.protobuf.ProtoReader -import me.rhunk.snapenhance.core.event.events.impl.NetworkApiRequestEvent -import me.rhunk.snapenhance.core.event.events.impl.UnaryCallEvent -import me.rhunk.snapenhance.core.features.BridgeFileFeature -import me.rhunk.snapenhance.core.ui.triggerRootCloseTouchEvent +import me.eternal.purrfectsnap.common.bridge.InternalFileHandleType +import me.eternal.purrfectsnap.common.util.protobuf.ProtoReader +import me.eternal.purrfectsnap.core.event.events.impl.NetworkApiRequestEvent +import me.eternal.purrfectsnap.core.event.events.impl.UnaryCallEvent +import me.eternal.purrfectsnap.core.features.BridgeFileFeature +import me.eternal.purrfectsnap.core.ui.triggerRootCloseTouchEvent import java.io.InputStreamReader import java.nio.ByteBuffer import java.util.UUID diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/experiments/BetterLocation.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/experiments/BetterLocation.kt similarity index 91% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/experiments/BetterLocation.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/experiments/BetterLocation.kt index b6474b24..30ffd1d6 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/experiments/BetterLocation.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/experiments/BetterLocation.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.core.features.impl.experiments +package me.eternal.purrfectsnap.core.features.impl.experiments import android.location.Location import android.location.LocationManager @@ -17,24 +17,24 @@ import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.dp -import me.rhunk.snapenhance.common.ui.OverlayType -import me.rhunk.snapenhance.common.ui.createComposeView -import me.rhunk.snapenhance.common.util.protobuf.EditorContext -import me.rhunk.snapenhance.common.util.protobuf.ProtoEditor -import me.rhunk.snapenhance.common.util.protobuf.ProtoReader -import me.rhunk.snapenhance.core.event.events.impl.AddViewEvent -import me.rhunk.snapenhance.core.event.events.impl.UnaryCallEvent -import me.rhunk.snapenhance.core.features.Feature -import me.rhunk.snapenhance.core.ui.children -import me.rhunk.snapenhance.core.util.RandomWalking -import me.rhunk.snapenhance.core.util.dataBuilder -import me.rhunk.snapenhance.core.util.hook.HookStage -import me.rhunk.snapenhance.core.util.hook.hook -import me.rhunk.snapenhance.core.util.hook.hookConstructor -import me.rhunk.snapenhance.core.util.ktx.getId -import me.rhunk.snapenhance.core.util.ktx.getObjectField -import me.rhunk.snapenhance.core.util.ktx.isDarkTheme -import me.rhunk.snapenhance.mapper.impl.CallbackMapper +import me.eternal.purrfectsnap.common.ui.OverlayType +import me.eternal.purrfectsnap.common.ui.createComposeView +import me.eternal.purrfectsnap.common.util.protobuf.EditorContext +import me.eternal.purrfectsnap.common.util.protobuf.ProtoEditor +import me.eternal.purrfectsnap.common.util.protobuf.ProtoReader +import me.eternal.purrfectsnap.core.event.events.impl.AddViewEvent +import me.eternal.purrfectsnap.core.event.events.impl.UnaryCallEvent +import me.eternal.purrfectsnap.core.features.Feature +import me.eternal.purrfectsnap.core.ui.children +import me.eternal.purrfectsnap.core.util.RandomWalking +import me.eternal.purrfectsnap.core.util.dataBuilder +import me.eternal.purrfectsnap.core.util.hook.HookStage +import me.eternal.purrfectsnap.core.util.hook.hook +import me.eternal.purrfectsnap.core.util.hook.hookConstructor +import me.eternal.purrfectsnap.core.util.ktx.getId +import me.eternal.purrfectsnap.core.util.ktx.getObjectField +import me.eternal.purrfectsnap.core.util.ktx.isDarkTheme +import me.eternal.purrfectsnap.mapper.impl.CallbackMapper import java.nio.ByteBuffer import java.util.UUID import kotlin.math.atan2 @@ -180,7 +180,7 @@ class BetterLocation : Feature("Better Location") { locationHistory.values.toList().mapNotNull { locationHistory -> val friendInfo = context.database.getFriendInfo(locationHistory.userId) ?: return@mapNotNull null - me.rhunk.snapenhance.bridge.location.FriendLocation().also { + me.eternal.purrfectsnap.bridge.location.FriendLocation().also { it.username = friendInfo.mutableUsername ?: return@mapNotNull null it.displayName = friendInfo.displayName it.bitmojiId = friendInfo.bitmojiAvatarId @@ -305,4 +305,4 @@ class BetterLocation : Feature("Better Location") { }) } } -} \ No newline at end of file +} diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/experiments/BetterTranscript.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/experiments/BetterTranscript.kt similarity index 82% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/experiments/BetterTranscript.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/experiments/BetterTranscript.kt index d2979048..d0909473 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/experiments/BetterTranscript.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/experiments/BetterTranscript.kt @@ -1,14 +1,14 @@ -package me.rhunk.snapenhance.core.features.impl.experiments +package me.eternal.purrfectsnap.core.features.impl.experiments -import me.rhunk.snapenhance.common.data.ContentType -import me.rhunk.snapenhance.common.util.protobuf.ProtoEditor -import me.rhunk.snapenhance.core.event.events.impl.BuildMessageEvent -import me.rhunk.snapenhance.core.features.Feature -import me.rhunk.snapenhance.core.util.dataBuilder -import me.rhunk.snapenhance.core.util.hook.HookStage -import me.rhunk.snapenhance.core.util.hook.hook -import me.rhunk.snapenhance.core.util.ktx.getObjectFieldOrNull -import me.rhunk.snapenhance.core.util.ktx.setObjectField +import me.eternal.purrfectsnap.common.data.ContentType +import me.eternal.purrfectsnap.common.util.protobuf.ProtoEditor +import me.eternal.purrfectsnap.core.event.events.impl.BuildMessageEvent +import me.eternal.purrfectsnap.core.features.Feature +import me.eternal.purrfectsnap.core.util.dataBuilder +import me.eternal.purrfectsnap.core.util.hook.HookStage +import me.eternal.purrfectsnap.core.util.hook.hook +import me.eternal.purrfectsnap.core.util.ktx.getObjectFieldOrNull +import me.eternal.purrfectsnap.core.util.ktx.setObjectField import java.nio.ByteBuffer class BetterTranscript: Feature("Better Transcript") { diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/experiments/CallRecorder.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/experiments/CallRecorder.kt similarity index 90% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/experiments/CallRecorder.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/experiments/CallRecorder.kt index 247e7da7..17bb976b 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/experiments/CallRecorder.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/experiments/CallRecorder.kt @@ -1,20 +1,20 @@ -package me.rhunk.snapenhance.core.features.impl.experiments +package me.eternal.purrfectsnap.core.features.impl.experiments import android.media.AudioAttributes import android.media.AudioFormat import android.media.AudioTrack import kotlinx.coroutines.runBlocking import kotlinx.coroutines.withTimeoutOrNull -import me.rhunk.snapenhance.common.data.download.AudioStreamFormat -import me.rhunk.snapenhance.common.data.download.MediaDownloadSource -import me.rhunk.snapenhance.core.features.Feature -import me.rhunk.snapenhance.core.features.impl.downloader.MediaDownloader -import me.rhunk.snapenhance.core.util.hook.HookStage -import me.rhunk.snapenhance.core.util.hook.hook -import me.rhunk.snapenhance.core.util.hook.hookConstructor -import me.rhunk.snapenhance.core.util.ktx.getObjectField -import me.rhunk.snapenhance.core.util.ktx.getObjectFieldOrNull -import me.rhunk.snapenhance.core.util.media.HttpServer +import me.eternal.purrfectsnap.common.data.download.AudioStreamFormat +import me.eternal.purrfectsnap.common.data.download.MediaDownloadSource +import me.eternal.purrfectsnap.core.features.Feature +import me.eternal.purrfectsnap.core.features.impl.downloader.MediaDownloader +import me.eternal.purrfectsnap.core.util.hook.HookStage +import me.eternal.purrfectsnap.core.util.hook.hook +import me.eternal.purrfectsnap.core.util.hook.hookConstructor +import me.eternal.purrfectsnap.core.util.ktx.getObjectField +import me.eternal.purrfectsnap.core.util.ktx.getObjectFieldOrNull +import me.eternal.purrfectsnap.core.util.media.HttpServer import java.io.PipedInputStream import java.io.PipedOutputStream import java.nio.ByteBuffer diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/experiments/ComposerHooks.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/experiments/ComposerHooks.kt similarity index 87% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/experiments/ComposerHooks.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/experiments/ComposerHooks.kt index e626b675..ac70580a 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/experiments/ComposerHooks.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/experiments/ComposerHooks.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.core.features.impl.experiments +package me.eternal.purrfectsnap.core.features.impl.experiments import androidx.compose.foundation.layout.* import androidx.compose.foundation.rememberScrollState @@ -17,17 +17,17 @@ import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import kotlinx.coroutines.launch -import me.rhunk.snapenhance.common.bridge.FileHandleScope -import me.rhunk.snapenhance.common.bridge.toWrapper -import me.rhunk.snapenhance.common.ui.createComposeAlertDialog -import me.rhunk.snapenhance.core.SnapEnhance -import me.rhunk.snapenhance.core.features.Feature -import me.rhunk.snapenhance.core.features.impl.downloader.MediaDownloader -import me.rhunk.snapenhance.core.util.hook.HookStage -import me.rhunk.snapenhance.core.util.hook.Hooker -import me.rhunk.snapenhance.core.util.hook.hook -import me.rhunk.snapenhance.core.wrapper.impl.composer.ComposerMarshaller -import me.rhunk.snapenhance.nativelib.NativeLib +import me.eternal.purrfectsnap.common.bridge.FileHandleScope +import me.eternal.purrfectsnap.common.bridge.toWrapper +import me.eternal.purrfectsnap.common.ui.createComposeAlertDialog +import me.eternal.purrfectsnap.core.PurrfectSnap +import me.eternal.purrfectsnap.core.features.Feature +import me.eternal.purrfectsnap.core.features.impl.downloader.MediaDownloader +import me.eternal.purrfectsnap.core.util.hook.HookStage +import me.eternal.purrfectsnap.core.util.hook.Hooker +import me.eternal.purrfectsnap.core.util.hook.hook +import me.eternal.purrfectsnap.core.wrapper.impl.composer.ComposerMarshaller +import me.eternal.purrfectsnap.nativelib.NativeLib import java.lang.reflect.Proxy import kotlin.math.absoluteValue import kotlin.random.Random @@ -184,7 +184,7 @@ class ComposerHooks: Feature("ComposerHooks") { context.native.setComposerLoader(""" const i = setInterval(() => { try { - const _runtimeName = "${if (SnapEnhance.classCache.nativeBridge.name == "com.snapchat.client.valdi.NativeBridge") "valdi" else "composer"}"; + const _runtimeName = "${if (PurrfectSnap.classCache.nativeBridge.name == "com.snapchat.client.valdi.NativeBridge") "valdi" else "composer"}"; require(_runtimeName + '_core/DeviceBridge').getDisplayWidth(); clearInterval(i); (() => { const _getImportsFunctionName = "$getImportsFunctionName"; $loaderScript })(); @@ -208,11 +208,16 @@ class ComposerHooks: Feature("ComposerHooks") { } } - SnapEnhance.classCache.nativeBridge.hook("registerNativeModuleFactory", HookStage.BEFORE) { param -> + PurrfectSnap.classCache.nativeBridge.hook("registerNativeModuleFactory", HookStage.BEFORE) { param -> val moduleFactory = param.argNullable(1) ?: return@hook - if (moduleFactory.javaClass.getMethod("getModulePath").invoke(moduleFactory)?.toString()?.contains("DeviceBridge") != true) return@hook + Hooker.ephemeralHookObjectMethod(moduleFactory.javaClass, moduleFactory, "loadModule", HookStage.AFTER) { methodParam -> val result = methodParam.getResult() as? MutableMap ?: return@ephemeralHookObjectMethod + + val looksLikeDeviceBridge = result.containsKey("getDisplayWidth") || result.containsKey("getDisplayHeight") + if (!looksLikeDeviceBridge) return@ephemeralHookObjectMethod + if (result.containsKey(getImportsFunctionName)) return@ephemeralHookObjectMethod + result[getImportsFunctionName] = newComposerFunction { pushUntyped(importedFunctions) true diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/experiments/ContextMenuFix.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/experiments/ContextMenuFix.kt similarity index 81% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/experiments/ContextMenuFix.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/experiments/ContextMenuFix.kt index 8104b576..412d73b8 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/experiments/ContextMenuFix.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/experiments/ContextMenuFix.kt @@ -1,7 +1,7 @@ -package me.rhunk.snapenhance.core.features.impl.experiments +package me.eternal.purrfectsnap.core.features.impl.experiments -import me.rhunk.snapenhance.core.event.events.impl.UnaryCallEvent -import me.rhunk.snapenhance.core.features.Feature +import me.eternal.purrfectsnap.core.event.events.impl.UnaryCallEvent +import me.eternal.purrfectsnap.core.features.Feature import java.nio.ByteBuffer class ContextMenuFix: Feature("Context Menu Fix") { diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/experiments/ConvertMessageLocally.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/experiments/ConvertMessageLocally.kt similarity index 81% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/experiments/ConvertMessageLocally.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/experiments/ConvertMessageLocally.kt index 2a63de0b..b4722f4d 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/experiments/ConvertMessageLocally.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/experiments/ConvertMessageLocally.kt @@ -1,14 +1,14 @@ -package me.rhunk.snapenhance.core.features.impl.experiments +package me.eternal.purrfectsnap.core.features.impl.experiments -import me.rhunk.snapenhance.common.data.ContentType -import me.rhunk.snapenhance.common.util.protobuf.ProtoReader -import me.rhunk.snapenhance.common.util.protobuf.ProtoWriter -import me.rhunk.snapenhance.core.event.events.impl.BuildMessageEvent -import me.rhunk.snapenhance.core.features.Feature -import me.rhunk.snapenhance.core.features.impl.messaging.Messaging -import me.rhunk.snapenhance.core.ui.ViewAppearanceHelper -import me.rhunk.snapenhance.core.wrapper.impl.Message -import me.rhunk.snapenhance.core.wrapper.impl.MessageContent +import me.eternal.purrfectsnap.common.data.ContentType +import me.eternal.purrfectsnap.common.util.protobuf.ProtoReader +import me.eternal.purrfectsnap.common.util.protobuf.ProtoWriter +import me.eternal.purrfectsnap.core.event.events.impl.BuildMessageEvent +import me.eternal.purrfectsnap.core.features.Feature +import me.eternal.purrfectsnap.core.features.impl.messaging.Messaging +import me.eternal.purrfectsnap.core.ui.ViewAppearanceHelper +import me.eternal.purrfectsnap.core.wrapper.impl.Message +import me.eternal.purrfectsnap.core.wrapper.impl.MessageContent class ConvertMessageLocally : Feature("Convert Message Edit") { private val messageCache = mutableMapOf() diff --git a/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/experiments/CustomEmojiFont.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/experiments/CustomEmojiFont.kt new file mode 100644 index 00000000..ffbf9b32 --- /dev/null +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/experiments/CustomEmojiFont.kt @@ -0,0 +1,53 @@ +package me.eternal.purrfectsnap.core.features.impl.experiments + +import me.eternal.purrfectsnap.common.bridge.FileHandleScope +import me.eternal.purrfectsnap.core.ModContext +import java.io.File +import java.io.FileOutputStream + + +private var cacheFontPath: String? = null +private var cacheFontName: String? = null + +fun getCustomEmojiFontPath( + context: ModContext +): String? { + val customFileName = context.config.experimental.nativeHooks.customEmojiFont.getNullable()?.takeIf { it.isNotBlank() } ?: return null + val safeFileName = customFileName.substringAfterLast("/") + return runCatching { + val handle = context.fileHandlerManager.getFileHandle( + FileHandleScope.USER_IMPORT.key, + customFileName + ) ?: return@runCatching null + if (!handle.exists()) { + File(context.androidContext.filesDir, "emoji_fonts") + .resolve(safeFileName) + .takeIf { it.exists() } + ?.delete() + cacheFontPath = "" + cacheFontName = safeFileName + return@runCatching null + } + + val persistentDir = File(context.androidContext.filesDir, "emoji_fonts").apply { + mkdirs() + } + val persistentFile = File(persistentDir, safeFileName) + handle.open(android.os.ParcelFileDescriptor.MODE_READ_ONLY)?.use { pfd -> + if (!persistentFile.exists() || pfd.statSize != persistentFile.length()) { + FileOutputStream(persistentFile).use { output -> + android.os.ParcelFileDescriptor.AutoCloseInputStream(pfd).use { input -> + input.copyTo(output) + } + } + } + } + cacheFontName = safeFileName + cacheFontPath = persistentFile.absolutePath + cacheFontPath?.takeIf { it.isNotEmpty() } + }.onFailure { + context.log.error("Failed to get custom emoji font", it) + }.getOrNull() +} + + diff --git a/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/experiments/DeviceSpooferHook.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/experiments/DeviceSpooferHook.kt new file mode 100644 index 00000000..7f43ef9f --- /dev/null +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/experiments/DeviceSpooferHook.kt @@ -0,0 +1,447 @@ +package me.eternal.purrfectsnap.core.features.impl.experiments + +import android.annotation.SuppressLint +import android.location.Location +import android.net.ConnectivityManager +import android.net.Network +import android.net.NetworkCapabilities +import android.os.Build +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Wifi +import me.eternal.purrfectsnap.core.features.Feature +import me.eternal.purrfectsnap.core.util.LSPatchUpdater +import me.eternal.purrfectsnap.core.util.hook.HookStage +import me.eternal.purrfectsnap.core.util.hook.hook +import java.security.SecureRandom + +class DeviceSpooferHook: Feature("Device Spoofer") { + private var spoofedAndroidId: String? = null + private var hasLoggedId = false + private var randomizedFingerprints = mutableMapOf() + + private fun generateAndroidId(): String { + if (spoofedAndroidId != null) return spoofedAndroidId!! + val customId = context.config.experimental.spoof.customAndroidId.getNullable() + if (!customId.isNullOrEmpty()) { + spoofedAndroidId = customId.lowercase() + if (!hasLoggedId) { + context.log.info("Using custom Android ID: $spoofedAndroidId") + hasLoggedId = true + } + return spoofedAndroidId!! + } + val sharedPrefs = context.androidContext.getSharedPreferences("purrfectsnap_spoof", 0) + spoofedAndroidId = sharedPrefs.getString("android_id", null) + if (spoofedAndroidId == null) { + spoofedAndroidId = generateRandomHexString(16) + sharedPrefs.edit().putString("android_id", spoofedAndroidId).apply() + context.log.info("Generated new Android ID: $spoofedAndroidId") + } else if (!hasLoggedId) { + context.log.info("Using stored Android ID: $spoofedAndroidId") + } + hasLoggedId = true + return spoofedAndroidId!! + } + + private fun generateRandomHexString(length: Int): String { + val random = SecureRandom() + val bytes = ByteArray(length / 2) + random.nextBytes(bytes) + return bytes.joinToString("") { "%02x".format(it) } + } + + private fun randomizeFingerprintBuildNumber(fingerprint: String, deviceKey: String): String { + if (randomizedFingerprints.containsKey(deviceKey)) { + return randomizedFingerprints[deviceKey]!! + } + val sharedPrefs = context.androidContext.getSharedPreferences("purrfectsnap_spoof", 0) + val savedFingerprint = sharedPrefs.getString("fingerprint_$deviceKey", null) + if (savedFingerprint != null) { + randomizedFingerprints[deviceKey] = savedFingerprint + return savedFingerprint + } + val parts = fingerprint.split("/") + if (parts.size >= 3) { + val buildPart = parts[2] + val buildSections = buildPart.split(":") + if (buildSections.size >= 2) { + val buildDetails = buildSections[1].split("/") + if (buildDetails.size >= 2) { + val randomBuildNumber = generateRandomBuildNumber() + val newBuildDetails = buildDetails.toMutableList() + newBuildDetails[1] = randomBuildNumber + val newBuildPart = "${buildSections[0]}:${newBuildDetails.joinToString("/")}" + val newFingerprint = "${parts[0]}/${parts[1]}/$newBuildPart" + randomizedFingerprints[deviceKey] = newFingerprint + sharedPrefs.edit().putString("fingerprint_$deviceKey", newFingerprint).apply() + return newFingerprint + } + } + } + randomizedFingerprints[deviceKey] = fingerprint + return fingerprint + } + + private fun generateRandomBuildNumber(): String { + val chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" + val random = SecureRandom() + return (1..10).map { chars[random.nextInt(chars.length)] }.joinToString("") + } + + private fun randomizeDisplayId(display: String, deviceKey: String, buildNumber: String): String { + val sharedPrefs = context.androidContext.getSharedPreferences("purrfectsnap_spoof", 0) + val savedDisplay = sharedPrefs.getString("display_$deviceKey", null) + if (savedDisplay != null) return savedDisplay + val parts = display.split(".") + val newDisplay = if (parts.size > 1) { + "${parts[0]}.${parts[1]}.$buildNumber" + } else { + display + } + sharedPrefs.edit().putString("display_$deviceKey", newDisplay).apply() + return newDisplay + } + + private fun getRandomSerial(deviceKey: String): String { + val sharedPrefs = context.androidContext.getSharedPreferences("purrfectsnap_spoof", 0) + val savedSerial = sharedPrefs.getString("serial_$deviceKey", null) + if (savedSerial != null) return savedSerial + val random = SecureRandom() + val serial = (1..16).map { + "0123456789ABCDEF"[random.nextInt(16)] + }.joinToString("") + sharedPrefs.edit().putString("serial_$deviceKey", serial).apply() + return serial + } + + private fun getRandomBuildId(deviceKey: String): String { + val sharedPrefs = context.androidContext.getSharedPreferences("purrfectsnap_spoof", 0) + val savedBuildId = sharedPrefs.getString("build_id_$deviceKey", null) + if (savedBuildId != null) return savedBuildId + val chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" + val random = SecureRandom() + val buildId = (1..8).map { chars[random.nextInt(chars.length)] }.joinToString("") + sharedPrefs.edit().putString("build_id_$deviceKey", buildId).apply() + return buildId + } + + private fun getRandomGsfId(): String { + val sharedPrefs = context.androidContext.getSharedPreferences("purrfectsnap_spoof", 0) + val savedGsfId = sharedPrefs.getString("gsf_id", null) + if (savedGsfId != null) return savedGsfId + val random = SecureRandom() + val gsfId = (1..16).map { + "0123456789abcdef"[random.nextInt(16)] + }.joinToString("") + sharedPrefs.edit().putString("gsf_id", gsfId).apply() + return gsfId + } + + private fun generateRandomUUID(): String { + val sharedPrefs = context.androidContext.getSharedPreferences("purrfectsnap_spoof", 0) + val savedUuid = sharedPrefs.getString("advertising_id", null) + if (savedUuid != null) return savedUuid + val random = SecureRandom() + val uuid = "%08x-%04x-%04x-%04x-%012x".format( + random.nextInt(), + random.nextInt() and 0xFFFF, + (random.nextInt() and 0x0FFF) or 0x4000, + (random.nextInt() and 0x3FFF) or 0x8000, + random.nextLong() and 0xFFFFFFFFFFFFL + ) + sharedPrefs.edit().putString("advertising_id", uuid).apply() + return uuid + } + + private fun generateRandomMacAddress(): String { + val sharedPrefs = context.androidContext.getSharedPreferences("purrfectsnap_spoof", 0) + val savedMac = sharedPrefs.getString("bluetooth_address", null) + if (savedMac != null) return savedMac + val random = SecureRandom() + val mac = (1..6).map { + "%02x".format(random.nextInt(256)) + }.joinToString(":") + sharedPrefs.edit().putString("bluetooth_address", mac).apply() + return mac + } + + data class DeviceProfile( + val manufacturer: String, + val brand: String, + val model: String, + val device: String, + val product: String, + val hardware: String, + val board: String, + val fingerprint: String, + val display: String + ) + + private val deviceProfiles = mapOf( + "samsung_s25_ultra" to DeviceProfile( + manufacturer = "samsung", + brand = "samsung", + model = "SM-S938U", + device = "e3q", + product = "e3qsqw", + hardware = "qcom", + board = "taro", + fingerprint = "samsung/e3qsqw/e3q:15/AP2A.240805.005/S938USQU1AXL2:user/release-keys", + display = "AP2A.240805.005.S938USQU1AXL2" + ), + "google_pixel_10_pro" to DeviceProfile( + manufacturer = "Google", + brand = "google", + model = "Pixel 10 Pro", + device = "caiman", + product = "caiman", + hardware = "caiman", + board = "caiman", + fingerprint = "google/caiman/caiman:15/AP2A.240805.005/12345678:user/release-keys", + display = "AP2A.240805.005" + ), + "oneplus_13" to DeviceProfile( + manufacturer = "OnePlus", + brand = "OnePlus", + model = "CPH2649", + device = "OP5B41L1", + product = "CPH2649_EEA", + hardware = "qcom", + board = "kalama", + fingerprint = "OnePlus/CPH2649_EEA/OP5B41L1:15/SKQ1.240805.001/1730123456789:user/release-keys", + display = "CPH2649_15.0.0.300(EX01)" + ), + "xiaomi_15_ultra" to DeviceProfile( + manufacturer = "Xiaomi", + brand = "Xiaomi", + model = "23127PN0CC", + device = "aurora", + product = "aurora_global", + hardware = "qcom", + board = "taro", + fingerprint = "Xiaomi/aurora_global/aurora:14/UKQ1.231003.002/V816.0.7.0.UMLMIXM:user/release-keys", + display = "UKQ1.231003.002" + ) + ) + + private fun hookInstallerPackageName() { + context.androidContext.packageManager::class.java.hook("getInstallerPackageName", HookStage.BEFORE) { param -> + param.setResult("com.android.vending") + } + } + + @SuppressLint("MissingPermission") + override fun init() { + if (LSPatchUpdater.HAS_LSPATCH) { + hookInstallerPackageName() + } + + if (context.config.experimental.spoof.globalState != true) return + + val removeMockLocationFlag by context.config.experimental.spoof.removeMockLocationFlag + val overridePlayStoreInstallerPackageName by context.config.experimental.spoof.overridePlayStoreInstallerPackageName + val removeVpnTransportFlag by context.config.experimental.spoof.removeVpnTransportFlag + val forceWifiTransportFlag by context.config.experimental.spoof.forceWifiTransportFlag + val spoofAndroidId by context.config.experimental.spoof.spoofAndroidId + + if(overridePlayStoreInstallerPackageName) { + hookInstallerPackageName() + } + + if (removeMockLocationFlag) { + Location::class.java.hook("isMock", HookStage.BEFORE) { param -> + param.setResult(false) + } + } + + if (removeVpnTransportFlag) { + ConnectivityManager::class.java.hook("getAllNetworks", HookStage.AFTER) { param -> + val instance = param.thisObject() as? ConnectivityManager ?: return@hook + val networks = param.getResult() as? Array<*> ?: return@hook + + param.setResult(networks.filterIsInstance().filter { network -> + val capabilities = instance.getNetworkCapabilities(network) ?: return@filter false + !capabilities.hasTransport(NetworkCapabilities.TRANSPORT_VPN) + }.toTypedArray()) + } + } + + if (forceWifiTransportFlag) { + val connectivityManager = context.androidContext.getSystemService(ConnectivityManager::class.java) + val activeNetwork = connectivityManager?.activeNetwork + val initialCapabilities = activeNetwork?.let { connectivityManager.getNetworkCapabilities(it) } + val isReallyOnWifi = initialCapabilities?.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) == true + + onNextActivityCreate { + if (isReallyOnWifi) { + context.inAppOverlay.showStatusToast( + icon = Icons.Filled.Wifi, + text = "Connected to Real WiFi", + durationMs = 3000 + ) + } else { + context.inAppOverlay.showStatusToast( + icon = Icons.Filled.Wifi, + text = "WiFi Spoofing Active", + durationMs = 3000 + ) + } + } + + NetworkCapabilities::class.java.apply { + hook("hasTransport", HookStage.BEFORE) { param -> + val transportType = param.args().getOrNull(0) as? Int + val actuallyHasWifi = runCatching { + param.invokeOriginal() as Boolean + }.getOrDefault(false) + + if (actuallyHasWifi == true && transportType == NetworkCapabilities.TRANSPORT_WIFI) { + return@hook + } + + if (transportType == NetworkCapabilities.TRANSPORT_WIFI) { + param.setResult(true) + } else if (transportType == NetworkCapabilities.TRANSPORT_CELLULAR) { + param.setResult(false) + } + } + hook("hasCapability", HookStage.BEFORE) { param -> + val capability = param.args().getOrNull(0) as? Int + if (capability == NetworkCapabilities.NET_CAPABILITY_NOT_VPN) { + param.setResult(true) + } + } + } + findClass("android.net.NetworkInfo").apply { + hook("getType", HookStage.BEFORE) { param -> + val originalType = runCatching { + param.invokeOriginal() as Int + }.getOrDefault(-1) + + if (originalType == 1) { + return@hook + } + param.setResult(1) + } + hook("getTypeName", HookStage.BEFORE) { param -> + val originalTypeName = runCatching { + param.invokeOriginal() as String + }.getOrNull() + + if (originalTypeName?.equals("WIFI", ignoreCase = true) == true) { + return@hook + } + param.setResult("WIFI") + } + hook("isConnected", HookStage.BEFORE) { param -> + param.setResult(true) + } + } + findClass("org.chromium.base.RadioUtils").hook("isWifiConnected", HookStage.BEFORE) { param -> + val actuallyOnWifi = runCatching { + val connectivityMgr = context.androidContext.getSystemService(ConnectivityManager::class.java) + val activeNet = connectivityMgr?.activeNetwork + val caps = activeNet?.let { connectivityMgr.getNetworkCapabilities(it) } + caps?.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) == true + }.getOrDefault(false) + + if (!actuallyOnWifi) { + param.setResult(true) + } + } + } + + if (spoofAndroidId) { + val gsfId = getRandomGsfId() + val wifiMac = generateRandomMacAddress() + findClass("android.provider.Settings\$Secure").hook("getString", HookStage.BEFORE) { param -> + val settingName = param.argNullable(1) + when (settingName) { + "android_id" -> param.setResult(generateAndroidId()) + "advertising_id" -> param.setResult(generateRandomUUID()) + "bluetooth_address" -> param.setResult(wifiMac) + } + } + findClass("android.provider.Settings\$Secure").hook("getLong", HookStage.BEFORE) { param -> + val settingName = param.argNullable(1) + if (settingName == "android_id") { + param.setResult(generateAndroidId().hashCode().toLong()) + } + } + runCatching { + findClass("android.net.wifi.WifiInfo").hook("getMacAddress", HookStage.BEFORE) { param -> + param.setResult(wifiMac) + } + } + runCatching { + findClass("android.bluetooth.BluetoothAdapter").hook("getAddress", HookStage.BEFORE) { param -> + param.setResult(wifiMac) + } + } + } + + val spoofDevice by context.config.experimental.spoof.spoofDevice + if (spoofDevice) { + val selectedDevice = context.config.experimental.spoof.deviceModel.getNullable() ?: "samsung_s25_ultra" + val deviceProfile = deviceProfiles[selectedDevice] ?: deviceProfiles["samsung_s25_ultra"]!! + val randomizedFingerprint = randomizeFingerprintBuildNumber(deviceProfile.fingerprint, selectedDevice) + val buildNumber = randomizedFingerprint.split("/").getOrNull(2)?.split(":")?.getOrNull(1)?.split("/")?.getOrNull(1) ?: generateRandomBuildNumber() + val randomizedDisplay = randomizeDisplayId(deviceProfile.display, selectedDevice, buildNumber) + val randomSerial = getRandomSerial(selectedDevice) + val randomBuildId = getRandomBuildId(selectedDevice) + + context.log.info("Spoofing device as: ${deviceProfile.model}") + + Build::class.java.apply { + fields.forEach { field -> + if (!field.isAccessible) field.isAccessible = true + runCatching { + val modifiersField = java.lang.reflect.Field::class.java.getDeclaredField("modifiers") + modifiersField.isAccessible = true + modifiersField.setInt(field, field.modifiers and java.lang.reflect.Modifier.FINAL.inv()) + } + when (field.name) { + "MANUFACTURER" -> field.set(null, deviceProfile.manufacturer) + "BRAND" -> field.set(null, deviceProfile.brand) + "MODEL" -> field.set(null, deviceProfile.model) + "DEVICE" -> field.set(null, deviceProfile.device) + "PRODUCT" -> field.set(null, deviceProfile.product) + "HARDWARE" -> field.set(null, deviceProfile.hardware) + "BOARD" -> field.set(null, deviceProfile.board) + "FINGERPRINT" -> field.set(null, randomizedFingerprint) + "DISPLAY" -> field.set(null, randomizedDisplay) + "SERIAL" -> field.set(null, randomSerial) + "ID" -> field.set(null, randomBuildId) + "TAGS" -> field.set(null, "release-keys") + "TYPE" -> field.set(null, "user") + "USER" -> field.set(null, "android-build") + "HOST" -> field.set(null, "build-host") + } + } + } + + findClass("android.os.SystemProperties").apply { + hook("get", HookStage.BEFORE) { param -> + val key = param.arg(0) + when (key) { + "ro.product.manufacturer", "ro.product.vendor.manufacturer", "ro.product.system.manufacturer", "ro.product.odm.manufacturer" -> param.setResult(deviceProfile.manufacturer) + "ro.product.brand", "ro.product.vendor.brand", "ro.product.system.brand", "ro.product.odm.brand" -> param.setResult(deviceProfile.brand) + "ro.product.model", "ro.product.vendor.model", "ro.product.system.model", "ro.product.odm.model" -> param.setResult(deviceProfile.model) + "ro.product.device", "ro.product.vendor.device", "ro.product.system.device", "ro.product.odm.device" -> param.setResult(deviceProfile.device) + "ro.product.name", "ro.product.vendor.name", "ro.product.system.name", "ro.product.odm.name" -> param.setResult(deviceProfile.product) + "ro.hardware", "ro.hardware.chipname" -> param.setResult(deviceProfile.hardware) + "ro.product.board" -> param.setResult(deviceProfile.board) + "ro.build.fingerprint" -> param.setResult(randomizedFingerprint) + "ro.build.display.id" -> param.setResult(randomizedDisplay) + "ro.serialno", "ro.boot.serialno", "ril.serialnumber" -> param.setResult(randomSerial) + "ro.build.id" -> param.setResult(randomBuildId) + "ro.build.tags" -> param.setResult("release-keys") + "ro.build.type" -> param.setResult("user") + "ro.build.user" -> param.setResult("android-build") + "ro.build.host" -> param.setResult("build-host") + } + } + } + } + } +} diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/experiments/EndToEndEncryption.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/experiments/EndToEndEncryption.kt similarity index 93% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/experiments/EndToEndEncryption.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/experiments/EndToEndEncryption.kt index 93ec0a40..45ad88bb 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/experiments/EndToEndEncryption.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/experiments/EndToEndEncryption.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.core.features.impl.experiments +package me.eternal.purrfectsnap.core.features.impl.experiments import android.annotation.SuppressLint import android.graphics.Canvas @@ -16,33 +16,33 @@ import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp -import me.rhunk.snapenhance.common.data.ContentType -import me.rhunk.snapenhance.common.data.MessageState -import me.rhunk.snapenhance.common.data.MessagingRuleType -import me.rhunk.snapenhance.common.data.RuleState -import me.rhunk.snapenhance.common.database.impl.ConversationMessage -import me.rhunk.snapenhance.common.ui.createComposeView -import me.rhunk.snapenhance.common.util.lazyBridge -import me.rhunk.snapenhance.common.util.protobuf.ProtoEditor -import me.rhunk.snapenhance.common.util.protobuf.ProtoReader -import me.rhunk.snapenhance.common.util.protobuf.ProtoWriter -import me.rhunk.snapenhance.core.event.events.impl.* -import me.rhunk.snapenhance.core.features.MessagingRuleFeature -import me.rhunk.snapenhance.core.features.impl.ui.ConversationToolbox -import me.rhunk.snapenhance.core.ui.ViewAppearanceHelper -import me.rhunk.snapenhance.core.ui.addForegroundDrawable -import me.rhunk.snapenhance.core.ui.findParent -import me.rhunk.snapenhance.core.ui.removeForegroundDrawable -import me.rhunk.snapenhance.core.util.EvictingMap -import me.rhunk.snapenhance.core.util.hook.HookStage -import me.rhunk.snapenhance.core.util.hook.hook -import me.rhunk.snapenhance.core.util.ktx.getObjectField -import me.rhunk.snapenhance.core.util.ktx.getObjectFieldOrNull -import me.rhunk.snapenhance.core.wrapper.impl.MessageContent -import me.rhunk.snapenhance.core.wrapper.impl.MessageDestinations -import me.rhunk.snapenhance.core.wrapper.impl.SnapUUID -import me.rhunk.snapenhance.mapper.impl.CallbackMapper -import me.rhunk.snapenhance.nativelib.NativeLib +import me.eternal.purrfectsnap.common.data.ContentType +import me.eternal.purrfectsnap.common.data.MessageState +import me.eternal.purrfectsnap.common.data.MessagingRuleType +import me.eternal.purrfectsnap.common.data.RuleState +import me.eternal.purrfectsnap.common.database.impl.ConversationMessage +import me.eternal.purrfectsnap.common.ui.createComposeView +import me.eternal.purrfectsnap.common.util.lazyBridge +import me.eternal.purrfectsnap.common.util.protobuf.ProtoEditor +import me.eternal.purrfectsnap.common.util.protobuf.ProtoReader +import me.eternal.purrfectsnap.common.util.protobuf.ProtoWriter +import me.eternal.purrfectsnap.core.event.events.impl.* +import me.eternal.purrfectsnap.core.features.MessagingRuleFeature +import me.eternal.purrfectsnap.core.features.impl.ui.ConversationToolbox +import me.eternal.purrfectsnap.core.ui.ViewAppearanceHelper +import me.eternal.purrfectsnap.core.ui.addForegroundDrawable +import me.eternal.purrfectsnap.core.ui.findParent +import me.eternal.purrfectsnap.core.ui.removeForegroundDrawable +import me.eternal.purrfectsnap.core.util.EvictingMap +import me.eternal.purrfectsnap.core.util.hook.HookStage +import me.eternal.purrfectsnap.core.util.hook.hook +import me.eternal.purrfectsnap.core.util.ktx.getObjectField +import me.eternal.purrfectsnap.core.util.ktx.getObjectFieldOrNull +import me.eternal.purrfectsnap.core.wrapper.impl.MessageContent +import me.eternal.purrfectsnap.core.wrapper.impl.MessageDestinations +import me.eternal.purrfectsnap.core.wrapper.impl.SnapUUID +import me.eternal.purrfectsnap.mapper.impl.CallbackMapper +import me.eternal.purrfectsnap.nativelib.NativeLib import java.security.MessageDigest import kotlin.random.Random diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/experiments/InfiniteStoryBoost.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/experiments/InfiniteStoryBoost.kt similarity index 70% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/experiments/InfiniteStoryBoost.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/experiments/InfiniteStoryBoost.kt index 7e645005..b8012a9c 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/experiments/InfiniteStoryBoost.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/experiments/InfiniteStoryBoost.kt @@ -1,9 +1,9 @@ -package me.rhunk.snapenhance.core.features.impl.experiments +package me.eternal.purrfectsnap.core.features.impl.experiments -import me.rhunk.snapenhance.core.features.Feature -import me.rhunk.snapenhance.core.util.hook.HookStage -import me.rhunk.snapenhance.core.util.hook.hookConstructor -import me.rhunk.snapenhance.mapper.impl.StoryBoostStateMapper +import me.eternal.purrfectsnap.core.features.Feature +import me.eternal.purrfectsnap.core.util.hook.HookStage +import me.eternal.purrfectsnap.core.util.hook.hookConstructor +import me.eternal.purrfectsnap.mapper.impl.StoryBoostStateMapper class InfiniteStoryBoost : Feature("InfiniteStoryBoost") { override fun init() { diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/experiments/MediaFilePicker.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/experiments/MediaFilePicker.kt similarity index 63% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/experiments/MediaFilePicker.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/experiments/MediaFilePicker.kt index 4df7152c..838331c6 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/experiments/MediaFilePicker.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/experiments/MediaFilePicker.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.core.features.impl.experiments +package me.eternal.purrfectsnap.core.features.impl.experiments import android.annotation.SuppressLint import android.app.Activity @@ -13,28 +13,41 @@ import android.provider.MediaStore import android.view.View import android.view.ViewGroup import android.widget.FrameLayout +import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.background +import androidx.compose.foundation.border +import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.CheckCircleOutline import androidx.compose.material.icons.filled.Crop import androidx.compose.material.icons.filled.Error import androidx.compose.material.icons.filled.Upload -import androidx.compose.material3.FilledIconButton import androidx.compose.material3.Icon import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.draw.shadow +import androidx.compose.ui.graphics.Brush +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.unit.dp import kotlinx.coroutines.launch -import me.rhunk.snapenhance.common.ui.createComposeView -import me.rhunk.snapenhance.common.util.ktx.getLongOrNull -import me.rhunk.snapenhance.common.util.ktx.getTypeArguments -import me.rhunk.snapenhance.core.event.events.impl.ActivityResultEvent -import me.rhunk.snapenhance.core.event.events.impl.AddViewEvent -import me.rhunk.snapenhance.core.features.Feature -import me.rhunk.snapenhance.core.ui.ViewAppearanceHelper -import me.rhunk.snapenhance.core.util.dataBuilder -import me.rhunk.snapenhance.core.util.hook.HookStage -import me.rhunk.snapenhance.core.util.hook.hook +import me.eternal.purrfectsnap.common.ui.createComposeView +import me.eternal.purrfectsnap.common.util.ktx.getLongOrNull +import me.eternal.purrfectsnap.common.util.ktx.getTypeArguments +import me.eternal.purrfectsnap.core.event.events.impl.ActivityResultEvent +import me.eternal.purrfectsnap.core.event.events.impl.AddViewEvent +import me.eternal.purrfectsnap.core.features.Feature +import me.eternal.purrfectsnap.core.ui.PurrfectOverlayPalette +import me.eternal.purrfectsnap.core.ui.PurrfectOverlayTheme +import me.eternal.purrfectsnap.core.ui.ViewAppearanceHelper +import me.eternal.purrfectsnap.core.util.dataBuilder +import me.eternal.purrfectsnap.core.util.hook.HookStage +import me.eternal.purrfectsnap.core.util.hook.hook import java.io.InputStream import java.lang.reflect.Method import kotlin.random.Random @@ -201,22 +214,63 @@ class MediaFilePicker : Feature("Media File Picker") { } != null) return event.parent.addView( createComposeView(context.mainActivity!!) { - Row( - modifier = Modifier.fillMaxWidth(), - horizontalArrangement = Arrangement.End - ) { - FilledIconButton(onClick = { - requestCode = Random.nextInt(0, 65535) - this@MediaFilePicker.context.mainActivity!!.startActivityForResult( - Intent(Intent.ACTION_OPEN_DOCUMENT).apply { - addCategory(Intent.CATEGORY_OPENABLE) - type = "video/*" - putExtra(Intent.EXTRA_MIME_TYPES, arrayOf("video/*", "audio/*")) - }, - requestCode!! - ) - }) { - Icon(Icons.Default.Upload, "Upload media") + PurrfectOverlayTheme { + Row( + modifier = Modifier + .fillMaxWidth() + .padding(end = 10.dp, top = 8.dp), + horizontalArrangement = Arrangement.End + ) { + val shape = RoundedCornerShape(18.dp) + Box( + modifier = Modifier + .size(54.dp) + .shadow( + elevation = 16.dp, + shape = shape, + spotColor = PurrfectOverlayPalette.glowPrimary.copy(alpha = 0.28f), + ambientColor = PurrfectOverlayPalette.glowSecondary.copy(alpha = 0.20f) + ) + .clip(shape) + .background( + brush = Brush.linearGradient( + listOf( + PurrfectOverlayPalette.glowPrimary.copy(alpha = 0.35f), + PurrfectOverlayPalette.glowSecondary.copy(alpha = 0.18f) + ) + ), + shape = shape + ) + .border( + 1.dp, + Brush.linearGradient( + listOf( + PurrfectOverlayPalette.glowPrimary.copy(alpha = 0.7f), + PurrfectOverlayPalette.glowSecondary.copy(alpha = 0.55f) + ) + ), + shape = shape + ) + .clickable { + requestCode = Random.nextInt(0, 65535) + this@MediaFilePicker.context.mainActivity!!.startActivityForResult( + Intent(Intent.ACTION_OPEN_DOCUMENT).apply { + addCategory(Intent.CATEGORY_OPENABLE) + type = "video/*" + putExtra(Intent.EXTRA_MIME_TYPES, arrayOf("video/*", "audio/*")) + }, + requestCode!! + ) + }, + contentAlignment = androidx.compose.ui.Alignment.Center + ) { + Icon( + imageVector = Icons.Default.Upload, + contentDescription = "Upload media", + tint = Color.White, + modifier = Modifier.size(24.dp) + ) + } } } }.apply { @@ -235,4 +289,4 @@ class MediaFilePicker : Feature("Media File Picker") { } } } -} \ No newline at end of file +} diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/experiments/MeoPasscodeBypass.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/experiments/MeoPasscodeBypass.kt similarity index 67% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/experiments/MeoPasscodeBypass.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/experiments/MeoPasscodeBypass.kt index 9ea6024e..6af67ede 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/experiments/MeoPasscodeBypass.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/experiments/MeoPasscodeBypass.kt @@ -1,9 +1,9 @@ -package me.rhunk.snapenhance.core.features.impl.experiments +package me.eternal.purrfectsnap.core.features.impl.experiments -import me.rhunk.snapenhance.core.features.Feature -import me.rhunk.snapenhance.core.util.hook.HookStage -import me.rhunk.snapenhance.core.util.hook.hook -import me.rhunk.snapenhance.mapper.impl.BCryptClassMapper +import me.eternal.purrfectsnap.core.features.Feature +import me.eternal.purrfectsnap.core.util.hook.HookStage +import me.eternal.purrfectsnap.core.util.hook.hook +import me.eternal.purrfectsnap.mapper.impl.BCryptClassMapper class MeoPasscodeBypass : Feature("Meo Passcode Bypass") { override fun init() { diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/experiments/NoFriendScoreDelay.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/experiments/NoFriendScoreDelay.kt similarity index 74% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/experiments/NoFriendScoreDelay.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/experiments/NoFriendScoreDelay.kt index 26c73154..11abe720 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/experiments/NoFriendScoreDelay.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/experiments/NoFriendScoreDelay.kt @@ -1,9 +1,9 @@ -package me.rhunk.snapenhance.core.features.impl.experiments +package me.eternal.purrfectsnap.core.features.impl.experiments -import me.rhunk.snapenhance.core.features.Feature -import me.rhunk.snapenhance.core.util.hook.HookStage -import me.rhunk.snapenhance.core.util.hook.hookConstructor -import me.rhunk.snapenhance.mapper.impl.ScoreUpdateMapper +import me.eternal.purrfectsnap.core.features.Feature +import me.eternal.purrfectsnap.core.util.hook.HookStage +import me.eternal.purrfectsnap.core.util.hook.hookConstructor +import me.eternal.purrfectsnap.mapper.impl.ScoreUpdateMapper import kotlin.time.Duration.Companion.days import kotlin.time.Duration.Companion.minutes diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/experiments/PreventForcedLogout.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/experiments/PreventForcedLogout.kt similarity index 72% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/experiments/PreventForcedLogout.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/experiments/PreventForcedLogout.kt index 213b9786..0e27ce4f 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/experiments/PreventForcedLogout.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/experiments/PreventForcedLogout.kt @@ -1,9 +1,9 @@ -package me.rhunk.snapenhance.core.features.impl.experiments +package me.eternal.purrfectsnap.core.features.impl.experiments import android.content.Intent -import me.rhunk.snapenhance.core.features.Feature -import me.rhunk.snapenhance.core.util.hook.HookStage -import me.rhunk.snapenhance.core.util.hook.hook +import me.eternal.purrfectsnap.core.features.Feature +import me.eternal.purrfectsnap.core.util.hook.HookStage +import me.eternal.purrfectsnap.core.util.hook.hook class PreventForcedLogout : Feature("Prevent Forced Logout") { override fun init() { diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/experiments/SnapScoreChanges.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/experiments/SnapScoreChanges.kt similarity index 84% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/experiments/SnapScoreChanges.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/experiments/SnapScoreChanges.kt index abe4a94e..22ccc601 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/experiments/SnapScoreChanges.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/experiments/SnapScoreChanges.kt @@ -1,14 +1,14 @@ -package me.rhunk.snapenhance.core.features.impl.experiments +package me.eternal.purrfectsnap.core.features.impl.experiments import android.view.ViewGroup -import me.rhunk.snapenhance.common.util.protobuf.ProtoReader -import me.rhunk.snapenhance.core.event.events.impl.AddViewEvent -import me.rhunk.snapenhance.core.event.events.impl.UnaryCallEvent -import me.rhunk.snapenhance.core.features.Feature -import me.rhunk.snapenhance.core.ui.getComposerContext -import me.rhunk.snapenhance.core.ui.getComposerViewNode -import me.rhunk.snapenhance.core.util.ktx.getObjectField -import me.rhunk.snapenhance.core.wrapper.impl.SnapUUID +import me.eternal.purrfectsnap.common.util.protobuf.ProtoReader +import me.eternal.purrfectsnap.core.event.events.impl.AddViewEvent +import me.eternal.purrfectsnap.core.event.events.impl.UnaryCallEvent +import me.eternal.purrfectsnap.core.features.Feature +import me.eternal.purrfectsnap.core.ui.getComposerContext +import me.eternal.purrfectsnap.core.ui.getComposerViewNode +import me.eternal.purrfectsnap.core.util.ktx.getObjectField +import me.eternal.purrfectsnap.core.wrapper.impl.SnapUUID class SnapScoreChanges: Feature("Snap Score Changes") { private val scores = mutableMapOf() diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/global/BypassVideoLengthRestriction.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/global/BypassVideoLengthRestriction.kt similarity index 83% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/global/BypassVideoLengthRestriction.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/global/BypassVideoLengthRestriction.kt index 0c5ec312..d986c300 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/global/BypassVideoLengthRestriction.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/global/BypassVideoLengthRestriction.kt @@ -1,15 +1,15 @@ -package me.rhunk.snapenhance.core.features.impl.global +package me.eternal.purrfectsnap.core.features.impl.global import android.os.Build import android.os.FileObserver import com.google.gson.JsonParser -import me.rhunk.snapenhance.core.event.events.impl.SendMessageWithContentEvent -import me.rhunk.snapenhance.core.features.Feature -import me.rhunk.snapenhance.core.util.dataBuilder -import me.rhunk.snapenhance.core.util.hook.HookStage -import me.rhunk.snapenhance.core.util.hook.hookConstructor -import me.rhunk.snapenhance.core.util.ktx.setObjectField -import me.rhunk.snapenhance.mapper.impl.DefaultMediaItemMapper +import me.eternal.purrfectsnap.core.event.events.impl.SendMessageWithContentEvent +import me.eternal.purrfectsnap.core.features.Feature +import me.eternal.purrfectsnap.core.util.dataBuilder +import me.eternal.purrfectsnap.core.util.hook.HookStage +import me.eternal.purrfectsnap.core.util.hook.hookConstructor +import me.eternal.purrfectsnap.core.util.ktx.setObjectField +import me.eternal.purrfectsnap.mapper.impl.DefaultMediaItemMapper import java.io.File class BypassVideoLengthRestriction : @@ -70,25 +70,26 @@ class BypassVideoLengthRestriction : } } - //TODO: allow split from any source if (mode == "split") { - // memories grid context.mappings.useMapper(DefaultMediaItemMapper::class) { cameraRollMediaId.getAsClass()?.hookConstructor(HookStage.AFTER) { param -> - //set the durationMs field param.thisObject() .setObjectField(durationMsField.get()!!, -1L) } } - // chat camera roll grid + findClass("com.snap.impala.common.media.MediaLibraryItem").hookConstructor(HookStage.AFTER) { param -> + param.thisObject().setObjectField("_durationMs", -1.0) + } + findClass("com.snap.composer.memories.MemoriesPickerVideoDurationConfig").hookConstructor(HookStage.AFTER) { param -> param.thisObject().apply { setObjectField("_maxSingleItemDurationMs", null) setObjectField("_maxTotalDurationMs", null) + setObjectField("_maxSnapLengthMs", null) } } } } } -} \ No newline at end of file +} diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/global/DisableCustomTabs.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/global/DisableCustomTabs.kt similarity index 71% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/global/DisableCustomTabs.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/global/DisableCustomTabs.kt index 0c78a637..349a1e66 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/global/DisableCustomTabs.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/global/DisableCustomTabs.kt @@ -1,9 +1,9 @@ -package me.rhunk.snapenhance.core.features.impl.global +package me.eternal.purrfectsnap.core.features.impl.global import android.content.Intent -import me.rhunk.snapenhance.core.features.Feature -import me.rhunk.snapenhance.core.util.hook.HookStage -import me.rhunk.snapenhance.core.util.hook.hook +import me.eternal.purrfectsnap.core.features.Feature +import me.eternal.purrfectsnap.core.util.hook.HookStage +import me.eternal.purrfectsnap.core.util.hook.hook class DisableCustomTabs: Feature("Disable Custom Tabs") { override fun init() { diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/global/DisableMemoriesSnapFeed.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/global/DisableMemoriesSnapFeed.kt similarity index 73% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/global/DisableMemoriesSnapFeed.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/global/DisableMemoriesSnapFeed.kt index c0d670a6..2e3f46b5 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/global/DisableMemoriesSnapFeed.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/global/DisableMemoriesSnapFeed.kt @@ -1,9 +1,9 @@ -package me.rhunk.snapenhance.core.features.impl.global +package me.eternal.purrfectsnap.core.features.impl.global -import me.rhunk.snapenhance.core.features.Feature -import me.rhunk.snapenhance.core.util.hook.HookStage -import me.rhunk.snapenhance.core.util.hook.hook -import me.rhunk.snapenhance.mapper.impl.MemoriesPresenterMapper +import me.eternal.purrfectsnap.core.features.Feature +import me.eternal.purrfectsnap.core.util.hook.HookStage +import me.eternal.purrfectsnap.core.util.hook.hook +import me.eternal.purrfectsnap.mapper.impl.MemoriesPresenterMapper class DisableMemoriesSnapFeed : Feature("Disable Memories Snap Feed") { override fun init() { diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/global/DisableMetrics.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/global/DisableMetrics.kt similarity index 72% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/global/DisableMetrics.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/global/DisableMetrics.kt index 253bba99..0546dd3c 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/global/DisableMetrics.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/global/DisableMetrics.kt @@ -1,9 +1,9 @@ -package me.rhunk.snapenhance.core.features.impl.global +package me.eternal.purrfectsnap.core.features.impl.global -import me.rhunk.snapenhance.common.util.protobuf.ProtoReader -import me.rhunk.snapenhance.core.event.events.impl.NetworkApiRequestEvent -import me.rhunk.snapenhance.core.event.events.impl.UnaryCallEvent -import me.rhunk.snapenhance.core.features.Feature +import me.eternal.purrfectsnap.common.util.protobuf.ProtoReader +import me.eternal.purrfectsnap.core.event.events.impl.NetworkApiRequestEvent +import me.eternal.purrfectsnap.core.event.events.impl.UnaryCallEvent +import me.eternal.purrfectsnap.core.features.Feature class DisableMetrics : Feature("DisableMetrics") { override fun init() { diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/global/DisableTelecomFramework.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/global/DisableTelecomFramework.kt similarity index 64% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/global/DisableTelecomFramework.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/global/DisableTelecomFramework.kt index aa22e58f..c7e49d8b 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/global/DisableTelecomFramework.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/global/DisableTelecomFramework.kt @@ -1,9 +1,9 @@ -package me.rhunk.snapenhance.core.features.impl.global +package me.eternal.purrfectsnap.core.features.impl.global import android.content.ContextWrapper -import me.rhunk.snapenhance.core.features.Feature -import me.rhunk.snapenhance.core.util.hook.HookStage -import me.rhunk.snapenhance.core.util.hook.hook +import me.eternal.purrfectsnap.core.features.Feature +import me.eternal.purrfectsnap.core.util.hook.HookStage +import me.eternal.purrfectsnap.core.util.hook.hook class DisableTelecomFramework: Feature("Disable Telecom Framework") { override fun init() { diff --git a/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/global/EndpointsBlocker.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/global/EndpointsBlocker.kt new file mode 100644 index 00000000..39b427ab --- /dev/null +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/global/EndpointsBlocker.kt @@ -0,0 +1,194 @@ +package me.eternal.purrfectsnap.core.features.impl.global + +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Check +import androidx.compose.material.icons.filled.Close +import androidx.compose.material3.Icon +import androidx.compose.material3.Text +import androidx.compose.runtime.* +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import kotlinx.coroutines.delay +import me.eternal.purrfectsnap.core.features.Feature +import me.eternal.purrfectsnap.core.event.events.impl.UnaryCallEvent +import me.eternal.purrfectsnap.core.ui.CustomComposable +import me.eternal.purrfectsnap.core.util.dataBuilder +import me.eternal.purrfectsnap.core.util.hook.HookStage +import me.eternal.purrfectsnap.core.util.hook.hook +import me.eternal.purrfectsnap.core.util.ktx.getObjectField +import me.eternal.purrfectsnap.mapper.impl.CallbackMapper +import me.eternal.purrfectsnap.mapper.impl.PlatformClientAttestationMapper +import java.io.IOException +import java.lang.reflect.Method + +class EndpointsBlocker : Feature("EndpointsBlocker") { + @Volatile + private var isInLoginSignup = false + + private fun showBypassStatusIndicator(isWorking: Boolean) { + if (context.bridgeClient.getDebugProp("disable_bypass_indicator", "false") == "true") { + return + } + + lateinit var composable: CustomComposable + composable = { + Row( + modifier = Modifier + .padding(16.dp) + .align(Alignment.TopCenter) + .background( + color = Color.Black.copy(alpha = 0.8f), + shape = RoundedCornerShape(8.dp) + ) + .padding(horizontal = 12.dp, vertical = 8.dp), + verticalAlignment = Alignment.CenterVertically + ) { + Icon( + imageVector = if (isWorking) Icons.Filled.Check else Icons.Filled.Close, + contentDescription = null, + tint = if (isWorking) Color.Green else Color.Red, + modifier = Modifier.size(16.dp) + ) + Spacer(modifier = Modifier.width(8.dp)) + Text( + text = "PurrAura", + color = Color.White, + fontSize = 14.sp + ) + } + + LaunchedEffect(Unit) { + delay(3000) + context.inAppOverlay.removeCustomComposable(composable) + } + } + + context.inAppOverlay.addCustomComposable(composable) + } + + override fun init() { + val bypassToggleEnabled = context.bridgeClient.getDebugProp("test_mode", "false") == "true" + + if (context.disablePlugin && !bypassToggleEnabled) { + context.log.verbose("EndpointsBlocker: Plugin disabled and test_mode not enabled, skipping initialization") + return + } + + onNextActivityCreate { activity -> + if (activity.javaClass.name.endsWith("LoginSignupActivity")) { + isInLoginSignup = true + runCatching { context.native.setInLoginSignup(true) } + + onNextActivityCreate { + isInLoginSignup = false + runCatching { context.native.setInLoginSignup(false) } + } + } + } + runCatching { context.native.setInLoginSignup(false) } + + if (bypassToggleEnabled) { + context.native.setTestMode(true) + val healthy = context.native.isEndpointBlockerHealthy(testMode = true) + if (!healthy) { + context.log.warn("EndpointsBlocker: native self-test failed, indicator set to inactive") + context.log.warn("EndpointsBlocker: Possible causes - config not loaded or self-test logic failed") + } + showBypassStatusIndicator(healthy) + } else { + context.native.setTestMode(false) + } + + context.event.subscribe(UnaryCallEvent::class) { event -> + val bypassToggleEnabled = context.bridgeClient.getDebugProp("test_mode", "false") == "true" + if (!bypassToggleEnabled && context.disablePlugin) { + return@subscribe + } + if (isInLoginSignup) return@subscribe + + val callOptions = event.adapter.arg(2).let { it.javaClass.getMethod("build").invoke(it) } ?: return@subscribe + val hasAttestation = callOptions.getObjectField("mAttestation") != null + val arg0 = event.adapter.arg(0).toString() + + val decision = context.native.evaluateEndpoint(event.uri, arg0, hasAttestation) + + if (decision.blocked) { + event.canceled = true + val eventHandler = event.adapter.arg(3) + eventHandler.javaClass.methods.first { it.name == "onEvent" }.also { method -> + method.invoke(eventHandler, null, method.parameterTypes[0].dataBuilder { + set("mStatusCode", "CANCELLED") + }) + } + } + } + + context.androidContext.classLoader.apply { + loadClass("com.snapchat.client.duplex.DuplexClient\$CppProxy").hook("registerHandler", + HookStage.BEFORE) { param -> + val bypassToggleEnabled = context.bridgeClient.getDebugProp("test_mode", "false") == "true" + if (!bypassToggleEnabled && context.disablePlugin) { + return@hook + } + if (isInLoginSignup) return@hook + + val path = param.arg(0) + if (context.native.shouldBlockDuplexClient(path)) { + param.setResult(null) + return@hook + } + } + } + + context.mappings.useMapper(CallbackMapper::class) { + callbacks.getClass("AuthContextDelegate")?.hook("getAuthContext", HookStage.BEFORE) { param -> + val bypassToggleEnabled = context.bridgeClient.getDebugProp("test_mode", "false") == "true" + if (!bypassToggleEnabled && context.disablePlugin) { + return@hook + } + if (isInLoginSignup) return@hook + + val authContextRequest = param.arg(0) + val requestPath = authContextRequest.getObjectField("mRequestPath").toString() + val attestationRequired = authContextRequest.getObjectField("mAttestationRequired") == true + val decision = context.native.evaluateAuthContext(requestPath, attestationRequired) + + if (decision.blocked) { + param.setResult(null) + } + } ?: error("AuthContextDelegate not found in mappings") + } + + context.mappings.useMapper(PlatformClientAttestationMapper::class) { + apiInvocationHandler.getAsClass()?.hook("invoke", HookStage.BEFORE) { param -> + val bypassToggleEnabled = context.bridgeClient.getDebugProp("test_mode", "false") == "true" + if (!bypassToggleEnabled && context.disablePlugin) { + return@hook + } + if (isInLoginSignup) return@hook + + val method = param.arg(1) + val methodId = "${method.declaringClass.name}.${method.name}" + val annotationBlob = method.annotations.joinToString("\n") { it.toString() } + val decision = context.native.evaluateApiInvocation(methodId, annotationBlob) + + if (decision.blocked) { + if (method.returnType.name.endsWith("Single")) { + val errorSingle = method.returnType.methods.first { + java.lang.reflect.Modifier.isStatic(it.modifiers) && it.parameterCount == 1 && it.parameterTypes[0] == Throwable::class.java + }.invoke(null, IOException()) + param.setResult(errorSingle) + return@hook + } + param.setResult(null) + } + } ?: context.log.warn("apiInvocationHandler not found in mappings") + } + } +} diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/global/GooglePlayServicesDialogs.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/global/GooglePlayServicesDialogs.kt similarity index 77% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/global/GooglePlayServicesDialogs.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/global/GooglePlayServicesDialogs.kt index 13890b22..a298c84b 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/global/GooglePlayServicesDialogs.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/global/GooglePlayServicesDialogs.kt @@ -1,9 +1,9 @@ -package me.rhunk.snapenhance.core.features.impl.global +package me.eternal.purrfectsnap.core.features.impl.global import android.app.AlertDialog -import me.rhunk.snapenhance.core.features.Feature -import me.rhunk.snapenhance.core.util.hook.HookStage -import me.rhunk.snapenhance.core.util.hook.hook +import me.eternal.purrfectsnap.core.features.Feature +import me.eternal.purrfectsnap.core.util.hook.HookStage +import me.eternal.purrfectsnap.core.util.hook.hook import java.lang.reflect.Modifier class GooglePlayServicesDialogs : Feature("Disable GMS Dialogs") { diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/global/MediaUploadQualityOverride.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/global/MediaUploadQualityOverride.kt similarity index 62% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/global/MediaUploadQualityOverride.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/global/MediaUploadQualityOverride.kt index 20f58fcd..4a2a4ab1 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/global/MediaUploadQualityOverride.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/global/MediaUploadQualityOverride.kt @@ -1,10 +1,10 @@ -package me.rhunk.snapenhance.core.features.impl.global +package me.eternal.purrfectsnap.core.features.impl.global import android.graphics.Bitmap -import me.rhunk.snapenhance.core.features.Feature -import me.rhunk.snapenhance.core.util.hook.HookStage -import me.rhunk.snapenhance.core.util.hook.hook -import me.rhunk.snapenhance.mapper.impl.MediaQualityLevelProviderMapper +import me.eternal.purrfectsnap.core.features.Feature +import me.eternal.purrfectsnap.core.util.hook.HookStage +import me.eternal.purrfectsnap.core.util.hook.hook +import me.eternal.purrfectsnap.mapper.impl.MediaQualityLevelProviderMapper import java.lang.reflect.Method class MediaUploadQualityOverride : Feature("Media Upload Quality Override") { @@ -13,9 +13,20 @@ class MediaUploadQualityOverride : Feature("Media Upload Quality Override") { context.mappings.useMapper(MediaQualityLevelProviderMapper::class) { mediaQualityLevelProvider.getAsClass()?.hook( mediaQualityLevelProviderMethod.getAsString()!!, - HookStage.BEFORE + HookStage.AFTER ) { param -> - param.setResult((param.method() as Method).returnType.enumConstants!!.firstOrNull { it.toString() == "LEVEL_MAX" } ) + val method = param.method() as Method + val enumClass = method.returnType + val values = enumClass.enumConstants ?: return@hook + val nameMethod = runCatching { enumClass.getMethod("name") }.getOrNull() + val maxIndex = values.indexOfFirst { nameMethod?.invoke(it)?.toString() == "LEVEL_MAX" } + val targetIndex = when { + maxIndex > 0 -> maxIndex - 1 + values.size > 1 -> values.lastIndex - 1 + else -> return@hook + } + val target = values[targetIndex] + if (param.getResult() != target) param.setResult(target) } } } @@ -45,4 +56,4 @@ class MediaUploadQualityOverride : Feature("Media Upload Quality Override") { } } } -} \ No newline at end of file +} diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/global/SnapchatPlus.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/global/SnapchatPlus.kt similarity index 86% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/global/SnapchatPlus.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/global/SnapchatPlus.kt index 5d0b1717..1b9dbbed 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/global/SnapchatPlus.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/global/SnapchatPlus.kt @@ -1,11 +1,11 @@ -package me.rhunk.snapenhance.core.features.impl.global +package me.eternal.purrfectsnap.core.features.impl.global -import me.rhunk.snapenhance.core.features.Feature -import me.rhunk.snapenhance.core.util.dataBuilder -import me.rhunk.snapenhance.core.util.hook.HookStage -import me.rhunk.snapenhance.core.util.hook.hook -import me.rhunk.snapenhance.core.util.hook.hookConstructor -import me.rhunk.snapenhance.mapper.impl.PlusSubscriptionMapper +import me.eternal.purrfectsnap.core.features.Feature +import me.eternal.purrfectsnap.core.util.dataBuilder +import me.eternal.purrfectsnap.core.util.hook.HookStage +import me.eternal.purrfectsnap.core.util.hook.hook +import me.eternal.purrfectsnap.core.util.hook.hookConstructor +import me.eternal.purrfectsnap.mapper.impl.PlusSubscriptionMapper class SnapchatPlus: Feature("SnapchatPlus") { private val originalSubscriptionTime = (System.currentTimeMillis() - 7776000000L) diff --git a/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/messaging/AutoDeleteSentMessages.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/messaging/AutoDeleteSentMessages.kt new file mode 100644 index 00000000..6796d221 --- /dev/null +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/messaging/AutoDeleteSentMessages.kt @@ -0,0 +1,402 @@ +package me.eternal.purrfectsnap.core.features.impl.messaging + +import android.app.NotificationChannel +import android.app.NotificationManager +import android.content.Context +import android.os.Build +import android.os.Handler +import android.os.Looper +import android.view.View +import android.view.ViewGroup +import android.widget.LinearLayout +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Delete +import androidx.compose.material.icons.filled.Schedule +import androidx.compose.material3.* +import androidx.compose.runtime.* +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import androidx.core.app.NotificationCompat +import kotlinx.coroutines.delay +import kotlinx.coroutines.launch +import me.eternal.purrfectsnap.common.data.ContentType +import me.eternal.purrfectsnap.common.data.MessageUpdate +import me.eternal.purrfectsnap.common.data.MessagingRuleType +import me.eternal.purrfectsnap.common.ui.createComposeView +import me.eternal.purrfectsnap.core.event.events.impl.BindViewEvent +import me.eternal.purrfectsnap.core.event.events.impl.SendMessageWithContentEvent +import me.eternal.purrfectsnap.core.features.MessagingRuleFeature +import me.eternal.purrfectsnap.core.features.impl.messaging.Messaging +import me.eternal.purrfectsnap.core.util.ktx.getObjectField +import kotlin.random.Random + +class AutoDeleteSentMessages : MessagingRuleFeature("Auto Delete Sent Messages", MessagingRuleType.AUTO_DELETE_SENT_MESSAGES) { + companion object { + } + + private val pendingDeletions = mutableMapOf() + private val countdownStates = mutableMapOf>() + private val activeViews = mutableMapOf() + private val translation by lazy { context.translation.getCategory("auto_delete_sent_messages") } + private val countdownTag = Random.nextLong().toString() + private val notificationChannelId = "auto_delete_messages" + private var notificationId = 1000 + + + + + override fun init() { + val config = context.config.messaging.autoDeleteSentMessages + + if (config.globalState != true) { + return + } + + if (getRuleState() == null) return + + val deleteAfterValue = config.deleteAfterValue.get() + val deleteAfterUnit = config.deleteAfterUnit.get() + val showCountdown = config.showCountdown.get() + val showNotification = config.showNotification.get() + val messageTypes = config.messageTypes.get() + val allowRunningInBackground = config.allowRunningInBackground.get() + + if (showNotification) { + setupNotificationChannel() + } + + + + + + if (allowRunningInBackground) { + context.coroutineScope.launch { + while (true) { + delay(5000) + if (context.isMainActivityPaused && pendingDeletions.isNotEmpty()) { + updatePersistentNotification() + } + } + } + } + + onNextActivityCreate { + context.event.subscribe(BindViewEvent::class) { event -> + event.chatMessage { _, _ -> + val view = event.view as? ViewGroup ?: return@subscribe + view.findViewWithTag(countdownTag)?.let { view.removeView(it) } + + val message = event.databaseMessage ?: return@chatMessage + val messageKey = "${message.clientConversationId}:${message.clientMessageId}" + + activeViews[messageKey] = view + + addCountdownToView(view, messageKey) + } + } + } + + + val deleteAfterSeconds = when (deleteAfterUnit) { + "minutes" -> deleteAfterValue * 60 + "hours" -> deleteAfterValue * 3600 + else -> deleteAfterValue + } + + context.event.subscribe(SendMessageWithContentEvent::class) { event -> + val contentType = event.messageContent.contentType + + if (contentType == null || !messageTypes.contains(contentType.name)) { + return@subscribe + } + + val conversationId = event.destinations.conversations?.firstOrNull()?.toString() + + if (conversationId == null) { + return@subscribe + } + + + if (!canUseRule(conversationId)) { + return@subscribe + } + + event.addCallbackResult("onSuccess") { args -> + context.coroutineScope.launch { + delay(100) + + val messageId = try { + context.database.getMessagesFromConversationId(conversationId, 1)?.firstOrNull()?.clientMessageId?.toLong() + } catch (e: Exception) { + context.log.warn("Failed to query database for latest message: ${e.message}") + null + } + + if (messageId == null) { + return@launch + } + + val messageKey = "$conversationId:$messageId" + pendingDeletions[messageKey] = messageId + + if (showCountdown || showNotification) { + val countdownState = mutableStateOf(deleteAfterSeconds) + countdownStates[messageKey] = countdownState + + if (showNotification) { + showDeleteNotification(messageKey, deleteAfterSeconds) + } + + if (showCountdown) { + Handler(Looper.getMainLooper()).post { + activeViews[messageKey]?.let { view -> + view.findViewWithTag(countdownTag)?.let { view.removeView(it) } + addCountdownToView(view, messageKey) + } + } + } + + for (i in deleteAfterSeconds downTo 1) { + if (!pendingDeletions.containsKey(messageKey)) { + break + } + + + Handler(Looper.getMainLooper()).post { + countdownState.value = i + } + + if (showNotification && (i % 10 == 0 || i <= 10)) { + updateDeleteNotification(messageKey, i) + } + + delay(1000) + } + + Handler(Looper.getMainLooper()).post { + countdownStates.remove(messageKey) + activeViews.remove(messageKey) + if (showNotification) { + cancelNotification(messageKey) + } + } + } else { + delay(deleteAfterSeconds * 1000L) + } + + if (!pendingDeletions.containsKey(messageKey)) return@launch + + if (showNotification) { + cancelNotification(messageKey) + } + + deleteMessage(conversationId, messageId, messageKey) + } + } + } + } + + private fun addCountdownToView(view: ViewGroup, messageKey: String) { + val countdownState = countdownStates[messageKey] + if (countdownState != null && countdownState.value > 0) { + createComposeView(view.context) { + val remainingTime by countdownState + + if (remainingTime > 0) { + Box( + modifier = Modifier + .fillMaxWidth() + .padding(4.dp), + contentAlignment = Alignment.CenterEnd + ) { + Box( + modifier = Modifier + .background( + Color.Red.copy(alpha = 0.8f), + RoundedCornerShape(12.dp) + ) + .padding(horizontal = 8.dp, vertical = 4.dp) + ) { + val timeText = when { + remainingTime >= 3600 -> { + val hours = remainingTime / 3600 + val minutes = (remainingTime % 3600) / 60 + val seconds = remainingTime % 60 + when { + minutes == 0 && seconds == 0 -> "${hours}h" + seconds == 0 -> "${hours}h ${minutes}m" + else -> "${hours}h ${minutes}m ${seconds}s" + } + } + remainingTime >= 60 -> { + val minutes = remainingTime / 60 + val seconds = remainingTime % 60 + if (seconds == 0) "${minutes}m" else "${minutes}m ${seconds}s" + } + else -> "${remainingTime}s" + } + + Text( + text = "Deleting in $timeText", + color = Color.White, + fontSize = 12.sp, + fontWeight = FontWeight.Medium + ) + } + } + } + }.apply { + tag = countdownTag + layoutParams = LinearLayout.LayoutParams( + LinearLayout.LayoutParams.MATCH_PARENT, + LinearLayout.LayoutParams.WRAP_CONTENT + ) + view.addView(this) + } + } + } + + private fun setupNotificationChannel() { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + val notificationManager = context.androidContext.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager + val channel = NotificationChannel( + notificationChannelId, + "Auto Delete Messages", + NotificationManager.IMPORTANCE_LOW + ).apply { + description = "Notifications for auto-deleting messages" + setShowBadge(false) + enableVibration(false) + setSound(null, null) + } + notificationManager.createNotificationChannel(channel) + } + } + + private fun showDeleteNotification(messageKey: String, remainingSeconds: Int) { + val notificationManager = context.androidContext.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager + val timeText = formatTime(remainingSeconds) + + val notification = NotificationCompat.Builder(context.androidContext, notificationChannelId) + .setSmallIcon(android.R.drawable.ic_delete) + .setContentTitle("Message Auto-Delete") + .setContentText("Message will be deleted in $timeText") + .setProgress(remainingSeconds, remainingSeconds, false) + .setOngoing(true) + .setSilent(true) + .setAutoCancel(false) + .setColor(0xFFE53E3E.toInt()) + .setStyle(NotificationCompat.BigTextStyle() + .bigText("Your message will be automatically deleted in $timeText. This notification will update as the countdown progresses.")) + .build() + + notificationManager.notify(getNotificationId(messageKey), notification) + } + + private fun updateDeleteNotification(messageKey: String, remainingSeconds: Int) { + val notificationManager = context.androidContext.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager + val timeText = formatTime(remainingSeconds) + val initialTime = countdownStates[messageKey]?.value ?: remainingSeconds + + val notification = NotificationCompat.Builder(context.androidContext, notificationChannelId) + .setSmallIcon(android.R.drawable.ic_delete) + .setContentTitle("Message Auto-Delete") + .setContentText("Message will be deleted in $timeText") + .setProgress(initialTime, initialTime - remainingSeconds, false) + .setOngoing(true) + .setSilent(true) + .setAutoCancel(false) + .setColor(if (remainingSeconds <= 10) 0xFFFF0000.toInt() else 0xFFE53E3E.toInt()) + .setStyle(NotificationCompat.BigTextStyle() + .bigText("Your message will be automatically deleted in $timeText${if (remainingSeconds <= 10) "🕒" else ""}")) + .build() + + notificationManager.notify(getNotificationId(messageKey), notification) + } + + private fun cancelNotification(messageKey: String) { + val notificationManager = context.androidContext.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager + notificationManager.cancel(getNotificationId(messageKey)) + } + + private fun getNotificationId(messageKey: String): Int { + return (notificationChannelId + messageKey).hashCode() + } + + private fun formatTime(seconds: Int): String { + return when { + seconds >= 3600 -> { + val hours = seconds / 3600 + val minutes = (seconds % 3600) / 60 + val secs = seconds % 60 + when { + minutes == 0 && secs == 0 -> "${hours}h" + secs == 0 -> "${hours}h ${minutes}m" + else -> "${hours}h ${minutes}m ${secs}s" + } + } + seconds >= 60 -> { + val minutes = seconds / 60 + val secs = seconds % 60 + if (secs == 0) "${minutes}m" else "${minutes}m ${secs}s" + } + else -> "${seconds}s" + } + } + + private fun deleteMessage(conversationId: String, messageId: Long, messageKey: String) { + val conversationManager = context.feature(Messaging::class).conversationManager + if (conversationManager == null) { + pendingDeletions.remove(messageKey) + return + } + + conversationManager.updateMessage( + conversationId, + messageId, + MessageUpdate.ERASE + ) { error -> + pendingDeletions.remove(messageKey) + activeViews.remove(messageKey) + + Handler(Looper.getMainLooper()).post { + if (error == null) { + context.shortToast(translation.get("delete_success_toast")) + } else { + context.shortToast(translation.get("delete_failed_toast")) + } + } + } + } + + private fun updatePersistentNotification() { + val notificationManager = context.androidContext.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager + val queueSize = pendingDeletions.size + + + notificationManager.cancel(9999) + return + } + + private fun clearAllPendingDeletions() { + pendingDeletions.clear() + countdownStates.clear() + activeViews.clear() + + val notificationManager = context.androidContext.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager + notificationManager.cancel(9999) + + Handler(Looper.getMainLooper()).post { + context.shortToast("Auto delete queue cleared") + } + } +} diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/messaging/AutoMarkAsRead.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/messaging/AutoMarkAsRead.kt similarity index 88% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/messaging/AutoMarkAsRead.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/messaging/AutoMarkAsRead.kt index 6845a2e2..7fc9b1db 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/messaging/AutoMarkAsRead.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/messaging/AutoMarkAsRead.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.core.features.impl.messaging +package me.eternal.purrfectsnap.core.features.impl.messaging import android.widget.ProgressBar import androidx.compose.material.icons.Icons @@ -7,19 +7,19 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job import kotlinx.coroutines.delay import kotlinx.coroutines.launch -import me.rhunk.snapenhance.common.data.ContentType -import me.rhunk.snapenhance.common.data.MessageUpdate -import me.rhunk.snapenhance.core.event.events.impl.OnSnapInteractionEvent -import me.rhunk.snapenhance.core.event.events.impl.SendMessageWithContentEvent -import me.rhunk.snapenhance.core.features.Feature -import me.rhunk.snapenhance.core.features.impl.spying.StealthMode -import me.rhunk.snapenhance.core.ui.ViewAppearanceHelper -import me.rhunk.snapenhance.core.util.CallbackBuilder -import me.rhunk.snapenhance.core.util.hook.HookStage -import me.rhunk.snapenhance.core.util.hook.hook -import me.rhunk.snapenhance.core.util.ktx.getObjectFieldOrNull -import me.rhunk.snapenhance.core.wrapper.impl.SnapUUID -import me.rhunk.snapenhance.mapper.impl.CallbackMapper +import me.eternal.purrfectsnap.common.data.ContentType +import me.eternal.purrfectsnap.common.data.MessageUpdate +import me.eternal.purrfectsnap.core.event.events.impl.OnSnapInteractionEvent +import me.eternal.purrfectsnap.core.event.events.impl.SendMessageWithContentEvent +import me.eternal.purrfectsnap.core.features.Feature +import me.eternal.purrfectsnap.core.features.impl.spying.StealthMode +import me.eternal.purrfectsnap.core.ui.ViewAppearanceHelper +import me.eternal.purrfectsnap.core.util.CallbackBuilder +import me.eternal.purrfectsnap.core.util.hook.HookStage +import me.eternal.purrfectsnap.core.util.hook.hook +import me.eternal.purrfectsnap.core.util.ktx.getObjectFieldOrNull +import me.eternal.purrfectsnap.core.wrapper.impl.SnapUUID +import me.eternal.purrfectsnap.mapper.impl.CallbackMapper import kotlin.coroutines.resume import kotlin.coroutines.suspendCoroutine import kotlin.random.Random diff --git a/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/messaging/AutoRead.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/messaging/AutoRead.kt new file mode 100644 index 00000000..2cb3c657 --- /dev/null +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/messaging/AutoRead.kt @@ -0,0 +1,92 @@ +package me.eternal.purrfectsnap.core.features.impl.messaging + +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import me.eternal.purrfectsnap.common.data.ContentType +import me.eternal.purrfectsnap.common.data.MessagingRuleType +import me.eternal.purrfectsnap.core.event.events.impl.ConversationUpdateEvent +import me.eternal.purrfectsnap.core.features.MessagingRuleFeature +import java.util.concurrent.ConcurrentHashMap + +class AutoRead : MessagingRuleFeature("Auto Read", MessagingRuleType.AUTO_READ) { + private val lastMarked = ConcurrentHashMap() + + override fun init() { + context.event.subscribe(ConversationUpdateEvent::class) { event -> + if (!canUseRule(event.conversationId)) return@subscribe + if (!shouldMarkConversation(event)) return@subscribe + val now = System.currentTimeMillis() + val last = lastMarked[event.conversationId] ?: 0L + if (now - last < 1000L) return@subscribe + lastMarked[event.conversationId] = now + context.coroutineScope.launch(Dispatchers.IO) { + markUnreadMessages(event.conversationId) + } + } + } + + private suspend fun markUnreadMessages(conversationId: String) { + runCatching { + val messaging = context.feature(Messaging::class) + val conversationManager = messaging.conversationManager ?: return + val autoMark = context.feature(AutoMarkAsRead::class) + val myId = context.database.myUserId + val unread = collectUnreadMessages(conversationId, myId) + if (unread.isEmpty()) return + val chatIds = mutableSetOf() + val snapIds = mutableSetOf() + unread.forEach { message -> + val messageId = message.clientMessageId.toLong() + when (ContentType.fromId(message.contentType)) { + ContentType.SNAP, + ContentType.TINY_SNAP, + ContentType.EXTERNAL_MEDIA -> snapIds.add(messageId) + else -> chatIds.add(messageId) + } + } + chatIds.sorted().forEach { id -> + conversationManager.displayedMessages(conversationId, id) { + if (it != null) { + context.log.warn("AutoRead failed to mark chat message $id in $conversationId: $it") + } + } + } + snapIds.sorted().forEach { id -> + val error = autoMark.markSnapAsSeen(conversationId, id) + if (error != null && error != "DUPLICATEREQUEST") { + context.log.warn("AutoRead failed to mark snap $id in $conversationId: $error") + } + } + }.onFailure { + context.log.error("AutoRead failed to mark conversation $conversationId", it) + } + } + + private fun collectUnreadMessages(conversationId: String, myId: String): List { + val unread = LinkedHashSet() + val pageSize = 200 + val maxPages = 5 + var page = 0 + while (page < maxPages) { + val messages = context.database.getMessagesFromConversationId(conversationId, pageSize, page) ?: break + if (messages.isEmpty()) break + val filtered = messages.filter { message -> + message.senderId != myId && message.isViewedByUser == 0 + } + unread.addAll(filtered) + if (messages.size < pageSize) break + page++ + } + return unread.toList() + } + + private fun shouldMarkConversation(event: ConversationUpdateEvent): Boolean { + val myId = context.database.myUserId + return event.messages.any { + val senderId = it.senderId?.toString() ?: return@any false + if (senderId == myId) return@any false + it.messageMetadata?.openedBy?.none { uuid -> uuid.toString() == myId } == true + } + } +} + diff --git a/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/messaging/AutoReply.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/messaging/AutoReply.kt new file mode 100644 index 00000000..14802de0 --- /dev/null +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/messaging/AutoReply.kt @@ -0,0 +1,1092 @@ +package me.eternal.purrfectsnap.core.features.impl.messaging + +import me.eternal.purrfectsnap.common.data.ContentType +import me.eternal.purrfectsnap.common.data.MessagingRuleType +import me.eternal.purrfectsnap.common.data.MessageState +import me.eternal.purrfectsnap.core.event.events.impl.BuildMessageEvent +import me.eternal.purrfectsnap.core.event.events.impl.ConversationUpdateEvent +import me.eternal.purrfectsnap.core.features.MessagingRuleFeature +import me.eternal.purrfectsnap.core.features.impl.spying.HalfSwipeNotifier +import me.eternal.purrfectsnap.core.util.hook.HookStage +import me.eternal.purrfectsnap.core.util.hook.hook +import me.eternal.purrfectsnap.core.util.hook.hookConstructor +import me.eternal.purrfectsnap.core.wrapper.impl.Message +import me.eternal.purrfectsnap.core.wrapper.impl.SnapUUID +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.delay +import kotlinx.coroutines.launch +import kotlinx.coroutines.sync.Mutex +import kotlinx.coroutines.sync.withLock +import java.util.concurrent.ConcurrentHashMap +import java.util.concurrent.CopyOnWriteArraySet +import java.util.concurrent.atomic.AtomicLong +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import com.google.gson.JsonParser +import com.google.gson.JsonObject +import com.google.gson.JsonArray +import me.eternal.purrfectsnap.core.wrapper.impl.MessageContent +import me.eternal.purrfectsnap.core.wrapper.impl.getMessageText +import okhttp3.MediaType.Companion.toMediaType +import okhttp3.OkHttpClient +import okhttp3.Request +import okhttp3.RequestBody.Companion.toRequestBody +import java.util.LinkedList +import java.net.URL +import java.net.HttpURLConnection +import java.io.OutputStreamWriter +import java.io.BufferedReader +import java.io.InputStreamReader +import java.io.IOException +import kotlinx.coroutines.withTimeout +import kotlinx.coroutines.withContext + +class AutoReply : MessagingRuleFeature("Auto Reply", MessagingRuleType.AUTO_REPLY) { + companion object { + private const val MAX_PROCESSED_MESSAGES = 5000 + private const val MAX_MESSAGE_INDICES = 500 + private const val CLEANUP_INTERVAL_MS = 180000L + private const val COOLDOWN_CLEANUP_THRESHOLD_MS = 24 * 60 * 60 * 1000L + private const val DEFAULT_FALLBACK_MESSAGE = "I'm currently away and will respond soon!" + private const val MAX_CONVERSATION_HISTORY = 200 + private const val MAX_RECENT_RESPONSES = 20 + private const val RESPONSE_SIMILARITY_THRESHOLD = 0.75 + } + + private val processedMessages = CopyOnWriteArraySet() + private val conversationCooldowns = ConcurrentHashMap() + private val activeConversations = CopyOnWriteArraySet() + private val messageIndices = ConcurrentHashMap() + private val lastCleanup = AtomicLong(System.currentTimeMillis()) + + private val cooldownMutex = Mutex() + private val indicesMutex = Mutex() + private val messageProcessingMutex = Mutex() + + private val gson = Gson() + private val messagingFeature by lazy { context.feature(Messaging::class) } + private val httpClient by lazy { OkHttpClient.Builder().build() } + private val historyMutex = Mutex() + private val responseMutex = Mutex() + private val conversationHistory = ConcurrentHashMap>() + private val recentResponses = ConcurrentHashMap>() + private val responseVariations = ConcurrentHashMap() + private val conversationPersonality = ConcurrentHashMap() + + private fun detectStoryContentType(messageContent: MessageContent?): ContentType? { + if (messageContent?.content == null) return null + + try { + val protoReader = me.eternal.purrfectsnap.common.util.protobuf.ProtoReader(messageContent.content!!) + + if (protoReader.contains(7)) { + return ContentType.STORY_REPLY + } + + if (protoReader.contains(5)) { + protoReader.followPath(5)?.let { share -> + if (share.contains(16)) { + return ContentType.SHARE + } + } + } + + if (protoReader.contains(3)) { + protoReader.followPath(3)?.let { external -> + if (external.contains(7) || external.contains(5)) { + val storyText = protoReader.getString(7, 11, 1) + if (storyText != null) { + return ContentType.STORY_REPLY + } + } + } + } + + return null + } catch (e: Exception) { + context.log.error("Error detecting story content type", e) + return null + } + } + + private suspend fun canSendAutoReply( + conversationId: String, + messageTime: Long? = null, + isHalfSwipe: Boolean = false + ): Boolean { + val config = context.config.messaging.autoReply + val currentTime = System.currentTimeMillis() + + try { + if (config.globalState != true) { + return false + } + + if (!canUseRule(conversationId)) { + return false + } + + if (activeConversations.contains(conversationId)) { + return false + } + + val cooldownMs = config.cooldownSeconds.get() * 1000L + cooldownMutex.withLock { + val lastReplyTime = conversationCooldowns[conversationId] ?: 0 + if (currentTime - lastReplyTime < cooldownMs) { + return false + } + } + + messageTime?.let { msgTime -> + val ageThresholdMs = config.messageAgeThreshold.get() * 1000L + if (currentTime - msgTime > ageThresholdMs) { + return false + } + } + + if (isHalfSwipe && !config.autoTriggerConfig.autoReplyContentTypes.get().contains("half_swipes")) { + return false + } + + return true + + } catch (e: Exception) { + context.log.error("Error in auto-reply validation", e) + return false + } + } + + private fun shouldReplyToContentType(contentType: ContentType?): Boolean { + val config = context.config.messaging.autoReply + val selectedContentTypes = config.autoTriggerConfig.autoReplyContentTypes.get() + + return when (contentType) { + ContentType.CHAT -> selectedContentTypes.contains("chat_messages") + ContentType.SNAP -> selectedContentTypes.contains("snap_messages") + ContentType.EXTERNAL_MEDIA -> selectedContentTypes.contains("external_media_messages") + ContentType.STICKER -> selectedContentTypes.contains("sticker_messages") + ContentType.TINY_SNAP -> selectedContentTypes.contains("tiny_snap_messages") + ContentType.MAP_REACTION -> selectedContentTypes.contains("map_reaction_messages") + ContentType.NOTE -> selectedContentTypes.contains("voice_note_messages") + ContentType.SHARE -> selectedContentTypes.contains("story_share_messages") + ContentType.STORY_REPLY -> selectedContentTypes.contains("story_reply_messages") + null, + ContentType.STATUS, + ContentType.UNKNOWN -> { + if (contentType == ContentType.STATUS) { + false + } else { + selectedContentTypes.contains("chat_messages") + } + } + else -> selectedContentTypes.contains("chat_messages") + } + } + + private fun parseMessageList(jsonString: String): List { + val input = jsonString.trim() + if (input.isBlank()) return listOf(DEFAULT_FALLBACK_MESSAGE) + + return try { + if (input.startsWith("[")) { + val type = object : TypeToken>() {}.type + val parsed = gson.fromJson>(input, type) ?: emptyList() + val filtered = parsed.filter { it.isNotBlank() } + if (filtered.isEmpty()) listOf(DEFAULT_FALLBACK_MESSAGE) else filtered + } else { + val single = runCatching { gson.fromJson(input, String::class.java) }.getOrElse { input }.trim() + if (single.isNotBlank()) listOf(single) else listOf(DEFAULT_FALLBACK_MESSAGE) + } + } catch (e: Exception) { + context.log.error("Failed to parse message list: $jsonString", e) + listOf(DEFAULT_FALLBACK_MESSAGE) + } + } + + private suspend fun getNextMessage(messageList: List, conversationId: String, contentType: String): String { + if (messageList.isEmpty()) { + return DEFAULT_FALLBACK_MESSAGE + } + + if (messageList.size == 1) { + return messageList[0] + } + + val key = "${conversationId}_${contentType}" + + return indicesMutex.withLock { + if (messageIndices.size > MAX_MESSAGE_INDICES) { + messageIndices.clear() + } + + val currentIndex = messageIndices.getOrDefault(key, 0) + val nextIndex = (currentIndex + 1) % messageList.size + + messageIndices[key] = nextIndex + messageList[currentIndex] + } + } + + override fun init() { + if (context.config.messaging.autoReply.globalState != true) { + return + } + + if (getRuleState() == null) return + + context.log.info("AutoReply - Initialized with content types: ${context.config.messaging.autoReply.autoTriggerConfig.autoReplyContentTypes.get()}") + + if (context.config.messaging.autoReply.allowRunningInBackground.get()) { + findClass("com.snapchat.client.duplex.DuplexClient\$CppProxy").apply { + hook("appStateChanged", HookStage.BEFORE) { param -> + if (param.arg(0).toString() == "INACTIVE") param.setResult(null) + } + hookConstructor(HookStage.AFTER) { param -> + methods.first { it.name == "appStateChanged" }.let { method -> + method.invoke(param.thisObject(), method.parameterTypes[0].enumConstants!!.first { it.toString() == "ACTIVE" }) + } + } + } + } + + context.event.subscribe(ConversationUpdateEvent::class, priority = 100) { event -> + val conversationId = event.conversationId + val currentTime = System.currentTimeMillis() + + try { + updateActiveConversations(conversationId) + processNewMessages(event, currentTime) + triggerCleanupIfNeeded(currentTime) + } catch (e: Exception) { + context.log.error("Error processing conversation update for auto-reply", e) + } + } + + context.event.subscribe(BuildMessageEvent::class, priority = 100) { event -> + val currentTime = System.currentTimeMillis() + + try { + if (event.message.messageState != MessageState.COMMITTED) return@subscribe + if (event.message.senderId?.toString() == context.database.myUserId) return@subscribe + + val conversationId = event.message.messageDescriptor?.conversationId?.toString() ?: return@subscribe + val messageId = event.message.messageDescriptor?.messageId ?: return@subscribe + val senderId = event.message.senderId?.toString() ?: return@subscribe + val messageTime = event.message.messageMetadata?.createdAt + val contentType = event.message.messageContent?.contentType + + val detectedContentType = detectStoryContentType(event.message.messageContent) ?: contentType + + if (!shouldReplyToContentType(detectedContentType)) { + return@subscribe + } + + context.coroutineScope.launch(Dispatchers.IO) { + try { + messageProcessingMutex.withLock { + if (processedMessages.contains(messageId)) return@launch + + if (!canSendAutoReply(conversationId, messageTime)) return@launch + + if (processedMessages.size > MAX_PROCESSED_MESSAGES) { + processedMessages.clear() + } + processedMessages.add(messageId) + } + + val aiCfg = context.config.messaging.autoReply.aiConfig + if (aiCfg.enableAiReplies.get() && aiCfg.aiUseConversationHistory.get()) { + val messageContent = extractMessageContent(event.message, detectedContentType) + addToConversationHistory(conversationId, messageContent, isFromMe = false, detectedContentType) + } + + val replyText = generateReply(event.message, senderId, conversationId, detectedContentType) + if (replyText.isNotEmpty()) { + sendAutoReply(conversationId, replyText) + if (aiCfg.enableAiReplies.get() && aiCfg.aiUseConversationHistory.get()) { + addToConversationHistory(conversationId, replyText, isFromMe = true, ContentType.CHAT) + } + updateCooldown(conversationId, currentTime) + } + } catch (e: Exception) { + context.log.error("Error processing BuildMessageEvent for auto-reply", e) + } + } + } catch (e: Exception) { + context.log.error("Error handling BuildMessageEvent for auto-reply", e) + } + } + + context.feature(HalfSwipeNotifier::class).addOnHalfSwipeListener { conversationId, userId, duration -> + context.coroutineScope.launch(Dispatchers.IO) { + try { + handleHalfSwipe(conversationId, userId, duration) + } catch (e: Exception) { + context.log.error("Error handling half-swipe auto-reply", e) + } + } + } + + context.coroutineScope.launch(Dispatchers.IO) { + while (true) { + try { + delay(CLEANUP_INTERVAL_MS) + performCleanup() + } catch (e: Exception) { + context.log.error("Error in auto-reply cleanup task", e) + } + } + } + } + + private fun updateActiveConversations(conversationId: String) { + val openedConversationId = messagingFeature.openedConversationUUID?.toString() + if (openedConversationId == conversationId) { + activeConversations.add(conversationId) + } else { + activeConversations.remove(conversationId) + } + } + + private fun processNewMessages(event: ConversationUpdateEvent, currentTime: Long) { + val conversationId = event.conversationId + val myUserId = context.database.myUserId + + context.coroutineScope.launch(Dispatchers.IO) { + try { + if (!canSendAutoReply(conversationId)) { + return@launch + } + + val sortedMessages = event.messages.sortedByDescending { it.messageMetadata?.createdAt ?: 0L } + + for (message in sortedMessages) { + try { + val messageId = message.messageDescriptor?.messageId ?: continue + val senderId = message.senderId?.toString() + val messageTime = message.messageMetadata?.createdAt + val messageContent = message.messageContent + val contentType = messageContent?.contentType + + if (senderId == myUserId) { + continue + } + + if (message.messageState != MessageState.COMMITTED) { + continue + } + + if (processedMessages.contains(messageId)) { + continue + } + + val detectedContentType = detectStoryContentType(messageContent) ?: contentType + + if (!shouldReplyToContentType(detectedContentType)) { + continue + } + + if (!canSendAutoReply(conversationId, messageTime)) { + continue + } + + processMessage(conversationId, message, currentTime, detectedContentType) + break + + } catch (e: Exception) { + context.log.error("Error processing individual message for auto-reply", e) + continue + } + } + } catch (e: Exception) { + context.log.error("Error processing new messages for auto-reply", e) + } + } + } + + private suspend fun processMessage(conversationId: String, message: Message, currentTime: Long, detectedContentType: ContentType? = null) { + val messageId = message.messageDescriptor?.messageId ?: return + val senderId = message.senderId?.toString() ?: return + + try { + messageProcessingMutex.withLock { + if (processedMessages.contains(messageId)) return + + if (processedMessages.size > MAX_PROCESSED_MESSAGES) { + processedMessages.clear() + } + processedMessages.add(messageId) + } + + val aiCfg = context.config.messaging.autoReply.aiConfig + if (aiCfg.enableAiReplies.get() && aiCfg.aiUseConversationHistory.get()) { + val messageContent = extractMessageContent(message, detectedContentType) + addToConversationHistory(conversationId, messageContent, isFromMe = false, detectedContentType) + } + + val replyText = generateReply(message, senderId, conversationId, detectedContentType) + if (replyText.isNotEmpty()) { + sendAutoReply(conversationId, replyText) + if (aiCfg.enableAiReplies.get() && aiCfg.aiUseConversationHistory.get()) { + addToConversationHistory(conversationId, replyText, isFromMe = true, ContentType.CHAT) + } + updateCooldown(conversationId, currentTime) + } + } catch (e: Exception) { + context.log.error("Error processing message for auto-reply", e) + } + } + + private suspend fun generateReply(message: Message, senderId: String, conversationId: String, detectedContentType: ContentType? = null): String { + val config = context.config.messaging.autoReply + + try { + val messageContent = message.messageContent + val contentType = detectedContentType ?: messageContent?.contentType + + + val messageListJson = when (contentType) { + ContentType.CHAT -> config.autoTriggerConfig.chatMessages.get() + ContentType.SNAP -> config.autoTriggerConfig.snapMessages.get() + ContentType.EXTERNAL_MEDIA -> config.autoTriggerConfig.externalMediaMessages.get() + ContentType.STICKER -> config.autoTriggerConfig.stickerMessages.get() + ContentType.TINY_SNAP -> config.autoTriggerConfig.tinySnapMessages.get() + ContentType.MAP_REACTION -> config.autoTriggerConfig.mapReactionMessages.get() + ContentType.NOTE -> config.autoTriggerConfig.voiceNoteMessages.get() + ContentType.SHARE -> config.autoTriggerConfig.storyShareMessages.get() + ContentType.STORY_REPLY -> config.autoTriggerConfig.storyReplyMessages.get() + else -> config.autoTriggerConfig.chatMessages.get() + } + val messageList = parseMessageList(messageListJson) + val contentTypeName = contentType?.name ?: "CHAT" + val baseMessage = getNextMessage(messageList, conversationId, contentTypeName) + val withGreeting = if (config.autoTriggerConfig.friendSpecificGreeting.get()) { + val friendInfo = context.database.getFriendInfo(senderId) + val friendName = friendInfo?.displayName ?: friendInfo?.mutableUsername ?: "Friend" + val greeting = config.autoTriggerConfig.friendGreeting.get().takeIf { it.isNotBlank() } ?: "Hey" + "$greeting $friendName! $baseMessage" + } else { + baseMessage + } + + val aiCfg = config.aiConfig + if (aiCfg.enableAiReplies.get()) { + return generateAiReply(message, senderId, conversationId, detectedContentType, withGreeting) + } + return withGreeting + } catch (e: Exception) { + context.log.error("Error generating auto-reply message", e) + return DEFAULT_FALLBACK_MESSAGE + } + } + + private suspend fun generateAiReply(message: Message, senderId: String, conversationId: String, detectedContentType: ContentType?, fallback: String): String { + val ai = context.config.messaging.autoReply.aiConfig + val provider = ai.aiProvider.get() + val apiKey = ai.aiApiKey.get().trim() + val model = when (provider) { + "deepseek" -> ai.aiModel.get().ifBlank { "deepseek-chat" } + "openai" -> ai.aiModel.get().ifBlank { "gpt-4o-mini" } + else -> ai.aiModel.get().ifBlank { "gemini-2.5-flash" } + } + val timeoutSec = ai.aiRequestTimeout.get() + val maxRetries = ai.aiRetryAttempts.get() + val temp = (ai.aiTemperature.get().toDoubleOrNull() ?: 0.7).coerceIn(0.0, 2.0) + val maxTokens = ai.aiMaxTokens.get() + + if (apiKey.isBlank()) { + context.log.warn("AI reply skipped: missing API key for $provider") + return if (ai.aiFallbackToTemplate.get()) fallback else "" + } + + val messages = if (ai.aiUseConversationHistory.get()) { + buildAIMessages(conversationId, senderId, message, detectedContentType) + } else { + val systemPrompt = buildSystemPrompt(senderId, detectedContentType, context.config.messaging.autoReply) + val currentContent = extractMessageContent(message, detectedContentType) + val formattedContent = formatMessageForAI(currentContent, detectedContentType) + listOf( + AIMessage("system", systemPrompt), + AIMessage("user", formattedContent) + ) + } + + suspend fun makeRequest(): String = withTimeout(timeoutSec * 1000L) { + withContext(Dispatchers.IO) { + when (provider) { + "deepseek", "openai" -> { + val payload = JsonObject().apply { + addProperty("model", model) + add("messages", JsonArray().apply { + messages.forEach { msg -> + add(JsonObject().apply { + addProperty("role", msg.role) + addProperty("content", msg.content) + }) + } + }) + if (maxTokens > 0) addProperty("max_tokens", maxTokens) + addProperty("temperature", temp) + } + val body = payload.toString() + val apiUrl = if (provider == "openai") "https://api.openai.com/v1/chat/completions" else "https://api.deepseek.com/v1/chat/completions" + val req = Request.Builder() + .url(apiUrl) + .addHeader("Authorization", "Bearer $apiKey") + .addHeader("Content-Type", "application/json") + .post(body.toRequestBody("application/json".toMediaType())) + .build() + httpClient.newCall(req).execute().use { resp -> + val respBody = resp.body?.string().orEmpty() + if (!resp.isSuccessful) throw Throwable(if (resp.code == 401) "$provider HTTP 401 (check API key)" else "$provider HTTP ${resp.code}: ${respBody.take(200)}") + val json = JsonParser.parseString(respBody).asJsonObject + json.getAsJsonArray("choices")?.firstOrNull()?.asJsonObject + ?.getAsJsonObject("message")?.get("content")?.asString?.trim().orEmpty() + } + } + else -> { + val systemPrompt = messages.firstOrNull { it.role == "system" }?.content ?: "" + val userMessages = messages.filter { it.role == "user" }.joinToString("\n") { it.content } + val combinedText = "$systemPrompt\n$userMessages" + val payload = JsonObject().apply { + val parts = JsonArray().apply { + add(JsonObject().apply { addProperty("text", combinedText) }) + } + val contents = JsonArray().apply { + add(JsonObject().apply { add("parts", parts) }) + } + add("contents", contents) + } + val body = payload.toString() + val req = Request.Builder() + .url("https://generativelanguage.googleapis.com/v1beta/models/$model:generateContent") + .addHeader("x-goog-api-key", apiKey) + .addHeader("Content-Type", "application/json") + .post(body.toRequestBody("application/json".toMediaType())) + .build() + httpClient.newCall(req).execute().use { resp -> + val respBody = resp.body?.string().orEmpty() + if (!resp.isSuccessful) throw Throwable(if (resp.code == 401) "Gemini HTTP 401 (check API key)" else "Gemini HTTP ${resp.code}: ${respBody.take(200)}") + val json = JsonParser.parseString(respBody).asJsonObject + val candidates = json.getAsJsonArray("candidates") + val content = candidates?.firstOrNull()?.asJsonObject?.getAsJsonObject("content") + content?.getAsJsonArray("parts")?.firstOrNull()?.asJsonObject?.get("text")?.asString?.trim().orEmpty() + } + } + } + } + } + + var lastError: Throwable? = null + repeat(maxRetries + 1) { attempt -> + val result = runCatching { + makeRequest() + }.getOrElse { err -> + lastError = err + context.log.warn("AI reply attempt ${attempt + 1} failed for provider $provider model $model timeout ${timeoutSec}s conversation $conversationId: ${err.localizedMessage}; ${err.stackTraceToString()}") + if (attempt < maxRetries) { + delay(1000L * (attempt + 1)) + null + } else { + null + } + } + if (result != null) { + val response = result.ifBlank { if (ai.aiFallbackToTemplate.get()) fallback else "" } + if (response.isNotEmpty()) { + return response + } + } + } + + context.log.warn("AI reply failed after ${maxRetries + 1} attempts: ${lastError?.message}") + return if (ai.aiFallbackToTemplate.get()) fallback else "" + } + + private suspend fun handleHalfSwipe(conversationId: String, userId: String, duration: Long) { + val currentTime = System.currentTimeMillis() + + try { + if (!canSendAutoReply(conversationId, currentTime, isHalfSwipe = true)) { + return + } + + val config = context.config.messaging.autoReply + val halfSwipeMessages = parseMessageList(config.autoTriggerConfig.halfSwipeMessages.get()) + val baseMessage = getNextMessage(halfSwipeMessages, conversationId, "HALF_SWIPE") + + val withGreeting = if (config.autoTriggerConfig.friendSpecificGreeting.get()) { + val friendInfo = context.database.getFriendInfo(userId) + val friendName = friendInfo?.displayName ?: friendInfo?.mutableUsername ?: "Friend" + val greeting = config.autoTriggerConfig.friendGreeting.get().takeIf { it.isNotBlank() } ?: "Hey" + "$greeting $friendName! $baseMessage" + } else { + baseMessage + } + + val aiCfg = config.aiConfig + val replyText = if (aiCfg.enableAiReplies.get()) { + generateAiReplyForHalfSwipe(userId, conversationId, withGreeting) + } else { + withGreeting + } + + if (replyText.isNotEmpty()) { + sendAutoReply(conversationId, replyText) + if (aiCfg.enableAiReplies.get() && aiCfg.aiUseConversationHistory.get()) { + addToConversationHistory(conversationId, replyText, isFromMe = true, ContentType.CHAT) + } + updateCooldown(conversationId, currentTime) + } + + } catch (e: Exception) { + context.log.error("Error handling half-swipe auto-reply", e) + } + } + + private suspend fun generateAiReplyForHalfSwipe(senderId: String, conversationId: String, fallback: String): String { + val ai = context.config.messaging.autoReply.aiConfig + val provider = ai.aiProvider.get() + val apiKey = ai.aiApiKey.get().trim() + val model = when (provider) { + "deepseek" -> ai.aiModel.get().ifBlank { "deepseek-chat" } + "openai" -> ai.aiModel.get().ifBlank { "gpt-4o-mini" } + else -> ai.aiModel.get().ifBlank { "gemini-2.5-flash" } + } + val timeoutSec = ai.aiRequestTimeout.get() + val maxRetries = ai.aiRetryAttempts.get() + val temp = (ai.aiTemperature.get().toDoubleOrNull() ?: 0.7).coerceIn(0.0, 2.0) + val maxTokens = ai.aiMaxTokens.get() + + if (apiKey.isBlank()) { + context.log.warn("AI reply skipped: missing API key for $provider") + return if (ai.aiFallbackToTemplate.get()) fallback else "" + } + + val systemPrompt = buildSystemPrompt(senderId, null, context.config.messaging.autoReply, isHalfSwipe = true) + val userPrompt = "They half-swiped on your conversation (peeked at your chat without opening it)." + + val messages = if (ai.aiUseConversationHistory.get()) { + val messagesList = mutableListOf() + messagesList.add(AIMessage("system", systemPrompt)) + historyMutex.withLock { + val history = conversationHistory[conversationId] ?: LinkedList() + val contextLength = ai.aiContextLength.get() + val recentMessages = history.takeLast(contextLength) + for (historyMessage in recentMessages) { + val role = if (historyMessage.isFromMe) "assistant" else "user" + val messageContent = formatMessageForAI(historyMessage.content, historyMessage.contentType) + messagesList.add(AIMessage(role, messageContent)) + } + } + messagesList.add(AIMessage("user", userPrompt)) + messagesList + } else { + listOf( + AIMessage("system", systemPrompt), + AIMessage("user", userPrompt) + ) + } + + suspend fun makeRequest(): String = withTimeout(timeoutSec * 1000L) { + withContext(Dispatchers.IO) { + when (provider) { + "deepseek", "openai" -> { + val payload = JsonObject().apply { + addProperty("model", model) + add("messages", JsonArray().apply { + messages.forEach { msg -> + add(JsonObject().apply { + addProperty("role", msg.role) + addProperty("content", msg.content) + }) + } + }) + if (maxTokens > 0) addProperty("max_tokens", maxTokens) + addProperty("temperature", temp) + } + val body = payload.toString() + val apiUrl = if (provider == "openai") "https://api.openai.com/v1/chat/completions" else "https://api.deepseek.com/v1/chat/completions" + val req = Request.Builder() + .url(apiUrl) + .addHeader("Authorization", "Bearer $apiKey") + .addHeader("Content-Type", "application/json") + .post(body.toRequestBody("application/json".toMediaType())) + .build() + httpClient.newCall(req).execute().use { resp -> + val respBody = resp.body?.string().orEmpty() + if (!resp.isSuccessful) throw Throwable(if (resp.code == 401) "$provider HTTP 401 (check API key)" else "$provider HTTP ${resp.code}: ${respBody.take(200)}") + val json = JsonParser.parseString(respBody).asJsonObject + json.getAsJsonArray("choices")?.firstOrNull()?.asJsonObject + ?.getAsJsonObject("message")?.get("content")?.asString?.trim().orEmpty() + } + } + else -> { + val systemPromptText = messages.firstOrNull { it.role == "system" }?.content ?: "" + val userMessages = messages.filter { it.role == "user" }.joinToString("\n") { it.content } + val combinedText = "$systemPromptText\n$userMessages" + val payload = JsonObject().apply { + val parts = JsonArray().apply { + add(JsonObject().apply { addProperty("text", combinedText) }) + } + val contents = JsonArray().apply { + add(JsonObject().apply { add("parts", parts) }) + } + add("contents", contents) + } + val body = payload.toString() + val req = Request.Builder() + .url("https://generativelanguage.googleapis.com/v1beta/models/$model:generateContent") + .addHeader("x-goog-api-key", apiKey) + .addHeader("Content-Type", "application/json") + .post(body.toRequestBody("application/json".toMediaType())) + .build() + httpClient.newCall(req).execute().use { resp -> + val respBody = resp.body?.string().orEmpty() + if (!resp.isSuccessful) throw Throwable(if (resp.code == 401) "Gemini HTTP 401 (check API key)" else "Gemini HTTP ${resp.code}: ${respBody.take(200)}") + val json = JsonParser.parseString(respBody).asJsonObject + val candidates = json.getAsJsonArray("candidates") + val content = candidates?.firstOrNull()?.asJsonObject?.getAsJsonObject("content") + content?.getAsJsonArray("parts")?.firstOrNull()?.asJsonObject?.get("text")?.asString?.trim().orEmpty() + } + } + } + } + } + + var lastError: Throwable? = null + repeat(maxRetries + 1) { attempt -> + val result = runCatching { + makeRequest() + }.getOrElse { err -> + lastError = err + context.log.warn("AI half-swipe reply attempt ${attempt + 1} failed for provider $provider model $model timeout ${timeoutSec}s conversation $conversationId: ${err.localizedMessage}; ${err.stackTraceToString()}") + if (attempt < maxRetries) { + delay(1000L * (attempt + 1)) + null + } else { + null + } + } + if (result != null) { + val response = result.ifBlank { if (ai.aiFallbackToTemplate.get()) fallback else "" } + if (response.isNotEmpty()) { + return response + } + } + } + + context.log.warn("AI reply failed after ${maxRetries + 1} attempts: ${lastError?.message}") + return if (ai.aiFallbackToTemplate.get()) fallback else "" + } + + // === AI helper structures === + private data class AIMessage(val role: String, val content: String) + private data class ConversationMessage( + val content: String, + val isFromMe: Boolean, + val timestamp: Long, + val contentType: ContentType? + ) + private data class AIRequest(val model: String, val messages: List, val temperature: Double = 0.7) + private data class AIResponse(val choices: List) + private data class AIChoice(val message: AIMessage) + + private suspend fun buildAIMessages(conversationId: String, senderId: String, currentMessage: Message, contentType: ContentType?): List { + val config = context.config.messaging.autoReply + val messages = mutableListOf() + val systemPrompt = buildSystemPrompt(senderId, contentType, config) + messages.add(AIMessage("system", systemPrompt)) + if (config.aiConfig.aiUseConversationHistory.get()) { + historyMutex.withLock { + val history = conversationHistory[conversationId] ?: LinkedList() + val contextLength = config.aiConfig.aiContextLength.get() + val recentMessages = history.takeLast(contextLength) + for (historyMessage in recentMessages) { + val role = if (historyMessage.isFromMe) "assistant" else "user" + val messageContent = formatMessageForAI(historyMessage.content, historyMessage.contentType) + messages.add(AIMessage(role, messageContent)) + } + } + } + val currentContent = extractMessageContent(currentMessage, contentType) + if (currentContent.isNotEmpty()) messages.add(AIMessage("user", formatMessageForAI(currentContent, contentType))) + return messages + } + + private fun formatMessageForAI(content: String, contentType: ContentType?): String = when (contentType) { + ContentType.SNAP -> "sent a snap: $content" + ContentType.CHAT -> content + ContentType.EXTERNAL_MEDIA -> "shared media: $content" + ContentType.STICKER -> "sent a sticker: $content" + ContentType.NOTE -> "sent a note: $content" + ContentType.LOCATION -> "shared location: $content" + ContentType.LIVE_LOCATION_SHARE -> "shared live location: $content" + ContentType.FAMILY_CENTER_INVITE -> "family center message: $content" + else -> content + } + + private suspend fun buildSystemPrompt(senderId: String, contentType: ContentType?, config: me.eternal.purrfectsnap.common.config.impl.MessagingTweaks.AutoReplyConfig, isHalfSwipe: Boolean = false): String { + val responseLanguage = config.aiConfig.aiResponseLanguage.get() + val provider = config.aiConfig.aiProvider.get() + val strict = provider != "deepseek" + val languageInstruction = when (responseLanguage) { + "auto" -> if (strict) "Detect the incoming message language and reply strictly in that language without mixing other languages." else "Always respond in the same language as the message you received." + "en" -> if (strict) "Respond only in English with no words from other languages." else "Always respond in English." + "es" -> if (strict) "Respond only in Spanish with no words from other languages." else "Always respond in Spanish." + "fr" -> if (strict) "Respond only in French with no words from other languages." else "Always respond in French." + "de" -> if (strict) "Respond only in German with no words from other languages." else "Always respond in German." + "it" -> if (strict) "Respond only in Italian with no words from other languages." else "Always respond in Italian." + "pt" -> if (strict) "Respond only in Portuguese with no words from other languages." else "Always respond in Portuguese." + "ru" -> if (strict) "Respond only in Russian with no words from other languages." else "Always respond in Russian." + "ja" -> if (strict) "Respond only in Japanese with no words from other languages." else "Always respond in Japanese." + "ko" -> if (strict) "Respond only in Korean with no words from other languages." else "Always respond in Korean." + "zh" -> if (strict) "Respond only in Chinese with no words from other languages." else "Always respond in Chinese." + "ar" -> if (strict) "Respond only in Arabic using UAE (Emirati) and KSA (Saudi) dialect expressions with no words from other languages." else "Always respond in Arabic using UAE (Emirati) and KSA (Saudi) dialect and expressions. Use Gulf Arabic vocabulary and phrases common in the United Arab Emirates and Saudi Arabia." + "hi" -> if (strict) "Respond only in Hindi with no words from other languages." else "Always respond in Hindi." + "tr" -> if (strict) "Respond only in Turkish with no words from other languages." else "Always respond in Turkish." + "pl" -> if (strict) "Respond only in Polish with no words from other languages." else "Always respond in Polish." + "nl" -> if (strict) "Respond only in Dutch with no words from other languages." else "Always respond in Dutch." + "sv" -> if (strict) "Respond only in Swedish with no words from other languages." else "Always respond in Swedish." + "da" -> if (strict) "Respond only in Danish with no words from other languages." else "Always respond in Danish." + "no" -> if (strict) "Respond only in Norwegian with no words from other languages." else "Always respond in Norwegian." + "fi" -> if (strict) "Respond only in Finnish with no words from other languages." else "Always respond in Finnish." + else -> if (strict) "Detect the incoming message language and reply strictly in that language without mixing other languages." else "Always respond in the same language as the message you received." + } + val basePrompt = config.aiConfig.aiSystemPrompt.get().takeIf { it.isNotBlank() } + ?: "You are a helpful and friendly assistant responding to messages on Snapchat. Keep your responses natural, conversational, and appropriate for the platform. Respond as if you're a real person having a casual conversation. $languageInstruction" + val personalityTraits = config.aiConfig.aiPersonalityTraits.get() + val responseStyle = config.aiConfig.aiResponseStyle.get() + val prompt = StringBuilder(basePrompt) + if (personalityTraits.isNotBlank()) prompt.append("\n\nPersonality traits: $personalityTraits") + val styleInstruction = when (responseStyle) { + "casual" -> "Use a casual, relaxed, and conversational tone. Write naturally like you're texting a friend. Keep it informal but appropriate. Use contractions and everyday language." + "formal" -> "Use a formal, professional, and polite tone. Maintain proper grammar and structure. Address the recipient respectfully. Avoid slang and casual expressions." + "friendly" -> "Use a warm, friendly, and positive tone. Be enthusiastic and welcoming. Show genuine interest and kindness. Keep the conversation light and engaging." + "humorous" -> "Use a funny, witty, and lighthearted tone. Make jokes, use wordplay, and be playful. Keep it entertaining and fun while staying appropriate." + "empathetic" -> "Use a caring, understanding, and supportive tone. Show empathy and validate feelings. Be compassionate and patient. Offer comfort and reassurance when needed." + "toxic" -> "Use an extremely toxic, aggressive, sassy, slur, and confrontational tone. Be extremely rude, edgy, and disrespectful. Use heavy slang, internet slang, profanity, and extremely casual/informal language. Don't hold back - be mean, insulting, and purposely antagonistic. Use slang like 'bruh', 'fr', 'ngl', 'lowkey', 'highkey', 'deadass', 'cap', 'no cap', 'bet', 'facts', 'periodt', 'sis', 'slay', 'yass', 'stfu', 'gtfo', 'lmao', 'oof', etc. Be extremely sarcastic and use excessive emojis. Make it sound like the most toxic person on the internet. Be extremely confrontational and don't care about being polite at all." + "busy" -> "Use a brief, concise, and busy tone. Keep responses short and to the point. Indicate you're occupied or in a hurry. Use quick responses like 'brb', 'ttyl', 'gotta go', 'busy rn', etc. Be polite but brief. Don't elaborate unless necessary." + else -> "casual" + } + prompt.append("\n\nResponse style: $styleInstruction. $languageInstruction") + if (config.aiConfig.aiIncludeFriendInfo.get()) try { + context.database.getFriendInfo(senderId)?.let { friend -> + val friendName = friend.displayName ?: friend.mutableUsername ?: "Friend" + prompt.append("\n\nYou're responding to your friend $friendName.") + } + } catch (_: Exception) {} + if (isHalfSwipe) { + prompt.append("\n\nContext: They half-swiped on your conversation (peeked at your chat without opening it).") + } else { + contentType?.let { + val ctx = when (it) { + ContentType.SNAP -> "They sent you a snap (photo/video)." + ContentType.STORY_REPLY -> "They replied to your story." + ContentType.SHARE -> "They shared a story with you." + ContentType.EXTERNAL_MEDIA -> "They sent you media from their camera roll." + ContentType.STICKER -> "They sent you a sticker or Bitmoji." + ContentType.NOTE -> "They sent you a voice note." + ContentType.TINY_SNAP -> "They sent you a tiny snap." + ContentType.MAP_REACTION -> "They reacted to your location on the map." + ContentType.LOCATION -> "They shared their current location." + ContentType.LIVE_LOCATION_SHARE -> "They started sharing live location." + ContentType.CREATIVE_TOOL_ITEM -> "They sent you a creative tool item." + ContentType.FAMILY_CENTER_INVITE -> "They sent you a family center invite." + ContentType.STATUS -> "They sent you a status update." + ContentType.UNKNOWN -> "They sent you a message." + else -> "They sent you a chat message." + } + prompt.append("\n\nContext: $ctx") + } + } + prompt.append("\n\nImportant: Keep your response natural, authentic, and conversational. Avoid being overly formal or robotic. Keep responses reasonably brief unless the context calls for longer.") + return prompt.toString() + } + + private fun extractMessageContent(message: Message, contentType: ContentType?): String = try { + run { + val text = message.messageContent?.content?.let { buf -> + buf.getMessageText(contentType ?: ContentType.CHAT) + } + if (!text.isNullOrBlank() && text != "Failed to parse message") { + text + } else { + when (contentType) { + ContentType.CHAT -> "sent a text message" + ContentType.SNAP -> "sent a snap" + ContentType.STORY_REPLY -> "replied to your story" + ContentType.SHARE -> "shared a story with you" + ContentType.EXTERNAL_MEDIA -> "shared media content" + ContentType.STICKER -> "sent a sticker" + ContentType.NOTE -> "sent a voice note" + ContentType.TINY_SNAP -> "sent a tiny snap" + ContentType.MAP_REACTION -> "reacted to your location on the map" + ContentType.LOCATION -> "shared their location" + ContentType.LIVE_LOCATION_SHARE -> "started sharing live location" + else -> "sent a message" + } + } + } + } catch (e: Exception) { context.log.warn("Failed to extract message content: ${e.message}"); "sent a message" } + + private suspend fun addToConversationHistory(conversationId: String, content: String, isFromMe: Boolean, contentType: ContentType? = null) { + historyMutex.withLock { + val history = conversationHistory.getOrPut(conversationId) { LinkedList() } + history.add(ConversationMessage(content, isFromMe, System.currentTimeMillis(), contentType)) + while (history.size > MAX_CONVERSATION_HISTORY) history.removeFirst() + val cutoff = System.currentTimeMillis() - (24 * 60 * 60 * 1000L) + while (history.isNotEmpty() && history.first().timestamp < cutoff) history.removeFirst() + } + } + + private suspend fun analyzeConversationContext(conversationId: String): ConversationContext = historyMutex.withLock { + val history = conversationHistory[conversationId] ?: LinkedList() + val recent = history.takeLast(5) + val userMessages = recent.count { !it.isFromMe } + val myMessages = recent.count { it.isFromMe } + val tone = when { + recent.any { it.content.contains("?") } -> ConversationTone.QUESTIONING + recent.any { it.content.matches(Regex(".*[!]{2,}.*")) } -> ConversationTone.EXCITED + recent.any { it.content.lowercase().contains(Regex("(sad|sorry|upset|angry|mad)")) } -> ConversationTone.SERIOUS + recent.any { it.content.contains(Regex("(haha|lol|😂|😄|😊)")) } -> ConversationTone.PLAYFUL + else -> ConversationTone.CASUAL + } + val urgency = when { + recent.any { it.content.lowercase().contains(Regex("(urgent|asap|emergency|help|now)")) } -> ConversationUrgency.HIGH + recent.any { it.content.contains("?") && userMessages > myMessages } -> ConversationUrgency.MEDIUM + else -> ConversationUrgency.LOW + } + val types = recent.mapNotNull { it.contentType }.distinct() + ConversationContext( + messageCount = recent.size, + userToMyMessageRatio = if (myMessages > 0) userMessages.toDouble() / myMessages else userMessages.toDouble(), + tone = tone, + urgency = urgency, + dominantContentTypes = types, + lastMessageTimestamp = recent.lastOrNull()?.timestamp ?: 0L, + hasRecentMedia = types.any { it in listOf(ContentType.SNAP, ContentType.EXTERNAL_MEDIA, ContentType.STICKER) } + ) + } + + private data class ConversationContext( + val messageCount: Int, + val userToMyMessageRatio: Double, + val tone: ConversationTone, + val urgency: ConversationUrgency, + val dominantContentTypes: List, + val lastMessageTimestamp: Long, + val hasRecentMedia: Boolean + ) + private enum class ConversationTone { CASUAL, PLAYFUL, SERIOUS, EXCITED, QUESTIONING } + private enum class ConversationUrgency { LOW, MEDIUM, HIGH } + + private suspend fun trackResponse(conversationId: String, response: String) { + responseMutex.withLock { + val responses = recentResponses.getOrPut(conversationId) { LinkedList() } + responses.addFirst(response) + if (responses.size > MAX_RECENT_RESPONSES) responses.removeLast() + } + } + private suspend fun isResponseTooSimilar(conversationId: String, newResponse: String): Boolean = responseMutex.withLock { + recentResponses[conversationId]?.any { existing -> calculateSimilarity(newResponse, existing) > RESPONSE_SIMILARITY_THRESHOLD } ?: false + } + private fun calculateSimilarity(text1: String, text2: String): Double { + val w1 = text1.lowercase().split("\\s+".toRegex()).toSet() + val w2 = text2.lowercase().split("\\s+".toRegex()).toSet() + val inter = w1.intersect(w2).size + val uni = w1.union(w2).size + return if (uni == 0) 0.0 else inter.toDouble() / uni.toDouble() + } + private suspend fun generateVariedResponse(originalResponse: String, conversationId: String): String { + val count = responseVariations.getOrPut(conversationId) { 0 } + responseVariations[conversationId] = count + 1 + return when (count % 4) { + 0 -> addPersonalTouch(originalResponse) + 1 -> addEmotionalVariation(originalResponse) + 2 -> addCasualVariation(originalResponse) + else -> addContextualVariation(originalResponse, conversationId) + } + } + private fun addPersonalTouch(response: String) = listOf( + "Honestly, $response","You know what, $response","I gotta say, $response","Real talk, $response","Just being real here, $response" + ).random() + private fun addEmotionalVariation(response: String) = listOf( + "😊 $response","Haha $response","Oh! $response","Aww $response","$response 😄" + ).random() + private fun addCasualVariation(response: String) = listOf( + "Yo, $response","Hey, $response","Btw, $response","So... $response","Actually, $response" + ).random() + private suspend fun addContextualVariation(response: String, conversationId: String): String { + val personality = conversationPersonality.getOrPut(conversationId) { listOf("friendly","playful","thoughtful","energetic","chill").random() } + return when (personality) { + "friendly" -> "Hey friend! $response" + "playful" -> "Hehe $response 😜" + "thoughtful" -> "Hmm, $response" + "energetic" -> "$response! 🔥" + else -> response + } + } + + private suspend fun updateCooldown(conversationId: String, currentTime: Long) { + cooldownMutex.withLock { + conversationCooldowns[conversationId] = currentTime + } + } + + private fun sendAutoReply(conversationId: String, message: String) { + context.coroutineScope.launch(Dispatchers.IO) { + try { + context.messageSender.sendChatMessage( + conversations = listOf(SnapUUID(conversationId)), + message = message, + onSuccess = { + context.log.verbose("Auto-reply sent successfully") + }, + onError = { error -> + context.log.error("Failed to send auto-reply: $error") + } + ) + } catch (e: Exception) { + context.log.error("Failed to send auto-reply", e) + } + } + } + + private fun triggerCleanupIfNeeded(currentTime: Long) { + if (currentTime - lastCleanup.get() > CLEANUP_INTERVAL_MS) { + context.coroutineScope.launch(Dispatchers.IO) { + performCleanup() + } + } + } + + private suspend fun performCleanup() { + val currentTime = System.currentTimeMillis() + lastCleanup.set(currentTime) + + try { + if (processedMessages.size > MAX_PROCESSED_MESSAGES) { + processedMessages.clear() + } + + cooldownMutex.withLock { + conversationCooldowns.entries.removeIf { (_, timestamp) -> + currentTime - timestamp > COOLDOWN_CLEANUP_THRESHOLD_MS + } + } + + indicesMutex.withLock { + if (messageIndices.size > MAX_MESSAGE_INDICES) { + messageIndices.clear() + } + } + + } catch (e: Exception) { + context.log.error("Error during auto-reply cleanup", e) + } + } + + +} diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/messaging/AutoSave.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/messaging/AutoSave.kt similarity index 80% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/messaging/AutoSave.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/messaging/AutoSave.kt index 9cbfc06c..4e4556ab 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/messaging/AutoSave.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/messaging/AutoSave.kt @@ -1,18 +1,18 @@ -package me.rhunk.snapenhance.core.features.impl.messaging +package me.eternal.purrfectsnap.core.features.impl.messaging -import me.rhunk.snapenhance.common.data.MessageState -import me.rhunk.snapenhance.common.data.MessageUpdate -import me.rhunk.snapenhance.common.data.MessagingRuleType -import me.rhunk.snapenhance.core.event.events.impl.ConversationUpdateEvent -import me.rhunk.snapenhance.core.features.MessagingRuleFeature -import me.rhunk.snapenhance.core.features.impl.spying.MessageLogger -import me.rhunk.snapenhance.core.features.impl.spying.StealthMode -import me.rhunk.snapenhance.core.util.hook.HookStage -import me.rhunk.snapenhance.core.util.hook.hook -import me.rhunk.snapenhance.core.util.ktx.getObjectField -import me.rhunk.snapenhance.core.wrapper.impl.Message -import me.rhunk.snapenhance.core.wrapper.impl.SnapUUID -import me.rhunk.snapenhance.mapper.impl.CallbackMapper +import me.eternal.purrfectsnap.common.data.MessageState +import me.eternal.purrfectsnap.common.data.MessageUpdate +import me.eternal.purrfectsnap.common.data.MessagingRuleType +import me.eternal.purrfectsnap.core.event.events.impl.ConversationUpdateEvent +import me.eternal.purrfectsnap.core.features.MessagingRuleFeature +import me.eternal.purrfectsnap.core.features.impl.spying.MessageLogger +import me.eternal.purrfectsnap.core.features.impl.spying.StealthMode +import me.eternal.purrfectsnap.core.util.hook.HookStage +import me.eternal.purrfectsnap.core.util.hook.hook +import me.eternal.purrfectsnap.core.util.ktx.getObjectField +import me.eternal.purrfectsnap.core.wrapper.impl.Message +import me.eternal.purrfectsnap.core.wrapper.impl.SnapUUID +import me.eternal.purrfectsnap.mapper.impl.CallbackMapper import java.util.concurrent.Executors class AutoSave : MessagingRuleFeature("Auto Save", MessagingRuleType.AUTO_SAVE) { @@ -68,6 +68,7 @@ class AutoSave : MessagingRuleFeature("Auto Save", MessagingRuleType.AUTO_SAVE) } override fun init() { + if (getRuleState() == null) return onNextActivityCreate(defer = true) { // called when enter in a conversation context.mappings.useMapper(CallbackMapper::class) { @@ -104,4 +105,4 @@ class AutoSave : MessagingRuleFeature("Auto Save", MessagingRuleType.AUTO_SAVE) } } } -} \ No newline at end of file +} diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/messaging/BypassMessageActionRestrictions.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/messaging/BypassMessageActionRestrictions.kt similarity index 72% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/messaging/BypassMessageActionRestrictions.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/messaging/BypassMessageActionRestrictions.kt index 784c9ed1..42a9872c 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/messaging/BypassMessageActionRestrictions.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/messaging/BypassMessageActionRestrictions.kt @@ -1,7 +1,7 @@ -package me.rhunk.snapenhance.core.features.impl.messaging +package me.eternal.purrfectsnap.core.features.impl.messaging -import me.rhunk.snapenhance.core.event.events.impl.BuildMessageEvent -import me.rhunk.snapenhance.core.features.Feature +import me.eternal.purrfectsnap.core.event.events.impl.BuildMessageEvent +import me.eternal.purrfectsnap.core.features.Feature class BypassMessageActionRestrictions : Feature("Bypass Message Action Restrictions") { override fun init() { diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/messaging/CallButtonsOverride.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/messaging/CallButtonsOverride.kt similarity index 88% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/messaging/CallButtonsOverride.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/messaging/CallButtonsOverride.kt index 1238d3ee..34833807 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/messaging/CallButtonsOverride.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/messaging/CallButtonsOverride.kt @@ -1,16 +1,16 @@ -package me.rhunk.snapenhance.core.features.impl.messaging +package me.eternal.purrfectsnap.core.features.impl.messaging import android.view.MotionEvent import android.view.View import android.view.ViewGroup -import me.rhunk.snapenhance.core.event.events.impl.AddViewEvent -import me.rhunk.snapenhance.core.features.Feature -import me.rhunk.snapenhance.core.ui.ViewAppearanceHelper -import me.rhunk.snapenhance.core.ui.children -import me.rhunk.snapenhance.core.ui.hideViewCompletely -import me.rhunk.snapenhance.core.util.hook.HookAdapter -import me.rhunk.snapenhance.core.util.hook.HookStage -import me.rhunk.snapenhance.core.util.hook.hook +import me.eternal.purrfectsnap.core.event.events.impl.AddViewEvent +import me.eternal.purrfectsnap.core.features.Feature +import me.eternal.purrfectsnap.core.ui.ViewAppearanceHelper +import me.eternal.purrfectsnap.core.ui.children +import me.eternal.purrfectsnap.core.ui.hideViewCompletely +import me.eternal.purrfectsnap.core.util.hook.HookAdapter +import me.eternal.purrfectsnap.core.util.hook.HookStage +import me.eternal.purrfectsnap.core.util.hook.hook class CallButtonsOverride : Feature("CallButtonsOverride") { private fun hookTouchEvent(param: HookAdapter, motionEvent: MotionEvent, onConfirm: () -> Unit) { diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/messaging/DisableReplayInFF.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/messaging/DisableReplayInFF.kt similarity index 65% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/messaging/DisableReplayInFF.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/messaging/DisableReplayInFF.kt index 786e1b11..510c26b0 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/messaging/DisableReplayInFF.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/messaging/DisableReplayInFF.kt @@ -1,10 +1,10 @@ -package me.rhunk.snapenhance.core.features.impl.messaging +package me.eternal.purrfectsnap.core.features.impl.messaging -import me.rhunk.snapenhance.core.features.Feature -import me.rhunk.snapenhance.core.util.hook.HookStage -import me.rhunk.snapenhance.core.util.hook.hookConstructor -import me.rhunk.snapenhance.core.util.ktx.getObjectField -import me.rhunk.snapenhance.core.util.ktx.setEnumField +import me.eternal.purrfectsnap.core.features.Feature +import me.eternal.purrfectsnap.core.util.hook.HookStage +import me.eternal.purrfectsnap.core.util.hook.hookConstructor +import me.eternal.purrfectsnap.core.util.ktx.getObjectField +import me.eternal.purrfectsnap.core.util.ktx.setEnumField class DisableReplayInFF : Feature("DisableReplayInFF") { override fun init() { diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/messaging/HideTypingIndicator.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/messaging/HideTypingIndicator.kt similarity index 61% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/messaging/HideTypingIndicator.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/messaging/HideTypingIndicator.kt index ad4a8829..0c31e095 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/messaging/HideTypingIndicator.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/messaging/HideTypingIndicator.kt @@ -1,9 +1,9 @@ -package me.rhunk.snapenhance.core.features.impl.messaging +package me.eternal.purrfectsnap.core.features.impl.messaging -import me.rhunk.snapenhance.common.data.MessagingRuleType -import me.rhunk.snapenhance.core.features.MessagingRuleFeature -import me.rhunk.snapenhance.core.util.hook.HookStage -import me.rhunk.snapenhance.core.util.hook.hook +import me.eternal.purrfectsnap.common.data.MessagingRuleType +import me.eternal.purrfectsnap.core.features.MessagingRuleFeature +import me.eternal.purrfectsnap.core.util.hook.HookStage +import me.eternal.purrfectsnap.core.util.hook.hook class HideTypingIndicator : MessagingRuleFeature("Hide Typing Indicator", MessagingRuleType.HIDE_TYPING_INDICATOR) { private val messaging: Messaging by lazy { context.feature(Messaging::class) } @@ -15,4 +15,4 @@ class HideTypingIndicator : MessagingRuleFeature("Hide Typing Indicator", Messag it.setResult(null) } } -} \ No newline at end of file +} diff --git a/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/messaging/MessageTranslator.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/messaging/MessageTranslator.kt new file mode 100644 index 00000000..99279125 --- /dev/null +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/messaging/MessageTranslator.kt @@ -0,0 +1,146 @@ +package me.eternal.purrfectsnap.core.features.impl.messaging + + +import kotlinx.coroutines.launch +import me.eternal.purrfectsnap.common.data.ContentType +import me.eternal.purrfectsnap.common.util.protobuf.ProtoWriter +import me.eternal.purrfectsnap.core.event.events.impl.BuildMessageEvent +import me.eternal.purrfectsnap.core.features.Feature +import me.eternal.purrfectsnap.core.util.hook.HookStage +import me.eternal.purrfectsnap.core.util.hook.hook +import me.eternal.purrfectsnap.core.wrapper.impl.Message +import me.eternal.purrfectsnap.core.wrapper.impl.getMessageText + +class MessageTranslator : Feature("Instant Translation") { + private val translationManager by lazy { TranslationManager(context) } + private val config by lazy { context.config.messaging.instantTranslation } + private var isPaused = false + + private fun shouldTranslateMessage(message: Message): Boolean { + if (isPaused) return false + val contentType = message.messageContent?.contentType ?: return false + return contentType == ContentType.CHAT + } + + private fun getMessageText(message: Message): String? { + val content = message.messageContent?.content ?: return null + return content.getMessageText(ContentType.CHAT) + } + + private fun updateMessageText(message: Message, newText: String) { + val messageContent = message.messageContent ?: return + val newContent = ProtoWriter().apply { + from(2) { + addString(1, newText) + } + }.toByteArray() + + messageContent.content = newContent + } + + private fun createTranslatedDisplayText(originalText: String, translatedText: String, position: String): String { + return when (position) { + "inline" -> "$originalText ($translatedText)" + "above" -> "$translatedText\n$originalText" + "below" -> "$originalText\n$translatedText" + else -> "$originalText\n$translatedText" + } + } + + private fun createTranslatedText(originalText: String, translatedText: String, position: String): String { + return when (position) { + "inline" -> "$originalText ($translatedText)" + "above" -> "$translatedText\n$originalText" + "below" -> "$originalText\n$translatedText" + else -> "$originalText\n$translatedText" + } + } + + override fun init() { + if (!config.enabled.get()) return + + onNextActivityCreate { + context.event.subscribe(BuildMessageEvent::class, priority = 10) { event -> + val message = event.message + if (!shouldTranslateMessage(message)) return@subscribe + + val originalText = getMessageText(message) ?: return@subscribe + val sourceLang = config.sourceLanguage.get() + val targetLang = config.targetLanguage.get() + + if (sourceLang == targetLang) return@subscribe + + context.coroutineScope.launch { + try { + val translatedText = translationManager.translateText(originalText, sourceLang, targetLang) ?: return@launch + + context.runOnUiThread { + val showOriginal = config.showOriginal.get() + val showTranslation = config.showTranslation.get() + + if (!showOriginal && showTranslation) { + updateMessageText(message, translatedText) + } else if (showOriginal && showTranslation) { + val position = config.translationPosition.get() + val displayText = createTranslatedDisplayText(originalText, translatedText, position) + updateMessageText(message, displayText) + } + } + } catch (e: Exception) { + context.log.error("Translation failed for message", e) + if (config.pauseOnError.get()) { + isPaused = true + context.log.warn("Translation paused due to errors") + context.shortToast("Translation service temporarily unavailable") + } + } + } + } + } + + if (config.translateOnTap.get()) { + hookMessageTap() + } + + context.coroutineScope.launch { + while (true) { + kotlinx.coroutines.delay(300000) // 5 minutes + if (isPaused) { + translationManager.resetBlockedStatus() + isPaused = false + context.log.info("Translation service re-enabled") + } + } + } + } + + private fun hookMessageTap() { + findClass("com.snapchat.client.messaging.Message")?.hook("getText", HookStage.AFTER) { param -> + val message = param.thisObject() + val originalText = param.getResult() as? String ?: return@hook + + if (originalText.isBlank()) return@hook + + context.coroutineScope.launch { + try { + val sourceLang = config.sourceLanguage.get() + val targetLang = config.targetLanguage.get() + + if (sourceLang == targetLang) return@launch + + val translatedText = translationManager.translateText(originalText, sourceLang, targetLang) ?: return@launch + + context.runOnUiThread { + val position = config.translationPosition.get() + val translatedText = createTranslatedText(originalText, translatedText, position) + param.setResult(translatedText) + } + } catch (e: Exception) { + context.log.error("Translation failed for tap", e) + } + } + } + } +} + + diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/messaging/Messaging.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/messaging/Messaging.kt similarity index 89% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/messaging/Messaging.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/messaging/Messaging.kt index 8d4a3d7a..dea0043b 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/messaging/Messaging.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/messaging/Messaging.kt @@ -1,22 +1,22 @@ -package me.rhunk.snapenhance.core.features.impl.messaging +package me.eternal.purrfectsnap.core.features.impl.messaging import android.content.ComponentName import android.content.Intent -import me.rhunk.snapenhance.common.Constants -import me.rhunk.snapenhance.common.ReceiversConfig -import me.rhunk.snapenhance.core.event.events.impl.ConversationUpdateEvent -import me.rhunk.snapenhance.core.event.events.impl.OnSnapInteractionEvent -import me.rhunk.snapenhance.core.features.Feature -import me.rhunk.snapenhance.core.features.impl.spying.StealthMode -import me.rhunk.snapenhance.core.util.EvictingMap -import me.rhunk.snapenhance.core.util.hook.HookStage -import me.rhunk.snapenhance.core.util.hook.hook -import me.rhunk.snapenhance.core.util.hook.hookConstructor -import me.rhunk.snapenhance.core.util.ktx.getObjectField -import me.rhunk.snapenhance.core.util.ktx.getObjectFieldOrNull -import me.rhunk.snapenhance.core.wrapper.impl.* -import me.rhunk.snapenhance.mapper.impl.CallbackMapper -import me.rhunk.snapenhance.mapper.impl.FriendsFeedEventDispatcherMapper +import me.eternal.purrfectsnap.common.Constants +import me.eternal.purrfectsnap.common.ReceiversConfig +import me.eternal.purrfectsnap.core.event.events.impl.ConversationUpdateEvent +import me.eternal.purrfectsnap.core.event.events.impl.OnSnapInteractionEvent +import me.eternal.purrfectsnap.core.features.Feature +import me.eternal.purrfectsnap.core.features.impl.spying.StealthMode +import me.eternal.purrfectsnap.core.util.EvictingMap +import me.eternal.purrfectsnap.core.util.hook.HookStage +import me.eternal.purrfectsnap.core.util.hook.hook +import me.eternal.purrfectsnap.core.util.hook.hookConstructor +import me.eternal.purrfectsnap.core.util.ktx.getObjectField +import me.eternal.purrfectsnap.core.util.ktx.getObjectFieldOrNull +import me.eternal.purrfectsnap.core.wrapper.impl.* +import me.eternal.purrfectsnap.mapper.impl.CallbackMapper +import me.eternal.purrfectsnap.mapper.impl.FriendsFeedEventDispatcherMapper import java.util.UUID import java.util.concurrent.Future @@ -60,7 +60,7 @@ class Messaging : Feature("Messaging") { context.messagingBridge.triggerSessionStart() context.mainActivity?.takeIf { it.intent.getBooleanExtra(ReceiversConfig.MESSAGING_PREVIEW_EXTRA, false) }?.run { startActivity(Intent().apply { - setComponent(ComponentName(Constants.SE_PACKAGE_NAME, "me.rhunk.snapenhance.ui.manager.MainActivity")) + setComponent(ComponentName(Constants.SE_PACKAGE_NAME, "me.eternal.purrfectsnap.ui.manager.MainActivity")) addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) }) } @@ -214,4 +214,4 @@ class Messaging : Feature("Messaging") { return (future.get() as? List<*>)?.map { Snapchatter(it) } ?: return emptyList() } -} \ No newline at end of file +} diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/messaging/Notifications.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/messaging/Notifications.kt similarity index 90% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/messaging/Notifications.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/messaging/Notifications.kt index 180de4d8..43331063 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/messaging/Notifications.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/messaging/Notifications.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.core.features.impl.messaging +package me.eternal.purrfectsnap.core.features.impl.messaging import android.app.Notification import android.app.NotificationManager @@ -13,29 +13,30 @@ import android.os.Bundle import android.os.UserHandle import de.robv.android.xposed.XposedBridge import kotlinx.coroutines.* -import me.rhunk.snapenhance.common.data.ContentType -import me.rhunk.snapenhance.common.data.FileType -import me.rhunk.snapenhance.common.data.MessageUpdate -import me.rhunk.snapenhance.common.data.NotificationType -import me.rhunk.snapenhance.common.data.download.SplitMediaAssetType -import me.rhunk.snapenhance.common.util.snap.MediaDownloaderHelper -import me.rhunk.snapenhance.common.util.snap.SnapWidgetBroadcastReceiverHelper -import me.rhunk.snapenhance.core.event.events.impl.SnapWidgetBroadcastReceiveEvent -import me.rhunk.snapenhance.core.features.Feature -import me.rhunk.snapenhance.core.features.impl.FriendMutationObserver -import me.rhunk.snapenhance.core.features.impl.downloader.MediaDownloader -import me.rhunk.snapenhance.core.features.impl.downloader.decoder.AttachmentType -import me.rhunk.snapenhance.core.features.impl.downloader.decoder.MessageDecoder -import me.rhunk.snapenhance.core.features.impl.experiments.BetterTranscript -import me.rhunk.snapenhance.core.features.impl.spying.StealthMode -import me.rhunk.snapenhance.core.util.hook.HookStage -import me.rhunk.snapenhance.core.util.hook.findRestrictedConstructor -import me.rhunk.snapenhance.core.util.hook.findRestrictedMethod -import me.rhunk.snapenhance.core.util.hook.hook -import me.rhunk.snapenhance.core.util.ktx.setObjectField -import me.rhunk.snapenhance.core.util.media.PreviewUtils -import me.rhunk.snapenhance.core.wrapper.impl.Message -import me.rhunk.snapenhance.core.wrapper.impl.SnapUUID +import me.eternal.purrfectsnap.common.data.ContentType +import me.eternal.purrfectsnap.common.data.FileType +import me.eternal.purrfectsnap.common.data.MessageUpdate +import me.eternal.purrfectsnap.common.data.NotificationType +import me.eternal.purrfectsnap.common.data.download.SplitMediaAssetType +import me.eternal.purrfectsnap.common.util.snap.MediaDownloaderHelper +import me.eternal.purrfectsnap.common.util.snap.SnapWidgetBroadcastReceiverHelper +import me.eternal.purrfectsnap.core.event.events.impl.SnapWidgetBroadcastReceiveEvent +import me.eternal.purrfectsnap.core.features.Feature +import me.eternal.purrfectsnap.core.features.impl.FriendMutationObserver +import me.eternal.purrfectsnap.core.features.impl.downloader.MediaDownloader +import me.eternal.purrfectsnap.core.features.impl.downloader.decoder.AttachmentType +import me.eternal.purrfectsnap.core.features.impl.downloader.decoder.MessageDecoder +import me.eternal.purrfectsnap.core.features.impl.experiments.BetterTranscript +import me.eternal.purrfectsnap.core.features.impl.spying.StealthMode +import me.eternal.purrfectsnap.core.util.hook.HookStage +import me.eternal.purrfectsnap.core.util.hook.findRestrictedConstructor +import me.eternal.purrfectsnap.core.util.hook.findRestrictedMethod +import me.eternal.purrfectsnap.core.util.hook.hook +import me.eternal.purrfectsnap.core.util.ktx.setObjectField +import me.eternal.purrfectsnap.core.util.media.PreviewUtils +import me.eternal.purrfectsnap.core.wrapper.impl.Message +import me.eternal.purrfectsnap.core.wrapper.impl.SnapUUID +import me.eternal.purrfectsnap.core.wrapper.impl.sanitizeForLayout import java.nio.ByteBuffer import kotlin.coroutines.suspendCoroutine @@ -57,9 +58,9 @@ class Notifications : Feature("Notifications") { } companion object{ - const val ACTION_REPLY = "me.rhunk.snapenhance.action.notification.REPLY" - const val ACTION_DOWNLOAD = "me.rhunk.snapenhance.action.notification.DOWNLOAD" - const val ACTION_MARK_AS_READ = "me.rhunk.snapenhance.action.notification.MARK_AS_READ" + const val ACTION_REPLY = "me.eternal.purrfectsnap.action.notification.REPLY" + const val ACTION_DOWNLOAD = "me.eternal.purrfectsnap.action.notification.DOWNLOAD" + const val ACTION_MARK_AS_READ = "me.eternal.purrfectsnap.action.notification.MARK_AS_READ" const val SNAPCHAT_NOTIFICATION_GROUP = "snapchat_notification_group" } @@ -84,9 +85,10 @@ class Notifications : Feature("Notifications") { }?.newInstance(context.androidContext, notification) as? Notification.Builder ?: throw NoSuchMethodException("Notification.Builder") private fun setNotificationText(notification: Notification, text: String) { - notification.extras.putString("android.text", text) - notification.extras.putString("android.bigText", text) - notification.extras.putParcelableArray("android.messages", text.split("\n").map { + val safeText = text.sanitizeForLayout() + notification.extras.putString("android.text", safeText) + notification.extras.putString("android.bigText", safeText) + notification.extras.putParcelableArray("android.messages", safeText.split("\n").map { Bundle().apply { putBundle("extras", Bundle()) putString("text", it) @@ -183,8 +185,10 @@ class Notifications : Feature("Notifications") { when (event.action) { ACTION_REPLY -> { - val input = RemoteInput.getResultsFromIntent(intent).getCharSequence("chat_reply_input") + val input = RemoteInput.getResultsFromIntent(intent) + .getCharSequence("chat_reply_input") .toString() + .sanitizeForLayout() val myUser = context.database.myUserId.let { context.database.getFriendInfo(it) } ?: return@subscribe context.messageSender.sendChatMessage(listOf(SnapUUID(conversationId)), input, onError = { @@ -314,9 +318,9 @@ class Notifications : Feature("Notifications") { val conversationId = message.messageDescriptor?.conversationId.toString() val orderKey = message.orderKey ?: return val senderUsername by lazy { - context.database.getFriendInfo(message.senderId.toString())?.let { + (context.database.getFriendInfo(message.senderId.toString())?.let { it.displayName ?: it.mutableUsername - } ?: "Unknown" + } ?: "Unknown").sanitizeForLayout() } val contentType = message.messageContent!!.contentType!!.let { contentType -> @@ -389,6 +393,7 @@ class Notifications : Feature("Notifications") { } else "" }" } + serializedMessage = serializedMessage.sanitizeForLayout() if (contentType == ContentType.NOTE && context.config.experimental.betterTranscript.takeIf { it.globalState == true }?.notificationTranscript?.get() == true) { MessageDecoder.decode(message.messageContent!!).firstOrNull { it.type == AttachmentType.NOTE }?.also { media -> @@ -537,4 +542,4 @@ class Notifications : Feature("Notifications") { } } } -} \ No newline at end of file +} diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/messaging/PreventMessageSending.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/messaging/PreventMessageSending.kt similarity index 77% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/messaging/PreventMessageSending.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/messaging/PreventMessageSending.kt index 8f2abe89..e9d7d3a5 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/messaging/PreventMessageSending.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/messaging/PreventMessageSending.kt @@ -1,12 +1,12 @@ -package me.rhunk.snapenhance.core.features.impl.messaging +package me.eternal.purrfectsnap.core.features.impl.messaging -import me.rhunk.snapenhance.common.data.NotificationType -import me.rhunk.snapenhance.common.util.protobuf.ProtoEditor -import me.rhunk.snapenhance.core.event.events.impl.NativeUnaryCallEvent -import me.rhunk.snapenhance.core.event.events.impl.SendMessageWithContentEvent -import me.rhunk.snapenhance.core.features.Feature -import me.rhunk.snapenhance.core.util.hook.HookStage -import me.rhunk.snapenhance.core.util.hook.hook +import me.eternal.purrfectsnap.common.data.NotificationType +import me.eternal.purrfectsnap.common.util.protobuf.ProtoEditor +import me.eternal.purrfectsnap.core.event.events.impl.NativeUnaryCallEvent +import me.eternal.purrfectsnap.core.event.events.impl.SendMessageWithContentEvent +import me.eternal.purrfectsnap.core.features.Feature +import me.eternal.purrfectsnap.core.util.hook.HookStage +import me.eternal.purrfectsnap.core.util.hook.hook class PreventMessageSending : Feature("Prevent message sending") { override fun init() { diff --git a/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/messaging/SendOverride.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/messaging/SendOverride.kt new file mode 100644 index 00000000..09f8da10 --- /dev/null +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/messaging/SendOverride.kt @@ -0,0 +1,765 @@ +package me.eternal.purrfectsnap.core.features.impl.messaging + +import android.app.NotificationChannel +import android.app.NotificationManager +import android.os.Build +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.text.KeyboardOptions +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.* +import androidx.compose.material3.* +import androidx.compose.runtime.* +import androidx.core.app.NotificationCompat +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.input.KeyboardType +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import de.robv.android.xposed.XC_MethodHook +import kotlinx.coroutines.* +import me.eternal.purrfectsnap.bridge.task.TaskListener +import me.eternal.purrfectsnap.common.data.ContentType +import me.eternal.purrfectsnap.common.ui.createComposeAlertDialog +import me.eternal.purrfectsnap.common.util.protobuf.ProtoEditor +import me.eternal.purrfectsnap.common.util.protobuf.ProtoReader +import me.eternal.purrfectsnap.common.util.protobuf.ProtoWriter +import me.eternal.purrfectsnap.core.event.events.impl.MediaUploadEvent +import me.eternal.purrfectsnap.core.event.events.impl.NativeUnaryCallEvent +import me.eternal.purrfectsnap.core.event.events.impl.SendMessageWithContentEvent +import me.eternal.purrfectsnap.core.features.Feature +import me.eternal.purrfectsnap.core.features.impl.experiments.MediaFilePicker +import me.eternal.purrfectsnap.core.messaging.MessageSender +import me.eternal.purrfectsnap.core.util.ktx.getObjectFieldOrNull +import me.eternal.purrfectsnap.core.util.hook.HookStage +import me.eternal.purrfectsnap.core.util.hook.hook +import me.eternal.purrfectsnap.core.util.hook.hookConstructor +import java.text.SimpleDateFormat +import java.util.Calendar +import java.util.Locale +import kotlin.time.DurationUnit +import kotlin.time.toDuration + + +@OptIn(ExperimentalMaterial3Api::class) +class SendOverride : Feature("Send Override") { + companion object { + private const val NOTIFICATION_CHANNEL_ID = "scheduled_send" + } + + private var selectedType by mutableStateOf("SNAP") + private var customDuration by mutableFloatStateOf(10f) + private var scheduledTime by mutableStateOf(null) + private var showClockPicker by mutableStateOf(false) + private var clockPickerHour by mutableIntStateOf(12) + private var clockPickerMinute by mutableIntStateOf(0) + private var notificationIdCounter = 1000 + private val backgroundHookLock = Any() + private var backgroundHookRefs = 0 + private var backgroundHooks: List? = null + + private fun acquireScheduledSendBackground(): () -> Unit { + if (!context.config.messaging.scheduledSendAllowRunningInBackground.get()) return {} + var enableFailed = false + synchronized(backgroundHookLock) { + backgroundHookRefs++ + if (backgroundHookRefs == 1) { + if (!enableScheduledSendBackgroundLocked()) { + backgroundHookRefs-- + enableFailed = true + } + } + } + if (enableFailed) return {} + var released = false + return { + synchronized(backgroundHookLock) { + if (released) return@synchronized + released = true + if (backgroundHookRefs > 0) backgroundHookRefs-- + if (backgroundHookRefs == 0) { + backgroundHooks?.forEach { it.unhook() } + backgroundHooks = null + } + } + } + } + + private fun enableScheduledSendBackgroundLocked(): Boolean { + return runCatching { + val duplexClass = findClass("com.snapchat.client.duplex.DuplexClient\$CppProxy") + val appStateMethod = duplexClass.methods.firstOrNull { it.name == "appStateChanged" } ?: return false + val hooks = mutableListOf() + hooks.addAll( + duplexClass.hook("appStateChanged", HookStage.BEFORE) { param -> + if (param.arg(0).toString() == "INACTIVE") param.setResult(null) + } + ) + hooks.addAll( + duplexClass.hookConstructor(HookStage.AFTER) { param -> + val activeValue = appStateMethod.parameterTypes[0].enumConstants?.firstOrNull { it.toString() == "ACTIVE" } + ?: return@hookConstructor + appStateMethod.invoke(param.thisObject(), activeValue) + } + ) + backgroundHooks = hooks + true + }.getOrElse { + context.log.error("Failed to enable scheduled send background mode", it) + false + } + } + + private fun createNotificationChannel() { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + val notificationManager = context.androidContext.getSystemService(NotificationManager::class.java) + val channel = NotificationChannel( + NOTIFICATION_CHANNEL_ID, + "Scheduled Send", + NotificationManager.IMPORTANCE_DEFAULT + ) + channel.description = "Notifications for scheduled snap sends" + notificationManager.createNotificationChannel(channel) + } + } + + private fun showNotification(title: String, content: String) { + val notificationManager = context.androidContext.getSystemService(NotificationManager::class.java) + val builder = NotificationCompat.Builder(context.androidContext, NOTIFICATION_CHANNEL_ID) + .setSmallIcon(android.R.drawable.ic_menu_recent_history) + .setContentTitle(title) + .setContentText(content) + .setStyle(NotificationCompat.BigTextStyle().bigText(content)) + .setPriority(NotificationCompat.PRIORITY_DEFAULT) + .setAutoCancel(true) + notificationManager.notify(notificationIdCounter++, builder.build()) + } + + @OptIn(ExperimentalLayoutApi::class) + override fun init() { + createNotificationChannel() + + val stripMediaMetadata = context.config.messaging.stripMediaMetadata.get() + var postSavePolicy: Int? = null + + val configOverrideType = context.config.messaging.galleryMediaSendOverride.getNullable() + if (configOverrideType == null && stripMediaMetadata.isEmpty()) return + + context.event.subscribe(MediaUploadEvent::class) { event -> + ProtoReader(event.localMessageContent.content!!).followPath(11, 5)?.let { snapDocPlayback -> + event.onMediaUploaded { result -> + result.messageContent.content = ProtoEditor(result.messageContent.content!!).apply { + edit(11, 5) { + edit(1) { + edit(1) { + snapDocPlayback.getVarInt(2, 99)?.let { customDuration -> + remove(15) + addVarInt(15, customDuration) + } + remove(27) + remove(26) + addBuffer(26, byteArrayOf()) + } + } + + // set back the original snap duration + snapDocPlayback.getByteArray(2)?.let { + val originalHasSound = firstOrNull(2)?.toReader()?.getVarInt(5) + remove(2) + addBuffer(2, it) + + originalHasSound?.let { hasSound -> + edit(2) { + remove(5) + addVarInt(5, hasSound) + } + } + } + } + + if (stripMediaMetadata.isNotEmpty()) { + when (result.messageContent.contentType) { + ContentType.SNAP, ContentType.EXTERNAL_MEDIA -> { + edit(*(if (result.messageContent.contentType == ContentType.SNAP) intArrayOf(11) else intArrayOf(3, 3))) { + if (stripMediaMetadata.contains("hide_caption_text")) { + edit(5) { + editEach(1) { + remove(2) + } + } + } + if (stripMediaMetadata.contains("hide_snap_filters")) { + remove(9) + remove(11) + } + if (stripMediaMetadata.contains("hide_extras")) { + remove(13) + edit(5, 1) { + remove(2) + } + } + } + } + ContentType.NOTE -> { + if (stripMediaMetadata.contains("remove_audio_note_duration")) { + edit(6, 1, 1) { + remove(13) + } + } + if (stripMediaMetadata.contains("remove_audio_note_transcript_capability")) { + edit(6, 1) { + remove(3) + } + } + } + else -> {} + } + } + + edit(11, 5, 2) { + remove(99) + } + }.toByteArray() + } + } + } + + if (configOverrideType == null) return + + context.event.subscribe(NativeUnaryCallEvent::class) { event -> + if (event.uri != "/messagingcoreservice.MessagingCoreService/CreateContentMessage") return@subscribe + postSavePolicy?.let { savePolicy -> + context.log.verbose("postSavePolicy=$savePolicy") + event.buffer = ProtoEditor(event.buffer).apply { + edit(4) { + remove(7) + addVarInt(7, savePolicy) + } + + // remove Keep Snaps in Chat ability + if (savePolicy == 1/* PROHIBITED */) { + edit(6, 9) { + remove(1) + } + } + }.toByteArray() + } + } + + context.event.subscribe(SendMessageWithContentEvent::class) { event -> + postSavePolicy = null + if (event.destinations.stories?.isNotEmpty() == true && event.destinations.conversations?.isEmpty() == true) return@subscribe + val localMessageContent = event.messageContent + // Allow both EXTERNAL_MEDIA (gallery) and SNAP (camera) + if (localMessageContent.contentType != ContentType.EXTERNAL_MEDIA && + localMessageContent.contentType != ContentType.SNAP && + localMessageContent.instanceNonNull().getObjectFieldOrNull("mExternalContentMetadata") == null) return@subscribe + + //prevent story replies + val messageProtoReader = ProtoReader(localMessageContent.content ?: return@subscribe) + if (messageProtoReader.contains(7)) return@subscribe + + val conversationIds = event.destinations.conversations?.map { it.toString() } ?: return@subscribe + if (conversationIds.isEmpty()) return@subscribe + + val recipientNames = conversationIds.mapNotNull { convId -> + runCatching { + val dmParticipant = context.database.getDMOtherParticipant(convId) + if (dmParticipant != null) { + context.database.getFriendInfo(dmParticipant)?.displayName ?: context.database.getFriendInfo(dmParticipant)?.mutableUsername + } else { + context.database.getFeedEntryByConversationId(convId)?.feedDisplayName + } + }.getOrNull() + }.ifEmpty { listOf("Unknown") } + + val recipientName = recipientNames.joinToString(", ") + + event.canceled = true + + fun sendMedia(overrideType: String, snapDurationMs: Int?): Boolean { + if (overrideType != "ORIGINAL" && (messageProtoReader.followPath(3)?.getCount(3) ?: 0) > 1) { + context.inAppOverlay.showStatusToast( + icon = Icons.Default.WarningAmber, + context.translation["gallery_media_send_override.multiple_media_toast"] + ) + return false + } + + when (overrideType) { + "SNAP", "SAVEABLE_SNAP" -> { + postSavePolicy = if (overrideType == "SAVEABLE_SNAP") 3 /* VIEW_SESSION */ else 1 /* PROHIBITED */ + + val extras = messageProtoReader.followPath(3, 3, 13)?.getBuffer() + + if (localMessageContent.contentType != ContentType.SNAP) { + localMessageContent.content = ProtoWriter().apply { + from(11) { + from(5) { + from(1) { + from(1) { + addVarInt(2, 0) + addVarInt(12, 0) + addVarInt(15, 0) + } + addVarInt(6, 1) + } + from(2) {} + } + extras?.let { + addBuffer(13, it) + } + from(22) {} + } + }.toByteArray() + } + + localMessageContent.contentType = ContentType.SNAP + localMessageContent.content = ProtoEditor(localMessageContent.content!!).apply { + edit(11, 5, 2) { + arrayOf(6, 7, 8).forEach { remove(it) } + addVarInt(5, messageProtoReader.getVarInt(3, 3, 5, 2, 5) ?: messageProtoReader.getVarInt(11, 5, 2, 5) ?: 1) + // set snap duration + if (snapDurationMs != null) { + addVarInt(8, snapDurationMs / 1000) + if (snapDurationMs / 1000 <= 0) { + addVarInt(99, snapDurationMs) + } + } else { + addBuffer(6, byteArrayOf()) + } + } + + // set app source + edit(11, 22) { + remove(4) + addVarInt(4, 5) // APP_SOURCE_CAMERA + } + }.toByteArray() + } + "NOTE" -> { + localMessageContent.contentType = ContentType.NOTE + localMessageContent.content = + MessageSender.audioNoteProto( + messageProtoReader.getVarInt(3, 3, 5, 1, 1, 15) ?: context.feature(MediaFilePicker::class).lastMediaDuration ?: 0, + Locale.getDefault().toLanguageTag() + ) + } + } + + return true + } + + if (configOverrideType != "always_ask") { + if (sendMedia(configOverrideType, 10)) { + event.invokeOriginal() + } + return@subscribe + } + + context.runOnUiThread { + val recipientNameForTask = recipientName + createComposeAlertDialog(context.mainActivity!!) { alertDialog -> + val mainTranslation = remember { + context.translation.getCategory("send_override_dialog") + } + + @Composable + fun ActionTile( + modifier: Modifier = Modifier, + selected: Boolean = false, + icon: ImageVector, + title: String, + onClick: () -> Unit + ) { + Card( + modifier = modifier, + onClick = onClick, + elevation = if (selected) CardDefaults.elevatedCardElevation(disabledElevation = 3.dp) else CardDefaults.cardElevation(), + colors = if (selected) CardDefaults.elevatedCardColors() else CardDefaults.cardColors() + ) { + Column( + modifier = Modifier + .padding(16.dp) + .size(75.dp), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.Center + ) { + Icon(icon, contentDescription = title, modifier = Modifier + .size(32.dp) + .padding(4.dp)) + Text(title, modifier = Modifier.fillMaxWidth(), fontSize = 12.sp, fontWeight = FontWeight.Light, softWrap = true, lineHeight = 14.sp, textAlign = TextAlign.Center) + } + } + } + + Column( + modifier = Modifier + .fillMaxWidth() + .padding(8.dp), + verticalArrangement = Arrangement.spacedBy(8.dp) + ) { + val translation = remember { + context.translation.getCategory("features.options.gallery_media_send_override") + } + var scheduleEnabled by remember { mutableStateOf(false) } + + Text(fontSize = 20.sp, fontWeight = FontWeight.Medium, text = "Send as ${ + translation[selectedType]}", modifier = Modifier.padding(5.dp)) + FlowRow( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.SpaceEvenly + ) { + ActionTile(selected = selectedType == "ORIGINAL", icon = Icons.Filled.Photo, title = + translation["ORIGINAL"]) { + selectedType = "ORIGINAL" + } + ActionTile(selected = selectedType == "SNAP" || selectedType == "SAVEABLE_SNAP", icon = Icons.Filled.PhotoCamera, title = translation["SNAP"]) { + selectedType = "SNAP" + } + ActionTile(selected = selectedType == "NOTE", icon = Icons.Filled.MusicNote, title = translation["NOTE"]) { + selectedType = "NOTE" + } + } + + fun convertDuration(duration: Float): Int? { + return when { + duration in -2f..-1f -> 100 + duration in -1f..-0f -> 250 + duration in -0f..1f -> 500 + duration >= 11f -> null + else -> ((duration * 1000).toInt() / 1000) * 1000 + } + } + + when (selectedType) { + "SNAP", "SAVEABLE_SNAP" -> { + fun toggleSaveable() { + selectedType = if (selectedType == "SAVEABLE_SNAP") "SNAP" else "SAVEABLE_SNAP" + } + Row( + modifier = Modifier.fillMaxWidth().clickable { + toggleSaveable() + }, + horizontalArrangement = Arrangement.spacedBy(4.dp), + verticalAlignment = Alignment.CenterVertically + ){ + Checkbox( + checked = selectedType == "SAVEABLE_SNAP", + onCheckedChange = { + toggleSaveable() + } + ) + Text(text = mainTranslation["saveable_snap_hint"], lineHeight = 15.sp) + } + Column( + modifier = Modifier.padding(start = 8.dp) + ) { + Text( + text = mainTranslation.format("duration", + "duration" to (convertDuration(customDuration)?.toDuration(DurationUnit.MILLISECONDS)?.toString(DurationUnit.SECONDS, 2) ?: mainTranslation["unlimited_duration"]) + ) + ) + Slider( + modifier = Modifier.fillMaxWidth(), + enabled = selectedType != "SAVEABLE_SNAP", + value = customDuration, + onValueChange = { + customDuration = it + }, + valueRange = -2f..11f, + ) + } + } + } + + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.SpaceEvenly, + verticalAlignment = Alignment.CenterVertically + ) { + Checkbox( + checked = scheduleEnabled, + onCheckedChange = { + scheduleEnabled = it + if (!it) scheduledTime = null + } + ) + Text(text = mainTranslation["schedule"], modifier = Modifier.weight(1f)) + if (scheduleEnabled) { + Button(onClick = { showClockPicker = true }) { + scheduledTime?.let { time -> + Text(text = SimpleDateFormat("HH:mm", Locale.getDefault()).format(time)) + } ?: Text(context.translation["select"]) + } + } + } + + if (scheduleEnabled && showClockPicker) { + val datePickerState = rememberDatePickerState( + initialSelectedDateMillis = scheduledTime ?: System.currentTimeMillis() + ) + val timePickerState = rememberTimePickerState( + initialHour = clockPickerHour, + initialMinute = clockPickerMinute + ) + + var showDatePickerDialog by remember { mutableStateOf(false) } + var showTimePickerDialog by remember { mutableStateOf(false) } + + // Date Picker Dialog + if (showDatePickerDialog) { + DatePickerDialog( + onDismissRequest = { showDatePickerDialog = false }, + confirmButton = { + TextButton(onClick = { showDatePickerDialog = false }) { + Text(context.translation["button.ok"]) + } + }, + dismissButton = { + TextButton(onClick = { showDatePickerDialog = false }) { + Text(context.translation["button.cancel"]) + } + } + ) { + DatePicker(state = datePickerState) + } + } + + // Time Picker Dialog + if (showTimePickerDialog) { + AlertDialog( + onDismissRequest = { showTimePickerDialog = false }, + confirmButton = { + TextButton(onClick = { + clockPickerHour = timePickerState.hour + clockPickerMinute = timePickerState.minute + showTimePickerDialog = false + }) { + Text(context.translation["button.ok"]) + } + }, + dismissButton = { + TextButton(onClick = { showTimePickerDialog = false }) { + Text(context.translation["button.cancel"]) + } + }, + text = { + TimePicker(state = timePickerState) + } + ) + } + + Card( + modifier = Modifier.fillMaxWidth(), + shape = MaterialTheme.shapes.medium + ) { + Column( + modifier = Modifier.padding(16.dp), + verticalArrangement = Arrangement.spacedBy(12.dp) + ) { + Text( + mainTranslation["select_time"], + fontWeight = FontWeight.Bold, + style = MaterialTheme.typography.titleMedium + ) + + // Date Selection Button + OutlinedButton( + onClick = { showDatePickerDialog = true }, + modifier = Modifier.fillMaxWidth() + ) { + Icon(Icons.Default.CalendarToday, contentDescription = null) + Spacer(Modifier.width(8.dp)) + Text( + datePickerState.selectedDateMillis?.let { millis -> + SimpleDateFormat("dd/MM/yyyy", Locale.getDefault()).format(millis) + } ?: context.translation.getOrNull("select_date") ?: "Select Date" + ) + } + + // Time Selection Button + OutlinedButton( + onClick = { showTimePickerDialog = true }, + modifier = Modifier.fillMaxWidth() + ) { + Icon(Icons.Default.Schedule, contentDescription = null) + Spacer(Modifier.width(8.dp)) + Text( + String.format("%02d:%02d", clockPickerHour, clockPickerMinute) + ) + } + + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.SpaceEvenly + ) { + OutlinedButton(onClick = { showClockPicker = false }) { + Text(context.translation["button.cancel"]) + } + Button(onClick = { + val selectedDateMillis = datePickerState.selectedDateMillis + if (selectedDateMillis == null) { + context.inAppOverlay.showStatusToast( + icon = Icons.Default.WarningAmber, + text = mainTranslation.getOrNull("select_date_first") ?: "Please select a date" + ) + return@Button + } + + val calendar = Calendar.getInstance() + calendar.timeInMillis = selectedDateMillis + calendar.set(Calendar.HOUR_OF_DAY, clockPickerHour) + calendar.set(Calendar.MINUTE, clockPickerMinute) + calendar.set(Calendar.SECOND, 0) + calendar.set(Calendar.MILLISECOND, 0) + + if (calendar.timeInMillis <= System.currentTimeMillis()) { + context.inAppOverlay.showStatusToast( + icon = Icons.Default.WarningAmber, + text = mainTranslation.getOrNull("invalid_time") ?: "Please select a future time" + ) + return@Button + } + + scheduledTime = calendar.timeInMillis + showClockPicker = false + }) { + Text(context.translation["button.ok"]) + } + } + } + } + } + + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.SpaceEvenly, + verticalAlignment = Alignment.CenterVertically + ) { + OutlinedButton(onClick = { + alertDialog.dismiss() + }) { + Text(context.translation["button.cancel"]) + } + Button(onClick = { + alertDialog.dismiss() + val delayMs = scheduledTime?.let { it - System.currentTimeMillis() } + if (delayMs != null && delayMs > 0) { + val taskHash = java.util.UUID.randomUUID().toString() + // Format the scheduled time for display + val scheduledDateTime = SimpleDateFormat("yyyy/MM/dd HH:mm", Locale.getDefault()).format(scheduledTime) + context.bridgeClient.getTaskInterface().createTask( + "scheduled_send", + scheduledDateTime, + recipientNameForTask, + taskHash + ) + val days = (delayMs / (24 * 60 * 60 * 1000)).toInt() + val hours = ((delayMs / (60 * 60 * 1000)) % 24).toInt() + val minutes = ((delayMs / (60 * 1000)) % 60).toInt() + val seconds = ((delayMs / 1000) % 60).toInt() + + val scheduledTimeText = StringBuilder().apply { + if (days > 0) append("${days}d ") + if (hours > 0 || days > 0) append("${hours}h ") + if (minutes > 0 || hours > 0 || days > 0) append("${minutes}m ") + append("${seconds}s") + }.toString() + context.inAppOverlay.showStatusToast( + icon = Icons.Filled.Schedule, + text = context.translation.format("schedule_scheduled_for", "name" to recipientNameForTask, "time" to scheduledTimeText) ?: "Scheduled for $recipientNameForTask in $scheduledTimeText" + ) + val releaseBackground = acquireScheduledSendBackground() + val job = context.coroutineScope.launch { + val startTime = System.currentTimeMillis() + while (true) { + delay(1000) + val elapsed = System.currentTimeMillis() - startTime + val remaining = delayMs - elapsed + if (remaining <= 0) break + val days = (remaining / (24 * 60 * 60 * 1000)).toInt() + val hours = ((remaining / (60 * 60 * 1000)) % 24).toInt() + val minutes = ((remaining / (60 * 1000)) % 60).toInt() + val seconds = ((remaining / 1000) % 60).toInt() + + val timeText = StringBuilder().apply { + if (days > 0) append("${days}d ") + if (hours > 0 || days > 0) append("${hours}h ") + if (minutes > 0 || hours > 0 || days > 0) append("${minutes}m ") + append("${seconds}s") + }.toString() + context.bridgeClient.getTaskInterface().updateTaskProgress( + taskHash, + context.translation.getOrNull("schedule_sending_in")?.replace("{time}", timeText) ?: "Sending in $timeText", + -1 + ) + } + if (sendMedia(selectedType, if (selectedType != "SAVEABLE_SNAP") convertDuration(customDuration) else null)) { + event.invokeOriginal() + context.bridgeClient.getTaskInterface().successTask(taskHash) + val successText = context.translation.format("schedule_sent_to", "name" to recipientNameForTask) ?: "Sent to $recipientNameForTask" + context.inAppOverlay.showStatusToast( + icon = Icons.Filled.CheckCircle, + text = successText + ) + val notificationTitle = context.translation.getOrNull("schedule_sent") ?: "Scheduled snap sent" + val notificationContent = "$scheduledDateTime\n$recipientNameForTask" + showNotification( + notificationTitle, + notificationContent + ) + } else { + context.bridgeClient.getTaskInterface().failTask(taskHash, "Failed to send") + val failureText = context.translation.format("schedule_failed_to", "name" to recipientNameForTask) ?: "Failed to send to $recipientNameForTask" + context.inAppOverlay.showStatusToast( + icon = Icons.Filled.WarningAmber, + text = failureText + ) + val failNotificationTitle = context.translation.getOrNull("schedule_failed") ?: "Scheduled snap failed" + val failNotificationContent = "$scheduledDateTime\n$recipientNameForTask" + showNotification( + failNotificationTitle, + failNotificationContent + ) + } + } + val listener = object : TaskListener.Stub() { + override fun onCancel() { + job.cancel() + } + override fun onProgress(label: String, progress: Int) {} + override fun onStateChange(status: String) {} + override fun onSuccess() {} + } + context.bridgeClient.getTaskInterface().registerTaskListener(taskHash, listener) + job.invokeOnCompletion { throwable -> + releaseBackground() + context.bridgeClient.getTaskInterface().unregisterTaskListener(taskHash, listener) + if (throwable is CancellationException) { + context.inAppOverlay.showStatusToast( + icon = Icons.Filled.Cancel, + text = context.translation.format("schedule_cancelled_for", "name" to recipientNameForTask) ?: "Cancelled for $recipientNameForTask" + ) + } + } + } else { + if (sendMedia(selectedType, if (selectedType != "SAVEABLE_SNAP") convertDuration(customDuration) else null)) { + event.invokeOriginal() + } + } + }) { + Text(if (scheduledTime != null) mainTranslation["schedule"] else context.translation["button.send"]) + } + } + } + }.show() + } + } + } +} + + diff --git a/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/messaging/TranslationManager.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/messaging/TranslationManager.kt new file mode 100644 index 00000000..a8f12629 --- /dev/null +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/messaging/TranslationManager.kt @@ -0,0 +1,203 @@ +package me.eternal.purrfectsnap.core.features.impl.messaging + +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.delay +import kotlinx.coroutines.withContext +import me.eternal.purrfectsnap.core.ModContext +import java.net.HttpURLConnection +import java.net.URL +import java.net.URLEncoder +import java.util.concurrent.ConcurrentHashMap +import java.util.concurrent.Executors +import java.util.concurrent.TimeUnit + +class TranslationManager(private val context: ModContext) { + private val translationCache = ConcurrentHashMap() + private val executor = Executors.newFixedThreadPool(3) + private var isBlocked = false + private var lastRequestTime = 0L + + data class CachedTranslation( + val translation: String, + val timestamp: Long, + val sourceLang: String, + val targetLang: String + ) + + companion object { + private const val CACHE_DURATION = 24 * 60 * 60 * 1000L + private const val MAX_CACHE_SIZE = 1000 + private const val MIN_REQUEST_INTERVAL = 1000L + private const val MAX_RETRIES = 3 + } + + suspend fun translateText( + text: String, + sourceLang: String, + targetLang: String, + forceRefresh: Boolean = false + ): String? { + if (text.isBlank()) return null + + val cacheKey = "${text}_${sourceLang}_${targetLang}" + + if (!forceRefresh) { + translationCache[cacheKey]?.let { cached -> + if (System.currentTimeMillis() - cached.timestamp < CACHE_DURATION) { + return cached.translation + } + } + } + + if (isBlocked) { + context.log.warn("Translation service is blocked, returning cached result if available") + return translationCache[cacheKey]?.translation + } + + val currentTime = System.currentTimeMillis() + if (currentTime - lastRequestTime < MIN_REQUEST_INTERVAL) { + delay(MIN_REQUEST_INTERVAL - (currentTime - lastRequestTime)) + } + + return try { + val translation = performTranslationWithRetry(text, sourceLang, targetLang) + if (translation != null) { + if (translationCache.size >= MAX_CACHE_SIZE) { + cleanupCache() + } + translationCache[cacheKey] = CachedTranslation( + translation = translation, + timestamp = System.currentTimeMillis(), + sourceLang = sourceLang, + targetLang = targetLang + ) + lastRequestTime = System.currentTimeMillis() + } + translation + } catch (e: Exception) { + context.log.error("Translation failed for text: $text", e) + null + } + } + + private suspend fun performTranslationWithRetry( + text: String, + sourceLang: String, + targetLang: String + ): String? { + var lastException: Exception? = null + + for (attempt in 1..MAX_RETRIES) { + try { + val translation = performTranslation(text, sourceLang, targetLang) + if (translation != null) { + return translation + } + } catch (e: Exception) { + lastException = e + context.log.warn("Translation attempt $attempt failed: ${e.message}") + + if (e.message?.contains("sorry/index") == true || e.message?.contains("429") == true) { + isBlocked = true + context.log.error("Translation service is blocked by Google") + break + } + + if (attempt < MAX_RETRIES) { + delay(attempt * 1000L) + } + } + } + + if (lastException != null) { + throw lastException + } + return null + } + + private suspend fun performTranslation(text: String, sourceLang: String, targetLang: String): String? { + return withContext(Dispatchers.IO) { + try { + val encodedText = URLEncoder.encode(text, "UTF-8") + val url = "https://translate.googleapis.com/translate_a/single?client=gtx&sl=$sourceLang&tl=$targetLang&dt=t&q=$encodedText" + + val connection = URL(url).openConnection() as HttpURLConnection + connection.requestMethod = "GET" + connection.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36") + connection.setRequestProperty("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8") + connection.setRequestProperty("Accept-Language", "en-US,en;q=0.5") + connection.setRequestProperty("Accept-Encoding", "gzip, deflate") + connection.setRequestProperty("Connection", "keep-alive") + connection.setRequestProperty("Upgrade-Insecure-Requests", "1") + connection.connectTimeout = 10000 + connection.readTimeout = 10000 + + val responseCode = connection.responseCode + if (responseCode == 429 || responseCode == 403) { + isBlocked = true + throw Exception("Translation service blocked (HTTP $responseCode)") + } + + if (responseCode != 200) { + throw Exception("HTTP $responseCode: ${connection.responseMessage}") + } + + val response = connection.inputStream.bufferedReader().use { it.readText() } + parseGoogleTranslateResponse(response) + } catch (e: Exception) { + context.log.error("Translation API call failed", e) + null + } + } + } + + private fun parseGoogleTranslateResponse(response: String): String? { + return try { + val startIndex = response.indexOf("[[[\"") + if (startIndex == -1) return null + + val endIndex = response.indexOf("\",\"", startIndex) + if (endIndex == -1) return null + + response.substring(startIndex + 4, endIndex) + } catch (e: Exception) { + context.log.error("Failed to parse translation response", e) + null + } + } + + private fun cleanupCache() { + val currentTime = System.currentTimeMillis() + translationCache.entries.removeIf { (_, cached) -> + currentTime - cached.timestamp > CACHE_DURATION + } + } + + fun clearCache() { + translationCache.clear() + } + + fun resetBlockedStatus() { + isBlocked = false + } + + fun getCacheStats(): Map { + return mapOf( + "size" to translationCache.size, + "maxSize" to MAX_CACHE_SIZE, + "cacheDuration" to CACHE_DURATION, + "isBlocked" to isBlocked + ) + } + + fun shutdown() { + executor.shutdown() + try { + if (!executor.awaitTermination(5, TimeUnit.SECONDS)) { + executor.shutdownNow() + } + } catch (e: InterruptedException) { + executor.shutdownNow() + } + } +} \ No newline at end of file diff --git a/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/messaging/TranslationUI.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/messaging/TranslationUI.kt new file mode 100644 index 00000000..7211b582 --- /dev/null +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/messaging/TranslationUI.kt @@ -0,0 +1,180 @@ +package me.eternal.purrfectsnap.core.features.impl.messaging + +import android.content.ClipData +import android.content.ClipboardManager +import android.content.Context +import android.view.View +import android.widget.Button +import androidx.compose.foundation.layout.* +import androidx.compose.material3.* +import androidx.compose.runtime.* +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import kotlinx.coroutines.launch +import me.eternal.purrfectsnap.common.data.ContentType +import me.eternal.purrfectsnap.core.ModContext +import me.eternal.purrfectsnap.core.wrapper.impl.Message +import me.eternal.purrfectsnap.core.wrapper.impl.getMessageText + +class TranslationUI(private val context: ModContext) { + private val translationManager by lazy { TranslationManager(context) } + private val config by lazy { context.config.messaging.instantTranslation } + + @Composable + fun TranslationOverlay( + message: Message, + onDismiss: () -> Unit + ) { + var originalText by remember { mutableStateOf("") } + var translatedText by remember { mutableStateOf("") } + var isLoading by remember { mutableStateOf(false) } + var error by remember { mutableStateOf(null) } + + val coroutineScope = rememberCoroutineScope() + + LaunchedEffect(message) { + originalText = message.messageContent?.content?.getMessageText(ContentType.CHAT) ?: "" + if (originalText.isNotBlank()) { + isLoading = true + error = null + + coroutineScope.launch { + try { + val translation = translationManager.translateText( + originalText, + "auto", + "en" + ) + translatedText = translation ?: "" + if (translation == null) { + error = "Translation failed" + } + } catch (e: Exception) { + error = "Translation error: ${e.message}" + } finally { + isLoading = false + } + } + } + } + + Card( + modifier = Modifier + .fillMaxWidth() + .padding(16.dp), + colors = CardDefaults.cardColors( + containerColor = MaterialTheme.colorScheme.surface + ) + ) { + Column( + modifier = Modifier.padding(16.dp) + ) { + Text( + text = "Translation", + fontSize = 18.sp, + fontWeight = FontWeight.Bold, + modifier = Modifier.padding(bottom = 8.dp) + ) + + if (isLoading) { + CircularProgressIndicator( + modifier = Modifier.align(Alignment.CenterHorizontally) + ) + } else if (error != null) { + Text( + text = error!!, + color = Color.Red, + modifier = Modifier.padding(vertical = 8.dp) + ) + } else { + Text( + text = "Original:", + fontWeight = FontWeight.Bold, + modifier = Modifier.padding(bottom = 4.dp) + ) + Text( + text = originalText, + modifier = Modifier.padding(bottom = 12.dp) + ) + + Text( + text = "Translation:", + fontWeight = FontWeight.Bold, + modifier = Modifier.padding(bottom = 4.dp) + ) + Text( + text = translatedText, + modifier = Modifier.padding(bottom = 12.dp) + ) + } + + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.SpaceEvenly + ) { + Button( + onClick = onDismiss, + colors = ButtonDefaults.buttonColors( + containerColor = MaterialTheme.colorScheme.surfaceVariant + ) + ) { + Text("Close") + } + + if (translatedText.isNotBlank()) { + Button( + onClick = { + copyToClipboard(translatedText) + } + ) { + Text("Copy Translation") + } + } + } + } + } + } + + fun createTranslationButton( + message: Message, + parentView: View + ): Button { + return Button(parentView.context).apply { + text = "Translate" + setOnClickListener { + showTranslationDialog(message) + } + } + } + + private fun showTranslationDialog(message: Message) { + val originalText = message.messageContent?.content?.getMessageText(ContentType.CHAT) ?: return + + context.coroutineScope.launch { + val translatedText = translationManager.translateText(originalText, "auto", "en") ?: return@launch + + context.runOnUiThread { + val dialog = android.app.AlertDialog.Builder(context.mainActivity!!) + .setTitle("Translation") + .setMessage("Original: $originalText\n\nTranslation: $translatedText") + .setPositiveButton("Copy") { _, _ -> + copyToClipboard(translatedText) + } + .setNegativeButton("Close", null) + .create() + + dialog.show() + } + } + } + + private fun copyToClipboard(text: String) { + val clipboard = context.androidContext.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager + val clip = ClipData.newPlainText("Translation", text) + clipboard.setPrimaryClip(clip) + } +} \ No newline at end of file diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/messaging/UnlimitedSnapViewTime.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/messaging/UnlimitedSnapViewTime.kt similarity index 70% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/messaging/UnlimitedSnapViewTime.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/messaging/UnlimitedSnapViewTime.kt index c3f2bda1..f14cae98 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/messaging/UnlimitedSnapViewTime.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/messaging/UnlimitedSnapViewTime.kt @@ -1,11 +1,11 @@ -package me.rhunk.snapenhance.core.features.impl.messaging +package me.eternal.purrfectsnap.core.features.impl.messaging -import me.rhunk.snapenhance.common.data.ContentType -import me.rhunk.snapenhance.common.data.MessageState -import me.rhunk.snapenhance.common.util.protobuf.ProtoEditor -import me.rhunk.snapenhance.common.util.protobuf.ProtoReader -import me.rhunk.snapenhance.core.event.events.impl.BuildMessageEvent -import me.rhunk.snapenhance.core.features.Feature +import me.eternal.purrfectsnap.common.data.ContentType +import me.eternal.purrfectsnap.common.data.MessageState +import me.eternal.purrfectsnap.common.util.protobuf.ProtoEditor +import me.eternal.purrfectsnap.common.util.protobuf.ProtoReader +import me.eternal.purrfectsnap.core.event.events.impl.BuildMessageEvent +import me.eternal.purrfectsnap.core.features.Feature class UnlimitedSnapViewTime : Feature("UnlimitedSnapViewTime") { override fun init() { diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/spying/FriendTracker.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/spying/FriendTracker.kt similarity index 71% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/spying/FriendTracker.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/spying/FriendTracker.kt index d99b902b..b6604676 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/spying/FriendTracker.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/spying/FriendTracker.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.core.features.impl.spying +package me.eternal.purrfectsnap.core.features.impl.spying import android.app.Notification import android.app.NotificationChannel @@ -6,36 +6,38 @@ import android.app.NotificationManager import android.app.PendingIntent import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Info -import me.rhunk.snapenhance.common.Constants -import me.rhunk.snapenhance.common.data.* -import me.rhunk.snapenhance.common.util.lazyBridge -import me.rhunk.snapenhance.common.util.protobuf.ProtoReader -import me.rhunk.snapenhance.common.util.toParcelable -import me.rhunk.snapenhance.core.features.Feature -import me.rhunk.snapenhance.core.features.impl.messaging.Messaging -import me.rhunk.snapenhance.core.util.hook.HookStage -import me.rhunk.snapenhance.core.util.hook.hook -import me.rhunk.snapenhance.core.util.hook.hookConstructor -import me.rhunk.snapenhance.core.wrapper.impl.SnapUUID -import me.rhunk.snapenhance.core.wrapper.impl.toSnapUUID -import me.rhunk.snapenhance.nativelib.NativeLib +import me.eternal.purrfectsnap.common.Constants +import me.eternal.purrfectsnap.common.data.* +import me.eternal.purrfectsnap.common.util.lazyBridge +import me.eternal.purrfectsnap.common.util.protobuf.ProtoReader +import me.eternal.purrfectsnap.common.util.toParcelable +import me.eternal.purrfectsnap.core.features.Feature +import me.eternal.purrfectsnap.core.features.impl.messaging.Messaging +import me.eternal.purrfectsnap.core.util.hook.HookStage +import me.eternal.purrfectsnap.core.util.hook.hook +import me.eternal.purrfectsnap.core.util.hook.hookConstructor +import me.eternal.purrfectsnap.core.wrapper.impl.SnapUUID +import me.eternal.purrfectsnap.core.wrapper.impl.toSnapUUID +import me.eternal.purrfectsnap.nativelib.NativeLib import java.lang.reflect.Method import java.nio.ByteBuffer +import java.text.DateFormat +import java.util.Date class FriendTracker : Feature("Friend Tracker") { - private val conversationPresenceState = mutableMapOf>() + private val conversationPresenceState = mutableMapOf>() // conversationId -> (userId -> state) private val tracker by lazyBridge { context.bridgeClient.getTracker() } - private val notificationManager by lazy { - context.androidContext.getSystemService(NotificationManager::class.java).apply { - createNotificationChannel( - NotificationChannel( - "friend_tracker", - "Friend Tracker", - NotificationManager.IMPORTANCE_DEFAULT - ) - ) - } - } + private val translation by lazy { context.translation.getCategory("friend_tracker_notifications") } + private val trackerTranslation by lazy { context.translation.getCategory("tracker") } + private val notificationManager by lazy { context.androidContext.getSystemService(NotificationManager::class.java).apply { + createNotificationChannel(NotificationChannel( + "friend_tracker", + translation["notification_channel_name"], + NotificationManager.IMPORTANCE_DEFAULT + )) + } } + private val conversationEntries = mutableMapOf, Long>() + private fun getTrackedEvents(eventType: TrackerEventType): TrackerEventsResult? { return runCatching { tracker.getTrackedEvents(eventType.key)?.let { @@ -45,15 +47,16 @@ class FriendTracker : Feature("Friend Tracker") { context.log.error("Failed to get tracked events for $eventType", it) }.getOrNull() } - private fun isInConversation(conversationId: String?) = - context.feature(Messaging::class).openedConversationUUID?.toString() == conversationId + + private fun isInConversation(conversationId: String?) = context.feature(Messaging::class).openedConversationUUID?.toString() == conversationId + private fun sendInfoNotification(id: Int = System.nanoTime().toInt(), text: String) { notificationManager.notify( id, Notification.Builder( context.androidContext, "friend_tracker" - ) + ) .setSmallIcon(android.R.drawable.ic_dialog_info) .setAutoCancel(true) .setShowWhen(true) @@ -70,9 +73,11 @@ class FriendTracker : Feature("Friend Tracker") { .build() ) } + private fun handleVolatileEvent(protoReader: ProtoReader) { context.log.verbose("volatile event\n$protoReader") } + private fun dispatchEvents( eventType: TrackerEventType, conversationId: String, @@ -80,23 +85,34 @@ class FriendTracker : Feature("Friend Tracker") { extras: String = "" ) { val feedEntry = context.database.getFeedEntryByConversationId(conversationId) - val conversationName = feedEntry?.feedDisplayName ?: "DMs" - val authorName = context.database.getFriendInfo(userId)?.mutableUsername ?: "Unknown" + val friendInfo = context.database.getFriendInfo(userId) + val conversationName = feedEntry?.feedDisplayName ?: trackerTranslation["logs.log_entry.unknown_conversation"] + val authorName = friendInfo?.displayName ?: friendInfo?.mutableUsername ?: trackerTranslation["logs.log_entry.unknown_user"] + context.log.verbose("$authorName $eventType in $conversationName") + getTrackedEvents(eventType)?.takeIf { it.canTrackOn(conversationId, userId) }?.getActions()?.forEach { (action, params) -> if ((params.onlyWhenAppActive || action == TrackerRuleAction.IN_APP_NOTIFICATION) && context.isMainActivityPaused) return@forEach if (params.onlyWhenAppInactive && !context.isMainActivityPaused) return@forEach if (params.onlyInsideConversation && !isInConversation(conversationId)) return@forEach if (params.onlyOutsideConversation && isInConversation(conversationId)) return@forEach + context.log.verbose("dispatching $action for $eventType in $conversationName") + + val iCanSeeYouDetails = if (eventType == TrackerEventType.I_CAN_SEE_YOU) buildICanSeeYouDetails(extras) else "" + val notificationText = translation[eventType.key] + .replace("{friend}", authorName) + .replace("{conversation}", conversationName) + .replace("{details}", iCanSeeYouDetails) + when (action) { TrackerRuleAction.PUSH_NOTIFICATION -> { if (params.noPushNotificationWhenAppActive && !context.isMainActivityPaused) return@forEach - sendInfoNotification(text = "$authorName $eventType in $conversationName") + sendInfoNotification(text = notificationText) } TrackerRuleAction.IN_APP_NOTIFICATION -> context.inAppOverlay.showStatusToast( icon = Icons.Default.Info, - text = "$authorName $eventType in $conversationName" + text = notificationText ) TrackerRuleAction.LOG -> context.bridgeClient.getMessageLogger().logTrackerEvent( conversationId, @@ -107,15 +123,62 @@ class FriendTracker : Feature("Friend Tracker") { eventType.key, extras ) - TrackerRuleAction.CUSTOM -> { - // If TrackerRuleAction enum has a CUSTOM branch, handle it here! - // If not used, you may log or leave empty as needed. - } + else -> {} } } } + + private fun buildICanSeeYouExtras(entry: Long?, exit: Long?, duration: Long?) = listOf( + entry ?: -1, + exit ?: -1, + duration ?: -1 + ).joinToString("|") + + private fun buildICanSeeYouDetails(extras: String): String { + val values = extras.split("|").map { it.toLongOrNull() ?: -1L }.let { + if (it.size >= 3) it else it + List(3 - it.size) { -1L } + } + val entered = values[0].takeIf { it >= 0 } + val exited = values[1].takeIf { it >= 0 } + val duration = values[2].takeIf { it >= 0 } + val enteredLabel = trackerTranslation["logs.log_entry.i_can_see_you_entered"] + val leftLabel = trackerTranslation["logs.log_entry.i_can_see_you_left"] + val durationLabel = trackerTranslation["logs.log_entry.i_can_see_you_duration"] + val notAvailable = trackerTranslation["logs.log_entry.i_can_see_you_not_available"] + val enteredText = formatICanSeeYouTime(entered, notAvailable) + val leftText = formatICanSeeYouTime(exited, notAvailable) + val durationText = formatICanSeeYouDuration(duration, notAvailable) + return listOf( + "$enteredLabel: $enteredText", + "$durationLabel: $durationText", + "$leftLabel: $leftText" + ).joinToString(" · ") + } + + private fun formatICanSeeYouTime(value: Long?, fallback: String): String { + if (value == null || value < 0) return fallback + return DateFormat.getTimeInstance(DateFormat.MEDIUM).format(Date(value)) + } + + private fun formatICanSeeYouDuration(value: Long?, fallback: String): String { + if (value == null || value < 0) return fallback + val totalSeconds = (value / 1000).coerceAtLeast(0) + val hours = totalSeconds / 3600 + val minutes = (totalSeconds % 3600) / 60 + val seconds = totalSeconds % 60 + val hourUnit = trackerTranslation["logs.log_entry.i_can_see_you_unit_hour"] + val minuteUnit = trackerTranslation["logs.log_entry.i_can_see_you_unit_minute"] + val secondUnit = trackerTranslation["logs.log_entry.i_can_see_you_unit_second"] + val parts = mutableListOf() + if (hours > 0) parts.add("${hours}${hourUnit}") + if (minutes > 0 || hours > 0) parts.add("${minutes}${minuteUnit}") + parts.add("${seconds}${secondUnit}") + return parts.joinToString(" ") + } + private fun onConversationPresenceUpdate(conversationId: String, userId: String, oldState: FriendPresenceState?, currentState: FriendPresenceState?) { context.log.verbose("presence state for $userId in conversation $conversationId\n$currentState") + val eventType = when { (oldState == null || currentState?.bitmojiPresent == false) && currentState?.bitmojiPresent == true -> TrackerEventType.CONVERSATION_ENTER (currentState == null || oldState?.bitmojiPresent == false) && oldState?.bitmojiPresent == true -> TrackerEventType.CONVERSATION_EXIT @@ -125,11 +188,32 @@ class FriendTracker : Feature("Friend Tracker") { oldState?.peeking == true && (currentState == null || !currentState.peeking) -> TrackerEventType.STOPPED_PEEKING else -> null } ?: return + + when (eventType) { + TrackerEventType.CONVERSATION_ENTER -> { + conversationEntries[conversationId to userId] = System.currentTimeMillis() + } + TrackerEventType.CONVERSATION_EXIT -> { + val key = conversationId to userId + val exit = System.currentTimeMillis() + val entry = conversationEntries.remove(key) + dispatchEvents( + TrackerEventType.I_CAN_SEE_YOU, + conversationId, + userId, + buildICanSeeYouExtras(entry, exit, entry?.let { exit - it }) + ) + } + else -> {} + } + dispatchEvents(eventType, conversationId, userId) } + private fun onConversationMessagingEvent(event: SessionEvent) { context.log.verbose("conversation messaging event\n${event.type} in ${event.conversationId} from ${event.authorUserId}") - val eventType = when (event.type) { + + val eventType = when(event.type) { SessionEventType.MESSAGE_READ_RECEIPTS -> TrackerEventType.MESSAGE_READ SessionEventType.MESSAGE_DELETED -> TrackerEventType.MESSAGE_DELETED SessionEventType.MESSAGE_REACTION_ADD -> TrackerEventType.MESSAGE_REACTION_ADD @@ -142,30 +226,36 @@ class FriendTracker : Feature("Friend Tracker") { SessionEventType.SNAP_REPLAYED_TWICE -> TrackerEventType.SNAP_REPLAYED_TWICE SessionEventType.SNAP_SCREENSHOT -> TrackerEventType.SNAP_SCREENSHOT SessionEventType.SNAP_SCREEN_RECORD -> TrackerEventType.SNAP_SCREEN_RECORD + else -> return } + val conversationMessage by lazy { (event as? SessionMessageEvent)?.serverMessageId?.let { context.database.getConversationServerMessage(event.conversationId, it) } } + dispatchEvents(eventType, event.conversationId, event.authorUserId, extras = conversationMessage?.takeIf { eventType == TrackerEventType.MESSAGE_READ || - eventType == TrackerEventType.MESSAGE_REACTION_ADD || - eventType == TrackerEventType.MESSAGE_REACTION_REMOVE || - eventType == TrackerEventType.MESSAGE_DELETED || - eventType == TrackerEventType.MESSAGE_SAVED || - eventType == TrackerEventType.MESSAGE_UNSAVED || - eventType == TrackerEventType.MESSAGE_EDITED + eventType == TrackerEventType.MESSAGE_REACTION_ADD || + eventType == TrackerEventType.MESSAGE_REACTION_REMOVE || + eventType == TrackerEventType.MESSAGE_DELETED || + eventType == TrackerEventType.MESSAGE_SAVED || + eventType == TrackerEventType.MESSAGE_UNSAVED || + eventType == TrackerEventType.MESSAGE_EDITED }?.contentType?.let { ContentType.fromId(it).name } ?: "") } + private fun handlePresenceEvent(protoReader: ProtoReader) { val conversationId = protoReader.getString(6) ?: return + val presenceMap = conversationPresenceState.getOrPut(conversationId) { mutableMapOf() }.toMutableMap() val userIds = mutableSetOf() + protoReader.eachBuffer(4) { val participantUserId = getString(1)?.takeIf { it.contains(":") }?.substringBefore(":") ?: return@eachBuffer userIds.add(participantUserId) if (participantUserId == context.database.myUserId) return@eachBuffer - val stateMap = getVarInt(2, 1)?.toString(2)?.padStart(16, '0')?.reversed()?.map { it == '1' } - ?: return@eachBuffer + val stateMap = getVarInt(2, 1)?.toString(2)?.padStart(16, '0')?.reversed()?.map { it == '1' } ?: return@eachBuffer + presenceMap[participantUserId] = FriendPresenceState( bitmojiPresent = stateMap[0], typing = stateMap[4], @@ -174,21 +264,28 @@ class FriendTracker : Feature("Friend Tracker") { peeking = stateMap[8] ) } + presenceMap.keys.filterNot { it in userIds }.forEach { presenceMap[it] = null } + presenceMap.forEach { (userId, state) -> val oldState = conversationPresenceState[conversationId]?.get(userId) if (oldState != state) { onConversationPresenceUpdate(conversationId, userId, oldState, state) } } + conversationPresenceState[conversationId] = presenceMap } + private fun handleMessagingEvent(protoReader: ProtoReader) { + // read receipts protoReader.followPath(12) { val conversationId = getByteArray(1, 1)?.toSnapUUID()?.toString() ?: return@followPath + followPath(7) readReceipts@{ val senderId = getByteArray(1, 1)?.toSnapUUID()?.toString() ?: return@readReceipts val serverMessageId = getVarInt(2, 2) ?: return@readReceipts + onConversationMessagingEvent( SessionMessageEvent( SessionEventType.MESSAGE_READ_RECEIPTS, @@ -199,10 +296,12 @@ class FriendTracker : Feature("Friend Tracker") { ) } } + protoReader.followPath(13, 1, 4) { val serverMessageId = getVarInt(1) ?: return@followPath val senderId = getByteArray(2, 1) ?: return@followPath val conversationId = getByteArray(3, 1, 1, 1) ?: return@followPath + onConversationMessagingEvent( SessionMessageEvent( SessionEventType.MESSAGE_EDITED, @@ -212,10 +311,12 @@ class FriendTracker : Feature("Friend Tracker") { ) ) } + protoReader.followPath(6, 2) { val conversationId = getByteArray(3, 1)?.toSnapUUID()?.toString() ?: return@followPath val senderId = getByteArray(1, 1)?.toSnapUUID()?.toString() ?: return@followPath val serverMessageId = getVarInt(2) ?: return@followPath + if (contains(4)) { onConversationMessagingEvent( SessionMessageEvent( @@ -226,6 +327,7 @@ class FriendTracker : Feature("Friend Tracker") { ) ) } + if (contains(13)) { onConversationMessagingEvent( SessionMessageEvent( @@ -236,6 +338,7 @@ class FriendTracker : Feature("Friend Tracker") { ) ) } + if (contains(6) || contains(7)) { onConversationMessagingEvent( SessionMessageEvent( @@ -246,6 +349,7 @@ class FriendTracker : Feature("Friend Tracker") { ) ) } + if (contains(11) || contains(12)) { onConversationMessagingEvent( SessionMessageEvent( @@ -256,6 +360,7 @@ class FriendTracker : Feature("Friend Tracker") { ) ) } + followPath(16) { onConversationMessagingEvent( SessionMessageEvent( @@ -263,11 +368,13 @@ class FriendTracker : Feature("Friend Tracker") { ) ) } + if (contains(17)) { onConversationMessagingEvent( SessionMessageEvent(SessionEventType.MESSAGE_REACTION_REMOVE, conversationId, senderId, serverMessageId) ) } + followPath(8) { onConversationMessagingEvent( SessionMessageEvent(SessionEventType.MESSAGE_DELETED, conversationId, senderId, serverMessageId, messageData = getByteArray(1)) @@ -275,14 +382,18 @@ class FriendTracker : Feature("Friend Tracker") { } } } + override fun init() { val sessionEventsConfig = context.config.friendTracker if (sessionEventsConfig.globalState != true) return + if (sessionEventsConfig.allowRunningInBackground.get()) { findClass("com.snapchat.client.duplex.DuplexClient\$CppProxy").apply { + // prevent disabling events when the app is inactive hook("appStateChanged", HookStage.BEFORE) { param -> if (param.arg(0).toString() == "INACTIVE") param.setResult(null) } + // allow events when a notification is received hookConstructor(HookStage.AFTER) { param -> methods.first { it.name == "appStateChanged" }.let { method -> method.invoke(param.thisObject(), method.parameterTypes[0].enumConstants!!.first { it.toString() == "ACTIVE" }) @@ -290,10 +401,12 @@ class FriendTracker : Feature("Friend Tracker") { } } } + if (sessionEventsConfig.recordMessagingEvents.get()) { val messageHandlerClass = findClass("com.snapchat.client.duplex.MessageHandler\$CppProxy").apply { hook("onReceive", HookStage.BEFORE) { param -> param.setResult(null) + val byteBuffer = param.arg(0) val content = byteBuffer.let { val bytes = ByteArray(it.limit()) @@ -307,6 +420,7 @@ class FriendTracker : Feature("Friend Tracker") { handleVolatileEvent(eventData) return@hook } + if (it == "presence") { handlePresenceEvent(eventData) return@hook @@ -316,11 +430,14 @@ class FriendTracker : Feature("Friend Tracker") { } hook("nativeDestroy", HookStage.BEFORE) { it.setResult(null) } } + + findClass("com.snapchat.client.messaging.Session").hook("create", HookStage.BEFORE) { param -> if (!NativeLib.initialized) { context.log.warn("Can't register duplex message handler, native lib not initialized") return@hook } + val method = param.method() as Method val duplexClient = method.parameterTypes.indexOfFirst { it.name.endsWith("DuplexClient") }.let { param.arg(it) diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/spying/HalfSwipeNotifier.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/spying/HalfSwipeNotifier.kt similarity index 85% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/spying/HalfSwipeNotifier.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/spying/HalfSwipeNotifier.kt index 37f270fd..447fa1c8 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/spying/HalfSwipeNotifier.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/spying/HalfSwipeNotifier.kt @@ -1,22 +1,23 @@ -package me.rhunk.snapenhance.core.features.impl.spying +package me.eternal.purrfectsnap.core.features.impl.spying import android.app.Notification import android.app.NotificationChannel import android.app.NotificationManager import android.app.PendingIntent -import me.rhunk.snapenhance.common.Constants -import me.rhunk.snapenhance.core.features.Feature -import me.rhunk.snapenhance.core.util.hook.HookStage -import me.rhunk.snapenhance.core.util.hook.hook -import me.rhunk.snapenhance.core.util.hook.hookConstructor -import me.rhunk.snapenhance.core.util.ktx.getObjectField -import me.rhunk.snapenhance.mapper.impl.CallbackMapper +import me.eternal.purrfectsnap.common.Constants +import me.eternal.purrfectsnap.core.features.Feature +import me.eternal.purrfectsnap.core.util.hook.HookStage +import me.eternal.purrfectsnap.core.util.hook.hook +import me.eternal.purrfectsnap.core.util.hook.hookConstructor +import me.eternal.purrfectsnap.core.util.ktx.getObjectField +import me.eternal.purrfectsnap.mapper.impl.CallbackMapper import java.util.concurrent.ConcurrentHashMap import kotlin.time.Duration.Companion.milliseconds class HalfSwipeNotifier : Feature("Half Swipe Notifier") { private val peekingConversations = ConcurrentHashMap>() private val startPeekingTimestamps = ConcurrentHashMap() + private val halfSwipeListeners = mutableListOf<(String, String, Long) -> Unit>() private val notificationManager get() = context.androidContext.getSystemService(NotificationManager::class.java) private val translation by lazy { context.translation.getCategory("half_swipe_notifier")} @@ -32,6 +33,9 @@ class HalfSwipeNotifier : Feature("Half Swipe Notifier") { } } + fun addOnHalfSwipeListener(listener: (conversationId: String, userId: String, duration: Long) -> Unit) { + halfSwipeListeners.add(listener) + } override fun init() { if (context.config.messaging.halfSwipeNotifier.globalState != true) return @@ -89,6 +93,15 @@ class HalfSwipeNotifier : Feature("Half Swipe Notifier") { if (minDuration > peekingDuration || maxDuration < peekingDuration) return + // Notify listeners about the half-swipe + halfSwipeListeners.forEach { listener -> + runCatching { + listener(conversationId, userId, peekingDuration) + }.onFailure { + context.log.error("Error in half-swipe listener", it) + } + } + val feedEntry = context.database.getFeedEntryByConversationId(conversationId) val friendInfo = context.database.getFriendInfo(userId) ?: return diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/spying/MessageLogger.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/spying/MessageLogger.kt similarity index 89% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/spying/MessageLogger.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/spying/MessageLogger.kt index 7b165265..fb31ea98 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/spying/MessageLogger.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/spying/MessageLogger.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.core.features.impl.spying +package me.eternal.purrfectsnap.core.features.impl.spying import android.graphics.Canvas import android.graphics.Paint @@ -7,23 +7,23 @@ import android.graphics.drawable.shapes.Shape import android.os.DeadObjectException import com.google.gson.JsonObject import com.google.gson.JsonParser -import me.rhunk.snapenhance.bridge.logger.BridgeLoggedMessage -import me.rhunk.snapenhance.bridge.logger.LoggedChatEdit -import me.rhunk.snapenhance.common.config.impl.MessagingTweaks -import me.rhunk.snapenhance.common.data.ContentType -import me.rhunk.snapenhance.common.data.MessageState -import me.rhunk.snapenhance.common.data.MessagingRuleType -import me.rhunk.snapenhance.common.data.QuotedMessageContentStatus -import me.rhunk.snapenhance.common.data.RuleState -import me.rhunk.snapenhance.common.util.ktx.longHashCode -import me.rhunk.snapenhance.common.util.lazyBridge -import me.rhunk.snapenhance.common.util.protobuf.ProtoReader -import me.rhunk.snapenhance.core.event.events.impl.BindViewEvent -import me.rhunk.snapenhance.core.event.events.impl.BuildMessageEvent -import me.rhunk.snapenhance.core.features.MessagingRuleFeature -import me.rhunk.snapenhance.core.ui.addForegroundDrawable -import me.rhunk.snapenhance.core.ui.removeForegroundDrawable -import me.rhunk.snapenhance.core.util.EvictingMap +import me.eternal.purrfectsnap.bridge.logger.BridgeLoggedMessage +import me.eternal.purrfectsnap.bridge.logger.LoggedChatEdit +import me.eternal.purrfectsnap.common.config.impl.MessagingTweaks +import me.eternal.purrfectsnap.common.data.ContentType +import me.eternal.purrfectsnap.common.data.MessageState +import me.eternal.purrfectsnap.common.data.MessagingRuleType +import me.eternal.purrfectsnap.common.data.QuotedMessageContentStatus +import me.eternal.purrfectsnap.common.data.RuleState +import me.eternal.purrfectsnap.common.util.ktx.longHashCode +import me.eternal.purrfectsnap.common.util.lazyBridge +import me.eternal.purrfectsnap.common.util.protobuf.ProtoReader +import me.eternal.purrfectsnap.core.event.events.impl.BindViewEvent +import me.eternal.purrfectsnap.core.event.events.impl.BuildMessageEvent +import me.eternal.purrfectsnap.core.features.MessagingRuleFeature +import me.eternal.purrfectsnap.core.ui.addForegroundDrawable +import me.eternal.purrfectsnap.core.ui.removeForegroundDrawable +import me.eternal.purrfectsnap.core.util.EvictingMap import java.util.concurrent.Executors import kotlin.system.measureTimeMillis @@ -199,4 +199,4 @@ class MessageLogger : MessagingRuleFeature("MessageLogger", MessagingRuleType.ME } } } -} \ No newline at end of file +} diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/spying/StealthMode.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/spying/StealthMode.kt similarity index 74% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/spying/StealthMode.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/spying/StealthMode.kt index 079d0f7e..5effa879 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/spying/StealthMode.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/spying/StealthMode.kt @@ -1,11 +1,11 @@ -package me.rhunk.snapenhance.core.features.impl.spying +package me.eternal.purrfectsnap.core.features.impl.spying -import me.rhunk.snapenhance.common.data.MessagingRuleType -import me.rhunk.snapenhance.core.event.events.impl.OnSnapInteractionEvent -import me.rhunk.snapenhance.core.features.MessagingRuleFeature -import me.rhunk.snapenhance.core.util.hook.HookStage -import me.rhunk.snapenhance.core.util.hook.hook -import me.rhunk.snapenhance.core.wrapper.impl.SnapUUID +import me.eternal.purrfectsnap.common.data.MessagingRuleType +import me.eternal.purrfectsnap.core.event.events.impl.OnSnapInteractionEvent +import me.eternal.purrfectsnap.core.features.MessagingRuleFeature +import me.eternal.purrfectsnap.core.util.hook.HookStage +import me.eternal.purrfectsnap.core.util.hook.hook +import me.eternal.purrfectsnap.core.wrapper.impl.SnapUUID import java.util.concurrent.CopyOnWriteArraySet class StealthMode : MessagingRuleFeature("StealthMode", MessagingRuleType.STEALTH) { @@ -22,6 +22,7 @@ class StealthMode : MessagingRuleFeature("StealthMode", MessagingRuleType.STEALT override fun init() { + if (getRuleState() == null) return val isConversationInStealthMode: (SnapUUID) -> Boolean = { canUseRule(it.toString()) } arrayOf("mediaMessagesDisplayed", "displayedMessages").forEach { methodName: String -> @@ -40,4 +41,4 @@ class StealthMode : MessagingRuleFeature("StealthMode", MessagingRuleType.STEALT } } } -} \ No newline at end of file +} diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/tweaks/BypassScreenshotDetection.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/tweaks/BypassScreenshotDetection.kt similarity index 80% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/tweaks/BypassScreenshotDetection.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/tweaks/BypassScreenshotDetection.kt index cafef0f8..57987355 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/tweaks/BypassScreenshotDetection.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/tweaks/BypassScreenshotDetection.kt @@ -1,12 +1,12 @@ -package me.rhunk.snapenhance.core.features.impl.tweaks +package me.eternal.purrfectsnap.core.features.impl.tweaks import android.app.Activity import android.content.ContentResolver import android.database.ContentObserver import android.net.Uri -import me.rhunk.snapenhance.core.features.Feature -import me.rhunk.snapenhance.core.util.hook.HookStage -import me.rhunk.snapenhance.core.util.hook.hook +import me.eternal.purrfectsnap.core.features.Feature +import me.eternal.purrfectsnap.core.util.hook.HookStage +import me.eternal.purrfectsnap.core.util.hook.hook class BypassScreenshotDetection : Feature("BypassScreenshotDetection") { override fun init() { diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/tweaks/CameraTweaks.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/tweaks/CameraTweaks.kt similarity index 95% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/tweaks/CameraTweaks.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/tweaks/CameraTweaks.kt index 765da077..a5ef7e8d 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/tweaks/CameraTweaks.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/tweaks/CameraTweaks.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.core.features.impl.tweaks +package me.eternal.purrfectsnap.core.features.impl.tweaks import android.Manifest import android.annotation.SuppressLint @@ -11,10 +11,10 @@ import android.hardware.camera2.CameraManager import android.media.Image import android.media.ImageReader import android.util.Range -import me.rhunk.snapenhance.core.features.Feature -import me.rhunk.snapenhance.core.util.hook.HookStage -import me.rhunk.snapenhance.core.util.hook.hook -import me.rhunk.snapenhance.core.util.ktx.setObjectField +import me.eternal.purrfectsnap.core.features.Feature +import me.eternal.purrfectsnap.core.util.hook.HookStage +import me.eternal.purrfectsnap.core.util.hook.hook +import me.eternal.purrfectsnap.core.util.ktx.setObjectField import java.io.ByteArrayOutputStream import java.nio.ByteBuffer diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/tweaks/DisablePermissionRequests.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/tweaks/DisablePermissionRequests.kt similarity index 71% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/tweaks/DisablePermissionRequests.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/tweaks/DisablePermissionRequests.kt index 077e9410..e4ae8b8d 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/tweaks/DisablePermissionRequests.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/tweaks/DisablePermissionRequests.kt @@ -1,11 +1,11 @@ -package me.rhunk.snapenhance.core.features.impl.tweaks +package me.eternal.purrfectsnap.core.features.impl.tweaks import android.content.ContextWrapper import android.content.pm.PackageManager -import me.rhunk.snapenhance.common.config.impl.Global -import me.rhunk.snapenhance.core.features.Feature -import me.rhunk.snapenhance.core.util.hook.HookStage -import me.rhunk.snapenhance.core.util.hook.hook +import me.eternal.purrfectsnap.common.config.impl.Global +import me.eternal.purrfectsnap.core.features.Feature +import me.eternal.purrfectsnap.core.util.hook.HookStage +import me.eternal.purrfectsnap.core.util.hook.hook class DisablePermissionRequests : Feature("Disable Permission Requests") { override fun init() { diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/tweaks/DisableSnapModeRestrictions.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/tweaks/DisableSnapModeRestrictions.kt similarity index 60% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/tweaks/DisableSnapModeRestrictions.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/tweaks/DisableSnapModeRestrictions.kt index ba44d2d3..599ba80e 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/tweaks/DisableSnapModeRestrictions.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/tweaks/DisableSnapModeRestrictions.kt @@ -1,9 +1,9 @@ -package me.rhunk.snapenhance.core.features.impl.tweaks +package me.eternal.purrfectsnap.core.features.impl.tweaks -import me.rhunk.snapenhance.core.features.Feature -import me.rhunk.snapenhance.core.util.dataBuilder -import me.rhunk.snapenhance.core.util.hook.HookStage -import me.rhunk.snapenhance.core.util.hook.hookConstructor +import me.eternal.purrfectsnap.core.features.Feature +import me.eternal.purrfectsnap.core.util.dataBuilder +import me.eternal.purrfectsnap.core.util.hook.HookStage +import me.eternal.purrfectsnap.core.util.hook.hookConstructor class DisableSnapModeRestrictions: Feature("Disable Snap Mode Restrictions") { override fun init() { diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/tweaks/DoubleTapChatAction.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/tweaks/DoubleTapChatAction.kt similarity index 78% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/tweaks/DoubleTapChatAction.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/tweaks/DoubleTapChatAction.kt index 578bc04f..05e092b5 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/tweaks/DoubleTapChatAction.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/tweaks/DoubleTapChatAction.kt @@ -1,16 +1,16 @@ -package me.rhunk.snapenhance.core.features.impl.tweaks +package me.eternal.purrfectsnap.core.features.impl.tweaks -import me.rhunk.snapenhance.common.data.ContentType -import me.rhunk.snapenhance.common.data.MessageUpdate -import me.rhunk.snapenhance.common.util.ktx.copyToClipboard -import me.rhunk.snapenhance.common.util.ktx.findFieldsToString -import me.rhunk.snapenhance.common.util.protobuf.ProtoReader -import me.rhunk.snapenhance.core.features.Feature -import me.rhunk.snapenhance.core.features.impl.messaging.Messaging -import me.rhunk.snapenhance.core.util.hook.HookStage -import me.rhunk.snapenhance.core.util.hook.hook -import me.rhunk.snapenhance.core.wrapper.impl.getMessageText -import me.rhunk.snapenhance.mapper.impl.ChatEventDispatcherMapper +import me.eternal.purrfectsnap.common.data.ContentType +import me.eternal.purrfectsnap.common.data.MessageUpdate +import me.eternal.purrfectsnap.common.util.ktx.copyToClipboard +import me.eternal.purrfectsnap.common.util.ktx.findFieldsToString +import me.eternal.purrfectsnap.common.util.protobuf.ProtoReader +import me.eternal.purrfectsnap.core.features.Feature +import me.eternal.purrfectsnap.core.features.impl.messaging.Messaging +import me.eternal.purrfectsnap.core.util.hook.HookStage +import me.eternal.purrfectsnap.core.util.hook.hook +import me.eternal.purrfectsnap.core.wrapper.impl.getMessageText +import me.eternal.purrfectsnap.mapper.impl.ChatEventDispatcherMapper class DoubleTapChatAction: Feature("Double Tap Chat Action") { override fun init() { diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/tweaks/HideActiveMusic.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/tweaks/HideActiveMusic.kt similarity index 62% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/tweaks/HideActiveMusic.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/tweaks/HideActiveMusic.kt index c7f95ae8..aa00f05c 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/tweaks/HideActiveMusic.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/tweaks/HideActiveMusic.kt @@ -1,9 +1,9 @@ -package me.rhunk.snapenhance.core.features.impl.tweaks +package me.eternal.purrfectsnap.core.features.impl.tweaks import android.media.AudioManager -import me.rhunk.snapenhance.core.features.Feature -import me.rhunk.snapenhance.core.util.hook.HookStage -import me.rhunk.snapenhance.core.util.hook.hook +import me.eternal.purrfectsnap.core.features.Feature +import me.eternal.purrfectsnap.core.util.hook.HookStage +import me.eternal.purrfectsnap.core.util.hook.hook class HideActiveMusic: Feature("Hide Active Music") { override fun init() { diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/tweaks/PreventForcedKeyboard.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/tweaks/PreventForcedKeyboard.kt similarity index 71% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/tweaks/PreventForcedKeyboard.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/tweaks/PreventForcedKeyboard.kt index 7919b2a3..fd7127f0 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/tweaks/PreventForcedKeyboard.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/tweaks/PreventForcedKeyboard.kt @@ -1,10 +1,10 @@ -package me.rhunk.snapenhance.core.features.impl.tweaks +package me.eternal.purrfectsnap.core.features.impl.tweaks import android.view.View import android.view.inputmethod.InputMethodManager -import me.rhunk.snapenhance.core.features.Feature -import me.rhunk.snapenhance.core.util.hook.HookStage -import me.rhunk.snapenhance.core.util.hook.hook +import me.eternal.purrfectsnap.core.features.Feature +import me.eternal.purrfectsnap.core.util.hook.HookStage +import me.eternal.purrfectsnap.core.util.hook.hook class PreventForcedKeyboard : Feature("Prevent Forced Keyboard") { override fun init() { diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/tweaks/PreventMessageListAutoScroll.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/tweaks/PreventMessageListAutoScroll.kt similarity index 85% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/tweaks/PreventMessageListAutoScroll.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/tweaks/PreventMessageListAutoScroll.kt index 5c6e9425..6de0b5f6 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/tweaks/PreventMessageListAutoScroll.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/tweaks/PreventMessageListAutoScroll.kt @@ -1,13 +1,13 @@ -package me.rhunk.snapenhance.core.features.impl.tweaks +package me.eternal.purrfectsnap.core.features.impl.tweaks import android.util.SparseIntArray import androidx.core.util.size -import me.rhunk.snapenhance.core.features.Feature -import me.rhunk.snapenhance.core.util.hook.HookStage -import me.rhunk.snapenhance.core.util.hook.hook -import me.rhunk.snapenhance.core.util.ktx.getObjectField -import me.rhunk.snapenhance.core.util.ktx.setObjectField -import me.rhunk.snapenhance.mapper.impl.FoldingLayoutMapper +import me.eternal.purrfectsnap.core.features.Feature +import me.eternal.purrfectsnap.core.util.hook.HookStage +import me.eternal.purrfectsnap.core.util.hook.hook +import me.eternal.purrfectsnap.core.util.ktx.getObjectField +import me.eternal.purrfectsnap.core.util.ktx.setObjectField +import me.eternal.purrfectsnap.mapper.impl.FoldingLayoutMapper class PreventMessageListAutoScroll : Feature("PreventMessageListAutoScroll") { diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/tweaks/RemoveGroupsLockedStatus.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/tweaks/RemoveGroupsLockedStatus.kt similarity index 62% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/tweaks/RemoveGroupsLockedStatus.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/tweaks/RemoveGroupsLockedStatus.kt index 8fc287cc..dd35470f 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/tweaks/RemoveGroupsLockedStatus.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/tweaks/RemoveGroupsLockedStatus.kt @@ -1,9 +1,9 @@ -package me.rhunk.snapenhance.core.features.impl.tweaks +package me.eternal.purrfectsnap.core.features.impl.tweaks -import me.rhunk.snapenhance.core.features.Feature -import me.rhunk.snapenhance.core.util.dataBuilder -import me.rhunk.snapenhance.core.util.hook.HookStage -import me.rhunk.snapenhance.core.util.hook.hookConstructor +import me.eternal.purrfectsnap.core.features.Feature +import me.eternal.purrfectsnap.core.util.dataBuilder +import me.eternal.purrfectsnap.core.util.hook.HookStage +import me.eternal.purrfectsnap.core.util.hook.hookConstructor class RemoveGroupsLockedStatus : Feature("Remove Groups Locked Status") { override fun init() { diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/tweaks/RequerySqlite.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/tweaks/RequerySqlite.kt similarity index 86% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/tweaks/RequerySqlite.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/tweaks/RequerySqlite.kt index 46662b9f..7410362e 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/tweaks/RequerySqlite.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/tweaks/RequerySqlite.kt @@ -1,9 +1,9 @@ -package me.rhunk.snapenhance.core.features.impl.tweaks +package me.eternal.purrfectsnap.core.features.impl.tweaks -import me.rhunk.snapenhance.common.data.MessagingRuleType -import me.rhunk.snapenhance.core.features.Feature -import me.rhunk.snapenhance.core.util.hook.HookStage -import me.rhunk.snapenhance.core.util.hook.hook +import me.eternal.purrfectsnap.common.data.MessagingRuleType +import me.eternal.purrfectsnap.core.features.Feature +import me.eternal.purrfectsnap.core.util.hook.HookStage +import me.eternal.purrfectsnap.core.util.hook.hook class RequerySqlite : Feature("Requery Sqlite") { override fun init() { diff --git a/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/tweaks/UnsaveableMessages.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/tweaks/UnsaveableMessages.kt new file mode 100644 index 00000000..4151853a --- /dev/null +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/tweaks/UnsaveableMessages.kt @@ -0,0 +1,130 @@ +package me.eternal.purrfectsnap.core.features.impl.tweaks + +import de.robv.android.xposed.XposedHelpers +import me.eternal.purrfectsnap.common.data.ContentType +import me.eternal.purrfectsnap.common.data.MessagingRuleType +import me.eternal.purrfectsnap.common.util.protobuf.ProtoEditor +import me.eternal.purrfectsnap.common.util.protobuf.ProtoReader +import me.eternal.purrfectsnap.core.event.events.impl.NativeUnaryCallEvent +import me.eternal.purrfectsnap.core.event.events.impl.SendMessageWithContentEvent +import me.eternal.purrfectsnap.core.features.MessagingRuleFeature + +class UnsaveableMessages : MessagingRuleFeature( + "Unsaveable Messages", + MessagingRuleType.UNSAVEABLE_MESSAGES +) { + private var shouldModifySavePolicy = false + + override fun init() { + val ruleState = context.config.rules.getRuleState(MessagingRuleType.UNSAVEABLE_MESSAGES) + if (ruleState == null) return + + context.event.subscribe(SendMessageWithContentEvent::class) { event -> + shouldModifySavePolicy = false + + if (event.destinations.stories?.isNotEmpty() == true && event.destinations.conversations?.isEmpty() == true) return@subscribe + + val localMessageContent = event.messageContent + if (localMessageContent.contentType == ContentType.STATUS) return@subscribe + + val conversationIds = event.destinations.conversations?.map { it.toString() } ?: emptyList() + val shouldApply = if (conversationIds.isEmpty()) { + true + } else { + conversationIds.all { canUseRule(it) } + } + + if (!shouldApply) return@subscribe + + shouldModifySavePolicy = true + + // Modify mSavePolicy directly using XposedHelpers + try { + val savePolicyEnumClass = runCatching { + XposedHelpers.findClass("com.snapchat.client.messaging.SavePolicy", + localMessageContent.instanceNonNull().javaClass.classLoader) + }.getOrNull() + + if (savePolicyEnumClass != null && savePolicyEnumClass.isEnum) { + val enumConstants = savePolicyEnumClass.enumConstants + if (enumConstants != null && enumConstants.size > 2) { + val viewSessionEnum = enumConstants[2] as Enum<*> + val savePolicyField = localMessageContent.instanceNonNull().javaClass.declaredFields + .find { it.name == "mSavePolicy" } + + if (savePolicyField != null) { + @Suppress("UNCHECKED_CAST") + val fieldType = savePolicyField.type as Class> + val enumValue = java.lang.Enum.valueOf(fieldType, viewSessionEnum.name) + XposedHelpers.setObjectField(localMessageContent.instanceNonNull(), "mSavePolicy", enumValue) + } + } + } + } catch (e: Exception) { + context.log.warn("UnsaveableMessages: Failed to set mSavePolicy: ${e.message}") + } + + // Modify proto + val messageContentBytes = localMessageContent.content ?: return@subscribe + + try { + val protoReader = ProtoReader(messageContentBytes) + val messageContentProto4 = protoReader.followPath(4) + val messageContentProto2 = protoReader.followPath(2) + + val targetProto = messageContentProto4 ?: messageContentProto2 + if (targetProto == null) return@subscribe + + val fieldPath = if (messageContentProto4 != null) 4 else 2 + + val modifiedContent = ProtoEditor(messageContentBytes).apply { + edit(fieldPath) { + if (getOrNull(7) != null) { + remove(7) + } + addVarInt(7, 3) + } + }.toByteArray() + + localMessageContent.content = modifiedContent + + } catch (e: Exception) { + context.log.error("UnsaveableMessages: Failed to modify savePolicy in proto: ${e.message}") + } + } + + // Modify in NativeUnaryCallEvent as fallback + context.event.subscribe(NativeUnaryCallEvent::class) { event -> + if (event.uri != "/messagingcoreservice.MessagingCoreService/CreateContentMessage") return@subscribe + if (!shouldModifySavePolicy) return@subscribe + + try { + event.buffer = ProtoEditor(event.buffer).apply { + edit(4) { + if (getOrNull(7) != null) { + remove(7) + } + addVarInt(7, 3) + } + }.toByteArray() + shouldModifySavePolicy = false + } catch (e: Exception) { + // Try field 2 as fallback + try { + event.buffer = ProtoEditor(event.buffer).apply { + edit(2) { + if (getOrNull(7) != null) { + remove(7) + } + addVarInt(7, 3) + } + }.toByteArray() + shouldModifySavePolicy = false + } catch (e2: Exception) { + context.log.error("UnsaveableMessages: NativeUnaryCallEvent modification failed: ${e2.message}") + } + } + } + + } +} diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/tweaks/VoiceNoteOverride.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/tweaks/VoiceNoteOverride.kt similarity index 88% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/tweaks/VoiceNoteOverride.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/tweaks/VoiceNoteOverride.kt index 430dd805..26043888 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/tweaks/VoiceNoteOverride.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/tweaks/VoiceNoteOverride.kt @@ -1,21 +1,21 @@ -package me.rhunk.snapenhance.core.features.impl.tweaks +package me.eternal.purrfectsnap.core.features.impl.tweaks import android.view.ViewGroup import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch -import me.rhunk.snapenhance.common.data.ContentType -import me.rhunk.snapenhance.core.SnapEnhance -import me.rhunk.snapenhance.core.event.events.impl.BindViewEvent -import me.rhunk.snapenhance.core.features.Feature -import me.rhunk.snapenhance.core.features.impl.downloader.MediaDownloader -import me.rhunk.snapenhance.core.features.impl.messaging.Messaging -import me.rhunk.snapenhance.core.ui.getComposerContext -import me.rhunk.snapenhance.core.util.dataBuilder -import me.rhunk.snapenhance.core.util.hook.HookStage -import me.rhunk.snapenhance.core.util.hook.hook -import me.rhunk.snapenhance.core.util.ktx.getId -import me.rhunk.snapenhance.core.util.ktx.getObjectField -import me.rhunk.snapenhance.core.util.makeFunctionProxy +import me.eternal.purrfectsnap.common.data.ContentType +import me.eternal.purrfectsnap.core.PurrfectSnap +import me.eternal.purrfectsnap.core.event.events.impl.BindViewEvent +import me.eternal.purrfectsnap.core.features.Feature +import me.eternal.purrfectsnap.core.features.impl.downloader.MediaDownloader +import me.eternal.purrfectsnap.core.features.impl.messaging.Messaging +import me.eternal.purrfectsnap.core.ui.getComposerContext +import me.eternal.purrfectsnap.core.util.dataBuilder +import me.eternal.purrfectsnap.core.util.hook.HookStage +import me.eternal.purrfectsnap.core.util.hook.hook +import me.eternal.purrfectsnap.core.util.ktx.getId +import me.eternal.purrfectsnap.core.util.ktx.getObjectField +import me.eternal.purrfectsnap.core.util.makeFunctionProxy class VoiceNoteOverride: Feature("Voice Note Override") { override fun init() { @@ -72,7 +72,7 @@ class VoiceNoteOverride: Feature("Voice Note Override") { } } - SnapEnhance.classCache.nativeBridge.hook("createContext", HookStage.BEFORE) { param -> + PurrfectSnap.classCache.nativeBridge.hook("createContext", HookStage.BEFORE) { param -> val componentPath = param.arg(1) val componentContext = param.argNullable(3) diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/ui/ClientBootstrapOverride.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/ui/ClientBootstrapOverride.kt similarity index 84% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/ui/ClientBootstrapOverride.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/ui/ClientBootstrapOverride.kt index 21ff52ea..366ed8ea 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/ui/ClientBootstrapOverride.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/ui/ClientBootstrapOverride.kt @@ -1,9 +1,9 @@ -package me.rhunk.snapenhance.core.features.impl.ui +package me.eternal.purrfectsnap.core.features.impl.ui -import me.rhunk.snapenhance.common.config.impl.UserInterfaceTweaks -import me.rhunk.snapenhance.common.util.protobuf.ProtoEditor -import me.rhunk.snapenhance.common.util.protobuf.ProtoWriter -import me.rhunk.snapenhance.core.features.Feature +import me.eternal.purrfectsnap.common.config.impl.UserInterfaceTweaks +import me.eternal.purrfectsnap.common.util.protobuf.ProtoEditor +import me.eternal.purrfectsnap.common.util.protobuf.ProtoWriter +import me.eternal.purrfectsnap.core.features.Feature import java.io.File diff --git a/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/ui/ConversationToolbox.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/ui/ConversationToolbox.kt new file mode 100644 index 00000000..5454455b --- /dev/null +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/ui/ConversationToolbox.kt @@ -0,0 +1,214 @@ +package me.eternal.purrfectsnap.core.features.impl.ui + +import android.annotation.SuppressLint +import android.app.AlertDialog +import android.view.Gravity +import android.view.ViewGroup +import android.widget.FrameLayout +import android.widget.LinearLayout +import android.widget.TextView +import androidx.compose.foundation.Image +import androidx.compose.foundation.clickable +import androidx.compose.foundation.background +import androidx.compose.foundation.border +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.verticalScroll +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.KeyboardArrowDown +import androidx.compose.material.icons.filled.KeyboardArrowUp +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.mutableStateMapOf +import androidx.compose.runtime.remember +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.draw.shadow +import androidx.compose.ui.graphics.Brush +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.ColorFilter +import androidx.compose.ui.platform.LocalConfiguration +import androidx.compose.ui.text.font.FontStyle +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import androidx.compose.ui.unit.times +import me.eternal.purrfectsnap.common.scripting.ui.EnumScriptInterface +import me.eternal.purrfectsnap.common.scripting.ui.InterfaceManager +import me.eternal.purrfectsnap.common.scripting.ui.ScriptInterface +import me.eternal.purrfectsnap.common.ui.createComposeAlertDialog +import me.eternal.purrfectsnap.core.event.events.impl.AddViewEvent +import me.eternal.purrfectsnap.core.features.Feature +import me.eternal.purrfectsnap.core.features.impl.messaging.Messaging +import me.eternal.purrfectsnap.core.ui.PurrfectOverlayPalette +import me.eternal.purrfectsnap.core.ui.PurrfectOverlayTheme + + +data class ComposableMenu( + val title: String, + val filter: (conversationId: String) -> Boolean, + val composable: @Composable (alertDialog: AlertDialog, conversationId: String) -> Unit, +) + +class ConversationToolbox : Feature("Conversation Toolbox") { + private val composableList = mutableListOf() + private val expandedComposableCache = mutableStateMapOf() + + fun addComposable(title: String, filter: (conversationId: String) -> Boolean = { true }, composable: @Composable (alertDialog: AlertDialog, conversationId: String) -> Unit) { + composableList.add( + ComposableMenu(title, filter, composable) + ) + } + + @SuppressLint("SetTextI18n") + override fun init() { + onNextActivityCreate { + context.event.subscribe(AddViewEvent::class) { event -> + if (composableList.isEmpty()) return@subscribe + + val chatInputBar by getChatInputBar(event) ?: return@subscribe + + chatInputBar?.addView(FrameLayout(event.view.context).apply { + layoutParams = LinearLayout.LayoutParams( + ViewGroup.LayoutParams.WRAP_CONTENT, + (52 * context.resources.displayMetrics.density).toInt(), + ).apply { + gravity = Gravity.BOTTOM + } + setPadding(25, 0, 25, 0) + + addView(TextView(event.view.context).apply { + layoutParams = FrameLayout.LayoutParams( + ViewGroup.LayoutParams.WRAP_CONTENT, + ViewGroup.LayoutParams.WRAP_CONTENT, + ).apply { + gravity = Gravity.CENTER_VERTICAL + } + setOnClickListener { + openToolbox() + } + textSize = 21f + text = "\uD83E\uDDF0" + }) + }) + } + + context.scriptRuntime.eachModule { + val interfaceManager = getBinding(InterfaceManager::class)?.takeIf { + it.hasInterface(EnumScriptInterface.CONVERSATION_TOOLBOX) + } ?: return@eachModule + addComposable("\uD83D\uDCDC ${moduleInfo.displayName}") { alertDialog, conversationId -> + ScriptInterface(remember { + interfaceManager.buildInterface(EnumScriptInterface.CONVERSATION_TOOLBOX, mapOf( + "alertDialog" to alertDialog, + "conversationId" to conversationId, + )) + } ?: return@addComposable) + } + } + } + } + + private fun openToolbox() { + val openedConversationId = context.feature(Messaging::class).openedConversationUUID?.toString() ?: run { + context.shortToast("You must open a conversation first") + return + } + + createComposeAlertDialog(context.mainActivity!!) { alertDialog -> + PurrfectOverlayTheme { + val shape = RoundedCornerShape(24.dp) + Column( + modifier = Modifier + .fillMaxWidth() + .heightIn( + min = 100.dp, + max = LocalConfiguration.current.screenHeightDp * 0.8f.dp + ) + .clip(shape) + .background(PurrfectOverlayPalette.cardOverlay, shape) + .border( + 1.dp, + Brush.linearGradient( + listOf( + PurrfectOverlayPalette.glowPrimary.copy(alpha = 0.55f), + PurrfectOverlayPalette.glowSecondary.copy(alpha = 0.35f) + ) + ), + shape + ) + .padding(12.dp) + .verticalScroll(rememberScrollState()) + ) { + Text( + "Conversation Toolbox", + fontSize = 18.sp, + modifier = Modifier + .fillMaxWidth() + .padding(10.dp), + textAlign = TextAlign.Center, + color = PurrfectOverlayPalette.textPrimary + ) + Spacer(modifier = Modifier.height(10.dp)) + + composableList.reversed().forEach { (title, filter, composable) -> + if (!filter(openedConversationId)) return@forEach + val expanded = expandedComposableCache[title] == true + val itemShape = RoundedCornerShape(18.dp) + Column( + modifier = Modifier + .fillMaxWidth() + .shadow(10.dp, itemShape, clip = true) + .clip(itemShape) + .background(Color.White.copy(alpha = 0.06f), itemShape) + .border(1.dp, Color.White.copy(alpha = 0.10f), itemShape) + ) { + Row( + modifier = Modifier + .clickable { expandedComposableCache[title] = !expanded } + .fillMaxWidth() + .padding(horizontal = 12.dp, vertical = 12.dp), + horizontalArrangement = Arrangement.spacedBy(10.dp), + verticalAlignment = Alignment.CenterVertically, + ) { + Image( + imageVector = if (expanded) Icons.Filled.KeyboardArrowDown else Icons.Filled.KeyboardArrowUp, + contentDescription = null, + colorFilter = ColorFilter.tint(Color.White.copy(alpha = 0.9f)), + ) + Text( + title, + fontSize = 15.sp, + fontStyle = FontStyle.Italic, + color = Color.White, + modifier = Modifier.weight(1f) + ) + } + if (expanded) { + Column( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 12.dp, vertical = 10.dp) + ) { + runCatching { + composable(alertDialog, openedConversationId) + }.onFailure { throwable -> + Text( + "Failed to load: ${throwable.message}", + color = PurrfectOverlayPalette.textSecondary, + fontSize = 12.sp + ) + context.log.error("Failed to load composable: ${throwable.message}", throwable) + } + } + } + } + Spacer(Modifier.height(10.dp)) + } + } + } + }.show() + } +} diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/ui/CustomStreaksExpirationFormat.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/ui/CustomStreaksExpirationFormat.kt similarity index 88% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/ui/CustomStreaksExpirationFormat.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/ui/CustomStreaksExpirationFormat.kt index c2fec3be..24796f4a 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/ui/CustomStreaksExpirationFormat.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/ui/CustomStreaksExpirationFormat.kt @@ -1,12 +1,12 @@ -package me.rhunk.snapenhance.core.features.impl.ui +package me.eternal.purrfectsnap.core.features.impl.ui -import me.rhunk.snapenhance.core.features.Feature -import me.rhunk.snapenhance.core.util.hook.HookStage -import me.rhunk.snapenhance.core.util.hook.hook -import me.rhunk.snapenhance.core.util.hook.hookConstructor -import me.rhunk.snapenhance.core.util.ktx.getObjectField -import me.rhunk.snapenhance.core.wrapper.impl.SnapUUID -import me.rhunk.snapenhance.mapper.impl.StreaksExpirationMapper +import me.eternal.purrfectsnap.core.features.Feature +import me.eternal.purrfectsnap.core.util.hook.HookStage +import me.eternal.purrfectsnap.core.util.hook.hook +import me.eternal.purrfectsnap.core.util.hook.hookConstructor +import me.eternal.purrfectsnap.core.util.ktx.getObjectField +import me.eternal.purrfectsnap.core.wrapper.impl.SnapUUID +import me.eternal.purrfectsnap.mapper.impl.StreaksExpirationMapper import java.util.concurrent.ConcurrentHashMap import kotlin.time.Duration.Companion.hours import kotlin.time.Duration.Companion.milliseconds diff --git a/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/ui/CustomTheming.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/ui/CustomTheming.kt new file mode 100644 index 00000000..510d48e7 --- /dev/null +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/ui/CustomTheming.kt @@ -0,0 +1,86 @@ +package me.eternal.purrfectsnap.core.features.impl.ui + +import android.content.res.TypedArray +import android.util.TypedValue +import me.eternal.purrfectsnap.core.features.Feature +import me.eternal.purrfectsnap.core.util.hook.HookStage +import me.eternal.purrfectsnap.core.util.hook.hook +import me.eternal.purrfectsnap.core.util.ktx.getObjectField + +class CustomTheming : Feature("Custom Theming") { + private val amoledBlack = 0xFF000000.toInt() + + private val legacyKnownAttrIds = setOf( + 0x7f0404b8 // older Snapchat builds + ) + + private val patchedAttrIds = hashSetOf() + + private val colorTypes = setOf( + TypedValue.TYPE_INT_COLOR_ARGB8, + TypedValue.TYPE_INT_COLOR_RGB8, + TypedValue.TYPE_INT_COLOR_ARGB4, + TypedValue.TYPE_INT_COLOR_RGB4 + ) + + private fun isNearBlackOpaque(color: Int): Boolean { + val alpha = (color ushr 24) and 0xFF + if (alpha != 0xFF) return false + val red = (color ushr 16) and 0xFF + val green = (color ushr 8) and 0xFF + val blue = color and 0xFF + val avg = (red + green + blue) / 3 + return avg <= 0x20 + } + + private fun shouldPatch(attrId: Int, attrName: String?, originalColor: Int): Boolean { + if (originalColor == amoledBlack) return false + if (attrId in legacyKnownAttrIds) return true + if (!isNearBlackOpaque(originalColor)) return false + + val name = (attrName ?: return true).lowercase() + return listOf( + "background", + "surface", + "container", + "scrim", + "overlay", + "sheet", + "panel" + ).any { it in name } + } + + override fun init() { + if (!context.config.userInterface.forceAmoledTheme.get()) return + + onNextActivityCreate { + context.androidContext.theme.javaClass + .getMethod("obtainStyledAttributes", IntArray::class.java) + .hook(HookStage.AFTER) { param -> + val array = param.arg(0) + val attrId = array[0] + val result = param.getResult() as TypedArray + val type = result.getType(0) + if (type !in colorTypes) return@hook + + val originalColor = runCatching { result.getColor(0, Int.MIN_VALUE) }.getOrNull() + ?.takeIf { it != Int.MIN_VALUE } + ?: return@hook + + val attrName = runCatching { context.androidContext.resources.getResourceEntryName(attrId) }.getOrNull() + val shouldPatch = attrId in patchedAttrIds || shouldPatch(attrId, attrName, originalColor) + if (!shouldPatch) return@hook + + val typedArrayData = runCatching { result.getObjectField("mData") as IntArray }.getOrNull() ?: return@hook + if (typedArrayData.size < 2) return@hook + + typedArrayData[1] = amoledBlack + if (patchedAttrIds.add(attrId)) { + context.log.verbose( + "[AMOLED PATCH] Patched attrId 0x${attrId.toString(16)} (${attrName ?: "unknown"}) from 0x${originalColor.toUInt().toString(16)} to AMOLED black" + ) + } + } + } + } +} diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/ui/DefaultVolumeControls.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/ui/DefaultVolumeControls.kt similarity index 72% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/ui/DefaultVolumeControls.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/ui/DefaultVolumeControls.kt index d2439bc4..cccc8809 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/ui/DefaultVolumeControls.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/ui/DefaultVolumeControls.kt @@ -1,9 +1,9 @@ -package me.rhunk.snapenhance.core.features.impl.ui +package me.eternal.purrfectsnap.core.features.impl.ui import android.view.KeyEvent -import me.rhunk.snapenhance.core.features.Feature -import me.rhunk.snapenhance.core.util.hook.HookStage -import me.rhunk.snapenhance.core.util.hook.hook +import me.eternal.purrfectsnap.core.features.Feature +import me.eternal.purrfectsnap.core.util.hook.HookStage +import me.eternal.purrfectsnap.core.util.hook.hook class DefaultVolumeControls : Feature("Default Volume Controls") { override fun init() { diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/ui/DisableConfirmationDialogs.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/ui/DisableConfirmationDialogs.kt similarity index 88% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/ui/DisableConfirmationDialogs.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/ui/DisableConfirmationDialogs.kt index a5be4ac7..893aba85 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/ui/DisableConfirmationDialogs.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/ui/DisableConfirmationDialogs.kt @@ -1,13 +1,13 @@ -package me.rhunk.snapenhance.core.features.impl.ui +package me.eternal.purrfectsnap.core.features.impl.ui import android.view.View import android.widget.TextView -import me.rhunk.snapenhance.core.event.events.impl.AddViewEvent -import me.rhunk.snapenhance.core.features.Feature -import me.rhunk.snapenhance.core.ui.children -import me.rhunk.snapenhance.core.ui.triggerRootCloseTouchEvent -import me.rhunk.snapenhance.core.util.ktx.getId -import me.rhunk.snapenhance.core.util.ktx.getIdentifier +import me.eternal.purrfectsnap.core.event.events.impl.AddViewEvent +import me.eternal.purrfectsnap.core.features.Feature +import me.eternal.purrfectsnap.core.ui.children +import me.eternal.purrfectsnap.core.ui.triggerRootCloseTouchEvent +import me.eternal.purrfectsnap.core.util.ktx.getId +import me.eternal.purrfectsnap.core.util.ktx.getIdentifier import java.util.regex.Pattern class DisableConfirmationDialogs : Feature("Disable Confirmation Dialogs") { diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/ui/EditTextOverride.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/ui/EditTextOverride.kt similarity index 82% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/ui/EditTextOverride.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/ui/EditTextOverride.kt index 20630f50..4ae6e8e7 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/ui/EditTextOverride.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/ui/EditTextOverride.kt @@ -1,13 +1,13 @@ -package me.rhunk.snapenhance.core.features.impl.ui +package me.eternal.purrfectsnap.core.features.impl.ui import android.text.InputFilter import android.text.InputType import android.widget.EditText import android.widget.TextView -import me.rhunk.snapenhance.core.features.Feature -import me.rhunk.snapenhance.core.util.hook.HookStage -import me.rhunk.snapenhance.core.util.hook.hook -import me.rhunk.snapenhance.core.util.hook.hookConstructor +import me.eternal.purrfectsnap.core.features.Feature +import me.eternal.purrfectsnap.core.util.hook.HookStage +import me.eternal.purrfectsnap.core.util.hook.hook +import me.eternal.purrfectsnap.core.util.hook.hookConstructor class EditTextOverride : Feature("Edit Text Override") { override fun init() { diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/ui/FriendFeedMessagePreview.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/ui/FriendFeedMessagePreview.kt similarity index 85% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/ui/FriendFeedMessagePreview.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/ui/FriendFeedMessagePreview.kt index 5899f6a8..625c35fa 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/ui/FriendFeedMessagePreview.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/ui/FriendFeedMessagePreview.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.core.features.impl.ui +package me.eternal.purrfectsnap.core.features.impl.ui import android.graphics.Canvas import android.graphics.Paint @@ -8,21 +8,23 @@ import android.graphics.drawable.shapes.Shape import android.text.TextPaint import android.view.View import android.view.ViewGroup +import android.graphics.Typeface import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.launch import kotlinx.coroutines.withContext -import me.rhunk.snapenhance.common.data.ContentType -import me.rhunk.snapenhance.common.util.protobuf.ProtoReader -import me.rhunk.snapenhance.core.event.events.impl.BindViewEvent -import me.rhunk.snapenhance.core.event.events.impl.BuildMessageEvent -import me.rhunk.snapenhance.core.features.Feature -import me.rhunk.snapenhance.core.features.impl.experiments.EndToEndEncryption -import me.rhunk.snapenhance.core.ui.addForegroundDrawable -import me.rhunk.snapenhance.core.ui.removeForegroundDrawable -import me.rhunk.snapenhance.core.util.EvictingMap -import me.rhunk.snapenhance.core.util.ktx.getId -import me.rhunk.snapenhance.core.wrapper.impl.getMessageText +import me.eternal.purrfectsnap.common.data.ContentType +import me.eternal.purrfectsnap.common.util.protobuf.ProtoReader +import me.eternal.purrfectsnap.core.event.events.impl.BindViewEvent +import me.eternal.purrfectsnap.core.event.events.impl.BuildMessageEvent +import me.eternal.purrfectsnap.core.features.Feature +import me.eternal.purrfectsnap.core.features.impl.experiments.EndToEndEncryption +import me.eternal.purrfectsnap.core.ui.addForegroundDrawable +import me.eternal.purrfectsnap.core.ui.removeForegroundDrawable +import me.eternal.purrfectsnap.core.util.EvictingMap +import me.eternal.purrfectsnap.core.util.ktx.getId +import me.eternal.purrfectsnap.core.wrapper.impl.getMessageText +import me.eternal.purrfectsnap.core.wrapper.impl.sanitizeForLayout import java.util.WeakHashMap import kotlin.math.absoluteValue @@ -49,9 +51,9 @@ class FriendFeedMessagePreview : Feature("FriendFeedMessagePreview") { val messageString = messageContainer.getBuffer().getMessageText(contentType) ?: "[${context.translation.getCategory("content_type")[contentType.name]}]" val friendName = friendNameCache.getOrPut(message.senderId ?: return@mapNotNull null) { - context.database.getFriendInfo(message.senderId ?: return@mapNotNull null)?.let { it.displayName?: it.mutableUsername } ?: "Unknown" - } - "$friendName: $messageString" + context.database.getFriendInfo(message.senderId ?: return@mapNotNull null)?.let { it.displayName ?: it.mutableUsername } ?: "Unknown" + }.sanitizeForLayout() + "${friendName}: ${messageString.sanitizeForLayout()}" }?.takeIf { it.isNotEmpty() }?.reversed() withContext(Dispatchers.Main) { @@ -128,7 +130,7 @@ class FriendFeedMessagePreview : Feature("FriendFeedMessagePreview") { val offsetY = canvas.height.toFloat() - previewContainerHeight paint.textSize = secondaryTextSize paint.color = context.userInterface.colorPrimary - paint.typeface = context.userInterface.avenirNextTypeface + paint.typeface = Typeface.DEFAULT messageCache[conversationId]?.forEachIndexed { index, messageString -> canvas.drawText(messageString, @@ -145,4 +147,4 @@ class FriendFeedMessagePreview : Feature("FriendFeedMessagePreview") { } } } -} \ No newline at end of file +} diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/ui/FriendNotes.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/ui/FriendNotes.kt similarity index 85% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/ui/FriendNotes.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/ui/FriendNotes.kt index ae9871ee..79cd9e55 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/ui/FriendNotes.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/ui/FriendNotes.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.core.features.impl.ui +package me.eternal.purrfectsnap.core.features.impl.ui import android.view.ViewGroup import android.widget.LinearLayout @@ -12,14 +12,14 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.ViewCompositionStrategy import androidx.compose.ui.unit.dp -import me.rhunk.snapenhance.common.ui.AutoClearKeyboardFocus -import me.rhunk.snapenhance.common.ui.EditNoteTextField -import me.rhunk.snapenhance.common.ui.createComposeView -import me.rhunk.snapenhance.common.ui.rememberAsyncMutableState -import me.rhunk.snapenhance.core.event.events.impl.AddViewEvent -import me.rhunk.snapenhance.core.features.Feature -import me.rhunk.snapenhance.core.ui.getComposerContext -import me.rhunk.snapenhance.core.util.ktx.getObjectFieldOrNull +import me.eternal.purrfectsnap.common.ui.AutoClearKeyboardFocus +import me.eternal.purrfectsnap.common.ui.EditNoteTextField +import me.eternal.purrfectsnap.common.ui.createComposeView +import me.eternal.purrfectsnap.common.ui.rememberAsyncMutableState +import me.eternal.purrfectsnap.core.event.events.impl.AddViewEvent +import me.eternal.purrfectsnap.core.features.Feature +import me.eternal.purrfectsnap.core.ui.getComposerContext +import me.eternal.purrfectsnap.core.util.ktx.getObjectFieldOrNull class FriendNotes: Feature("Friend Notes") { override fun init() { @@ -80,4 +80,4 @@ class FriendNotes: Feature("Friend Notes") { } } } -} \ No newline at end of file +} diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/ui/HideFriendFeedEntry.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/ui/HideFriendFeedEntry.kt similarity index 82% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/ui/HideFriendFeedEntry.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/ui/HideFriendFeedEntry.kt index 2a0d1a21..78f7875c 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/ui/HideFriendFeedEntry.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/ui/HideFriendFeedEntry.kt @@ -1,15 +1,15 @@ -package me.rhunk.snapenhance.core.features.impl.ui +package me.eternal.purrfectsnap.core.features.impl.ui -import me.rhunk.snapenhance.common.data.MessagingRuleType -import me.rhunk.snapenhance.common.data.RuleState +import me.eternal.purrfectsnap.common.data.MessagingRuleType +import me.eternal.purrfectsnap.common.data.RuleState -import me.rhunk.snapenhance.core.features.MessagingRuleFeature -import me.rhunk.snapenhance.core.util.dataBuilder -import me.rhunk.snapenhance.core.util.hook.HookStage -import me.rhunk.snapenhance.core.util.hook.hook -import me.rhunk.snapenhance.core.util.ktx.getObjectField -import me.rhunk.snapenhance.core.wrapper.impl.SnapUUID -import me.rhunk.snapenhance.mapper.impl.CallbackMapper +import me.eternal.purrfectsnap.core.features.MessagingRuleFeature +import me.eternal.purrfectsnap.core.util.dataBuilder +import me.eternal.purrfectsnap.core.util.hook.HookStage +import me.eternal.purrfectsnap.core.util.hook.hook +import me.eternal.purrfectsnap.core.util.ktx.getObjectField +import me.eternal.purrfectsnap.core.wrapper.impl.SnapUUID +import me.eternal.purrfectsnap.mapper.impl.CallbackMapper class HideFriendFeedEntry : MessagingRuleFeature("HideFriendFeedEntry", ruleType = MessagingRuleType.HIDE_FRIEND_FEED) { private fun createDeletedFeedEntry(conversationIdInstance: Any) = findClass("com.snapchat.client.messaging.DeletedFeedEntry").dataBuilder { diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/ui/HideStreakRestore.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/ui/HideStreakRestore.kt similarity index 72% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/ui/HideStreakRestore.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/ui/HideStreakRestore.kt index a089bc99..34be4342 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/ui/HideStreakRestore.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/ui/HideStreakRestore.kt @@ -1,14 +1,14 @@ -package me.rhunk.snapenhance.core.features.impl.ui +package me.eternal.purrfectsnap.core.features.impl.ui -import me.rhunk.snapenhance.core.features.Feature -import me.rhunk.snapenhance.core.features.impl.messaging.Messaging -import me.rhunk.snapenhance.core.util.dataBuilder -import me.rhunk.snapenhance.core.util.hook.HookStage -import me.rhunk.snapenhance.core.util.hook.hookConstructor -import me.rhunk.snapenhance.core.util.ktx.getObjectField -import me.rhunk.snapenhance.core.util.ktx.getObjectFieldOrNull -import me.rhunk.snapenhance.core.util.ktx.setObjectField -import me.rhunk.snapenhance.core.wrapper.impl.SnapUUID +import me.eternal.purrfectsnap.core.features.Feature +import me.eternal.purrfectsnap.core.features.impl.messaging.Messaging +import me.eternal.purrfectsnap.core.util.dataBuilder +import me.eternal.purrfectsnap.core.util.hook.HookStage +import me.eternal.purrfectsnap.core.util.hook.hookConstructor +import me.eternal.purrfectsnap.core.util.ktx.getObjectField +import me.eternal.purrfectsnap.core.util.ktx.getObjectFieldOrNull +import me.eternal.purrfectsnap.core.util.ktx.setObjectField +import me.eternal.purrfectsnap.core.wrapper.impl.SnapUUID class HideStreakRestore : Feature("HideStreakRestore") { override fun init() { diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/ui/MessageIndicators.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/ui/MessageIndicators.kt similarity index 94% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/ui/MessageIndicators.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/ui/MessageIndicators.kt index 2a63418c..4c820012 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/ui/MessageIndicators.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/ui/MessageIndicators.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.core.features.impl.ui +package me.eternal.purrfectsnap.core.features.impl.ui import android.view.View import android.view.ViewGroup @@ -16,13 +16,13 @@ import androidx.compose.ui.graphics.ColorFilter import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp -import me.rhunk.snapenhance.common.data.ContentType -import me.rhunk.snapenhance.common.ui.createComposeView -import me.rhunk.snapenhance.common.ui.rememberAsyncMutableState -import me.rhunk.snapenhance.common.util.protobuf.ProtoReader -import me.rhunk.snapenhance.core.event.events.impl.BindViewEvent -import me.rhunk.snapenhance.core.features.Feature -import me.rhunk.snapenhance.core.ui.AppleLogo +import me.eternal.purrfectsnap.common.data.ContentType +import me.eternal.purrfectsnap.common.ui.createComposeView +import me.eternal.purrfectsnap.common.ui.rememberAsyncMutableState +import me.eternal.purrfectsnap.common.util.protobuf.ProtoReader +import me.eternal.purrfectsnap.core.event.events.impl.BindViewEvent +import me.eternal.purrfectsnap.core.features.Feature +import me.eternal.purrfectsnap.core.ui.AppleLogo import kotlin.random.Random class MessageIndicators : Feature("Message Indicators") { diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/ui/OldBitmojiSelfie.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/ui/OldBitmojiSelfie.kt similarity index 85% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/ui/OldBitmojiSelfie.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/ui/OldBitmojiSelfie.kt index c8e65d73..0ea20525 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/ui/OldBitmojiSelfie.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/ui/OldBitmojiSelfie.kt @@ -1,9 +1,9 @@ -package me.rhunk.snapenhance.core.features.impl.ui +package me.eternal.purrfectsnap.core.features.impl.ui import android.net.Uri -import me.rhunk.snapenhance.common.util.snap.BitmojiSelfie -import me.rhunk.snapenhance.core.event.events.impl.NetworkApiRequestEvent -import me.rhunk.snapenhance.core.features.Feature +import me.eternal.purrfectsnap.common.util.snap.BitmojiSelfie +import me.eternal.purrfectsnap.core.event.events.impl.NetworkApiRequestEvent +import me.eternal.purrfectsnap.core.features.Feature class OldBitmojiSelfie : Feature("OldBitmojiSelfie") { override fun init() { diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/ui/PinConversations.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/ui/PinConversations.kt similarity index 75% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/ui/PinConversations.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/ui/PinConversations.kt index ef74e932..03e946ca 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/ui/PinConversations.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/ui/PinConversations.kt @@ -1,15 +1,15 @@ -package me.rhunk.snapenhance.core.features.impl.ui +package me.eternal.purrfectsnap.core.features.impl.ui -import me.rhunk.snapenhance.common.data.MessagingRuleType -import me.rhunk.snapenhance.common.data.RuleState -import me.rhunk.snapenhance.core.features.MessagingRuleFeature -import me.rhunk.snapenhance.core.util.hook.HookStage -import me.rhunk.snapenhance.core.util.hook.Hooker -import me.rhunk.snapenhance.core.util.hook.hook -import me.rhunk.snapenhance.core.util.hook.hookConstructor -import me.rhunk.snapenhance.core.util.ktx.getObjectField -import me.rhunk.snapenhance.core.util.ktx.setObjectField -import me.rhunk.snapenhance.core.wrapper.impl.SnapUUID +import me.eternal.purrfectsnap.common.data.MessagingRuleType +import me.eternal.purrfectsnap.common.data.RuleState +import me.eternal.purrfectsnap.core.features.MessagingRuleFeature +import me.eternal.purrfectsnap.core.util.hook.HookStage +import me.eternal.purrfectsnap.core.util.hook.Hooker +import me.eternal.purrfectsnap.core.util.hook.hook +import me.eternal.purrfectsnap.core.util.hook.hookConstructor +import me.eternal.purrfectsnap.core.util.ktx.getObjectField +import me.eternal.purrfectsnap.core.util.ktx.setObjectField +import me.eternal.purrfectsnap.core.wrapper.impl.SnapUUID class PinConversations : MessagingRuleFeature("PinConversations", MessagingRuleType.PIN_CONVERSATION) { override fun init() { diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/ui/SnapPreview.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/ui/SnapPreview.kt similarity index 84% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/ui/SnapPreview.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/ui/SnapPreview.kt index b6d64cec..f833d234 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/ui/SnapPreview.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/ui/SnapPreview.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.core.features.impl.ui +package me.eternal.purrfectsnap.core.features.impl.ui import android.graphics.Bitmap import android.graphics.Canvas @@ -8,19 +8,19 @@ import android.graphics.drawable.shapes.Shape import android.view.ViewGroup import kotlinx.coroutines.Job import kotlinx.coroutines.launch -import me.rhunk.snapenhance.common.data.ContentType -import me.rhunk.snapenhance.common.util.protobuf.ProtoReader -import me.rhunk.snapenhance.core.event.events.impl.BindViewEvent -import me.rhunk.snapenhance.core.features.Feature -import me.rhunk.snapenhance.core.ui.addForegroundDrawable -import me.rhunk.snapenhance.core.ui.randomTag -import me.rhunk.snapenhance.core.ui.removeForegroundDrawable -import me.rhunk.snapenhance.core.util.EvictingMap -import me.rhunk.snapenhance.core.util.hook.HookStage -import me.rhunk.snapenhance.core.util.hook.hook -import me.rhunk.snapenhance.core.util.ktx.getObjectField -import me.rhunk.snapenhance.core.util.media.PreviewUtils -import me.rhunk.snapenhance.mapper.impl.CallbackMapper +import me.eternal.purrfectsnap.common.data.ContentType +import me.eternal.purrfectsnap.common.util.protobuf.ProtoReader +import me.eternal.purrfectsnap.core.event.events.impl.BindViewEvent +import me.eternal.purrfectsnap.core.features.Feature +import me.eternal.purrfectsnap.core.ui.addForegroundDrawable +import me.eternal.purrfectsnap.core.ui.randomTag +import me.eternal.purrfectsnap.core.ui.removeForegroundDrawable +import me.eternal.purrfectsnap.core.util.EvictingMap +import me.eternal.purrfectsnap.core.util.hook.HookStage +import me.eternal.purrfectsnap.core.util.hook.hook +import me.eternal.purrfectsnap.core.util.ktx.getObjectField +import me.eternal.purrfectsnap.core.util.media.PreviewUtils +import me.eternal.purrfectsnap.mapper.impl.CallbackMapper import java.io.File class SnapPreview : Feature("SnapPreview") { diff --git a/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/ui/SpotlightCommentsUsername.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/ui/SpotlightCommentsUsername.kt new file mode 100644 index 00000000..603e9e63 --- /dev/null +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/ui/SpotlightCommentsUsername.kt @@ -0,0 +1,134 @@ +package me.eternal.purrfectsnap.core.features.impl.ui + +import android.annotation.SuppressLint +import android.content.DialogInterface +import android.graphics.Color +import android.graphics.Typeface +import android.text.SpannableString +import android.text.method.LinkMovementMethod +import android.text.style.ClickableSpan +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext +import me.eternal.purrfectsnap.core.event.events.impl.BindViewEvent +import me.eternal.purrfectsnap.core.features.Feature +import me.eternal.purrfectsnap.core.features.impl.messaging.Messaging +import me.eternal.purrfectsnap.core.ui.ViewAppearanceHelper +import me.eternal.purrfectsnap.core.ui.children +import me.eternal.purrfectsnap.core.util.EvictingMap +import java.text.SimpleDateFormat +import java.util.* + +class SpotlightCommentsUsername : Feature("SpotlightCommentsUsername") { + private val usernameCache = EvictingMap(150) + + @SuppressLint("SetTextI18n") + override fun init() { + if (!context.config.global.spotlightCommentsUsername.get()) return + + onNextActivityCreate(defer = true) { + val messaging = context.feature(Messaging::class) + context.event.subscribe(BindViewEvent::class) { event -> + val posterUserId = event.prevModel.toString().takeIf { it.startsWith("Comment") } + ?.substringAfter("posterUserId=")?.substringBefore(",")?.substringBefore(")") ?: return@subscribe + + if (posterUserId == "null") return@subscribe + + fun setUserInfo(username: String) { + usernameCache[posterUserId] = username + val commentsCreatorBadgeTimestamp = (event.view as ViewGroup).children().filterIsInstance() + .getOrNull(1) ?: return + + val customIcon = context.config.global.spotlightCommentsUsernameIcon.get().takeIf { it.isNotBlank() } ?: "[👤]" + val exclamationIcon = " $customIcon" + val spannableString = SpannableString(exclamationIcon + commentsCreatorBadgeTimestamp.text.toString()) + + val clickableSpan = object : ClickableSpan() { + override fun onClick(widget: View) { + showUserInfoDialog(posterUserId, username) + } + + override fun updateDrawState(ds: android.text.TextPaint) { + super.updateDrawState(ds) + ds.isUnderlineText = false + } + } + + spannableString.setSpan(clickableSpan, 0, exclamationIcon.length, SpannableString.SPAN_EXCLUSIVE_EXCLUSIVE) + + commentsCreatorBadgeTimestamp.text = spannableString + commentsCreatorBadgeTimestamp.movementMethod = LinkMovementMethod.getInstance() + commentsCreatorBadgeTimestamp.setTextColor(Color.WHITE) + } + + event.view.post { + usernameCache[posterUserId]?.let { + setUserInfo(it) + return@post + } + + context.coroutineScope.launch { + val username = runCatching { + messaging.fetchSnapchatterInfos(listOf(posterUserId)).firstOrNull() + }.onFailure { + context.log.error("Failed to fetch snapchatter info for user $posterUserId", it) + }.getOrNull()?.username ?: return@launch + + withContext(Dispatchers.Main) { + setUserInfo(username) + } + } + } + } + } + } + + private fun showUserInfoDialog(userId: String, username: String) { + context.coroutineScope.launch { + val messaging = context.feature(Messaging::class) + val userInfo = runCatching { + messaging.fetchSnapchatterInfos(listOf(userId)).firstOrNull() + }.onFailure { + context.log.error("Failed to fetch detailed user info for $userId", it) + }.getOrNull() + + withContext(Dispatchers.Main) { + val builder = ViewAppearanceHelper.newAlertDialogBuilder(context.mainActivity) + builder.setTitle("User Information") + + val userInfoText = buildString { + append("Username: $username\n") + userInfo?.let { info -> + append("User ID: ${userId}\n") + append("Display Name: ${info.displayName ?: "Not available"}\n") + } ?: append("Unable to retrieve additional information") + } + + builder.setMessage(userInfoText) + builder.setPositiveButton("OK") { dialog: DialogInterface, _: Int -> + dialog.dismiss() + } + + val dialog = builder.create() + dialog.show() + + // Make text selectable + dialog.findViewById(android.R.id.message)?.let { messageView -> + messageView.setTextIsSelectable(true) + messageView.typeface = Typeface.MONOSPACE + } + } + } + } + + private fun formatDate(timestamp: Long): String { + return if (timestamp > 0) { + SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault()).format(Date(timestamp)) + } else { + "Not available" + } + } +} diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/ui/StealthModeIndicator.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/ui/StealthModeIndicator.kt similarity index 85% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/ui/StealthModeIndicator.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/ui/StealthModeIndicator.kt index e6958230..828f8c23 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/ui/StealthModeIndicator.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/ui/StealthModeIndicator.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.core.features.impl.ui +package me.eternal.purrfectsnap.core.features.impl.ui import android.graphics.Canvas import android.graphics.Paint @@ -9,16 +9,16 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job import kotlinx.coroutines.launch import kotlinx.coroutines.withContext -import me.rhunk.snapenhance.common.data.RuleState -import me.rhunk.snapenhance.core.event.events.impl.BindViewEvent -import me.rhunk.snapenhance.core.features.Feature -import me.rhunk.snapenhance.core.features.impl.spying.StealthMode -import me.rhunk.snapenhance.core.ui.addForegroundDrawable -import me.rhunk.snapenhance.core.ui.randomTag -import me.rhunk.snapenhance.core.ui.removeForegroundDrawable -import me.rhunk.snapenhance.core.util.EvictingMap -import me.rhunk.snapenhance.core.util.ktx.getDimens -import me.rhunk.snapenhance.core.util.ktx.getIdentifier +import me.eternal.purrfectsnap.common.data.RuleState +import me.eternal.purrfectsnap.core.event.events.impl.BindViewEvent +import me.eternal.purrfectsnap.core.features.Feature +import me.eternal.purrfectsnap.core.features.impl.spying.StealthMode +import me.eternal.purrfectsnap.core.ui.addForegroundDrawable +import me.eternal.purrfectsnap.core.ui.randomTag +import me.eternal.purrfectsnap.core.ui.removeForegroundDrawable +import me.eternal.purrfectsnap.core.util.EvictingMap +import me.eternal.purrfectsnap.core.util.ktx.getDimens +import me.eternal.purrfectsnap.core.util.ktx.getIdentifier class StealthModeIndicator : Feature("StealthModeIndicator") { private val stealthMode by lazy { context.feature(StealthMode::class) } diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/ui/UITweaks.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/ui/UITweaks.kt similarity index 91% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/ui/UITweaks.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/ui/UITweaks.kt index 0ebf6edf..f671d7b1 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/ui/UITweaks.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/ui/UITweaks.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.core.features.impl.ui +package me.eternal.purrfectsnap.core.features.impl.ui import android.content.res.Resources import android.view.View @@ -6,18 +6,18 @@ import android.view.ViewGroup import android.view.ViewGroup.MarginLayoutParams import android.widget.FrameLayout import android.widget.LinearLayout -import me.rhunk.snapenhance.core.event.events.impl.AddViewEvent -import me.rhunk.snapenhance.core.event.events.impl.BindViewEvent -import me.rhunk.snapenhance.core.features.Feature -import me.rhunk.snapenhance.core.ui.children -import me.rhunk.snapenhance.core.ui.getComposerContext -import me.rhunk.snapenhance.core.ui.hideViewCompletely -import me.rhunk.snapenhance.core.ui.onLayoutChange -import me.rhunk.snapenhance.core.util.dataBuilder -import me.rhunk.snapenhance.core.util.hook.HookStage -import me.rhunk.snapenhance.core.util.hook.Hooker -import me.rhunk.snapenhance.core.util.hook.hook -import me.rhunk.snapenhance.core.util.ktx.getIdentifier +import me.eternal.purrfectsnap.core.event.events.impl.AddViewEvent +import me.eternal.purrfectsnap.core.event.events.impl.BindViewEvent +import me.eternal.purrfectsnap.core.features.Feature +import me.eternal.purrfectsnap.core.ui.children +import me.eternal.purrfectsnap.core.ui.getComposerContext +import me.eternal.purrfectsnap.core.ui.hideViewCompletely +import me.eternal.purrfectsnap.core.ui.onLayoutChange +import me.eternal.purrfectsnap.core.util.dataBuilder +import me.eternal.purrfectsnap.core.util.hook.HookStage +import me.eternal.purrfectsnap.core.util.hook.Hooker +import me.eternal.purrfectsnap.core.util.hook.hook +import me.eternal.purrfectsnap.core.util.ktx.getIdentifier fun getChatInputBar(event: AddViewEvent): Lazy? { if (!event.parent.javaClass.name.endsWith("ChatInputLayout")) return null diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/logger/CoreLogger.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/logger/CoreLogger.kt similarity index 85% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/logger/CoreLogger.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/logger/CoreLogger.kt index 64caa058..db1c49e0 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/logger/CoreLogger.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/logger/CoreLogger.kt @@ -1,14 +1,14 @@ -package me.rhunk.snapenhance.core.logger +package me.eternal.purrfectsnap.core.logger import android.annotation.SuppressLint import android.util.Log import de.robv.android.xposed.XposedBridge -import me.rhunk.snapenhance.common.logger.AbstractLogger -import me.rhunk.snapenhance.common.logger.LogChannel -import me.rhunk.snapenhance.common.logger.LogLevel -import me.rhunk.snapenhance.core.bridge.BridgeClient -import me.rhunk.snapenhance.core.util.hook.HookStage -import me.rhunk.snapenhance.core.util.hook.hook +import me.eternal.purrfectsnap.common.logger.AbstractLogger +import me.eternal.purrfectsnap.common.logger.LogChannel +import me.eternal.purrfectsnap.common.logger.LogLevel +import me.eternal.purrfectsnap.core.bridge.BridgeClient +import me.eternal.purrfectsnap.core.util.hook.HookStage +import me.eternal.purrfectsnap.core.util.hook.hook @SuppressLint("PrivateApi") class CoreLogger( @@ -16,7 +16,7 @@ class CoreLogger( ) : AbstractLogger(LogChannel.CORE) { companion object { - private const val TAG = "SnapEnhanceCore" + private const val TAG = "PurrfectSnapCore" fun xposedLog(message: Any?, tag: String = TAG) { Log.println(Log.INFO, tag, message.toString()) diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/messaging/ConversationExporter.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/messaging/ConversationExporter.kt similarity index 95% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/messaging/ConversationExporter.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/messaging/ConversationExporter.kt index ef40df4c..8367e82b 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/messaging/ConversationExporter.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/messaging/ConversationExporter.kt @@ -1,19 +1,19 @@ -package me.rhunk.snapenhance.core.messaging +package me.eternal.purrfectsnap.core.messaging import android.util.Base64InputStream import android.util.Base64OutputStream import com.google.gson.stream.JsonWriter import kotlinx.coroutines.runBlocking -import me.rhunk.snapenhance.common.BuildConfig -import me.rhunk.snapenhance.common.data.ContentType -import me.rhunk.snapenhance.common.database.impl.FriendFeedEntry -import me.rhunk.snapenhance.common.database.impl.FriendInfo -import me.rhunk.snapenhance.common.util.snap.MediaDownloaderHelper -import me.rhunk.snapenhance.core.ModContext -import me.rhunk.snapenhance.core.features.impl.downloader.decoder.MessageDecoder -import me.rhunk.snapenhance.core.util.hook.findRestrictedConstructor -import me.rhunk.snapenhance.core.wrapper.impl.Message -import me.rhunk.snapenhance.core.wrapper.impl.SnapUUID +import me.eternal.purrfectsnap.common.BuildConfig +import me.eternal.purrfectsnap.common.data.ContentType +import me.eternal.purrfectsnap.common.database.impl.FriendFeedEntry +import me.eternal.purrfectsnap.common.database.impl.FriendInfo +import me.eternal.purrfectsnap.common.util.snap.MediaDownloaderHelper +import me.eternal.purrfectsnap.core.ModContext +import me.eternal.purrfectsnap.core.features.impl.downloader.decoder.MessageDecoder +import me.eternal.purrfectsnap.core.util.hook.findRestrictedConstructor +import me.eternal.purrfectsnap.core.wrapper.impl.Message +import me.eternal.purrfectsnap.core.wrapper.impl.SnapUUID import java.io.BufferedInputStream import java.io.File import java.io.InputStream @@ -115,7 +115,7 @@ class ConversationExporter( """.trimIndent().toByteArray()) - outputFileStream.write("\n".toByteArray()) + outputFileStream.write("\n".toByteArray()) outputFileStream.flush() } diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/messaging/CoreMessagingBridge.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/messaging/CoreMessagingBridge.kt similarity index 87% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/messaging/CoreMessagingBridge.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/messaging/CoreMessagingBridge.kt index e8d13ce5..09ad018a 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/messaging/CoreMessagingBridge.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/messaging/CoreMessagingBridge.kt @@ -1,17 +1,17 @@ -package me.rhunk.snapenhance.core.messaging +package me.eternal.purrfectsnap.core.messaging import kotlinx.coroutines.runBlocking import kotlinx.coroutines.suspendCancellableCoroutine -import me.rhunk.snapenhance.bridge.snapclient.MessagingBridge -import me.rhunk.snapenhance.bridge.snapclient.SessionStartListener -import me.rhunk.snapenhance.bridge.snapclient.types.Message -import me.rhunk.snapenhance.common.data.MessageUpdate -import me.rhunk.snapenhance.core.ModContext -import me.rhunk.snapenhance.core.features.impl.downloader.decoder.MessageDecoder -import me.rhunk.snapenhance.core.features.impl.messaging.Messaging +import me.eternal.purrfectsnap.bridge.snapclient.MessagingBridge +import me.eternal.purrfectsnap.bridge.snapclient.SessionStartListener +import me.eternal.purrfectsnap.bridge.snapclient.types.Message +import me.eternal.purrfectsnap.common.data.MessageUpdate +import me.eternal.purrfectsnap.core.ModContext +import me.eternal.purrfectsnap.core.features.impl.downloader.decoder.MessageDecoder +import me.eternal.purrfectsnap.core.features.impl.messaging.Messaging -fun me.rhunk.snapenhance.core.wrapper.impl.Message.toBridge(): Message { +fun me.eternal.purrfectsnap.core.wrapper.impl.Message.toBridge(): Message { return Message().also { output -> output.conversationId = this.messageDescriptor!!.conversationId.toString() output.senderId = this.senderId.toString() diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/messaging/EnumBulkAction.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/messaging/EnumBulkAction.kt similarity index 74% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/messaging/EnumBulkAction.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/messaging/EnumBulkAction.kt index 66a317fd..ee70ff44 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/messaging/EnumBulkAction.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/messaging/EnumBulkAction.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.core.messaging +package me.eternal.purrfectsnap.core.messaging enum class EnumBulkAction( val key: String, diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/messaging/ExportFormat.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/messaging/ExportFormat.kt similarity index 69% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/messaging/ExportFormat.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/messaging/ExportFormat.kt index d84197e4..46373da2 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/messaging/ExportFormat.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/messaging/ExportFormat.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.core.messaging; +package me.eternal.purrfectsnap.core.messaging; enum class ExportFormat( val extension: String, diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/messaging/ExportParams.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/messaging/ExportParams.kt similarity index 67% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/messaging/ExportParams.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/messaging/ExportParams.kt index e12ae1ea..db091863 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/messaging/ExportParams.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/messaging/ExportParams.kt @@ -1,6 +1,6 @@ -package me.rhunk.snapenhance.core.messaging +package me.eternal.purrfectsnap.core.messaging -import me.rhunk.snapenhance.common.data.ContentType +import me.eternal.purrfectsnap.common.data.ContentType class ExportParams( val exportFormat: ExportFormat = ExportFormat.HTML, diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/messaging/MessageSender.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/messaging/MessageSender.kt similarity index 78% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/messaging/MessageSender.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/messaging/MessageSender.kt index 73763557..90e1522f 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/messaging/MessageSender.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/messaging/MessageSender.kt @@ -1,14 +1,14 @@ -package me.rhunk.snapenhance.core.messaging +package me.eternal.purrfectsnap.core.messaging -import me.rhunk.snapenhance.common.data.ContentType -import me.rhunk.snapenhance.common.util.protobuf.ProtoWriter -import me.rhunk.snapenhance.core.ModContext -import me.rhunk.snapenhance.core.features.impl.messaging.Messaging -import me.rhunk.snapenhance.core.util.CallbackBuilder -import me.rhunk.snapenhance.core.wrapper.AbstractWrapper -import me.rhunk.snapenhance.core.wrapper.impl.MessageDestinations -import me.rhunk.snapenhance.core.wrapper.impl.SnapUUID -import me.rhunk.snapenhance.mapper.impl.CallbackMapper +import me.eternal.purrfectsnap.common.data.ContentType +import me.eternal.purrfectsnap.common.util.protobuf.ProtoWriter +import me.eternal.purrfectsnap.core.ModContext +import me.eternal.purrfectsnap.core.features.impl.messaging.Messaging +import me.eternal.purrfectsnap.core.util.CallbackBuilder +import me.eternal.purrfectsnap.core.wrapper.AbstractWrapper +import me.eternal.purrfectsnap.core.wrapper.impl.MessageDestinations +import me.eternal.purrfectsnap.core.wrapper.impl.SnapUUID +import me.eternal.purrfectsnap.mapper.impl.CallbackMapper class MessageSender( private val context: ModContext, @@ -53,8 +53,11 @@ class MessageSender( { "mAllowsTranscription": false, "mBotMention": false, + "mBundleMetadata": null, "mContent": [${messageContent.joinToString(",")}], "mContentType": "${contentType.name}", + "mExternalContentMetadata": null, + "mFeedDisplayInfo": null, "mIncidentalAttachments": [], "mLocalMediaReferences": [${ if (localMediaReference != null) { @@ -63,14 +66,22 @@ class MessageSender( "" } }], + "mLocalPlatformData": null, + "mMessageBehaviorHint": null, + "mMessageTypeMetadata": null, "mPlatformAnalytics": { "mAttemptId": null, "mContent": null, "mMetricsMessageMediaType": "NO_MEDIA", "mMetricsMessageType": "TEXT", - "mReactionSource": "NONE" + "mReactionSendSource": "NONE", + "mReactionSource": "NONE", + "mSendMessageAnalytics": null }, - "mSavePolicy": "$savePolicy" + "mQuotedMessageId": null, + "mRemoteMediaReferences": [], + "mSavePolicy": "$savePolicy", + "mSnapModeInfo": null } """.trimIndent() } @@ -107,4 +118,4 @@ class MessageSender( .override("onError", callback = { onError(it.arg(0)) }) .build()) } -} \ No newline at end of file +} diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/scripting/CoreScriptRuntime.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/scripting/CoreScriptRuntime.kt similarity index 81% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/scripting/CoreScriptRuntime.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/scripting/CoreScriptRuntime.kt index 0a7509eb..847ba6e4 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/scripting/CoreScriptRuntime.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/scripting/CoreScriptRuntime.kt @@ -1,11 +1,11 @@ -package me.rhunk.snapenhance.core.scripting +package me.eternal.purrfectsnap.core.scripting -import me.rhunk.snapenhance.bridge.scripting.AutoReloadListener -import me.rhunk.snapenhance.common.logger.AbstractLogger -import me.rhunk.snapenhance.common.scripting.ScriptRuntime -import me.rhunk.snapenhance.common.scripting.bindings.BindingSide -import me.rhunk.snapenhance.core.ModContext -import me.rhunk.snapenhance.core.scripting.impl.* +import me.eternal.purrfectsnap.bridge.scripting.AutoReloadListener +import me.eternal.purrfectsnap.common.logger.AbstractLogger +import me.eternal.purrfectsnap.common.scripting.ScriptRuntime +import me.eternal.purrfectsnap.common.scripting.bindings.BindingSide +import me.eternal.purrfectsnap.core.ModContext +import me.eternal.purrfectsnap.core.scripting.impl.* class CoreScriptRuntime( private val modContext: ModContext, @@ -60,4 +60,4 @@ class CoreScriptRuntime( } } } -} \ No newline at end of file +} diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/scripting/impl/CoreEvents.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/scripting/impl/CoreEvents.kt similarity index 87% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/scripting/impl/CoreEvents.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/scripting/impl/CoreEvents.kt index 57dacadf..507d3c0e 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/scripting/impl/CoreEvents.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/scripting/impl/CoreEvents.kt @@ -1,11 +1,11 @@ -package me.rhunk.snapenhance.core.scripting.impl +package me.eternal.purrfectsnap.core.scripting.impl -import me.rhunk.snapenhance.common.scripting.bindings.AbstractBinding -import me.rhunk.snapenhance.common.scripting.bindings.BindingSide -import me.rhunk.snapenhance.common.scripting.ktx.scriptableObject -import me.rhunk.snapenhance.core.ModContext -import me.rhunk.snapenhance.core.event.Event -import me.rhunk.snapenhance.core.event.events.impl.* +import me.eternal.purrfectsnap.common.scripting.bindings.AbstractBinding +import me.eternal.purrfectsnap.common.scripting.bindings.BindingSide +import me.eternal.purrfectsnap.common.scripting.ktx.scriptableObject +import me.eternal.purrfectsnap.core.ModContext +import me.eternal.purrfectsnap.core.event.Event +import me.eternal.purrfectsnap.core.event.events.impl.* import org.mozilla.javascript.ScriptableObject class CoreEvents( diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/scripting/impl/CoreIPC.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/scripting/impl/CoreIPC.kt similarity index 79% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/scripting/impl/CoreIPC.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/scripting/impl/CoreIPC.kt index f3eaee38..38ee8097 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/scripting/impl/CoreIPC.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/scripting/impl/CoreIPC.kt @@ -1,8 +1,8 @@ -package me.rhunk.snapenhance.core.scripting.impl +package me.eternal.purrfectsnap.core.scripting.impl -import me.rhunk.snapenhance.bridge.scripting.IPCListener -import me.rhunk.snapenhance.common.scripting.impl.IPCInterface -import me.rhunk.snapenhance.common.scripting.impl.Listener +import me.eternal.purrfectsnap.bridge.scripting.IPCListener +import me.eternal.purrfectsnap.common.scripting.impl.IPCInterface +import me.eternal.purrfectsnap.common.scripting.impl.Listener class CoreIPC : IPCInterface() { override fun onBroadcast(channel: String, eventName: String, listener: Listener) { diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/scripting/impl/CoreMessaging.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/scripting/impl/CoreMessaging.kt similarity index 88% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/scripting/impl/CoreMessaging.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/scripting/impl/CoreMessaging.kt index 98a26b7e..ece12590 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/scripting/impl/CoreMessaging.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/scripting/impl/CoreMessaging.kt @@ -1,14 +1,14 @@ -package me.rhunk.snapenhance.core.scripting.impl +package me.eternal.purrfectsnap.core.scripting.impl -import me.rhunk.snapenhance.common.data.MessageUpdate -import me.rhunk.snapenhance.common.scripting.bindings.AbstractBinding -import me.rhunk.snapenhance.common.scripting.bindings.BindingSide -import me.rhunk.snapenhance.common.scripting.ktx.scriptableObject -import me.rhunk.snapenhance.core.ModContext -import me.rhunk.snapenhance.core.features.impl.messaging.Messaging -import me.rhunk.snapenhance.core.wrapper.impl.Message -import me.rhunk.snapenhance.core.wrapper.impl.SnapUUID -import me.rhunk.snapenhance.core.wrapper.impl.Snapchatter +import me.eternal.purrfectsnap.common.data.MessageUpdate +import me.eternal.purrfectsnap.common.scripting.bindings.AbstractBinding +import me.eternal.purrfectsnap.common.scripting.bindings.BindingSide +import me.eternal.purrfectsnap.common.scripting.ktx.scriptableObject +import me.eternal.purrfectsnap.core.ModContext +import me.eternal.purrfectsnap.core.features.impl.messaging.Messaging +import me.eternal.purrfectsnap.core.wrapper.impl.Message +import me.eternal.purrfectsnap.core.wrapper.impl.SnapUUID +import me.eternal.purrfectsnap.core.wrapper.impl.Snapchatter import org.mozilla.javascript.Scriptable import org.mozilla.javascript.annotations.JSFunction diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/scripting/impl/CoreScriptConfig.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/scripting/impl/CoreScriptConfig.kt similarity index 83% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/scripting/impl/CoreScriptConfig.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/scripting/impl/CoreScriptConfig.kt index 4baba70e..005d00ef 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/scripting/impl/CoreScriptConfig.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/scripting/impl/CoreScriptConfig.kt @@ -1,7 +1,7 @@ -package me.rhunk.snapenhance.core.scripting.impl +package me.eternal.purrfectsnap.core.scripting.impl -import me.rhunk.snapenhance.common.scripting.impl.ConfigInterface -import me.rhunk.snapenhance.common.scripting.impl.ConfigTransactionType +import me.eternal.purrfectsnap.common.scripting.impl.ConfigInterface +import me.eternal.purrfectsnap.common.scripting.impl.ConfigTransactionType class CoreScriptConfig: ConfigInterface() { override fun get(key: String, defaultValue: Any?): String? { diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/scripting/impl/CoreScriptHooker.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/scripting/impl/CoreScriptHooker.kt similarity index 90% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/scripting/impl/CoreScriptHooker.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/scripting/impl/CoreScriptHooker.kt index ca127a95..4c329564 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/scripting/impl/CoreScriptHooker.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/scripting/impl/CoreScriptHooker.kt @@ -1,14 +1,14 @@ -package me.rhunk.snapenhance.core.scripting.impl +package me.eternal.purrfectsnap.core.scripting.impl -import me.rhunk.snapenhance.common.scripting.bindings.AbstractBinding -import me.rhunk.snapenhance.common.scripting.bindings.BindingSide -import me.rhunk.snapenhance.common.scripting.ktx.scriptableObject -import me.rhunk.snapenhance.common.scripting.toPrimitiveValue -import me.rhunk.snapenhance.core.util.hook.HookAdapter -import me.rhunk.snapenhance.core.util.hook.HookStage -import me.rhunk.snapenhance.core.util.hook.Hooker -import me.rhunk.snapenhance.core.util.hook.hook -import me.rhunk.snapenhance.core.util.hook.hookConstructor +import me.eternal.purrfectsnap.common.scripting.bindings.AbstractBinding +import me.eternal.purrfectsnap.common.scripting.bindings.BindingSide +import me.eternal.purrfectsnap.common.scripting.ktx.scriptableObject +import me.eternal.purrfectsnap.common.scripting.toPrimitiveValue +import me.eternal.purrfectsnap.core.util.hook.HookAdapter +import me.eternal.purrfectsnap.core.util.hook.HookStage +import me.eternal.purrfectsnap.core.util.hook.Hooker +import me.eternal.purrfectsnap.core.util.hook.hook +import me.eternal.purrfectsnap.core.util.hook.hookConstructor import org.mozilla.javascript.annotations.JSGetter import org.mozilla.javascript.annotations.JSSetter import java.lang.reflect.Constructor diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/ui/ComposeIcons.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/ui/ComposeIcons.kt similarity index 99% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/ui/ComposeIcons.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/ui/ComposeIcons.kt index a8d9ae9b..f9e7f40b 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/ui/ComposeIcons.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/ui/ComposeIcons.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.core.ui +package me.eternal.purrfectsnap.core.ui import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.PathFillType diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/ui/DebugComponents.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/ui/DebugComponents.kt similarity index 94% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/ui/DebugComponents.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/ui/DebugComponents.kt index 8b5c93aa..421e1e7b 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/ui/DebugComponents.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/ui/DebugComponents.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.core.ui +package me.eternal.purrfectsnap.core.ui import android.content.Context import android.text.InputType diff --git a/core/src/main/kotlin/me/eternal/purrfectsnap/core/ui/InAppOverlay.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/ui/InAppOverlay.kt new file mode 100644 index 00000000..871f90b5 --- /dev/null +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/ui/InAppOverlay.kt @@ -0,0 +1,373 @@ +package me.eternal.purrfectsnap.core.ui + +import android.app.Activity +import android.view.View +import android.widget.FrameLayout +import androidx.compose.animation.core.Animatable +import androidx.compose.animation.core.LinearEasing +import androidx.compose.animation.core.animateFloatAsState +import androidx.compose.animation.core.tween +import androidx.compose.animation.rememberSplineBasedDecay +import androidx.compose.foundation.BorderStroke +import androidx.compose.foundation.background +import androidx.compose.foundation.border +import androidx.compose.foundation.ExperimentalFoundationApi +import androidx.compose.foundation.gestures.AnchoredDraggableState +import androidx.compose.foundation.gestures.AnchoredDraggableDefaults +import androidx.compose.foundation.gestures.DraggableAnchors +import androidx.compose.foundation.gestures.Orientation +import androidx.compose.foundation.gestures.anchoredDraggable +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.outlined.Warning +import androidx.compose.material3.* +import androidx.compose.runtime.* +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.draw.shadow +import androidx.compose.ui.graphics.Brush +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.graphicsLayer +import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.style.TextOverflow +import androidx.compose.ui.unit.IntOffset +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import kotlinx.coroutines.delay +import me.eternal.purrfectsnap.common.ui.createComposeView +import me.eternal.purrfectsnap.common.util.ktx.copyToClipboard +import me.eternal.purrfectsnap.core.ModContext +import me.eternal.purrfectsnap.core.PurrfectSnap +import me.eternal.purrfectsnap.core.util.hook.HookStage +import me.eternal.purrfectsnap.core.util.hook.Hooker +import me.eternal.purrfectsnap.core.util.hook.hook +import me.eternal.purrfectsnap.core.util.ktx.isDarkTheme +import kotlin.math.roundToInt +import kotlin.random.Random +import kotlin.system.exitProcess + +typealias CustomComposable = @Composable BoxScope.() -> Unit + +class InAppOverlay( + private val context: ModContext +) { + companion object { + fun showCrashOverlay(content: String, throwable: Throwable? = null) { + // deny network requests + PurrfectSnap.classCache.apply { + unifiedGrpcService.hook("unaryCall", HookStage.BEFORE) { param -> + param.setResult(null) + } + networkApi.hook("submit", HookStage.BEFORE) { param -> + param.setResult(null) + } + } + + Hooker.ephemeralHook(Activity::class.java, "onPostCreate", HookStage.AFTER) { param -> + val contentView = param.thisObject().findViewById(android.R.id.content) + contentView.children().forEach { it.visibility = View.GONE } + val screenView = createComposeView(param.thisObject()) { + PurrfectOverlayTheme { + Box( + modifier = Modifier + .fillMaxSize() + .background(PurrfectOverlayPalette.backgroundGradient), + contentAlignment = Alignment.Center + ) { + PurrfectGlassCard( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 16.dp), + title = "PurrfectSnap", + subtitle = content, + icon = Icons.Outlined.Warning + ) { + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.spacedBy(10.dp, Alignment.CenterHorizontally) + ) { + if (throwable != null) { + Surface( + onClick = { contentView.context.copyToClipboard(throwable.stackTraceToString()) }, + shape = RoundedCornerShape(999.dp), + color = Color.White.copy(alpha = 0.10f), + border = BorderStroke(1.dp, Color.White.copy(alpha = 0.12f)) + ) { + Text( + "Copy error", + modifier = Modifier.padding(horizontal = 14.dp, vertical = 10.dp), + color = Color.White + ) + } + } + Surface( + onClick = { exitProcess(1) }, + shape = RoundedCornerShape(999.dp), + color = PurrfectOverlayPalette.glowPrimary.copy(alpha = 0.28f), + border = BorderStroke( + 1.dp, + Brush.linearGradient( + listOf( + PurrfectOverlayPalette.glowPrimary.copy(alpha = 0.7f), + PurrfectOverlayPalette.glowSecondary.copy(alpha = 0.55f), + ) + ) + ) + ) { + Text( + "Exit", + modifier = Modifier.padding(horizontal = 18.dp, vertical = 10.dp), + color = Color.White, + fontWeight = androidx.compose.ui.text.font.FontWeight.SemiBold + ) + } + } + } + } + } + }.apply { + layoutParams = FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT) + } + contentView.addView(screenView) + } + } + } + + inner class Toast( + val composable: @Composable Toast.() -> Unit, + val durationMs: Int + ) { + var shown by mutableStateOf(false) + var visible by mutableStateOf(false) + } + + private val toasts = mutableStateListOf() + private val customComposables = mutableStateListOf() + + @OptIn(ExperimentalFoundationApi::class) + @Composable + private fun OverlayContent() { + CompositionLocalProvider( + LocalContentColor provides Color.White, + LocalTextStyle provides LocalTextStyle.current.merge(TextStyle(color = Color.White)) + ) { + Box( + modifier = Modifier + .fillMaxSize() + .statusBarsPadding() + .navigationBarsPadding(), + ) { + toasts.forEach { toast -> + val animation by animateFloatAsState( + targetValue = if (toast.visible) 1f else 0f, + animationSpec = if (toast.visible) tween(durationMillis = 150) else tween(durationMillis = 300), + label = "toast" + ) + + LaunchedEffect(toast) { + toast.visible = true + if (toast.durationMs < 0) return@LaunchedEffect + delay(toast.durationMs.toLong()) + toast.visible = false + delay(1000) + toast.shown = true + synchronized(toasts) { + if (toasts.isNotEmpty() && toasts.all { it.shown }) toasts.clear() + } + } + + val deviceWidth = LocalContext.current.resources.displayMetrics.widthPixels + val delayAnimationSpec = rememberSplineBasedDecay() + val anchors = DraggableAnchors { + 0 at 0f + 1 at deviceWidth.toFloat() + } + val draggableState = remember { + AnchoredDraggableState( + initialValue = 0, + anchors = anchors + ) + } + + LaunchedEffect(draggableState.currentValue) { + if (draggableState.currentValue == 1) { + toast.visible = false + } + } + + Box( + modifier = Modifier + .fillMaxWidth() + .anchoredDraggable( + state = draggableState, + orientation = Orientation.Horizontal + ) + .offset { IntOffset(draggableState.offset.roundToInt(), 0) } + .graphicsLayer { + alpha = animation + translationY = -100.dp.toPx() * (1 - animation) + } + ) { + if (animation > 0.01f) { + toast.composable(toast) + } + } + } + + customComposables.forEach { + it() + } + } + } + } + + private val overlayTag = Random.nextLong() + + private fun injectOverlay(activity: Activity) { + val root = activity.findViewById(android.R.id.content) + activity.runOnUiThread { + if (root.findViewWithTag(overlayTag) != null) return@runOnUiThread + root.addView(createComposeView(activity) { + PurrfectOverlayTheme { OverlayContent() } + }.apply { + tag = overlayTag + layoutParams = FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT) + }) + } + } + + fun onActivityCreate(activity: Activity) { + injectOverlay(activity) + } + + fun addCustomComposable(composable: CustomComposable) { + customComposables.add(composable) + } + + fun removeCustomComposable(composable: CustomComposable) { + customComposables.remove(composable) + } + + @Composable + private fun DurationProgress( + duration: Int, + modifier: Modifier = Modifier + ) { + val progress = remember { Animatable(1f) } + + LaunchedEffect(Unit) { + progress.animateTo( + targetValue = 0f, + animationSpec = tween(durationMillis = duration, easing = LinearEasing) + ) + } + + LinearProgressIndicator( + progress = { progress.value }, + modifier = modifier, + color = PurrfectOverlayPalette.glowSecondary.copy(alpha = 0.85f), + trackColor = Color.White.copy(alpha = 0.10f), + ) + } + + fun showStatusToast( + icon: ImageVector, + text: String, + durationMs: Int = 2000, + showDuration: Boolean = true, + maxLines: Int = 3 + ) { + showToast( + icon = { Icon(icon, contentDescription = "icon", modifier = Modifier.size(32.dp)) }, + text = { + Text( + text, + modifier = Modifier.fillMaxWidth(), + maxLines = maxLines, + overflow = TextOverflow.Ellipsis, + lineHeight = 15.sp, + fontSize = 13.sp, + color = Color.White + ) + }, + durationMs = durationMs, + showDuration = showDuration + ) + } + + private fun showToast( + icon: @Composable () -> Unit = { + Icon(Icons.Outlined.Warning, contentDescription = "icon", modifier = Modifier.size(32.dp)) + }, + text: @Composable () -> Unit = {}, + durationMs: Int = 3000, + showDuration: Boolean = true, + ) { + val activity = context.mainActivity ?: return + injectOverlay(activity) + toasts.add(Toast( + composable = { + val shape = RoundedCornerShape(18.dp) + Surface( + modifier = Modifier + .padding(horizontal = 14.dp, vertical = 10.dp) + .fillMaxWidth() + .shadow( + elevation = 18.dp, + shape = shape, + spotColor = PurrfectOverlayPalette.glowPrimary.copy(alpha = 0.22f), + ambientColor = PurrfectOverlayPalette.glowSecondary.copy(alpha = 0.16f) + ) + .clip(shape) + .background(PurrfectOverlayPalette.cardOverlay, shape) + .border( + BorderStroke( + 1.dp, + Brush.linearGradient( + listOf( + PurrfectOverlayPalette.glowPrimary.copy(alpha = 0.55f), + PurrfectOverlayPalette.glowSecondary.copy(alpha = 0.35f), + ) + ) + ), + shape + ), + color = Color.Transparent, + contentColor = Color.White, + tonalElevation = 0.dp, + shadowElevation = 0.dp + ) { + Column { + Row( + horizontalArrangement = Arrangement.spacedBy(12.dp), + verticalAlignment = Alignment.CenterVertically, + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 14.dp, vertical = 12.dp) + ) { + Box( + modifier = Modifier + .size(42.dp) + .clip(RoundedCornerShape(14.dp)) + .background(Color.White.copy(alpha = 0.08f)) + .border(1.dp, Color.White.copy(alpha = 0.10f), RoundedCornerShape(14.dp)), + contentAlignment = Alignment.Center + ) { + icon() + } + text() + } + if (showDuration && durationMs > 0) { + DurationProgress(duration = durationMs, modifier = Modifier.fillMaxWidth()) + } + } + } + }, + durationMs = durationMs + )) + } +} diff --git a/core/src/main/kotlin/me/eternal/purrfectsnap/core/ui/PurrfectOverlayTheme.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/ui/PurrfectOverlayTheme.kt new file mode 100644 index 00000000..d9ad01e2 --- /dev/null +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/ui/PurrfectOverlayTheme.kt @@ -0,0 +1,181 @@ +package me.eternal.purrfectsnap.core.ui + +import androidx.compose.foundation.BorderStroke +import androidx.compose.foundation.background +import androidx.compose.foundation.border +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.BoxScope +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Surface +import androidx.compose.material3.darkColorScheme +import androidx.compose.runtime.Composable +import androidx.compose.runtime.Immutable +import androidx.compose.runtime.CompositionLocalProvider +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.draw.shadow +import androidx.compose.ui.graphics.Brush +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextOverflow +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import androidx.compose.material3.Icon +import androidx.compose.material3.LocalTextStyle +import androidx.compose.material3.Text +import androidx.compose.ui.text.TextStyle + +@Immutable +object PurrfectOverlayPalette { + val glowPrimary = Color(0xFF8C7BFF) + val glowSecondary = Color(0xFF5FD8FF) + val textPrimary = Color.White + val textSecondary = Color(0xFFD9D3FF) + + val backgroundGradient = Brush.verticalGradient( + listOf( + Color(0xFF261F58), + Color(0xFF302A6D), + Color(0xFF241F52), + ) + ) + + val cardOverlay = Brush.linearGradient( + listOf( + Color(0xFF2A2452).copy(alpha = 0.96f), + Color(0xFF1A143A).copy(alpha = 0.92f), + ) + ) + + val cardOverlayColor = Color(0xFF2A2452).copy(alpha = 0.94f) +} + +@Composable +fun PurrfectOverlayTheme(content: @Composable () -> Unit) { + val scheme = darkColorScheme( + primary = PurrfectOverlayPalette.glowPrimary, + secondary = PurrfectOverlayPalette.glowSecondary, + background = Color.Transparent, + surface = PurrfectOverlayPalette.cardOverlayColor, + onPrimary = Color.White, + onSecondary = Color.White, + onBackground = Color.White, + onSurface = Color.White, + ) + MaterialTheme( + colorScheme = scheme, + shapes = MaterialTheme.shapes.copy( + small = RoundedCornerShape(14.dp), + medium = RoundedCornerShape(18.dp), + large = RoundedCornerShape(22.dp), + ), + content = { + CompositionLocalProvider( + androidx.compose.material3.LocalContentColor provides PurrfectOverlayPalette.textPrimary, + LocalTextStyle provides LocalTextStyle.current.merge( + TextStyle(color = PurrfectOverlayPalette.textPrimary) + ) + ) { + content() + } + } + ) +} + +@Composable +fun PurrfectGlassCard( + modifier: Modifier = Modifier, + title: String? = null, + subtitle: String? = null, + icon: ImageVector? = null, + content: @Composable BoxScope.() -> Unit, +) { + val shape = RoundedCornerShape(22.dp) + Surface( + modifier = modifier + .shadow( + elevation = 18.dp, + shape = shape, + spotColor = PurrfectOverlayPalette.glowPrimary.copy(alpha = 0.25f), + ambientColor = PurrfectOverlayPalette.glowSecondary.copy(alpha = 0.18f), + ) + .clip(shape) + .background(PurrfectOverlayPalette.cardOverlay, shape) + .border( + BorderStroke( + 1.dp, + Brush.linearGradient( + listOf( + PurrfectOverlayPalette.glowPrimary.copy(alpha = 0.55f), + PurrfectOverlayPalette.glowSecondary.copy(alpha = 0.35f), + ) + ) + ), + shape + ), + color = Color.Transparent, + tonalElevation = 0.dp, + shadowElevation = 0.dp + ) { + Box( + modifier = Modifier + .background(PurrfectOverlayPalette.cardOverlay, shape) + .padding(16.dp) + ) { + Column { + if (title != null || subtitle != null || icon != null) { + Row(verticalAlignment = Alignment.CenterVertically) { + if (icon != null) { + Box( + modifier = Modifier + .size(40.dp) + .clip(RoundedCornerShape(14.dp)) + .background(Color.White.copy(alpha = 0.08f)) + .border(1.dp, Color.White.copy(alpha = 0.10f), RoundedCornerShape(14.dp)), + contentAlignment = Alignment.Center + ) { + Icon(icon, contentDescription = null, tint = Color.White, modifier = Modifier.size(20.dp)) + } + Spacer(Modifier.width(12.dp)) + } + Column(modifier = Modifier.weight(1f)) { + if (title != null) { + Text( + text = title, + color = PurrfectOverlayPalette.textPrimary, + fontWeight = FontWeight.ExtraBold, + fontSize = 18.sp, + maxLines = 1, + overflow = TextOverflow.Ellipsis + ) + } + if (!subtitle.isNullOrBlank()) { + Spacer(Modifier.height(2.dp)) + Text( + text = subtitle, + color = PurrfectOverlayPalette.textSecondary, + fontSize = 12.sp, + maxLines = 2, + overflow = TextOverflow.Ellipsis + ) + } + } + } + Spacer(Modifier.height(12.dp)) + } + Box(content = content) + } + } + } +} + diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/ui/UserInterface.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/ui/UserInterface.kt similarity index 91% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/ui/UserInterface.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/ui/UserInterface.kt index 8b917ee5..7a1abf29 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/ui/UserInterface.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/ui/UserInterface.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.core.ui +package me.eternal.purrfectsnap.core.ui import android.content.res.Resources import android.graphics.Typeface @@ -6,10 +6,10 @@ import android.util.TypedValue import android.view.Gravity import android.widget.TextView import androidx.core.content.res.ResourcesCompat -import me.rhunk.snapenhance.core.ModContext -import me.rhunk.snapenhance.core.util.hook.HookStage -import me.rhunk.snapenhance.core.util.hook.hook -import me.rhunk.snapenhance.core.util.ktx.isDarkTheme +import me.eternal.purrfectsnap.core.ModContext +import me.eternal.purrfectsnap.core.util.hook.HookStage +import me.eternal.purrfectsnap.core.util.hook.hook +import me.eternal.purrfectsnap.core.util.ktx.isDarkTheme class UserInterface( private val context: ModContext @@ -80,4 +80,4 @@ class UserInterface( { unhooks.forEach { it.unhook() } } } } -} \ No newline at end of file +} diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/ui/ViewAppearanceHelper.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/ui/ViewAppearanceHelper.kt similarity index 77% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/ui/ViewAppearanceHelper.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/ui/ViewAppearanceHelper.kt index c2091ce3..588e094d 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/ui/ViewAppearanceHelper.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/ui/ViewAppearanceHelper.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.core.ui +package me.eternal.purrfectsnap.core.ui import android.app.Activity import android.app.AlertDialog @@ -12,9 +12,8 @@ import android.os.SystemClock import android.view.MotionEvent import android.view.View import android.view.ViewGroup -import me.rhunk.snapenhance.core.SnapEnhance -import me.rhunk.snapenhance.core.wrapper.impl.composer.ComposerContext -import me.rhunk.snapenhance.core.wrapper.impl.composer.ComposerViewNode +import me.eternal.purrfectsnap.core.wrapper.impl.composer.ComposerContext +import me.eternal.purrfectsnap.core.wrapper.impl.composer.ComposerViewNode private val foregroundDrawableListTag = randomTag() @@ -137,21 +136,31 @@ fun View.hideViewCompletely() { } fun View.getComposerViewNode(): ComposerViewNode? { - if (!SnapEnhance.classCache.composerView.isInstance(this)) return null - - val composerViewNode = this::class.java.methods.firstOrNull { - it.name == "getComposerViewNode" - }?.invoke(this) ?: return null - - return ComposerViewNode.fromNode(composerViewNode) + // Prefer Composer API if present + this::class.java.methods.firstOrNull { it.name == "getComposerViewNode" }?.let { method -> + val node = method.invoke(this) ?: return null + return ComposerViewNode.fromNode(node) + } + // Fallback to Valdi API + this::class.java.methods.firstOrNull { it.name == "getValdiViewNode" && it.parameterTypes.isEmpty() }?.let { method -> + val node = method.invoke(this) ?: return null + return ComposerViewNode.fromNode(node) + } + return null } fun View.getComposerContext(): ComposerContext? { - if (!SnapEnhance.classCache.composerView.isInstance(this)) return null - - return ComposerContext(this::class.java.methods.firstOrNull { - it.name == "getComposerContext" - }?.invoke(this) ?: return null) + // Prefer Composer API if present + this::class.java.methods.firstOrNull { it.name == "getComposerContext" }?.let { method -> + val ctx = method.invoke(this) ?: return null + return ComposerContext(ctx) + } + // Fallback to Valdi API + this::class.java.methods.firstOrNull { it.name == "getValdiContext" && it.parameterTypes.isEmpty() }?.let { method -> + val ctx = method.invoke(this) ?: return null + return ComposerContext(ctx) + } + return null } object ViewAppearanceHelper { diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/ui/ViewTagState.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/ui/ViewTagState.kt similarity index 91% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/ui/ViewTagState.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/ui/ViewTagState.kt index 64b8348e..197f6a3f 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/ui/ViewTagState.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/ui/ViewTagState.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.core.ui +package me.eternal.purrfectsnap.core.ui import android.view.View import kotlin.random.Random diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/ui/menu/AbstractMenu.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/ui/menu/AbstractMenu.kt similarity index 67% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/ui/menu/AbstractMenu.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/ui/menu/AbstractMenu.kt index 89b4dddb..5d162f51 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/ui/menu/AbstractMenu.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/ui/menu/AbstractMenu.kt @@ -1,9 +1,9 @@ -package me.rhunk.snapenhance.core.ui.menu +package me.eternal.purrfectsnap.core.ui.menu import android.view.View import android.view.ViewGroup -import me.rhunk.snapenhance.core.ModContext -import me.rhunk.snapenhance.core.event.events.impl.AddViewEvent +import me.eternal.purrfectsnap.core.ModContext +import me.eternal.purrfectsnap.core.event.events.impl.AddViewEvent abstract class AbstractMenu { lateinit var menuViewInjector: MenuViewInjector diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/ui/menu/MenuViewInjector.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/ui/menu/MenuViewInjector.kt similarity index 90% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/ui/menu/MenuViewInjector.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/ui/menu/MenuViewInjector.kt index 64774176..e9a3c658 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/ui/menu/MenuViewInjector.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/ui/menu/MenuViewInjector.kt @@ -1,15 +1,15 @@ -package me.rhunk.snapenhance.core.ui.menu +package me.eternal.purrfectsnap.core.ui.menu import android.annotation.SuppressLint import android.view.Gravity import android.view.View import android.view.ViewGroup import android.widget.FrameLayout -import me.rhunk.snapenhance.core.event.events.impl.AddViewEvent -import me.rhunk.snapenhance.core.features.Feature -import me.rhunk.snapenhance.core.features.impl.COFOverride -import me.rhunk.snapenhance.core.ui.menu.impl.* -import me.rhunk.snapenhance.core.util.ktx.getIdentifier +import me.eternal.purrfectsnap.core.event.events.impl.AddViewEvent +import me.eternal.purrfectsnap.core.features.Feature +import me.eternal.purrfectsnap.core.features.impl.COFOverride +import me.eternal.purrfectsnap.core.ui.menu.impl.* +import me.eternal.purrfectsnap.core.util.ktx.getIdentifier import kotlin.reflect.KClass @SuppressLint("DiscouragedApi") @@ -85,4 +85,4 @@ class MenuViewInjector : Feature("MenuViewInjector") { } } } -} \ No newline at end of file +} diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/ui/menu/impl/ChatActionMenu.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/ui/menu/impl/ChatActionMenu.kt similarity index 89% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/ui/menu/impl/ChatActionMenu.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/ui/menu/impl/ChatActionMenu.kt index 2657ec95..f93f64ec 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/ui/menu/impl/ChatActionMenu.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/ui/menu/impl/ChatActionMenu.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.core.ui.menu.impl +package me.eternal.purrfectsnap.core.ui.menu.impl import android.graphics.drawable.ColorDrawable import android.graphics.drawable.Drawable @@ -9,17 +9,17 @@ import android.view.ViewGroup import android.view.ViewGroup.MarginLayoutParams import android.widget.Button import android.widget.LinearLayout -import me.rhunk.snapenhance.bridge.logger.LoggedChatEdit -import me.rhunk.snapenhance.core.features.impl.downloader.MediaDownloader -import me.rhunk.snapenhance.core.features.impl.experiments.ConvertMessageLocally -import me.rhunk.snapenhance.core.features.impl.messaging.Messaging -import me.rhunk.snapenhance.core.features.impl.spying.MessageLogger -import me.rhunk.snapenhance.core.ui.ViewTagState -import me.rhunk.snapenhance.core.ui.menu.AbstractMenu -import me.rhunk.snapenhance.core.ui.triggerCloseTouchEvent -import me.rhunk.snapenhance.core.util.hook.HookStage -import me.rhunk.snapenhance.core.util.hook.hook -import me.rhunk.snapenhance.core.util.ktx.vibrateLongPress +import me.eternal.purrfectsnap.bridge.logger.LoggedChatEdit +import me.eternal.purrfectsnap.core.features.impl.downloader.MediaDownloader +import me.eternal.purrfectsnap.core.features.impl.experiments.ConvertMessageLocally +import me.eternal.purrfectsnap.core.features.impl.messaging.Messaging +import me.eternal.purrfectsnap.core.features.impl.spying.MessageLogger +import me.eternal.purrfectsnap.core.ui.ViewTagState +import me.eternal.purrfectsnap.core.ui.menu.AbstractMenu +import me.eternal.purrfectsnap.core.ui.triggerCloseTouchEvent +import me.eternal.purrfectsnap.core.util.hook.HookStage +import me.eternal.purrfectsnap.core.util.hook.hook +import me.eternal.purrfectsnap.core.util.ktx.vibrateLongPress class ChatActionMenu : AbstractMenu() { @@ -200,12 +200,12 @@ class ChatActionMenu : AbstractMenu() { .convertMessageInterface(it) }.onFailure { this@ChatActionMenu.context.log.verbose("Failed to convert message: $it") - this@ChatActionMenu.context.shortToast("Failed to edit message: $it") + this@ChatActionMenu.context.shortToast(this@ChatActionMenu.context.translation["error_messages.failed_to_edit_message"].replace("{error}", it.toString())) } } }, onError = { - this@ChatActionMenu.context.shortToast("Failed to fetch message: $it") + this@ChatActionMenu.context.shortToast(this@ChatActionMenu.context.translation["error_messages.failed_to_fetch_message"].replace("{error}", it.toString())) } ) } diff --git a/core/src/main/kotlin/me/eternal/purrfectsnap/core/ui/menu/impl/FriendFeedInfoMenu.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/ui/menu/impl/FriendFeedInfoMenu.kt new file mode 100644 index 00000000..67c7bfb5 --- /dev/null +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/ui/menu/impl/FriendFeedInfoMenu.kt @@ -0,0 +1,796 @@ +package me.eternal.purrfectsnap.core.ui.menu.impl + +import android.graphics.BitmapFactory +import android.view.Gravity +import android.view.View +import android.view.ViewGroup +import android.widget.FrameLayout +import android.widget.LinearLayout +import android.widget.ScrollView +import androidx.compose.foundation.Image +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +import androidx.compose.foundation.BorderStroke +import androidx.compose.foundation.border +import androidx.compose.foundation.gestures.detectTapGestures +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.automirrored.outlined.Message +import androidx.compose.material.icons.filled.CheckCircleOutline +import androidx.compose.material.icons.filled.Info +import androidx.compose.material.icons.filled.NotInterested +import androidx.compose.material.icons.outlined.* +import androidx.compose.material3.* +import androidx.compose.runtime.* +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Brush +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.asImageBitmap +import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.input.pointer.pointerInput +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.font.FontFamily +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext +import me.eternal.purrfectsnap.common.data.ContentType +import me.eternal.purrfectsnap.common.data.FriendLinkType +import me.eternal.purrfectsnap.common.database.impl.ConversationMessage +import me.eternal.purrfectsnap.common.database.impl.FriendInfo +import me.eternal.purrfectsnap.common.scripting.ui.EnumScriptInterface +import me.eternal.purrfectsnap.common.scripting.ui.InterfaceManager +import me.eternal.purrfectsnap.common.scripting.ui.ScriptInterface +import me.eternal.purrfectsnap.common.ui.createComposeAlertDialog +import me.eternal.purrfectsnap.common.ui.createComposeView +import me.eternal.purrfectsnap.common.util.protobuf.ProtoReader +import me.eternal.purrfectsnap.common.util.snap.BitmojiSelfie +import me.eternal.purrfectsnap.core.event.events.impl.AddViewEvent +import me.eternal.purrfectsnap.core.features.impl.experiments.EndToEndEncryption +import me.eternal.purrfectsnap.core.features.impl.messaging.AutoMarkAsRead +import me.eternal.purrfectsnap.core.features.impl.messaging.Messaging +import me.eternal.purrfectsnap.core.features.impl.spying.MessageLogger +import me.eternal.purrfectsnap.core.ui.ViewAppearanceHelper +import me.eternal.purrfectsnap.core.ui.children +import me.eternal.purrfectsnap.core.ui.PurrfectGlassCard +import me.eternal.purrfectsnap.core.ui.PurrfectOverlayPalette +import me.eternal.purrfectsnap.core.ui.PurrfectOverlayTheme +import me.eternal.purrfectsnap.core.ui.menu.AbstractMenu +import me.eternal.purrfectsnap.core.ui.randomTag +import me.eternal.purrfectsnap.core.ui.triggerRootCloseTouchEvent +import me.eternal.purrfectsnap.core.util.ktx.isDarkTheme +import me.eternal.purrfectsnap.core.wrapper.impl.sanitizeForLayout +import java.net.URL +import java.text.DateFormat +import java.text.SimpleDateFormat +import java.util.Calendar +import java.util.Date +import java.util.Locale + +class FriendFeedInfoMenu : AbstractMenu() { + private fun formatDate(timestamp: Long): String? { + return SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.ENGLISH).format(Date(timestamp)) + } + + private fun showProfileInfo(profile: FriendInfo) { + val translation = context.translation.getCategory("profile_info") + val firstCreatedUsername = context.database.getFriendOriginalUsername(profile.mutableUsername.toString()) ?: profile.firstCreatedUsername + + context.runOnUiThread { + val addedTimestamp: Long = profile.addedTimestamp.coerceAtLeast(profile.reverseAddedTimestamp) + val birthday = Calendar.getInstance() + birthday[Calendar.MONTH] = (profile.birthday shr 32).toInt() - 1 + val birthdayLine = birthday.getDisplayName( + Calendar.MONTH, + Calendar.LONG, + context.translation.loadedLocale + )?.let { + if (profile.birthday == 0L) context.translation["profile_info.hidden_birthday"] + else context.translation.format( + "profile_info.birthday", + "month" to it, + "day" to profile.birthday.toInt().toString() + ) + } + val friendshipLine = run { + context.translation["friendship_link_type.${FriendLinkType.fromValue(profile.friendLinkType).shortName}"] + }.takeIf { + if (profile.friendLinkType == FriendLinkType.MUTUAL.value) addedTimestamp.toInt() > 0 else true + } + val snapchatPlusState = translation.getCategory("snapchat_plus_state")[ + if (profile.postViewEmoji != null) "subscribed" else "not_subscribed" + ] + + val lines = buildList { + translation["first_created_username"]?.let { add("$it: $firstCreatedUsername") } + translation["mutable_username"]?.let { add("$it: ${profile.mutableUsername}") } + profile.displayName?.let { name -> + translation["display_name"]?.let { add("$it: $name") } + } + formatDate(addedTimestamp)?.takeIf { addedTimestamp > 0 }?.let { date -> + translation["added_date"]?.let { add("$it: $date") } + } + birthdayLine?.let { add(it) } + friendshipLine?.let { value -> + translation["friendship"]?.let { add("$it: $value") } + } + context.database.getAddSource(profile.userId!!)?.takeIf { it.isNotEmpty() }?.let { value -> + translation["add_source"]?.let { add("$it: $value") } + } + translation["snapchat_plus"]?.let { add("$it: $snapchatPlusState") } + } + + val avatarUrl = runCatching { + if (profile.bitmojiSelfieId != null && profile.bitmojiAvatarId != null) { + BitmojiSelfie.getBitmojiSelfie( + profile.bitmojiSelfieId.toString(), + profile.bitmojiAvatarId.toString(), + BitmojiSelfie.BitmojiSelfieType.NEW_THREE_D + ) + } else null + }.getOrNull() + + createComposeAlertDialog(context.mainActivity!!) { alertDialog -> + PurrfectOverlayTheme { + val border = remember { + Brush.linearGradient( + listOf( + PurrfectOverlayPalette.glowPrimary.copy(alpha = 0.55f), + PurrfectOverlayPalette.glowSecondary.copy(alpha = 0.35f) + ) + ) + } + val shape = RoundedCornerShape(26.dp) + val avatarBitmap by produceState(initialValue = null, avatarUrl) { + value = runCatching { + val url = avatarUrl ?: return@runCatching null + val bytes = withContext(Dispatchers.IO) { URL(url).readBytes() } + BitmapFactory.decodeByteArray(bytes, 0, bytes.size)?.asImageBitmap() + }.getOrNull() + } + Surface( + modifier = Modifier + .fillMaxWidth() + .widthIn(max = 420.dp), + shape = shape, + color = Color.Transparent, + tonalElevation = 0.dp, + shadowElevation = 18.dp, + border = BorderStroke(1.dp, border) + ) { + Column( + modifier = Modifier + .background(PurrfectOverlayPalette.cardOverlay, shape) + .padding(horizontal = 18.dp, vertical = 16.dp), + verticalArrangement = Arrangement.spacedBy(12.dp), + horizontalAlignment = Alignment.CenterHorizontally + ) { + Row( + modifier = Modifier.fillMaxWidth(), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(10.dp) + ) { + Surface( + shape = RoundedCornerShape(12.dp), + color = Color.White.copy(alpha = 0.08f) + ) { + Icon( + Icons.Outlined.Info, + contentDescription = null, + modifier = Modifier.padding(8.dp), + tint = Color.White + ) + } + Column(modifier = Modifier.weight(1f)) { + Text( + text = translation["title"] ?: "Profile Info", + color = Color.White, + fontWeight = FontWeight.Bold, + fontSize = 16.sp + ) + val subtitleText = listOfNotNull( + profile.displayName, + profile.username, + profile.mutableUsername + ).firstOrNull()?.toString().orEmpty() + Text( + text = subtitleText, + color = PurrfectOverlayPalette.textSecondary, + fontSize = 12.sp + ) + } + } + Surface( + shape = RoundedCornerShape(999.dp), + color = Color.White.copy(alpha = 0.08f), + border = BorderStroke(1.dp, Color.White.copy(alpha = 0.12f)) + ) { + Box( + modifier = Modifier + .size(72.dp) + .padding(10.dp), + contentAlignment = Alignment.Center + ) { + if (avatarBitmap != null) { + Image( + bitmap = avatarBitmap!!, + contentDescription = null, + modifier = Modifier.fillMaxSize() + ) + } else { + Icon( + Icons.Outlined.Person, + contentDescription = null, + tint = Color.White.copy(alpha = 0.85f), + modifier = Modifier.size(32.dp) + ) + } + } + } + Surface( + shape = RoundedCornerShape(18.dp), + color = Color.White.copy(alpha = 0.06f), + border = BorderStroke(1.dp, Color.White.copy(alpha = 0.12f)), + modifier = Modifier.fillMaxWidth() + ) { + Column( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 12.dp, vertical = 12.dp), + verticalArrangement = Arrangement.spacedBy(6.dp) + ) { + lines.forEach { line -> + Text( + text = line, + color = Color.White, + fontSize = 13.sp, + lineHeight = 16.sp + ) + } + } + } + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.End + ) { + Text( + text = context.translation["button.ok"] ?: "OK", + color = Color.White, + fontWeight = FontWeight.SemiBold, + modifier = Modifier + .clickable { alertDialog.dismiss() } + .padding(horizontal = 6.dp, vertical = 4.dp) + ) + } + } + } + } + }.show() + } + } + + private suspend fun showConversationPreview( + targetUser: String?, + conversationId: String + ) { + val friendInfo = targetUser?.let { context.database.getFriendInfo(it) } + val conversationInfo = conversationId.takeIf { targetUser == null }?.let { context.database.getFeedEntryByConversationId(it) } + val participants by lazy { + context.database.getConversationParticipants(conversationId)!! + .map { context.database.getFriendInfo(it)!! } + .associateBy { it.userId!! } + } + + withContext(Dispatchers.Main) { + createComposeAlertDialog( + context.mainActivity!!, + ) { + var pageIndex by remember { mutableIntStateOf(0) } + val messages = remember { mutableStateListOf<@Composable () -> Unit>() } + var totalMessages by remember { mutableIntStateOf(-1) } + val coroutineScope = rememberCoroutineScope() + + suspend fun loadMore() { + val conversationMessages = context.database.getMessagesFromConversationId( + conversationId, + 50, + page = pageIndex++ + ) ?: emptyList() + + if (totalMessages == -1) { + totalMessages = conversationMessages.firstOrNull()?.serverMessageId ?: 0 + } + + val messageLogger = context.feature(MessageLogger::class) + val endToEndEncryption = context.feature(EndToEndEncryption::class) + + val parsedMessages = conversationMessages.mapNotNull Unit> { message -> + val sender = participants[message.senderId] + val messageProtoReader = + (messageLogger.takeIf { it.isEnabled && message.contentType == ContentType.STATUS.id }?.getMessageProto(conversationId, message.clientMessageId.toLong()) // process deleted messages if message logger is enabled + ?: ProtoReader(message.messageContent!!).followPath(4, 4) // database message + )?.let { + if (endToEndEncryption.isEnabled) endToEndEncryption.decryptDatabaseMessage(message) else it // try to decrypt message if e2ee is enabled + } ?: return@mapNotNull null + + val contentType = ContentType.fromMessageContainer(messageProtoReader) ?: ContentType.fromId(message.contentType) + var messageString = if (contentType == ContentType.CHAT) { + messageProtoReader.getString(2, 1) ?: return@mapNotNull null + } else "[${context.translation.getOrNull("content_type.${contentType.name}") ?: contentType.name}]" + + if (contentType == ContentType.SNAP) { + messageString = "\uD83D\uDFE5" //red square + if (message.readTimestamp > 0) { + messageString += " \uD83D\uDC40 " //eyes + messageString += DateFormat.getDateTimeInstance( + DateFormat.SHORT, + DateFormat.SHORT + ).format(Date(message.readTimestamp)) + } + } + + messageString = messageString.sanitizeForLayout() + + var displayUsername = sender?.displayName ?: sender?.usernameForSorting ?: context.translation["conversation_preview.unknown_user"] + displayUsername = displayUsername.sanitizeForLayout() + + if (displayUsername.length > 12) { + displayUsername = displayUsername.substring(0, 13) + "... " + } + + { + Text( + text = "$displayUsername: $messageString", + modifier = Modifier.padding(4.dp), + color = Color.White + ) + } + } + + withContext(Dispatchers.Main) { + messages.addAll(parsedMessages) + } + } + + PurrfectOverlayTheme { + PurrfectGlassCard( + modifier = Modifier + .fillMaxWidth() + .widthIn(max = 420.dp), + title = context.translation.getOrNull("conversation_preview.title") ?: "Preview", + subtitle = (friendInfo?.displayName ?: conversationInfo?.feedDisplayName ?: conversationId).sanitizeForLayout(), + icon = Icons.Outlined.Visibility + ) { + Column( + modifier = Modifier + .fillMaxWidth() + .heightIn(max = 560.dp), + verticalArrangement = Arrangement.spacedBy(10.dp) + ) { + @Composable + fun Entry(icon: ImageVector, text: String?, title: Boolean) { + Row( + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(6.dp) + ) { + Icon(icon, contentDescription = null, tint = Color.White.copy(alpha = 0.9f)) + Text( + text = text ?: "", + fontWeight = if (title) FontWeight.Bold else FontWeight.Normal, + fontSize = if (title) 14.sp else 12.sp, + color = Color.White.copy(alpha = if (title) 0.95f else 0.80f), + maxLines = 1, + overflow = androidx.compose.ui.text.style.TextOverflow.Ellipsis + ) + } + } + + Row( + modifier = Modifier.fillMaxWidth(), + verticalAlignment = Alignment.CenterVertically, + ) { + Column(modifier = Modifier.weight(1f)) { + friendInfo?.let { info -> + Entry( + Icons.Outlined.Person, + info.displayName?.let { "$it (${info.usernameForSorting})" } ?: info.usernameForSorting, + true + ) + } + conversationInfo?.let { + Entry(Icons.Outlined.Group, (it.feedDisplayName ?: it.key).toString(), true) + } + Entry( + Icons.AutoMirrored.Outlined.Message, + context.translation.format("conversation_preview.total_messages", "count" to totalMessages.toString()), + false + ) + } + friendInfo?.let { + IconButton( + onClick = { coroutineScope.launch(Dispatchers.IO) { showProfileInfo(it) } } + ) { + Icon(Icons.Outlined.MoreVert, contentDescription = null, tint = Color.White) + } + } + } + + Spacer( + modifier = Modifier + .height(1.dp) + .fillMaxWidth() + .background(Color.White.copy(alpha = 0.10f)) + ) + + LazyColumn( + modifier = Modifier.fillMaxWidth().weight(1f), + contentPadding = PaddingValues(8.dp), + reverseLayout = true + ) { + items(messages) { message -> + Row(modifier = Modifier.fillMaxWidth()) { + CompositionLocalProvider( + LocalContentColor provides Color.White + ) { + message() + } + } + } + item { + Spacer(modifier = Modifier.height(10.dp)) + LaunchedEffect(Unit) { withContext(Dispatchers.IO) { loadMore() } } + if (messages.isEmpty()) { + Text( + text = context.translation["conversation_preview.no_messages"], + modifier = Modifier + .padding(4.dp) + .fillMaxWidth(), + textAlign = TextAlign.Center, + color = Color.White.copy(alpha = 0.75f) + ) + } + } + } + } + } + } + }.show() + } + } + + @Composable + private fun MenuElement( + index: Int, + icon: ImageVector, + text: String, + onClick: () -> Unit, + onLongClick: (() -> Unit)? = null, + content: @Composable RowScope.() -> Unit = {} + ) { + val shape = RoundedCornerShape(18.dp) + val border = Brush.linearGradient( + listOf( + PurrfectOverlayPalette.glowPrimary.copy(alpha = 0.45f), + PurrfectOverlayPalette.glowSecondary.copy(alpha = 0.28f) + ) + ) + if (index > 0) Spacer(Modifier.height(10.dp)) + Surface( + color = Color.Transparent, + contentColor = Color.White, + shape = shape, + tonalElevation = 0.dp, + shadowElevation = 0.dp, + modifier = Modifier + .fillMaxWidth() + .background(PurrfectOverlayPalette.cardOverlay, shape) + .border(1.dp, border, shape) + ) { + Row( + modifier = Modifier + .fillMaxWidth() + .pointerInput(Unit) { + detectTapGestures( + onLongPress = { + onLongClick?.invoke() + }, + onTap = { + onClick() + } + ) + } + .heightIn(min = 55.dp) + .padding(start = 16.dp, end = 16.dp), + verticalAlignment = Alignment.CenterVertically + ) { + Icon(icon, contentDescription = null, modifier = Modifier + .size(32.dp) + .padding(end = 8.dp)) + Text( + text = text, + modifier = Modifier.weight(1f), + lineHeight = 18.sp, + fontSize = 16.sp, + ) + content() + } + } + } + + private val recyclerViewTag = randomTag() + private val messaging by lazy { context.feature(Messaging::class)} + + override fun onViewAdded(event: AddViewEvent) { + fun hasAvatarHeader(viewGroup: ViewGroup): Boolean { + val constraintLayout = viewGroup.getChildAt(0)?.takeIf { it.javaClass.name.endsWith("ConstraintLayout") } as? ViewGroup ?: return false + return constraintLayout.children().firstOrNull { it.javaClass.name.endsWith("AvatarView") } != null + } + + if (event.parent is FrameLayout && messaging.lastFocusedConversationType == 1 && event.view.javaClass.name.endsWith("RecyclerView")) { + event.view.addOnLayoutChangeListener { _, _, _, _, _, _, _, _, _ -> + if (event.view.tag == recyclerViewTag || !hasAvatarHeader(event.view as ViewGroup)) return@addOnLayoutChangeListener + event.view.tag = recyclerViewTag + + // remove recycler view + event.parent.removeView(event.view) + + val newLayout = LinearLayout(event.view.context).apply { + orientation = LinearLayout.VERTICAL + gravity = Gravity.BOTTOM + layoutParams = ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT) + addView(event.view) + } + + newLayout.addView(ScrollView(newLayout.context).apply { + layoutParams = LinearLayout.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.WRAP_CONTENT + ).apply { + weight = 1f; + setMargins(0, 100, 0, 0) + } + + addView(LinearLayout(context).apply { + orientation = LinearLayout.VERTICAL + injectIntoActionSheetItems(newLayout) { + it.layoutParams = LinearLayout.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.WRAP_CONTENT + ).apply { + setMargins(0, 5, 0, 5) + } + addView(it) + } + }) + }, 0) + + event.parent.addView(newLayout) + } + } + + if (event.parent is LinearLayout && event.viewClassName.endsWith("SnapCardView") && hasAvatarHeader(event.parent)) { + val actionSheetItemsContainerLayout = (event.view as ViewGroup).getChildAt(0) as? ViewGroup ?: throw IllegalStateException("ActionSheetItemsContainerLayout not found") + injectIntoActionSheetItems(actionSheetItemsContainerLayout) { + actionSheetItemsContainerLayout.addView(it, 0) + } + } + } + + private fun injectIntoActionSheetItems(actionSheetItemsContainer: View, viewConsumer: ((View) -> Unit)) { + val friendFeedMenuOptions by context.config.userInterface.friendFeedMenuButtons + if (friendFeedMenuOptions.isEmpty()) return + + val messaging = context.feature(Messaging::class) + val conversationId = messaging.lastFocusedConversationId ?: return + val targetUser by lazy { context.database.getDMOtherParticipant(conversationId) } + messaging.resetLastFocusedConversation() + + val translation = context.translation.getCategory("friend_menu_option") + + fun closeMenu() { + if (!context.config.userInterface.autoCloseFriendFeedMenu.get()) return + context.mainActivity?.triggerRootCloseTouchEvent() + } + + @Composable + fun ComposeFriendFeedMenu() { + Column( + modifier = Modifier.fillMaxWidth(), + ) { + var elementIndex by remember { mutableIntStateOf(0) } + + if (friendFeedMenuOptions.contains("conversation_info")) { + MenuElement( + remember { elementIndex++ }, + Icons.Outlined.RemoveRedEye, + translation["preview"], + onClick = { + context.coroutineScope.launch { + showConversationPreview(targetUser, conversationId) + } + } + ) + } + + context.features.getRuleFeatures().forEach { ruleFeature -> + if (!friendFeedMenuOptions.contains(ruleFeature.ruleType.key)) return@forEach + + val ruleState = ruleFeature.getRuleState() ?: return@forEach + var state by remember { mutableStateOf(ruleFeature.getState(conversationId)) } + + fun toggle() { + state = !ruleFeature.getState(conversationId) + ruleFeature.setState(conversationId, state) + context.inAppOverlay.showStatusToast( + if (state) Icons.Default.CheckCircleOutline else Icons.Default.NotInterested, + context.translation.format("rules.toasts.${if (state) "enabled" else "disabled"}", "ruleName" to context.translation[ruleFeature.ruleType.translateOptionKey(ruleState.key)]), + durationMs = 1500 + ) + closeMenu() + } + + MenuElement( + remember { elementIndex++ }, + icon = ruleFeature.ruleType.icon, + text = context.translation[ruleFeature.ruleType.translateOptionKey(ruleState.key)], + onClick = { + toggle() + } + ) { + Switch( + checked = state, + onCheckedChange = { + state = it + toggle() + }, + colors = SwitchDefaults.colors( + checkedThumbColor = Color.White, + checkedTrackColor = PurrfectOverlayPalette.glowPrimary.copy(alpha = 0.55f), + checkedBorderColor = Color.Transparent, + uncheckedThumbColor = Color.White.copy(alpha = 0.9f), + uncheckedTrackColor = Color.White.copy(alpha = 0.12f), + uncheckedBorderColor = Color.White.copy(alpha = 0.18f), + ) + ) + } + } + + if (friendFeedMenuOptions.contains("mark_snaps_as_seen")) { + MenuElement( + remember { elementIndex++ }, + Icons.Outlined.EditNote, + translation["mark_snaps_as_seen"], + onClick = { + context.apply { + closeMenu() + feature(AutoMarkAsRead::class).markSnapsAsSeen(conversationId) + } + } + ) + } + + if (targetUser != null && friendFeedMenuOptions.contains("mark_stories_as_seen_locally")) { + val markAsSeenTranslation = remember { context.translation.getCategory("mark_as_seen") } + + MenuElement( + remember { elementIndex++ }, + Icons.Outlined.RemoveRedEye, + translation["mark_stories_as_seen_locally"], + onClick = { + context.apply { + closeMenu() + inAppOverlay.showStatusToast( + Icons.Default.Info, + if (database.setStoriesViewedState(targetUser!!, true)) markAsSeenTranslation["seen_toast"] + else markAsSeenTranslation["already_seen_toast"], + durationMs = 2500 + ) + } + }, + onLongClick = { + actionSheetItemsContainer.post { + context.apply { + closeMenu() + inAppOverlay.showStatusToast( + Icons.Default.Info, + if (database.setStoriesViewedState(targetUser!!, false)) markAsSeenTranslation["unseen_toast"] + else markAsSeenTranslation["already_unseen_toast"], + durationMs = 2500 + ) + } + } + } + ) + } + } + } + + viewConsumer( + createComposeView(actionSheetItemsContainer.context) { + PurrfectOverlayTheme { + CompositionLocalProvider( + LocalTextStyle provides LocalTextStyle.current.merge( + TextStyle( + fontFamily = FontFamily.SansSerif, + fontWeight = FontWeight.Medium + ) + ) + ) { + Column( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 10.dp, vertical = 10.dp) + ) { + ComposeFriendFeedMenu() + } + } + } + }.apply { + layoutParams = ViewGroup.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.WRAP_CONTENT + ) + } + ) + + if (context.config.scripting.integratedUI.get()) { + context.scriptRuntime.eachModule { + val interfaceManager = getBinding(InterfaceManager::class) + ?.takeIf { + it.hasInterface(EnumScriptInterface.FRIEND_FEED_CONTEXT_MENU) + } ?: return@eachModule + + viewConsumer(LinearLayout(actionSheetItemsContainer.context).apply { + layoutParams = ViewGroup.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.WRAP_CONTENT + ) + + orientation = LinearLayout.VERTICAL + addView(createComposeView(actionSheetItemsContainer.context) { + PurrfectOverlayTheme { + val shape = RoundedCornerShape(18.dp) + Surface( + modifier = Modifier + .fillMaxWidth() + .background(Color.White.copy(alpha = 0.06f), shape) + .border( + 1.dp, + Brush.linearGradient( + listOf( + PurrfectOverlayPalette.glowPrimary.copy(alpha = 0.4f), + PurrfectOverlayPalette.glowSecondary.copy(alpha = 0.28f) + ) + ), + shape + ) + .padding(10.dp), + color = Color.Transparent, + shape = shape, + tonalElevation = 0.dp, + shadowElevation = 0.dp + ) { + ScriptInterface(interfaceBuilder = remember { + interfaceManager.buildInterface( + EnumScriptInterface.FRIEND_FEED_CONTEXT_MENU, + mapOf( + "conversationId" to conversationId, + "userId" to targetUser + ) + ) + } ?: return@Surface) + } + } + }) + }) + } + } + } +} diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/ui/menu/impl/NewChatActionMenu.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/ui/menu/impl/NewChatActionMenu.kt similarity index 85% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/ui/menu/impl/NewChatActionMenu.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/ui/menu/impl/NewChatActionMenu.kt index d4a8110d..be3b445f 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/ui/menu/impl/NewChatActionMenu.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/ui/menu/impl/NewChatActionMenu.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.core.ui.menu.impl +package me.eternal.purrfectsnap.core.ui.menu.impl import android.content.Context import android.text.format.Formatter @@ -23,33 +23,32 @@ import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.input.pointer.pointerInput import androidx.compose.ui.platform.ComposeView -import androidx.compose.ui.text.font.Font import androidx.compose.ui.text.font.FontFamily import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp -import me.rhunk.snapenhance.bridge.logger.LoggedChatEdit -import me.rhunk.snapenhance.common.data.ContentType -import me.rhunk.snapenhance.common.ui.createComposeAlertDialog -import me.rhunk.snapenhance.common.ui.createComposeView -import me.rhunk.snapenhance.common.ui.rememberAsyncMutableState -import me.rhunk.snapenhance.common.util.ktx.copyToClipboard -import me.rhunk.snapenhance.common.util.protobuf.ProtoReader -import me.rhunk.snapenhance.common.util.snap.RemoteMediaResolver -import me.rhunk.snapenhance.core.event.events.impl.AddViewEvent -import me.rhunk.snapenhance.core.features.impl.downloader.MediaDownloader -import me.rhunk.snapenhance.core.features.impl.downloader.decoder.MessageDecoder -import me.rhunk.snapenhance.core.features.impl.experiments.ConvertMessageLocally -import me.rhunk.snapenhance.core.features.impl.messaging.Messaging -import me.rhunk.snapenhance.core.features.impl.spying.MessageLogger -import me.rhunk.snapenhance.core.ui.ViewAppearanceHelper -import me.rhunk.snapenhance.core.ui.debugEditText -import me.rhunk.snapenhance.core.ui.iterateParent -import me.rhunk.snapenhance.core.ui.menu.AbstractMenu -import me.rhunk.snapenhance.core.ui.triggerCloseTouchEvent -import me.rhunk.snapenhance.core.util.ktx.isDarkTheme -import me.rhunk.snapenhance.core.util.ktx.setObjectField -import me.rhunk.snapenhance.core.util.ktx.vibrateLongPress +import me.eternal.purrfectsnap.bridge.logger.LoggedChatEdit +import me.eternal.purrfectsnap.common.data.ContentType +import me.eternal.purrfectsnap.common.ui.createComposeAlertDialog +import me.eternal.purrfectsnap.common.ui.createComposeView +import me.eternal.purrfectsnap.common.ui.rememberAsyncMutableState +import me.eternal.purrfectsnap.common.util.ktx.copyToClipboard +import me.eternal.purrfectsnap.common.util.protobuf.ProtoReader +import me.eternal.purrfectsnap.common.util.snap.RemoteMediaResolver +import me.eternal.purrfectsnap.core.event.events.impl.AddViewEvent +import me.eternal.purrfectsnap.core.features.impl.downloader.MediaDownloader +import me.eternal.purrfectsnap.core.features.impl.downloader.decoder.MessageDecoder +import me.eternal.purrfectsnap.core.features.impl.experiments.ConvertMessageLocally +import me.eternal.purrfectsnap.core.features.impl.messaging.Messaging +import me.eternal.purrfectsnap.core.features.impl.spying.MessageLogger +import me.eternal.purrfectsnap.core.ui.ViewAppearanceHelper +import me.eternal.purrfectsnap.core.ui.debugEditText +import me.eternal.purrfectsnap.core.ui.iterateParent +import me.eternal.purrfectsnap.core.ui.menu.AbstractMenu +import me.eternal.purrfectsnap.core.ui.triggerCloseTouchEvent +import me.eternal.purrfectsnap.core.util.ktx.isDarkTheme +import me.eternal.purrfectsnap.core.util.ktx.setObjectField +import me.eternal.purrfectsnap.core.util.ktx.vibrateLongPress import java.text.DateFormat import java.text.SimpleDateFormat import java.util.Date @@ -142,7 +141,7 @@ class NewChatActionMenu : AbstractMenu() { }.toString() ) }) { - Text("Info") + Text(this@NewChatActionMenu.context.translation["debug_dialogs.info"]) } Button(onClick = { val arroyoMessage = lastFocusedMessage ?: return@Button @@ -150,7 +149,7 @@ class NewChatActionMenu : AbstractMenu() { val decodedAttachments = MessageDecoder.decode(message.messageContent!!) debugAlertDialog( context, - "Media References", + this@NewChatActionMenu.context.translation["debug_dialogs.media_references"], decodedAttachments.mapIndexed { index, attachment -> StringBuilder().apply { append("---- media $index ----\n") @@ -184,31 +183,31 @@ class NewChatActionMenu : AbstractMenu() { ) }) }) { - Text("Refs") + Text(this@NewChatActionMenu.context.translation["debug_dialogs.refs"]) } Button(onClick = { val message = lastFocusedMessage ?: return@Button debugAlertDialog( context, - "Arroyo proto", + this@NewChatActionMenu.context.translation["debug_dialogs.arroyo_proto"], message.messageContent?.let { ProtoReader(it) }?.toString() ?: "empty" ) }) { - Text("Arroyo") + Text(this@NewChatActionMenu.context.translation["debug_dialogs.arroyo"]) } Button(onClick = { val arroyoMessage = lastFocusedMessage ?: return@Button messaging.conversationManager?.fetchMessage(arroyoMessage.clientConversationId!!, arroyoMessage.clientMessageId.toLong(), onSuccess = { message -> - debugAlertDialog( - context, - "Message proto", + debugAlertDialog( + context, + this@NewChatActionMenu.context.translation["debug_dialogs.message_proto"], message.messageContent?.content?.let { ProtoReader(it) }?.toString() ?: "empty" ) }, onError = { - this@NewChatActionMenu.context.shortToast("Failed to fetch message: $it") + this@NewChatActionMenu.context.shortToast(this@NewChatActionMenu.context.translation["error_messages.failed_to_fetch_message"].replace("{error}", it.toString())) }) }) { - Text("Message") + Text(this@NewChatActionMenu.context.translation["debug_dialogs.message"]) } } } @@ -229,9 +228,7 @@ class NewChatActionMenu : AbstractMenu() { val composeView = createComposeView(event.view.context) { val primaryColor = remember { if (event.view.context.isDarkTheme()) Color.White else Color.Black } val avenirNextMediumFont = remember { - FontFamily( - Font(context.userInterface.avenirNextFontId, FontWeight.Medium) - ) + FontFamily.SansSerif } @Composable @@ -320,12 +317,12 @@ class NewChatActionMenu : AbstractMenu() { .convertMessageInterface(it) }.onFailure { context.log.verbose("Failed to convert message: $it") - context.shortToast("Failed to edit message: $it") + context.shortToast(context.translation["error_messages.failed_to_edit_message"].replace("{error}", it.toString())) } } }, onError = { - context.shortToast("Failed to fetch message: $it") + context.shortToast(context.translation["error_messages.failed_to_fetch_message"].replace("{error}", it.toString())) } ) }) @@ -359,4 +356,4 @@ class NewChatActionMenu : AbstractMenu() { }) } } -} \ No newline at end of file +} diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/ui/menu/impl/OperaContextActionMenu.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/ui/menu/impl/OperaContextActionMenu.kt similarity index 92% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/ui/menu/impl/OperaContextActionMenu.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/ui/menu/impl/OperaContextActionMenu.kt index 5a328f13..98ffcbec 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/ui/menu/impl/OperaContextActionMenu.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/ui/menu/impl/OperaContextActionMenu.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.core.ui.menu.impl +package me.eternal.purrfectsnap.core.ui.menu.impl import android.annotation.SuppressLint import android.view.Gravity @@ -22,16 +22,16 @@ import androidx.compose.ui.graphics.Color import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import androidx.core.content.res.use -import me.rhunk.snapenhance.common.ui.createComposeView -import me.rhunk.snapenhance.core.event.events.impl.AddViewEvent -import me.rhunk.snapenhance.core.features.impl.OperaViewerParamsOverride -import me.rhunk.snapenhance.core.features.impl.downloader.MediaDownloader -import me.rhunk.snapenhance.core.ui.children -import me.rhunk.snapenhance.core.ui.menu.AbstractMenu -import me.rhunk.snapenhance.core.ui.triggerCloseTouchEvent -import me.rhunk.snapenhance.core.util.ktx.getIdentifier -import me.rhunk.snapenhance.core.util.ktx.vibrateLongPress -import me.rhunk.snapenhance.core.wrapper.impl.ScSize +import me.eternal.purrfectsnap.common.ui.createComposeView +import me.eternal.purrfectsnap.core.event.events.impl.AddViewEvent +import me.eternal.purrfectsnap.core.features.impl.OperaViewerParamsOverride +import me.eternal.purrfectsnap.core.features.impl.downloader.MediaDownloader +import me.eternal.purrfectsnap.core.ui.children +import me.eternal.purrfectsnap.core.ui.menu.AbstractMenu +import me.eternal.purrfectsnap.core.ui.triggerCloseTouchEvent +import me.eternal.purrfectsnap.core.util.ktx.getIdentifier +import me.eternal.purrfectsnap.core.util.ktx.vibrateLongPress +import me.eternal.purrfectsnap.core.wrapper.impl.ScSize import java.text.DateFormat import java.util.Date diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/ui/menu/impl/OperaViewerIcons.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/ui/menu/impl/OperaViewerIcons.kt similarity index 92% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/ui/menu/impl/OperaViewerIcons.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/ui/menu/impl/OperaViewerIcons.kt index 360b179d..e1614e10 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/ui/menu/impl/OperaViewerIcons.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/ui/menu/impl/OperaViewerIcons.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.core.ui.menu.impl +package me.eternal.purrfectsnap.core.ui.menu.impl import android.view.Gravity import android.view.View @@ -16,15 +16,15 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.delay import kotlinx.coroutines.launch import kotlinx.coroutines.withContext -import me.rhunk.snapenhance.common.ui.createComposeView -import me.rhunk.snapenhance.core.event.events.impl.AddViewEvent -import me.rhunk.snapenhance.core.features.impl.downloader.MediaDownloader -import me.rhunk.snapenhance.core.features.impl.messaging.AutoMarkAsRead -import me.rhunk.snapenhance.core.ui.children -import me.rhunk.snapenhance.core.ui.iterateParent -import me.rhunk.snapenhance.core.ui.menu.AbstractMenu -import me.rhunk.snapenhance.core.ui.triggerCloseTouchEvent -import me.rhunk.snapenhance.core.util.ktx.vibrateLongPress +import me.eternal.purrfectsnap.common.ui.createComposeView +import me.eternal.purrfectsnap.core.event.events.impl.AddViewEvent +import me.eternal.purrfectsnap.core.features.impl.downloader.MediaDownloader +import me.eternal.purrfectsnap.core.features.impl.messaging.AutoMarkAsRead +import me.eternal.purrfectsnap.core.ui.children +import me.eternal.purrfectsnap.core.ui.iterateParent +import me.eternal.purrfectsnap.core.ui.menu.AbstractMenu +import me.eternal.purrfectsnap.core.ui.triggerCloseTouchEvent +import me.eternal.purrfectsnap.core.util.ktx.vibrateLongPress class OperaViewerIcons : AbstractMenu() { private val actionMenuIconSize by lazy { context.userInterface.dpToPx(32) } diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/ui/menu/impl/SettingsGearInjector.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/ui/menu/impl/SettingsGearInjector.kt similarity index 92% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/ui/menu/impl/SettingsGearInjector.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/ui/menu/impl/SettingsGearInjector.kt index f351fd3a..09240a3c 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/ui/menu/impl/SettingsGearInjector.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/ui/menu/impl/SettingsGearInjector.kt @@ -1,14 +1,14 @@ -package me.rhunk.snapenhance.core.ui.menu.impl +package me.eternal.purrfectsnap.core.ui.menu.impl import android.view.View import android.view.ViewGroup import android.widget.FrameLayout import android.widget.ImageView -import me.rhunk.snapenhance.common.ui.OverlayType -import me.rhunk.snapenhance.core.event.events.impl.AddViewEvent -import me.rhunk.snapenhance.core.ui.menu.AbstractMenu -import me.rhunk.snapenhance.core.util.ktx.getDrawable -import me.rhunk.snapenhance.core.util.ktx.getStyledAttributes +import me.eternal.purrfectsnap.common.ui.OverlayType +import me.eternal.purrfectsnap.core.event.events.impl.AddViewEvent +import me.eternal.purrfectsnap.core.ui.menu.AbstractMenu +import me.eternal.purrfectsnap.core.util.ktx.getDrawable +import me.eternal.purrfectsnap.core.util.ktx.getStyledAttributes class SettingsGearInjector : AbstractMenu() { private val hovaHeaderAddFriendIconId by lazy { diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/ui/menu/impl/SettingsMenu.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/ui/menu/impl/SettingsMenu.kt similarity index 72% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/ui/menu/impl/SettingsMenu.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/ui/menu/impl/SettingsMenu.kt index 869d379f..f9052bf0 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/ui/menu/impl/SettingsMenu.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/ui/menu/impl/SettingsMenu.kt @@ -1,12 +1,12 @@ -package me.rhunk.snapenhance.core.ui.menu.impl +package me.eternal.purrfectsnap.core.ui.menu.impl import android.view.View import android.widget.FrameLayout -import me.rhunk.snapenhance.common.ui.OverlayType -import me.rhunk.snapenhance.core.ui.menu.AbstractMenu -import me.rhunk.snapenhance.core.util.hook.HookStage -import me.rhunk.snapenhance.core.util.hook.hook -import me.rhunk.snapenhance.core.util.ktx.getId +import me.eternal.purrfectsnap.common.ui.OverlayType +import me.eternal.purrfectsnap.core.ui.menu.AbstractMenu +import me.eternal.purrfectsnap.core.util.hook.HookStage +import me.eternal.purrfectsnap.core.util.hook.hook +import me.eternal.purrfectsnap.core.util.ktx.getId class SettingsMenu : AbstractMenu() { private val hovaHeaderSearchIconId by lazy { @@ -26,4 +26,4 @@ class SettingsMenu : AbstractMenu() { } } } -} \ No newline at end of file +} diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/util/CallbackBuilder.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/util/CallbackBuilder.kt similarity index 94% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/util/CallbackBuilder.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/util/CallbackBuilder.kt index e8e2920a..08aed558 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/util/CallbackBuilder.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/util/CallbackBuilder.kt @@ -1,9 +1,9 @@ -package me.rhunk.snapenhance.core.util +package me.eternal.purrfectsnap.core.util import de.robv.android.xposed.XC_MethodHook -import me.rhunk.snapenhance.core.util.hook.HookAdapter -import me.rhunk.snapenhance.core.util.hook.HookStage -import me.rhunk.snapenhance.core.util.hook.Hooker +import me.eternal.purrfectsnap.core.util.hook.HookAdapter +import me.eternal.purrfectsnap.core.util.hook.HookStage +import me.eternal.purrfectsnap.core.util.hook.Hooker import java.lang.reflect.Constructor import java.lang.reflect.Field import java.lang.reflect.Modifier diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/util/DataClassBuilder.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/util/DataClassBuilder.kt similarity index 98% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/util/DataClassBuilder.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/util/DataClassBuilder.kt index 6ac8f5c4..1d6b0b7c 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/util/DataClassBuilder.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/util/DataClassBuilder.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.core.util +package me.eternal.purrfectsnap.core.util import java.lang.reflect.Proxy diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/util/EvictingMap.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/util/EvictingMap.kt similarity index 81% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/util/EvictingMap.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/util/EvictingMap.kt index dc7bf533..44dd9b75 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/util/EvictingMap.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/util/EvictingMap.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.core.util +package me.eternal.purrfectsnap.core.util class EvictingMap(private val maxSize: Int) : LinkedHashMap(maxSize, 0.75f, true) { override fun removeEldestEntry(eldest: MutableMap.MutableEntry) = size > maxSize diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/util/LSPatchUpdater.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/util/LSPatchUpdater.kt similarity index 95% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/util/LSPatchUpdater.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/util/LSPatchUpdater.kt index 3fcfe9c5..349f4f9c 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/util/LSPatchUpdater.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/util/LSPatchUpdater.kt @@ -1,7 +1,7 @@ -package me.rhunk.snapenhance.core.util +package me.eternal.purrfectsnap.core.util -import me.rhunk.snapenhance.common.Constants -import me.rhunk.snapenhance.core.ModContext +import me.eternal.purrfectsnap.common.Constants +import me.eternal.purrfectsnap.core.ModContext import java.io.File import java.util.zip.ZipFile @@ -75,4 +75,4 @@ object LSPatchUpdater { context.log.verbose("updated", TAG) context.softRestartApp() } -} \ No newline at end of file +} diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/util/RandomWalking.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/util/RandomWalking.kt similarity index 98% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/util/RandomWalking.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/util/RandomWalking.kt index fa81e396..235728c1 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/util/RandomWalking.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/util/RandomWalking.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.core.util +package me.eternal.purrfectsnap.core.util import kotlin.math.cos import kotlin.math.hypot diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/util/hook/HookAdapter.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/util/hook/HookAdapter.kt similarity index 97% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/util/hook/HookAdapter.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/util/hook/HookAdapter.kt index c29ec52d..03f98fe4 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/util/hook/HookAdapter.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/util/hook/HookAdapter.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.core.util.hook +package me.eternal.purrfectsnap.core.util.hook import de.robv.android.xposed.XC_MethodHook import de.robv.android.xposed.XposedBridge diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/util/hook/HookStage.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/util/hook/HookStage.kt similarity index 50% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/util/hook/HookStage.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/util/hook/HookStage.kt index f991eb01..e006b929 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/util/hook/HookStage.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/util/hook/HookStage.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.core.util.hook +package me.eternal.purrfectsnap.core.util.hook enum class HookStage { BEFORE, diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/util/hook/Hooker.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/util/hook/Hooker.kt similarity index 98% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/util/hook/Hooker.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/util/hook/Hooker.kt index 99d7297b..578e94b0 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/util/hook/Hooker.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/util/hook/Hooker.kt @@ -1,8 +1,8 @@ -package me.rhunk.snapenhance.core.util.hook +package me.eternal.purrfectsnap.core.util.hook import de.robv.android.xposed.XC_MethodHook import de.robv.android.xposed.XposedBridge -import me.rhunk.snapenhance.common.logger.AbstractLogger +import me.eternal.purrfectsnap.common.logger.AbstractLogger import org.lsposed.hiddenapibypass.HiddenApiBypass import java.lang.reflect.Constructor import java.lang.reflect.Member diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/util/ktx/AndroidExt.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/util/ktx/AndroidExt.kt similarity index 92% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/util/ktx/AndroidExt.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/util/ktx/AndroidExt.kt index 49635d0b..123a72dd 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/util/ktx/AndroidExt.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/util/ktx/AndroidExt.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.core.util.ktx +package me.eternal.purrfectsnap.core.util.ktx import android.annotation.SuppressLint import android.content.Context @@ -9,8 +9,8 @@ import android.graphics.drawable.Drawable import android.os.VibrationEffect import android.os.Vibrator import androidx.core.graphics.ColorUtils -import me.rhunk.snapenhance.common.Constants -import me.rhunk.snapenhance.common.logger.AbstractLogger +import me.eternal.purrfectsnap.common.Constants +import me.eternal.purrfectsnap.common.logger.AbstractLogger val notFoundCache = mutableSetOf() diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/util/ktx/FileHandleManagerKtx.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/util/ktx/FileHandleManagerKtx.kt similarity index 76% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/util/ktx/FileHandleManagerKtx.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/util/ktx/FileHandleManagerKtx.kt index 9a4ab437..794434b1 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/util/ktx/FileHandleManagerKtx.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/util/ktx/FileHandleManagerKtx.kt @@ -1,11 +1,11 @@ -package me.rhunk.snapenhance.core.util.ktx +package me.eternal.purrfectsnap.core.util.ktx import android.os.Build import android.os.ParcelFileDescriptor -import me.rhunk.snapenhance.bridge.storage.FileHandleManager -import me.rhunk.snapenhance.common.bridge.FileHandleScope -import me.rhunk.snapenhance.common.util.ktx.longHashCode -import me.rhunk.snapenhance.core.ModContext +import me.eternal.purrfectsnap.bridge.storage.FileHandleManager +import me.eternal.purrfectsnap.common.bridge.FileHandleScope +import me.eternal.purrfectsnap.common.util.ktx.longHashCode +import me.eternal.purrfectsnap.core.ModContext import java.io.FileOutputStream import kotlin.math.absoluteValue diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/util/ktx/XposedHelperExt.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/util/ktx/XposedHelperExt.kt similarity index 93% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/util/ktx/XposedHelperExt.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/util/ktx/XposedHelperExt.kt index 45adb1b0..60323b60 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/util/ktx/XposedHelperExt.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/util/ktx/XposedHelperExt.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.core.util.ktx +package me.eternal.purrfectsnap.core.util.ktx import de.robv.android.xposed.XposedHelpers diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/util/media/HttpServer.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/util/media/HttpServer.kt similarity index 98% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/util/media/HttpServer.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/util/media/HttpServer.kt index 080bae89..c42a3c6f 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/util/media/HttpServer.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/util/media/HttpServer.kt @@ -1,7 +1,7 @@ -package me.rhunk.snapenhance.core.util.media +package me.eternal.purrfectsnap.core.util.media import kotlinx.coroutines.* -import me.rhunk.snapenhance.common.logger.AbstractLogger +import me.eternal.purrfectsnap.common.logger.AbstractLogger import java.io.BufferedReader import java.io.InputStream import java.io.InputStreamReader diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/util/media/PreviewUtils.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/util/media/PreviewUtils.kt similarity index 97% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/util/media/PreviewUtils.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/util/media/PreviewUtils.kt index d693e32c..b4856945 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/util/media/PreviewUtils.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/util/media/PreviewUtils.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.core.util.media +package me.eternal.purrfectsnap.core.util.media import android.graphics.Bitmap import android.graphics.BitmapFactory @@ -6,7 +6,7 @@ import android.graphics.Canvas import android.graphics.Matrix import android.media.MediaDataSource import android.media.MediaMetadataRetriever -import me.rhunk.snapenhance.common.data.FileType +import me.eternal.purrfectsnap.common.data.FileType import java.io.File import kotlin.math.max diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/wrapper/AbstractWrapper.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/wrapper/AbstractWrapper.kt similarity index 94% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/wrapper/AbstractWrapper.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/wrapper/AbstractWrapper.kt index c8bbd890..b9c7ddbf 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/wrapper/AbstractWrapper.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/wrapper/AbstractWrapper.kt @@ -1,8 +1,8 @@ -package me.rhunk.snapenhance.core.wrapper +package me.eternal.purrfectsnap.core.wrapper import de.robv.android.xposed.XposedHelpers -import me.rhunk.snapenhance.core.util.CallbackBuilder -import me.rhunk.snapenhance.core.wrapper.impl.SnapUUID +import me.eternal.purrfectsnap.core.util.CallbackBuilder +import me.eternal.purrfectsnap.core.wrapper.impl.SnapUUID import kotlin.reflect.KProperty abstract class AbstractWrapper( diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/wrapper/impl/ConversationManager.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/wrapper/impl/ConversationManager.kt similarity index 95% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/wrapper/impl/ConversationManager.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/wrapper/impl/ConversationManager.kt index 51f10ff3..fa700b2c 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/wrapper/impl/ConversationManager.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/wrapper/impl/ConversationManager.kt @@ -1,13 +1,13 @@ -package me.rhunk.snapenhance.core.wrapper.impl +package me.eternal.purrfectsnap.core.wrapper.impl -import me.rhunk.snapenhance.common.data.MessageUpdate -import me.rhunk.snapenhance.core.ModContext -import me.rhunk.snapenhance.core.util.CallbackBuilder -import me.rhunk.snapenhance.core.util.dataBuilder -import me.rhunk.snapenhance.core.util.ktx.getObjectField -import me.rhunk.snapenhance.core.util.ktx.setObjectField -import me.rhunk.snapenhance.core.wrapper.AbstractWrapper -import me.rhunk.snapenhance.mapper.impl.CallbackMapper +import me.eternal.purrfectsnap.common.data.MessageUpdate +import me.eternal.purrfectsnap.core.ModContext +import me.eternal.purrfectsnap.core.util.CallbackBuilder +import me.eternal.purrfectsnap.core.util.dataBuilder +import me.eternal.purrfectsnap.core.util.ktx.getObjectField +import me.eternal.purrfectsnap.core.util.ktx.setObjectField +import me.eternal.purrfectsnap.core.wrapper.AbstractWrapper +import me.eternal.purrfectsnap.mapper.impl.CallbackMapper typealias CallbackResult = (error: String?) -> Unit diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/wrapper/impl/Message.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/wrapper/impl/Message.kt similarity index 57% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/wrapper/impl/Message.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/wrapper/impl/Message.kt index e58404f4..c94abf36 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/wrapper/impl/Message.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/wrapper/impl/Message.kt @@ -1,19 +1,20 @@ -package me.rhunk.snapenhance.core.wrapper.impl +package me.eternal.purrfectsnap.core.wrapper.impl -import me.rhunk.snapenhance.common.data.ContentType -import me.rhunk.snapenhance.common.data.MessageState -import me.rhunk.snapenhance.common.util.protobuf.ProtoReader -import me.rhunk.snapenhance.core.wrapper.AbstractWrapper +import me.eternal.purrfectsnap.common.data.ContentType +import me.eternal.purrfectsnap.common.data.MessageState +import me.eternal.purrfectsnap.common.util.protobuf.ProtoReader +import me.eternal.purrfectsnap.core.wrapper.AbstractWrapper import org.mozilla.javascript.annotations.JSGetter import org.mozilla.javascript.annotations.JSSetter fun ByteArray.getMessageText(contentType: ContentType): String? { val protoReader by lazy { ProtoReader(this) } - return when (contentType) { + val raw = when (contentType) { ContentType.CHAT -> protoReader.getString(2, 1) ?: "Failed to parse message" ContentType.TINY_SNAP -> protoReader.getString(19, 1, 1) ContentType.EXTERNAL_MEDIA -> protoReader.getString(7, 11, 1) + ContentType.STORY_REPLY -> protoReader.getString(7, 11, 1) ContentType.SNAP -> protoReader.followPath(11, 5)?.run { val captions = mutableListOf() @@ -30,6 +31,36 @@ fun ByteArray.getMessageText(contentType: ContentType): String? { } else -> null } + return raw?.sanitizeForLayout() +} + +fun String.sanitizeForLayout(): String { + var changed = false + val builder = StringBuilder(length) + var index = 0 + while (index < length) { + val char = this[index] + if (Character.isHighSurrogate(char)) { + if (index + 1 < length && Character.isLowSurrogate(this[index + 1])) { + builder.append(char).append(this[index + 1]) + index += 2 + continue + } + builder.append('\uFFFD') + changed = true + index++ + continue + } + if (Character.isLowSurrogate(char)) { + builder.append('\uFFFD') + changed = true + index++ + continue + } + builder.append(char) + index++ + } + return if (changed) builder.toString() else this } class Message(obj: Any?) : AbstractWrapper(obj) { @@ -49,4 +80,4 @@ class Message(obj: Any?) : AbstractWrapper(obj) { fun serialize(): String?{ return messageContent?.content?.getMessageText(messageContent?.contentType ?: return null) } -} \ No newline at end of file +} diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/wrapper/impl/MessageContent.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/wrapper/impl/MessageContent.kt similarity index 76% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/wrapper/impl/MessageContent.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/wrapper/impl/MessageContent.kt index d9ceb52f..3cfa5afc 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/wrapper/impl/MessageContent.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/wrapper/impl/MessageContent.kt @@ -1,7 +1,7 @@ -package me.rhunk.snapenhance.core.wrapper.impl +package me.eternal.purrfectsnap.core.wrapper.impl -import me.rhunk.snapenhance.common.data.ContentType -import me.rhunk.snapenhance.core.wrapper.AbstractWrapper +import me.eternal.purrfectsnap.common.data.ContentType +import me.eternal.purrfectsnap.core.wrapper.AbstractWrapper import org.mozilla.javascript.annotations.JSGetter import org.mozilla.javascript.annotations.JSSetter diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/wrapper/impl/MessageDescriptor.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/wrapper/impl/MessageDescriptor.kt similarity index 73% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/wrapper/impl/MessageDescriptor.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/wrapper/impl/MessageDescriptor.kt index d1f04341..69347061 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/wrapper/impl/MessageDescriptor.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/wrapper/impl/MessageDescriptor.kt @@ -1,6 +1,6 @@ -package me.rhunk.snapenhance.core.wrapper.impl +package me.eternal.purrfectsnap.core.wrapper.impl -import me.rhunk.snapenhance.core.wrapper.AbstractWrapper +import me.eternal.purrfectsnap.core.wrapper.AbstractWrapper import org.mozilla.javascript.annotations.JSGetter import org.mozilla.javascript.annotations.JSSetter diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/wrapper/impl/MessageDestinations.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/wrapper/impl/MessageDestinations.kt similarity index 59% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/wrapper/impl/MessageDestinations.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/wrapper/impl/MessageDestinations.kt index b6221f28..ab37c8eb 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/wrapper/impl/MessageDestinations.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/wrapper/impl/MessageDestinations.kt @@ -1,9 +1,10 @@ -package me.rhunk.snapenhance.core.wrapper.impl +package me.eternal.purrfectsnap.core.wrapper.impl -import me.rhunk.snapenhance.core.wrapper.AbstractWrapper +import me.eternal.purrfectsnap.core.wrapper.AbstractWrapper class MessageDestinations(obj: Any) : AbstractWrapper(obj){ var conversations by field("mConversations", uuidArrayListMapper) var stories by field>("mStories") var mPhoneNumbers by field>("mPhoneNumbers") -} \ No newline at end of file + var massSnaps by field>("mMassSnaps") +} diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/wrapper/impl/MessageMetadata.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/wrapper/impl/MessageMetadata.kt similarity index 90% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/wrapper/impl/MessageMetadata.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/wrapper/impl/MessageMetadata.kt index 804f44c7..0c66784a 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/wrapper/impl/MessageMetadata.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/wrapper/impl/MessageMetadata.kt @@ -1,7 +1,7 @@ -package me.rhunk.snapenhance.core.wrapper.impl +package me.eternal.purrfectsnap.core.wrapper.impl -import me.rhunk.snapenhance.common.data.PlayableSnapState -import me.rhunk.snapenhance.core.wrapper.AbstractWrapper +import me.eternal.purrfectsnap.common.data.PlayableSnapState +import me.eternal.purrfectsnap.core.wrapper.AbstractWrapper import org.mozilla.javascript.annotations.JSGetter import org.mozilla.javascript.annotations.JSSetter diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/wrapper/impl/QuotedMessage.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/wrapper/impl/QuotedMessage.kt similarity index 65% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/wrapper/impl/QuotedMessage.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/wrapper/impl/QuotedMessage.kt index 16242e36..0d54b6a4 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/wrapper/impl/QuotedMessage.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/wrapper/impl/QuotedMessage.kt @@ -1,7 +1,7 @@ -package me.rhunk.snapenhance.core.wrapper.impl +package me.eternal.purrfectsnap.core.wrapper.impl -import me.rhunk.snapenhance.common.data.QuotedMessageContentStatus -import me.rhunk.snapenhance.core.wrapper.AbstractWrapper +import me.eternal.purrfectsnap.common.data.QuotedMessageContentStatus +import me.eternal.purrfectsnap.core.wrapper.AbstractWrapper import org.mozilla.javascript.annotations.JSGetter import org.mozilla.javascript.annotations.JSSetter diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/wrapper/impl/QuotedMessageContent.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/wrapper/impl/QuotedMessageContent.kt similarity index 69% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/wrapper/impl/QuotedMessageContent.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/wrapper/impl/QuotedMessageContent.kt index b89ede16..a5f63f53 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/wrapper/impl/QuotedMessageContent.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/wrapper/impl/QuotedMessageContent.kt @@ -1,6 +1,6 @@ -package me.rhunk.snapenhance.core.wrapper.impl +package me.eternal.purrfectsnap.core.wrapper.impl -import me.rhunk.snapenhance.core.wrapper.AbstractWrapper +import me.eternal.purrfectsnap.core.wrapper.AbstractWrapper import org.mozilla.javascript.annotations.JSGetter import org.mozilla.javascript.annotations.JSSetter diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/wrapper/impl/ScSize.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/wrapper/impl/ScSize.kt similarity index 86% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/wrapper/impl/ScSize.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/wrapper/impl/ScSize.kt index 86d45a42..1a73e709 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/wrapper/impl/ScSize.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/wrapper/impl/ScSize.kt @@ -1,6 +1,6 @@ -package me.rhunk.snapenhance.core.wrapper.impl +package me.eternal.purrfectsnap.core.wrapper.impl -import me.rhunk.snapenhance.core.wrapper.AbstractWrapper +import me.eternal.purrfectsnap.core.wrapper.AbstractWrapper class ScSize( obj: Any? diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/wrapper/impl/SnapUUID.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/wrapper/impl/SnapUUID.kt similarity index 66% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/wrapper/impl/SnapUUID.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/wrapper/impl/SnapUUID.kt index a5f32a57..6dff682d 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/wrapper/impl/SnapUUID.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/wrapper/impl/SnapUUID.kt @@ -1,8 +1,8 @@ -package me.rhunk.snapenhance.core.wrapper.impl +package me.eternal.purrfectsnap.core.wrapper.impl -import me.rhunk.snapenhance.core.SnapEnhance -import me.rhunk.snapenhance.core.util.ktx.getObjectField -import me.rhunk.snapenhance.core.wrapper.AbstractWrapper +import me.eternal.purrfectsnap.core.PurrfectSnap +import me.eternal.purrfectsnap.core.util.ktx.getObjectField +import me.eternal.purrfectsnap.core.wrapper.AbstractWrapper import java.nio.ByteBuffer import java.util.UUID @@ -29,9 +29,13 @@ class SnapUUID( obj } obj is UUID -> obj.toBytes() - SnapEnhance.classCache.snapUUID.isInstance(obj) -> { + PurrfectSnap.classCache.snapUUID.isInstance(obj) -> { obj?.getObjectField("mId") as ByteArray } + PurrfectSnap.classCache.snapShimsUUID?.isInstance(obj) == true -> { + val any = obj as Any + any::class.java.methods.firstOrNull { it.name == "getId" }?.invoke(any) as? ByteArray ?: ByteArray(16) + } else -> ByteArray(16) } } @@ -40,7 +44,7 @@ class SnapUUID( override var instance: Any? set(_) {} - get() = SnapEnhance.classCache.snapUUID.getConstructor(ByteArray::class.java).newInstance(uuidBytes) + get() = PurrfectSnap.classCache.snapUUID.getConstructor(ByteArray::class.java).newInstance(uuidBytes) override fun toString(): String { return uuidString diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/wrapper/impl/Snapchatter.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/wrapper/impl/Snapchatter.kt similarity index 88% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/wrapper/impl/Snapchatter.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/wrapper/impl/Snapchatter.kt index 38619c59..20499668 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/wrapper/impl/Snapchatter.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/wrapper/impl/Snapchatter.kt @@ -1,6 +1,6 @@ -package me.rhunk.snapenhance.core.wrapper.impl +package me.eternal.purrfectsnap.core.wrapper.impl -import me.rhunk.snapenhance.core.wrapper.AbstractWrapper +import me.eternal.purrfectsnap.core.wrapper.AbstractWrapper import org.mozilla.javascript.annotations.JSGetter import org.mozilla.javascript.annotations.JSSetter diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/wrapper/impl/UserIdToReaction.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/wrapper/impl/UserIdToReaction.kt similarity index 73% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/wrapper/impl/UserIdToReaction.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/wrapper/impl/UserIdToReaction.kt index 1bf67f51..84979657 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/wrapper/impl/UserIdToReaction.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/wrapper/impl/UserIdToReaction.kt @@ -1,8 +1,8 @@ -package me.rhunk.snapenhance.core.wrapper.impl +package me.eternal.purrfectsnap.core.wrapper.impl -import me.rhunk.snapenhance.core.util.ktx.getObjectField -import me.rhunk.snapenhance.core.util.ktx.setObjectField -import me.rhunk.snapenhance.core.wrapper.AbstractWrapper +import me.eternal.purrfectsnap.core.util.ktx.getObjectField +import me.eternal.purrfectsnap.core.util.ktx.setObjectField +import me.eternal.purrfectsnap.core.wrapper.AbstractWrapper import org.mozilla.javascript.annotations.JSGetter import org.mozilla.javascript.annotations.JSSetter diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/wrapper/impl/composer/ComposerContext.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/wrapper/impl/composer/ComposerContext.kt similarity index 56% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/wrapper/impl/composer/ComposerContext.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/wrapper/impl/composer/ComposerContext.kt index 0396e8ed..c02d131e 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/wrapper/impl/composer/ComposerContext.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/wrapper/impl/composer/ComposerContext.kt @@ -1,15 +1,20 @@ -package me.rhunk.snapenhance.core.wrapper.impl.composer +package me.eternal.purrfectsnap.core.wrapper.impl.composer -import me.rhunk.snapenhance.core.wrapper.AbstractWrapper +import de.robv.android.xposed.XposedHelpers +import me.eternal.purrfectsnap.core.wrapper.AbstractWrapper import java.lang.ref.WeakReference import java.lang.reflect.Proxy class ComposerContext(obj: Any): AbstractWrapper(obj) { val componentPath by field("componentPath") - val viewModel by field("innerViewModel") val moduleName by field("moduleName") val componentContext by field>("componentContext") + val viewModel: Any? + get() = runCatching { XposedHelpers.getObjectField(instanceNonNull(), "innerViewModel") }.getOrNull() + ?: runCatching { XposedHelpers.getObjectField(instanceNonNull(), "viewModel") }.getOrNull() + ?: instanceNonNull()::class.java.methods.firstOrNull { it.name == "getViewModel" && it.parameterTypes.isEmpty() }?.invoke(instanceNonNull()) + fun enqueueNextRenderCallback(callback: () -> Unit) { val method = instanceNonNull()::class.java.methods.firstOrNull { it.name == "onNextLayout" @@ -21,4 +26,4 @@ class ComposerContext(obj: Any): AbstractWrapper(obj) { callback() }) } -} \ No newline at end of file +} diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/wrapper/impl/composer/ComposerMarshaller.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/wrapper/impl/composer/ComposerMarshaller.kt similarity index 84% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/wrapper/impl/composer/ComposerMarshaller.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/wrapper/impl/composer/ComposerMarshaller.kt index 10ecdb8c..29249317 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/wrapper/impl/composer/ComposerMarshaller.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/wrapper/impl/composer/ComposerMarshaller.kt @@ -1,6 +1,6 @@ -package me.rhunk.snapenhance.core.wrapper.impl.composer +package me.eternal.purrfectsnap.core.wrapper.impl.composer -import me.rhunk.snapenhance.core.wrapper.AbstractWrapper +import me.eternal.purrfectsnap.core.wrapper.AbstractWrapper class ComposerMarshaller(obj: Any): AbstractWrapper(obj) { private val getUntypedMethod by lazy { instanceNonNull().javaClass.methods.first { it.name == "getUntyped" } } diff --git a/core/src/main/kotlin/me/eternal/purrfectsnap/core/wrapper/impl/composer/ComposerViewNode.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/wrapper/impl/composer/ComposerViewNode.kt new file mode 100644 index 00000000..e5f336b1 --- /dev/null +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/wrapper/impl/composer/ComposerViewNode.kt @@ -0,0 +1,62 @@ +package me.eternal.purrfectsnap.core.wrapper.impl.composer + +import me.eternal.purrfectsnap.core.PurrfectSnap +import me.eternal.purrfectsnap.core.wrapper.AbstractWrapper +import java.lang.reflect.Proxy + +fun createComposerFunction(block: (args: Array<*>) -> Any?): Any { + val adapter = PurrfectSnap.classCache.composerFunctionActionAdapter + ?: throw IllegalStateException("composerFunctionActionAdapter not available") + val action = PurrfectSnap.classCache.composerAction + ?: throw IllegalStateException("composerAction not available") + + return adapter.constructors.first().newInstance( + Proxy.newProxyInstance( + action.classLoader, + arrayOf(action), + ) { _, _, args -> + block(args?.get(0) as Array<*>) + } + ) +} + +class ComposerViewNode(obj: Long) : AbstractWrapper(obj) { + companion object { + fun fromNode(composerViewNode: Any?): ComposerViewNode? { + return (composerViewNode?.javaClass?.methods?.firstOrNull { + it.name == "getNativeHandle" + }?.invoke(composerViewNode) as? Long)?.let { ComposerViewNode(it) } ?: return null + } + } + + fun getAttribute(name: String): Any? { + return PurrfectSnap.classCache.nativeBridge?.methods?.firstOrNull { + it.name == "getValueForAttribute" + }?.invoke(null, instanceNonNull(), name) + } + + fun setAttribute(name: String, value: Any) { + PurrfectSnap.classCache.nativeBridge?.methods?.firstOrNull { + it.name == "setValueForAttribute" + }?.invoke(null, instanceNonNull(), name, value, false) + } + + fun getChildren(): List { + val children = PurrfectSnap.classCache.nativeBridge?.methods?.firstOrNull { + it.name == "getRetainedViewNodeChildren" + }?.invoke(null, instanceNonNull(), 1) as? LongArray ?: return emptyList() + return children.map { ComposerViewNode(it) } + } + + fun getClassName(): String { + return PurrfectSnap.classCache.nativeBridge?.methods?.firstOrNull { + it.name == "getViewClassName" + }?.invoke(null, instanceNonNull())?.toString() ?: "" + } + + override fun toString(): String { + return PurrfectSnap.classCache.nativeBridge?.methods?.firstOrNull { + it.name == "getViewNodeDebugDescription" + }?.invoke(null, instanceNonNull())?.toString() ?: "" + } +} diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/wrapper/impl/media/EncryptionWrapper.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/wrapper/impl/media/EncryptionWrapper.kt similarity index 92% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/wrapper/impl/media/EncryptionWrapper.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/wrapper/impl/media/EncryptionWrapper.kt index f4e08da7..15a780fd 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/wrapper/impl/media/EncryptionWrapper.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/wrapper/impl/media/EncryptionWrapper.kt @@ -1,7 +1,7 @@ -package me.rhunk.snapenhance.core.wrapper.impl.media +package me.eternal.purrfectsnap.core.wrapper.impl.media -import me.rhunk.snapenhance.common.data.download.MediaEncryptionKeyPair -import me.rhunk.snapenhance.core.wrapper.AbstractWrapper +import me.eternal.purrfectsnap.common.data.download.MediaEncryptionKeyPair +import me.eternal.purrfectsnap.core.wrapper.AbstractWrapper import java.io.InputStream import java.io.OutputStream import java.lang.reflect.Field diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/wrapper/impl/media/MediaInfo.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/wrapper/impl/media/MediaInfo.kt similarity index 84% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/wrapper/impl/media/MediaInfo.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/wrapper/impl/media/MediaInfo.kt index 70ae2955..5f30021a 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/wrapper/impl/media/MediaInfo.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/wrapper/impl/media/MediaInfo.kt @@ -1,8 +1,8 @@ -package me.rhunk.snapenhance.core.wrapper.impl.media +package me.eternal.purrfectsnap.core.wrapper.impl.media import android.os.Parcelable -import me.rhunk.snapenhance.core.util.ktx.getObjectField -import me.rhunk.snapenhance.core.wrapper.AbstractWrapper +import me.eternal.purrfectsnap.core.util.ktx.getObjectField +import me.eternal.purrfectsnap.core.wrapper.AbstractWrapper import java.lang.reflect.Field diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/wrapper/impl/media/dash/LongformVideoPlaylistItem.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/wrapper/impl/media/dash/LongformVideoPlaylistItem.kt similarity index 73% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/wrapper/impl/media/dash/LongformVideoPlaylistItem.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/wrapper/impl/media/dash/LongformVideoPlaylistItem.kt index 1456c935..ba54018a 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/wrapper/impl/media/dash/LongformVideoPlaylistItem.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/wrapper/impl/media/dash/LongformVideoPlaylistItem.kt @@ -1,6 +1,6 @@ -package me.rhunk.snapenhance.core.wrapper.impl.media.dash +package me.eternal.purrfectsnap.core.wrapper.impl.media.dash -import me.rhunk.snapenhance.core.wrapper.AbstractWrapper +import me.eternal.purrfectsnap.core.wrapper.AbstractWrapper class LongformVideoPlaylistItem(obj: Any?) : AbstractWrapper(obj) { private val chapterList by lazy { diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/wrapper/impl/media/dash/SnapChapter.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/wrapper/impl/media/dash/SnapChapter.kt similarity index 76% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/wrapper/impl/media/dash/SnapChapter.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/wrapper/impl/media/dash/SnapChapter.kt index acef3238..75405d3f 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/wrapper/impl/media/dash/SnapChapter.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/wrapper/impl/media/dash/SnapChapter.kt @@ -1,6 +1,6 @@ -package me.rhunk.snapenhance.core.wrapper.impl.media.dash +package me.eternal.purrfectsnap.core.wrapper.impl.media.dash -import me.rhunk.snapenhance.core.wrapper.AbstractWrapper +import me.eternal.purrfectsnap.core.wrapper.AbstractWrapper class SnapChapter (obj: Any?) : AbstractWrapper(obj) { val snapId by lazy { diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/wrapper/impl/media/dash/SnapPlaylistItem.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/wrapper/impl/media/dash/SnapPlaylistItem.kt similarity index 65% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/wrapper/impl/media/dash/SnapPlaylistItem.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/wrapper/impl/media/dash/SnapPlaylistItem.kt index 5fa736a0..792bd326 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/wrapper/impl/media/dash/SnapPlaylistItem.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/wrapper/impl/media/dash/SnapPlaylistItem.kt @@ -1,6 +1,6 @@ -package me.rhunk.snapenhance.core.wrapper.impl.media.dash +package me.eternal.purrfectsnap.core.wrapper.impl.media.dash -import me.rhunk.snapenhance.core.wrapper.AbstractWrapper +import me.eternal.purrfectsnap.core.wrapper.AbstractWrapper class SnapPlaylistItem (obj: Any?) : AbstractWrapper(obj) { val snapId by lazy { diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/wrapper/impl/media/opera/Layer.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/wrapper/impl/media/opera/Layer.kt similarity index 79% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/wrapper/impl/media/opera/Layer.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/wrapper/impl/media/opera/Layer.kt index 66585297..5b4d3280 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/wrapper/impl/media/opera/Layer.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/wrapper/impl/media/opera/Layer.kt @@ -1,7 +1,7 @@ -package me.rhunk.snapenhance.core.wrapper.impl.media.opera +package me.eternal.purrfectsnap.core.wrapper.impl.media.opera -import me.rhunk.snapenhance.common.util.ktx.findFieldsToString -import me.rhunk.snapenhance.core.wrapper.AbstractWrapper +import me.eternal.purrfectsnap.common.util.ktx.findFieldsToString +import me.eternal.purrfectsnap.core.wrapper.AbstractWrapper class Layer(obj: Any?) : AbstractWrapper(obj) { val paramMap: ParamMap diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/wrapper/impl/media/opera/ParamMap.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/wrapper/impl/media/opera/ParamMap.kt similarity index 83% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/wrapper/impl/media/opera/ParamMap.kt rename to core/src/main/kotlin/me/eternal/purrfectsnap/core/wrapper/impl/media/opera/ParamMap.kt index a3a75910..630e3dda 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/wrapper/impl/media/opera/ParamMap.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/wrapper/impl/media/opera/ParamMap.kt @@ -1,8 +1,8 @@ -package me.rhunk.snapenhance.core.wrapper.impl.media.opera +package me.eternal.purrfectsnap.core.wrapper.impl.media.opera -import me.rhunk.snapenhance.common.util.ktx.findFields -import me.rhunk.snapenhance.core.util.ktx.getObjectField -import me.rhunk.snapenhance.core.wrapper.AbstractWrapper +import me.eternal.purrfectsnap.common.util.ktx.findFields +import me.eternal.purrfectsnap.core.util.ktx.getObjectField +import me.eternal.purrfectsnap.core.wrapper.AbstractWrapper import java.lang.reflect.Field import java.util.concurrent.ConcurrentHashMap diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/action/impl/BulkMessagingAction.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/action/impl/BulkMessagingAction.kt deleted file mode 100644 index 3b98384a..00000000 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/action/impl/BulkMessagingAction.kt +++ /dev/null @@ -1,650 +0,0 @@ -package me.rhunk.snapenhance.core.action.impl - -import android.content.Context -import android.graphics.Bitmap -import android.graphics.BitmapFactory -import android.view.Gravity -import android.view.View -import android.widget.LinearLayout -import android.widget.ProgressBar -import android.widget.TextView -import androidx.compose.foundation.ExperimentalFoundationApi -import androidx.compose.foundation.Image -import androidx.compose.foundation.background -import androidx.compose.foundation.clickable -import androidx.compose.foundation.gestures.detectTapGestures -import androidx.compose.foundation.layout.* -import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.items -import androidx.compose.material3.* -import androidx.compose.runtime.* -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.graphics.asImageBitmap -import androidx.compose.ui.input.pointer.pointerInput -import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.platform.LocalFocusManager -import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.text.style.TextAlign -import androidx.compose.ui.text.style.TextOverflow -import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.delay -import kotlinx.coroutines.launch -import kotlinx.coroutines.withContext -import me.rhunk.snapenhance.common.data.ContentType -import me.rhunk.snapenhance.common.data.FriendLinkType -import me.rhunk.snapenhance.common.database.impl.ConversationMessage -import me.rhunk.snapenhance.common.database.impl.FriendInfo -import me.rhunk.snapenhance.common.messaging.MessagingConstraints -import me.rhunk.snapenhance.common.messaging.MessagingTask -import me.rhunk.snapenhance.common.messaging.MessagingTaskType -import me.rhunk.snapenhance.common.ui.createComposeAlertDialog -import me.rhunk.snapenhance.common.ui.rememberAsyncMutableState -import me.rhunk.snapenhance.common.util.ktx.copyToClipboard -import me.rhunk.snapenhance.common.util.snap.BitmojiSelfie -import me.rhunk.snapenhance.common.util.snap.RemoteMediaResolver -import me.rhunk.snapenhance.core.action.AbstractAction -import me.rhunk.snapenhance.core.features.impl.experiments.AddFriendSourceSpoof -import me.rhunk.snapenhance.core.features.impl.experiments.BetterLocation -import me.rhunk.snapenhance.core.features.impl.messaging.Messaging -import me.rhunk.snapenhance.core.ui.ViewAppearanceHelper -import me.rhunk.snapenhance.core.util.EvictingMap -import me.rhunk.snapenhance.core.util.dataBuilder -import me.rhunk.snapenhance.mapper.impl.FriendRelationshipChangerMapper -import java.text.DateFormat -import java.util.Date -import kotlin.random.Random - -class BulkMessagingAction : AbstractAction() { - enum class SortBy { - NONE, - USERNAME, - ADDED_TIMESTAMP, - SNAP_SCORE, - STREAK_LENGTH, - MOST_MESSAGES_SENT, - MOST_RECENT_MESSAGE, - NEAREST_LOCATION - } - enum class Filter { - ALL, - MY_FRIENDS, - BLOCKED, - REMOVED_ME, - DELETED, - SUGGESTED, - BUSINESS_ACCOUNTS, - STREAKS, - NON_STREAKS, - LOCATION_ON_MAP - } - private val translation by lazy { context.translation.getCategory("bulk_messaging_action") } - private val betterLocation by lazy { context.feature(BetterLocation::class) } - private fun removeAction( - ctx: Context, - ids: List, - delay: Pair, - action: suspend (id: String, setDialogMessage: (String) -> Unit) -> Unit = { _, _ -> } - ) = context.coroutineScope.launch { - val statusTextView = TextView(ctx) - val dialog = withContext(Dispatchers.Main) { - ViewAppearanceHelper.newAlertDialogBuilder(ctx) - .setTitle("...") - .setView(LinearLayout(ctx).apply { - orientation = LinearLayout.VERTICAL - gravity = Gravity.CENTER - addView(statusTextView.apply { - layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT) - textAlignment = View.TEXT_ALIGNMENT_CENTER - }) - addView(ProgressBar(ctx)) - }) - .setCancelable(false) - .show() - } - ids.forEachIndexed { index, id -> - launch(Dispatchers.Main) { - dialog.setTitle( - translation.format("progress_status", "index" to (index + 1).toString(), "total" to ids.size.toString()) - ) - } - runCatching { - action(id) { - launch(Dispatchers.Main) { - statusTextView.text = it - } - } - }.onFailure { - context.log.error("Failed to process $it", it) - context.shortToast("Failed to process $id") - } - delay(Random.nextLong(delay.first, delay.second)) - } - withContext(Dispatchers.Main) { - dialog.dismiss() - } - } - @Composable - private fun ConfirmationDialog( - onConfirm: () -> Unit, - onCancel: () -> Unit, - ) { - AlertDialog( - onDismissRequest = onCancel, - title = { Text(text = translation["confirmation_dialog.title"]) }, - text = { Text(text = translation["confirmation_dialog.message"]) }, - confirmButton = { - TextButton(onClick = onConfirm) { - Text(text = context.translation["button.positive"]) - } - }, - dismissButton = { - TextButton(onClick = onCancel) { - Text(text = context.translation["button.negative"]) - } - } - ) - } - private fun filterFriends(friends: List, filter: Filter, nameFilter: String): List { - val userIdBlacklist = arrayOf( - context.database.myUserId, - "b42f1f70-5a8b-4c53-8c25-34e7ec9e6781", // myai - "84ee8839-3911-492d-8b94-72dd80f3713a", // teamsnapchat - ) - return friends.filter { friend -> - // FIX: add safe call, as userIdBlacklist could be nullable - friend.userId !in userIdBlacklist && when (filter) { - Filter.ALL -> true - Filter.MY_FRIENDS -> friend.friendLinkType == FriendLinkType.MUTUAL.value && friend.addedTimestamp > 0 - Filter.BLOCKED -> friend.friendLinkType == FriendLinkType.BLOCKED.value - Filter.REMOVED_ME -> friend.friendLinkType == FriendLinkType.OUTGOING.value && friend.addedTimestamp > 0 && friend.businessCategory == 0 - Filter.SUGGESTED -> friend.friendLinkType == FriendLinkType.SUGGESTED.value - Filter.DELETED -> friend.friendLinkType == FriendLinkType.DELETED.value - Filter.BUSINESS_ACCOUNTS -> friend.businessCategory > 0 - Filter.STREAKS -> friend.friendLinkType == FriendLinkType.MUTUAL.value && friend.addedTimestamp > 0 && friend.streakLength != 0 - Filter.NON_STREAKS -> friend.friendLinkType == FriendLinkType.MUTUAL.value && friend.addedTimestamp > 0 && friend.streakLength == 0 - Filter.LOCATION_ON_MAP -> betterLocation.locationHistory.contains(friend.userId) - } && nameFilter.takeIf { it.isNotBlank() }?.let { name -> - friend.mutableUsername?.contains( - name, - ignoreCase = true - ) == true || friend.displayName?.contains(name, ignoreCase = true) == true - } ?: true - } - } - private fun getDMLastMessage(userId: String?): ConversationMessage? { - return context.database.getDMConversationId(userId ?: return null)?.let { - context.database.getMessagesFromConversationId(it, 1) - }?.firstOrNull() - } - @OptIn(ExperimentalMaterial3Api::class, ExperimentalFoundationApi::class) - @Composable - private fun BulkMessagingDialog() { - val coroutineScope = rememberCoroutineScope { Dispatchers.IO } - var sortBy by remember { mutableStateOf(SortBy.USERNAME) } - var filter by remember { mutableStateOf(Filter.REMOVED_ME) } - var sortReverseOrder by remember { mutableStateOf(false) } - val selectedFriends = remember { mutableStateListOf() } - val friends = remember { mutableStateListOf() } - val bitmojiCache = remember { EvictingMap(50) } - val noBitmojiBitmap = remember { BitmapFactory.decodeResource(context.resources, android.R.drawable.ic_menu_report_image).asImageBitmap() } - val focusManager = LocalFocusManager.current - var nameFilter by remember { mutableStateOf("") } - suspend fun refreshList(clearSelected: Boolean = true) { - val myLocation = betterLocation.locationHistory[context.database.myUserId] - withContext(Dispatchers.IO) { - val newFriends = context.database.getAllFriends().let { friends -> - filterFriends(friends, filter, nameFilter) - }.toMutableList() - when (sortBy) { - SortBy.NONE -> {} - SortBy.USERNAME -> newFriends.sortBy { it.mutableUsername } - SortBy.ADDED_TIMESTAMP -> newFriends.sortBy { it.addedTimestamp } - SortBy.SNAP_SCORE -> newFriends.sortBy { it.snapScore } - SortBy.STREAK_LENGTH -> newFriends.sortBy { it.streakLength } - SortBy.MOST_MESSAGES_SENT -> newFriends.sortByDescending { - getDMLastMessage(it.userId)?.serverMessageId ?: 0 - } - SortBy.MOST_RECENT_MESSAGE -> newFriends.sortByDescending { - getDMLastMessage(it.userId)?.creationTimestamp - } - SortBy.NEAREST_LOCATION -> { - if (myLocation != null) { - newFriends.sortBy { - betterLocation.locationHistory[it.userId]?.distanceTo(myLocation) - ?: Double.MAX_VALUE - } - } - } - } - if (sortReverseOrder) newFriends.reverse() - withContext(Dispatchers.Main) { - if (clearSelected) selectedFriends.clear() - friends.clear() - friends.addAll(newFriends) - } - } - } - Column( - modifier = Modifier - .fillMaxWidth() - .padding(10.dp), - verticalArrangement = Arrangement.spacedBy(10.dp) - ) { - Row( - modifier = Modifier.fillMaxWidth(), - horizontalArrangement = Arrangement.SpaceEvenly, - verticalAlignment = Alignment.CenterVertically - ) { - var filterMenuExpanded by remember { mutableStateOf(false) } - ExposedDropdownMenuBox( - expanded = filterMenuExpanded, - onExpandedChange = { filterMenuExpanded = it }, - ) { - ElevatedCard( - modifier = Modifier.menuAnchor(MenuAnchorType.PrimaryNotEditable) - ) { - Text(text = filter.name, modifier = Modifier.padding(5.dp)) - } - DropdownMenu( - expanded = filterMenuExpanded, - onDismissRequest = { filterMenuExpanded = false } - ) { - Filter.entries.forEach { entry -> - DropdownMenuItem(onClick = { - filter = entry - filterMenuExpanded = false - }, text = { - Text(text = entry.name, fontWeight = if (entry == filter) FontWeight.Bold else FontWeight.Normal) - }) - } - } - } - var sortMenuExpanded by remember { mutableStateOf(false) } - ExposedDropdownMenuBox( - expanded = sortMenuExpanded, - onExpandedChange = { sortMenuExpanded = it }, - ) { - ElevatedCard( - modifier = Modifier.menuAnchor(MenuAnchorType.PrimaryNotEditable) - ) { - Text(text = "Sort by", modifier = Modifier.padding(5.dp)) - } - DropdownMenu( - expanded = sortMenuExpanded, - onDismissRequest = { sortMenuExpanded = false } - ) { - SortBy.entries.forEach { entry -> - DropdownMenuItem(onClick = { - sortBy = entry - sortMenuExpanded = false - }, text = { - Text(text = entry.name, fontWeight = if (entry == sortBy) FontWeight.Bold else FontWeight.Normal) - }) - } - } - } - Row( - verticalAlignment = Alignment.CenterVertically - ) { - Checkbox( - checked = sortReverseOrder, - onCheckedChange = { sortReverseOrder = it }, - ) - Text(text = "Reverse order", fontSize = 15.sp, fontWeight = FontWeight.Light, maxLines = 1, overflow = TextOverflow.Ellipsis) - } - } - LazyColumn( - modifier = Modifier - .fillMaxWidth() - .weight(1f), - verticalArrangement = Arrangement.spacedBy(3.dp) - ) { - stickyHeader { - Row( - modifier = Modifier - .fillMaxWidth() - .background(MaterialTheme.colorScheme.surface) - .padding(bottom = 2.dp), - horizontalArrangement = Arrangement.End, - verticalAlignment = Alignment.CenterVertically, - ) { - TextField( - value = nameFilter, - onValueChange = { - nameFilter = it - coroutineScope.launch { refreshList(clearSelected = false) } - }, - placeholder = { Text(text = "Search by name") }, - singleLine = true, - modifier = Modifier - .padding(end = 5.dp), - colors = TextFieldDefaults.colors( - focusedContainerColor = Color.Transparent, - unfocusedContainerColor = Color.Transparent - ), - ) - Checkbox( - checked = if (friends.isEmpty() || selectedFriends.size < friends.size) false else friends.all { friend -> selectedFriends.contains(friend.userId) }, - onCheckedChange = { state -> - if (state) { - friends.mapNotNull { it.userId }.forEach { userId -> - if (!selectedFriends.contains(userId)) { - selectedFriends.add(userId) - } - } - } else { - if (nameFilter.isNotBlank()) { - filterFriends(friends, filter, nameFilter).mapNotNull { it.userId }.forEach { userId -> - selectedFriends.remove(userId) - } - } else { - selectedFriends.clear() - } - } - } - ) - } - } - item { - if (friends.isEmpty()) { - Text(text = "No friends found", fontSize = 12.sp, fontWeight = FontWeight.Light, modifier = Modifier.fillMaxWidth(), textAlign = TextAlign.Center) - } - } - items(friends, key = { it.userId!! }) { friendInfo -> - var bitmojiBitmap by remember(friendInfo) { mutableStateOf(bitmojiCache[friendInfo.bitmojiAvatarId]) } - fun selectFriend(state: Boolean) { - friendInfo.userId?.let { - if (state) { - selectedFriends.add(it) - } else { - selectedFriends.remove(it) - } - } - } - Row( - modifier = Modifier - .fillMaxWidth() - .clickable { - selectFriend(!selectedFriends.contains(friendInfo.userId)) - } - .pointerInput(Unit) { - detectTapGestures( - onLongPress = { context.androidContext.copyToClipboard(friendInfo.mutableUsername.toString()) } - ) - }, - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.spacedBy(10.dp) - ) { - LaunchedEffect(friendInfo) { - withContext(Dispatchers.IO) { - if (bitmojiBitmap != null || friendInfo.bitmojiAvatarId == null || friendInfo.bitmojiSelfieId == null) return@withContext - val bitmojiUrl = BitmojiSelfie.getBitmojiSelfie(friendInfo.bitmojiSelfieId, friendInfo.bitmojiAvatarId, BitmojiSelfie.BitmojiSelfieType.NEW_THREE_D) ?: return@withContext - runCatching { - RemoteMediaResolver.downloadMedia(bitmojiUrl) { inputStream, _ -> - bitmojiCache[friendInfo.bitmojiAvatarId ?: return@withContext] = BitmapFactory.decodeStream(inputStream).also { - bitmojiBitmap = it - } - } - } - } - } - Image( - bitmap = remember (bitmojiBitmap) { bitmojiBitmap?.asImageBitmap() ?: noBitmojiBitmap }, - contentDescription = null, - modifier = Modifier.size(35.dp) - ) - Column( - modifier = Modifier.weight(1f), - ) { - Row( - modifier = Modifier.fillMaxWidth(), - horizontalArrangement = Arrangement.spacedBy(3.dp), - verticalAlignment = Alignment.CenterVertically - ){ - Text(text = (friendInfo.displayName ?: friendInfo.mutableUsername).toString(), fontSize = 16.sp, fontWeight = FontWeight.Bold, overflow = TextOverflow.Ellipsis, maxLines = 1, lineHeight = 10.sp) - Text(text = friendInfo.mutableUsername.toString(), fontSize = 10.sp, fontWeight = FontWeight.Light, overflow = TextOverflow.Ellipsis, maxLines = 1, lineHeight = 10.sp) - } - val lastMessage by rememberAsyncMutableState(defaultValue = null) { - getDMLastMessage(friendInfo.userId) - } - val userInfo = remember(friendInfo, lastMessage) { - buildString { - append("Relationship: ") - append(context.translation["friendship_link_type.${FriendLinkType.fromValue(friendInfo.friendLinkType).shortName}"]) - friendInfo.addedTimestamp.takeIf { it > 0L }?.let { - append("\nAdded ${DateFormat.getDateTimeInstance().format(Date(it))}") - } - friendInfo.snapScore.takeIf { it > 0 }?.let { - append("\nSnap Score: $it") - } - friendInfo.streakLength.takeIf { it > 0 }?.let { - append("\nStreaks length: $it") - } - lastMessage?.let { - append("\nSent messages: ${it.serverMessageId}") - append("\nLast message: ${DateFormat.getDateTimeInstance().format(Date(it.creationTimestamp))}") - } - betterLocation.locationHistory[context.database.myUserId]?.let { myLocation -> - betterLocation.locationHistory[friendInfo.userId]?.let { - append("\n${myLocation.distanceTo(it).let { distance -> - if (distance < 1) "${(distance * 1000).toInt()} m" else "${distance.toInt()} km" - } } away") - } - } - } - } - Text(text = userInfo, fontSize = 12.sp, fontWeight = FontWeight.Light, lineHeight = 12.sp, overflow = TextOverflow.Ellipsis) - } - Checkbox( - checked = selectedFriends.contains(friendInfo.userId), - onCheckedChange = { selectFriend(it) } - ) - } - } - } - var showConfirmationDialog by remember { mutableStateOf(false) } - var action by remember { mutableStateOf({}) } - if (showConfirmationDialog) { - ConfirmationDialog( - onConfirm = { - action() - action = {} - showConfirmationDialog = false - }, - onCancel = { - action = {} - showConfirmationDialog = false - } - ) - } - val ctx = LocalContext.current - val actions = remember { - mapOf<() -> String, () -> Unit>( - { "Clean " + selectedFriends.size + " conversations" } to { - context.feature(Messaging::class).conversationManager?.getOneOnOneConversationIds(selectedFriends.toList().also { - selectedFriends.clear() - }, onError = { error -> - context.shortToast("Failed to fetch conversations: $error") - }, onSuccess = { conversations -> - removeAction(ctx, conversations.map { it.second }.distinct(), delay = 10L to 40L) { conversationId, setDialogMessage -> - cleanConversation( - conversationId, setDialogMessage - ) - }.invokeOnCompletion { - coroutineScope.launch { refreshList() } - } - }) - }, - { "Remove " + selectedFriends.size + " friends" } to { - removeAction(ctx, selectedFriends.toList().also { - selectedFriends.clear() - }, delay = 500L to 1200L) { userId, _ -> removeFriend(userId) }.invokeOnCompletion { - coroutineScope.launch { refreshList() } - } - }, - { "Clean " + selectedFriends.size + " conversations and remove " + selectedFriends.size + " friends" } to { - context.feature(Messaging::class).conversationManager?.getOneOnOneConversationIds(selectedFriends.toList().also { - selectedFriends.clear() - }, onError = { error -> - context.shortToast("Failed to fetch conversations: $error") - }, onSuccess = { conversations -> - removeAction(ctx, conversations.map { it.second }.distinct(), delay = 500L to 1200L) { conversationId, setDialogMessage -> - cleanConversation( - conversationId, setDialogMessage - ) - removeFriend(conversations.firstOrNull { it.second == conversationId }?.first ?: return@removeAction) - }.invokeOnCompletion { - coroutineScope.launch { refreshList() } - } - }) - } - ) - } - Column( - modifier = Modifier.fillMaxWidth(), - ) { - actions.forEach { (text, actionFunction) -> - Button( - modifier = Modifier - .fillMaxWidth() - .padding(2.dp), - onClick = { - showConfirmationDialog = true - action = actionFunction - }, - enabled = selectedFriends.isNotEmpty() - ) { - Text(text = remember(selectedFriends.size) { text() }) - } - } - } - } - LaunchedEffect(sortBy, sortReverseOrder) { - coroutineScope.launch { - refreshList(clearSelected = false) - } - focusManager.clearFocus() - } - LaunchedEffect(filter) { - coroutineScope.launch { - refreshList() - } - focusManager.clearFocus() - } - } - override fun run() { - context.coroutineScope.launch(Dispatchers.Main) { - createComposeAlertDialog(context.mainActivity!!) { - BulkMessagingDialog() - }.apply { - setCanceledOnTouchOutside(false) - show() - } - } - } - private fun removeFriend(userId: String) { - context.mappings.useMapper(FriendRelationshipChangerMapper::class) { - try { - context.log.info("removeFriend started for $userId") - val addFriendSpoofInstance = context.feature(AddFriendSourceSpoof::class).friendRelationshipChangerInstance - context.log.info("addFriendSpoofInstance is: ${addFriendSpoofInstance?.javaClass?.name}") - val friendRelationshipChangerInstance: Any = addFriendSpoofInstance ?: run { - val clazz = classReference.get() - ?: throw Exception("FriendRelationshipChanger class not found") - context.log.info("FriendRelationshipChanger constructors: " + clazz.constructors.joinToString { it.toString() }) - when { - clazz.constructors.any { it.parameterTypes.isEmpty() } -> clazz.constructors.first { it.parameterTypes.isEmpty() }.newInstance() - clazz.constructors.any { it.parameterTypes.size == 1 } -> clazz.constructors.first { it.parameterTypes.size == 1 }.newInstance(context.mainActivity) - clazz.constructors.any { it.parameterTypes.size == 2 } -> clazz.constructors.first { it.parameterTypes.size == 2 }.newInstance(context.mainActivity, context.mainActivity!!.application) - else -> throw Exception("No suitable FriendRelationshipChanger constructor found") - } - } - context.log.info("Obtained instance: ${friendRelationshipChangerInstance.javaClass.name}") - val method = friendRelationshipChangerInstance.javaClass.methods.firstOrNull { - it.parameterTypes.size == 5 - } ?: throw Exception("Failed to find a suitable method for remove friend. Please contact support.") - context.log.info("Target method found: ${method.name}") - val enumClass = method.parameterTypes[1] - val enumConstants = enumClass.enumConstants ?: throw Exception("Could not get enum constants from ${enumClass.name}") - val deletedByMyFriends = enumConstants.firstOrNull { - it.toString() == "DELETED_BY_MY_FRIENDS" - } ?: enumConstants.first() - context.log.info("Enum resolved: $deletedByMyFriends") - val c36077qT8Class = method.parameterTypes[4] - val constructor = c36077qT8Class.constructors.firstOrNull { - it.parameterTypes.size == 2 && it.parameterTypes.all { p -> p == String::class.java } - } ?: throw Exception("Failed to find suitable constructor for C36077qT8") - val placementInfo = constructor.newInstance("", "") - context.log.info("C36077qT8 instance created: $placementInfo") - val completable = method.invoke( - friendRelationshipChangerInstance, - userId, - deletedByMyFriends, - "", - "", - placementInfo - ) ?: throw Exception("Friend removal call returned null.") - context.log.info("Completable: $completable") - val completableClass = completable::class.java - val allMethods = completableClass.methods.joinToString("\n") { it.toString() } - context.log.info("Completable class: ${completableClass.name}") - context.log.info("All Completable methods:\n$allMethods") - val vMethod = completableClass.methods.firstOrNull { it.name == "V" && it.parameterTypes.size == 1 } - if (vMethod != null) { - context.log.info("Found V(hq3), creating dynamic proxy by parameter type...") - val hq3Class = vMethod.parameterTypes[0] - val proxy = java.lang.reflect.Proxy.newProxyInstance( - hq3Class.classLoader, - arrayOf(hq3Class) - ) { _, _, _ -> } - context.log.info("Invoking V(hq3) with dynamic proxy") - vMethod.invoke(completable, proxy) - context.log.info("removeFriend triggered with V(hq3) and proxy") - } else { - val bMethod = completableClass.methods.firstOrNull { it.name == "b" && it.parameterTypes.size == 1 } - if (bMethod != null) { - val hq3Class = bMethod.parameterTypes[0] - val proxy = java.lang.reflect.Proxy.newProxyInstance( - hq3Class.classLoader, - arrayOf(hq3Class) - ) { _, _, _ -> } - context.log.info("Invoking b(hq3) with dynamic proxy") - bMethod.invoke(completable, proxy) - context.log.info("removeFriend triggered with b(hq3) and proxy") - } else { - val triggerMethods = completableClass.methods.filter { it.returnType == Void.TYPE && it.parameterTypes.size == 1 } - context.log.error("No trigger method found. 1-arg void methods: ${triggerMethods.joinToString { it.toString() }}") - throw IllegalArgumentException("No trigger method found on Completable.") - } - } - } catch (e: Exception) { - context.log.error("removeFriend failed", e) - println("removeFriend failed: " + e + "\n" + e.stackTraceToString()) - context.shortToast("removeFriend failed: ${e.message}") - throw e - } - } - } - private suspend fun cleanConversation( - conversationId: String, - setDialogMessage: (String) -> Unit - ) { - val messageCount = mutableIntStateOf(0) - MessagingTask( - context.messagingBridge, - conversationId, - taskType = MessagingTaskType.DELETE, - constraints = listOf(MessagingConstraints.MY_USER_ID(context.messagingBridge), { - contentType != ContentType.STATUS.id - }), - processedMessageCount = messageCount, - onSuccess = { - setDialogMessage("${messageCount.intValue} deleted messages") - }, - ).run() - } -} diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/action/impl/ExportChatMessages.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/action/impl/ExportChatMessages.kt deleted file mode 100644 index 3cd812d4..00000000 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/action/impl/ExportChatMessages.kt +++ /dev/null @@ -1,425 +0,0 @@ -package me.rhunk.snapenhance.core.action.impl - -import android.app.AlertDialog -import android.content.DialogInterface -import android.os.Environment -import androidx.compose.foundation.ScrollState -import androidx.compose.foundation.layout.* -import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.items -import androidx.compose.foundation.text.KeyboardActions -import androidx.compose.foundation.text.KeyboardOptions -import androidx.compose.foundation.verticalScroll -import androidx.compose.material3.* -import androidx.compose.runtime.* -import androidx.compose.ui.Alignment -import androidx.compose.ui.ExperimentalComposeUiApi -import androidx.compose.ui.Modifier -import androidx.compose.ui.platform.LocalConfiguration -import androidx.compose.ui.platform.LocalFocusManager -import androidx.compose.ui.platform.LocalSoftwareKeyboardController -import androidx.compose.ui.text.input.ImeAction -import androidx.compose.ui.text.input.KeyboardType -import androidx.compose.ui.text.style.TextOverflow -import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp -import kotlinx.coroutines.* -import me.rhunk.snapenhance.common.data.ContentType -import me.rhunk.snapenhance.common.database.impl.FriendFeedEntry -import me.rhunk.snapenhance.common.ui.createComposeAlertDialog -import me.rhunk.snapenhance.common.ui.rememberAsyncMutableState -import me.rhunk.snapenhance.core.action.AbstractAction -import me.rhunk.snapenhance.core.features.impl.messaging.Messaging -import me.rhunk.snapenhance.core.logger.CoreLogger -import me.rhunk.snapenhance.core.messaging.ConversationExporter -import me.rhunk.snapenhance.core.messaging.ExportFormat -import me.rhunk.snapenhance.core.messaging.ExportParams -import me.rhunk.snapenhance.core.ui.ViewAppearanceHelper -import me.rhunk.snapenhance.core.wrapper.impl.Message -import java.io.File -import kotlin.math.absoluteValue - -class ExportChatMessages : AbstractAction() { - private val translation by lazy { context.translation.getCategory("chat_export") } - private val dialogLogs = mutableListOf() - private var currentActionDialog: AlertDialog? = null - - private fun logDialog(message: String) { - context.runOnUiThread { - if (dialogLogs.size > 10) dialogLogs.removeAt(0) - dialogLogs.add(message) - context.log.debug("dialog: $message", "ExportChatMessages") - currentActionDialog!!.setMessage(dialogLogs.joinToString("\n")) - } - } - - private fun setStatus(message: String) { - context.runOnUiThread { - currentActionDialog!!.setTitle(message) - } - } - - @OptIn(ExperimentalMaterial3Api::class, ExperimentalComposeUiApi::class) - @Composable - private fun ExporterDialog( - getDialog: () -> AlertDialog? = { null } - ) { - val exporterTranslation = remember { - translation.getCategory("exporter_dialog") - } - - var feedEntries by remember { mutableStateOf(emptyList()) } - var exportType by remember { mutableStateOf(ExportFormat.HTML) } - val selectedFeedEntries = remember { mutableStateListOf() } - val messageTypeFilter = remember { mutableStateListOf() } - var amountOfMessages by remember { mutableIntStateOf(-1) } - var downloadMedias by remember { mutableStateOf(false) } - val allFriends by rememberAsyncMutableState(null) { context.database.getAllFriends().associateBy { it.userId!! } } - val myUserId = context.database.myUserId - - Column( - modifier = Modifier - .fillMaxWidth() - .verticalScroll(remember { ScrollState(0) }) - .padding(16.dp), - verticalArrangement = Arrangement.spacedBy(10.dp) - ) { - Text(exporterTranslation["select_conversations_title"]) - run { - var expanded by remember { mutableStateOf(false) } - - ExposedDropdownMenuBox( - expanded = expanded, - onExpandedChange = { expanded = it }, - ) { - TextField( - value = selectedFeedEntries.let { - exporterTranslation.format("text_field_selection", "amount" to it.size.toString()) - }, - onValueChange = {}, - readOnly = true, - singleLine = true, - modifier = Modifier.menuAnchor(MenuAnchorType.PrimaryNotEditable) - ) - - ExposedDropdownMenu(expanded = expanded, onDismissRequest = { expanded = false }) { - LazyColumn( - modifier = Modifier.size(LocalConfiguration.current.screenWidthDp.dp, 300.dp) - ) { - items(feedEntries, key = { it.key!! }) { feedEntry -> - DropdownMenuItem( - modifier = Modifier.fillMaxWidth(), - onClick = { - if (selectedFeedEntries.contains(feedEntry)) selectedFeedEntries -= feedEntry - else selectedFeedEntries += feedEntry - }, - text = { - Row( - verticalAlignment = Alignment.CenterVertically - ) { - Checkbox(checked = selectedFeedEntries.contains(feedEntry), onCheckedChange = null) - Column { - Text( - text = remember(feedEntry) { - (if (feedEntry.conversationType == 1) feedEntry.feedDisplayName else feedEntry.participants?.filter { it != myUserId }?.firstOrNull()?.let { userId -> - allFriends?.get(userId)?.let { friend -> friend.displayName?.let { "$it (${friend.mutableUsername})" } ?: friend.mutableUsername } - }) ?: "Unknown" - }, - overflow = TextOverflow.Ellipsis, - lineHeight = 15.sp, - maxLines = 1 - ) - if (feedEntry.conversationType == 1) { - Text( - text = "${feedEntry.participantsSize} participants", - fontSize = 10.sp, - lineHeight = 15.sp, - overflow = TextOverflow.Ellipsis, - ) - } - } - } - } - ) - } - } - } - } - } - - Text(exporterTranslation["export_file_format_title"]) - run { - var expanded by remember { mutableStateOf(false) } - - ExposedDropdownMenuBox( - expanded = expanded, - onExpandedChange = { expanded = it }, - ) { - TextField( - value = exportType.extension, - onValueChange = {}, - readOnly = true, - modifier = Modifier.menuAnchor(MenuAnchorType.PrimaryNotEditable) - ) - - ExposedDropdownMenu(expanded = expanded, onDismissRequest = { expanded = false }) { - ExportFormat.entries.forEach { exportFormat -> - DropdownMenuItem(onClick = { - exportType = exportFormat - expanded = false - }, text = { - Text(text = exportFormat.name) - }) - } - } - } - } - Text(exporterTranslation["message_type_filter_title"]) - run { - var expanded by remember { mutableStateOf(false) } - - ExposedDropdownMenuBox( - expanded = expanded, - onExpandedChange = { expanded = it }, - ) { - TextField( - value = messageTypeFilter.takeIf { it.isNotEmpty() }?.let { - exporterTranslation.format("text_field_selection", "amount" to it.size.toString()) - } ?: exporterTranslation["text_field_selection_all"], - onValueChange = {}, - readOnly = true, - modifier = Modifier.menuAnchor(MenuAnchorType.PrimaryNotEditable) - ) - - ExposedDropdownMenu(expanded = expanded, onDismissRequest = { expanded = false }) { - arrayOf( - ContentType.CHAT, - ContentType.SNAP, - ContentType.EXTERNAL_MEDIA, - ContentType.NOTE, - ContentType.STICKER - ).forEach { contentType -> - DropdownMenuItem(onClick = { - if (messageTypeFilter.contains(contentType)) messageTypeFilter -= contentType - else messageTypeFilter += contentType - }, text = { - Row( - verticalAlignment = Alignment.CenterVertically - ) { - Checkbox(checked = messageTypeFilter.contains(contentType), onCheckedChange = null) - Text(text = contentType.name) - } - }) - } - } - } - } - - Text(exporterTranslation["amount_of_messages_title"]) - val focusManager = LocalFocusManager.current - val keyboard = LocalSoftwareKeyboardController.current - TextField( - value = amountOfMessages.takeIf { it != -1 }?.toString() ?: "", - onValueChange = { amountOfMessages = it.toIntOrNull()?.absoluteValue ?: -1 }, - singleLine = true, - keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done, keyboardType = KeyboardType.Number), - keyboardActions = KeyboardActions( - onDone = { - focusManager.clearFocus() - keyboard?.hide() - }) - ) - - Row( - modifier = Modifier.fillMaxWidth(), - horizontalArrangement = Arrangement.spacedBy(10.dp), - verticalAlignment = Alignment.CenterVertically - ) { - Checkbox(checked = downloadMedias, onCheckedChange = { downloadMedias = it }) - Text(exporterTranslation["download_medias_title"]) - } - - Row( - modifier = Modifier.fillMaxWidth(), - horizontalArrangement = Arrangement.SpaceEvenly, - ) { - Button( - onClick = { getDialog()?.dismiss() } - ) { - Text(text = translation["dialog_negative_button"]) - } - Button( - enabled = selectedFeedEntries.isNotEmpty(), - onClick = { - exportChatForConversations(selectedFeedEntries, ExportParams( - exportFormat = exportType, - messageTypeFilter = messageTypeFilter.takeIf { it.isNotEmpty() }, - amountOfMessages = amountOfMessages.takeIf { it != -1 }, - downloadMedias = downloadMedias - )) - } - ) { - Text(text = translation["dialog_positive_button"]) - } - } - - LaunchedEffect(Unit) { - withContext(Dispatchers.IO) { - feedEntries = context.database.getFeedEntries(500) - } - } - } - } - - override fun run() { - context.coroutineScope.launch(Dispatchers.Main) { - createComposeAlertDialog(context.mainActivity!!) { alertDialog -> - ExporterDialog { alertDialog } - }.apply { - setCanceledOnTouchOutside(false) - show() - } - } - } - - private suspend fun fetchMessagesPaginated(conversationId: String, lastMessageId: Long, amount: Int): List = runBlocking { - for (i in 0..5) { - val messages: List? = suspendCancellableCoroutine { continuation -> - context.feature(Messaging::class).conversationManager?.fetchConversationWithMessagesPaginated(conversationId, - lastMessageId, - amount, onSuccess = { messages -> - continuation.resumeWith(Result.success(messages)) - }, onError = { - continuation.resumeWith(Result.success(null)) - }) ?: continuation.resumeWith(Result.success(null)) - } - if (messages != null) return@runBlocking messages - logDialog("Retrying in 1 second...") - delay(1000) - } - logDialog("Failed to fetch messages") - emptyList() - } - - private fun exportChatForConversations( - conversations: List, - exportParams: ExportParams, - ) { - dialogLogs.clear() - val jobs = mutableListOf() - - currentActionDialog = ViewAppearanceHelper.newAlertDialogBuilder(context.mainActivity) - .setTitle(translation["exporting_chats"]) - .setCancelable(false) - .setMessage("") - .create() - - val conversationSize = translation.format("processing_chats", "amount" to conversations.size.toString()) - - logDialog(conversationSize) - - context.coroutineScope.launch { - conversations.forEach { conversation -> - launch { - runCatching { - exportFullConversation(conversation, exportParams) - }.onFailure { - logDialog(translation.format("export_fail", "conversation" to conversation.key.toString())) - logDialog(it.stackTraceToString()) - CoreLogger.xposedLog(it) - } - }.also { jobs.add(it) } - } - jobs.joinAll() - logDialog(translation["finished"]) - }.also { - currentActionDialog?.setButton(DialogInterface.BUTTON_POSITIVE, translation["dialog_negative_button"]) { dialog, _ -> - it.cancel() - jobs.forEach { it.cancel() } - dialog.dismiss() - } - } - - currentActionDialog!!.also { - it.setCanceledOnTouchOutside(false) - }.show() - } - - private suspend fun exportFullConversation( - feedEntry: FriendFeedEntry, - exportParams: ExportParams, - ) { - //first fetch the first message - val conversationId = feedEntry.key!! - val conversationParticipants = context.database.getConversationParticipants(feedEntry.key!!, useCache = false) - ?.mapNotNull { - context.database.getFriendInfo(it) - }?.associateBy { it.userId!! } ?: emptyMap() - - val conversationName = feedEntry.feedDisplayName ?: conversationParticipants.values.take(3).joinToString("_") { it.mutableUsername ?: "" } - - val publicFolder = File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), "SnapEnhance").also { if (!it.exists()) it.mkdirs() } - val outputFile = publicFolder.resolve("conversation_${conversationName}_${System.currentTimeMillis()}.${exportParams.exportFormat.extension}") - - logDialog(translation.format("exporting_message", "conversation" to conversationName)) - - val conversationExporter = ConversationExporter( - context = context, - friendFeedEntry = feedEntry, - conversationParticipants = conversationParticipants, - exportParams = exportParams, - cacheFolder = publicFolder.resolve("cache").also { if (!it.exists()) it.mkdirs() }, - outputFile = outputFile, - ).apply { init(); printLog = { - logDialog(it.toString()) - } } - - var foundMessageCount = 0 - - var lastMessageId = fetchMessagesPaginated(conversationId, Long.MAX_VALUE, amount = 1).firstOrNull()?.also { - conversationExporter.readMessage(it) - foundMessageCount++ - }?.messageDescriptor?.messageId ?: run { - logDialog(translation["no_messages_found"]) - return - } - - while (true) { - val fetchedMessages = fetchMessagesPaginated(conversationId, lastMessageId, amount = 500).toMutableList() - if (fetchedMessages.isEmpty()) break - - fetchedMessages.firstOrNull()?.let { - lastMessageId = it.messageDescriptor!!.messageId!! - } - - exportParams.messageTypeFilter?.let { filter -> - fetchedMessages.removeIf { message -> - !filter.contains(message.messageContent?.contentType ?: return@removeIf false) - } - } - - foundMessageCount += fetchedMessages.size - - if (exportParams.amountOfMessages != null && foundMessageCount >= exportParams.amountOfMessages) { - fetchedMessages.reversed().subList(0, exportParams.amountOfMessages - (foundMessageCount - fetchedMessages.size)).forEach { message -> - conversationExporter.readMessage(message) - } - break - } - - fetchedMessages.reversed().forEach { message -> - conversationExporter.readMessage(message) - } - - setStatus("Exporting (found ${foundMessageCount})") - } - - if (exportParams.exportFormat == ExportFormat.HTML) conversationExporter.awaitDownload() - conversationExporter.close() - logDialog(translation["writing_output"]) - dialogLogs.clear() - logDialog("\n" + translation.format("exported_to", - "path" to outputFile.absolutePath.toString() - ) + "\n") - } -} \ No newline at end of file diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/action/impl/ExportMemories.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/action/impl/ExportMemories.kt deleted file mode 100644 index 54da9059..00000000 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/action/impl/ExportMemories.kt +++ /dev/null @@ -1,387 +0,0 @@ -package me.rhunk.snapenhance.core.action.impl - -import android.database.sqlite.SQLiteDatabase -import android.database.sqlite.SQLiteDatabase.OpenParams -import android.os.Environment -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.padding -import androidx.compose.material3.* -import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember -import androidx.compose.runtime.setValue -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.text.style.TextAlign -import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp -import kotlinx.coroutines.* -import me.rhunk.snapenhance.common.data.FileType -import me.rhunk.snapenhance.common.ui.createComposeAlertDialog -import me.rhunk.snapenhance.common.util.ktx.getLongOrNull -import me.rhunk.snapenhance.common.util.ktx.getStringOrNull -import me.rhunk.snapenhance.core.action.AbstractAction -import okhttp3.OkHttpClient -import java.io.File -import java.io.FileOutputStream -import java.nio.file.attribute.FileTime -import java.time.Instant -import java.time.OffsetDateTime -import java.util.zip.ZipEntry -import java.util.zip.ZipOutputStream -import javax.crypto.Cipher -import javax.crypto.CipherInputStream -import javax.crypto.spec.IvParameterSpec -import javax.crypto.spec.SecretKeySpec -import kotlin.io.encoding.Base64 -import kotlin.io.encoding.ExperimentalEncodingApi -import kotlin.math.absoluteValue - -class ExportMemories : AbstractAction() { - data class TimeRange( - val start: Long?, - val end: Long?, - ) - - data class MemoriesEntry( - val storyTitle: String, - val createTime: Long, - val mediaKey: String?, - val mediaIv: String?, - val downloadUrl: String - ) { - val folderName: String - get() = storyTitle.replace(Regex("[^a-zA-Z0-9\\s]"), "").trim().replace(Regex("\\s+"), "_") - } - - @OptIn(ExperimentalCoroutinesApi::class, ExperimentalEncodingApi::class) - private suspend fun exportMemories( - scope: CoroutineScope = context.coroutineScope, - database: SQLiteDatabase, - timeRange: TimeRange?, - includeMEO: Boolean, - folders: Boolean, - progress: (Int, Int) -> Unit - ) { - val downloadContext = Dispatchers.IO.limitedParallelism(10) - val writeToZipContext = Dispatchers.IO.limitedParallelism(1) - val outputZip = File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS), "memories_" + System.currentTimeMillis() + ".zip").also { - if (it.exists()) it.delete() - } - val okHttpClient = OkHttpClient.Builder().build() - val outputZipFile = withContext(Dispatchers.IO) { - ZipOutputStream(FileOutputStream(outputZip)).apply { - setComment("Exported from SnapEnhance") - setMethod(ZipOutputStream.DEFLATED) - } - } - var totalCount = 0 - var currentCount = 0 - var failed = 0 - - fun updateProgress() { - progress((currentCount.toFloat() / totalCount.toFloat() * 100f).toInt(), failed) - } - - val jobs = mutableListOf() - - val meoMasterKeyPair = if (includeMEO) { - runCatching { - database.rawQuery("SELECT * FROM memories_meo_confidential", null).use { cursor -> - if (cursor.moveToNext()) { - cursor.getStringOrNull("master_key")!!.trim() to cursor.getStringOrNull("master_key_iv")!!.trim() - } else null - } - }.getOrNull() - } else null - - database.rawQuery("SELECT memories_entry.title as story_title, memories_snap.create_time, " + - "memories_snap.media_key, memories_snap.media_iv, memories_snap.encrypted_media_key, memories_snap.encrypted_media_iv, " + - "memories_media.download_url FROM memories_snap " + - "INNER JOIN memories_entry ON memories_snap.memories_entry_id = memories_entry._id " + - "INNER JOIN memories_media ON memories_snap.media_id = memories_media._id " + - "WHERE memories_snap.create_time >= ? AND memories_snap.create_time <= ? " + - "ORDER BY memories_snap.create_time ASC", arrayOf(timeRange?.start?.toString() ?: "-1", timeRange?.end?.toString() ?: Long.MAX_VALUE.toString()) - ).use { cursor -> - while (cursor.moveToNext()) { - val encryptedMediaKey = cursor.getStringOrNull("encrypted_media_key")?.trim() - val encryptedMediaIv = cursor.getStringOrNull("encrypted_media_iv")?.trim() - var mediaKey = cursor.getStringOrNull("media_key")?.trim() - var mediaIv = cursor.getStringOrNull("media_iv")?.trim() - - if (!includeMEO && encryptedMediaKey != null && encryptedMediaIv != null) continue - - meoMasterKeyPair.takeIf { encryptedMediaKey != null && encryptedMediaIv != null }?.let { keyPair -> - val cipher = Cipher.getInstance("AES/CBC/PKCS5Padding") - runCatching { - cipher.init(Cipher.DECRYPT_MODE, SecretKeySpec(Base64.decode(keyPair.first), "AES"), IvParameterSpec(Base64.decode(keyPair.second))) - mediaKey = Base64.encode(cipher.doFinal(Base64.decode(encryptedMediaKey ?: return@let))) - mediaIv = Base64.encode(cipher.doFinal(Base64.decode(encryptedMediaIv ?: return@let))) - context.log.verbose("decrypted meo $mediaKey/$mediaIv") - }.onFailure { - context.log.error("failed to decrypt meo", it) - } - } - - if (mediaKey == null || mediaIv == null) { - context.log.error("missing media key or iv for ${cursor.getStringOrNull("download_url")}") - failed++ - updateProgress() - continue - } - - val entry = MemoriesEntry( - storyTitle = cursor.getStringOrNull("story_title") ?: "unknown", - createTime = cursor.getLongOrNull("create_time") ?: -1L, - mediaKey = mediaKey, - mediaIv = mediaIv, - downloadUrl = cursor.getStringOrNull("download_url") ?: continue - ) - - totalCount++ - - scope.launch(downloadContext) { - var downloadedFile = File.createTempFile("memories", ".tmp", context.androidContext.cacheDir) - - runCatching { - okHttpClient.newCall( - okhttp3.Request.Builder() - .url(entry.downloadUrl) - .build() - ).execute().use { response -> - val inputStream = response.body.byteStream().let { - if (entry.mediaKey != null && entry.mediaIv != null) { - val cipher = Cipher.getInstance("AES/CBC/PKCS5Padding") - cipher.init(Cipher.DECRYPT_MODE, SecretKeySpec(Base64.decode(entry.mediaKey), "AES"), IvParameterSpec(Base64.decode(entry.mediaIv))) - CipherInputStream(it, cipher) - } else it - } - - downloadedFile.outputStream().use { outputStream -> - inputStream.use { inputStream -> - inputStream.copyTo(outputStream) - } - } - - val fileType = FileType.fromFile(downloadedFile) - - downloadedFile = File( - downloadedFile.parentFile, - "${entry.createTime}-${entry.downloadUrl.hashCode().absoluteValue.toString(16)}.${fileType.fileExtension}" - ).also { - downloadedFile.renameTo(it) - } - - withContext(writeToZipContext) { - val zipEntry = ZipEntry("${if (folders) entry.folderName + "/" else entry.folderName}${downloadedFile.name}") - FileTime.fromMillis(entry.createTime).let { - zipEntry.lastModifiedTime = it - zipEntry.lastAccessTime = it - zipEntry.creationTime = it - } - outputZipFile.apply { - putNextEntry(zipEntry) - downloadedFile.inputStream().use { it.copyTo(outputZipFile) } - closeEntry() - flush() - } - currentCount++ - updateProgress() - } - } - }.onFailure { - context.log.error("failed to download ${entry.downloadUrl}", it) - failed++ - updateProgress() - } - downloadedFile.delete() - }.also { jobs.add(it) } - } - } - - jobs.joinAll() - withContext(Dispatchers.IO) { - outputZipFile.close() - } - context.longToast("Exported to ${outputZip.absolutePath}") - } - - @OptIn(ExperimentalMaterial3Api::class) - @Composable - fun ExporterDialog(database: SQLiteDatabase, onDismiss: () -> Unit) { - var exportJob by remember { mutableStateOf(null as Job?) } - var exportFinished by remember { mutableStateOf(false) } - var exportProgress by remember { mutableStateOf(Pair(0, 0)) } // progress, failed - - var dateRangeFilter by remember { mutableStateOf(false) } - var sortByFolder by remember { mutableStateOf(false) } - var includeMEO by remember { mutableStateOf(false) } - val dateRangePickerState = rememberDateRangePickerState( - initialSelectedStartDateMillis = OffsetDateTime.now().minusDays(8).toInstant().toEpochMilli(), - initialSelectedEndDateMillis = Instant.now().toEpochMilli(), - initialDisplayMode = DisplayMode.Input - ) - - val totalCount = remember(dateRangePickerState.selectedStartDateMillis, dateRangePickerState.selectedEndDateMillis, dateRangeFilter) { - val timeRange = dateRangePickerState.takeIf { dateRangeFilter }?.let { - TimeRange(it.selectedStartDateMillis, it.selectedEndDateMillis) - } - - database.rawQuery("SELECT COUNT(*) FROM memories_snap WHERE create_time >= ? AND create_time <= ? ", arrayOf(timeRange?.start?.toString() ?: "-1", timeRange?.end?.toString() ?: Long.MAX_VALUE.toString())).use { - it.moveToFirst() - it.getInt(0) - } - } - - Column( - modifier = Modifier.padding(16.dp), - verticalArrangement = Arrangement.spacedBy(8.dp) - ) { - Text("Export memories", modifier = Modifier.fillMaxWidth(), textAlign = TextAlign.Center, fontSize = 20.sp) - - if (exportJob != null) { - Text(text = "Exporting memories... (${exportProgress.second} failed)", modifier = Modifier.fillMaxWidth(), textAlign = TextAlign.Center) - LinearProgressIndicator( - progress = { exportProgress.first / 100f }, - modifier = Modifier.fillMaxWidth(), - ) - Row( - modifier = Modifier.fillMaxWidth(), - horizontalArrangement = Arrangement.SpaceEvenly, - verticalAlignment = Alignment.CenterVertically - ) { - Button(onClick = { - exportJob?.cancel() - exportJob = null - onDismiss() - }) { - Text("Quit") - } - if (exportFinished) { - Button(onClick = { - exportJob = null - onDismiss() - }) { - Text("Done") - } - } - } - } else { - Text("Total memories: $totalCount", modifier = Modifier.fillMaxWidth(), textAlign = TextAlign.Center) - - Row( - modifier = Modifier.fillMaxWidth(), - horizontalArrangement = Arrangement.spacedBy(5.dp), - verticalAlignment = Alignment.CenterVertically - ) { - var dateRangeDialog by remember { mutableStateOf(false) } - Checkbox(checked = dateRangeFilter, onCheckedChange = { dateRangeFilter = it }) - Text("Date Range", modifier = Modifier.weight(1f)) - Button(onClick = { dateRangeDialog = true }, enabled = dateRangeFilter) { - Text("Select") - } - - if (dateRangeDialog) { - DatePickerDialog(onDismissRequest = { - dateRangeDialog = false - }, confirmButton = {}) { - DateRangePicker( - state = dateRangePickerState, - modifier = Modifier.weight(1f), - ) - Row( - modifier = Modifier - .fillMaxWidth() - .padding(8.dp), - horizontalArrangement = Arrangement.End - ) { - Button(onClick = { - dateRangeDialog = false - }) { - Text("OK") - } - } - } - } - } - - Row( - modifier = Modifier.fillMaxWidth(), - horizontalArrangement = Arrangement.spacedBy(5.dp), - verticalAlignment = Alignment.CenterVertically - ) { - Checkbox(checked = sortByFolder, onCheckedChange = { sortByFolder = it }) - Text("Sort by folder", modifier = Modifier.weight(1f)) - } - - Row( - modifier = Modifier.fillMaxWidth(), - horizontalArrangement = Arrangement.spacedBy(5.dp), - verticalAlignment = Alignment.CenterVertically - ) { - Checkbox(checked = includeMEO, onCheckedChange = { includeMEO = it }) - Text("Include My Eyes Only", modifier = Modifier.weight(1f)) - } - - Row( - modifier = Modifier.fillMaxWidth(), - horizontalArrangement = Arrangement.SpaceEvenly, - verticalAlignment = Alignment.CenterVertically - ) { - Button(onClick = onDismiss) { - Text("Cancel") - } - Button(onClick = { - context.coroutineScope.launch { - exportMemories( - scope = this, - database = database, - timeRange = dateRangePickerState.takeIf { dateRangeFilter }?.let { - TimeRange(it.selectedStartDateMillis, it.selectedEndDateMillis) - }, - folders = sortByFolder, - includeMEO = includeMEO, - ) { progress, failed -> - exportProgress = Pair(progress, failed) - } - }.also { exportJob = it }.invokeOnCompletion { - exportFinished = true - } - }) { - Text("Export") - } - } - } - - - } - } - - override fun run() { - context.coroutineScope.launch(Dispatchers.Main) { - val database = runCatching { - SQLiteDatabase.openDatabase( - context.androidContext.getDatabasePath("memories.db"), - OpenParams.Builder().setOpenFlags(SQLiteDatabase.OPEN_READONLY).build() - ) - }.getOrNull() - - if (database == null) { - context.longToast("Failed to open memories database") - return@launch - } - - createComposeAlertDialog(context.mainActivity!!) { alertDialog -> - ExporterDialog(database) { alertDialog.dismiss() } - }.apply { - setOnDismissListener { database.close() } - setCanceledOnTouchOutside(false) - show() - } - } - } -} \ No newline at end of file diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/action/impl/ManageFriendList.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/action/impl/ManageFriendList.kt deleted file mode 100644 index 93cba82a..00000000 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/action/impl/ManageFriendList.kt +++ /dev/null @@ -1,268 +0,0 @@ -package me.rhunk.snapenhance.core.action.impl - -import android.content.Intent -import android.net.Uri -import androidx.compose.foundation.layout.* -import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.items -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.automirrored.filled.ArrowBack -import androidx.compose.material3.* -import androidx.compose.runtime.* -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.text.style.TextAlign -import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.Job -import kotlinx.coroutines.delay -import kotlinx.coroutines.launch -import kotlinx.coroutines.withTimeout -import me.rhunk.snapenhance.common.data.FriendLinkType -import me.rhunk.snapenhance.common.ui.createComposeAlertDialog -import me.rhunk.snapenhance.core.action.AbstractAction -import me.rhunk.snapenhance.core.event.events.impl.ActivityResultEvent -import me.rhunk.snapenhance.core.features.impl.experiments.AddFriendSourceSpoof -import me.rhunk.snapenhance.core.features.impl.messaging.Messaging -import me.rhunk.snapenhance.core.wrapper.impl.Snapchatter -import me.rhunk.snapenhance.mapper.impl.FriendRelationshipChangerMapper -import kotlin.random.Random - -class ManageFriendList : AbstractAction() { - private var pendingPickerAction: Pair Unit>? = null - - private val uuidRegex by lazy { - Regex("[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}") - } - - private fun addFriend(userId: String) { - val friendRelationshipChangerInstance = context.feature(AddFriendSourceSpoof::class).friendRelationshipChangerInstance - context.mappings.useMapper(FriendRelationshipChangerMapper::class) { - val addFriend = friendshipRelationshipChangerKtx.get()?.methods?.firstOrNull { it.name == addFriendMethod.get() } - ?: return@useMapper - - addFriend.invoke( - null, - friendRelationshipChangerInstance, - userId, - addFriend.parameterTypes[2].enumConstants!!.first { it.toString() == "ADDED_BY_USERNAME" }, - addFriend.parameterTypes[3].enumConstants!!.first { it.toString() == "SEARCH" }, - addFriend.parameterTypes[4].enumConstants!!.first { it.toString() == "SEARCH" }, - 0 - ) - } - } - - override fun onActivityCreate() { - context.event.subscribe(ActivityResultEvent::class) { event -> - if (event.requestCode == pendingPickerAction?.first) { - val pendingAction = pendingPickerAction ?: return@subscribe - this.pendingPickerAction = null - event.canceled = true - pendingAction.second(event.intent.data!!) - } - } - } - - private fun exportFriends( - userIds: List - ) { - pendingPickerAction = Random.nextInt(0, 65535) to { data -> - context.androidContext.contentResolver.openOutputStream(data).use { output -> - output?.bufferedWriter()?.use { writer -> - userIds.forEach { - writer.write(it) - writer.newLine() - } - } - context.longToast("Exported ${userIds.size} friends!") - } - } - context.mainActivity?.startActivityForResult( - Intent.createChooser( - Intent(Intent.ACTION_CREATE_DOCUMENT).apply { - type = "text/plain" - putExtra(Intent.EXTRA_TITLE, "my_friends.txt") - }, - "Select a location to save the file" - ), - pendingPickerAction!!.first - ) - } - - private val userIdToSnapchatter = mutableMapOf() - - @Composable - private fun ManagerDialog() { - val pendingFriendRequests = remember { mutableStateMapOf() } - var fetchedFriends by remember { mutableStateOf?>(null) } // list of uuids - val coroutineScope = rememberCoroutineScope() - - if (fetchedFriends == null) { - Box( - modifier = Modifier - .fillMaxWidth() - .heightIn(min = 200.dp), - contentAlignment = Alignment.Center - ) { - Column( - modifier = Modifier - .fillMaxWidth() - .padding(16.dp), - horizontalAlignment = Alignment.CenterHorizontally, - ) { - Text("Manage Friend List", fontSize = 20.sp) - Spacer(modifier = Modifier.height(5.dp)) - Text( - text = "Export friends allows you to save a list of your friends' IDs in a text file. Importing from a file will display the friends in a list where you can add them.", - fontSize = 14.sp, - fontWeight = FontWeight.Light, - textAlign = TextAlign.Center - ) - Spacer(modifier = Modifier.height(10.dp)) - Row( - horizontalArrangement = Arrangement.spacedBy(16.dp) - ) { - Button(onClick = { - exportFriends(context.database.getAllFriends().filter { it.friendLinkType == FriendLinkType.MUTUAL.value && it.addedTimestamp > 0L }.mapNotNull { it.userId }) - }) { - Text("Export friends") - } - Button(onClick = { - pendingPickerAction = Random.nextInt(0, 65535) to { data -> - runCatching { - fetchedFriends = null - context.androidContext.contentResolver.openInputStream(data).use { input -> - fetchedFriends = input?.bufferedReader()?.readLines()?.filter { - it.matches(uuidRegex) - }?.map { it.trim() }?.toMutableList() ?: mutableListOf() - } - }.onFailure { - context.log.error("Failed to import friends", it) - context.longToast("Failed to import friends: ${it.message}") - } - } - // launch file picker - context.mainActivity?.startActivityForResult( - Intent.createChooser( - Intent(Intent.ACTION_GET_CONTENT).apply { type = "*/*" }, - "Select a file" - ), - pendingPickerAction!!.first - ) - }) { - Text("Import from file") - } - } - } - } - } else { - Column( - modifier = Modifier.fillMaxSize(), - ) { - Row( - modifier = Modifier.fillMaxWidth(), - horizontalArrangement = Arrangement.spacedBy(8.dp) - ) { - IconButton( - modifier = Modifier.padding(8.dp), - onClick = { - fetchedFriends = null - } - ) { - Icon(Icons.AutoMirrored.Default.ArrowBack, contentDescription = "Back") - } - } - LazyColumn( - modifier = Modifier.weight(1f).padding(8.dp) - ) { - item { - if (fetchedFriends?.isEmpty() == true) { - Text("No friends found", modifier = Modifier.padding(8.dp)) - } - } - items(fetchedFriends ?: emptyList()) { userId -> - fun fetchLocalLinkType(): FriendLinkType? { - return context.database.getFriendInfo(userId)?.friendLinkType?.let { FriendLinkType.fromValue(it) } - } - - var friendSnapchatter by remember(userId) { mutableStateOf(null) } - var failedToFetch by remember(userId) { mutableStateOf(false) } - var friendLinkType by remember(userId) { mutableStateOf(fetchLocalLinkType()) } - - LaunchedEffect(userId) { - launch(Dispatchers.IO) { - friendSnapchatter = userIdToSnapchatter.getOrPut(userId) { - context.feature(Messaging::class).fetchSnapchatterInfos(listOf(userId)).firstOrNull() ?: run { - failedToFetch = true - return@launch - } - } - } - } - - Row( - modifier = Modifier - .fillMaxWidth() - .padding(6.dp), - verticalAlignment = Alignment.CenterVertically - ){ - Column( - modifier = Modifier.weight(1f) - ) { - friendSnapchatter?.let { snapchatter -> - Text(snapchatter.displayName?.let { "$it (${snapchatter.username}) " } ?: snapchatter.username ?: "Unknown") - } - Text(userId, fontSize = 12.sp, fontWeight = FontWeight.Light) - } - - if (friendSnapchatter != null && friendLinkType != FriendLinkType.FOLLOWING) { - Button( - enabled = friendLinkType != FriendLinkType.MUTUAL, - onClick = { - val prevLinkType = fetchLocalLinkType() - if (prevLinkType == FriendLinkType.MUTUAL || pendingFriendRequests[userId]?.isActive == true) return@Button - addFriend(userId) - pendingFriendRequests[userId] = coroutineScope.launch { - withTimeout(10000) { - while (fetchLocalLinkType()?.value == prevLinkType?.value) { - delay(500) - } - } - }.apply { - invokeOnCompletion { - pendingFriendRequests.remove(userId) - friendLinkType = fetchLocalLinkType() - } - } - } - ) { - if (friendLinkType == FriendLinkType.MUTUAL) { - Text("Added") - } else if (pendingFriendRequests[userId]?.isActive == true) { - CircularProgressIndicator(color = MaterialTheme.colorScheme.onPrimary, modifier = Modifier.size(20.dp), strokeWidth = 1.dp) - } else { - Text("Add") - } - } - } - } - } - } - } - } - } - - override fun run() { - context.coroutineScope.launch(Dispatchers.Main) { - createComposeAlertDialog(context.mainActivity!!) { - ManagerDialog() - }.apply { - setCanceledOnTouchOutside(false) - show() - } - } - } -} \ No newline at end of file diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/event/events/impl/BuildMessageEvent.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/event/events/impl/BuildMessageEvent.kt deleted file mode 100644 index 7133be16..00000000 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/event/events/impl/BuildMessageEvent.kt +++ /dev/null @@ -1,8 +0,0 @@ -package me.rhunk.snapenhance.core.event.events.impl - -import me.rhunk.snapenhance.core.event.Event -import me.rhunk.snapenhance.core.wrapper.impl.Message - -class BuildMessageEvent( - val message: Message -): Event() \ No newline at end of file diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/event/events/impl/ConversationUpdateEvent.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/event/events/impl/ConversationUpdateEvent.kt deleted file mode 100644 index 276cda29..00000000 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/event/events/impl/ConversationUpdateEvent.kt +++ /dev/null @@ -1,10 +0,0 @@ -package me.rhunk.snapenhance.core.event.events.impl - -import me.rhunk.snapenhance.core.event.events.AbstractHookEvent -import me.rhunk.snapenhance.core.wrapper.impl.Message - -class ConversationUpdateEvent( - val conversationId: String, - val conversation: Any?, - val messages: List -) : AbstractHookEvent() \ No newline at end of file diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/event/events/impl/NativeUnaryCallEvent.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/event/events/impl/NativeUnaryCallEvent.kt deleted file mode 100644 index 5d08af39..00000000 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/event/events/impl/NativeUnaryCallEvent.kt +++ /dev/null @@ -1,8 +0,0 @@ -package me.rhunk.snapenhance.core.event.events.impl - -import me.rhunk.snapenhance.core.event.events.AbstractHookEvent - -class NativeUnaryCallEvent( - val uri: String, - var buffer: ByteArray -) : AbstractHookEvent() \ No newline at end of file diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/event/events/impl/OnSnapInteractionEvent.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/event/events/impl/OnSnapInteractionEvent.kt deleted file mode 100644 index 9ef0784c..00000000 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/event/events/impl/OnSnapInteractionEvent.kt +++ /dev/null @@ -1,10 +0,0 @@ -package me.rhunk.snapenhance.core.event.events.impl - -import me.rhunk.snapenhance.core.event.events.AbstractHookEvent -import me.rhunk.snapenhance.core.wrapper.impl.SnapUUID - -class OnSnapInteractionEvent( - val interactionType: String, - val conversationId: SnapUUID, - val messageId: Long -) : AbstractHookEvent() \ No newline at end of file diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/downloader/ProfilePictureDownloader.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/downloader/ProfilePictureDownloader.kt deleted file mode 100644 index 1b95961e..00000000 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/downloader/ProfilePictureDownloader.kt +++ /dev/null @@ -1,71 +0,0 @@ -package me.rhunk.snapenhance.core.features.impl.downloader - -import android.annotation.SuppressLint -import android.widget.Button -import android.widget.RelativeLayout -import me.rhunk.snapenhance.common.util.protobuf.ProtoReader -import me.rhunk.snapenhance.core.event.events.impl.AddViewEvent -import me.rhunk.snapenhance.core.event.events.impl.NetworkApiRequestEvent -import me.rhunk.snapenhance.core.features.Feature -import me.rhunk.snapenhance.core.ui.ViewAppearanceHelper - -class ProfilePictureDownloader : Feature("ProfilePictureDownloader") { - @SuppressLint("SetTextI18n") - override fun init() { - if (!context.config.downloader.downloadProfilePictures.get()) return - - var friendUsername: String? = null - var backgroundUrl: String? = null - var avatarUrl: String? = null - - onNextActivityCreate(defer = true) { - context.event.subscribe(AddViewEvent::class) { event -> - if (event.view::class.java.name != "com.snap.unifiedpublicprofile.UnifiedPublicProfileView") return@subscribe - - event.parent.addView(Button(event.parent.context).apply { - text = this@ProfilePictureDownloader.context.translation["profile_picture_downloader.button"] - layoutParams = RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT).apply { - setMargins(0, 200, 0, 0) - } - setOnClickListener { - ViewAppearanceHelper.newAlertDialogBuilder( - this@ProfilePictureDownloader.context.mainActivity!! - ).apply { - setTitle(this@ProfilePictureDownloader.context.translation["profile_picture_downloader.title"]) - val choices = mutableMapOf() - backgroundUrl?.let { choices["background_option"] = it } - avatarUrl?.let { choices["avatar_option"] = it } - - setItems(choices.keys.map { - this@ProfilePictureDownloader.context.translation["profile_picture_downloader.$it"] - }.toTypedArray()) { _, which -> - runCatching { - this@ProfilePictureDownloader.context.feature(MediaDownloader::class).downloadProfilePicture( - choices.values.elementAt(which), - friendUsername!! - ) - }.onFailure { - this@ProfilePictureDownloader.context.log.error("Failed to download profile picture", it) - } - } - }.show() - } - }) - } - - - context.event.subscribe(NetworkApiRequestEvent::class) { event -> - if (!event.url.endsWith("/rpc/getPublicProfile")) return@subscribe - event.onSuccess { buffer -> - ProtoReader(buffer ?: return@onSuccess).followPath(1, 1, 2) { - friendUsername = getString(2) ?: return@followPath - followPath(4) { - backgroundUrl = getString(2) - avatarUrl = getString(100) - } - } - } - } - } - } -} diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/experiments/AddFriendSourceSpoof.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/experiments/AddFriendSourceSpoof.kt deleted file mode 100644 index b05dc079..00000000 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/experiments/AddFriendSourceSpoof.kt +++ /dev/null @@ -1,72 +0,0 @@ -package me.rhunk.snapenhance.core.features.impl.experiments - -import me.rhunk.snapenhance.common.data.FriendAddSource -import me.rhunk.snapenhance.common.util.protobuf.ProtoEditor -import me.rhunk.snapenhance.core.event.events.impl.UnaryCallEvent -import me.rhunk.snapenhance.core.features.Feature -import me.rhunk.snapenhance.core.util.hook.HookStage -import me.rhunk.snapenhance.core.util.hook.hookConstructor -import me.rhunk.snapenhance.mapper.impl.FriendRelationshipChangerMapper - -class AddFriendSourceSpoof : Feature("AddFriendSourceSpoof") { - var friendRelationshipChangerInstance: Any? = null - private set - - override fun init() { - onNextActivityCreate { - context.mappings.useMapper(FriendRelationshipChangerMapper::class) { - classReference.get()?.hookConstructor(HookStage.AFTER) { param -> - friendRelationshipChangerInstance = param.thisObject() - } - } - - context.event.subscribe(UnaryCallEvent::class) { event -> - if (event.uri != "/snapchat.friending.server.FriendAction/AddFriends") return@subscribe - val spoofedSource = context.config.experimental.addFriendSourceSpoof.getNullable() ?: return@subscribe - event.buffer = ProtoEditor(event.buffer).apply { - edit { - fun setPage(value: String) { - remove(1) - addString(1, value) - } - - editEach(2) { - remove(3) // remove suggestion token - fun setSource(source: FriendAddSource) { - remove(2) - addVarInt(2, source.id) - } - - when (spoofedSource) { - "added_by_group_chat" -> { - setPage("group_profile") - setSource(FriendAddSource.GROUP_CHAT) - } - "added_by_username" -> { - setPage("search") - setSource(FriendAddSource.USERNAME) - } - "added_by_qr_code" -> { - setPage("scan_snapcode") - setSource(FriendAddSource.QR_CODE) - } - "added_by_mention" -> { - setPage("context_card") - setSource(FriendAddSource.MENTION) - } - "added_by_community" -> { - setPage("profile") - setSource(FriendAddSource.COMMUNITY) - } - "added_by_quick_add" -> { - setPage("add_friends_button_on_top_bar_on_friends_feed") - setSource(FriendAddSource.SUGGESTED) - } - } - } - } - }.toByteArray() - } - } - } -} \ No newline at end of file diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/experiments/AutoOpenSnaps.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/experiments/AutoOpenSnaps.kt deleted file mode 100644 index 6da7f02b..00000000 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/experiments/AutoOpenSnaps.kt +++ /dev/null @@ -1,121 +0,0 @@ -package me.rhunk.snapenhance.core.features.impl.experiments - -import android.app.Notification -import android.app.NotificationChannel -import android.app.NotificationManager -import kotlinx.coroutines.CoroutineStart -import kotlinx.coroutines.delay -import kotlinx.coroutines.flow.MutableSharedFlow -import kotlinx.coroutines.launch -import me.rhunk.snapenhance.common.data.ContentType -import me.rhunk.snapenhance.common.data.MessageUpdate -import me.rhunk.snapenhance.common.data.MessagingRuleType -import me.rhunk.snapenhance.core.event.events.impl.BuildMessageEvent -import me.rhunk.snapenhance.core.features.MessagingRuleFeature -import me.rhunk.snapenhance.core.features.impl.messaging.Messaging -import java.util.concurrent.atomic.AtomicInteger -import kotlin.coroutines.resume -import kotlin.coroutines.suspendCoroutine -import kotlin.random.Random - -class AutoOpenSnaps: MessagingRuleFeature("Auto Open Snaps", MessagingRuleType.AUTO_OPEN_SNAPS) { - private val snapQueue = MutableSharedFlow>() - private var snapQueueSize = AtomicInteger(0) - private val openedSnaps = mutableListOf() - - private val notificationManager by lazy { - context.androidContext.getSystemService(NotificationManager::class.java) - } - - private val notificationId by lazy { Random.nextInt() } - - private val channelId by lazy { - "auto_open_snaps".also { - notificationManager.createNotificationChannel( - NotificationChannel(it, context.translation["auto_open_snaps.title"], NotificationManager.IMPORTANCE_LOW) - ) - } - } - - private fun sendStatusNotification(count: Int) { - notificationManager.notify( - notificationId, - Notification.Builder(context.androidContext, channelId) - .setContentTitle(context.translation["auto_open_snaps.title"]) - .setContentText(context.translation.format("auto_open_snaps.notification_content", "count" to count.toString())) - .setSmallIcon(android.R.drawable.ic_menu_view) - .setProgress(0, 0, true) - .build().apply { - flags = flags or Notification.FLAG_ONLY_ALERT_ONCE - } - ) - } - - override fun init() { - if (getRuleState() == null) return - val messaging = context.feature(Messaging::class) - - context.coroutineScope.launch(start = CoroutineStart.UNDISPATCHED) { - snapQueue.collect { (conversationId, messageId) -> - snapQueueSize.addAndGet(-1) - delay(Random.nextLong(50, 100)) - var result: String? - - for (i in 0..5) { - while (context.isMainActivityPaused || messaging.conversationManager == null) { - delay(2000) - } - - result = suspendCoroutine { continuation -> - runCatching { - messaging.conversationManager?.updateMessage(conversationId, messageId, MessageUpdate.READ) { result -> - continuation.resume(result) - } - }.getOrNull() ?: continuation.resume("ConversationManager is null") - } - - if (result != null && result != "DUPLICATEREQUEST") { - context.log.warn("Failed to mark snap as read, retrying in 3 second") - delay(3000) - continue - } - break - } - - if (snapQueueSize.get() <= 5) { - notificationManager.cancel(notificationId) - synchronized(openedSnaps) { - openedSnaps.clear() - } - } else { - sendStatusNotification(openedSnaps.size) - } - } - } - - context.event.subscribe(BuildMessageEvent::class, priority = 103) { event -> - if (event.message.senderId?.toString() == context.database.myUserId) return@subscribe - val conversationId = event.message.messageDescriptor?.conversationId?.toString() ?: return@subscribe - val clientMessageId = event.message.messageDescriptor?.messageId ?: return@subscribe - - if ( - event.message.messageContent?.contentType != ContentType.SNAP || - event.message.messageMetadata?.openedBy?.any { it.toString() == context.database.myUserId } == true - ) { - return@subscribe - } - - context.coroutineScope.launch { - if (!canUseRule(conversationId)) return@launch - synchronized(openedSnaps) { - if (openedSnaps.contains(clientMessageId)) { - return@launch - } - openedSnaps.add(clientMessageId) - } - snapQueueSize.addAndGet(1) - snapQueue.emit(conversationId to clientMessageId) - } - } - } -} diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/experiments/CustomEmojiFont.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/experiments/CustomEmojiFont.kt deleted file mode 100644 index 58540a47..00000000 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/experiments/CustomEmojiFont.kt +++ /dev/null @@ -1,29 +0,0 @@ -package me.rhunk.snapenhance.core.features.impl.experiments - -import me.rhunk.snapenhance.common.bridge.FileHandleScope -import me.rhunk.snapenhance.core.ModContext -import me.rhunk.snapenhance.core.util.ktx.getFileHandleLocalPath - - -private var cacheFontPath: String? = null - -fun getCustomEmojiFontPath( - context: ModContext -): String? { - val customFileName = context.config.experimental.nativeHooks.customEmojiFont.getNullable()?.takeIf { it.isNotBlank() } ?: return null - if (cacheFontPath == null) { - cacheFontPath = runCatching { - context.fileHandlerManager.getFileHandleLocalPath( - context, - FileHandleScope.USER_IMPORT, - customFileName, - "custom_emoji_font" - ) - }.onFailure { - context.log.error("Failed to get custom emoji font", it) - }.getOrNull() ?: "" - } - return cacheFontPath?.takeIf { it.isNotEmpty() } -} - - diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/experiments/DeviceSpooferHook.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/experiments/DeviceSpooferHook.kt deleted file mode 100644 index 6d18ed71..00000000 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/experiments/DeviceSpooferHook.kt +++ /dev/null @@ -1,57 +0,0 @@ -package me.rhunk.snapenhance.core.features.impl.experiments - -import android.annotation.SuppressLint -import android.location.Location -import android.net.ConnectivityManager -import android.net.Network -import android.net.NetworkCapabilities -import android.os.Build -import me.rhunk.snapenhance.core.features.Feature -import me.rhunk.snapenhance.core.util.LSPatchUpdater -import me.rhunk.snapenhance.core.util.hook.HookStage -import me.rhunk.snapenhance.core.util.hook.hook - -class DeviceSpooferHook: Feature("Device Spoofer") { - private fun hookInstallerPackageName() { - context.androidContext.packageManager::class.java.hook("getInstallerPackageName", HookStage.BEFORE) { param -> - param.setResult("com.android.vending") - } - } - - @SuppressLint("MissingPermission") - override fun init() { - // force installer package name for lspatch users - if (LSPatchUpdater.HAS_LSPATCH) { - hookInstallerPackageName() - } - - if (context.config.experimental.spoof.globalState != true) return - - val removeMockLocationFlag by context.config.experimental.spoof.removeMockLocationFlag - val overridePlayStoreInstallerPackageName by context.config.experimental.spoof.overridePlayStoreInstallerPackageName - val removeVpnTransportFlag by context.config.experimental.spoof.removeVpnTransportFlag - - //Installer package name - if(overridePlayStoreInstallerPackageName) { - hookInstallerPackageName() - } - - if (removeMockLocationFlag) { - Location::class.java.hook("isMock", HookStage.BEFORE) { param -> - param.setResult(false) - } - } - - if (removeVpnTransportFlag) { - ConnectivityManager::class.java.hook("getAllNetworks", HookStage.AFTER) { param -> - val instance = param.thisObject() as? ConnectivityManager ?: return@hook - val networks = param.getResult() as? Array<*> ?: return@hook - - param.setResult(networks.filterIsInstance().filter { network -> - val capabilities = instance.getNetworkCapabilities(network) ?: return@filter false - !capabilities.hasTransport(NetworkCapabilities.TRANSPORT_VPN) - }.toTypedArray()) - } - } - } -} \ No newline at end of file diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/messaging/SendOverride.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/messaging/SendOverride.kt deleted file mode 100644 index 1ff23c7f..00000000 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/messaging/SendOverride.kt +++ /dev/null @@ -1,379 +0,0 @@ -package me.rhunk.snapenhance.core.features.impl.messaging - -import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.* -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.MusicNote -import androidx.compose.material.icons.filled.Photo -import androidx.compose.material.icons.filled.PhotoCamera -import androidx.compose.material.icons.filled.WarningAmber -import androidx.compose.material3.* -import androidx.compose.runtime.* -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.vector.ImageVector -import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.text.style.TextAlign -import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp -import me.rhunk.snapenhance.common.data.ContentType -import me.rhunk.snapenhance.common.ui.createComposeAlertDialog -import me.rhunk.snapenhance.common.util.protobuf.ProtoEditor -import me.rhunk.snapenhance.common.util.protobuf.ProtoReader -import me.rhunk.snapenhance.common.util.protobuf.ProtoWriter -import me.rhunk.snapenhance.core.event.events.impl.MediaUploadEvent -import me.rhunk.snapenhance.core.event.events.impl.NativeUnaryCallEvent -import me.rhunk.snapenhance.core.event.events.impl.SendMessageWithContentEvent -import me.rhunk.snapenhance.core.features.Feature -import me.rhunk.snapenhance.core.features.impl.experiments.MediaFilePicker -import me.rhunk.snapenhance.core.messaging.MessageSender -import me.rhunk.snapenhance.core.util.ktx.getObjectFieldOrNull -import java.util.Locale -import kotlin.time.DurationUnit -import kotlin.time.toDuration - - -class SendOverride : Feature("Send Override") { - private var selectedType by mutableStateOf("SNAP") - private var customDuration by mutableFloatStateOf(10f) - - @OptIn(ExperimentalLayoutApi::class) - override fun init() { - val stripMediaMetadata = context.config.messaging.stripMediaMetadata.get() - var postSavePolicy: Int? = null - - val configOverrideType = context.config.messaging.galleryMediaSendOverride.getNullable() - if (configOverrideType == null && stripMediaMetadata.isEmpty()) return - - context.event.subscribe(MediaUploadEvent::class) { event -> - ProtoReader(event.localMessageContent.content!!).followPath(11, 5)?.let { snapDocPlayback -> - event.onMediaUploaded { result -> - result.messageContent.content = ProtoEditor(result.messageContent.content!!).apply { - edit(11, 5) { - edit(1) { - edit(1) { - snapDocPlayback.getVarInt(2, 99)?.let { customDuration -> - remove(15) - addVarInt(15, customDuration) - } - remove(27) - remove(26) - addBuffer(26, byteArrayOf()) - } - } - - // set back the original snap duration - snapDocPlayback.getByteArray(2)?.let { - val originalHasSound = firstOrNull(2)?.toReader()?.getVarInt(5) - remove(2) - addBuffer(2, it) - - originalHasSound?.let { hasSound -> - edit(2) { - remove(5) - addVarInt(5, hasSound) - } - } - } - } - - if (stripMediaMetadata.isNotEmpty()) { - when (result.messageContent.contentType) { - ContentType.SNAP, ContentType.EXTERNAL_MEDIA -> { - edit(*(if (result.messageContent.contentType == ContentType.SNAP) intArrayOf(11) else intArrayOf(3, 3))) { - if (stripMediaMetadata.contains("hide_caption_text")) { - edit(5) { - editEach(1) { - remove(2) - } - } - } - if (stripMediaMetadata.contains("hide_snap_filters")) { - remove(9) - remove(11) - } - if (stripMediaMetadata.contains("hide_extras")) { - remove(13) - edit(5, 1) { - remove(2) - } - } - } - } - ContentType.NOTE -> { - if (stripMediaMetadata.contains("remove_audio_note_duration")) { - edit(6, 1, 1) { - remove(13) - } - } - if (stripMediaMetadata.contains("remove_audio_note_transcript_capability")) { - edit(6, 1) { - remove(3) - } - } - } - else -> {} - } - } - - edit(11, 5, 2) { - remove(99) - } - }.toByteArray() - } - } - } - - if (configOverrideType == null) return - - context.event.subscribe(NativeUnaryCallEvent::class) { event -> - if (event.uri != "/messagingcoreservice.MessagingCoreService/CreateContentMessage") return@subscribe - postSavePolicy?.let { savePolicy -> - context.log.verbose("postSavePolicy=$savePolicy") - event.buffer = ProtoEditor(event.buffer).apply { - edit(4) { - remove(7) - addVarInt(7, savePolicy) - } - - // remove Keep Snaps in Chat ability - if (savePolicy == 1/* PROHIBITED */) { - edit(6, 9) { - remove(1) - } - } - }.toByteArray() - } - } - - context.event.subscribe(SendMessageWithContentEvent::class) { event -> - postSavePolicy = null - if (event.destinations.stories?.isNotEmpty() == true && event.destinations.conversations?.isEmpty() == true) return@subscribe - val localMessageContent = event.messageContent - if (localMessageContent.contentType != ContentType.EXTERNAL_MEDIA && localMessageContent.instanceNonNull().getObjectFieldOrNull("mExternalContentMetadata") == null) return@subscribe - - //prevent story replies - val messageProtoReader = ProtoReader(localMessageContent.content ?: return@subscribe) - if (messageProtoReader.contains(7)) return@subscribe - - event.canceled = true - - fun sendMedia(overrideType: String, snapDurationMs: Int?): Boolean { - if (overrideType != "ORIGINAL" && (messageProtoReader.followPath(3)?.getCount(3) ?: 0) > 1) { - context.inAppOverlay.showStatusToast( - icon = Icons.Default.WarningAmber, - context.translation["gallery_media_send_override.multiple_media_toast"] - ) - return false - } - - when (overrideType) { - "SNAP", "SAVEABLE_SNAP" -> { - postSavePolicy = if (overrideType == "SAVEABLE_SNAP") 3 /* VIEW_SESSION */ else 1 /* PROHIBITED */ - - val extras = messageProtoReader.followPath(3, 3, 13)?.getBuffer() - - if (localMessageContent.contentType != ContentType.SNAP) { - localMessageContent.content = ProtoWriter().apply { - from(11) { - from(5) { - from(1) { - from(1) { - addVarInt(2, 0) - addVarInt(12, 0) - addVarInt(15, 0) - } - addVarInt(6, 1) - } - from(2) {} - } - extras?.let { - addBuffer(13, it) - } - from(22) {} - } - }.toByteArray() - } - - localMessageContent.contentType = ContentType.SNAP - localMessageContent.content = ProtoEditor(localMessageContent.content!!).apply { - edit(11, 5, 2) { - arrayOf(6, 7, 8).forEach { remove(it) } - addVarInt(5, messageProtoReader.getVarInt(3, 3, 5, 2, 5) ?: messageProtoReader.getVarInt(11, 5, 2, 5) ?: 1) - // set snap duration - if (snapDurationMs != null) { - addVarInt(8, snapDurationMs / 1000) - if (snapDurationMs / 1000 <= 0) { - addVarInt(99, snapDurationMs) - } - } else { - addBuffer(6, byteArrayOf()) - } - } - - // set app source - edit(11, 22) { - remove(4) - addVarInt(4, 5) // APP_SOURCE_CAMERA - } - }.toByteArray() - } - "NOTE" -> { - localMessageContent.contentType = ContentType.NOTE - localMessageContent.content = - MessageSender.audioNoteProto( - messageProtoReader.getVarInt(3, 3, 5, 1, 1, 15) ?: context.feature(MediaFilePicker::class).lastMediaDuration ?: 0, - Locale.getDefault().toLanguageTag() - ) - } - } - - return true - } - - if (configOverrideType != "always_ask") { - if (sendMedia(configOverrideType, 10)) { - event.invokeOriginal() - } - return@subscribe - } - - context.runOnUiThread { - createComposeAlertDialog(context.mainActivity!!) { alertDialog -> - val mainTranslation = remember { - context.translation.getCategory("send_override_dialog") - } - - @Composable - fun ActionTile( - modifier: Modifier = Modifier, - selected: Boolean = false, - icon: ImageVector, - title: String, - onClick: () -> Unit - ) { - Card( - modifier = modifier, - onClick = onClick, - elevation = if (selected) CardDefaults.elevatedCardElevation(disabledElevation = 3.dp) else CardDefaults.cardElevation(), - colors = if (selected) CardDefaults.elevatedCardColors() else CardDefaults.cardColors() - ) { - Column( - modifier = Modifier - .padding(16.dp) - .size(75.dp), - horizontalAlignment = Alignment.CenterHorizontally, - verticalArrangement = Arrangement.Center - ) { - Icon(icon, contentDescription = title, modifier = Modifier - .size(32.dp) - .padding(4.dp)) - Text(title, modifier = Modifier.fillMaxWidth(), fontSize = 12.sp, fontWeight = FontWeight.Light, softWrap = true, lineHeight = 14.sp, textAlign = TextAlign.Center) - } - } - } - - Column( - modifier = Modifier - .fillMaxWidth() - .padding(8.dp), - verticalArrangement = Arrangement.spacedBy(8.dp) - ) { - val translation = remember { - context.translation.getCategory("features.options.gallery_media_send_override") - } - - Text(fontSize = 20.sp, fontWeight = FontWeight.Medium, text = "Send as ${ - translation[selectedType]}", modifier = Modifier.padding(5.dp)) - FlowRow( - modifier = Modifier.fillMaxWidth(), - horizontalArrangement = Arrangement.SpaceEvenly - ) { - ActionTile(selected = selectedType == "ORIGINAL", icon = Icons.Filled.Photo, title = - translation["ORIGINAL"]) { - selectedType = "ORIGINAL" - } - ActionTile(selected = selectedType == "SNAP" || selectedType == "SAVEABLE_SNAP", icon = Icons.Filled.PhotoCamera, title = translation["SNAP"]) { - selectedType = "SNAP" - } - ActionTile(selected = selectedType == "NOTE", icon = Icons.Filled.MusicNote, title = translation["NOTE"]) { - selectedType = "NOTE" - } - } - - fun convertDuration(duration: Float): Int? { - return when { - duration in -2f..-1f -> 100 - duration in -1f..-0f -> 250 - duration in -0f..1f -> 500 - duration >= 11f -> null - else -> ((duration * 1000).toInt() / 1000) * 1000 - } - } - - when (selectedType) { - "SNAP", "SAVEABLE_SNAP" -> { - fun toggleSaveable() { - selectedType = if (selectedType == "SAVEABLE_SNAP") "SNAP" else "SAVEABLE_SNAP" - } - Row( - modifier = Modifier.fillMaxWidth().clickable { - toggleSaveable() - }, - horizontalArrangement = Arrangement.spacedBy(4.dp), - verticalAlignment = Alignment.CenterVertically - ){ - Checkbox( - checked = selectedType == "SAVEABLE_SNAP", - onCheckedChange = { - toggleSaveable() - } - ) - Text(text = mainTranslation["saveable_snap_hint"], lineHeight = 15.sp) - } - Column( - modifier = Modifier.padding(start = 8.dp) - ) { - Text( - text = mainTranslation.format("duration", - "duration" to (convertDuration(customDuration)?.toDuration(DurationUnit.MILLISECONDS)?.toString(DurationUnit.SECONDS, 2) ?: mainTranslation["unlimited_duration"]) - ) - ) - Slider( - modifier = Modifier.fillMaxWidth(), - enabled = selectedType != "SAVEABLE_SNAP", - value = customDuration, - onValueChange = { - customDuration = it - }, - valueRange = -2f..11f, - ) - } - } - } - - Row( - modifier = Modifier.fillMaxWidth(), - horizontalArrangement = Arrangement.SpaceEvenly, - verticalAlignment = Alignment.CenterVertically - ) { - OutlinedButton(onClick = { - alertDialog.dismiss() - }) { - Text(context.translation["button.cancel"]) - } - Button(onClick = { - alertDialog.dismiss() - if (sendMedia(selectedType, if (selectedType != "SAVEABLE_SNAP" ) convertDuration(customDuration) else null)) { - event.invokeOriginal() - } - }) { - Text(context.translation["button.send"]) - } - } - } - }.show() - } - } - } -} \ No newline at end of file diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/tweaks/UnsaveableMessages.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/tweaks/UnsaveableMessages.kt deleted file mode 100644 index bc73dac1..00000000 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/tweaks/UnsaveableMessages.kt +++ /dev/null @@ -1,44 +0,0 @@ -package me.rhunk.snapenhance.core.features.impl.tweaks - -import me.rhunk.snapenhance.common.data.ContentType -import me.rhunk.snapenhance.common.data.MessagingRuleType -import me.rhunk.snapenhance.common.util.protobuf.ProtoEditor -import me.rhunk.snapenhance.common.util.protobuf.ProtoReader -import me.rhunk.snapenhance.core.event.events.impl.NativeUnaryCallEvent -import me.rhunk.snapenhance.core.features.MessagingRuleFeature -import me.rhunk.snapenhance.core.wrapper.impl.SnapUUID - -class UnsaveableMessages : MessagingRuleFeature( - "Unsaveable Messages", - MessagingRuleType.UNSAVEABLE_MESSAGES -) { - override fun init() { - if (context.config.rules.getRuleState(MessagingRuleType.UNSAVEABLE_MESSAGES) == null) return - - context.event.subscribe(NativeUnaryCallEvent::class) { event -> - if (event.uri != "/messagingcoreservice.MessagingCoreService/CreateContentMessage") return@subscribe - - val protoReader = ProtoReader(event.buffer) - val conversationIds = mutableListOf() - - protoReader.eachBuffer(3) { - if (contains(2)) { - return@eachBuffer - } - conversationIds.add(SnapUUID(getByteArray(1, 1, 1) ?: return@eachBuffer).toString()) - } - - if (conversationIds.all { canUseRule(it) }) { - event.buffer = ProtoEditor(event.buffer).apply { - edit(4) { - val contentType = firstOrNull(2)?.value - if (contentType != ContentType.STATUS.id.toLong() && firstOrNull(4)?.toReader()?.contains(11) != true && contentType != null) { - remove(7) - addVarInt(7, 3) // set savePolicy to VIEW_SESSION except for status and snaps - } - } - }.toByteArray() - } - } - } -} \ No newline at end of file diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/ui/ConversationToolbox.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/ui/ConversationToolbox.kt deleted file mode 100644 index 62673177..00000000 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/ui/ConversationToolbox.kt +++ /dev/null @@ -1,172 +0,0 @@ -package me.rhunk.snapenhance.core.features.impl.ui - -import android.annotation.SuppressLint -import android.app.AlertDialog -import android.view.Gravity -import android.view.ViewGroup -import android.widget.FrameLayout -import android.widget.LinearLayout -import android.widget.TextView -import androidx.compose.foundation.Image -import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.* -import androidx.compose.foundation.rememberScrollState -import androidx.compose.foundation.verticalScroll -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.KeyboardArrowDown -import androidx.compose.material.icons.filled.KeyboardArrowUp -import androidx.compose.material3.Card -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.runtime.mutableStateMapOf -import androidx.compose.runtime.remember -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.ColorFilter -import androidx.compose.ui.platform.LocalConfiguration -import androidx.compose.ui.text.font.FontStyle -import androidx.compose.ui.text.style.TextAlign -import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp -import androidx.compose.ui.unit.times -import me.rhunk.snapenhance.common.scripting.ui.EnumScriptInterface -import me.rhunk.snapenhance.common.scripting.ui.InterfaceManager -import me.rhunk.snapenhance.common.scripting.ui.ScriptInterface -import me.rhunk.snapenhance.common.ui.createComposeAlertDialog -import me.rhunk.snapenhance.core.event.events.impl.AddViewEvent -import me.rhunk.snapenhance.core.features.Feature -import me.rhunk.snapenhance.core.features.impl.messaging.Messaging - - -data class ComposableMenu( - val title: String, - val filter: (conversationId: String) -> Boolean, - val composable: @Composable (alertDialog: AlertDialog, conversationId: String) -> Unit, -) - -class ConversationToolbox : Feature("Conversation Toolbox") { - private val composableList = mutableListOf() - private val expandedComposableCache = mutableStateMapOf() - - fun addComposable(title: String, filter: (conversationId: String) -> Boolean = { true }, composable: @Composable (alertDialog: AlertDialog, conversationId: String) -> Unit) { - composableList.add( - ComposableMenu(title, filter, composable) - ) - } - - @SuppressLint("SetTextI18n") - override fun init() { - onNextActivityCreate { - context.event.subscribe(AddViewEvent::class) { event -> - if (composableList.isEmpty()) return@subscribe - - val chatInputBar by getChatInputBar(event) ?: return@subscribe - - chatInputBar?.addView(FrameLayout(event.view.context).apply { - layoutParams = LinearLayout.LayoutParams( - ViewGroup.LayoutParams.WRAP_CONTENT, - (52 * context.resources.displayMetrics.density).toInt(), - ).apply { - gravity = Gravity.BOTTOM - } - setPadding(25, 0, 25, 0) - - addView(TextView(event.view.context).apply { - layoutParams = FrameLayout.LayoutParams( - ViewGroup.LayoutParams.WRAP_CONTENT, - ViewGroup.LayoutParams.WRAP_CONTENT, - ).apply { - gravity = Gravity.CENTER_VERTICAL - } - setOnClickListener { - openToolbox() - } - textSize = 21f - text = "\uD83E\uDDF0" - }) - }) - } - - context.scriptRuntime.eachModule { - val interfaceManager = getBinding(InterfaceManager::class)?.takeIf { - it.hasInterface(EnumScriptInterface.CONVERSATION_TOOLBOX) - } ?: return@eachModule - addComposable("\uD83D\uDCDC ${moduleInfo.displayName}") { alertDialog, conversationId -> - ScriptInterface(remember { - interfaceManager.buildInterface(EnumScriptInterface.CONVERSATION_TOOLBOX, mapOf( - "alertDialog" to alertDialog, - "conversationId" to conversationId, - )) - } ?: return@addComposable) - } - } - } - } - - private fun openToolbox() { - val openedConversationId = context.feature(Messaging::class).openedConversationUUID?.toString() ?: run { - context.shortToast("You must open a conversation first") - return - } - - createComposeAlertDialog(context.mainActivity!!) { alertDialog -> - Column( - modifier = Modifier - .fillMaxWidth() - .heightIn( - min = 100.dp, - max = LocalConfiguration.current.screenHeightDp * 0.8f.dp - ) - .verticalScroll(rememberScrollState()) - ) { - Text("Conversation Toolbox", fontSize = 20.sp, modifier = Modifier - .fillMaxWidth() - .padding(10.dp), textAlign = TextAlign.Center) - Spacer(modifier = Modifier.height(10.dp)) - - composableList.reversed().forEach { (title, filter, composable) -> - if (!filter(openedConversationId)) return@forEach - Card( - modifier = Modifier - .fillMaxWidth() - .padding(5.dp), - shape = MaterialTheme.shapes.medium - ) { - Row( - modifier = Modifier - .clickable { - expandedComposableCache[title] = !(expandedComposableCache[title] ?: false) - } - .fillMaxWidth() - .padding(10.dp), - horizontalArrangement = Arrangement.spacedBy(10.dp), - verticalAlignment = Alignment.CenterVertically, - ) { - Image( - imageVector = if (expandedComposableCache[title] == true) Icons.Filled.KeyboardArrowDown else Icons.Filled.KeyboardArrowUp, - contentDescription = null, - colorFilter = ColorFilter.tint(MaterialTheme.colorScheme.onSurface), - ) - Text(title, fontSize = 16.sp, fontStyle = FontStyle.Italic) - } - if (expandedComposableCache[title] == true) { - Column( - modifier = Modifier - .fillMaxWidth() - .padding(10.dp) - ) { - runCatching { - composable(alertDialog, openedConversationId) - }.onFailure { throwable -> - Text("Failed to load composable: ${throwable.message}") - context.log.error("Failed to load composable: ${throwable.message}", throwable) - } - } - } - } - } - } - }.show() - } -} \ No newline at end of file diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/ui/CustomTheming.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/ui/CustomTheming.kt deleted file mode 100644 index 01668ee3..00000000 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/ui/CustomTheming.kt +++ /dev/null @@ -1,42 +0,0 @@ -package me.rhunk.snapenhance.core.features.impl.ui - -import android.content.res.TypedArray -import android.util.TypedValue -import me.rhunk.snapenhance.core.features.Feature -import me.rhunk.snapenhance.core.util.hook.HookStage -import me.rhunk.snapenhance.core.util.hook.hook -import me.rhunk.snapenhance.core.util.ktx.getObjectField - -class CustomTheming : Feature("Custom Theming") { - private val amoledBlack = 0xFF000000.toInt() - private val onlyPatchId = 0x7f0404b8 // The attrId you want to patch for AMOLED - - private val colorTypes = setOf( - TypedValue.TYPE_INT_COLOR_ARGB8, - TypedValue.TYPE_INT_COLOR_RGB8, - TypedValue.TYPE_INT_COLOR_ARGB4, - TypedValue.TYPE_INT_COLOR_RGB4 - ) - - override fun init() { - if (!context.config.userInterface.forceAmoledTheme.get()) return - - onNextActivityCreate { - context.androidContext.theme.javaClass - .getMethod("obtainStyledAttributes", IntArray::class.java) - .hook(HookStage.AFTER) { param -> - val array = param.arg(0) - val attrId = array[0] - val result = param.getResult() as TypedArray - val typedArrayData = result.getObjectField("mData") as IntArray - val type = result.getType(0) - if (type in colorTypes && attrId == onlyPatchId) { - typedArrayData[1] = amoledBlack - context.log.error( - "[AMOLED PATCH] Patched ONLY attrId 0x${attrId.toString(16)} to AMOLED black" - ) - } - } - } - } -} diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/ui/SpotlightCommentsUsername.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/ui/SpotlightCommentsUsername.kt deleted file mode 100644 index ac9209d1..00000000 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/ui/SpotlightCommentsUsername.kt +++ /dev/null @@ -1,59 +0,0 @@ -package me.rhunk.snapenhance.core.features.impl.ui - -import android.annotation.SuppressLint -import android.view.ViewGroup -import android.widget.TextView -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.launch -import kotlinx.coroutines.withContext -import me.rhunk.snapenhance.core.event.events.impl.BindViewEvent -import me.rhunk.snapenhance.core.features.Feature -import me.rhunk.snapenhance.core.features.impl.messaging.Messaging -import me.rhunk.snapenhance.core.ui.children -import me.rhunk.snapenhance.core.util.EvictingMap - -class SpotlightCommentsUsername : Feature("SpotlightCommentsUsername") { - private val usernameCache = EvictingMap(150) - - @SuppressLint("SetTextI18n") - override fun init() { - if (!context.config.global.spotlightCommentsUsername.get()) return - - onNextActivityCreate(defer = true) { - val messaging = context.feature(Messaging::class) - context.event.subscribe(BindViewEvent::class) { event -> - val posterUserId = event.prevModel.toString().takeIf { it.startsWith("Comment") } - ?.substringAfter("posterUserId=")?.substringBefore(",")?.substringBefore(")") ?: return@subscribe - - if (posterUserId == "null") return@subscribe - - fun setUsername(username: String) { - usernameCache[posterUserId] = username - val commentsCreatorBadgeTimestamp = (event.view as ViewGroup).children().filterIsInstance() - .getOrNull(1) ?: return - if (commentsCreatorBadgeTimestamp.text.contains(username)) return - commentsCreatorBadgeTimestamp.text = " (${username})" + commentsCreatorBadgeTimestamp?.text.toString() - } - - event.view.post { - usernameCache[posterUserId]?.let { - setUsername(it) - return@post - } - - context.coroutineScope.launch { - val username = runCatching { - messaging.fetchSnapchatterInfos(listOf(posterUserId)).firstOrNull() - }.onFailure { - context.log.error("Failed to fetch snapchatter info for user $posterUserId", it) - }.getOrNull()?.username ?: return@launch - - withContext(Dispatchers.Main) { - setUsername(username) - } - } - } - } - } - } -} \ No newline at end of file diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/ui/InAppOverlay.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/ui/InAppOverlay.kt deleted file mode 100644 index ffc1458a..00000000 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/ui/InAppOverlay.kt +++ /dev/null @@ -1,294 +0,0 @@ -package me.rhunk.snapenhance.core.ui - -import android.app.Activity -import android.view.View -import android.widget.FrameLayout -import androidx.compose.animation.core.Animatable -import androidx.compose.animation.core.LinearEasing -import androidx.compose.animation.core.animateFloatAsState -import androidx.compose.animation.core.tween -import androidx.compose.animation.rememberSplineBasedDecay -import androidx.compose.foundation.ExperimentalFoundationApi -import androidx.compose.foundation.gestures.AnchoredDraggableDefaults -import androidx.compose.foundation.gestures.AnchoredDraggableState -import androidx.compose.foundation.gestures.DraggableAnchors -import androidx.compose.foundation.gestures.Orientation -import androidx.compose.foundation.gestures.anchoredDraggable -import androidx.compose.foundation.layout.* -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.outlined.Warning -import androidx.compose.material3.* -import androidx.compose.runtime.* -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.clip -import androidx.compose.ui.draw.shadow -import androidx.compose.ui.graphics.graphicsLayer -import androidx.compose.ui.graphics.vector.ImageVector -import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.text.style.TextOverflow -import androidx.compose.ui.unit.IntOffset -import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp -import kotlinx.coroutines.delay -import me.rhunk.snapenhance.common.ui.AppMaterialTheme -import me.rhunk.snapenhance.common.ui.createComposeView -import me.rhunk.snapenhance.common.util.ktx.copyToClipboard -import me.rhunk.snapenhance.core.ModContext -import me.rhunk.snapenhance.core.SnapEnhance -import me.rhunk.snapenhance.core.util.hook.HookStage -import me.rhunk.snapenhance.core.util.hook.Hooker -import me.rhunk.snapenhance.core.util.hook.hook -import me.rhunk.snapenhance.core.util.ktx.isDarkTheme -import kotlin.math.roundToInt -import kotlin.random.Random -import kotlin.system.exitProcess - -typealias CustomComposable = @Composable BoxScope.() -> Unit - -class InAppOverlay( - private val context: ModContext -) { - enum class ToastPosition { Start, Center, End } - - companion object { - fun showCrashOverlay(content: String, throwable: Throwable? = null) { - SnapEnhance.classCache.apply { - unifiedGrpcService.hook("unaryCall", HookStage.BEFORE) { param -> - param.setResult(null) - } - networkApi.hook("submit", HookStage.BEFORE) { param -> - param.setResult(null) - } - } - Hooker.ephemeralHook(Activity::class.java, "onPostCreate", HookStage.AFTER) { param -> - val contentView = param.thisObject().findViewById(android.R.id.content) - contentView.children().forEach { it.visibility = View.GONE } - val screenView = createComposeView(param.thisObject()) { - AppMaterialTheme(isDarkTheme = true) { - Surface( - color = MaterialTheme.colorScheme.surface - ) { - Box( - modifier = Modifier.fillMaxSize(), - contentAlignment = Alignment.Center - ) { - Column( - modifier = Modifier - .fillMaxWidth() - .padding(16.dp), - horizontalAlignment = Alignment.CenterHorizontally - ) { - Text( - text = "PurrfectSnap", - fontSize = 28.sp - ) - Spacer(modifier = Modifier.height(40.dp)) - Text( - text = content, - fontSize = 16.sp - ) - Spacer(modifier = Modifier.height(40.dp)) - Row( - modifier = Modifier.fillMaxWidth(), - horizontalArrangement = Arrangement.SpaceEvenly - ) { - throwable?.let { th -> - Button(onClick = { - contentView.context.copyToClipboard(th.stackTraceToString()) - }) { - Text("Copy error to clipboard") - } - } - Button(onClick = { - exitProcess(1) - }) { - Text("Exit") - } - } - } - } - } - } - }.apply { - layoutParams = FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT) - } - contentView.addView(screenView) - } - } - } - inner class Toast( - val composable: @Composable Toast.() -> Unit, - val durationMs: Int - ) { - var shown by mutableStateOf(false) - var visible by mutableStateOf(false) - } - private val toasts = mutableStateListOf() - private val customComposables = mutableStateListOf() - @OptIn(ExperimentalFoundationApi::class) - @Composable - private fun OverlayContent() { - Box( - modifier = Modifier - .fillMaxSize() - .statusBarsPadding() - .navigationBarsPadding(), - ) { - toasts.forEach { toast -> - val animation by animateFloatAsState( - targetValue = if (toast.visible) 1f else 0f, - animationSpec = if (toast.visible) tween(durationMillis = 150) else tween(durationMillis = 300), - label = "toast" - ) - LaunchedEffect(toast) { - toast.visible = true - if (toast.durationMs < 0) return@LaunchedEffect - delay(toast.durationMs.toLong()) - toast.visible = false - delay(1000) - toast.shown = true - synchronized(toasts) { - if (toasts.isNotEmpty() && toasts.all { it.shown }) toasts.clear() - } - } - val deviceWidth = LocalContext.current.resources.displayMetrics.widthPixels - val anchors = DraggableAnchors { - ToastPosition.Start at -deviceWidth.toFloat() - ToastPosition.Center at 0f - ToastPosition.End at deviceWidth.toFloat() - } - val draggableState = remember { - AnchoredDraggableState( - initialValue = ToastPosition.Center, - anchors = anchors, - ) - } - LaunchedEffect(draggableState.currentValue) { - if (draggableState.currentValue != ToastPosition.Center) { - toast.visible = false - } - } - val flingBehavior = AnchoredDraggableDefaults.flingBehavior(draggableState, animationSpec = tween()) - Box( - modifier = Modifier - .fillMaxWidth() - .anchoredDraggable( - state = draggableState, - orientation = Orientation.Horizontal, - flingBehavior = flingBehavior - ) - .offset { - val offsetValue = draggableState.offset - IntOffset(offsetValue.roundToInt(), 0) - } - .graphicsLayer { - alpha = animation - translationY = -100.dp.toPx() * (1 - animation) - } - ) { - if (animation > 0.01f) { - toast.composable(toast) - } - } - } - customComposables.forEach { customComposable -> - customComposable() - } - } - } - private val overlayTag = Random.nextLong() - private fun injectOverlay(activity: Activity) { - val root = activity.findViewById(android.R.id.content) - activity.runOnUiThread { - if (root.findViewWithTag(overlayTag) != null) return@runOnUiThread - root.addView(createComposeView(activity) { - AppMaterialTheme(isDarkTheme = remember { activity.isDarkTheme() }) { - OverlayContent() - } - }.apply { - tag = overlayTag - layoutParams = FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT) - }) - } - } - fun onActivityCreate(activity: Activity) { - injectOverlay(activity) - } - fun addCustomComposable(composable: CustomComposable) { - customComposables.add(composable) - } - fun removeCustomComposable(composable: CustomComposable) { - customComposables.remove(composable) - } - @Composable - private fun DurationProgress( - duration: Int, - modifier: Modifier = Modifier - ) { - val progress = remember { Animatable(1f) } - LaunchedEffect(Unit) { - progress.animateTo( - targetValue = 0f, - animationSpec = tween(durationMillis = duration, easing = LinearEasing) - ) - } - LinearProgressIndicator( - progress = { progress.value }, - modifier = modifier - ) - } - fun showStatusToast( - icon: ImageVector, - text: String, - durationMs: Int = 2000, - showDuration: Boolean = true, - maxLines: Int = 3 - ) { - showToast( - icon = { Icon(icon, contentDescription = "icon", modifier = Modifier.size(32.dp)) }, - text = { - Text(text, modifier = Modifier.fillMaxWidth(), maxLines = maxLines, overflow = TextOverflow.Ellipsis, lineHeight = 15.sp, fontSize = 13.sp) - }, - durationMs = durationMs, - showDuration = showDuration - ) - } - private fun showToast( - icon: @Composable () -> Unit = { - Icon(Icons.Outlined.Warning, contentDescription = "icon", modifier = Modifier.size(32.dp)) - }, - text: @Composable () -> Unit = {}, - durationMs: Int = 3000, - showDuration: Boolean = true, - ) { - injectOverlay(context.mainActivity!!) - toasts.add(Toast( - composable = { - ElevatedCard( - modifier = Modifier - .padding(12.dp) - .shadow(8.dp, RoundedCornerShape(8.dp)) - .fillMaxWidth() - .clip(RoundedCornerShape(8.dp)) - ) { - Row( - horizontalArrangement = Arrangement.spacedBy(16.dp), - verticalAlignment = Alignment.CenterVertically, - modifier = Modifier - .fillMaxWidth() - .padding(12.dp) - ) { - icon() - text() - } - if (showDuration && durationMs > 0) { - DurationProgress(duration = durationMs, modifier = Modifier.fillMaxWidth()) - } - } - }, - durationMs = durationMs - )) - } -} diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/ui/menu/impl/FriendFeedInfoMenu.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/ui/menu/impl/FriendFeedInfoMenu.kt deleted file mode 100644 index 7ba71d41..00000000 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/ui/menu/impl/FriendFeedInfoMenu.kt +++ /dev/null @@ -1,595 +0,0 @@ -package me.rhunk.snapenhance.core.ui.menu.impl - -import android.content.DialogInterface -import android.content.res.Resources -import android.graphics.BitmapFactory -import android.graphics.drawable.BitmapDrawable -import android.graphics.drawable.Drawable -import android.view.Gravity -import android.view.View -import android.view.ViewGroup -import android.widget.FrameLayout -import android.widget.LinearLayout -import android.widget.ScrollView -import androidx.compose.foundation.background -import androidx.compose.foundation.gestures.detectTapGestures -import androidx.compose.foundation.layout.* -import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.items -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.automirrored.outlined.Message -import androidx.compose.material.icons.filled.CheckCircleOutline -import androidx.compose.material.icons.filled.Info -import androidx.compose.material.icons.filled.NotInterested -import androidx.compose.material.icons.outlined.* -import androidx.compose.material3.* -import androidx.compose.runtime.* -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.graphics.vector.ImageVector -import androidx.compose.ui.input.pointer.pointerInput -import androidx.compose.ui.text.TextStyle -import androidx.compose.ui.text.font.Font -import androidx.compose.ui.text.font.FontFamily -import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.text.style.TextAlign -import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.launch -import kotlinx.coroutines.withContext -import me.rhunk.snapenhance.common.data.ContentType -import me.rhunk.snapenhance.common.data.FriendLinkType -import me.rhunk.snapenhance.common.database.impl.ConversationMessage -import me.rhunk.snapenhance.common.database.impl.FriendInfo -import me.rhunk.snapenhance.common.scripting.ui.EnumScriptInterface -import me.rhunk.snapenhance.common.scripting.ui.InterfaceManager -import me.rhunk.snapenhance.common.scripting.ui.ScriptInterface -import me.rhunk.snapenhance.common.ui.createComposeAlertDialog -import me.rhunk.snapenhance.common.ui.createComposeView -import me.rhunk.snapenhance.common.util.protobuf.ProtoReader -import me.rhunk.snapenhance.common.util.snap.BitmojiSelfie -import me.rhunk.snapenhance.core.event.events.impl.AddViewEvent -import me.rhunk.snapenhance.core.features.impl.experiments.EndToEndEncryption -import me.rhunk.snapenhance.core.features.impl.messaging.AutoMarkAsRead -import me.rhunk.snapenhance.core.features.impl.messaging.Messaging -import me.rhunk.snapenhance.core.features.impl.spying.MessageLogger -import me.rhunk.snapenhance.core.ui.ViewAppearanceHelper -import me.rhunk.snapenhance.core.ui.children -import me.rhunk.snapenhance.core.ui.menu.AbstractMenu -import me.rhunk.snapenhance.core.ui.randomTag -import me.rhunk.snapenhance.core.ui.triggerRootCloseTouchEvent -import me.rhunk.snapenhance.core.util.ktx.isDarkTheme -import java.net.HttpURLConnection -import java.net.URL -import java.text.DateFormat -import java.text.SimpleDateFormat -import java.util.Calendar -import java.util.Date -import java.util.Locale - -class FriendFeedInfoMenu : AbstractMenu() { - private fun getImageDrawable(url: String): Drawable { - val connection = URL(url).openConnection() as HttpURLConnection - connection.connect() - val input = connection.inputStream - return BitmapDrawable(Resources.getSystem(), BitmapFactory.decodeStream(input)) - } - - private fun formatDate(timestamp: Long): String? { - return SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.ENGLISH).format(Date(timestamp)) - } - - private fun showProfileInfo(profile: FriendInfo) { - var icon: Drawable? = null - try { - if (profile.bitmojiSelfieId != null && profile.bitmojiAvatarId != null) { - icon = getImageDrawable( - BitmojiSelfie.getBitmojiSelfie( - profile.bitmojiSelfieId.toString(), - profile.bitmojiAvatarId.toString(), - BitmojiSelfie.BitmojiSelfieType.NEW_THREE_D - )!! - ) - } - } catch (e: Throwable) { - context.log.error("Error loading bitmoji selfie", e) - } - val finalIcon = icon - val translation = context.translation.getCategory("profile_info") - val firstCreatedUsername = context.database.getFriendOriginalUsername(profile.mutableUsername.toString()) ?: profile.firstCreatedUsername - - context.runOnUiThread { - val addedTimestamp: Long = profile.addedTimestamp.coerceAtLeast(profile.reverseAddedTimestamp) - val builder = ViewAppearanceHelper.newAlertDialogBuilder(context.mainActivity) - builder.setIcon(finalIcon) - builder.setTitle(profile.displayName ?: profile.username) - - val birthday = Calendar.getInstance() - birthday[Calendar.MONTH] = (profile.birthday shr 32).toInt() - 1 - - builder.setMessage(mapOf( - translation["first_created_username"] to firstCreatedUsername, - translation["mutable_username"] to profile.mutableUsername, - translation["display_name"] to profile.displayName, - translation["added_date"] to formatDate(addedTimestamp).takeIf { addedTimestamp > 0 }, - null to birthday.getDisplayName( - Calendar.MONTH, - Calendar.LONG, - context.translation.loadedLocale - )?.let { - if (profile.birthday == 0L) context.translation["profile_info.hidden_birthday"] - else context.translation.format("profile_info.birthday", - "month" to it, - "day" to profile.birthday.toInt().toString()) - }, - translation["friendship"] to run { - context.translation["friendship_link_type.${FriendLinkType.fromValue(profile.friendLinkType).shortName}"] - }.takeIf { - if (profile.friendLinkType == FriendLinkType.MUTUAL.value) addedTimestamp.toInt() > 0 else true - }, - translation["add_source"] to context.database.getAddSource(profile.userId!!)?.takeIf { it.isNotEmpty() }, - translation["snapchat_plus"] to run { - translation.getCategory("snapchat_plus_state")[if (profile.postViewEmoji != null) "subscribed" else "not_subscribed"] - } - ).filterValues { it != null }.map { - line -> "${line.key?.let { "$it: " } ?: ""}${line.value}" - }.joinToString("\n")) - - builder.setPositiveButton( - "OK" - ) { dialog: DialogInterface, _: Int -> dialog.dismiss() } - builder.show() - } - } - - private suspend fun showConversationPreview( - targetUser: String?, - conversationId: String - ) { - val friendInfo = targetUser?.let { context.database.getFriendInfo(it) } - val conversationInfo = conversationId.takeIf { targetUser == null }?.let { context.database.getFeedEntryByConversationId(it) } - val participants by lazy { - context.database.getConversationParticipants(conversationId)!! - .map { context.database.getFriendInfo(it)!! } - .associateBy { it.userId!! } - } - - withContext(Dispatchers.Main) { - createComposeAlertDialog( - context.mainActivity!!, - ) { - var pageIndex by remember { mutableIntStateOf(0) } - val messages = remember { mutableStateListOf<@Composable () -> Unit>() } - var totalMessages by remember { mutableIntStateOf(-1) } - val coroutineScope = rememberCoroutineScope() - - suspend fun loadMore() { - val conversationMessages = context.database.getMessagesFromConversationId( - conversationId, - 50, - page = pageIndex++ - ) ?: emptyList() - - if (totalMessages == -1) { - totalMessages = conversationMessages.firstOrNull()?.serverMessageId ?: 0 - } - - val messageLogger = context.feature(MessageLogger::class) - val endToEndEncryption = context.feature(EndToEndEncryption::class) - - val parsedMessages = conversationMessages.mapNotNull Unit> { message -> - val sender = participants[message.senderId] - val messageProtoReader = - (messageLogger.takeIf { it.isEnabled && message.contentType == ContentType.STATUS.id }?.getMessageProto(conversationId, message.clientMessageId.toLong()) // process deleted messages if message logger is enabled - ?: ProtoReader(message.messageContent!!).followPath(4, 4) // database message - )?.let { - if (endToEndEncryption.isEnabled) endToEndEncryption.decryptDatabaseMessage(message) else it // try to decrypt message if e2ee is enabled - } ?: return@mapNotNull null - - val contentType = ContentType.fromMessageContainer(messageProtoReader) ?: ContentType.fromId(message.contentType) - var messageString = if (contentType == ContentType.CHAT) { - messageProtoReader.getString(2, 1) ?: return@mapNotNull null - } else "[${context.translation.getOrNull("content_type.${contentType.name}") ?: contentType.name}]" - - if (contentType == ContentType.SNAP) { - messageString = "\uD83D\uDFE5" //red square - if (message.readTimestamp > 0) { - messageString += " \uD83D\uDC40 " //eyes - messageString += DateFormat.getDateTimeInstance( - DateFormat.SHORT, - DateFormat.SHORT - ).format(Date(message.readTimestamp)) - } - } - - var displayUsername = sender?.displayName ?: sender?.usernameForSorting?: context.translation["conversation_preview.unknown_user"] - - if (displayUsername.length > 12) { - displayUsername = displayUsername.substring(0, 13) + "... " - } - - { - Text( - text = "$displayUsername: $messageString", - modifier = Modifier.padding(4.dp) - ) - } - } - - withContext(Dispatchers.Main) { - messages.addAll(parsedMessages) - } - } - - Column( - modifier = Modifier.fillMaxHeight(fraction = 0.85f) - ) { - Row( - modifier = Modifier - .fillMaxWidth() - .padding(10.dp), - verticalAlignment = Alignment.CenterVertically, - ) { - @Composable - fun Entry(icon: ImageVector, text: String?, title: Boolean) { - Row( - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.spacedBy(3.dp) - ) { - Icon(icon, contentDescription = null) - Text( - text = text ?: "", - fontWeight = if (title) FontWeight.Bold else FontWeight.Light, - fontSize = if (title) 16.sp else 14.sp - ) - } - } - - Column( - modifier = Modifier.weight(1f), - ) { - friendInfo?.let { friendInfo -> - Entry(Icons.Outlined.Person, friendInfo.displayName?.let { "$it (${friendInfo.usernameForSorting})" } ?: friendInfo.usernameForSorting, true) - friendInfo.streakExpirationTimestamp.takeIf { it > 0L && friendInfo.streakLength > 0 && System.currentTimeMillis() < it }?.let { timestamp -> - Entry(Icons.Outlined.LocalFireDepartment, context.translation.format("conversation_preview.streak_expiration", - "day" to ((timestamp - System.currentTimeMillis()) / 1000 / 60 / 60 / 24).toString(), - "hour" to ((timestamp - System.currentTimeMillis()) / 1000 / 60 / 60 % 24).toString(), - "minute" to ((timestamp - System.currentTimeMillis()) / 1000 / 60 % 60).toString() - ), false) - } - } - conversationInfo?.let { - Entry(Icons.Outlined.Group, (it.feedDisplayName ?: it.key).toString(), true) - } - Entry(Icons.AutoMirrored.Outlined.Message, context.translation.format("conversation_preview.total_messages", "count" to totalMessages.toString()), false) - } - friendInfo?.let { - IconButton( - onClick = { - coroutineScope.launch(Dispatchers.IO) { showProfileInfo(it) } - } - ) { - Icon(Icons.Outlined.MoreVert, contentDescription = null) - } - } - } - Spacer(modifier = Modifier.height(1.dp).fillMaxWidth().background(MaterialTheme.colorScheme.onSurface.copy(alpha = 0.1f))) - LazyColumn( - contentPadding = PaddingValues(8.dp), - reverseLayout = true - ) { - items(messages) { message -> - Row( - modifier = Modifier.fillMaxWidth(), - ) { - message() - } - } - item { - Spacer(modifier = Modifier.height(10.dp)) - LaunchedEffect(Unit) { - withContext(Dispatchers.IO) { - loadMore() - } - } - if (messages.isEmpty()) { - Text( - text = context.translation["conversation_preview.no_messages"], - modifier = Modifier - .padding(4.dp) - .fillMaxWidth(), - textAlign = TextAlign.Center - ) - } - } - } - } - }.show() - } - } - - @Composable - private fun MenuElement( - index: Int, - icon: ImageVector, - text: String, - onClick: () -> Unit, - onLongClick: (() -> Unit)? = null, - content: @Composable RowScope.() -> Unit = {} - ) { - if (index > 0) { - Spacer(modifier = Modifier - .height(1.dp) - .background(remember { - if (context.androidContext.isDarkTheme()) Color(0x1affffff) else Color( - 0xffeeeeee - ) - }) - .fillMaxWidth()) - } - Surface( - color = Color(context.userInterface.actionSheetBackground), - contentColor = Color(context.userInterface.colorPrimary), - ) { - Row( - modifier = Modifier - .fillMaxWidth() - .pointerInput(Unit) { - detectTapGestures( - onLongPress = { - onLongClick?.invoke() - }, - onTap = { - onClick() - } - ) - } - .heightIn(min = 55.dp) - .padding(start = 16.dp, end = 16.dp), - verticalAlignment = Alignment.CenterVertically - ) { - Icon(icon, contentDescription = null, modifier = Modifier - .size(32.dp) - .padding(end = 8.dp)) - Text( - text = text, - modifier = Modifier.weight(1f), - lineHeight = 18.sp, - fontSize = 16.sp, - ) - content() - } - } - } - - private val recyclerViewTag = randomTag() - private val messaging by lazy { context.feature(Messaging::class)} - - override fun onViewAdded(event: AddViewEvent) { - fun hasAvatarHeader(viewGroup: ViewGroup): Boolean { - val constraintLayout = viewGroup.getChildAt(0)?.takeIf { it.javaClass.name.endsWith("ConstraintLayout") } as? ViewGroup ?: return false - return constraintLayout.children().firstOrNull { it.javaClass.name.endsWith("AvatarView") } != null - } - - if (event.parent is FrameLayout && messaging.lastFocusedConversationType == 1 && event.view.javaClass.name.endsWith("RecyclerView")) { - event.view.addOnLayoutChangeListener { _, _, _, _, _, _, _, _, _ -> - if (event.view.tag == recyclerViewTag || !hasAvatarHeader(event.view as ViewGroup)) return@addOnLayoutChangeListener - event.view.tag = recyclerViewTag - - // remove recycler view - event.parent.removeView(event.view) - - val newLayout = LinearLayout(event.view.context).apply { - orientation = LinearLayout.VERTICAL - gravity = Gravity.BOTTOM - layoutParams = ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT) - addView(event.view) - } - - newLayout.addView(ScrollView(newLayout.context).apply { - layoutParams = LinearLayout.LayoutParams( - ViewGroup.LayoutParams.MATCH_PARENT, - ViewGroup.LayoutParams.WRAP_CONTENT - ).apply { - weight = 1f; - setMargins(0, 100, 0, 0) - } - - addView(LinearLayout(context).apply { - orientation = LinearLayout.VERTICAL - injectIntoActionSheetItems(newLayout) { - it.layoutParams = LinearLayout.LayoutParams( - ViewGroup.LayoutParams.MATCH_PARENT, - ViewGroup.LayoutParams.WRAP_CONTENT - ).apply { - setMargins(0, 5, 0, 5) - } - addView(it) - } - }) - }, 0) - - event.parent.addView(newLayout) - } - } - - if (event.parent is LinearLayout && event.viewClassName.endsWith("SnapCardView") && hasAvatarHeader(event.parent)) { - val actionSheetItemsContainerLayout = (event.view as ViewGroup).getChildAt(0) as? ViewGroup ?: throw IllegalStateException("ActionSheetItemsContainerLayout not found") - injectIntoActionSheetItems(actionSheetItemsContainerLayout) { - actionSheetItemsContainerLayout.addView(it, 0) - } - } - } - - private fun injectIntoActionSheetItems(actionSheetItemsContainer: View, viewConsumer: ((View) -> Unit)) { - val friendFeedMenuOptions by context.config.userInterface.friendFeedMenuButtons - if (friendFeedMenuOptions.isEmpty()) return - - val messaging = context.feature(Messaging::class) - val conversationId = messaging.lastFocusedConversationId ?: return - val targetUser by lazy { context.database.getDMOtherParticipant(conversationId) } - messaging.resetLastFocusedConversation() - - val translation = context.translation.getCategory("friend_menu_option") - - fun closeMenu() { - if (!context.config.userInterface.autoCloseFriendFeedMenu.get()) return - context.mainActivity?.triggerRootCloseTouchEvent() - } - - @Composable - fun ComposeFriendFeedMenu() { - Column( - modifier = Modifier.fillMaxWidth(), - ) { - var elementIndex by remember { mutableIntStateOf(0) } - - if (friendFeedMenuOptions.contains("conversation_info")) { - MenuElement( - remember { elementIndex++ }, - Icons.Outlined.RemoveRedEye, - translation["preview"], - onClick = { - context.coroutineScope.launch { - showConversationPreview(targetUser, conversationId) - } - } - ) - } - - context.features.getRuleFeatures().forEach { ruleFeature -> - if (!friendFeedMenuOptions.contains(ruleFeature.ruleType.key)) return@forEach - - val ruleState = ruleFeature.getRuleState() ?: return@forEach - var state by remember { mutableStateOf(ruleFeature.getState(conversationId)) } - - fun toggle() { - state = !ruleFeature.getState(conversationId) - ruleFeature.setState(conversationId, state) - context.inAppOverlay.showStatusToast( - if (state) Icons.Default.CheckCircleOutline else Icons.Default.NotInterested, - context.translation.format("rules.toasts.${if (state) "enabled" else "disabled"}", "ruleName" to context.translation[ruleFeature.ruleType.translateOptionKey(ruleState.key)]), - durationMs = 1500 - ) - closeMenu() - } - - MenuElement( - remember { elementIndex++ }, - icon = ruleFeature.ruleType.icon, - text = context.translation[ruleFeature.ruleType.translateOptionKey(ruleState.key)], - onClick = { - toggle() - } - ) { - Switch( - checked = state, - onCheckedChange = { - state = it - toggle() - } - ) - } - } - - if (friendFeedMenuOptions.contains("mark_snaps_as_seen")) { - MenuElement( - remember { elementIndex++ }, - Icons.Outlined.EditNote, - translation["mark_snaps_as_seen"], - onClick = { - context.apply { - closeMenu() - feature(AutoMarkAsRead::class).markSnapsAsSeen(conversationId) - } - } - ) - } - - if (targetUser != null && friendFeedMenuOptions.contains("mark_stories_as_seen_locally")) { - val markAsSeenTranslation = remember { context.translation.getCategory("mark_as_seen") } - - MenuElement( - remember { elementIndex++ }, - Icons.Outlined.RemoveRedEye, - translation["mark_stories_as_seen_locally"], - onClick = { - context.apply { - closeMenu() - inAppOverlay.showStatusToast( - Icons.Default.Info, - if (database.setStoriesViewedState(targetUser!!, true)) markAsSeenTranslation["seen_toast"] - else markAsSeenTranslation["already_seen_toast"], - durationMs = 2500 - ) - } - }, - onLongClick = { - actionSheetItemsContainer.post { - context.apply { - closeMenu() - inAppOverlay.showStatusToast( - Icons.Default.Info, - if (database.setStoriesViewedState(targetUser!!, false)) markAsSeenTranslation["unseen_toast"] - else markAsSeenTranslation["already_unseen_toast"], - durationMs = 2500 - ) - } - } - } - ) - } - } - } - - viewConsumer( - createComposeView(actionSheetItemsContainer.context) { - CompositionLocalProvider( - LocalTextStyle provides LocalTextStyle.current.merge(TextStyle(fontFamily = FontFamily( - Font(context.userInterface.avenirNextFontId, FontWeight.Medium) - ))) - ) { - ComposeFriendFeedMenu() - } - }.apply { - layoutParams = ViewGroup.LayoutParams( - ViewGroup.LayoutParams.MATCH_PARENT, - ViewGroup.LayoutParams.WRAP_CONTENT - ) - } - ) - - if (context.config.scripting.integratedUI.get()) { - context.scriptRuntime.eachModule { - val interfaceManager = getBinding(InterfaceManager::class) - ?.takeIf { - it.hasInterface(EnumScriptInterface.FRIEND_FEED_CONTEXT_MENU) - } ?: return@eachModule - - viewConsumer(LinearLayout(actionSheetItemsContainer.context).apply { - layoutParams = ViewGroup.LayoutParams( - ViewGroup.LayoutParams.MATCH_PARENT, - ViewGroup.LayoutParams.WRAP_CONTENT - ) - - orientation = LinearLayout.VERTICAL - addView(createComposeView(actionSheetItemsContainer.context) { - Surface( - modifier = Modifier.fillMaxWidth(), - color = MaterialTheme.colorScheme.surface - ) { - ScriptInterface(interfaceBuilder = remember { - interfaceManager.buildInterface(EnumScriptInterface.FRIEND_FEED_CONTEXT_MENU, mapOf( - "conversationId" to conversationId, - "userId" to targetUser - )) - } ?: return@Surface) - } - }) - }) - } - } - } -} \ No newline at end of file diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/wrapper/impl/composer/ComposerViewNode.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/wrapper/impl/composer/ComposerViewNode.kt deleted file mode 100644 index c4c2ec3d..00000000 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/wrapper/impl/composer/ComposerViewNode.kt +++ /dev/null @@ -1,58 +0,0 @@ -package me.rhunk.snapenhance.core.wrapper.impl.composer - -import me.rhunk.snapenhance.core.SnapEnhance -import me.rhunk.snapenhance.core.wrapper.AbstractWrapper -import java.lang.reflect.Proxy - -fun createComposerFunction(block: (args: Array<*>) -> Any?): Any { - return SnapEnhance.classCache.composerFunctionActionAdapter.constructors.first().newInstance( - Proxy.newProxyInstance( - SnapEnhance.classCache.composerAction.classLoader, - arrayOf(SnapEnhance.classCache.composerAction), - ) { _, _, args -> - block(args?.get(0) as Array<*>) - } - ) -} - -class ComposerViewNode(obj: Long) : AbstractWrapper(obj) { - companion object { - fun fromNode(composerViewNode: Any?): ComposerViewNode? { - return (composerViewNode?.javaClass?.methods?.firstOrNull { - it.name == "getNativeHandle" - }?.invoke(composerViewNode) as? Long)?.let { ComposerViewNode(it) } ?: return null - } - } - - fun getAttribute(name: String): Any? { - return SnapEnhance.classCache.nativeBridge.methods.firstOrNull { - it.name == "getValueForAttribute" - }?.invoke(null, instanceNonNull(), name) - } - - fun setAttribute(name: String, value: Any) { - SnapEnhance.classCache.nativeBridge.methods.firstOrNull { - it.name == "setValueForAttribute" - }?.invoke(null, instanceNonNull(), name, value, false) - } - - fun getChildren(): List { - return ((SnapEnhance.classCache.nativeBridge.methods.firstOrNull { - it.name == "getRetainedViewNodeChildren" - }?.invoke(null, instanceNonNull(), 1))!! as? LongArray)?.map { - ComposerViewNode(it) - } ?: emptyList() - } - - fun getClassName(): String { - return SnapEnhance.classCache.nativeBridge.methods.firstOrNull { - it.name == "getViewClassName" - }?.invoke(null, instanceNonNull()).toString() - } - - override fun toString(): String { - return SnapEnhance.classCache.nativeBridge.methods.firstOrNull { - it.name == "getViewNodeDebugDescription" - }?.invoke(null, instanceNonNull()).toString() - } -} \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index 92983510..de772a28 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,9 +1,15 @@ -org.gradle.jvmargs=-Xms4G -Xmx4G -Dfile.encoding=UTF-8 +org.gradle.jvmargs=-Xms2G -Xmx4G -Dfile.encoding=UTF-8 org.gradle.parallel=true +org.gradle.workers.max=8 android.useAndroidX=true kotlin.code.style=official android.nonTransitiveRClass=true org.gradle.configuration-cache=true org.gradle.configuration-cache.problems=warn +org.gradle.java.home=C\:\\Program\ Files\\Java\\jdk-21 +nativeAbis=arm64-v8a -APP_VERSION_NAME=2.1.0 +APP_VERSION_NAME=1.0.0 +debug_build_hash=18fe2a814d0e2eb5 +psIntegrityPinnedSha256= +EXPECTED_CERT_SHA256=97fc5c4dff7e33c159528eb9e53f86c356d430cd63d177f40c22b577ac829dee diff --git a/logo.png b/logo.png deleted file mode 100644 index bb0cc867c21abbd0d72ab4490dae073a030534ec..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 194897 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

1VKBtY>k1zwGRs{rC>o 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�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Πw43+hSl!17af!n$x(u%SaR=kV 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 YStGSG;Q2s>`OC4#4?zzKwXEO&9~`9OA^-pY diff --git a/manager/.gitignore b/manager/.gitignore deleted file mode 100644 index 42afabfd..00000000 --- a/manager/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build \ No newline at end of file diff --git a/manager/build.gradle.kts b/manager/build.gradle.kts deleted file mode 100644 index 708b983e..00000000 --- a/manager/build.gradle.kts +++ /dev/null @@ -1,86 +0,0 @@ -import com.android.build.gradle.internal.api.BaseVariantOutputImpl - -plugins { - alias(libs.plugins.androidApplication) - alias(libs.plugins.compose.compiler) - id("kotlin-parcelize") -} - -android { - namespace = rootProject.ext["applicationId"].toString() + ".manager" - compileSdk = 36 - - androidResources { - noCompress += ".so" - } - - buildFeatures { - compose = true - buildConfig = true - } - - defaultConfig { - buildConfigField("String", "APPLICATION_ID", "\"${rootProject.ext["applicationId"]}\"") - applicationId = rootProject.ext["applicationId"].toString() + ".manager" - versionCode = 1 - versionName = "1.0.0" - minSdk = 28 - targetSdk = 36 - multiDexEnabled = true - } - - buildTypes { - release { - isMinifyEnabled = true - proguardFiles += file("proguard-rules.pro") - } - debug { - (properties["debug_flavor"] == null).also { - isDebuggable = !it - isMinifyEnabled = it - isShrinkResources = it - } - proguardFiles += file("proguard-rules.pro") - } - } - - androidComponents { - onVariants { variant -> - variant.outputs.forEach { output -> - val variantOutput = output as com.android.build.api.variant.impl.VariantOutputImpl - variantOutput.outputFileName.set("manager.apk") - } - } - } - - compileOptions { - sourceCompatibility = JavaVersion.VERSION_21 - targetCompatibility = JavaVersion.VERSION_21 - } -} - -configurations { - all { - resolutionStrategy { - exclude(group = "com.google.guava", module = "listenablefuture") - } - } -} - -dependencies { - implementation(fileTree(mapOf("dir" to "libs", "include" to listOf("*.jar")))) - implementation(libs.libsu) - implementation(libs.guava) - implementation(libs.apksig) - implementation(libs.dexlib2) - implementation(libs.gson) - implementation(libs.jsoup) - implementation(libs.okhttp) - implementation(platform(libs.androidx.compose.bom)) - implementation(libs.androidx.material3) - implementation(libs.androidx.activity.ktx) - implementation(libs.androidx.navigation.compose) - implementation(libs.androidx.material.icons.core) - implementation(libs.androidx.material.ripple) - implementation(libs.androidx.material.icons.extended) -} diff --git a/manager/proguard-rules.pro b/manager/proguard-rules.pro deleted file mode 100644 index 717606da..00000000 --- a/manager/proguard-rules.pro +++ /dev/null @@ -1,5 +0,0 @@ --dontwarn com.google.errorprone.annotations.** --dontwarn com.google.auto.value.** --keep enum * { *; } --keep class com.android.tools.smali.dexlib2.** { *; } --keep class me.rhunk.snapenhance.manager.ui.tab.** { *; } \ No newline at end of file diff --git a/manager/src/main/AndroidManifest.xml b/manager/src/main/AndroidManifest.xml deleted file mode 100644 index 636d87d7..00000000 --- a/manager/src/main/AndroidManifest.xml +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/manager/src/main/assets/lspatch/dexes/loader.dex b/manager/src/main/assets/lspatch/dexes/loader.dex deleted file mode 100644 index 5e06ac441051b4f88fec65c3a8619577ff371bd9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1083544 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
HgEzt&=4=G8{Kjfhjt?9!w7P5;2T;w4ii9X0V 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

h6(TpJPj|y0(b|O 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

rmIh~wA&QxA9&uIT$!hO0UsOJ*L%_Y16E&Y9o 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

ZdVJkBqe=#UbNIb5w!`ua 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 z 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.>hWq`ZaDvSeFmexNY`vyW85& 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

ZAwE>`nizns@o=dCNTz&pE=* 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ß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 ?%x?el$T)R!Ri_u8dt&eQH>8XBP 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