├── WTVRBGLauncher.plist ├── Artworks ├── AppIcon.png ├── Assets.xcassets │ ├── Contents.json │ └── AppIcon.appiconset │ │ ├── icon_16x16.png │ │ ├── icon_32x32.png │ │ ├── icon_128x128.png │ │ ├── icon_16x16@2x.png │ │ ├── icon_256x256.png │ │ ├── icon_32x32@2x.png │ │ ├── icon_512x512.png │ │ ├── icon_128x128@2x.png │ │ ├── icon_256x256@2x.png │ │ ├── icon_512x512@2x.png │ │ └── Contents.json └── IconDrawer.swift ├── WTVRBGPrefs ├── Resources │ ├── icon@2x.png │ ├── icon@3x.png │ ├── Empty.plist │ ├── Info.plist │ └── Root.plist ├── WTVRBGRootListController.h ├── Makefile ├── layout │ └── Library │ │ └── PreferenceLoader │ │ └── Preferences │ │ └── WTVRBGPrefs.plist └── WTVRBGRootListController.m ├── devkit ├── env.sh ├── rootless.sh └── roothide.sh ├── control ├── README.md ├── Makefile ├── LICENSE ├── .github └── workflows │ └── build.yml ├── .gitignore └── WTVRBGLauncher.x /WTVRBGLauncher.plist: -------------------------------------------------------------------------------- 1 | { Filter = { Bundles = ( "com.apple.springboard" ); }; } 2 | -------------------------------------------------------------------------------- /Artworks/AppIcon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OwnGoalStudio/WTVRBGLauncher/HEAD/Artworks/AppIcon.png -------------------------------------------------------------------------------- /Artworks/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } -------------------------------------------------------------------------------- /WTVRBGPrefs/Resources/icon@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OwnGoalStudio/WTVRBGLauncher/HEAD/WTVRBGPrefs/Resources/icon@2x.png -------------------------------------------------------------------------------- /WTVRBGPrefs/Resources/icon@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OwnGoalStudio/WTVRBGLauncher/HEAD/WTVRBGPrefs/Resources/icon@3x.png -------------------------------------------------------------------------------- /WTVRBGPrefs/WTVRBGRootListController.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | @interface WTVRBGRootListController : PSListController 4 | 5 | @end 6 | -------------------------------------------------------------------------------- /Artworks/Assets.xcassets/AppIcon.appiconset/icon_16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OwnGoalStudio/WTVRBGLauncher/HEAD/Artworks/Assets.xcassets/AppIcon.appiconset/icon_16x16.png -------------------------------------------------------------------------------- /Artworks/Assets.xcassets/AppIcon.appiconset/icon_32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OwnGoalStudio/WTVRBGLauncher/HEAD/Artworks/Assets.xcassets/AppIcon.appiconset/icon_32x32.png -------------------------------------------------------------------------------- /Artworks/Assets.xcassets/AppIcon.appiconset/icon_128x128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OwnGoalStudio/WTVRBGLauncher/HEAD/Artworks/Assets.xcassets/AppIcon.appiconset/icon_128x128.png -------------------------------------------------------------------------------- /Artworks/Assets.xcassets/AppIcon.appiconset/icon_16x16@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OwnGoalStudio/WTVRBGLauncher/HEAD/Artworks/Assets.xcassets/AppIcon.appiconset/icon_16x16@2x.png -------------------------------------------------------------------------------- /Artworks/Assets.xcassets/AppIcon.appiconset/icon_256x256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OwnGoalStudio/WTVRBGLauncher/HEAD/Artworks/Assets.xcassets/AppIcon.appiconset/icon_256x256.png -------------------------------------------------------------------------------- /Artworks/Assets.xcassets/AppIcon.appiconset/icon_32x32@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OwnGoalStudio/WTVRBGLauncher/HEAD/Artworks/Assets.xcassets/AppIcon.appiconset/icon_32x32@2x.png -------------------------------------------------------------------------------- /Artworks/Assets.xcassets/AppIcon.appiconset/icon_512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OwnGoalStudio/WTVRBGLauncher/HEAD/Artworks/Assets.xcassets/AppIcon.appiconset/icon_512x512.png -------------------------------------------------------------------------------- /Artworks/Assets.xcassets/AppIcon.appiconset/icon_128x128@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OwnGoalStudio/WTVRBGLauncher/HEAD/Artworks/Assets.xcassets/AppIcon.appiconset/icon_128x128@2x.png -------------------------------------------------------------------------------- /Artworks/Assets.xcassets/AppIcon.appiconset/icon_256x256@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OwnGoalStudio/WTVRBGLauncher/HEAD/Artworks/Assets.xcassets/AppIcon.appiconset/icon_256x256@2x.png -------------------------------------------------------------------------------- /Artworks/Assets.xcassets/AppIcon.appiconset/icon_512x512@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OwnGoalStudio/WTVRBGLauncher/HEAD/Artworks/Assets.xcassets/AppIcon.appiconset/icon_512x512@2x.png -------------------------------------------------------------------------------- /devkit/env.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | export THEOS=$HOME/theos 4 | export THEOS_PACKAGE_SCHEME= 5 | export THEOS_DEVICE_IP=127.0.0.1 6 | export THEOS_DEVICE_PORT=58422 7 | export THEOS_DEVICE_SIMULATOR= 8 | -------------------------------------------------------------------------------- /devkit/rootless.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | export THEOS=$HOME/theos 4 | export THEOS_PACKAGE_SCHEME=rootless 5 | export THEOS_DEVICE_IP=127.0.0.1 6 | export THEOS_DEVICE_PORT=58422 7 | export THEOS_DEVICE_SIMULATOR= 8 | -------------------------------------------------------------------------------- /devkit/roothide.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | export THEOS=$HOME/theos-roothide 4 | export THEOS_PACKAGE_SCHEME=roothide 5 | export THEOS_DEVICE_IP=127.0.0.1 6 | export THEOS_DEVICE_PORT=58422 7 | export THEOS_DEVICE_SIMULATOR= 8 | -------------------------------------------------------------------------------- /control: -------------------------------------------------------------------------------- 1 | Package: com.82flex.wtvrbglauncher 2 | Name: 语音转文字免跳转 3 | Version: 1.2 4 | Architecture: iphoneos-arm 5 | Description: 中文输入法语音转文字免跳转插件。无设置选项,安装并注销后立即生效。支持的输入法:微信、百度、搜狗、讯飞 6 | Maintainer: Lessica 7 | Author: Lessica 8 | Section: Tweaks 9 | Depends: firmware (>= 14.0), mobilesubstrate, preferenceloader 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # WTVRBGLauncher 2 | 3 | 中文输入法语音转文字免跳转插件。 4 | 无设置选项,安装并注销后立即生效。 5 | 6 | 原理:动画移除术 7 | 支持的输入法:微信、百度、搜狗、讯飞 8 | 9 | Tested on iOS 15.4.1 / 16.4.1, Dopamine 2. 10 | 11 | ## BEFORE 12 | 13 | https://github.com/user-attachments/assets/f9121eab-632b-4ed0-a5df-332b83da1427 14 | 15 | ## AFTER 16 | 17 | https://github.com/user-attachments/assets/d48cfddc-0897-4207-8564-218427ce0d88 18 | -------------------------------------------------------------------------------- /WTVRBGPrefs/Resources/Empty.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | items 6 | 7 | 8 | cell 9 | PSGroupCell 10 | label 11 | 未找到支持的输入法 12 | 13 | 14 | title 15 | 语音转文字免跳转 16 | 17 | 18 | -------------------------------------------------------------------------------- /WTVRBGPrefs/Makefile: -------------------------------------------------------------------------------- 1 | TARGET := iphone:clang:16.5:14.0 2 | INSTALL_TARGET_PROCESSES := Preferences 3 | 4 | include $(THEOS)/makefiles/common.mk 5 | 6 | BUNDLE_NAME := WTVRBGPrefs 7 | 8 | WTVRBGPrefs_FILES += WTVRBGRootListController.m 9 | WTVRBGPrefs_CFLAGS += -fobjc-arc 10 | 11 | WTVRBGPrefs_FRAMEWORKS += UIKit 12 | WTVRBGPrefs_PRIVATE_FRAMEWORKS += CoreServices 13 | WTVRBGPrefs_PRIVATE_FRAMEWORKS += Preferences 14 | WTVRBGPrefs_INSTALL_PATH += /Library/PreferenceBundles 15 | 16 | include $(THEOS_MAKE_PATH)/bundle.mk -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | export PACKAGE_VERSION := 1.2 2 | 3 | ARCHS := arm64 arm64e 4 | TARGET := iphone:clang:16.5:14.0 5 | INSTALL_TARGET_PROCESSES := SpringBoard 6 | 7 | include $(THEOS)/makefiles/common.mk 8 | 9 | TWEAK_NAME := WTVRBGLauncher 10 | 11 | WTVRBGLauncher_FILES += WTVRBGLauncher.x 12 | WTVRBGLauncher_CFLAGS += -fobjc-arc 13 | WTVRBGLauncher_CFLAGS += -Wno-unused-variable 14 | WTVRBGLauncher_CFLAGS += -Wno-unused-function 15 | 16 | include $(THEOS_MAKE_PATH)/tweak.mk 17 | 18 | SUBPROJECTS += WTVRBGPrefs 19 | 20 | include $(THEOS_MAKE_PATH)/aggregate.mk -------------------------------------------------------------------------------- /WTVRBGPrefs/layout/Library/PreferenceLoader/Preferences/WTVRBGPrefs.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | entry 6 | 7 | bundle 8 | WTVRBGPrefs 9 | cell 10 | PSLinkCell 11 | detail 12 | WTVRBGRootListController 13 | icon 14 | icon.png 15 | isController 16 | 17 | label 18 | 语音转文字免跳转 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /WTVRBGPrefs/Resources/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | English 7 | CFBundleExecutable 8 | WTVRBGPrefs 9 | CFBundleIdentifier 10 | com.82flex.wtvrbgprefs 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundlePackageType 14 | BNDL 15 | CFBundleShortVersionString 16 | 1.0.0 17 | CFBundleSignature 18 | ???? 19 | CFBundleVersion 20 | 1.0 21 | NSPrincipalClass 22 | WTVRBGRootListController 23 | 24 | 25 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 Lessica <82flex@gmail.com> 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Artworks/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "icon_16x16.png", 5 | "idiom" : "mac", 6 | "scale" : "1x", 7 | "size" : "16x16" 8 | }, 9 | { 10 | "filename" : "icon_16x16@2x.png", 11 | "idiom" : "mac", 12 | "scale" : "2x", 13 | "size" : "16x16" 14 | }, 15 | { 16 | "filename" : "icon_32x32.png", 17 | "idiom" : "mac", 18 | "scale" : "1x", 19 | "size" : "32x32" 20 | }, 21 | { 22 | "filename" : "icon_32x32@2x.png", 23 | "idiom" : "mac", 24 | "scale" : "2x", 25 | "size" : "32x32" 26 | }, 27 | { 28 | "filename" : "icon_128x128.png", 29 | "idiom" : "mac", 30 | "scale" : "1x", 31 | "size" : "128x128" 32 | }, 33 | { 34 | "filename" : "icon_128x128@2x.png", 35 | "idiom" : "mac", 36 | "scale" : "2x", 37 | "size" : "128x128" 38 | }, 39 | { 40 | "filename" : "icon_256x256.png", 41 | "idiom" : "mac", 42 | "scale" : "1x", 43 | "size" : "256x256" 44 | }, 45 | { 46 | "filename" : "icon_256x256@2x.png", 47 | "idiom" : "mac", 48 | "scale" : "2x", 49 | "size" : "256x256" 50 | }, 51 | { 52 | "filename" : "icon_512x512.png", 53 | "idiom" : "mac", 54 | "scale" : "1x", 55 | "size" : "512x512" 56 | }, 57 | { 58 | "filename" : "icon_512x512@2x.png", 59 | "idiom" : "mac", 60 | "scale" : "2x", 61 | "size" : "512x512" 62 | } 63 | ], 64 | "info" : { 65 | "author" : "xcode", 66 | "version" : 1 67 | } 68 | } -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: Build Package 2 | 3 | on: 4 | workflow_dispatch: 5 | push: 6 | branches: 7 | - release 8 | 9 | env: 10 | VERSION: 1.0 11 | FINALPACKAGE: 1 12 | HOMEBREW_NO_AUTO_UPDATE: 1 13 | HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK: 1 14 | 15 | jobs: 16 | build: 17 | runs-on: macos-14 18 | 19 | steps: 20 | - name: Setup Xcode 21 | uses: maxim-lobanov/setup-xcode@v1 22 | with: 23 | xcode-version: '15.4' 24 | 25 | - name: Setup Environment 26 | run: | 27 | echo "THEOS=$HOME/theos" >> $GITHUB_ENV 28 | echo "THEOS_IGNORE_PARALLEL_BUILDING_NOTICE=yes" >> $HOME/.theosrc 29 | 30 | - name: Setup Theos 31 | run: | 32 | bash -c "$(curl -fsSL https://raw.githubusercontent.com/OwnGoalStudio/theos/refs/heads/master/bin/install-theos)" 33 | env: 34 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 35 | 36 | - name: Setup Environment (RootHide) 37 | run: | 38 | echo "THEOS=$HOME/theos-roothide" >> $GITHUB_ENV 39 | 40 | - name: Setup Theos (RootHide) 41 | run: | 42 | bash -c "$(curl -fsSL https://raw.githubusercontent.com/OwnGoalStudio/theos-roothide/refs/heads/master/bin/install-theos)" 43 | env: 44 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 45 | 46 | - name: Checkout 47 | uses: actions/checkout@v4 48 | 49 | - name: Build (arm) 50 | run: | 51 | source devkit/env.sh 52 | make clean package 53 | 54 | - name: Build (arm64) 55 | run: | 56 | source devkit/rootless.sh 57 | make clean package 58 | 59 | - name: Build (arm64e) 60 | run: | 61 | source devkit/roothide.sh 62 | make clean package 63 | 64 | - name: Collect dSYMs 65 | run: | 66 | find .theos/obj -name "*.dSYM" -exec cp -r {} ./packages/ \; 67 | VERSION=$(grep '^Version:' .theos/_/DEBIAN/control | awk '{print $2}') 68 | echo "VERSION=$VERSION" >> $GITHUB_ENV 69 | 70 | - name: Upload dSYMs 71 | uses: actions/upload-artifact@v4 72 | with: 73 | name: symbols-${{ env.VERSION }} 74 | path: | 75 | ./packages/*.dSYM 76 | 77 | - name: Upload Packages 78 | uses: actions/upload-artifact@v4 79 | with: 80 | name: packages-${{ env.VERSION }} 81 | path: | 82 | ./packages/*.deb 83 | 84 | - name: Release 85 | uses: softprops/action-gh-release@v2 86 | with: 87 | tag_name: v${{ env.VERSION }} 88 | draft: true 89 | prerelease: false 90 | files: | 91 | ./packages/*.deb 92 | -------------------------------------------------------------------------------- /WTVRBGPrefs/WTVRBGRootListController.m: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | 4 | #import "WTVRBGRootListController.h" 5 | 6 | @interface LSApplicationProxy : NSObject 7 | + (LSApplicationProxy *)applicationProxyForIdentifier:(NSString *)bundleIdentifier; 8 | - (BOOL)isInstalled; 9 | @end 10 | 11 | @implementation WTVRBGRootListController 12 | 13 | static void RemoveSpecifiersWithKey(NSString *key, NSMutableArray *specifiers) { 14 | NSMutableArray *specifiersToRemove = [NSMutableArray array]; 15 | for (PSSpecifier *specifier in specifiers) { 16 | if ([[specifier.properties objectForKey:@"key"] isEqualToString:key]) { 17 | [specifiersToRemove addObject:specifier]; 18 | } 19 | } 20 | [specifiers removeObjectsInArray:specifiersToRemove]; 21 | } 22 | 23 | - (NSArray *)specifiers { 24 | if (!_specifiers) { 25 | _specifiers = [self loadSpecifiersFromPlistName:@"Root" target:self]; 26 | NSMutableArray *specifiers = [NSMutableArray arrayWithArray:_specifiers]; 27 | NSInteger installedCount = 0; 28 | BOOL isWeTypeInstalled = [[LSApplicationProxy applicationProxyForIdentifier:@"com.tencent.wetype"] isInstalled]; 29 | if (!isWeTypeInstalled) { 30 | RemoveSpecifiersWithKey(@"IsWeTypeEnabled", specifiers); 31 | } else { 32 | installedCount++; 33 | } 34 | BOOL isBaiduInstalled = [[LSApplicationProxy applicationProxyForIdentifier:@"com.baidu.inputMethod"] isInstalled]; 35 | if (!isBaiduInstalled) { 36 | RemoveSpecifiersWithKey(@"IsBaiduEnabled", specifiers); 37 | } else { 38 | installedCount++; 39 | } 40 | BOOL isSogouInstalled = [[LSApplicationProxy applicationProxyForIdentifier:@"com.sogou.sogouinput"] isInstalled]; 41 | if (!isSogouInstalled) { 42 | RemoveSpecifiersWithKey(@"IsSogouEnabled", specifiers); 43 | } else { 44 | installedCount++; 45 | } 46 | BOOL isXunFeiInstalled = [[LSApplicationProxy applicationProxyForIdentifier:@"com.iflytek.inputime"] isInstalled]; 47 | if (!isXunFeiInstalled) { 48 | RemoveSpecifiersWithKey(@"IsXunFeiEnabled", specifiers); 49 | } else { 50 | installedCount++; 51 | } 52 | BOOL isDoubaoInstalled = [[LSApplicationProxy applicationProxyForIdentifier:@"com.bytedance.ios.doubaoime"] isInstalled]; 53 | if (!isDoubaoInstalled) { 54 | RemoveSpecifiersWithKey(@"IsDoubaoEnabled", specifiers); 55 | } else { 56 | installedCount++; 57 | } 58 | if (installedCount > 0) { 59 | _specifiers = specifiers; 60 | } else { 61 | _specifiers = [self loadSpecifiersFromPlistName:@"Empty" target:self]; 62 | } 63 | } 64 | return _specifiers; 65 | } 66 | 67 | - (void)support { 68 | NSURL *url = [NSURL URLWithString:@"https://havoc.app/search/82Flex"]; 69 | if ([[UIApplication sharedApplication] canOpenURL:url]) { 70 | [[UIApplication sharedApplication] openURL:url options:@{} completionHandler:nil]; 71 | } 72 | } 73 | 74 | @end 75 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .theos 2 | packages 3 | /Artworks/IconDrawer 4 | 5 | # Created by https://www.toptal.com/developers/gitignore/api/swift,macos,xcode 6 | # Edit at https://www.toptal.com/developers/gitignore?templates=swift,macos,xcode 7 | 8 | ### macOS ### 9 | # General 10 | .DS_Store 11 | .AppleDouble 12 | .LSOverride 13 | 14 | # Icon must end with two \r 15 | Icon 16 | 17 | 18 | # Thumbnails 19 | ._* 20 | 21 | # Files that might appear in the root of a volume 22 | .DocumentRevisions-V100 23 | .fseventsd 24 | .Spotlight-V100 25 | .TemporaryItems 26 | .Trashes 27 | .VolumeIcon.icns 28 | .com.apple.timemachine.donotpresent 29 | 30 | # Directories potentially created on remote AFP share 31 | .AppleDB 32 | .AppleDesktop 33 | Network Trash Folder 34 | Temporary Items 35 | .apdisk 36 | 37 | ### macOS Patch ### 38 | # iCloud generated files 39 | *.icloud 40 | 41 | ### Swift ### 42 | # Xcode 43 | # 44 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 45 | 46 | ## User settings 47 | xcuserdata/ 48 | 49 | ## compatibility with Xcode 8 and earlier (ignoring not required starting Xcode 9) 50 | *.xcscmblueprint 51 | *.xccheckout 52 | 53 | ## compatibility with Xcode 3 and earlier (ignoring not required starting Xcode 4) 54 | build/ 55 | DerivedData/ 56 | *.moved-aside 57 | *.pbxuser 58 | !default.pbxuser 59 | *.mode1v3 60 | !default.mode1v3 61 | *.mode2v3 62 | !default.mode2v3 63 | *.perspectivev3 64 | !default.perspectivev3 65 | 66 | ## Obj-C/Swift specific 67 | *.hmap 68 | 69 | ## App packaging 70 | *.ipa 71 | *.dSYM.zip 72 | *.dSYM 73 | 74 | ## Playgrounds 75 | timeline.xctimeline 76 | playground.xcworkspace 77 | 78 | # Swift Package Manager 79 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. 80 | # Packages/ 81 | # Package.pins 82 | # Package.resolved 83 | # *.xcodeproj 84 | # Xcode automatically generates this directory with a .xcworkspacedata file and xcuserdata 85 | # hence it is not needed unless you have added a package configuration file to your project 86 | # .swiftpm 87 | 88 | .build/ 89 | 90 | # CocoaPods 91 | # We recommend against adding the Pods directory to your .gitignore. However 92 | # you should judge for yourself, the pros and cons are mentioned at: 93 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 94 | # Pods/ 95 | # Add this line if you want to avoid checking in source code from the Xcode workspace 96 | # *.xcworkspace 97 | 98 | # Carthage 99 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 100 | # Carthage/Checkouts 101 | 102 | Carthage/Build/ 103 | 104 | # Accio dependency management 105 | Dependencies/ 106 | .accio/ 107 | 108 | # fastlane 109 | # It is recommended to not store the screenshots in the git repo. 110 | # Instead, use fastlane to re-generate the screenshots whenever they are needed. 111 | # For more information about the recommended setup visit: 112 | # https://docs.fastlane.tools/best-practices/source-control/#source-control 113 | 114 | fastlane/report.xml 115 | fastlane/Preview.html 116 | fastlane/screenshots/**/*.png 117 | fastlane/test_output 118 | 119 | # Code Injection 120 | # After new code Injection tools there's a generated folder /iOSInjectionProject 121 | # https://github.com/johnno1962/injectionforxcode 122 | 123 | iOSInjectionProject/ 124 | 125 | ### Xcode ### 126 | 127 | ## Xcode 8 and earlier 128 | 129 | ### Xcode Patch ### 130 | *.xcodeproj/* 131 | !*.xcodeproj/project.pbxproj 132 | !*.xcodeproj/xcshareddata/ 133 | !*.xcodeproj/project.xcworkspace/ 134 | !*.xcworkspace/contents.xcworkspacedata 135 | /*.gcno 136 | **/xcshareddata/WorkspaceSettings.xcsettings 137 | 138 | # End of https://www.toptal.com/developers/gitignore/api/swift,macos,xcode 139 | n -------------------------------------------------------------------------------- /Artworks/IconDrawer.swift: -------------------------------------------------------------------------------- 1 | // 2 | // IconDrawer.swift 3 | // TRApp 4 | // 5 | // Created by 秋星桥 on 2024/3/6. 6 | // 7 | 8 | // swiftc -parse-as-library IconDrawer.swift 9 | // ./IconDrawer 10 | 11 | import QuickLook 12 | import SwiftUI 13 | 14 | @main 15 | struct DemoApp: App { 16 | var body: some Scene { 17 | WindowGroup { 18 | ContentView() 19 | } 20 | .windowResizability(.contentSize) 21 | } 22 | } 23 | 24 | let previewSize = CGSize(width: 1024, height: 1024) 25 | let symbolWidth: CGFloat = 680 26 | 27 | struct ContentView: View { 28 | var body: some View { 29 | PreviewExporter() 30 | .scaleEffect(.init(width: 0.5, height: 0.5)) 31 | .frame(width: previewSize.width / 2, height: previewSize.height / 2, alignment: .center) 32 | } 33 | } 34 | 35 | struct PreviewWaveformView: View { 36 | let waveWidth: CGFloat = 32 37 | let waveHeight: CGFloat = symbolWidth 38 | let waveSpacing: CGFloat = 32 39 | 40 | struct Waves: Identifiable, Equatable { 41 | var id: UUID = .init() 42 | var height: CGFloat 43 | } 44 | 45 | let waves: [Waves] 46 | 47 | init() { 48 | var builder = [Waves]() 49 | let targetCount = 128 50 | while builder.count < targetCount { 51 | builder.append(.init(height: .random(in: 0.2 ... 1.0))) 52 | } 53 | while builder.count > targetCount { 54 | builder.removeLast() 55 | } 56 | waves = builder 57 | } 58 | 59 | var body: some View { 60 | HStack(alignment: .center, spacing: waveSpacing) { 61 | ForEach(waves) { wave in 62 | RoundedRectangle(cornerRadius: waveWidth / 2) 63 | .frame(width: waveWidth, height: waveHeight * wave.height) 64 | .animation(.spring, value: wave.height) 65 | } 66 | } 67 | .frame(maxHeight: .infinity) 68 | .padding(-8) 69 | } 70 | } 71 | 72 | struct PreviewBannerView: View { 73 | var body: some View { 74 | ZStack { 75 | Image(systemName: "figure.run.square.stack") 76 | .resizable() 77 | .aspectRatio(contentMode: .fit) 78 | .frame(width: symbolWidth, height: symbolWidth) 79 | .font(.system(size: symbolWidth, weight: .regular, design: .rounded)) 80 | .opacity(0.88) 81 | .padding(72) 82 | } 83 | .foregroundStyle(.white) 84 | .frame(maxWidth: .infinity, maxHeight: .infinity) 85 | .padding(50) 86 | .background { 87 | LinearGradient( 88 | gradient: Gradient(colors: [ 89 | .init(red: 141 / 255, green: 233 / 255, blue: 213 / 255), 90 | .init(red: 50 / 255, green: 196 / 255, blue: 191 / 255), 91 | ]), 92 | startPoint: .top, 93 | endPoint: .bottom 94 | ) 95 | .ignoresSafeArea() 96 | } 97 | .frame(width: previewSize.width, height: previewSize.height, alignment: .center) 98 | .clipped() 99 | } 100 | } 101 | 102 | struct PreviewExporter: View { 103 | var body: some View { 104 | VStack { 105 | PreviewBannerView() 106 | .onTapGesture { 107 | let renderer = ImageRenderer(content: PreviewBannerView()) 108 | let data = renderer.nsImage!.tiffRepresentation! 109 | let url = URL(fileURLWithPath: NSTemporaryDirectory()) 110 | .appendingPathComponent("AppIcon") 111 | .appendingPathExtension("tiff") 112 | try! data.write(to: url) 113 | NSWorkspace.shared.open(url) 114 | } 115 | } 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /WTVRBGPrefs/Resources/Root.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | items 6 | 7 | 8 | cell 9 | PSGroupCell 10 | label 11 | 通用 12 | 13 | 14 | cell 15 | PSSwitchCell 16 | default 17 | 18 | defaults 19 | com.82flex.wtvrbgprefs 20 | key 21 | IsEnabled 22 | label 23 | 启用 24 | PostNotification 25 | com.82flex.wtvrbgprefs/saved 26 | 27 | 28 | cell 29 | PSGroupCell 30 | label 31 | 支持的输入法 32 | 33 | 34 | cell 35 | PSSwitchCell 36 | default 37 | 38 | defaults 39 | com.82flex.wtvrbgprefs 40 | key 41 | IsWeTypeEnabled 42 | label 43 | 微信输入法 44 | PostNotification 45 | com.82flex.wtvrbgprefs/saved 46 | 47 | 48 | cell 49 | PSSwitchCell 50 | default 51 | 52 | defaults 53 | com.82flex.wtvrbgprefs 54 | key 55 | IsBaiduEnabled 56 | label 57 | 百度输入法 58 | PostNotification 59 | com.82flex.wtvrbgprefs/saved 60 | 61 | 62 | cell 63 | PSSwitchCell 64 | default 65 | 66 | defaults 67 | com.82flex.wtvrbgprefs 68 | key 69 | IsSogouEnabled 70 | label 71 | 搜狗输入法 72 | PostNotification 73 | com.82flex.wtvrbgprefs/saved 74 | 75 | 76 | cell 77 | PSSwitchCell 78 | default 79 | 80 | defaults 81 | com.82flex.wtvrbgprefs 82 | key 83 | IsXunFeiEnabled 84 | label 85 | 讯飞输入法 86 | PostNotification 87 | com.82flex.wtvrbgprefs/saved 88 | 89 | 90 | cell 91 | PSSwitchCell 92 | default 93 | 94 | defaults 95 | com.82flex.wtvrbgprefs 96 | key 97 | IsDoubaoEnabled 98 | label 99 | 豆包输入法 100 | PostNotification 101 | com.82flex.wtvrbgprefs/saved 102 | 103 | 104 | cell 105 | PSGroupCell 106 | label 107 | 动画延迟时间 108 | 109 | 110 | cell 111 | PSSliderCell 112 | default 113 | 300 114 | min 115 | 0 116 | max 117 | 900 118 | showValue 119 | 120 | isSegmented 121 | 122 | segmentCount 123 | 9 124 | defaults 125 | com.82flex.wtvrbgprefs 126 | key 127 | AnimationDelay 128 | label 129 | 延迟时间 130 | PostNotification 131 | com.82flex.wtvrbgprefs/saved 132 | 133 | 134 | cell 135 | PSGroupCell 136 | label 137 | 动画持续时间 138 | 139 | 140 | cell 141 | PSSliderCell 142 | default 143 | 300 144 | min 145 | 0 146 | max 147 | 900 148 | showValue 149 | 150 | isSegmented 151 | 152 | segmentCount 153 | 9 154 | defaults 155 | com.82flex.wtvrbgprefs 156 | key 157 | AnimationInterval 158 | label 159 | 持续时间 160 | PostNotification 161 | com.82flex.wtvrbgprefs/saved 162 | 163 | 164 | cell 165 | PSGroupCell 166 | label 167 | 168 | footerText 169 | 请支持我们的其他付费作品,谢谢! 170 | 171 | 172 | cell 173 | PSButtonCell 174 | label 175 | 「乌龙工作室」倾情献制 176 | action 177 | support 178 | 179 | 180 | title 181 | 语音转文字免跳转 182 | 183 | 184 | -------------------------------------------------------------------------------- /WTVRBGLauncher.x: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | 4 | typedef NS_ENUM(unsigned, SBActivationSetting) { 5 | SBActivationSettingNotASetting = 0, 6 | SBActivationSettingNoAnimate = 1, 7 | SBActivationSettingSuspended = 3, 8 | SBActivationSettingURL = 5, 9 | SBActivationSettingSourceIdentifier = 14, 10 | SBActivationSettingFromBreadcrumb = 42, 11 | }; 12 | 13 | @interface SBActivationSettings : NSObject 14 | - (id)objectForActivationSetting:(SBActivationSetting)arg1; 15 | - (long long)flagForActivationSetting:(SBActivationSetting)arg1; 16 | - (void)setObject:(id)object forActivationSetting:(SBActivationSetting)activationSetting; 17 | - (void)setFlag:(long long)flag forActivationSetting:(SBActivationSetting)activationSetting; 18 | @end 19 | 20 | @interface SBApplication : NSObject 21 | @property (nonatomic, copy, readonly) NSString * bundleIdentifier; 22 | @end 23 | 24 | @interface SBApplicationSceneView : UIView 25 | @property (nonatomic, readonly) SBApplication *application; 26 | @end 27 | 28 | @interface SBApplicationSceneEntity : NSObject 29 | @property (nonatomic, readonly) SBApplication *application; 30 | @property (nonatomic, readonly) SBActivationSettings *activationSettings; 31 | @end 32 | 33 | @interface SBWorkspaceTransitionContext : NSObject 34 | @property (nonatomic, copy, readonly) NSSet *entities; 35 | @property (nonatomic, copy, readonly) NSSet *previousEntities; 36 | @property (nonatomic, weak) id request; 37 | @end 38 | 39 | %hook SBActivationSettings 40 | 41 | - (void)setFlag:(long long)flag forActivationSetting:(SBActivationSetting)activationSetting { 42 | HBLogDebug(@"[WTVRBGLauncher] setFlag:%lld forActivationSetting:%u", flag, activationSetting); 43 | %orig; 44 | } 45 | 46 | - (void)setObject:(id)object forActivationSetting:(SBActivationSetting)activationSetting { 47 | HBLogDebug(@"[WTVRBGLauncher] setObject:%@ forActivationSetting:%u", object, activationSetting); 48 | %orig; 49 | } 50 | 51 | %end 52 | 53 | static NSString *gFrozenAppSceneIdentifier = nil; 54 | static UIView *gSnapshotView = nil; 55 | 56 | static BOOL gIsEnabled = NO; 57 | static BOOL gIsWeTypeEnabled = NO; 58 | static BOOL gIsBaiduEnabled = NO; 59 | static BOOL gIsSogouEnabled = NO; 60 | static BOOL gIsXunFeiEnabled = NO; 61 | static BOOL gIsDoubaoEnabled = NO; 62 | 63 | static NSTimeInterval gAnimationInterval = 0.3; 64 | static NSTimeInterval gAnimationDelay = 0.3; 65 | 66 | static void ReloadPrefs() { 67 | static NSUserDefaults *prefs = nil; 68 | if (!prefs) { 69 | prefs = [[NSUserDefaults alloc] initWithSuiteName:@"com.82flex.wtvrbgprefs"]; 70 | } 71 | 72 | NSDictionary *settings = [prefs dictionaryRepresentation]; 73 | 74 | gIsEnabled = settings[@"IsEnabled"] ? [settings[@"IsEnabled"] boolValue] : YES; 75 | gIsWeTypeEnabled = settings[@"IsWeTypeEnabled"] ? [settings[@"IsWeTypeEnabled"] boolValue] : YES; 76 | gIsBaiduEnabled = settings[@"IsBaiduEnabled"] ? [settings[@"IsBaiduEnabled"] boolValue] : YES; 77 | gIsSogouEnabled = settings[@"IsSogouEnabled"] ? [settings[@"IsSogouEnabled"] boolValue] : YES; 78 | gIsXunFeiEnabled = settings[@"IsXunFeiEnabled"] ? [settings[@"IsXunFeiEnabled"] boolValue] : YES; 79 | gIsDoubaoEnabled = settings[@"IsDoubaoEnabled"] ? [settings[@"IsDoubaoEnabled"] boolValue] : YES; 80 | gAnimationInterval = settings[@"AnimationInterval"] ? [settings[@"AnimationInterval"] doubleValue] / 1000.0 : 0.3; 81 | gAnimationDelay = settings[@"AnimationDelay"] ? [settings[@"AnimationDelay"] doubleValue] / 1000.0 : 0.3; 82 | 83 | HBLogDebug(@"[WTVRBGLauncher] ReloadPrefs: %@", settings); 84 | } 85 | 86 | %hook SBWorkspaceTransitionContext 87 | 88 | - (BOOL)animationDisabled { 89 | BOOL disabled = %orig; 90 | if (!gIsEnabled) { 91 | return disabled; 92 | } 93 | SBApplicationSceneEntity *prevEntity = self.previousEntities.anyObject; 94 | SBApplicationSceneEntity *nextEntity = self.entities.anyObject; 95 | Class SBApplicationSceneEntityCls = %c(SBApplicationSceneEntity); 96 | if ([prevEntity isKindOfClass:SBApplicationSceneEntityCls] && [nextEntity isKindOfClass:SBApplicationSceneEntityCls]) { 97 | NSString *prevBundleIdentifier = prevEntity.application.bundleIdentifier; 98 | NSString *nextBundleIdentifier = nextEntity.application.bundleIdentifier; 99 | NSString *sourceIdentifier = (NSString *)[nextEntity.activationSettings objectForActivationSetting:SBActivationSettingSourceIdentifier]; 100 | if (gIsBaiduEnabled && 101 | [nextBundleIdentifier isEqualToString:@"com.baidu.inputMethod"] && 102 | [sourceIdentifier isKindOfClass:[NSString class]] && 103 | [sourceIdentifier isEqualToString:@"com.baidu.inputMethod.keyboard"] 104 | ) { 105 | gFrozenAppSceneIdentifier = prevBundleIdentifier; 106 | return YES; 107 | } 108 | NSURL *nextURL = [nextEntity.activationSettings objectForActivationSetting:SBActivationSettingURL]; 109 | if (gIsWeTypeEnabled && 110 | [nextBundleIdentifier isEqualToString:@"com.tencent.wetype"] && 111 | [nextURL isKindOfClass:[NSURL class]] && 112 | [nextURL.scheme isEqualToString:@"wetype"] && 113 | [nextURL.host isEqualToString:@"WXKBURL_STARTVOICERECORD"] 114 | ) { 115 | gFrozenAppSceneIdentifier = prevBundleIdentifier; 116 | return YES; 117 | } 118 | if (gIsSogouEnabled && 119 | [nextBundleIdentifier isEqualToString:@"com.sogou.sogouinput"] && 120 | [nextURL isKindOfClass:[NSURL class]] && 121 | [nextURL.scheme isEqualToString:@"com.sogou.sogouinput.ext"] && 122 | [nextURL.absoluteString containsString:@":path=SpeechInput&"] 123 | ) { 124 | gFrozenAppSceneIdentifier = prevBundleIdentifier; 125 | return YES; 126 | } 127 | if (gIsXunFeiEnabled && 128 | [nextBundleIdentifier isEqualToString:@"com.iflytek.inputime"] && 129 | [nextURL isKindOfClass:[NSURL class]] && 130 | [nextURL.scheme isEqualToString:@"xfime"] && 131 | [nextURL.host isEqualToString:@"activate_for_record"] 132 | ) { 133 | gFrozenAppSceneIdentifier = prevBundleIdentifier; 134 | return YES; 135 | } 136 | if (gIsDoubaoEnabled && 137 | [nextBundleIdentifier isEqualToString:@"com.bytedance.ios.doubaoime"] && 138 | [nextURL isKindOfClass:[NSURL class]] && 139 | [nextURL.scheme isEqualToString:@"oime"] && 140 | [nextURL.host isEqualToString:@"start_asr_from_keyboard"] 141 | ) { 142 | gFrozenAppSceneIdentifier = prevBundleIdentifier; 143 | return YES; 144 | } 145 | BOOL isFromBreadcrumb = [nextEntity.activationSettings flagForActivationSetting:SBActivationSettingFromBreadcrumb]; 146 | if (isFromBreadcrumb && ( 147 | (gIsWeTypeEnabled && [prevBundleIdentifier isEqualToString:@"com.tencent.wetype"]) || 148 | (gIsBaiduEnabled && [prevBundleIdentifier isEqualToString:@"com.baidu.inputMethod"]) || 149 | (gIsSogouEnabled && [prevBundleIdentifier isEqualToString:@"com.sogou.sogouinput"]) || 150 | (gIsXunFeiEnabled && [prevBundleIdentifier isEqualToString:@"com.iflytek.inputime"]) || 151 | (gIsDoubaoEnabled && [prevBundleIdentifier isEqualToString:@"com.bytedance.ios.doubaoime"]) 152 | )) { 153 | return YES; 154 | } 155 | } 156 | return disabled; 157 | } 158 | 159 | %end 160 | 161 | %hook SBApplicationSceneView 162 | 163 | - (void)layoutSubviews 164 | { 165 | %orig; 166 | if (!gIsEnabled) { 167 | return; 168 | } 169 | if (self.application.bundleIdentifier) { 170 | if ([gFrozenAppSceneIdentifier isEqualToString:self.application.bundleIdentifier]) { 171 | gFrozenAppSceneIdentifier = nil; 172 | if (!gSnapshotView) { 173 | UIWindow *window = self.window; 174 | gSnapshotView = [window snapshotViewAfterScreenUpdates:NO]; 175 | gSnapshotView.frame = window.bounds; 176 | gSnapshotView.userInteractionEnabled = NO; 177 | [window addSubview:gSnapshotView]; 178 | return; 179 | } 180 | } 181 | if (gSnapshotView) { 182 | UIView *viewToRemove = gSnapshotView; 183 | gSnapshotView = nil; 184 | [UIView animateWithDuration:gAnimationInterval 185 | delay:gAnimationDelay 186 | options:kNilOptions 187 | animations:^{ 188 | viewToRemove.alpha = 0; 189 | } 190 | completion:^(BOOL finished) { 191 | [viewToRemove removeFromSuperview]; 192 | }]; 193 | } 194 | } 195 | } 196 | 197 | %end 198 | 199 | %ctor { 200 | ReloadPrefs(); 201 | CFNotificationCenterAddObserver( 202 | CFNotificationCenterGetDarwinNotifyCenter(), 203 | NULL, 204 | (CFNotificationCallback)ReloadPrefs, 205 | CFSTR("com.82flex.wtvrbgprefs/saved"), 206 | NULL, 207 | CFNotificationSuspensionBehaviorCoalesce 208 | ); 209 | } --------------------------------------------------------------------------------