diff --git a/apps/stage-capacitor/README.md b/apps/stage-capacitor/README.md new file mode 100644 index 000000000..3233e4cf2 --- /dev/null +++ b/apps/stage-capacitor/README.md @@ -0,0 +1,7 @@ +

アイリ VTuber

+ +

+ [Try it] +

+ +> Heavily inspired by [Neuro-sama](https://www.youtube.com/@Neurosama) diff --git a/apps/stage-capacitor/capacitor.config.ts b/apps/stage-capacitor/capacitor.config.ts new file mode 100644 index 000000000..98e434740 --- /dev/null +++ b/apps/stage-capacitor/capacitor.config.ts @@ -0,0 +1,9 @@ +import type { CapacitorConfig } from '@capacitor/cli' + +const config: CapacitorConfig = { + appId: 'ai.moeru.airi', + appName: 'AIRI', + webDir: 'dist', +} + +export default config diff --git a/apps/stage-capacitor/index.html b/apps/stage-capacitor/index.html new file mode 100644 index 000000000..96743ea18 --- /dev/null +++ b/apps/stage-capacitor/index.html @@ -0,0 +1,58 @@ + + + + + AIRI + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + diff --git a/apps/stage-capacitor/ios/.gitignore b/apps/stage-capacitor/ios/.gitignore new file mode 100644 index 000000000..f47029973 --- /dev/null +++ b/apps/stage-capacitor/ios/.gitignore @@ -0,0 +1,13 @@ +App/build +App/Pods +App/output +App/App/public +DerivedData +xcuserdata + +# Cordova plugins for Capacitor +capacitor-cordova-ios-plugins + +# Generated Config files +App/App/capacitor.config.json +App/App/config.xml diff --git a/apps/stage-capacitor/ios/App/App.xcodeproj/project.pbxproj b/apps/stage-capacitor/ios/App/App.xcodeproj/project.pbxproj new file mode 100644 index 000000000..a8efc0bf8 --- /dev/null +++ b/apps/stage-capacitor/ios/App/App.xcodeproj/project.pbxproj @@ -0,0 +1,378 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 60; + objects = { + +/* Begin PBXBuildFile section */ + 2FAD9763203C412B000D30F8 /* config.xml in Resources */ = {isa = PBXBuildFile; fileRef = 2FAD9762203C412B000D30F8 /* config.xml */; }; + 4D22ABE92AF431CB00220026 /* CapApp-SPM in Frameworks */ = {isa = PBXBuildFile; productRef = 4D22ABE82AF431CB00220026 /* CapApp-SPM */; }; + 50379B232058CBB4000EE86E /* capacitor.config.json in Resources */ = {isa = PBXBuildFile; fileRef = 50379B222058CBB4000EE86E /* capacitor.config.json */; }; + 504EC3081FED79650016851F /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 504EC3071FED79650016851F /* AppDelegate.swift */; }; + 504EC30D1FED79650016851F /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 504EC30B1FED79650016851F /* Main.storyboard */; }; + 504EC30F1FED79650016851F /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 504EC30E1FED79650016851F /* Assets.xcassets */; }; + 504EC3121FED79650016851F /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 504EC3101FED79650016851F /* LaunchScreen.storyboard */; }; + 50B271D11FEDC1A000F3C39B /* public in Resources */ = {isa = PBXBuildFile; fileRef = 50B271D01FEDC1A000F3C39B /* public */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 2FAD9762203C412B000D30F8 /* config.xml */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = config.xml; sourceTree = ""; }; + 50379B222058CBB4000EE86E /* capacitor.config.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = capacitor.config.json; sourceTree = ""; }; + 504EC3041FED79650016851F /* App.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = App.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 504EC3071FED79650016851F /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 504EC30C1FED79650016851F /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 504EC30E1FED79650016851F /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 504EC3111FED79650016851F /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + 504EC3131FED79650016851F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 50B271D01FEDC1A000F3C39B /* public */ = {isa = PBXFileReference; lastKnownFileType = folder; path = public; sourceTree = ""; }; + 958DCC722DB07C7200EA8C5F /* debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = debug.xcconfig; path = ../debug.xcconfig; sourceTree = SOURCE_ROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 504EC3011FED79650016851F /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 4D22ABE92AF431CB00220026 /* CapApp-SPM in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 504EC2FB1FED79650016851F = { + isa = PBXGroup; + children = ( + 958DCC722DB07C7200EA8C5F /* debug.xcconfig */, + 504EC3061FED79650016851F /* App */, + 504EC3051FED79650016851F /* Products */, + ); + sourceTree = ""; + }; + 504EC3051FED79650016851F /* Products */ = { + isa = PBXGroup; + children = ( + 504EC3041FED79650016851F /* App.app */, + ); + name = Products; + sourceTree = ""; + }; + 504EC3061FED79650016851F /* App */ = { + isa = PBXGroup; + children = ( + 50379B222058CBB4000EE86E /* capacitor.config.json */, + 504EC3071FED79650016851F /* AppDelegate.swift */, + 504EC30B1FED79650016851F /* Main.storyboard */, + 504EC30E1FED79650016851F /* Assets.xcassets */, + 504EC3101FED79650016851F /* LaunchScreen.storyboard */, + 504EC3131FED79650016851F /* Info.plist */, + 2FAD9762203C412B000D30F8 /* config.xml */, + 50B271D01FEDC1A000F3C39B /* public */, + ); + path = App; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 504EC3031FED79650016851F /* App */ = { + isa = PBXNativeTarget; + buildConfigurationList = 504EC3161FED79650016851F /* Build configuration list for PBXNativeTarget "App" */; + buildPhases = ( + 504EC3001FED79650016851F /* Sources */, + 504EC3011FED79650016851F /* Frameworks */, + 504EC3021FED79650016851F /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = App; + packageProductDependencies = ( + 4D22ABE82AF431CB00220026 /* CapApp-SPM */, + ); + productName = App; + productReference = 504EC3041FED79650016851F /* App.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 504EC2FC1FED79650016851F /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0920; + LastUpgradeCheck = 0920; + TargetAttributes = { + 504EC3031FED79650016851F = { + CreatedOnToolsVersion = 9.2; + LastSwiftMigration = 1100; + ProvisioningStyle = Automatic; + }; + }; + }; + buildConfigurationList = 504EC2FF1FED79650016851F /* Build configuration list for PBXProject "App" */; + compatibilityVersion = "Xcode 8.0"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 504EC2FB1FED79650016851F; + packageReferences = ( + D4C12C0A2AAA248700AAC8A2 /* XCLocalSwiftPackageReference "CapApp-SPM" */, + ); + productRefGroup = 504EC3051FED79650016851F /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 504EC3031FED79650016851F /* App */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 504EC3021FED79650016851F /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 504EC3121FED79650016851F /* LaunchScreen.storyboard in Resources */, + 50B271D11FEDC1A000F3C39B /* public in Resources */, + 504EC30F1FED79650016851F /* Assets.xcassets in Resources */, + 50379B232058CBB4000EE86E /* capacitor.config.json in Resources */, + 504EC30D1FED79650016851F /* Main.storyboard in Resources */, + 2FAD9763203C412B000D30F8 /* config.xml in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 504EC3001FED79650016851F /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 504EC3081FED79650016851F /* AppDelegate.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 504EC30B1FED79650016851F /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 504EC30C1FED79650016851F /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 504EC3101FED79650016851F /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 504EC3111FED79650016851F /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 504EC3141FED79650016851F /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 958DCC722DB07C7200EA8C5F /* debug.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 504EC3151FED79650016851F /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 504EC3171FED79650016851F /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 958DCC722DB07C7200EA8C5F /* debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = R3M9XV85VN; + INFOPLIST_FILE = App/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 1.0; + OTHER_SWIFT_FLAGS = "$(inherited) \"-D\" \"COCOAPODS\" \"-DDEBUG\""; + PRODUCT_BUNDLE_IDENTIFIER = ai.moeru.airi; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 504EC3181FED79650016851F /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = R3M9XV85VN; + INFOPLIST_FILE = App/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = ai.moeru.airi; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = ""; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 504EC2FF1FED79650016851F /* Build configuration list for PBXProject "App" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 504EC3141FED79650016851F /* Debug */, + 504EC3151FED79650016851F /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 504EC3161FED79650016851F /* Build configuration list for PBXNativeTarget "App" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 504EC3171FED79650016851F /* Debug */, + 504EC3181FED79650016851F /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + +/* Begin XCLocalSwiftPackageReference section */ + D4C12C0A2AAA248700AAC8A2 /* XCLocalSwiftPackageReference "CapApp-SPM" */ = { + isa = XCLocalSwiftPackageReference; + relativePath = "CapApp-SPM"; + }; +/* End XCLocalSwiftPackageReference section */ + +/* Begin XCSwiftPackageProductDependency section */ + 4D22ABE82AF431CB00220026 /* CapApp-SPM */ = { + isa = XCSwiftPackageProductDependency; + package = D4C12C0A2AAA248700AAC8A2 /* XCLocalSwiftPackageReference "CapApp-SPM" */; + productName = "CapApp-SPM"; + }; +/* End XCSwiftPackageProductDependency section */ + }; + rootObject = 504EC2FC1FED79650016851F /* Project object */; +} diff --git a/apps/stage-capacitor/ios/App/App.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/apps/stage-capacitor/ios/App/App.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 000000000..18d981003 --- /dev/null +++ b/apps/stage-capacitor/ios/App/App.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/apps/stage-capacitor/ios/App/App.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/apps/stage-capacitor/ios/App/App.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved new file mode 100644 index 000000000..16abd2813 --- /dev/null +++ b/apps/stage-capacitor/ios/App/App.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -0,0 +1,15 @@ +{ + "originHash" : "dcf9f6e21852e11ae14bb56853ac46203932d4fb843c3f466bc75208582c5e27", + "pins" : [ + { + "identity" : "capacitor-swift-pm", + "kind" : "remoteSourceControl", + "location" : "https://github.com/ionic-team/capacitor-swift-pm.git", + "state" : { + "revision" : "596259033e94829dffc552a40e7129262122995e", + "version" : "8.0.0" + } + } + ], + "version" : 3 +} diff --git a/apps/stage-capacitor/ios/App/App/AppDelegate.swift b/apps/stage-capacitor/ios/App/App/AppDelegate.swift new file mode 100644 index 000000000..c3cd83b5c --- /dev/null +++ b/apps/stage-capacitor/ios/App/App/AppDelegate.swift @@ -0,0 +1,49 @@ +import UIKit +import Capacitor + +@UIApplicationMain +class AppDelegate: UIResponder, UIApplicationDelegate { + + var window: UIWindow? + + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { + // Override point for customization after application launch. + return true + } + + func applicationWillResignActive(_ application: UIApplication) { + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. + } + + func applicationDidEnterBackground(_ application: UIApplication) { + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. + } + + func applicationWillEnterForeground(_ application: UIApplication) { + // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. + } + + func applicationDidBecomeActive(_ application: UIApplication) { + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. + } + + func applicationWillTerminate(_ application: UIApplication) { + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. + } + + func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey: Any] = [:]) -> Bool { + // Called when the app was launched with a url. Feel free to add additional processing here, + // but if you want the App API to support tracking app url opens, make sure to keep this call + return ApplicationDelegateProxy.shared.application(app, open: url, options: options) + } + + func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool { + // Called when the app was launched with an activity, including Universal Links. + // Feel free to add additional processing here, but if you want the App API to support + // tracking app url opens, make sure to keep this call + return ApplicationDelegateProxy.shared.application(application, continue: userActivity, restorationHandler: restorationHandler) + } + +} diff --git a/apps/stage-capacitor/ios/App/App/Assets.xcassets/AppIcon.appiconset/AppIcon-512@2x.png b/apps/stage-capacitor/ios/App/App/Assets.xcassets/AppIcon.appiconset/AppIcon-512@2x.png new file mode 100644 index 000000000..adf6ba01d Binary files /dev/null and b/apps/stage-capacitor/ios/App/App/Assets.xcassets/AppIcon.appiconset/AppIcon-512@2x.png differ diff --git a/apps/stage-capacitor/ios/App/App/Assets.xcassets/AppIcon.appiconset/Contents.json b/apps/stage-capacitor/ios/App/App/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 000000000..00b5bd341 --- /dev/null +++ b/apps/stage-capacitor/ios/App/App/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,14 @@ +{ + "images": [ + { + "filename": "AppIcon-512@2x.png", + "idiom": "universal", + "platform": "ios", + "size": "1024x1024" + } + ], + "info": { + "author": "xcode", + "version": 1 + } +} diff --git a/apps/stage-capacitor/ios/App/App/Assets.xcassets/Contents.json b/apps/stage-capacitor/ios/App/App/Assets.xcassets/Contents.json new file mode 100644 index 000000000..97a8662eb --- /dev/null +++ b/apps/stage-capacitor/ios/App/App/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info": { + "version": 1, + "author": "xcode" + } +} diff --git a/apps/stage-capacitor/ios/App/App/Assets.xcassets/Splash.imageset/Contents.json b/apps/stage-capacitor/ios/App/App/Assets.xcassets/Splash.imageset/Contents.json new file mode 100644 index 000000000..b78149276 --- /dev/null +++ b/apps/stage-capacitor/ios/App/App/Assets.xcassets/Splash.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images": [ + { + "idiom": "universal", + "filename": "splash-2732x2732-2.png", + "scale": "1x" + }, + { + "idiom": "universal", + "filename": "splash-2732x2732-1.png", + "scale": "2x" + }, + { + "idiom": "universal", + "filename": "splash-2732x2732.png", + "scale": "3x" + } + ], + "info": { + "version": 1, + "author": "xcode" + } +} diff --git a/apps/stage-capacitor/ios/App/App/Assets.xcassets/Splash.imageset/splash-2732x2732-1.png b/apps/stage-capacitor/ios/App/App/Assets.xcassets/Splash.imageset/splash-2732x2732-1.png new file mode 100644 index 000000000..33ea6c970 Binary files /dev/null and b/apps/stage-capacitor/ios/App/App/Assets.xcassets/Splash.imageset/splash-2732x2732-1.png differ diff --git a/apps/stage-capacitor/ios/App/App/Assets.xcassets/Splash.imageset/splash-2732x2732-2.png b/apps/stage-capacitor/ios/App/App/Assets.xcassets/Splash.imageset/splash-2732x2732-2.png new file mode 100644 index 000000000..33ea6c970 Binary files /dev/null and b/apps/stage-capacitor/ios/App/App/Assets.xcassets/Splash.imageset/splash-2732x2732-2.png differ diff --git a/apps/stage-capacitor/ios/App/App/Assets.xcassets/Splash.imageset/splash-2732x2732.png b/apps/stage-capacitor/ios/App/App/Assets.xcassets/Splash.imageset/splash-2732x2732.png new file mode 100644 index 000000000..33ea6c970 Binary files /dev/null and b/apps/stage-capacitor/ios/App/App/Assets.xcassets/Splash.imageset/splash-2732x2732.png differ diff --git a/apps/stage-capacitor/ios/App/App/Base.lproj/LaunchScreen.storyboard b/apps/stage-capacitor/ios/App/App/Base.lproj/LaunchScreen.storyboard new file mode 100644 index 000000000..e7ae5d780 --- /dev/null +++ b/apps/stage-capacitor/ios/App/App/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/stage-capacitor/ios/App/App/Base.lproj/Main.storyboard b/apps/stage-capacitor/ios/App/App/Base.lproj/Main.storyboard new file mode 100644 index 000000000..b44df7be8 --- /dev/null +++ b/apps/stage-capacitor/ios/App/App/Base.lproj/Main.storyboard @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/apps/stage-capacitor/ios/App/App/Info.plist b/apps/stage-capacitor/ios/App/App/Info.plist new file mode 100644 index 000000000..d153a7436 --- /dev/null +++ b/apps/stage-capacitor/ios/App/App/Info.plist @@ -0,0 +1,51 @@ + + + + + CAPACITOR_DEBUG + $(CAPACITOR_DEBUG) + CFBundleDevelopmentRegion + en + CFBundleDisplayName + AIRI + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + $(MARKETING_VERSION) + CFBundleVersion + $(CURRENT_PROJECT_VERSION) + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + armv7 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UIViewControllerBasedStatusBarAppearance + + + diff --git a/apps/stage-capacitor/ios/App/CapApp-SPM/.gitignore b/apps/stage-capacitor/ios/App/CapApp-SPM/.gitignore new file mode 100644 index 000000000..3b2981208 --- /dev/null +++ b/apps/stage-capacitor/ios/App/CapApp-SPM/.gitignore @@ -0,0 +1,9 @@ +.DS_Store +/.build +/Packages +/*.xcodeproj +xcuserdata/ +DerivedData/ +.swiftpm/config/registries.json +.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata +.netrc diff --git a/apps/stage-capacitor/ios/App/CapApp-SPM/Package.swift b/apps/stage-capacitor/ios/App/CapApp-SPM/Package.swift new file mode 100644 index 000000000..48e63d82a --- /dev/null +++ b/apps/stage-capacitor/ios/App/CapApp-SPM/Package.swift @@ -0,0 +1,25 @@ +// swift-tools-version: 5.9 +import PackageDescription + +// DO NOT MODIFY THIS FILE - managed by Capacitor CLI commands +let package = Package( + name: "CapApp-SPM", + platforms: [.iOS(.v15)], + products: [ + .library( + name: "CapApp-SPM", + targets: ["CapApp-SPM"]) + ], + dependencies: [ + .package(url: "https://github.com/ionic-team/capacitor-swift-pm.git", exact: "8.0.0") + ], + targets: [ + .target( + name: "CapApp-SPM", + dependencies: [ + .product(name: "Capacitor", package: "capacitor-swift-pm"), + .product(name: "Cordova", package: "capacitor-swift-pm") + ] + ) + ] +) diff --git a/apps/stage-capacitor/ios/App/CapApp-SPM/README.md b/apps/stage-capacitor/ios/App/CapApp-SPM/README.md new file mode 100644 index 000000000..5e22a2f8a --- /dev/null +++ b/apps/stage-capacitor/ios/App/CapApp-SPM/README.md @@ -0,0 +1,5 @@ +# CapApp-SPM + +This SPM is used to host SPM dependencies for you Capacitor project + +Do not modify the contents of it or there may be unintended consequences. diff --git a/apps/stage-capacitor/ios/App/CapApp-SPM/Sources/CapApp-SPM/CapApp-SPM.swift b/apps/stage-capacitor/ios/App/CapApp-SPM/Sources/CapApp-SPM/CapApp-SPM.swift new file mode 100644 index 000000000..945afec8c --- /dev/null +++ b/apps/stage-capacitor/ios/App/CapApp-SPM/Sources/CapApp-SPM/CapApp-SPM.swift @@ -0,0 +1 @@ +public let isCapacitorApp = true diff --git a/apps/stage-capacitor/ios/debug.xcconfig b/apps/stage-capacitor/ios/debug.xcconfig new file mode 100644 index 000000000..53ce18dea --- /dev/null +++ b/apps/stage-capacitor/ios/debug.xcconfig @@ -0,0 +1 @@ +CAPACITOR_DEBUG = true diff --git a/apps/stage-capacitor/package.json b/apps/stage-capacitor/package.json new file mode 100644 index 000000000..7e8957a95 --- /dev/null +++ b/apps/stage-capacitor/package.json @@ -0,0 +1,138 @@ +{ + "name": "@proj-airi/stage-capacitor", + "type": "module", + "private": true, + "description": "LLM powered virtual character", + "author": { + "name": "Moeru AI Project AIRI Team", + "email": "airi@moeru.ai", + "url": "https://github.com/moeru-ai" + }, + "license": "MIT", + "scripts": { + "build": "vite build", + "dev": "vite --port 5273", + "lint": "eslint .", + "preview": "vite preview", + "typecheck": "vue-tsc --noEmit", + "dev:ios": "cap run ios -l --port 5273" + }, + "dependencies": { + "@capacitor/core": "catalog:", + "@capacitor/ios": "catalog:", + "@date-fns/utc": "^2.1.1", + "@formkit/auto-animate": "^0.9.0", + "@huggingface/transformers": "^3.8.1", + "@moeru/eventa": "^1.0.0-alpha.10", + "@moeru/std": "catalog:", + "@proj-airi/audio": "workspace:^", + "@proj-airi/ccc": "workspace:^", + "@proj-airi/drizzle-duckdb-wasm": "catalog:", + "@proj-airi/font-cjkfonts-allseto": "workspace:^", + "@proj-airi/font-xiaolai": "workspace:^", + "@proj-airi/i18n": "workspace:^", + "@proj-airi/server-sdk": "workspace:^", + "@proj-airi/stage-ui": "workspace:^", + "@proj-airi/stage-ui-three": "workspace:^", + "@proj-airi/stage-ui-three-performance-runtime": "workspace:^", + "@proj-airi/ui": "workspace:^", + "@proj-airi/ui-transitions": "workspace:^", + "@standard-schema/spec": "^1.1.0", + "@stdlib/string-base-kebabcase": "^0.2.2", + "@tresjs/cientos": "^5.2.1", + "@tresjs/core": "^5.2.1", + "@valibot/to-json-schema": "1.0.0-rc.0", + "@vueuse/core": "^14.1.0", + "@vueuse/shared": "^14.1.0", + "@xsai-ext/providers": "catalog:", + "@xsai-transformers/embed": "^0.0.11", + "@xsai/generate-speech": "catalog:", + "@xsai/generate-text": "catalog:", + "@xsai/model": "catalog:", + "@xsai/shared": "catalog:", + "@xsai/shared-chat": "catalog:", + "@xsai/stream-text": "catalog:", + "@xsai/stream-transcription": "0.4.0-beta.8", + "@xsai/utils-chat": "catalog:", + "animejs": "^4.2.2", + "colorjs.io": "^0.6.0", + "culori": "^4.0.2", + "date-fns": "^4.1.0", + "dompurify": "^3.3.1", + "driver.js": "^1.4.0", + "drizzle-kit": "^0.31.8", + "drizzle-orm": "^0.45.1", + "gpuu": "^1.0.6", + "html2canvas": "^1.4.1", + "jszip": "^3.10.1", + "localforage": "^1.10.0", + "mediabunny": "^1.27.2", + "nanoid": "^5.1.6", + "node-vibrant": "^4.0.3", + "nprogress": "^0.2.0", + "ofetch": "^1.5.1", + "onnxruntime-web": "^1.23.2", + "pinia": "^3.0.4", + "posthog-js": "catalog:", + "rehype-stringify": "^10.0.1", + "reka-ui": "^2.7.0", + "remark-parse": "^11.0.0", + "remark-rehype": "^11.1.2", + "shiki": "^3.20.0", + "three": "^0.182.0", + "unified": "^11.0.5", + "unspeech": "^0.1.7", + "uuid": "^13.0.0", + "valibot": "^1.2.0", + "vaul-vue": "^0.4.1", + "vue": "^3.5.25", + "vue-demi": "^0.14.10", + "vue-i18n": "^11.2.2", + "vue-router": "^4.6.4", + "vue-sonner": "^2.0.9", + "workbox-window": "^7.4.0", + "xsschema": "catalog:", + "yauzl": "^3.2.0", + "zod": "^4.2.1" + }, + "devDependencies": { + "@capacitor/cli": "catalog:", + "@iconify-json/carbon": "^1.2.15", + "@iconify-json/eos-icons": "^1.2.4", + "@iconify-json/lucide": "^1.2.82", + "@iconify-json/mingcute": "^1.2.6", + "@iconify-json/ph": "^1.2.2", + "@iconify-json/simple-icons": "^1.2.63", + "@iconify-json/solar": "^1.2.5", + "@iconify-json/svg-spinners": "^1.2.4", + "@iconify-json/vscode-icons": "^1.2.37", + "@intlify/unplugin-vue-i18n": "^11.0.1", + "@proj-airi/lobe-icons": "^1.0.18", + "@proj-airi/unplugin-fetch": "^0.2.1", + "@proj-airi/unplugin-live2d-sdk": "^0.1.6", + "@proj-airi/vite-plugin-warpdrive": "workspace:*", + "@shikijs/markdown-it": "^3.20.0", + "@types/audioworklet": "catalog:", + "@types/culori": "^4.0.1", + "@types/nprogress": "^0.2.3", + "@types/three": "^0.182.0", + "@types/yauzl": "^2.10.3", + "@unocss/reset": "^66.5.11", + "@vitejs/plugin-vue": "^6.0.3", + "@vue-macros/volar": "^3.1.1", + "@vueuse/motion": "^3.0.3", + "csstype": "^3.2.3", + "hfup": "^1.0.0", + "less": "^4.5.1", + "unplugin-info": "^1.2.4", + "unplugin-vue-router": "^0.19.0", + "unplugin-yaml": "^3.0.7", + "vite": "catalog:rolldown-vite", + "vite-bundle-visualizer": "^1.2.1", + "vite-plugin-pwa": "^1.2.0", + "vite-plugin-vue-devtools": "^8.0.5", + "vite-plugin-vue-layouts": "^0.11.0", + "vue-macros": "^3.1.1", + "vue-tsc": "^3.1.8" + } +} diff --git a/apps/stage-capacitor/public/.assetsignore b/apps/stage-capacitor/public/.assetsignore new file mode 100644 index 000000000..421c66e16 --- /dev/null +++ b/apps/stage-capacitor/public/.assetsignore @@ -0,0 +1,3 @@ +**/node_modules +**/.DS_Store +**/.git diff --git a/apps/stage-capacitor/public/_headers b/apps/stage-capacitor/public/_headers new file mode 100644 index 000000000..7f40d0894 --- /dev/null +++ b/apps/stage-capacitor/public/_headers @@ -0,0 +1,4 @@ +/assets/* + cache-control: max-age=31536000 + cache-control: immutable + diff --git a/apps/stage-capacitor/public/_redirects b/apps/stage-capacitor/public/_redirects new file mode 100644 index 000000000..b885e9174 --- /dev/null +++ b/apps/stage-capacitor/public/_redirects @@ -0,0 +1,15 @@ +# Plausible.io analytics +# +# Originally proxying Plausible through Netlify | Plausible docs +# https://plausible.io/docs/proxy/guides/netlify +# +# /remote-assets/page-external-data/js/script.js https://plausible.io/js/script.js 200 +# /api/v1/page-external-data/submit https://plausible.io/api/event 200 + +# i18n +/docs/ /docs/en/ 301 + +# Normalize old zh-hans locale path to zh-Hans +# This ensures legacy links like /docs/zh-hans/ still work +/docs/zh-hans/* /docs/zh-Hans/:splat 301 +/docs/zh-hans /docs/zh-Hans/ 301 diff --git a/apps/stage-capacitor/public/apple-touch-icon.png b/apps/stage-capacitor/public/apple-touch-icon.png new file mode 100644 index 000000000..e3bfed969 Binary files /dev/null and b/apps/stage-capacitor/public/apple-touch-icon.png differ diff --git a/apps/stage-capacitor/public/favicon.ico b/apps/stage-capacitor/public/favicon.ico new file mode 100644 index 000000000..a47f8f675 Binary files /dev/null and b/apps/stage-capacitor/public/favicon.ico differ diff --git a/apps/stage-capacitor/public/favicon.svg b/apps/stage-capacitor/public/favicon.svg new file mode 100644 index 000000000..eae728aa1 --- /dev/null +++ b/apps/stage-capacitor/public/favicon.svg @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/stage-capacitor/public/maskable_icon_x192.png b/apps/stage-capacitor/public/maskable_icon_x192.png new file mode 100644 index 000000000..9a1728ebd Binary files /dev/null and b/apps/stage-capacitor/public/maskable_icon_x192.png differ diff --git a/apps/stage-capacitor/public/maskable_icon_x512.png b/apps/stage-capacitor/public/maskable_icon_x512.png new file mode 100644 index 000000000..2a56ae126 Binary files /dev/null and b/apps/stage-capacitor/public/maskable_icon_x512.png differ diff --git a/apps/stage-capacitor/public/open-graph.png b/apps/stage-capacitor/public/open-graph.png new file mode 100644 index 000000000..a7d26580c Binary files /dev/null and b/apps/stage-capacitor/public/open-graph.png differ diff --git a/apps/stage-capacitor/public/web-app-manifest-192x192.png b/apps/stage-capacitor/public/web-app-manifest-192x192.png new file mode 100644 index 000000000..c046e5331 Binary files /dev/null and b/apps/stage-capacitor/public/web-app-manifest-192x192.png differ diff --git a/apps/stage-capacitor/public/web-app-manifest-512x512.png b/apps/stage-capacitor/public/web-app-manifest-512x512.png new file mode 100644 index 000000000..e92eb2fd7 Binary files /dev/null and b/apps/stage-capacitor/public/web-app-manifest-512x512.png differ diff --git a/apps/stage-capacitor/src/App.vue b/apps/stage-capacitor/src/App.vue new file mode 100644 index 000000000..1d62e7f79 --- /dev/null +++ b/apps/stage-capacitor/src/App.vue @@ -0,0 +1,143 @@ + + + + + diff --git a/apps/stage-capacitor/src/assets/backgrounds/fairy-forest.e17cbc2774.ko-fi.com.avif b/apps/stage-capacitor/src/assets/backgrounds/fairy-forest.e17cbc2774.ko-fi.com.avif new file mode 100644 index 000000000..4fc190fe5 Binary files /dev/null and b/apps/stage-capacitor/src/assets/backgrounds/fairy-forest.e17cbc2774.ko-fi.com.avif differ diff --git a/apps/stage-capacitor/src/assets/icons/modules/games/factorio.png b/apps/stage-capacitor/src/assets/icons/modules/games/factorio.png new file mode 100644 index 000000000..8162e4817 Binary files /dev/null and b/apps/stage-capacitor/src/assets/icons/modules/games/factorio.png differ diff --git a/apps/stage-capacitor/src/assets/logo-dark.svg b/apps/stage-capacitor/src/assets/logo-dark.svg new file mode 100644 index 000000000..9bdcabaa0 --- /dev/null +++ b/apps/stage-capacitor/src/assets/logo-dark.svg @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/stage-capacitor/src/assets/logo.svg b/apps/stage-capacitor/src/assets/logo.svg new file mode 100644 index 000000000..e3be30e0a --- /dev/null +++ b/apps/stage-capacitor/src/assets/logo.svg @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/stage-capacitor/src/components/AudioWaveform.vue b/apps/stage-capacitor/src/components/AudioWaveform.vue new file mode 100644 index 000000000..d974d29fe --- /dev/null +++ b/apps/stage-capacitor/src/components/AudioWaveform.vue @@ -0,0 +1,97 @@ + + + diff --git a/apps/stage-capacitor/src/components/Backgrounds/DialogPicker.vue b/apps/stage-capacitor/src/components/Backgrounds/DialogPicker.vue new file mode 100644 index 000000000..c00bd30d0 --- /dev/null +++ b/apps/stage-capacitor/src/components/Backgrounds/DialogPicker.vue @@ -0,0 +1,21 @@ + + + diff --git a/apps/stage-capacitor/src/components/Backgrounds/Line1.vue b/apps/stage-capacitor/src/components/Backgrounds/Line1.vue new file mode 100644 index 000000000..2beb911ff --- /dev/null +++ b/apps/stage-capacitor/src/components/Backgrounds/Line1.vue @@ -0,0 +1,16 @@ + + + diff --git a/apps/stage-capacitor/src/components/Backgrounds/Provider.vue b/apps/stage-capacitor/src/components/Backgrounds/Provider.vue new file mode 100644 index 000000000..c7615bbae --- /dev/null +++ b/apps/stage-capacitor/src/components/Backgrounds/Provider.vue @@ -0,0 +1,56 @@ + + + + + diff --git a/apps/stage-capacitor/src/components/Backgrounds/SakuraPetal.vue b/apps/stage-capacitor/src/components/Backgrounds/SakuraPetal.vue new file mode 100644 index 000000000..1e1b01237 --- /dev/null +++ b/apps/stage-capacitor/src/components/Backgrounds/SakuraPetal.vue @@ -0,0 +1,166 @@ + + + + + diff --git a/apps/stage-capacitor/src/components/Backgrounds/TicTacToe.vue b/apps/stage-capacitor/src/components/Backgrounds/TicTacToe.vue new file mode 100644 index 000000000..c05d5e4c4 --- /dev/null +++ b/apps/stage-capacitor/src/components/Backgrounds/TicTacToe.vue @@ -0,0 +1,34 @@ + + + diff --git a/apps/stage-capacitor/src/components/Backgrounds/default/index.ts b/apps/stage-capacitor/src/components/Backgrounds/default/index.ts new file mode 100644 index 000000000..d393f9ed0 --- /dev/null +++ b/apps/stage-capacitor/src/components/Backgrounds/default/index.ts @@ -0,0 +1,4 @@ +export { default as DefaultBackground } from './index.vue' +export { default as PartAnimatedWave } from './part-animated-wave.vue' +export { default as PatternCross } from './pattern-cross.vue' +export { default as DefaultBackgroundPreview } from './preview.vue' diff --git a/apps/stage-capacitor/src/components/Backgrounds/default/index.vue b/apps/stage-capacitor/src/components/Backgrounds/default/index.vue new file mode 100644 index 000000000..0adf4b682 --- /dev/null +++ b/apps/stage-capacitor/src/components/Backgrounds/default/index.vue @@ -0,0 +1,20 @@ + + + diff --git a/apps/stage-capacitor/src/components/Backgrounds/default/part-animated-wave.vue b/apps/stage-capacitor/src/components/Backgrounds/default/part-animated-wave.vue new file mode 100644 index 000000000..b3b7f5647 --- /dev/null +++ b/apps/stage-capacitor/src/components/Backgrounds/default/part-animated-wave.vue @@ -0,0 +1,138 @@ + + + + + diff --git a/apps/stage-capacitor/src/components/Backgrounds/default/pattern-cross.vue b/apps/stage-capacitor/src/components/Backgrounds/default/pattern-cross.vue new file mode 100644 index 000000000..4e5850598 --- /dev/null +++ b/apps/stage-capacitor/src/components/Backgrounds/default/pattern-cross.vue @@ -0,0 +1,41 @@ + + + diff --git a/apps/stage-capacitor/src/components/Backgrounds/default/preview.vue b/apps/stage-capacitor/src/components/Backgrounds/default/preview.vue new file mode 100644 index 000000000..a0f5cca14 --- /dev/null +++ b/apps/stage-capacitor/src/components/Backgrounds/default/preview.vue @@ -0,0 +1,20 @@ + + + diff --git a/apps/stage-capacitor/src/components/Backgrounds/index.ts b/apps/stage-capacitor/src/components/Backgrounds/index.ts new file mode 100644 index 000000000..82ec7dcef --- /dev/null +++ b/apps/stage-capacitor/src/components/Backgrounds/index.ts @@ -0,0 +1,2 @@ +export { default as BackgroundDialogPicker } from './DialogPicker.vue' +export { default as BackgroundProvider } from './Provider.vue' diff --git a/apps/stage-capacitor/src/components/DataGui/DualEndRange.vue b/apps/stage-capacitor/src/components/DataGui/DualEndRange.vue new file mode 100644 index 000000000..8466d1d27 --- /dev/null +++ b/apps/stage-capacitor/src/components/DataGui/DualEndRange.vue @@ -0,0 +1,204 @@ + + + + + diff --git a/apps/stage-capacitor/src/components/IconAnimation.vue b/apps/stage-capacitor/src/components/IconAnimation.vue new file mode 100644 index 000000000..976762cb7 --- /dev/null +++ b/apps/stage-capacitor/src/components/IconAnimation.vue @@ -0,0 +1,76 @@ + + + diff --git a/apps/stage-capacitor/src/components/Layouts/Header.vue b/apps/stage-capacitor/src/components/Layouts/Header.vue new file mode 100644 index 000000000..479ac351c --- /dev/null +++ b/apps/stage-capacitor/src/components/Layouts/Header.vue @@ -0,0 +1,24 @@ + + + diff --git a/apps/stage-capacitor/src/components/Layouts/HeaderLink.vue b/apps/stage-capacitor/src/components/Layouts/HeaderLink.vue new file mode 100644 index 000000000..430695cd1 --- /dev/null +++ b/apps/stage-capacitor/src/components/Layouts/HeaderLink.vue @@ -0,0 +1,32 @@ + + + + + diff --git a/apps/stage-capacitor/src/components/Layouts/InteractiveArea.vue b/apps/stage-capacitor/src/components/Layouts/InteractiveArea.vue new file mode 100644 index 000000000..d3d585200 --- /dev/null +++ b/apps/stage-capacitor/src/components/Layouts/InteractiveArea.vue @@ -0,0 +1,64 @@ + + + + + diff --git a/apps/stage-capacitor/src/components/Layouts/InteractiveArea/Actions/About.vue b/apps/stage-capacitor/src/components/Layouts/InteractiveArea/Actions/About.vue new file mode 100644 index 000000000..969828253 --- /dev/null +++ b/apps/stage-capacitor/src/components/Layouts/InteractiveArea/Actions/About.vue @@ -0,0 +1,23 @@ + + + diff --git a/apps/stage-capacitor/src/components/Layouts/InteractiveArea/Actions/ViewControls.vue b/apps/stage-capacitor/src/components/Layouts/InteractiveArea/Actions/ViewControls.vue new file mode 100644 index 000000000..e3ee30932 --- /dev/null +++ b/apps/stage-capacitor/src/components/Layouts/InteractiveArea/Actions/ViewControls.vue @@ -0,0 +1,73 @@ + + + + + diff --git a/apps/stage-capacitor/src/components/Layouts/MobileHeader.vue b/apps/stage-capacitor/src/components/Layouts/MobileHeader.vue new file mode 100644 index 000000000..46b106466 --- /dev/null +++ b/apps/stage-capacitor/src/components/Layouts/MobileHeader.vue @@ -0,0 +1,11 @@ + + + diff --git a/apps/stage-capacitor/src/components/Layouts/MobileHeaderLink.vue b/apps/stage-capacitor/src/components/Layouts/MobileHeaderLink.vue new file mode 100644 index 000000000..b2776f66c --- /dev/null +++ b/apps/stage-capacitor/src/components/Layouts/MobileHeaderLink.vue @@ -0,0 +1,35 @@ + + + + + diff --git a/apps/stage-capacitor/src/components/Layouts/MobileInteractiveArea.vue b/apps/stage-capacitor/src/components/Layouts/MobileInteractiveArea.vue new file mode 100644 index 000000000..39ac71ac0 --- /dev/null +++ b/apps/stage-capacitor/src/components/Layouts/MobileInteractiveArea.vue @@ -0,0 +1,280 @@ + + + + + diff --git a/apps/stage-capacitor/src/components/Layouts/ViewControls/Inputs.vue b/apps/stage-capacitor/src/components/Layouts/ViewControls/Inputs.vue new file mode 100644 index 000000000..bb7a5e7ff --- /dev/null +++ b/apps/stage-capacitor/src/components/Layouts/ViewControls/Inputs.vue @@ -0,0 +1,205 @@ + + + + + diff --git a/apps/stage-capacitor/src/components/Widgets/ChatActionButtons.vue b/apps/stage-capacitor/src/components/Widgets/ChatActionButtons.vue new file mode 100644 index 000000000..b35962681 --- /dev/null +++ b/apps/stage-capacitor/src/components/Widgets/ChatActionButtons.vue @@ -0,0 +1,54 @@ + + + diff --git a/apps/stage-capacitor/src/components/Widgets/ChatArea.vue b/apps/stage-capacitor/src/components/Widgets/ChatArea.vue new file mode 100644 index 000000000..d0970f674 --- /dev/null +++ b/apps/stage-capacitor/src/components/Widgets/ChatArea.vue @@ -0,0 +1,210 @@ + + + diff --git a/apps/stage-capacitor/src/components/Widgets/ChatContainer.vue b/apps/stage-capacitor/src/components/Widgets/ChatContainer.vue new file mode 100644 index 000000000..a89207d67 --- /dev/null +++ b/apps/stage-capacitor/src/components/Widgets/ChatContainer.vue @@ -0,0 +1,10 @@ + diff --git a/apps/stage-capacitor/src/components/Widgets/IndicatorMicVolume.vue b/apps/stage-capacitor/src/components/Widgets/IndicatorMicVolume.vue new file mode 100644 index 000000000..7fff11675 --- /dev/null +++ b/apps/stage-capacitor/src/components/Widgets/IndicatorMicVolume.vue @@ -0,0 +1,77 @@ + + + diff --git a/apps/stage-capacitor/src/composables/audio-input.ts b/apps/stage-capacitor/src/composables/audio-input.ts new file mode 100644 index 000000000..64ac2a549 --- /dev/null +++ b/apps/stage-capacitor/src/composables/audio-input.ts @@ -0,0 +1,83 @@ +import { useDevicesList, useUserMedia } from '@vueuse/core' +import { computed, ref, watch } from 'vue' + +export function useAudioInput() { + const devices = useDevicesList({ constraints: { audio: true }, requestPermissions: false }) + + const selectedAudioInputId = ref(devices.audioInputs.value[0]?.deviceId || '') + const selectedAudioInput = ref() + const audioInputs = computed(() => devices.audioInputs.value) + + const constraints = ref({ audio: true }) + const media = useUserMedia({ constraints, autoSwitch: true, enabled: false }) + + async function request() { + if (devices.permissionGranted.value) { + return + } + if (!devices.isSupported.value) { + return + } + + await devices.ensurePermissions() + } + + watch(selectedAudioInputId, () => { + if (selectedAudioInputId.value) { + constraints.value = { + audio: { + deviceId: { exact: selectedAudioInputId.value! }, + }, + } + } + }, { immediate: true }) + + watch(devices.audioInputs, () => { + selectedAudioInput.value = audioInputs.value.find(device => device.deviceId === selectedAudioInputId.value) + }, { immediate: true }) + + watch([devices.permissionGranted, audioInputs, selectedAudioInputId], async () => { + await request() + if (!devices.permissionGranted.value) { + return + } + if (audioInputs.value.length === 0) { + return + } + if (!selectedAudioInput.value) { + selectedAudioInput.value = audioInputs.value[0] + } + }, { immediate: true }) + + async function start() { + await request() + + if (!devices.permissionGranted.value) { + return + } + if (!selectedAudioInput.value) { + return + } + + if (media.enabled.value) { + media.restart() + } + + media.start() + } + + function stop() { + media.stop() + } + + return { + selectedAudioInputId, + selectedAudioInput, + audioInputs, + + start, + stop, + request, + media, + } +} diff --git a/apps/stage-capacitor/src/composables/audio-record.ts b/apps/stage-capacitor/src/composables/audio-record.ts new file mode 100644 index 000000000..8a642b568 --- /dev/null +++ b/apps/stage-capacitor/src/composables/audio-record.ts @@ -0,0 +1,42 @@ +import type { MaybeRefOrGetter } from 'vue' + +import { until } from '@vueuse/core' +import { ref, toRef } from 'vue' + +export function useAudioRecord( + media: MaybeRefOrGetter, + start: () => Promise = () => Promise.resolve(), +) { + const audioRecorder = ref() + const mediaRef = toRef(media) + + async function startRecord() { + await start() + await until(mediaRef).toBeTruthy() + + if (!mediaRef.value) { + console.error('No media media available') + return + } + + audioRecorder.value = new MediaRecorder(mediaRef.value) + audioRecorder.value.start() + } + + function stopRecord() { + if (audioRecorder.value) { + audioRecorder.value.stop() + audioRecorder.value.ondataavailable = (event) => { + const audioBlob = event.data + const audioUrl = URL.createObjectURL(audioBlob) + const audioElement = new Audio(audioUrl) + audioElement.play() + } + } + } + + return { + startRecord, + stopRecord, + } +} diff --git a/apps/stage-capacitor/src/composables/icon-animation.ts b/apps/stage-capacitor/src/composables/icon-animation.ts new file mode 100644 index 000000000..3149a8e5b --- /dev/null +++ b/apps/stage-capacitor/src/composables/icon-animation.ts @@ -0,0 +1,29 @@ +import { useSettings } from '@proj-airi/stage-ui/stores/settings' +import { computed, onMounted, onUnmounted, ref } from 'vue' + +export function useIconAnimation(icon: string) { + const iconAnimationStarted = ref(false) + const showAnimationComponent = ref(false) + const animationIcon = ref(icon) + + const settingsStore = useSettings() + const showIconAnimation = computed(() => showAnimationComponent.value && !settingsStore.disableTransitions && settingsStore.usePageSpecificTransitions) + + onMounted(() => { + showAnimationComponent.value = true + requestAnimationFrame(() => { + iconAnimationStarted.value = true + }) + }) + + onUnmounted(() => { + iconAnimationStarted.value = false + showAnimationComponent.value = false + }) + + return { + iconAnimationStarted, + showIconAnimation, + animationIcon, + } +} diff --git a/apps/stage-capacitor/src/composables/theme-color.ts b/apps/stage-capacitor/src/composables/theme-color.ts new file mode 100644 index 000000000..18db8f6bf --- /dev/null +++ b/apps/stage-capacitor/src/composables/theme-color.ts @@ -0,0 +1,193 @@ +import type { Ref } from 'vue' + +import type { BackgroundProvider } from '../components/Backgrounds' +import type { BackgroundItem } from '../stores/background' + +import Color from 'colorjs.io' + +import { withRetry } from '@moeru/std' +import { colorFromElement, patchThemeSamplingHtml2CanvasClone } from '@proj-airi/stage-ui/libs' +import { useSettings } from '@proj-airi/stage-ui/stores/settings' +import { useTheme } from '@proj-airi/ui' +import { useDocumentVisibility, useIntervalFn } from '@vueuse/core' +import { storeToRefs } from 'pinia' +import { nextTick, watch } from 'vue' + +import { BackgroundKind } from '../stores/background' + +export function themeColorFromPropertyOf(colorFromClass: string, property: string): () => Promise { + return async () => { + const fetchUntilWidgetMounted = withRetry(() => { + const widgets = document.querySelector(colorFromClass) as HTMLDivElement | undefined + if (!widgets) + throw new Error('Widgets element not found') + + return widgets + }, { retry: 10, retryDelay: 1000 }) + + const widgets = await fetchUntilWidgetMounted() + return window.getComputedStyle(widgets).getPropertyValue(property) + } +} + +export function themeColorFromValue(value: string | { light: string, dark: string }): () => Promise { + return async () => { + if (typeof value === 'string') { + return value + } + else { + const { isDark: dark } = useTheme() + return dark.value ? value.dark : value.light + } + } +} + +export function useThemeColor(colorFrom: () => string | Promise) { + async function updateThemeColor() { + if (!('document' in globalThis) || globalThis.document == null) + return + if (!('window' in globalThis) || globalThis.window == null) + return + + document.querySelector('meta[name="theme-color"]')?.setAttribute('content', new Color(await colorFrom()).to('srgb').toString({ format: 'hex' })) + } + + return { + updateThemeColor, + } +} + +export function useBackgroundThemeColor({ + backgroundSurface, + selectedOption, + sampledColor, +}: { + backgroundSurface: Ref | undefined | null> + selectedOption: Ref + sampledColor: Ref +}) { + const visibility = useDocumentVisibility() + const { themeColorsHueDynamic } = storeToRefs(useSettings()) + + let samplingToken = 0 + + const { isDark } = useTheme() + const waveThemeColor = themeColorFromPropertyOf('.widgets.top-widgets .colored-area', 'background-color') + + const { updateThemeColor } = useThemeColor(() => { + if (selectedOption.value?.kind === BackgroundKind.Wave) { + return waveThemeColor() + } + + return sampledColor.value + }) + + // Keep theme-color reasonably fresh for animated wave backgrounds without doing per-frame work. + const { pause, resume } = useIntervalFn(() => { + if (visibility.value !== 'visible') + return + if (selectedOption.value?.kind === BackgroundKind.Wave && themeColorsHueDynamic) + void updateThemeColor() + }, 250, { immediate: false }) + + watch([() => selectedOption.value?.kind, () => themeColorsHueDynamic], ([kind, dynamic]) => { + if (kind === BackgroundKind.Wave && dynamic) { + void updateThemeColor() + resume() + } + else { + pause() + } + }, { immediate: true }) + + async function waitForBackgroundReady() { + await nextTick() + const image = backgroundSurface.value?.surfaceEl?.querySelector('img') + if (image && !image.complete) { + await new Promise((resolve, reject) => { + image.addEventListener('load', () => resolve(), { once: true }) + image.addEventListener('error', () => reject(new Error('Background image failed to load')), { once: true }) + }) + } + } + + // Exposed for optional manual triggers; also used within syncBackgroundTheme. + async function sampleBackgroundColor() { + const token = ++samplingToken + const optionId = selectedOption.value?.id + if (selectedOption.value?.kind === BackgroundKind.Wave) { + await updateThemeColor() + return + } + + const el = backgroundSurface.value?.surfaceEl + if (!el) + return + + await waitForBackgroundReady() + + const result = await colorFromElement(el, { + mode: 'html2canvas', + html2canvas: { + region: { + x: 0, + y: 0, + width: el.offsetWidth, + height: Math.min(140, el.offsetHeight), + }, + sampleHeight: 20, + sampleStride: 10, + scale: 0.5, + backgroundColor: null, + allowTaint: true, + useCORS: true, + onclone: patchThemeSamplingHtml2CanvasClone, + }, + }) + + const color = result.html2canvas?.average + if (token !== samplingToken) + return + if (optionId && selectedOption.value?.id !== optionId) + return + + if (color) { + sampledColor.value = color + } + } + + async function syncBackgroundTheme() { + if (selectedOption.value?.kind === BackgroundKind.Wave) { + await updateThemeColor() + } + else if (sampledColor.value) { + await updateThemeColor() + } + else { + await sampleBackgroundColor() + } + } + + watch([selectedOption], () => { + syncBackgroundTheme() + }, { immediate: true }) + + watch(sampledColor, () => { + syncBackgroundTheme() + }) + + watch(() => backgroundSurface.value?.surfaceEl, (el) => { + if (el) + syncBackgroundTheme() + }) + + watch(isDark, () => { + syncBackgroundTheme() + }) + + return { + sampledColor, + sampleBackgroundColor, + syncBackgroundTheme, + } +} diff --git a/apps/stage-capacitor/src/layouts/default.vue b/apps/stage-capacitor/src/layouts/default.vue new file mode 100644 index 000000000..e917d47bc --- /dev/null +++ b/apps/stage-capacitor/src/layouts/default.vue @@ -0,0 +1,30 @@ + + + diff --git a/apps/stage-capacitor/src/layouts/home.vue b/apps/stage-capacitor/src/layouts/home.vue new file mode 100644 index 000000000..2b34eac02 --- /dev/null +++ b/apps/stage-capacitor/src/layouts/home.vue @@ -0,0 +1,20 @@ + + + diff --git a/apps/stage-capacitor/src/layouts/plain.vue b/apps/stage-capacitor/src/layouts/plain.vue new file mode 100644 index 000000000..7c2aa3f3e --- /dev/null +++ b/apps/stage-capacitor/src/layouts/plain.vue @@ -0,0 +1,3 @@ + diff --git a/apps/stage-capacitor/src/layouts/settings.vue b/apps/stage-capacitor/src/layouts/settings.vue new file mode 100644 index 000000000..3645f1286 --- /dev/null +++ b/apps/stage-capacitor/src/layouts/settings.vue @@ -0,0 +1,157 @@ + + + diff --git a/apps/stage-capacitor/src/layouts/stage.vue b/apps/stage-capacitor/src/layouts/stage.vue new file mode 100644 index 000000000..cd46f3ce6 --- /dev/null +++ b/apps/stage-capacitor/src/layouts/stage.vue @@ -0,0 +1,9 @@ + + + diff --git a/apps/stage-capacitor/src/main.ts b/apps/stage-capacitor/src/main.ts new file mode 100644 index 000000000..4cdd0ee6c --- /dev/null +++ b/apps/stage-capacitor/src/main.ts @@ -0,0 +1,95 @@ +import type { Plugin } from 'vue' +import type { Router, RouteRecordRaw } from 'vue-router' + +import Tres from '@tresjs/core' +import NProgress from 'nprogress' + +import { autoAnimatePlugin } from '@formkit/auto-animate/vue' +import { MotionPlugin } from '@vueuse/motion' +import { createPinia } from 'pinia' +import { setupLayouts } from 'virtual:generated-layouts' +import { createApp } from 'vue' +import { createRouter, createWebHashHistory, createWebHistory } from 'vue-router' +import { routes } from 'vue-router/auto-routes' + +import App from './App.vue' + +import { i18n } from './modules/i18n' + +import './modules/posthog' + +// eslint-disable-next-line perfectionist/sort-imports +import '@proj-airi/font-cjkfonts-allseto/index.css' +import '@proj-airi/font-xiaolai/index.css' +import '@unocss/reset/tailwind.css' +import './styles/main.css' +import 'uno.css' + +const pinia = createPinia() + +// TODO: vite-plugin-vue-layouts is long deprecated, replace with another layout solution +const routeRecords = setupLayouts(routes as RouteRecordRaw[]) + +let router: Router +if (import.meta.env.VITE_APP_TARGET_HUGGINGFACE_SPACE) + router = createRouter({ routes: routeRecords, history: createWebHashHistory() }) +else + router = createRouter({ routes: routeRecords, history: createWebHistory() }) + +router.beforeEach((to, from) => { + if (to.path !== from.path) + NProgress.start() +}) + +router.afterEach(() => { + NProgress.done() +}) + +window.addEventListener('unhandledrejection', (event) => { + console.warn('Unhandled rejection:', event.reason) +}) + +createApp(App) + .use(MotionPlugin) + // TODO: Fix autoAnimatePlugin type error + .use(autoAnimatePlugin as unknown as Plugin) + .use(router) + .use(pinia) + .use(i18n) + .use(Tres) + .mount('#app') + +if (import.meta.env.DEV && !import.meta.env.SSR) { + function captureEvents(el: HTMLElement) { + // Force `pointer-events: auto` as DismissableLayer in Reka UI adds + // `pointer-events: none` to document body. + el.style.pointerEvents = 'auto' + + // We need to capture events inside elements like devtools to prevent them + // from leaking to other layers (like DismissableLayer in Reka UI). + // + // See: https://github.com/unovue/reka-ui/blob/14866201d179b8bae3c8b4346a1ca8eff1c5eaa4/packages/radix-vue/src/DismissableLayer/DismissableLayer.vue#L186-L188 + el.addEventListener('focus', e => e.stopPropagation(), { capture: true }) + el.addEventListener('blur', e => e.stopPropagation(), { capture: true }) + el.addEventListener('pointerdown', e => e.stopPropagation(), { capture: true }) + } + + const observer = new MutationObserver((mutationsList, observer) => { + for (const mutation of mutationsList) { + if (mutation.type === 'childList') { + const devtoolsContainer = document.getElementById('__vue-devtools-container__') + + if (devtoolsContainer) { + captureEvents(devtoolsContainer) + observer.disconnect() + } + } + } + }) + + observer.observe(document.body, { childList: true, subtree: true }) + + // Disconnect on timeout in case the MutationObserver is left here forever. + // `observer.disconnect()` is idempotent, so it's safe to call it multiple times. + setTimeout(() => observer.disconnect(), 15 * 1000) +} diff --git a/apps/stage-capacitor/src/modules/i18n.ts b/apps/stage-capacitor/src/modules/i18n.ts new file mode 100644 index 000000000..a1f450752 --- /dev/null +++ b/apps/stage-capacitor/src/modules/i18n.ts @@ -0,0 +1,49 @@ +import messages from '@proj-airi/i18n/locales' + +import { createI18n } from 'vue-i18n' + +const languageRemap: Record = { + 'zh-CN': 'zh-Hans', + 'zh-TW': 'zh-Hant', + 'zh-HK': 'zh-Hans', // TODO: remove this when zh-Hant is supported + 'zh-Hant': 'zh-Hans', // TODO: remove this when zh-Hant is supported + 'en-US': 'en', + 'en-GB': 'en', + 'en-AU': 'en', + 'en': 'en', + 'es-ES': 'es', + 'es-MX': 'es', + 'es-AR': 'es', + 'es': 'es', + 'vi': 'vi', + 'vi-VN': 'vi', + 'ru': 'ru', + 'ru-RU': 'ru', + 'fr': 'fr', + 'fr-FR': 'fr', +} + +function getLocale() { + let language = localStorage.getItem('settings/language') + + if (!language) { + // Fallback to browser language + language = navigator.language || 'en' + } + + const languages = Object.keys(messages!) + if (languageRemap[language || 'en'] != null) { + language = languageRemap[language || 'en'] + } + if (language && languages.includes(language)) + return language + + return 'en' +} + +export const i18n = createI18n({ + legacy: false, + locale: getLocale(), + fallbackLocale: 'en', + messages, +}) diff --git a/apps/stage-capacitor/src/modules/posthog.ts b/apps/stage-capacitor/src/modules/posthog.ts new file mode 100644 index 000000000..af8a46f8b --- /dev/null +++ b/apps/stage-capacitor/src/modules/posthog.ts @@ -0,0 +1,6 @@ +import posthog from 'posthog-js' + +posthog.init('phc_pzjziJjrVZpa9SqnQqq0QEKvkmuCPH7GDTA6TbRTEf9', { + api_host: 'https://us.i.posthog.com', + person_profiles: 'identified_only', // or 'always' to create profiles for anonymous users as well +}) diff --git a/apps/stage-capacitor/src/modules/pwa.ts b/apps/stage-capacitor/src/modules/pwa.ts new file mode 100644 index 000000000..5804fd1a5 --- /dev/null +++ b/apps/stage-capacitor/src/modules/pwa.ts @@ -0,0 +1 @@ +export { registerSW } from 'virtual:pwa-register' diff --git a/apps/stage-capacitor/src/pages/[...all].vue b/apps/stage-capacitor/src/pages/[...all].vue new file mode 100644 index 000000000..5a92e2244 --- /dev/null +++ b/apps/stage-capacitor/src/pages/[...all].vue @@ -0,0 +1,19 @@ + + + diff --git a/apps/stage-capacitor/src/pages/devtools/audio-record.vue b/apps/stage-capacitor/src/pages/devtools/audio-record.vue new file mode 100644 index 000000000..1d264e8b1 --- /dev/null +++ b/apps/stage-capacitor/src/pages/devtools/audio-record.vue @@ -0,0 +1,75 @@ + + + diff --git a/apps/stage-capacitor/src/pages/devtools/background-gradient-blending.vue b/apps/stage-capacitor/src/pages/devtools/background-gradient-blending.vue new file mode 100644 index 000000000..d004edf0a --- /dev/null +++ b/apps/stage-capacitor/src/pages/devtools/background-gradient-blending.vue @@ -0,0 +1,221 @@ + + + + + diff --git a/apps/stage-capacitor/src/pages/devtools/background-removal.vue b/apps/stage-capacitor/src/pages/devtools/background-removal.vue new file mode 100644 index 000000000..2877391d0 --- /dev/null +++ b/apps/stage-capacitor/src/pages/devtools/background-removal.vue @@ -0,0 +1,393 @@ + + + diff --git a/apps/stage-capacitor/src/pages/devtools/gesture-circle.vue b/apps/stage-capacitor/src/pages/devtools/gesture-circle.vue new file mode 100644 index 000000000..80d6bf3a0 --- /dev/null +++ b/apps/stage-capacitor/src/pages/devtools/gesture-circle.vue @@ -0,0 +1,179 @@ + + + + + +meta: + layout: plain + diff --git a/apps/stage-capacitor/src/pages/devtools/performance-playground.vue b/apps/stage-capacitor/src/pages/devtools/performance-playground.vue new file mode 100644 index 000000000..a1e866038 --- /dev/null +++ b/apps/stage-capacitor/src/pages/devtools/performance-playground.vue @@ -0,0 +1,311 @@ + + + + + +meta: + layout: settings + diff --git a/apps/stage-capacitor/src/pages/devtools/polaroid.vue b/apps/stage-capacitor/src/pages/devtools/polaroid.vue new file mode 100644 index 000000000..202a1eeb5 --- /dev/null +++ b/apps/stage-capacitor/src/pages/devtools/polaroid.vue @@ -0,0 +1,94 @@ + + + diff --git a/apps/stage-capacitor/src/pages/devtools/use-magic-keys.vue b/apps/stage-capacitor/src/pages/devtools/use-magic-keys.vue new file mode 100644 index 000000000..14229058b --- /dev/null +++ b/apps/stage-capacitor/src/pages/devtools/use-magic-keys.vue @@ -0,0 +1,131 @@ + + + diff --git a/apps/stage-capacitor/src/pages/index.vue b/apps/stage-capacitor/src/pages/index.vue new file mode 100644 index 000000000..3bb504c09 --- /dev/null +++ b/apps/stage-capacitor/src/pages/index.vue @@ -0,0 +1,213 @@ + + + + + +name: IndexScenePage +meta: + layout: stage + stageTransition: + name: bubble-wave-out + diff --git a/apps/stage-capacitor/src/pages/settings/system/developer.vue b/apps/stage-capacitor/src/pages/settings/system/developer.vue new file mode 100644 index 000000000..a104e4736 --- /dev/null +++ b/apps/stage-capacitor/src/pages/settings/system/developer.vue @@ -0,0 +1,145 @@ + + + + + +meta: + layout: settings + stageTransition: + name: slide + diff --git a/apps/stage-capacitor/src/pages/settings/system/index.vue b/apps/stage-capacitor/src/pages/settings/system/index.vue new file mode 100644 index 000000000..8b14d1d55 --- /dev/null +++ b/apps/stage-capacitor/src/pages/settings/system/index.vue @@ -0,0 +1,74 @@ + + + + + +meta: + layout: settings + stageTransition: + name: slide + pageSpecificAvailable: true + diff --git a/apps/stage-capacitor/src/stores/background.ts b/apps/stage-capacitor/src/stores/background.ts new file mode 100644 index 000000000..b7907d723 --- /dev/null +++ b/apps/stage-capacitor/src/stores/background.ts @@ -0,0 +1,279 @@ +import type { BackgroundOption } from '@proj-airi/stage-ui/components' +import type { Ref, ShallowRef } from 'vue' + +import localforage from 'localforage' + +import { useLocalStorage, useObjectUrl } from '@vueuse/core' +import { defineStore } from 'pinia' +import { computed, markRaw, onScopeDispose, ref, shallowRef } from 'vue' + +import { DefaultBackgroundPreview } from '../components/Backgrounds/default' + +export enum BackgroundKind { + Wave = 'wave', + Image = 'image', +} + +export interface BackgroundItem extends BackgroundOption { + kind: BackgroundKind + importedAt?: number +} + +type PersistedBackgroundItem = Omit & { + file?: Blob +} + +export const useBackgroundStore = defineStore('background', () => { + // TODO: STORAGE_PREFIX used with multiple less maintainable `localforage` and `key.startsWith(...)` call that creates complexity. + const STORAGE_PREFIX = 'background-' + const presets: BackgroundItem[] = [ + { + id: 'colorful-wave', + label: 'Colorful Wave', + description: 'Animated wave on cross grid', + kind: BackgroundKind.Wave, + component: markRaw(DefaultBackgroundPreview), + }, + ] + + const options = ref([...presets]) + const loading = ref(false) + + const selectedId = useLocalStorage('settings/theme/background/selected-id', options.value[0]?.id) + const sampledColor = useLocalStorage('settings/theme/background/sampled-color', '') + + const selectedOption = computed(() => options.value.find(option => option.id === selectedId.value) ?? options.value[0]) + + const blobRefs = new Map>() + const urlRefs = new Map>>() + + function ensureObjectUrl(id: string, blob: Blob) { + let blobRef = blobRefs.get(id) + let urlRef = urlRefs.get(id) + + if (!blobRef || !urlRef) { + blobRef = shallowRef(blob) + blobRefs.set(id, blobRef) + urlRef = useObjectUrl(blobRef) + urlRefs.set(id, urlRef) + } + + if (blobRef.value !== blob) + blobRef.value = blob + + return urlRef!.value! + } + + onScopeDispose(() => { + blobRefs.clear() + urlRefs.clear() + }) + + async function migrateDataUrlToBlob(key: string, val: PersistedBackgroundItem, dataUrl: string) { + try { + const blob = await (await fetch(dataUrl)).blob() + const objectUrl = ensureObjectUrl(key, blob) + + const existing = options.value.find(o => o.id === key) + if (existing) { + existing.src = objectUrl + existing.file = undefined + } + + const payload: PersistedBackgroundItem = { + ...val, + src: undefined, + file: blob, + } + + await localforage.setItem(key, payload) + } + catch (error) { + console.error('Failed to migrate background data URL to Blob', error) + } + } + + function setSelection(option: BackgroundItem, color?: string) { + selectedId.value = option.id + if (color) + sampledColor.value = color + } + + async function applyPickerSelection(payload: { option: BackgroundOption, color?: string }) { + const kind = payload.option.kind === BackgroundKind.Wave + ? BackgroundKind.Wave + : payload.option.kind === BackgroundKind.Image + ? BackgroundKind.Image + : BackgroundKind.Image + + const selection: BackgroundItem = { + ...payload.option, + kind, + } + + const saved = await addOption(selection) + setSelection(saved, payload.color) + return saved + } + + async function loadFromIndexedDb() { + if (loading.value) + return + loading.value = true + const stored: BackgroundItem[] = [] + try { + await localforage.iterate((val, key) => { + if (!key.startsWith(STORAGE_PREFIX)) + return + + const storedBlob = val.file instanceof Blob ? val.file : undefined + const storedSrc = typeof val.src === 'string' && val.src.length > 0 ? val.src : undefined + + if (storedBlob) { + const objectUrl = ensureObjectUrl(key, storedBlob) + stored.push({ + ...val, + id: key, + kind: BackgroundKind.Image, + src: objectUrl, + file: undefined, + component: undefined, + removable: true, + }) + return + } + + if (storedSrc) { + stored.push({ + ...val, + id: key, + kind: BackgroundKind.Image, + src: storedSrc, + file: undefined, + component: undefined, + removable: true, + }) + + if (storedSrc.startsWith('data:')) { + setTimeout(() => { + void migrateDataUrlToBlob(key, val, storedSrc) + }, 0) + } + } + }) + } + catch (error) { + console.error('Failed to load backgrounds from IndexedDB', error) + } + + options.value = [...presets, ...stored].sort((a, b) => (b.importedAt ?? 0) - (a.importedAt ?? 0)) + loading.value = false + } + + void loadFromIndexedDb() + + async function addOption(option: BackgroundItem): Promise { + const normalizedId = option.file ? (option.id.startsWith(STORAGE_PREFIX) ? option.id : `${STORAGE_PREFIX}${option.id}`) : option.id + + const hasUploadedFile = option.file instanceof Blob + const storedBlob = hasUploadedFile ? option.file : undefined + + const src = storedBlob + ? ensureObjectUrl(normalizedId, storedBlob) + : option.src + + const normalizedOption: BackgroundItem = { + ...option, + id: normalizedId, + kind: option.kind ?? BackgroundKind.Image, + component: option.component ? markRaw(option.component) : option.component, + src, + importedAt: option.importedAt ?? Date.now(), + blur: option.blur, + file: undefined, + removable: true, + } + + const existing = options.value.find(o => o.id === normalizedId) + if (existing) { + Object.assign(existing, normalizedOption) + } + else { + options.value.push(normalizedOption) + } + selectedId.value = normalizedId + + if (hasUploadedFile && storedBlob) { + const payload: PersistedBackgroundItem = { + ...normalizedOption, + // ensure we store under prefix for consistency + id: normalizedId.startsWith(STORAGE_PREFIX) ? normalizedId : `${STORAGE_PREFIX}${normalizedId}`, + src: undefined, + file: storedBlob, + removable: true, + } + try { + await localforage.setItem(payload.id, payload) + } + catch (error) { + console.error('Failed to persist background', error) + } + } + + return normalizedOption + } + + async function removeOption(optionId: string) { + const optionIndex = options.value.findIndex(o => o.id === optionId) + if (optionIndex === -1) + return + + const option = options.value[optionIndex] + + // Remove from localforage + try { + if (option.id.startsWith(STORAGE_PREFIX)) { + await localforage.removeItem(option.id) + } + } + catch (error) { + console.error('Failed to remove background from storage', error) + } + + const blobRef = blobRefs.get(optionId) + if (blobRef) + blobRef.value = undefined + blobRefs.delete(optionId) + urlRefs.delete(optionId) + + // Remove from list + options.value.splice(optionIndex, 1) + + // If selected, fallback to first available option + if (selectedId.value === optionId) { + const fallback = options.value[0] + if (fallback) { + selectedId.value = fallback.id + } + } + } + + function setSampledColor(color?: string) { + if (color) + sampledColor.value = color + } + + return { + options, + selectedId, + selectedOption, + sampledColor, + loading, + loadFromIndexedDb, + addOption, + removeOption, + setSelection, + applyPickerSelection, + setSampledColor, + } +}) diff --git a/apps/stage-capacitor/src/styles/main.css b/apps/stage-capacitor/src/styles/main.css new file mode 100755 index 000000000..6f8e46919 --- /dev/null +++ b/apps/stage-capacitor/src/styles/main.css @@ -0,0 +1,65 @@ +@import './transitions.css'; +@import './vue-transitions.css'; + +:root { + --bg-color-light: rgb(255 255 255); + --bg-color-dark: rgb(18 18 18); + --bg-color: var(--bg-color-light); +} + +/** + Disable double-tap "zoom" option in browser on touch devices + + https://stackoverflow.com/a/54207844 + https://stackoverflow.com/questions/10614481/disable-double-tap-zoom-option-in-browser-on-touch-devices + */ +* { + touch-action: manipulation; +} + +html, +body, +#app { + height: 100%; + margin: 0; + padding: 0; + overscroll-behavior: none; +} + +html { + background: var(--bg-color); + transition: all 0.3s ease-in-out; +} + +html.dark { + --bg-color: var(--bg-color-dark); + color-scheme: dark; +} + +#nprogress { + pointer-events: none; +} + +#nprogress .bar { + background: color-mix(in srgb, oklch(95% var(--chromatic-chroma-900) calc(var(--chromatic-hue) + ${0})) 70%, oklch(50% 0 360)); + opacity: 0.75; + position: fixed; + z-index: 1031; + top: 0; + left: 0; + width: 100%; + height: 2px; +} + +.dark #nprogress .bar { + background: `color-mix(in srgb, oklch(95% var(--chromatic-chroma-900) calc(var(--chromatic-hue) + ${0})) 90%, oklch(90% 0 360))`; +} + +@media (display-mode: standalone) { + #nprogress { + display: none; + } + #nprogress .bar { + display: none; + } +} diff --git a/apps/stage-capacitor/src/styles/transitions.css b/apps/stage-capacitor/src/styles/transitions.css new file mode 100644 index 000000000..82ae842e3 --- /dev/null +++ b/apps/stage-capacitor/src/styles/transitions.css @@ -0,0 +1,18 @@ +.slide-away-enter-active, +.slide-away-leave-active { + transition: + transform 0.3s ease-in-out, + opacity 0.3s ease-in-out; +} + +.slide-away-enter, +.slide-away-leave-to { + transform: translateY(-10px); + opacity: 0; +} + +.slide-away-enter-from, +.slide-away-leave { + transform: translateY(10px); + opacity: 0; +} diff --git a/apps/stage-capacitor/src/styles/vue-transitions.css b/apps/stage-capacitor/src/styles/vue-transitions.css new file mode 100644 index 000000000..2beab3d5c --- /dev/null +++ b/apps/stage-capacitor/src/styles/vue-transitions.css @@ -0,0 +1,48 @@ +.fade-slide-out-r-to-l-enter-active, +.fade-slide-out-r-to-l-leave-active { + transition: opacity 0.2s ease-in-out, transform 0.2s ease-in-out; +} + +.fade-slide-out-r-to-l-enter-from, +.fade-slide-out-r-to-l-leave-to { + opacity: 0; + transform: translateX(10px); +} + +.fade-slide-out-r-to-l-enter-to, +.fade-slide-out-r-to-l-leave-from { + opacity: 1; + transform: translateX(0); +} + +.fade-slide-out-l-to-r-enter-active, +.fade-slide-out-l-to-r-leave-active { + transition: opacity 0.2s ease-in-out, transform 0.2s ease-in-out; +} + +.fade-slide-out-l-to-r-enter-from, +.fade-slide-out-l-to-r-leave-to { + opacity: 0; + transform: translateX(-10px); +} + +.fade-slide-out-l-to-r-enter-to, +.fade-slide-out-l-to-r-leave-from { + opacity: 1; + transform: translateX(0); +} + +.fade-enter-active, +.fade-leave-active { + transition: opacity 0.2s ease-in-out; +} + +.fade-enter-from, +.fade-leave-to { + opacity: 0; +} + +.fade-enter-to, +.fade-leave-from { + opacity: 1; +} diff --git a/apps/stage-capacitor/src/utils/jsonFormat.ts b/apps/stage-capacitor/src/utils/jsonFormat.ts new file mode 100644 index 000000000..36bb17078 --- /dev/null +++ b/apps/stage-capacitor/src/utils/jsonFormat.ts @@ -0,0 +1,74 @@ +import type { CommonRequestOptions } from '@xsai/shared' +import type { Message } from '@xsai/shared-chat' +import type { Infer, Schema } from 'xsschema' + +import { generateText } from '@xsai/generate-text' +import { message } from '@xsai/utils-chat' +import { toJsonSchema, validate } from 'xsschema' + +type SchemaOrString = S extends unknown ? string : S extends Schema ? Infer : never + +async function parseJSONFormat>(content: string, options: { messages: Message[], apiKey?: string, baseURL: string, model: string } & Partial, schema?: S, erroredValue?: string, errorMessage?: string): Promise { + if (!schema) + return content as unknown as R + + try { + let parsedContent: Infer + let correctionPrompt = '' + + if (erroredValue && errorMessage) { + correctionPrompt = `Previous response "${JSON.stringify(erroredValue)}" was invalid due to: ${JSON.stringify(errorMessage)}\n\n` + } + + try { + parsedContent = JSON.parse(content) + } + catch (parseError) { + console.error('Error parsing JSON:', parseError, content) + + options.messages.push(message.user(` +${correctionPrompt}The response was not valid JSON: +${JSON.stringify(content)} + +Error: ${String(parseError)} + +Please provide a corrected JSON response that matches the schema: +${JSON.stringify(await toJsonSchema(schema))}`)) + + const response = await call(options, schema) + return parseJSONFormat(response, options, schema, content, String(parseError)) + } + + // TODO: print validation issues + return await validate(schema, parsedContent) as R + } + catch (error) { + console.error('Error processing response:', error) + throw error + } +} + +/** + * Processes user input and generates LLM response along with thought nodes. + */ +async function call>(options: { messages: Message[], apiKey?: string, baseURL: string, model: string } & Partial, schema?: S): Promise { + if (schema != null) { + options.messages.push(message.user(`Your response must follow the following schema: +${JSON.stringify(await toJsonSchema(schema))} + +Without any extra markups such as \`\`\` in markdown, or descriptions.`)) + } + + const response = await generateText({ + baseURL: options.baseURL, + apiKey: options.apiKey, + model: options.model, + messages: options.messages, + }) + + return await parseJSONFormat(response.text || '', options, schema) +} + +export async function generateObject>(options: { messages: Message[], model: string, apiKey?: string, baseURL: string } & Partial, schema?: S): Promise { + return await call(options, schema) +} diff --git a/apps/stage-capacitor/src/utils/platform.ts b/apps/stage-capacitor/src/utils/platform.ts new file mode 100644 index 000000000..a5b30f2ef --- /dev/null +++ b/apps/stage-capacitor/src/utils/platform.ts @@ -0,0 +1,18 @@ +export function isPlatformTamagotchi() { + return import.meta.env.MODE === 'tamagotchi' +} + +export function isStandalone() { + if (import.meta.env.SSR) { + return false + } + if (!('window' in globalThis) || globalThis.window == null) { + return false + } + + const mediaStandalone = ('matchMedia' in window) && window.matchMedia('(display-mode: standalone)').matches + const navigatorStandalone = ('navigator' in window && 'standalone' in window.navigator && window.navigator.standalone) + const referrerStandalone = document.referrer.includes('android-app://') + + return mediaStandalone || navigatorStandalone || referrerStandalone +} diff --git a/apps/stage-capacitor/src/workers/vad/index.ts b/apps/stage-capacitor/src/workers/vad/index.ts new file mode 100644 index 000000000..753421a38 --- /dev/null +++ b/apps/stage-capacitor/src/workers/vad/index.ts @@ -0,0 +1,3 @@ +export { createVADStates } from './manager' +export type { VADAudioOptions } from './manager' +export { createVAD, VAD } from './vad' diff --git a/apps/stage-capacitor/src/workers/vad/manager.ts b/apps/stage-capacitor/src/workers/vad/manager.ts new file mode 100644 index 000000000..8fc1108e2 --- /dev/null +++ b/apps/stage-capacitor/src/workers/vad/manager.ts @@ -0,0 +1,2 @@ +export type { VADAudioOptions } from '@proj-airi/stage-ui/libs/audio/vad' +export { createVADStates } from '@proj-airi/stage-ui/libs/audio/vad' diff --git a/apps/stage-capacitor/src/workers/vad/process.worklet.ts b/apps/stage-capacitor/src/workers/vad/process.worklet.ts new file mode 100644 index 000000000..684543d0c --- /dev/null +++ b/apps/stage-capacitor/src/workers/vad/process.worklet.ts @@ -0,0 +1,53 @@ +// vad-worklet-processor.ts +// This file needs to be registered as an AudioWorklet + +/** + * Minimum chunk size for processing audio + */ +const MIN_CHUNK_SIZE = 512 + +/** + * Global state for audio buffer accumulation + */ +let globalPointer = 0 +const globalBuffer = new Float32Array(MIN_CHUNK_SIZE) + +/** + * VAD AudioWorklet Processor - processes audio chunks and sends them to the main thread + */ +class VADProcessor extends AudioWorkletProcessor { + process(inputs: Float32Array[][], _outputs: Float32Array[][], _parameters: Record) { + const buffer = inputs[0][0] + if (!buffer) + return true // buffer is null when the stream ends + + if (buffer.length > MIN_CHUNK_SIZE) { + // If the buffer is larger than the minimum chunk size, send the entire buffer + this.port.postMessage({ buffer }) + } + else { + const remaining = MIN_CHUNK_SIZE - globalPointer + if (buffer.length >= remaining) { + // If the buffer is larger than (or equal to) the remaining space in the global buffer, copy the remaining space + globalBuffer.set(buffer.subarray(0, remaining), globalPointer) + + // Send the global buffer + this.port.postMessage({ buffer: globalBuffer }) + + // Reset the global buffer and set the remaining buffer + globalBuffer.fill(0) + globalBuffer.set(buffer.subarray(remaining), 0) + globalPointer = buffer.length - remaining + } + else { + // If the buffer is smaller than the remaining space in the global buffer, copy the buffer to the global buffer + globalBuffer.set(buffer, globalPointer) + globalPointer += buffer.length + } + } + + return true + } +} + +registerProcessor('vad-audio-worklet-processor', VADProcessor) diff --git a/apps/stage-capacitor/src/workers/vad/vad.ts b/apps/stage-capacitor/src/workers/vad/vad.ts new file mode 100644 index 000000000..1cf21fd3c --- /dev/null +++ b/apps/stage-capacitor/src/workers/vad/vad.ts @@ -0,0 +1,277 @@ +import type { PreTrainedModel } from '@huggingface/transformers' +import type { BaseVAD, BaseVADConfig, VADEventCallback, VADEvents } from '@proj-airi/stage-ui/libs/audio/vad' + +import { AutoModel, Tensor } from '@huggingface/transformers' + +/** + * Voice Activity Detection processor + */ +export class VAD implements BaseVAD { + private config: BaseVADConfig + private model: PreTrainedModel | undefined + private state: Tensor + private sampleRateTensor: Tensor + private buffer: Float32Array + private bufferPointer: number = 0 + private isRecording: boolean = false + private postSpeechSamples: number = 0 + private prevBuffers: Float32Array[] = [] + private inferenceChain: Promise = Promise.resolve() + private eventListeners: Partial[]>> = {} + private isReady: boolean = false + + constructor(userConfig: Partial = {}) { + // Default configuration + const defaultConfig: BaseVADConfig = { + sampleRate: 16000, + speechThreshold: 0.3, + exitThreshold: 0.1, + minSilenceDurationMs: 400, + speechPadMs: 80, + minSpeechDurationMs: 250, + maxBufferDuration: 30, + newBufferSize: 512, + } + + this.config = { ...defaultConfig, ...userConfig } + + this.buffer = new Float32Array(this.config.maxBufferDuration * this.config.sampleRate) + this.sampleRateTensor = new Tensor('int64', [this.config.sampleRate], []) + this.state = new Tensor('float32', new Float32Array(2 * 1 * 128), [2, 1, 128]) + } + + /** + * Initialize the VAD model + */ + public async initialize(): Promise { + try { + this.emit('status', { type: 'info', message: 'Loading VAD model...' }) + + this.model = await AutoModel.from_pretrained('onnx-community/silero-vad', { + config: { model_type: 'custom' } as any, + dtype: 'fp32', // Full-precision + }) + + this.isReady = true + this.emit('status', { type: 'info', message: 'VAD model loaded successfully' }) + } + catch (error) { + this.emit('status', { type: 'error', message: `Failed to load VAD model: ${error}` }) + throw error + } + } + + /** + * Add event listener + */ + public on(event: K, callback: VADEventCallback): void { + if (!this.eventListeners[event]) { + this.eventListeners[event] = [] + } + this.eventListeners[event]!.push(callback as any) + } + + /** + * Remove event listener + */ + public off(event: K, callback: VADEventCallback): void { + if (!this.eventListeners[event]) + return + this.eventListeners[event] = this.eventListeners[event]!.filter(cb => cb !== callback) + } + + /** + * Emit event + */ + private emit(event: K, data: VADEvents[K]): void { + if (!this.eventListeners[event]) + return + for (const callback of this.eventListeners[event]!) { + callback(data) + } + } + + /** + * Process audio buffer for speech detection + */ + public async processAudio(inputBuffer: Float32Array): Promise { + if (!this.isReady) { + throw new Error('VAD model is not initialized. Call initialize() first.') + } + + const wasRecording = this.isRecording + + // Perform VAD on the input buffer + const isSpeech = await this.detectSpeech(inputBuffer) + + // Calculate derived constants + const sampleRateMs = this.config.sampleRate / 1000 + const minSilenceDurationSamples = this.config.minSilenceDurationMs * sampleRateMs + const speechPadSamples = this.config.speechPadMs * sampleRateMs + const minSpeechDurationSamples = this.config.minSpeechDurationMs * sampleRateMs + const maxPrevBuffers = Math.ceil(speechPadSamples / this.config.newBufferSize) + + // If not currently in speech and the current buffer isn't speech, + // store it in the previous buffers queue for potential padding + if (!wasRecording && !isSpeech) { + if (this.prevBuffers.length >= maxPrevBuffers) { + this.prevBuffers.shift() + } + this.prevBuffers.push(inputBuffer.slice(0)) + return + } + + // Check if we need to handle buffer overflow + const remaining = this.buffer.length - this.bufferPointer + if (inputBuffer.length >= remaining) { + // The buffer is full, process what we have + this.buffer.set(inputBuffer.subarray(0, remaining), this.bufferPointer) + this.bufferPointer += remaining + + // Process and reset with overflow + const overflow = inputBuffer.subarray(remaining) + this.processSpeechSegment(overflow) + return + } + else { + // Add input to the buffer + this.buffer.set(inputBuffer, this.bufferPointer) + this.bufferPointer += inputBuffer.length + } + + // Handle speech detection + if (isSpeech) { + if (!this.isRecording) { + // Speech just started + this.emit('speech-start', undefined) + this.emit('status', { type: 'info', message: 'Speech detected' }) + } + + // Update state + this.isRecording = true + this.postSpeechSamples = 0 + return + } + + // At this point, we were recording but the current buffer is not speech + this.postSpeechSamples += inputBuffer.length + + // Check if silence is long enough to consider speech ended + if (this.postSpeechSamples >= minSilenceDurationSamples) { + // Check if the speech segment is long enough to process + if (this.bufferPointer < minSpeechDurationSamples) { + // Too short, reset without processing + this.reset() + return + } + + // Process the speech segment + this.processSpeechSegment() + } + } + + /** + * Detect speech in an audio buffer + */ + private async detectSpeech(buffer: Float32Array): Promise { + const input = new Tensor('float32', buffer, [1, buffer.length]) + + const { stateN, output } = await (this.inferenceChain = this.inferenceChain.then(() => + this.model?.({ + input, + sr: this.sampleRateTensor, + state: this.state, + }), + )) + + // Update the state + this.state = stateN + // Get the speech probability + const speechProb = output.data[0] + + this.emit('debug', { message: 'VAD score', data: { probability: speechProb } }) + + // Apply thresholds + return ( + speechProb > this.config.speechThreshold + || (this.isRecording && speechProb >= this.config.exitThreshold) + ) + } + + /** + * Process a complete speech segment + */ + private processSpeechSegment(overflow?: Float32Array): void { + const sampleRateMs = this.config.sampleRate / 1000 + const speechPadSamples = this.config.speechPadMs * sampleRateMs + + // Calculate duration info + const duration = (this.bufferPointer / this.config.sampleRate) * 1000 + const overflowLength = overflow?.length ?? 0 + + // Create the final buffer with padding + const prevLength = this.prevBuffers.reduce((acc, b) => acc + b.length, 0) + const finalBuffer = new Float32Array(prevLength + this.bufferPointer + speechPadSamples) + + // Add previous buffers for pre-speech padding + let offset = 0 + for (const prev of this.prevBuffers) { + finalBuffer.set(prev, offset) + offset += prev.length + } + + // Add the main speech segment + finalBuffer.set(this.buffer.slice(0, this.bufferPointer + speechPadSamples), offset) + + // Emit the speech segment + this.emit('speech-end', undefined) + this.emit('speech-ready', { + buffer: finalBuffer, + duration, + }) + + // Reset for the next segment + if (overflow) { + this.buffer.set(overflow, 0) + } + this.reset(overflowLength) + } + + /** + * Reset the VAD state + */ + private reset(offset: number = 0): void { + this.buffer.fill(0, offset) + this.bufferPointer = offset + this.isRecording = false + this.postSpeechSamples = 0 + this.prevBuffers = [] + } + + /** + * Update configuration + */ + public updateConfig(newConfig: Partial): void { + this.config = { ...this.config, ...newConfig } + + // If buffer size changed, create a new buffer + if (newConfig.maxBufferDuration || newConfig.sampleRate) { + this.buffer = new Float32Array(this.config.maxBufferDuration * this.config.sampleRate) + this.bufferPointer = 0 + } + + // Update sample rate tensor if needed + if (newConfig.sampleRate) { + this.sampleRateTensor = new Tensor('int64', [this.config.sampleRate], []) + } + } +} + +/** + * Create a VAD processor with the given configuration + */ +export async function createVAD(config?: Partial): Promise { + const vad = new VAD(config) + await vad.initialize() + return vad +} diff --git a/apps/stage-capacitor/tsconfig.json b/apps/stage-capacitor/tsconfig.json new file mode 100644 index 000000000..19602cd36 --- /dev/null +++ b/apps/stage-capacitor/tsconfig.json @@ -0,0 +1,37 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "jsx": "preserve", + "lib": [ + "DOM", + "ESNext", + "DOM.Iterable", + "DOM.AsyncIterable" + ], + "paths": { + "@proj-airi/stage-ui/*": [ + "../../packages/stage-ui/src/*" + ] + }, + "resolveJsonModule": true, + "types": [ + "vitest", + "vite/client", + "vite-plugin-vue-layouts/client", + "vite-plugin-pwa/client", + "vue-macros/macros-global", + "unplugin-vue-router/client", + "@types/audioworklet", + "unplugin-info/client" + ], + "allowJs": true, + "strict": true, + "skipLibCheck": true + }, + "vueCompilerOptions": { + "plugins": [ + "@vue-macros/volar/define-models", + "@vue-macros/volar/define-slots" + ] + } +} diff --git a/apps/stage-capacitor/uno.config.ts b/apps/stage-capacitor/uno.config.ts new file mode 100644 index 000000000..693fbd0ef --- /dev/null +++ b/apps/stage-capacitor/uno.config.ts @@ -0,0 +1,26 @@ +import { mergeConfigs, presetWebFonts } from 'unocss' + +import { presetWebFontsFonts, sharedUnoConfig } from '../../uno.config' + +export default mergeConfigs([ + sharedUnoConfig(), + { + presets: [ + presetWebFonts({ + fonts: { + ...presetWebFontsFonts('fontsource'), + }, + timeouts: { + warning: 5000, + failure: 10000, + }, + }), + ], + rules: [ + ['transition-colors-none', { + 'transition-property': 'color, background-color, border-color, text-color', + 'transition-duration': '0s', + }], + ], + }, +]) diff --git a/apps/stage-capacitor/vite-env.d.ts b/apps/stage-capacitor/vite-env.d.ts new file mode 100644 index 000000000..0a7646264 --- /dev/null +++ b/apps/stage-capacitor/vite-env.d.ts @@ -0,0 +1,9 @@ +interface ImportMetaEnv { + readonly VITE_APP_TARGET_HUGGINGFACE_SPACE: boolean + readonly VITE_PLATFORM: 'ios' | 'android' | 'web' + // more env variables... +} + +interface ImportMeta { + readonly env: ImportMetaEnv +} diff --git a/apps/stage-capacitor/vite.config.ts b/apps/stage-capacitor/vite.config.ts new file mode 100644 index 000000000..f95f61aaa --- /dev/null +++ b/apps/stage-capacitor/vite.config.ts @@ -0,0 +1,137 @@ +import { join, resolve } from 'node:path' + +import VueI18n from '@intlify/unplugin-vue-i18n/vite' +import Vue from '@vitejs/plugin-vue' +import Unocss from 'unocss/vite' +import Info from 'unplugin-info/vite' +import VueRouter from 'unplugin-vue-router/vite' +import Yaml from 'unplugin-yaml/vite' +import VueDevTools from 'vite-plugin-vue-devtools' +import Layouts from 'vite-plugin-vue-layouts' +import VueMacros from 'vue-macros/vite' + +import { Download } from '@proj-airi/unplugin-fetch/vite' +import { DownloadLive2DSDK } from '@proj-airi/unplugin-live2d-sdk/vite' +import { templateCompilerOptions } from '@tresjs/core' +import { defineConfig } from 'vite' + +const stageUIAssetsRoot = resolve(join(import.meta.dirname, '..', '..', 'packages', 'stage-ui', 'src', 'assets')) +const sharedCacheDir = resolve(join(import.meta.dirname, '..', '..', '.cache')) + +export default defineConfig({ + optimizeDeps: { + exclude: [ + // Internal Packages + '@proj-airi/stage-ui/*', + '@proj-airi/drizzle-duckdb-wasm', + '@proj-airi/drizzle-duckdb-wasm/*', + + // Static Assets: Models, Images, etc. + 'public/assets/*', + + // Live2D SDK + '@framework/live2dcubismframework', + '@framework/math/cubismmatrix44', + '@framework/type/csmvector', + '@framework/math/cubismviewmatrix', + '@framework/cubismdefaultparameterid', + '@framework/cubismmodelsettingjson', + '@framework/effect/cubismbreath', + '@framework/effect/cubismeyeblink', + '@framework/model/cubismusermodel', + '@framework/motion/acubismmotion', + '@framework/motion/cubismmotionqueuemanager', + '@framework/type/csmmap', + '@framework/utils/cubismdebug', + '@framework/model/cubismmoc', + ], + }, + resolve: { + alias: { + '@proj-airi/server-sdk': resolve(join(import.meta.dirname, '..', '..', 'packages', 'server-sdk', 'src')), + '@proj-airi/i18n': resolve(join(import.meta.dirname, '..', '..', 'packages', 'i18n', 'src')), + '@proj-airi/stage-ui': resolve(join(import.meta.dirname, '..', '..', 'packages', 'stage-ui', 'src')), + '@proj-airi/stage-pages': resolve(join(import.meta.dirname, '..', '..', 'packages', 'stage-pages', 'src')), + '@proj-airi/stage-shared': resolve(join(import.meta.dirname, '..', '..', 'packages', 'stage-shared', 'src')), + }, + }, + server: { + warmup: { + clientFiles: [ + `${resolve(join(import.meta.dirname, '..', '..', 'packages', 'stage-ui', 'src'))}/*.vue`, + `${resolve(join(import.meta.dirname, '..', '..', 'packages', 'stage-pages', 'src'))}/*.vue`, + ], + }, + }, + build: { + sourcemap: true, + }, + + plugins: [ + Info(), + + Yaml(), + + VueMacros({ + plugins: { + vue: Vue({ + include: [/\.vue$/, /\.md$/], + ...templateCompilerOptions, + }), + vueJsx: false, + }, + betterDefine: false, + }), + + // https://github.com/posva/unplugin-vue-router + VueRouter({ + extensions: ['.vue', '.md'], + dts: resolve(import.meta.dirname, 'src/typed-router.d.ts'), + importMode: 'async', + routesFolder: [ + resolve(import.meta.dirname, 'src', 'pages'), + resolve(import.meta.dirname, '..', '..', 'packages', 'stage-pages', 'src', 'pages'), + ], + }), + + // https://github.com/JohnCampionJr/vite-plugin-vue-layouts + Layouts(), + + // https://github.com/antfu/unocss + // see uno.config.ts for config + Unocss(), + + // https://github.com/intlify/bundle-tools/tree/main/packages/unplugin-vue-i18n + VueI18n({ + runtimeOnly: true, + compositionOnly: true, + fullInstall: true, + }), + + // https://github.com/webfansplz/vite-plugin-vue-devtools + VueDevTools(), + + DownloadLive2DSDK(), + Download('https://dist.ayaka.moe/live2d-models/hiyori_free_zh.zip', 'hiyori_free_zh.zip', 'live2d/models', { parentDir: stageUIAssetsRoot, cacheDir: sharedCacheDir }), + Download('https://dist.ayaka.moe/live2d-models/hiyori_pro_zh.zip', 'hiyori_pro_zh.zip', 'live2d/models', { parentDir: stageUIAssetsRoot, cacheDir: sharedCacheDir }), + Download('https://dist.ayaka.moe/vrm-models/VRoid-Hub/AvatarSample-A/AvatarSample_A.vrm', 'AvatarSample_A.vrm', 'vrm/models/AvatarSample-A', { parentDir: stageUIAssetsRoot, cacheDir: sharedCacheDir }), + Download('https://dist.ayaka.moe/vrm-models/VRoid-Hub/AvatarSample-B/AvatarSample_B.vrm', 'AvatarSample_B.vrm', 'vrm/models/AvatarSample-B', { parentDir: stageUIAssetsRoot, cacheDir: sharedCacheDir }), + + { + name: 'proj-airi:defines', + config(ctx) { + const define: Record = { + 'import.meta.env.RUNTIME_ENVIRONMENT': '\'capacitor\'', + } + if (ctx.mode === 'development') { + define['import.meta.env.URL_MODE'] = '\'server\'' + } + if (ctx.mode === 'production') { + define['import.meta.env.URL_MODE'] = '\'file\'' + } + + return { define } + }, + }, + ], +}) diff --git a/packages/stage-shared/src/beat-sync/detector.ts b/packages/stage-shared/src/beat-sync/detector.ts index caab03900..b953fb7e2 100644 --- a/packages/stage-shared/src/beat-sync/detector.ts +++ b/packages/stage-shared/src/beat-sync/detector.ts @@ -43,6 +43,8 @@ export type CreateBeatSyncDetectorOptions = | } | { env: StageEnvironment.Web + } | { + env: StageEnvironment.Capacitor } export function createBeatSyncDetector(options: CreateBeatSyncDetectorOptions): BeatSyncDetector { diff --git a/packages/stage-shared/src/environment.ts b/packages/stage-shared/src/environment.ts index 8269eea76..e34fe96e0 100644 --- a/packages/stage-shared/src/environment.ts +++ b/packages/stage-shared/src/environment.ts @@ -1,5 +1,6 @@ export enum StageEnvironment { Web = 'web', + Capacitor = 'capacitor', Tamagotchi = 'tamagotchi', } @@ -7,6 +8,10 @@ export function isStageWeb(): boolean { return !import.meta.env.RUNTIME_ENVIRONMENT || import.meta.env.RUNTIME_ENVIRONMENT === 'browser' } +export function isStageCapacitor(): boolean { + return import.meta.env.RUNTIME_ENVIRONMENT === 'capacitor' +} + export function isStageTamagotchi(): boolean { return import.meta.env.RUNTIME_ENVIRONMENT === 'electron' } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 8859ef006..616f7b251 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -6,6 +6,15 @@ settings: catalogs: default: + '@capacitor/cli': + specifier: ^8.0.0 + version: 8.0.0 + '@capacitor/core': + specifier: ^8.0.0 + version: 8.0.0 + '@capacitor/ios': + specifier: ^8.0.0 + version: 8.0.0 '@guiiai/logg': specifier: ^1.2.11 version: 1.2.11 @@ -298,6 +307,352 @@ importers: specifier: ^3.1.8 version: 3.2.1(typescript@5.9.3) + apps/stage-capacitor: + dependencies: + '@capacitor/core': + specifier: 'catalog:' + version: 8.0.0 + '@capacitor/ios': + specifier: 'catalog:' + version: 8.0.0(@capacitor/core@8.0.0) + '@date-fns/utc': + specifier: ^2.1.1 + version: 2.1.1 + '@formkit/auto-animate': + specifier: ^0.9.0 + version: 0.9.0 + '@huggingface/transformers': + specifier: ^3.8.1 + version: 3.8.1 + '@moeru/eventa': + specifier: ^1.0.0-alpha.10 + version: 1.0.0-alpha.10(electron@39.2.7)(h3@2.0.1-rc.5(crossws@0.4.1(srvx@0.9.8))) + '@moeru/std': + specifier: 'catalog:' + version: 0.1.0-beta.14 + '@proj-airi/audio': + specifier: workspace:^ + version: link:../../packages/audio + '@proj-airi/ccc': + specifier: workspace:^ + version: link:../../packages/ccc + '@proj-airi/drizzle-duckdb-wasm': + specifier: 'catalog:' + version: 0.4.29(drizzle-orm@0.45.1(@opentelemetry/api@1.9.0)(@types/pg@8.16.0)(pg@8.16.3)(postgres@3.4.7)) + '@proj-airi/font-cjkfonts-allseto': + specifier: workspace:^ + version: link:../../packages/font-cjkfonts-allseto + '@proj-airi/font-xiaolai': + specifier: workspace:^ + version: link:../../packages/font-xiaolai + '@proj-airi/i18n': + specifier: workspace:^ + version: link:../../packages/i18n + '@proj-airi/server-sdk': + specifier: workspace:^ + version: link:../../packages/server-sdk + '@proj-airi/stage-ui': + specifier: workspace:^ + version: link:../../packages/stage-ui + '@proj-airi/stage-ui-three': + specifier: workspace:^ + version: link:../../packages/stage-ui-three + '@proj-airi/stage-ui-three-performance-runtime': + specifier: workspace:^ + version: link:../../packages/stage-ui-three-performance-runtime + '@proj-airi/ui': + specifier: workspace:^ + version: link:../../packages/ui + '@proj-airi/ui-transitions': + specifier: workspace:^ + version: link:../../packages/ui-transitions + '@standard-schema/spec': + specifier: ^1.1.0 + version: 1.1.0 + '@stdlib/string-base-kebabcase': + specifier: ^0.2.2 + version: 0.2.2 + '@tresjs/cientos': + specifier: ^5.2.1 + version: 5.2.1(@tresjs/core@5.2.1(three@0.182.0)(vue@3.5.25(typescript@5.9.3)))(@types/three@0.182.0)(react@19.2.3)(three@0.182.0)(vue@3.5.25(typescript@5.9.3)) + '@tresjs/core': + specifier: ^5.2.1 + version: 5.2.1(three@0.182.0)(vue@3.5.25(typescript@5.9.3)) + '@valibot/to-json-schema': + specifier: 1.0.0-rc.0 + version: 1.0.0-rc.0(valibot@1.2.0(typescript@5.9.3)) + '@vueuse/core': + specifier: ^14.1.0 + version: 14.1.0(vue@3.5.25(typescript@5.9.3)) + '@vueuse/shared': + specifier: ^14.1.0 + version: 14.1.0(vue@3.5.25(typescript@5.9.3)) + '@xsai-ext/providers': + specifier: 'catalog:' + version: 0.4.0-beta.13 + '@xsai-transformers/embed': + specifier: ^0.0.11 + version: 0.0.11(electron@39.2.7)(h3@2.0.1-rc.5(crossws@0.4.1(srvx@0.9.8))) + '@xsai/generate-speech': + specifier: 'catalog:' + version: 0.4.0-beta.13 + '@xsai/generate-text': + specifier: 'catalog:' + version: 0.4.0-beta.13 + '@xsai/model': + specifier: 'catalog:' + version: 0.4.0-beta.13 + '@xsai/shared': + specifier: 'catalog:' + version: 0.4.0-beta.13 + '@xsai/shared-chat': + specifier: 'catalog:' + version: 0.4.0-beta.13 + '@xsai/stream-text': + specifier: 'catalog:' + version: 0.4.0-beta.13 + '@xsai/stream-transcription': + specifier: 0.4.0-beta.8 + version: 0.4.0-beta.8 + '@xsai/utils-chat': + specifier: 'catalog:' + version: 0.4.0-beta.13 + animejs: + specifier: ^4.2.2 + version: 4.2.2 + colorjs.io: + specifier: ^0.6.0 + version: 0.6.0 + culori: + specifier: ^4.0.2 + version: 4.0.2 + date-fns: + specifier: ^4.1.0 + version: 4.1.0 + dompurify: + specifier: ^3.3.1 + version: 3.3.1 + driver.js: + specifier: ^1.4.0 + version: 1.4.0 + drizzle-kit: + specifier: ^0.31.8 + version: 0.31.8 + drizzle-orm: + specifier: ^0.45.1 + version: 0.45.1(@opentelemetry/api@1.9.0)(@types/pg@8.16.0)(pg@8.16.3)(postgres@3.4.7) + gpuu: + specifier: ^1.0.6 + version: 1.0.6 + html2canvas: + specifier: ^1.4.1 + version: 1.4.1 + jszip: + specifier: ^3.10.1 + version: 3.10.1 + localforage: + specifier: ^1.10.0 + version: 1.10.0 + mediabunny: + specifier: ^1.27.2 + version: 1.27.2 + nanoid: + specifier: ^5.1.6 + version: 5.1.6 + node-vibrant: + specifier: ^4.0.3 + version: 4.0.3(encoding@0.1.13) + nprogress: + specifier: ^0.2.0 + version: 0.2.0 + ofetch: + specifier: ^1.5.1 + version: 1.5.1 + onnxruntime-web: + specifier: ^1.23.2 + version: 1.23.2 + pinia: + specifier: ^3.0.4 + version: 3.0.4(typescript@5.9.3)(vue@3.5.25(typescript@5.9.3)) + posthog-js: + specifier: 'catalog:' + version: 1.306.1 + rehype-stringify: + specifier: ^10.0.1 + version: 10.0.1 + reka-ui: + specifier: ^2.7.0 + version: 2.7.0(typescript@5.9.3)(vue@3.5.25(typescript@5.9.3)) + remark-parse: + specifier: ^11.0.0 + version: 11.0.0 + remark-rehype: + specifier: ^11.1.2 + version: 11.1.2 + shiki: + specifier: ^3.20.0 + version: 3.20.0 + three: + specifier: ^0.182.0 + version: 0.182.0 + unified: + specifier: ^11.0.5 + version: 11.0.5 + unspeech: + specifier: ^0.1.7 + version: 0.1.7 + uuid: + specifier: ^13.0.0 + version: 13.0.0 + valibot: + specifier: ^1.2.0 + version: 1.2.0(typescript@5.9.3) + vaul-vue: + specifier: ^0.4.1 + version: 0.4.1(reka-ui@2.7.0(typescript@5.9.3)(vue@3.5.25(typescript@5.9.3)))(vue@3.5.25(typescript@5.9.3)) + vue: + specifier: ^3.5.25 + version: 3.5.25(typescript@5.9.3) + vue-demi: + specifier: ^0.14.10 + version: 0.14.10(vue@3.5.25(typescript@5.9.3)) + vue-i18n: + specifier: ^11.2.2 + version: 11.2.7(vue@3.5.25(typescript@5.9.3)) + vue-router: + specifier: ^4.6.4 + version: 4.6.4(vue@3.5.25(typescript@5.9.3)) + vue-sonner: + specifier: ^2.0.9 + version: 2.0.9 + workbox-window: + specifier: ^7.4.0 + version: 7.4.0 + xsschema: + specifier: 'catalog:' + version: 0.4.0-beta.13(@valibot/to-json-schema@1.0.0-rc.0(valibot@1.2.0(typescript@5.9.3)))(zod-to-json-schema@3.25.1(zod@4.2.1))(zod@4.2.1) + yauzl: + specifier: ^3.2.0 + version: 3.2.0 + zod: + specifier: ^4.2.1 + version: 4.2.1 + devDependencies: + '@capacitor/cli': + specifier: 'catalog:' + version: 8.0.0 + '@iconify-json/carbon': + specifier: ^1.2.15 + version: 1.2.15 + '@iconify-json/eos-icons': + specifier: ^1.2.4 + version: 1.2.4 + '@iconify-json/lucide': + specifier: ^1.2.82 + version: 1.2.82 + '@iconify-json/mingcute': + specifier: ^1.2.6 + version: 1.2.6 + '@iconify-json/ph': + specifier: ^1.2.2 + version: 1.2.2 + '@iconify-json/simple-icons': + specifier: ^1.2.63 + version: 1.2.64 + '@iconify-json/solar': + specifier: ^1.2.5 + version: 1.2.5 + '@iconify-json/svg-spinners': + specifier: ^1.2.4 + version: 1.2.4 + '@iconify-json/vscode-icons': + specifier: ^1.2.37 + version: 1.2.37 + '@intlify/unplugin-vue-i18n': + specifier: ^11.0.1 + version: 11.0.3(@vue/compiler-dom@3.5.26)(eslint@9.39.2(jiti@2.6.1))(rollup@2.79.2)(typescript@5.9.3)(vue-i18n@11.2.7(vue@3.5.25(typescript@5.9.3)))(vue@3.5.25(typescript@5.9.3)) + '@proj-airi/lobe-icons': + specifier: ^1.0.18 + version: 1.0.18 + '@proj-airi/unplugin-fetch': + specifier: ^0.2.1 + version: 0.2.1(rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.25.12)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) + '@proj-airi/unplugin-live2d-sdk': + specifier: ^0.1.6 + version: 0.1.6(@types/node@24.10.4)(jiti@2.6.1)(less@4.5.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) + '@proj-airi/vite-plugin-warpdrive': + specifier: workspace:* + version: link:../../packages/vite-plugin-warpdrive + '@shikijs/markdown-it': + specifier: ^3.20.0 + version: 3.20.0 + '@types/audioworklet': + specifier: 'catalog:' + version: 0.0.92 + '@types/culori': + specifier: ^4.0.1 + version: 4.0.1 + '@types/nprogress': + specifier: ^0.2.3 + version: 0.2.3 + '@types/three': + specifier: ^0.182.0 + version: 0.182.0 + '@types/yauzl': + specifier: ^2.10.3 + version: 2.10.3 + '@unocss/reset': + specifier: ^66.5.11 + version: 66.5.11 + '@vitejs/plugin-vue': + specifier: ^6.0.3 + version: 6.0.3(rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.25.12)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))(vue@3.5.25(typescript@5.9.3)) + '@vue-macros/volar': + specifier: ^3.1.1 + version: 3.1.1(typescript@5.9.3)(vue-tsc@3.2.1(typescript@5.9.3))(vue@3.5.25(typescript@5.9.3)) + '@vueuse/motion': + specifier: ^3.0.3 + version: 3.0.3(magicast@0.5.1)(vue@3.5.25(typescript@5.9.3)) + csstype: + specifier: ^3.2.3 + version: 3.2.3 + hfup: + specifier: ^1.0.0 + version: 1.0.0 + less: + specifier: ^4.5.1 + version: 4.5.1 + unplugin-info: + specifier: ^1.2.4 + version: 1.2.4(esbuild@0.25.12)(rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.25.12)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))(rollup@2.79.2) + unplugin-vue-router: + specifier: ^0.19.0 + version: 0.19.2(@vue/compiler-sfc@3.5.26)(vue-router@4.6.4(vue@3.5.25(typescript@5.9.3)))(vue@3.5.25(typescript@5.9.3)) + unplugin-yaml: + specifier: ^3.0.7 + version: 3.0.7(esbuild@0.25.12)(rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.25.12)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))(rolldown@1.0.0-beta.53)(rollup@2.79.2) + vite: + specifier: catalog:rolldown-vite + version: rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.25.12)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) + vite-bundle-visualizer: + specifier: ^1.2.1 + version: 1.2.1(rolldown@1.0.0-beta.53)(rollup@2.79.2) + vite-plugin-pwa: + specifier: ^1.2.0 + version: 1.2.0(rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.25.12)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))(workbox-build@7.4.0)(workbox-window@7.4.0) + vite-plugin-vue-devtools: + specifier: ^8.0.5 + version: 8.0.5(rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.25.12)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))(vue@3.5.25(typescript@5.9.3)) + vite-plugin-vue-layouts: + specifier: ^0.11.0 + version: 0.11.0(rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.25.12)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))(vue-router@4.6.4(vue@3.5.25(typescript@5.9.3)))(vue@3.5.25(typescript@5.9.3)) + vue-macros: + specifier: ^3.1.1 + version: 3.1.1(@vueuse/core@14.1.0(vue@3.5.25(typescript@5.9.3)))(esbuild@0.25.12)(rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.25.12)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))(rolldown@1.0.0-beta.53)(rollup@2.79.2)(typescript@5.9.3)(vue-tsc@3.2.1(typescript@5.9.3))(vue@3.5.25(typescript@5.9.3)) + vue-tsc: + specifier: ^3.1.8 + version: 3.2.1(typescript@5.9.3) + apps/stage-tamagotchi: dependencies: '@date-fns/utc': @@ -618,7 +973,7 @@ importers: version: link:../../packages/ui-transitions '@proj-airi/unplugin-fetch': specifier: ^0.2.1 - version: 0.2.1(rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.25.12)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) + version: 0.2.1(rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) '@proj-airi/unplugin-live2d-sdk': specifier: ^0.1.6 version: 0.1.6(@types/node@24.10.4)(jiti@2.6.1)(less@4.5.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) @@ -645,7 +1000,7 @@ importers: version: 66.5.11 '@vitejs/plugin-vue': specifier: ^6.0.3 - version: 6.0.3(rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.25.12)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))(vue@3.5.25(typescript@5.9.3)) + version: 6.0.3(rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))(vue@3.5.25(typescript@5.9.3)) '@vue-macros/volar': specifier: ^3.1.1 version: 3.1.1(typescript@5.9.3)(vue-tsc@3.2.1(typescript@5.9.3))(vue@3.5.25(typescript@5.9.3)) @@ -672,37 +1027,37 @@ importers: version: 26.4.0(electron-builder-squirrel-windows@26.4.0) electron-vite: specifier: ^5.0.0 - version: 5.0.0(rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.25.12)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) + version: 5.0.0(rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) less: specifier: ^4.5.1 version: 4.5.1 unocss-preset-scrollbar: specifier: ^3.2.0 - version: 3.2.0(unocss@66.5.11(postcss@8.5.6)(rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.25.12)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))) + version: 3.2.0(unocss@66.5.11(postcss@8.5.6)(rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))) unplugin-info: specifier: ^1.2.4 - version: 1.2.4(@nuxt/kit@3.20.2(magicast@0.5.1))(esbuild@0.25.12)(rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.25.12)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))(rollup@4.54.0) + version: 1.2.4(@nuxt/kit@3.20.2(magicast@0.5.1))(esbuild@0.27.2)(rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))(rollup@4.54.0) unplugin-vue-router: specifier: ^0.19.0 version: 0.19.2(@vue/compiler-sfc@3.5.26)(vue-router@4.6.4(vue@3.5.25(typescript@5.9.3)))(vue@3.5.25(typescript@5.9.3)) unplugin-yaml: specifier: ^3.0.7 - version: 3.0.7(@nuxt/kit@3.20.2(magicast@0.5.1))(esbuild@0.25.12)(rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.25.12)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))(rolldown@1.0.0-beta.53)(rollup@4.54.0) + version: 3.0.7(@nuxt/kit@3.20.2(magicast@0.5.1))(esbuild@0.27.2)(rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))(rolldown@1.0.0-beta.53)(rollup@4.54.0) vite: specifier: catalog:rolldown-vite - version: rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.25.12)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) + version: rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) vite-bundle-visualizer: specifier: ^1.2.1 version: 1.2.1(rolldown@1.0.0-beta.53)(rollup@4.54.0) vite-plugin-vue-devtools: specifier: ^8.0.5 - version: 8.0.5(@nuxt/kit@3.20.2(magicast@0.5.1))(rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.25.12)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))(vue@3.5.25(typescript@5.9.3)) + version: 8.0.5(@nuxt/kit@3.20.2(magicast@0.5.1))(rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))(vue@3.5.25(typescript@5.9.3)) vite-plugin-vue-layouts: specifier: ^0.11.0 - version: 0.11.0(rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.25.12)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))(vue-router@4.6.4(vue@3.5.25(typescript@5.9.3)))(vue@3.5.25(typescript@5.9.3)) + version: 0.11.0(rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))(vue-router@4.6.4(vue@3.5.25(typescript@5.9.3)))(vue@3.5.25(typescript@5.9.3)) vue-macros: specifier: ^3.1.1 - version: 3.1.1(@vueuse/core@14.1.0(vue@3.5.25(typescript@5.9.3)))(esbuild@0.25.12)(rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.25.12)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))(rolldown@1.0.0-beta.53)(rollup@4.54.0)(typescript@5.9.3)(vue-tsc@3.2.1(typescript@5.9.3))(vue@3.5.25(typescript@5.9.3)) + version: 3.1.1(@vueuse/core@14.1.0(vue@3.5.25(typescript@5.9.3)))(esbuild@0.27.2)(rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))(rolldown@1.0.0-beta.53)(rollup@4.54.0)(typescript@5.9.3)(vue-tsc@3.2.1(typescript@5.9.3))(vue@3.5.25(typescript@5.9.3)) vue-tsc: specifier: ^3.1.8 version: 3.2.1(typescript@5.9.3) @@ -967,7 +1322,7 @@ importers: version: 1.2.37 '@intlify/unplugin-vue-i18n': specifier: ^11.0.1 - version: 11.0.3(@vue/compiler-dom@3.5.26)(eslint@9.39.2(jiti@2.6.1))(rollup@2.79.2)(typescript@5.9.3)(vue-i18n@11.2.7(vue@3.5.25(typescript@5.9.3)))(vue@3.5.25(typescript@5.9.3)) + version: 11.0.3(@vue/compiler-dom@3.5.26)(eslint@9.39.2(jiti@2.6.1))(rollup@4.54.0)(typescript@5.9.3)(vue-i18n@11.2.7(vue@3.5.25(typescript@5.9.3)))(vue@3.5.25(typescript@5.9.3)) '@proj-airi/lobe-icons': specifier: ^1.0.18 version: 1.0.18 @@ -1021,31 +1376,31 @@ importers: version: 4.5.1 unplugin-info: specifier: ^1.2.4 - version: 1.2.4(esbuild@0.27.2)(rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))(rollup@2.79.2) + version: 1.2.4(@nuxt/kit@3.20.2(magicast@0.5.1))(esbuild@0.27.2)(rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))(rollup@4.54.0) unplugin-vue-router: specifier: ^0.19.0 version: 0.19.2(@vue/compiler-sfc@3.5.26)(vue-router@4.6.4(vue@3.5.25(typescript@5.9.3)))(vue@3.5.25(typescript@5.9.3)) unplugin-yaml: specifier: ^3.0.7 - version: 3.0.7(esbuild@0.27.2)(rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))(rolldown@1.0.0-beta.53)(rollup@2.79.2) + version: 3.0.7(@nuxt/kit@3.20.2(magicast@0.5.1))(esbuild@0.27.2)(rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))(rolldown@1.0.0-beta.53)(rollup@4.54.0) vite: specifier: catalog:rolldown-vite version: rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) vite-bundle-visualizer: specifier: ^1.2.1 - version: 1.2.1(rolldown@1.0.0-beta.53)(rollup@2.79.2) + version: 1.2.1(rolldown@1.0.0-beta.53)(rollup@4.54.0) vite-plugin-pwa: specifier: ^1.2.0 version: 1.2.0(rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))(workbox-build@7.4.0)(workbox-window@7.4.0) vite-plugin-vue-devtools: specifier: ^8.0.5 - version: 8.0.5(rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))(vue@3.5.25(typescript@5.9.3)) + version: 8.0.5(@nuxt/kit@3.20.2(magicast@0.5.1))(rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))(vue@3.5.25(typescript@5.9.3)) vite-plugin-vue-layouts: specifier: ^0.11.0 version: 0.11.0(rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))(vue-router@4.6.4(vue@3.5.25(typescript@5.9.3)))(vue@3.5.25(typescript@5.9.3)) vue-macros: specifier: ^3.1.1 - version: 3.1.1(@vueuse/core@14.1.0(vue@3.5.25(typescript@5.9.3)))(esbuild@0.27.2)(rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))(rolldown@1.0.0-beta.53)(rollup@2.79.2)(typescript@5.9.3)(vue-tsc@3.2.1(typescript@5.9.3))(vue@3.5.25(typescript@5.9.3)) + version: 3.1.1(@vueuse/core@14.1.0(vue@3.5.25(typescript@5.9.3)))(esbuild@0.27.2)(rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))(rolldown@1.0.0-beta.53)(rollup@4.54.0)(typescript@5.9.3)(vue-tsc@3.2.1(typescript@5.9.3))(vue@3.5.25(typescript@5.9.3)) vue-tsc: specifier: ^3.1.8 version: 3.2.1(typescript@5.9.3) @@ -1978,7 +2333,7 @@ importers: version: rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) vite-plugin-vue-devtools: specifier: ^8.0.5 - version: 8.0.5(rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))(vue@3.5.25(typescript@5.9.3)) + version: 8.0.5(@nuxt/kit@3.20.2(magicast@0.5.1))(rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))(vue@3.5.25(typescript@5.9.3)) vue-router: specifier: ^4.6.4 version: 4.6.4(vue@3.5.25(typescript@5.9.3)) @@ -2012,7 +2367,7 @@ importers: version: rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) vite-plugin-vue-devtools: specifier: ^8.0.5 - version: 8.0.5(rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))(vue@3.5.25(typescript@5.9.3)) + version: 8.0.5(@nuxt/kit@3.20.2(magicast@0.5.1))(rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))(vue@3.5.25(typescript@5.9.3)) vue-router: specifier: ^4.6.4 version: 4.6.4(vue@3.5.25(typescript@5.9.3)) @@ -3290,6 +3645,19 @@ packages: '@bufbuild/protobuf@2.10.2': resolution: {integrity: sha512-uFsRXwIGyu+r6AMdz+XijIIZJYpoWeYzILt5yZ2d3mCjQrWUTVpVD9WL/jZAbvp+Ed04rOhrsk7FiTcEDseB5A==} + '@capacitor/cli@8.0.0': + resolution: {integrity: sha512-v9hEBi69xGxuuZhg55N031bMEenKaPSv71Il8C22VOOH6surDyv/MPeImN0oVfFc7eiklaW3rDFYVz6cmXfJWQ==} + engines: {node: '>=22.0.0'} + hasBin: true + + '@capacitor/core@8.0.0': + resolution: {integrity: sha512-250HTVd/W/KdMygoqaedisvNbHbpbQTN2Hy/8ZYGm1nAqE0Fx7sGss4l0nDg33STxEdDhtVRoL2fIaaiukKseA==} + + '@capacitor/ios@8.0.0': + resolution: {integrity: sha512-gwSn6X4uHYNHlM8zZmVmM1zjEhexxbHpPSSnH1DZkp8o3zdK/RmH8tmDma+3zPZrhhTSrMC7sT24dKTOvV8www==} + peerDependencies: + '@capacitor/core': ^8.0.0 + '@cfworker/json-schema@4.1.1': resolution: {integrity: sha512-gAmrUZSGtKc3AiBL71iNWxDsyUC5uMaKKGdvzYsBoTW/xi42JQHl7eKV2OYzCUqvc+D2RCcf7EXY2iCyFIk6og==} @@ -4845,6 +5213,38 @@ packages: vue-i18n: optional: true + '@ionic/cli-framework-output@2.2.8': + resolution: {integrity: sha512-TshtaFQsovB4NWRBydbNFawql6yul7d5bMiW1WYYf17hd99V6xdDdk3vtF51bw6sLkxON3bDQpWsnUc9/hVo3g==} + engines: {node: '>=16.0.0'} + + '@ionic/utils-array@2.1.6': + resolution: {integrity: sha512-0JZ1Zkp3wURnv8oq6Qt7fMPo5MpjbLoUoa9Bu2Q4PJuSDWM8H8gwF3dQO7VTeUj3/0o1IB1wGkFWZZYgUXZMUg==} + engines: {node: '>=16.0.0'} + + '@ionic/utils-fs@3.1.7': + resolution: {integrity: sha512-2EknRvMVfhnyhL1VhFkSLa5gOcycK91VnjfrTB0kbqkTFCOXyXgVLI5whzq7SLrgD9t1aqos3lMMQyVzaQ5gVA==} + engines: {node: '>=16.0.0'} + + '@ionic/utils-object@2.1.6': + resolution: {integrity: sha512-vCl7sl6JjBHFw99CuAqHljYJpcE88YaH2ZW4ELiC/Zwxl5tiwn4kbdP/gxi2OT3MQb1vOtgAmSNRtusvgxI8ww==} + engines: {node: '>=16.0.0'} + + '@ionic/utils-process@2.1.12': + resolution: {integrity: sha512-Jqkgyq7zBs/v/J3YvKtQQiIcxfJyplPgECMWgdO0E1fKrrH8EF0QGHNJ9mJCn6PYe2UtHNS8JJf5G21e09DfYg==} + engines: {node: '>=16.0.0'} + + '@ionic/utils-stream@3.1.7': + resolution: {integrity: sha512-eSELBE7NWNFIHTbTC2jiMvh1ABKGIpGdUIvARsNPMNQhxJB3wpwdiVnoBoTYp+5a6UUIww4Kpg7v6S7iTctH1w==} + engines: {node: '>=16.0.0'} + + '@ionic/utils-subprocess@3.0.1': + resolution: {integrity: sha512-cT4te3AQQPeIM9WCwIg8ohroJ8TjsYaMb2G4ZEgv9YzeDqHZ4JpeIKqG2SoaA3GmVQ3sOfhPM6Ox9sxphV/d1A==} + engines: {node: '>=16.0.0'} + + '@ionic/utils-terminal@2.3.5': + resolution: {integrity: sha512-3cKScz9Jx2/Pr9ijj1OzGlBDfcmx7OMVBt4+P1uRR0SSW4cm1/y3Mo4OY3lfkuaYifMNBW8Wz6lQHbs1bihr7A==} + engines: {node: '>=16.0.0'} + '@isaacs/balanced-match@4.0.1': resolution: {integrity: sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ==} engines: {node: 20 || >=22} @@ -7079,6 +7479,9 @@ packages: '@types/fs-extra@11.0.4': resolution: {integrity: sha512-yTbItCNreRooED33qjunPthRcSjERP1r4MqCZc7wv0u2sUkzTFp45tgUfS5+r7FrZPdmCCNflLhVSP/o+SemsQ==} + '@types/fs-extra@8.1.5': + resolution: {integrity: sha512-0dzKcwO+S8s2kuF5Z9oUWatQJj5Uq/iqphEtE3GQJVRRYm/tD1LglU2UnXi2A8jLq5umkGouOXOR9y0n613ZwQ==} + '@types/fs-extra@9.0.13': resolution: {integrity: sha512-nEnwB++1u5lVDM2UI4c1+5R+FYaKfaAzS4OococimjVm3nQw3TuzH5UNsocrcTBbhnerblyHj4A49qXbIiZdpA==} @@ -7188,6 +7591,9 @@ packages: '@types/retry@0.12.0': resolution: {integrity: sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==} + '@types/slice-ansi@4.0.0': + resolution: {integrity: sha512-+OpjSaq85gvlZAYINyzKpLeiFkSC4EsC6IIiT6v6TLSU5k5U83fHGj9Lel8oKEXM0HqgrMVCjXPDPVICtxF7EQ==} + '@types/stats.js@0.17.4': resolution: {integrity: sha512-jIBvWWShCvlBqBNIZt0KAshWpvSjhkwkEu4ZUcASoAvhmrgAUI2t1dXrjSL4xXVLB4FznPrIsX3nKXFl/Dt4vA==} @@ -8468,6 +8874,10 @@ packages: resolution: {integrity: sha512-F3PH5k5juxom4xktynS7MoFY+NUWH5LC4CnH11YB8NPew+HLpmBLCybSAEyb2F+4pRXhuhWqFesoQd6DAyc2hw==} engines: {node: '>=18'} + bplist-parser@0.3.2: + resolution: {integrity: sha512-apC2+fspHGI3mMKj+dGevkGo/tCqVB8jMb6i+OX+E29p0Iposz07fABkRIfVUPNd5A5VbuOz1bZbnmkKLYF+wQ==} + engines: {node: '>= 5.10.0'} + brace-expansion@1.1.12: resolution: {integrity: sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==} @@ -8759,6 +9169,10 @@ packages: resolution: {integrity: sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==} engines: {node: '>=16'} + commander@12.1.0: + resolution: {integrity: sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==} + engines: {node: '>=18'} + commander@14.0.2: resolution: {integrity: sha512-TywoWNNRbhoD0BXs1P3ZEScW8W5iKrnbithIl0YH+uCmBd0QpPOA8yc82DS3BIE5Ma6FnBVUsJ7wVUDz4dvOWQ==} engines: {node: '>=20'} @@ -9376,6 +9790,10 @@ packages: engines: {node: '>= 12.20.55'} hasBin: true + elementtree@0.1.7: + resolution: {integrity: sha512-wkgGT6kugeQk/P6VZ/f4T+4HB41BVgNBq5CDIZVbQ02nvTVqAiVTbskxxu3eA/X96lMlfYOwnLQpN2v5E1zDEg==} + engines: {node: '>= 0.4.0'} + email-addresses@3.1.0: resolution: {integrity: sha512-k0/r7GrWVL32kZlGwfPNgB2Y/mMXVTq/decgLczm/j34whdaspNrZO8CnXPf1laaHxI6ptUlsnAxN+UAPw+fzg==} @@ -10291,6 +10709,10 @@ packages: engines: {node: 20 || >=22} hasBin: true + glob@13.0.0: + resolution: {integrity: sha512-tvZgpqk6fz4BaNZ66ZsRaZnbHvP/jG3uKJvAZOwEVUL4RTA5nJeeLYfyN9/VA8NX/V3IBG+hkeuGpKjvELkVhA==} + engines: {node: 20 || >=22} + glob@7.2.3: resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} deprecated: Glob versions prior to v9 are no longer supported @@ -11057,6 +11479,10 @@ packages: resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==} engines: {node: '>=6'} + kleur@4.1.5: + resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==} + engines: {node: '>=6'} + klona@2.0.6: resolution: {integrity: sha512-dhG34DXATL5hSxJbIexCft8FChFXtmskoZYnoPWjXQuebWYCNkVeV3KkGegCK9CP1oswI/vQibS2GY7Em/sJJA==} engines: {node: '>= 8'} @@ -11847,6 +12273,11 @@ packages: engines: {node: ^18 || >=20} hasBin: true + native-run@2.0.1: + resolution: {integrity: sha512-XfG1FBZLM50J10xH9361whJRC9SHZ0Bub4iNRhhI61C8Jv0e1ud19muex6sNKB51ibQNUJNuYn25MuYET/rE6w==} + engines: {node: '>=16.0.0'} + hasBin: true + natural-compare@1.4.0: resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} @@ -12994,6 +13425,11 @@ packages: resolution: {integrity: sha512-l0OE8wL34P4nJH/H2ffoaniAokM2qSmrtXHmlpvYr5AVVX8msAyW0l8NVJFDxlSK4u3Uh/f41cQheDVdnYijwQ==} hasBin: true + rimraf@6.1.2: + resolution: {integrity: sha512-cFCkPslJv7BAXJsYlK1dZsbP8/ZNLkCAQ0bi1hf5EKX2QHegmDFEFA6QhuYJlk7UDdc+02JjO80YSOrWPpw06g==} + engines: {node: 20 || >=22} + hasBin: true + roarr@2.15.4: resolution: {integrity: sha512-CHhPh+UNHD2GTXNYhPWLnU8ONHdI+5DI+4EYIAOaiD63rHeYlZvyh8P+in5999TTSFgUYuKUAjzRI4mdh/p+2A==} engines: {node: '>=8.0'} @@ -13136,6 +13572,9 @@ packages: sanitize-filename@1.6.3: resolution: {integrity: sha512-y/52Mcy7aw3gRm7IrcGDFx/bCk4AhRh2eI9luHOQM86nZsqwiRkkq2GekHXBBD+SmPidc8i2PqtYZl+pWJ8Oeg==} + sax@1.1.4: + resolution: {integrity: sha512-5f3k2PbGGp+YtKJjOItpg3P99IMD84E4HOvcfleTb5joCHNXYLsR9yWFPOYGgaeMPDubQILTCMdsFb2OMeOjtg==} + sax@1.4.3: resolution: {integrity: sha512-yqYn1JhPczigF94DMS+shiDMjDowYO6y9+wB/4WgO0Y19jWYk0lQ4tuG5KI7kj4FTp1wxPj5IFfcrz/s1c3jjQ==} @@ -13281,6 +13720,10 @@ packages: resolution: {integrity: sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==} engines: {node: '>=8'} + slice-ansi@4.0.0: + resolution: {integrity: sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==} + engines: {node: '>=10'} + slice-ansi@5.0.0: resolution: {integrity: sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==} engines: {node: '>=12'} @@ -13679,6 +14122,9 @@ packages: through2@0.6.5: resolution: {integrity: sha512-RkK/CCESdTKQZHdmKICijdKKsCRVHs5KsLZ6pACAmF/1GPUQhonHSXWNERctxEp7RmvjdNbZTL5z9V7nSCXKcg==} + through2@4.0.2: + resolution: {integrity: sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==} + through@2.3.8: resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} @@ -14246,6 +14692,10 @@ packages: unspeech@0.1.7: resolution: {integrity: sha512-HQ49mqEfvkMIKsbYDfHXDxbpUuNnb+gJdLO6wjQ/iPP1VuUfXs5Ky20attrRr1Qp2S0FHWsuz7/nlv9CAHHuhg==} + untildify@4.0.0: + resolution: {integrity: sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==} + engines: {node: '>=8'} + untun@0.1.3: resolution: {integrity: sha512-4luGP9LMYszMRZwsvyUd9MrxgEGZdZuZgpVQHEEX0lCYFESasVRvZd0EYpCkOIbJKHMuv0LskpXc/8Un+MJzEQ==} hasBin: true @@ -16253,6 +16703,36 @@ snapshots: '@bufbuild/protobuf@2.10.2': {} + '@capacitor/cli@8.0.0': + dependencies: + '@ionic/cli-framework-output': 2.2.8 + '@ionic/utils-subprocess': 3.0.1 + '@ionic/utils-terminal': 2.3.5 + commander: 12.1.0 + debug: 4.4.3 + env-paths: 2.2.1 + fs-extra: 11.3.3 + kleur: 4.1.5 + native-run: 2.0.1 + open: 8.4.2 + plist: 3.1.0 + prompts: 2.4.2 + rimraf: 6.1.2 + semver: 7.7.3 + tar: 6.2.1 + tslib: 2.8.1 + xml2js: 0.6.2 + transitivePeerDependencies: + - supports-color + + '@capacitor/core@8.0.0': + dependencies: + tslib: 2.8.1 + + '@capacitor/ios@8.0.0(@capacitor/core@8.0.0)': + dependencies: + '@capacitor/core': 8.0.0 + '@cfworker/json-schema@4.1.1': {} '@clack/core@0.5.0': @@ -17566,6 +18046,82 @@ snapshots: vue: 3.5.25(typescript@5.9.3) vue-i18n: 11.2.7(vue@3.5.25(typescript@5.9.3)) + '@ionic/cli-framework-output@2.2.8': + dependencies: + '@ionic/utils-terminal': 2.3.5 + debug: 4.4.3 + tslib: 2.8.1 + transitivePeerDependencies: + - supports-color + + '@ionic/utils-array@2.1.6': + dependencies: + debug: 4.4.3 + tslib: 2.8.1 + transitivePeerDependencies: + - supports-color + + '@ionic/utils-fs@3.1.7': + dependencies: + '@types/fs-extra': 8.1.5 + debug: 4.4.3 + fs-extra: 9.1.0 + tslib: 2.8.1 + transitivePeerDependencies: + - supports-color + + '@ionic/utils-object@2.1.6': + dependencies: + debug: 4.4.3 + tslib: 2.8.1 + transitivePeerDependencies: + - supports-color + + '@ionic/utils-process@2.1.12': + dependencies: + '@ionic/utils-object': 2.1.6 + '@ionic/utils-terminal': 2.3.5 + debug: 4.4.3 + signal-exit: 3.0.7 + tree-kill: 1.2.2 + tslib: 2.8.1 + transitivePeerDependencies: + - supports-color + + '@ionic/utils-stream@3.1.7': + dependencies: + debug: 4.4.3 + tslib: 2.8.1 + transitivePeerDependencies: + - supports-color + + '@ionic/utils-subprocess@3.0.1': + dependencies: + '@ionic/utils-array': 2.1.6 + '@ionic/utils-fs': 3.1.7 + '@ionic/utils-process': 2.1.12 + '@ionic/utils-stream': 3.1.7 + '@ionic/utils-terminal': 2.3.5 + cross-spawn: 7.0.6 + debug: 4.4.3 + tslib: 2.8.1 + transitivePeerDependencies: + - supports-color + + '@ionic/utils-terminal@2.3.5': + dependencies: + '@types/slice-ansi': 4.0.0 + debug: 4.4.3 + signal-exit: 3.0.7 + slice-ansi: 4.0.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + tslib: 2.8.1 + untildify: 4.0.0 + wrap-ansi: 7.0.0 + transitivePeerDependencies: + - supports-color + '@isaacs/balanced-match@4.0.1': {} '@isaacs/brace-expansion@5.0.0': @@ -19857,6 +20413,10 @@ snapshots: '@types/jsonfile': 6.1.4 '@types/node': 24.10.4 + '@types/fs-extra@8.1.5': + dependencies: + '@types/node': 24.10.4 + '@types/fs-extra@9.0.13': dependencies: '@types/node': 24.10.4 @@ -19981,6 +20541,8 @@ snapshots: '@types/retry@0.12.0': {} + '@types/slice-ansi@4.0.0': {} + '@types/stats.js@0.17.4': {} '@types/tedious@4.0.14': @@ -20119,13 +20681,13 @@ snapshots: '@ungap/structured-clone@1.3.0': {} - '@unocss/astro@66.5.11(rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.25.12)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))': + '@unocss/astro@66.5.11(rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))': dependencies: '@unocss/core': 66.5.11 '@unocss/reset': 66.5.11 - '@unocss/vite': 66.5.11(rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.25.12)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) + '@unocss/vite': 66.5.11(rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) optionalDependencies: - vite: rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.25.12)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) + vite: rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) '@unocss/astro@66.5.11(vite@6.4.1(@types/node@24.10.4)(jiti@2.6.1)(less@4.5.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))': dependencies: @@ -20307,7 +20869,7 @@ snapshots: dependencies: '@unocss/core': 66.5.11 - '@unocss/vite@66.5.11(rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.25.12)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))': + '@unocss/vite@66.5.11(rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))': dependencies: '@jridgewell/remapping': 2.3.5 '@unocss/config': 66.5.11 @@ -20318,7 +20880,7 @@ snapshots: pathe: 2.0.3 tinyglobby: 0.2.15 unplugin-utils: 0.3.1 - vite: rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.25.12)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) + vite: rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) '@unocss/vite@66.5.11(vite@6.4.1(@types/node@24.10.4)(jiti@2.6.1)(less@4.5.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))': dependencies: @@ -21629,8 +22191,7 @@ snapshots: '@babel/parser': 7.28.5 ast-kit: 2.2.0 - astral-regex@2.0.0: - optional: true + astral-regex@2.0.0: {} astring@1.9.0: {} @@ -21818,6 +22379,10 @@ snapshots: widest-line: 5.0.0 wrap-ansi: 9.0.2 + bplist-parser@0.3.2: + dependencies: + big-integer: 1.6.52 + brace-expansion@1.1.12: dependencies: balanced-match: 1.0.2 @@ -22172,6 +22737,8 @@ snapshots: commander@11.1.0: {} + commander@12.1.0: {} + commander@14.0.2: {} commander@2.20.3: {} @@ -22695,7 +23262,7 @@ snapshots: transitivePeerDependencies: - supports-color - electron-vite@5.0.0(rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.25.12)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)): + electron-vite@5.0.0(rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)): dependencies: '@babel/core': 7.28.5 '@babel/plugin-transform-arrow-functions': 7.27.1(@babel/core@7.28.5) @@ -22703,7 +23270,7 @@ snapshots: esbuild: 0.25.12 magic-string: 0.30.21 picocolors: 1.1.1 - vite: rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.25.12)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) + vite: rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) transitivePeerDependencies: - supports-color @@ -22727,6 +23294,10 @@ snapshots: transitivePeerDependencies: - supports-color + elementtree@0.1.7: + dependencies: + sax: 1.1.4 + email-addresses@3.1.0: {} embla-carousel-reactive-utils@8.6.0(embla-carousel@8.6.0): @@ -23969,6 +24540,12 @@ snapshots: package-json-from-dist: 1.0.1 path-scurry: 2.0.1 + glob@13.0.0: + dependencies: + minimatch: 10.1.1 + minipass: 7.1.2 + path-scurry: 2.0.1 + glob@7.2.3: dependencies: fs.realpath: 1.0.0 @@ -24835,6 +25412,8 @@ snapshots: kleur@3.0.3: {} + kleur@4.1.5: {} + klona@2.0.6: optional: true @@ -25900,6 +26479,22 @@ snapshots: nanoid@5.1.6: {} + native-run@2.0.1: + dependencies: + '@ionic/utils-fs': 3.1.7 + '@ionic/utils-terminal': 2.3.5 + bplist-parser: 0.3.2 + debug: 4.4.3 + elementtree: 0.1.7 + ini: 4.1.3 + plist: 3.1.0 + split2: 4.2.0 + through2: 4.0.2 + tslib: 2.8.1 + yauzl: 2.10.0 + transitivePeerDependencies: + - supports-color + natural-compare@1.4.0: {} natural-orderby@5.0.0: {} @@ -27323,6 +27918,11 @@ snapshots: dependencies: glob: 10.5.0 + rimraf@6.1.2: + dependencies: + glob: 13.0.0 + package-json-from-dist: 1.0.1 + roarr@2.15.4: dependencies: boolean: 3.2.0 @@ -27540,6 +28140,8 @@ snapshots: dependencies: truncate-utf8-bytes: 1.0.2 + sax@1.1.4: {} + sax@1.4.3: {} saxes@6.0.0: @@ -27737,6 +28339,12 @@ snapshots: is-fullwidth-code-point: 3.0.0 optional: true + slice-ansi@4.0.0: + dependencies: + ansi-styles: 4.3.0 + astral-regex: 2.0.0 + is-fullwidth-code-point: 3.0.0 + slice-ansi@5.0.0: dependencies: ansi-styles: 6.2.3 @@ -28205,6 +28813,10 @@ snapshots: readable-stream: 1.0.34 xtend: 4.0.2 + through2@4.0.2: + dependencies: + readable-stream: 3.6.2 + through@2.3.8: {} timm@1.7.1: {} @@ -28595,19 +29207,19 @@ snapshots: universalify@2.0.1: {} - unocss-preset-scrollbar@3.2.0(unocss@66.5.11(postcss@8.5.6)(rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.25.12)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))): + unocss-preset-scrollbar@3.2.0(unocss@66.5.11(postcss@8.5.6)(rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))): dependencies: '@unocss/preset-mini': 65.5.0 - unocss: 66.5.11(postcss@8.5.6)(rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.25.12)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) + unocss: 66.5.11(postcss@8.5.6)(rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) unocss-preset-scrollbar@3.2.0(unocss@66.5.11(postcss@8.5.6)(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(less@4.5.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))): dependencies: '@unocss/preset-mini': 65.5.0 unocss: 66.5.11(postcss@8.5.6)(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(less@4.5.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) - unocss@66.5.11(postcss@8.5.6)(rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.25.12)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)): + unocss@66.5.11(postcss@8.5.6)(rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)): dependencies: - '@unocss/astro': 66.5.11(rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.25.12)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) + '@unocss/astro': 66.5.11(rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) '@unocss/cli': 66.5.11 '@unocss/core': 66.5.11 '@unocss/postcss': 66.5.11(postcss@8.5.6) @@ -28625,9 +29237,9 @@ snapshots: '@unocss/transformer-compile-class': 66.5.11 '@unocss/transformer-directives': 66.5.11 '@unocss/transformer-variant-group': 66.5.11 - '@unocss/vite': 66.5.11(rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.25.12)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) + '@unocss/vite': 66.5.11(rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) optionalDependencies: - vite: rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.25.12)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) + vite: rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) transitivePeerDependencies: - postcss - supports-color @@ -28688,23 +29300,23 @@ snapshots: unpipe@1.0.0: {} - unplugin-combine@2.1.3(esbuild@0.25.12)(rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.25.12)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))(rolldown@1.0.0-beta.53)(rollup@4.54.0)(unplugin@2.3.11): + unplugin-combine@2.1.3(esbuild@0.25.12)(rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.25.12)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))(rolldown@1.0.0-beta.53)(rollup@2.79.2)(unplugin@2.3.11): optionalDependencies: esbuild: 0.25.12 rolldown: 1.0.0-beta.53 - rollup: 4.54.0 + rollup: 2.79.2 unplugin: 2.3.11 vite: rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.25.12)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) - unplugin-combine@2.1.3(esbuild@0.27.2)(rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))(rolldown@1.0.0-beta.53)(rollup@2.79.2)(unplugin@2.3.11): + unplugin-combine@2.1.3(esbuild@0.27.2)(rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))(rolldown@1.0.0-beta.53)(rollup@4.54.0)(unplugin@2.3.11): optionalDependencies: esbuild: 0.27.2 rolldown: 1.0.0-beta.53 - rollup: 2.79.2 + rollup: 4.54.0 unplugin: 2.3.11 vite: rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) - unplugin-info@1.2.4(@nuxt/kit@3.20.2(magicast@0.5.1))(esbuild@0.25.12)(rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.25.12)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))(rollup@4.54.0): + unplugin-info@1.2.4(@nuxt/kit@3.20.2(magicast@0.5.1))(esbuild@0.27.2)(rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))(rollup@4.54.0): dependencies: ci-info: 4.3.1 git-url-parse: 16.1.0 @@ -28712,9 +29324,9 @@ snapshots: unplugin: 2.3.11 optionalDependencies: '@nuxt/kit': 3.20.2(magicast@0.5.1) - esbuild: 0.25.12 + esbuild: 0.27.2 rollup: 4.54.0 - vite: rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.25.12)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) + vite: rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) transitivePeerDependencies: - supports-color @@ -28732,16 +29344,16 @@ snapshots: transitivePeerDependencies: - supports-color - unplugin-info@1.2.4(esbuild@0.27.2)(rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))(rollup@2.79.2): + unplugin-info@1.2.4(esbuild@0.25.12)(rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.25.12)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))(rollup@2.79.2): dependencies: ci-info: 4.3.1 git-url-parse: 16.1.0 simple-git: 3.30.0 unplugin: 2.3.11 optionalDependencies: - esbuild: 0.27.2 + esbuild: 0.25.12 rollup: 2.79.2 - vite: rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) + vite: rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.25.12)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) transitivePeerDependencies: - supports-color @@ -28842,17 +29454,17 @@ snapshots: - tsx - yaml - unplugin-yaml@3.0.7(@nuxt/kit@3.20.2(magicast@0.5.1))(esbuild@0.25.12)(rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.25.12)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))(rolldown@1.0.0-beta.53)(rollup@4.54.0): + unplugin-yaml@3.0.7(@nuxt/kit@3.20.2(magicast@0.5.1))(esbuild@0.27.2)(rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))(rolldown@1.0.0-beta.53)(rollup@4.54.0): dependencies: '@rollup/pluginutils': 5.3.0(rollup@4.54.0) unplugin: 2.3.10 yaml: 2.8.1 optionalDependencies: '@nuxt/kit': 3.20.2(magicast@0.5.1) - esbuild: 0.25.12 + esbuild: 0.27.2 rolldown: 1.0.0-beta.53 rollup: 4.54.0 - vite: rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.25.12)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) + vite: rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) unplugin-yaml@3.0.7(@nuxt/kit@3.20.2(magicast@0.5.1))(esbuild@0.27.2)(rolldown@1.0.0-beta.53)(rollup@4.54.0)(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(less@4.5.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)): dependencies: @@ -28866,16 +29478,16 @@ snapshots: rollup: 4.54.0 vite: 7.3.0(@types/node@24.10.4)(jiti@2.6.1)(less@4.5.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) - unplugin-yaml@3.0.7(esbuild@0.27.2)(rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))(rolldown@1.0.0-beta.53)(rollup@2.79.2): + unplugin-yaml@3.0.7(esbuild@0.25.12)(rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.25.12)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))(rolldown@1.0.0-beta.53)(rollup@2.79.2): dependencies: '@rollup/pluginutils': 5.3.0(rollup@2.79.2) unplugin: 2.3.10 yaml: 2.8.1 optionalDependencies: - esbuild: 0.27.2 + esbuild: 0.25.12 rolldown: 1.0.0-beta.53 rollup: 2.79.2 - vite: rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) + vite: rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.25.12)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) unplugin-yaml@3.0.7(esbuild@0.27.2)(rolldown@1.0.0-beta.53)(rollup@4.54.0)(vite@6.4.1(@types/node@24.10.4)(jiti@2.6.1)(less@4.5.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)): dependencies: @@ -28913,6 +29525,8 @@ snapshots: '@xsai-ext/shared-providers': 0.2.2 '@xsai/shared': 0.2.2 + untildify@4.0.0: {} + untun@0.1.3: dependencies: citty: 0.1.6 @@ -29130,24 +29744,7 @@ snapshots: - tsx - yaml - vite-plugin-inspect@11.3.3(@nuxt/kit@3.20.2(magicast@0.5.1))(rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.25.12)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)): - dependencies: - ansis: 4.2.0 - debug: 4.4.3 - error-stack-parser-es: 1.0.5 - ohash: 2.0.11 - open: 10.2.0 - perfect-debounce: 2.0.0 - sirv: 3.0.2 - unplugin-utils: 0.3.1 - vite: rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.25.12)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) - vite-dev-rpc: 1.1.0(rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.25.12)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) - optionalDependencies: - '@nuxt/kit': 3.20.2(magicast@0.5.1) - transitivePeerDependencies: - - supports-color - - vite-plugin-inspect@11.3.3(rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)): + vite-plugin-inspect@11.3.3(@nuxt/kit@3.20.2(magicast@0.5.1))(rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)): dependencies: ansis: 4.2.0 debug: 4.4.3 @@ -29159,6 +29756,23 @@ snapshots: unplugin-utils: 0.3.1 vite: rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) vite-dev-rpc: 1.1.0(rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) + optionalDependencies: + '@nuxt/kit': 3.20.2(magicast@0.5.1) + transitivePeerDependencies: + - supports-color + + vite-plugin-inspect@11.3.3(rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.25.12)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)): + dependencies: + ansis: 4.2.0 + debug: 4.4.3 + error-stack-parser-es: 1.0.5 + ohash: 2.0.11 + open: 10.2.0 + perfect-debounce: 2.0.0 + sirv: 3.0.2 + unplugin-utils: 0.3.1 + vite: rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.25.12)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) + vite-dev-rpc: 1.1.0(rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.25.12)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) transitivePeerDependencies: - supports-color @@ -29177,6 +29791,17 @@ snapshots: transitivePeerDependencies: - supports-color + vite-plugin-pwa@1.2.0(rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.25.12)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))(workbox-build@7.4.0)(workbox-window@7.4.0): + dependencies: + debug: 4.4.3 + pretty-bytes: 6.1.1 + tinyglobby: 0.2.15 + vite: rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.25.12)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) + workbox-build: 7.4.0 + workbox-window: 7.4.0 + transitivePeerDependencies: + - supports-color + vite-plugin-pwa@1.2.0(rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))(workbox-build@7.4.0)(workbox-window@7.4.0): dependencies: debug: 4.4.3 @@ -29188,34 +29813,34 @@ snapshots: transitivePeerDependencies: - supports-color - vite-plugin-vue-devtools@8.0.5(@nuxt/kit@3.20.2(magicast@0.5.1))(rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.25.12)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))(vue@3.5.25(typescript@5.9.3)): - dependencies: - '@vue/devtools-core': 8.0.5(rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.25.12)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))(vue@3.5.25(typescript@5.9.3)) - '@vue/devtools-kit': 8.0.5 - '@vue/devtools-shared': 8.0.5 - sirv: 3.0.2 - vite: rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.25.12)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) - vite-plugin-inspect: 11.3.3(@nuxt/kit@3.20.2(magicast@0.5.1))(rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.25.12)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) - vite-plugin-vue-inspector: 5.3.2(rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.25.12)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) - transitivePeerDependencies: - - '@nuxt/kit' - - supports-color - - vue - - vite-plugin-vue-devtools@8.0.5(rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))(vue@3.5.25(typescript@5.9.3)): + vite-plugin-vue-devtools@8.0.5(@nuxt/kit@3.20.2(magicast@0.5.1))(rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))(vue@3.5.25(typescript@5.9.3)): dependencies: '@vue/devtools-core': 8.0.5(rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))(vue@3.5.25(typescript@5.9.3)) '@vue/devtools-kit': 8.0.5 '@vue/devtools-shared': 8.0.5 sirv: 3.0.2 vite: rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) - vite-plugin-inspect: 11.3.3(rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) + vite-plugin-inspect: 11.3.3(@nuxt/kit@3.20.2(magicast@0.5.1))(rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) vite-plugin-vue-inspector: 5.3.2(rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) transitivePeerDependencies: - '@nuxt/kit' - supports-color - vue + vite-plugin-vue-devtools@8.0.5(rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.25.12)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))(vue@3.5.25(typescript@5.9.3)): + dependencies: + '@vue/devtools-core': 8.0.5(rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.25.12)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))(vue@3.5.25(typescript@5.9.3)) + '@vue/devtools-kit': 8.0.5 + '@vue/devtools-shared': 8.0.5 + sirv: 3.0.2 + vite: rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.25.12)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) + vite-plugin-inspect: 11.3.3(rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.25.12)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) + vite-plugin-vue-inspector: 5.3.2(rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.25.12)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) + transitivePeerDependencies: + - '@nuxt/kit' + - supports-color + - vue + vite-plugin-vue-inspector@5.3.2(rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.25.12)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)): dependencies: '@babel/core': 7.28.5 @@ -29457,7 +30082,7 @@ snapshots: '@vue/devtools-api': 6.6.4 vue: 3.5.25(typescript@5.9.3) - vue-macros@3.1.1(@vueuse/core@14.1.0(vue@3.5.25(typescript@5.9.3)))(esbuild@0.25.12)(rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.25.12)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))(rolldown@1.0.0-beta.53)(rollup@4.54.0)(typescript@5.9.3)(vue-tsc@3.2.1(typescript@5.9.3))(vue@3.5.25(typescript@5.9.3)): + vue-macros@3.1.1(@vueuse/core@14.1.0(vue@3.5.25(typescript@5.9.3)))(esbuild@0.25.12)(rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.25.12)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))(rolldown@1.0.0-beta.53)(rollup@2.79.2)(typescript@5.9.3)(vue-tsc@3.2.1(typescript@5.9.3))(vue@3.5.25(typescript@5.9.3)): dependencies: '@vue-macros/better-define': 3.1.1(vue@3.5.25(typescript@5.9.3)) '@vue-macros/boolean-prop': 3.1.1(vue@3.5.25(typescript@5.9.3)) @@ -29489,7 +30114,7 @@ snapshots: '@vue-macros/short-vmodel': 3.1.1(vue@3.5.25(typescript@5.9.3)) '@vue-macros/volar': 3.1.1(typescript@5.9.3)(vue-tsc@3.2.1(typescript@5.9.3))(vue@3.5.25(typescript@5.9.3)) unplugin: 2.3.11 - unplugin-combine: 2.1.3(esbuild@0.25.12)(rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.25.12)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))(rolldown@1.0.0-beta.53)(rollup@4.54.0)(unplugin@2.3.11) + unplugin-combine: 2.1.3(esbuild@0.25.12)(rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.25.12)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))(rolldown@1.0.0-beta.53)(rollup@2.79.2)(unplugin@2.3.11) unplugin-vue-define-options: 3.1.1(vue@3.5.25(typescript@5.9.3)) vue: 3.5.25(typescript@5.9.3) transitivePeerDependencies: @@ -29503,7 +30128,7 @@ snapshots: - vue-tsc - webpack - vue-macros@3.1.1(@vueuse/core@14.1.0(vue@3.5.25(typescript@5.9.3)))(esbuild@0.27.2)(rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))(rolldown@1.0.0-beta.53)(rollup@2.79.2)(typescript@5.9.3)(vue-tsc@3.2.1(typescript@5.9.3))(vue@3.5.25(typescript@5.9.3)): + vue-macros@3.1.1(@vueuse/core@14.1.0(vue@3.5.25(typescript@5.9.3)))(esbuild@0.27.2)(rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))(rolldown@1.0.0-beta.53)(rollup@4.54.0)(typescript@5.9.3)(vue-tsc@3.2.1(typescript@5.9.3))(vue@3.5.25(typescript@5.9.3)): dependencies: '@vue-macros/better-define': 3.1.1(vue@3.5.25(typescript@5.9.3)) '@vue-macros/boolean-prop': 3.1.1(vue@3.5.25(typescript@5.9.3)) @@ -29535,7 +30160,7 @@ snapshots: '@vue-macros/short-vmodel': 3.1.1(vue@3.5.25(typescript@5.9.3)) '@vue-macros/volar': 3.1.1(typescript@5.9.3)(vue-tsc@3.2.1(typescript@5.9.3))(vue@3.5.25(typescript@5.9.3)) unplugin: 2.3.11 - unplugin-combine: 2.1.3(esbuild@0.27.2)(rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))(rolldown@1.0.0-beta.53)(rollup@2.79.2)(unplugin@2.3.11) + unplugin-combine: 2.1.3(esbuild@0.27.2)(rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))(rolldown@1.0.0-beta.53)(rollup@4.54.0)(unplugin@2.3.11) unplugin-vue-define-options: 3.1.1(vue@3.5.25(typescript@5.9.3)) vue: 3.5.25(typescript@5.9.3) transitivePeerDependencies: diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 1ba19245b..1bef746df 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -20,6 +20,9 @@ overrides: side-channel: npm:@nolyfill/side-channel@^1.0.44 string.prototype.matchall: npm:@nolyfill/string.prototype.matchall@^1.0.44 catalog: + '@capacitor/cli': ^8.0.0 + '@capacitor/core': ^8.0.0 + '@capacitor/ios': ^8.0.0 '@guiiai/logg': ^1.2.11 '@moeru/eslint-config': 0.1.0-beta.14 '@moeru/std': 0.1.0-beta.14