From 3f188132dbd4d24516307d561320a0273fe0ab8d Mon Sep 17 00:00:00 2001 From: zortos293 <65777760+zortos293@users.noreply.github.com> Date: Fri, 10 Apr 2026 21:38:02 +0000 Subject: [PATCH 01/66] Add Capacitor Android target and platform abstraction --- README.md | 37 +- docs/development.md | 30 +- opennow-stable/android/.gitignore | 101 +++ opennow-stable/android/app/.gitignore | 2 + opennow-stable/android/app/build.gradle | 54 ++ .../android/app/capacitor.build.gradle | 25 + opennow-stable/android/app/proguard-rules.pro | 21 + .../myapp/ExampleInstrumentedTest.java | 26 + .../android/app/src/main/AndroidManifest.xml | 48 ++ .../opencouldgaming/opennow/MainActivity.java | 5 + .../main/res/drawable-land-hdpi/splash.png | Bin 0 -> 7705 bytes .../main/res/drawable-land-mdpi/splash.png | Bin 0 -> 4040 bytes .../main/res/drawable-land-xhdpi/splash.png | Bin 0 -> 9251 bytes .../main/res/drawable-land-xxhdpi/splash.png | Bin 0 -> 13984 bytes .../main/res/drawable-land-xxxhdpi/splash.png | Bin 0 -> 17683 bytes .../main/res/drawable-port-hdpi/splash.png | Bin 0 -> 7934 bytes .../main/res/drawable-port-mdpi/splash.png | Bin 0 -> 4096 bytes .../main/res/drawable-port-xhdpi/splash.png | Bin 0 -> 9875 bytes .../main/res/drawable-port-xxhdpi/splash.png | Bin 0 -> 13346 bytes .../main/res/drawable-port-xxxhdpi/splash.png | Bin 0 -> 17489 bytes .../drawable-v24/ic_launcher_foreground.xml | 34 + .../res/drawable/ic_launcher_background.xml | 170 +++++ .../app/src/main/res/drawable/splash.png | Bin 0 -> 4040 bytes .../app/src/main/res/layout/activity_main.xml | 12 + .../res/mipmap-anydpi-v26/ic_launcher.xml | 5 + .../mipmap-anydpi-v26/ic_launcher_round.xml | 5 + .../src/main/res/mipmap-hdpi/ic_launcher.png | Bin 0 -> 2786 bytes .../mipmap-hdpi/ic_launcher_foreground.png | Bin 0 -> 3450 bytes .../res/mipmap-hdpi/ic_launcher_round.png | Bin 0 -> 4341 bytes .../src/main/res/mipmap-mdpi/ic_launcher.png | Bin 0 -> 1869 bytes .../mipmap-mdpi/ic_launcher_foreground.png | Bin 0 -> 2110 bytes .../res/mipmap-mdpi/ic_launcher_round.png | Bin 0 -> 2725 bytes .../src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 0 -> 3981 bytes .../mipmap-xhdpi/ic_launcher_foreground.png | Bin 0 -> 5036 bytes .../res/mipmap-xhdpi/ic_launcher_round.png | Bin 0 -> 6593 bytes .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin 0 -> 6644 bytes .../mipmap-xxhdpi/ic_launcher_foreground.png | Bin 0 -> 9793 bytes .../res/mipmap-xxhdpi/ic_launcher_round.png | Bin 0 -> 10455 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin 0 -> 9441 bytes .../mipmap-xxxhdpi/ic_launcher_foreground.png | Bin 0 -> 15529 bytes .../res/mipmap-xxxhdpi/ic_launcher_round.png | Bin 0 -> 15916 bytes .../res/values/ic_launcher_background.xml | 4 + .../app/src/main/res/values/strings.xml | 7 + .../app/src/main/res/values/styles.xml | 22 + .../app/src/main/res/xml/file_paths.xml | 5 + opennow-stable/android/build.gradle | 29 + .../android/capacitor.settings.gradle | 24 + opennow-stable/android/gradle.properties | 22 + .../android/gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 43764 bytes .../gradle/wrapper/gradle-wrapper.properties | 7 + opennow-stable/android/gradlew | 251 ++++++ opennow-stable/android/gradlew.bat | 94 +++ opennow-stable/android/settings.gradle | 5 + opennow-stable/android/variables.gradle | 16 + opennow-stable/capacitor.config.ts | 13 + opennow-stable/package-lock.json | 712 +++++++++++++++++- opennow-stable/package.json | 13 + opennow-stable/src/main/settings.ts | 39 +- opennow-stable/src/renderer/src/App.tsx | 82 +- .../src/components/ControllerLibraryPage.tsx | 25 +- .../renderer/src/components/SettingsPage.tsx | 135 ++-- .../renderer/src/components/StreamView.tsx | 49 +- .../src/renderer/src/gfn/webrtcClient.ts | 11 +- .../src/renderer/src/platform/android/api.ts | 392 ++++++++++ .../src/platform/android/browserSignaling.ts | 238 ++++++ .../src/renderer/src/platform/android/http.ts | 41 + .../renderer/src/platform/android/storage.ts | 104 +++ .../src/renderer/src/platform/electron.ts | 26 + .../src/renderer/src/platform/index.ts | 10 + .../src/renderer/src/platform/types.ts | 26 + opennow-stable/src/shared/gfnRuntime.ts | 99 +++ opennow-stable/src/shared/settings.ts | 39 + 72 files changed, 2900 insertions(+), 215 deletions(-) create mode 100644 opennow-stable/android/.gitignore create mode 100644 opennow-stable/android/app/.gitignore create mode 100644 opennow-stable/android/app/build.gradle create mode 100644 opennow-stable/android/app/capacitor.build.gradle create mode 100644 opennow-stable/android/app/proguard-rules.pro create mode 100644 opennow-stable/android/app/src/androidTest/java/com/getcapacitor/myapp/ExampleInstrumentedTest.java create mode 100644 opennow-stable/android/app/src/main/AndroidManifest.xml create mode 100644 opennow-stable/android/app/src/main/java/com/opencouldgaming/opennow/MainActivity.java create mode 100644 opennow-stable/android/app/src/main/res/drawable-land-hdpi/splash.png create mode 100644 opennow-stable/android/app/src/main/res/drawable-land-mdpi/splash.png create mode 100644 opennow-stable/android/app/src/main/res/drawable-land-xhdpi/splash.png create mode 100644 opennow-stable/android/app/src/main/res/drawable-land-xxhdpi/splash.png create mode 100644 opennow-stable/android/app/src/main/res/drawable-land-xxxhdpi/splash.png create mode 100644 opennow-stable/android/app/src/main/res/drawable-port-hdpi/splash.png create mode 100644 opennow-stable/android/app/src/main/res/drawable-port-mdpi/splash.png create mode 100644 opennow-stable/android/app/src/main/res/drawable-port-xhdpi/splash.png create mode 100644 opennow-stable/android/app/src/main/res/drawable-port-xxhdpi/splash.png create mode 100644 opennow-stable/android/app/src/main/res/drawable-port-xxxhdpi/splash.png create mode 100644 opennow-stable/android/app/src/main/res/drawable-v24/ic_launcher_foreground.xml create mode 100644 opennow-stable/android/app/src/main/res/drawable/ic_launcher_background.xml create mode 100644 opennow-stable/android/app/src/main/res/drawable/splash.png create mode 100644 opennow-stable/android/app/src/main/res/layout/activity_main.xml create mode 100644 opennow-stable/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml create mode 100644 opennow-stable/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml create mode 100644 opennow-stable/android/app/src/main/res/mipmap-hdpi/ic_launcher.png create mode 100644 opennow-stable/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png create mode 100644 opennow-stable/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png create mode 100644 opennow-stable/android/app/src/main/res/mipmap-mdpi/ic_launcher.png create mode 100644 opennow-stable/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png create mode 100644 opennow-stable/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png create mode 100644 opennow-stable/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png create mode 100644 opennow-stable/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png create mode 100644 opennow-stable/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png create mode 100644 opennow-stable/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png create mode 100644 opennow-stable/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png create mode 100644 opennow-stable/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png create mode 100644 opennow-stable/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png create mode 100644 opennow-stable/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png create mode 100644 opennow-stable/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png create mode 100644 opennow-stable/android/app/src/main/res/values/ic_launcher_background.xml create mode 100644 opennow-stable/android/app/src/main/res/values/strings.xml create mode 100644 opennow-stable/android/app/src/main/res/values/styles.xml create mode 100644 opennow-stable/android/app/src/main/res/xml/file_paths.xml create mode 100644 opennow-stable/android/build.gradle create mode 100644 opennow-stable/android/capacitor.settings.gradle create mode 100644 opennow-stable/android/gradle.properties create mode 100644 opennow-stable/android/gradle/wrapper/gradle-wrapper.jar create mode 100644 opennow-stable/android/gradle/wrapper/gradle-wrapper.properties create mode 100755 opennow-stable/android/gradlew create mode 100644 opennow-stable/android/gradlew.bat create mode 100644 opennow-stable/android/settings.gradle create mode 100644 opennow-stable/android/variables.gradle create mode 100644 opennow-stable/capacitor.config.ts create mode 100644 opennow-stable/src/renderer/src/platform/android/api.ts create mode 100644 opennow-stable/src/renderer/src/platform/android/browserSignaling.ts create mode 100644 opennow-stable/src/renderer/src/platform/android/http.ts create mode 100644 opennow-stable/src/renderer/src/platform/android/storage.ts create mode 100644 opennow-stable/src/renderer/src/platform/electron.ts create mode 100644 opennow-stable/src/renderer/src/platform/index.ts create mode 100644 opennow-stable/src/renderer/src/platform/types.ts create mode 100644 opennow-stable/src/shared/gfnRuntime.ts create mode 100644 opennow-stable/src/shared/settings.ts diff --git a/README.md b/README.md index 235d2389..b2cc69cc 100644 --- a/README.md +++ b/README.md @@ -53,13 +53,14 @@ ## Overview -OpenNOW is a community-built Electron app for playing GeForce NOW from an open-source desktop client. The active implementation lives in [`opennow-stable/`](opennow-stable) and uses Electron, React, and TypeScript across the main, preload, and renderer processes. +OpenNOW is a community-built GeForce NOW client. The active implementation lives in [`opennow-stable/`](opennow-stable) and now supports two runtime targets from the same React renderer: Electron for desktop and Capacitor for Android. The project aims to give players a transparent, customizable alternative to the official client without hiding the technical parts from contributors. ## Highlights - Open-source desktop client for Windows, macOS, and Linux +- Experimental Android target via Capacitor using the shared React renderer in a WebView - Catalog and public game browsing with search and library-aware session handling - Stream controls for codec, resolution, FPS, aspect ratio, region, and quality preferences - In-stream diagnostics overlay with latency, packet loss, decode, and render stats @@ -122,15 +123,39 @@ For a fuller setup guide, see [docs/development.md](docs/development.md). ## Architecture At A Glance -OpenNOW is split into three Electron layers: +OpenNOW uses a shared renderer with thin platform adapters: | Layer | Tech | Responsibility | | --- | --- | --- | -| Main | Electron + Node.js | OAuth, CloudMatch/session orchestration, signaling, caching, local file handling | -| Preload | Electron `contextBridge` | Safe IPC bridge between the app shell and UI | -| Renderer | React + TypeScript | Login flow, browsing, settings, WebRTC playback, diagnostics, controls | +| Main | Electron + Node.js | Desktop-only OAuth, IPC, local filesystem/media, cache, window management | +| Preload | Electron `contextBridge` | Desktop bridge exposing the existing OpenNOW API surface | +| Renderer | React + TypeScript | Shared login flow, browsing, settings, WebRTC playback, diagnostics, controls | +| Capacitor Android | Capacitor + WebView | Android shell, deep links, Preferences/filesystem storage, browser-based signaling | + +The code lives under [`opennow-stable/src/`](opennow-stable/src), with shared TypeScript types and platform-neutral helpers in [`opennow-stable/src/shared/`](opennow-stable/src/shared). The renderer now consumes [`src/renderer/src/platform/`](opennow-stable/src/renderer/src/platform/) instead of hard-coding `window.openNow`. + +## Android Status + +The Android target is an initial pass intended to run the core OpenNOW flow inside a Capacitor WebView. Current Android support includes: + +- auth session restore +- login via external browser + deep-link callback +- provider and region loading +- main/library/public game catalog fetches +- session create, poll, claim, and stop +- direct signaling from the WebView +- settings persistence +- screenshots and recordings stored in the app data directory + +Known Android limitations in this pass: + +- no desktop-style quit action +- no pointer-lock toggle semantics +- no Electron log export or cache deletion flow +- no show-in-folder integration for media +- screenshot export/save-as remains desktop-only +- some desktop shortcut UX is hidden or non-applicable on touch devices -The code lives under [`opennow-stable/src/`](opennow-stable/src), with shared TypeScript types and IPC contracts in [`opennow-stable/src/shared/`](opennow-stable/src/shared). ## Contributing diff --git a/docs/development.md b/docs/development.md index c2170597..985b3324 100644 --- a/docs/development.md +++ b/docs/development.md @@ -1,6 +1,6 @@ # Development Guide -This guide covers the active Electron-based OpenNOW client in [`opennow-stable/`](../opennow-stable). +This guide covers the active OpenNOW app in [`opennow-stable/`](../opennow-stable), including the existing Electron desktop target and the new Capacitor Android target. ## Prerequisites @@ -35,12 +35,18 @@ npm run dev npm run preview npm run typecheck npm run build +npm run build:web +npm run cap:sync:android +npm run cap:open:android npm run dist npm run dist:signed ``` ## Workspace Layout +The Android shell lives in [`opennow-stable/android/`](../opennow-stable/android), Capacitor config lives in [`opennow-stable/capacitor.config.ts`](../opennow-stable/capacitor.config.ts), and the renderer platform abstraction lives in [`opennow-stable/src/renderer/src/platform/`](../opennow-stable/src/renderer/src/platform/). + + ```text opennow-stable/ ├── src/ @@ -91,7 +97,8 @@ The renderer is a React app responsible for: - Browsing the catalog and public listings - Managing stream launch state and session recovery - Rendering the WebRTC stream -- Handling controller input, shortcuts, stats overlay, screenshots, recordings, and settings UI +- Handling controller input, stats overlay, screenshots, recordings, and settings UI +- Choosing the active runtime implementation through `src/renderer/src/platform/` Key entry points: @@ -162,3 +169,22 @@ Current build matrix: - Before opening a PR, run `npm run typecheck` and `npm run build`. For contribution workflow details, see [`.github/CONTRIBUTING.md`](../.github/CONTRIBUTING.md). + + +## Android Workflow + +Build and sync web assets into the Android project: + +```bash +cd opennow-stable +npm run cap:sync:android +``` + +Open the Android project in Android Studio: + +```bash +cd opennow-stable +npm run cap:open:android +``` + +Current Android support is limited to the core cloud-gaming path. Desktop-specific features such as quit app, pointer-lock toggles, log export, cache deletion, show-in-folder actions, and screenshot save-as are intentionally gated or unavailable on Android in this pass. diff --git a/opennow-stable/android/.gitignore b/opennow-stable/android/.gitignore new file mode 100644 index 00000000..48354a3d --- /dev/null +++ b/opennow-stable/android/.gitignore @@ -0,0 +1,101 @@ +# Using Android gitignore template: https://github.com/github/gitignore/blob/HEAD/Android.gitignore + +# Built application files +*.apk +*.aar +*.ap_ +*.aab + +# Files for the ART/Dalvik VM +*.dex + +# Java class files +*.class + +# Generated files +bin/ +gen/ +out/ +# Uncomment the following line in case you need and you don't have the release build type files in your app +# release/ + +# Gradle files +.gradle/ +build/ + +# Local configuration file (sdk path, etc) +local.properties + +# Proguard folder generated by Eclipse +proguard/ + +# Log Files +*.log + +# Android Studio Navigation editor temp files +.navigation/ + +# Android Studio captures folder +captures/ + +# IntelliJ +*.iml +.idea/workspace.xml +.idea/tasks.xml +.idea/gradle.xml +.idea/assetWizardSettings.xml +.idea/dictionaries +.idea/libraries +# Android Studio 3 in .gitignore file. +.idea/caches +.idea/modules.xml +# Comment next line if keeping position of elements in Navigation Editor is relevant for you +.idea/navEditor.xml + +# Keystore files +# Uncomment the following lines if you do not want to check your keystore files in. +#*.jks +#*.keystore + +# External native build folder generated in Android Studio 2.2 and later +.externalNativeBuild +.cxx/ + +# Google Services (e.g. APIs or Firebase) +# google-services.json + +# Freeline +freeline.py +freeline/ +freeline_project_description.json + +# fastlane +fastlane/report.xml +fastlane/Preview.html +fastlane/screenshots +fastlane/test_output +fastlane/readme.md + +# Version control +vcs.xml + +# lint +lint/intermediates/ +lint/generated/ +lint/outputs/ +lint/tmp/ +# lint/reports/ + +# Android Profiling +*.hprof + +# Cordova plugins for Capacitor +capacitor-cordova-android-plugins + +# Copied web assets +app/src/main/assets/public + +# Generated Config files +app/src/main/assets/capacitor.config.json +app/src/main/assets/capacitor.plugins.json +app/src/main/res/xml/config.xml diff --git a/opennow-stable/android/app/.gitignore b/opennow-stable/android/app/.gitignore new file mode 100644 index 00000000..043df802 --- /dev/null +++ b/opennow-stable/android/app/.gitignore @@ -0,0 +1,2 @@ +/build/* +!/build/.npmkeep diff --git a/opennow-stable/android/app/build.gradle b/opennow-stable/android/app/build.gradle new file mode 100644 index 00000000..f9f2e3e3 --- /dev/null +++ b/opennow-stable/android/app/build.gradle @@ -0,0 +1,54 @@ +apply plugin: 'com.android.application' + +android { + namespace = "com.opencouldgaming.opennow" + compileSdk = rootProject.ext.compileSdkVersion + defaultConfig { + applicationId "com.opencouldgaming.opennow" + minSdkVersion rootProject.ext.minSdkVersion + targetSdkVersion rootProject.ext.targetSdkVersion + versionCode 1 + versionName "1.0" + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + aaptOptions { + // Files and dirs to omit from the packaged assets dir, modified to accommodate modern web apps. + // Default: https://android.googlesource.com/platform/frameworks/base/+/282e181b58cf72b6ca770dc7ca5f91f135444502/tools/aapt/AaptAssets.cpp#61 + ignoreAssetsPattern = '!.svn:!.git:!.ds_store:!*.scc:.*:!CVS:!thumbs.db:!picasa.ini:!*~' + } + } + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + } + } +} + +repositories { + flatDir{ + dirs '../capacitor-cordova-android-plugins/src/main/libs', 'libs' + } +} + +dependencies { + implementation fileTree(include: ['*.jar'], dir: 'libs') + implementation "androidx.appcompat:appcompat:$androidxAppCompatVersion" + implementation "androidx.coordinatorlayout:coordinatorlayout:$androidxCoordinatorLayoutVersion" + implementation "androidx.core:core-splashscreen:$coreSplashScreenVersion" + implementation project(':capacitor-android') + testImplementation "junit:junit:$junitVersion" + androidTestImplementation "androidx.test.ext:junit:$androidxJunitVersion" + androidTestImplementation "androidx.test.espresso:espresso-core:$androidxEspressoCoreVersion" + implementation project(':capacitor-cordova-android-plugins') +} + +apply from: 'capacitor.build.gradle' + +try { + def servicesJSON = file('google-services.json') + if (servicesJSON.text) { + apply plugin: 'com.google.gms.google-services' + } +} catch(Exception e) { + logger.info("google-services.json not found, google-services plugin not applied. Push Notifications won't work") +} diff --git a/opennow-stable/android/app/capacitor.build.gradle b/opennow-stable/android/app/capacitor.build.gradle new file mode 100644 index 00000000..e2147299 --- /dev/null +++ b/opennow-stable/android/app/capacitor.build.gradle @@ -0,0 +1,25 @@ +// DO NOT EDIT THIS FILE! IT IS GENERATED EACH TIME "capacitor update" IS RUN + +android { + compileOptions { + sourceCompatibility JavaVersion.VERSION_21 + targetCompatibility JavaVersion.VERSION_21 + } +} + +apply from: "../capacitor-cordova-android-plugins/cordova.variables.gradle" +dependencies { + implementation project(':capacitor-app') + implementation project(':capacitor-browser') + implementation project(':capacitor-device') + implementation project(':capacitor-filesystem') + implementation project(':capacitor-http') + implementation project(':capacitor-preferences') + implementation project(':capacitor-status-bar') + +} + + +if (hasProperty('postBuildExtras')) { + postBuildExtras() +} diff --git a/opennow-stable/android/app/proguard-rules.pro b/opennow-stable/android/app/proguard-rules.pro new file mode 100644 index 00000000..f1b42451 --- /dev/null +++ b/opennow-stable/android/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile diff --git a/opennow-stable/android/app/src/androidTest/java/com/getcapacitor/myapp/ExampleInstrumentedTest.java b/opennow-stable/android/app/src/androidTest/java/com/getcapacitor/myapp/ExampleInstrumentedTest.java new file mode 100644 index 00000000..f2c2217e --- /dev/null +++ b/opennow-stable/android/app/src/androidTest/java/com/getcapacitor/myapp/ExampleInstrumentedTest.java @@ -0,0 +1,26 @@ +package com.getcapacitor.myapp; + +import static org.junit.Assert.*; + +import android.content.Context; +import androidx.test.ext.junit.runners.AndroidJUnit4; +import androidx.test.platform.app.InstrumentationRegistry; +import org.junit.Test; +import org.junit.runner.RunWith; + +/** + * Instrumented test, which will execute on an Android device. + * + * @see Testing documentation + */ +@RunWith(AndroidJUnit4.class) +public class ExampleInstrumentedTest { + + @Test + public void useAppContext() throws Exception { + // Context of the app under test. + Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); + + assertEquals("com.getcapacitor.app", appContext.getPackageName()); + } +} diff --git a/opennow-stable/android/app/src/main/AndroidManifest.xml b/opennow-stable/android/app/src/main/AndroidManifest.xml new file mode 100644 index 00000000..a1f342c4 --- /dev/null +++ b/opennow-stable/android/app/src/main/AndroidManifest.xml @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/opennow-stable/android/app/src/main/java/com/opencouldgaming/opennow/MainActivity.java b/opennow-stable/android/app/src/main/java/com/opencouldgaming/opennow/MainActivity.java new file mode 100644 index 00000000..e94ea72c --- /dev/null +++ b/opennow-stable/android/app/src/main/java/com/opencouldgaming/opennow/MainActivity.java @@ -0,0 +1,5 @@ +package com.opencouldgaming.opennow; + +import com.getcapacitor.BridgeActivity; + +public class MainActivity extends BridgeActivity {} diff --git a/opennow-stable/android/app/src/main/res/drawable-land-hdpi/splash.png b/opennow-stable/android/app/src/main/res/drawable-land-hdpi/splash.png new file mode 100644 index 0000000000000000000000000000000000000000..e31573b4fc93e60d171f4046c0220e1463075d9e GIT binary patch literal 7705 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 wKmFJ0_JHhk1&0B>;%YXATM literal 0 HcmV?d00001 diff --git a/opennow-stable/android/app/src/main/res/drawable-land-mdpi/splash.png b/opennow-stable/android/app/src/main/res/drawable-land-mdpi/splash.png new file mode 100644 index 0000000000000000000000000000000000000000..f7a64923ea1a0565d25fa139c176d6bf42184e48 GIT binary patch literal 4040 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 XyOn+%7f`N3b2T^T3uj5+eShz7v)7qy literal 0 HcmV?d00001 diff --git a/opennow-stable/android/app/src/main/res/drawable-land-xhdpi/splash.png b/opennow-stable/android/app/src/main/res/drawable-land-xhdpi/splash.png new file mode 100644 index 0000000000000000000000000000000000000000..807725501bdd92e94e51e7b2b0006f69e0083a0b GIT binary patch literal 9251 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 literal 0 HcmV?d00001 diff --git a/opennow-stable/android/app/src/main/res/drawable-land-xxhdpi/splash.png b/opennow-stable/android/app/src/main/res/drawable-land-xxhdpi/splash.png new file mode 100644 index 0000000000000000000000000000000000000000..14c6c8fe39fcd51a0414866ad28cbe8ff3acb060 GIT binary patch literal 13984 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®q@N z14_H8ofW)l{|J8q+a)eH)I0r)>WXdzV%7J>PA~6_J)KLT90iYa^K=Wz7D!OybzqSru=f4?|KFl;Y)gP_H6V4x`~kZ6fE(xM1&;?72-TZNk+0 zr+Crr5yl%Iy@vfmt3eYFl!jIvPGFz^8Ek+2`48O1_pCX3xNWh-zBa{rIcc%+=|XVj zANYTg&s}TKb#OztQrCW(Xk?V^i{`q~%HtcveTxq(_HKeC9GzrtguMT4Nvs@KakPTA z9>*8bBZmLz`lK5=l)=b|=dT3a5ag^a1^znZyx5QKfUb1b9yacArRp%3@QWo(hrsCU z-K!-=jDmv!zb7XT>)r|-Z0Ry}lk2;dk-ECqMwr_nKN#x*X6~B5hVIN>6$1HwBz3Of z=Pk){AL5*=d90f17_qZEJLm;Q%WMdX=*N&!ki@E&cy7?>{1ssAH(tACtp*r@d^til z)x(1#6(kPD+joSF&J3sxJU@{-sWCS+pZq{Gsx=?z4wP;>?)1yHv0?X?VP{}cX4~aH zxeBPKw_rgW8rvewS1W2#^y+c>-183iMbJCqc38RN_o~__9-n|jcd&oA`m7*&Fqqpc z;Tev*0LS-ZK47Sq1unfvP1S43uA12P?PJmI8BeTYPr~R*tYUm^0;U%Hmu?bSZHEK6 zPjsW=E67Kq-&trmf;)UkmRABH2U)V)-eRT$j(%G12lLMsThSsU10iP#{)ZnvjzN$d z*K%P3`}oqyvpWP~venr>3viH8^`)Ma*=B31hw*Q+tqE>i2y7w!(o^lI^Yss^=tHW( z;cnCT(%B1gLz+TRGW9roFjI1EQTu-u`(f#RmZ8;FSN(bsC1J;+(i_R6mrW=yYx$cy z#%QKVrEx~kVMg~yo?^N28Wnk6x%L;J8i|*|ANEiNjq(Vhzuzl3ikpA*G!Z}kLAzAI z9qnySo%D|AuJj12%h;Otqjs(>LPj?rNdeU8so>P(C>XMzlho94ZD#w=cCOOU;=3&^ zsqAG!i{~lY271D|m>ztPV`)X@FO_;`wPjppYNQpM+ncvtz1lZjN>!Q^*I}T%uP78Z7tbV2$q3W_)14=kLFyJ z1GqL6T>ClgeZorL!}xP4f%OB_EsmJ`uw7dGWNV9OLlhb|UMpVhc{4@Bhh`tO!ZqzD zhusd<=K^ah!L@gQ?6dOpI-ge^e>S5W9eII57Zu16eU?GRbgKTeVk9yS{iK|O(zLR> zheb?;jwGCHS80NCn=jKxgJ>}qu4l%5NPihjzazGv#J?Jcyl;<#IW&x4mm>nrW8>}C z3U@aeD~)*F(0o^2{GnKVm$Jr#aZE ztl~TOkM^SdzJapQ((!-i8b!RkVQBKkL`2ZCBuy!qI1L{3Er526plVols~68U-^9Px zR(3{j;Z9RHX^muc0dUywJ|`yyZFf=k&-Gb#m4u73Lm5Ks%BfHj%2|gjn#i> zLC5pO$2Em9H;qoKQmMtl<@wgtPF1%2HariD5O~u>8=^*J&au~JH%Ih@&2Uging3U_ z0bzfKucW$ZHSx}!#buB?+-J)%RQbbXM-!BJTS&#dU_@lxU6>te2O+9 z@F{F{Nb!;{Cd`Gx+$G?11aB~S#wIH%D=*=7f7H@D@%B1)&bF$@t3JDq4l*%(wJTlh zo`?uMq{YilKUewPNaC)GuOr<8j9&ofqRU__BRUX^x8Cj3a;a$rXzgXqW>LR#CUn%~m)t zYC&ol(gAkbc^fd`xWU&bk5vT6KbFmsR=O78Bn%t7 znbw&=c+|T&#r+bls5rU6D#HMvqA<|;)BV%jOMonkm^p$7Vcel-Wwn$=uAJv&(8W>% z9))Fxpl*(%E#wFm_m!U~2HqgZs^2vaGeY(UfYKrSHV}w^D0N6!se5Ewy)Yy-!(2

aKj2hWG7>znxs|SE zN4rHtiSPqLskWp(?(_YYwgq+1@8v+~8As|(bC>$D(atG3ZE8-ZM3SVcg|vHQz$I=!(A`k`5= zOqR>&%G)$)k*QLz7MTB9wleWpv&N9Sta64wy}3Ytd?x!Ja8z>(z~(3UNFu^eFmn#6 zw!!gUxOuZi$PQIs*ixfZR3iLyADJ z5&s%tPfk>V!x|A-;oq%1!yk9H$UBP0ToA*EDtz(^!_AnF1bBQ7joj|? z5b)gSI8c8O$PYFE!vXJ<4gebg*9G9P2wcB{#kv0FItc5T@PDNo)}Rh4Us}L{e}xzW zhwt`)j`M)mP=G6H0;^&q=I0{jU%bIRkF#uLF;{vVC&H|_uc literal 0 HcmV?d00001 diff --git a/opennow-stable/android/app/src/main/res/drawable-land-xxxhdpi/splash.png b/opennow-stable/android/app/src/main/res/drawable-land-xxxhdpi/splash.png new file mode 100644 index 0000000000000000000000000000000000000000..244ca2506dbe0fd8f6a05520ac7d1a629ea81438 GIT binary patch literal 17683 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 literal 0 HcmV?d00001 diff --git a/opennow-stable/android/app/src/main/res/drawable-port-xxhdpi/splash.png b/opennow-stable/android/app/src/main/res/drawable-port-xxhdpi/splash.png new file mode 100644 index 0000000000000000000000000000000000000000..bfabe6871a17a5e95b78fb30d49b7d2b4d2fe4c0 GIT binary patch literal 13346 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

VwO4Hu8X}%XHUAz_J@50rzbkIsat>4oWtQt< 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 literal 0 HcmV?d00001 diff --git a/opennow-stable/android/app/src/main/res/drawable-port-xxxhdpi/splash.png b/opennow-stable/android/app/src/main/res/drawable-port-xxxhdpi/splash.png new file mode 100644 index 0000000000000000000000000000000000000000..6929071268eb03ee0f088142b6523566b78550e2 GIT binary patch literal 17489 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 KR&><$`~L^lv%S~= literal 0 HcmV?d00001 diff --git a/opennow-stable/android/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/opennow-stable/android/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 00000000..c7bd21db --- /dev/null +++ b/opennow-stable/android/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + diff --git a/opennow-stable/android/app/src/main/res/drawable/ic_launcher_background.xml b/opennow-stable/android/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 00000000..d5fccc53 --- /dev/null +++ b/opennow-stable/android/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/opennow-stable/android/app/src/main/res/drawable/splash.png b/opennow-stable/android/app/src/main/res/drawable/splash.png new file mode 100644 index 0000000000000000000000000000000000000000..f7a64923ea1a0565d25fa139c176d6bf42184e48 GIT binary patch literal 4040 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 XyOn+%7f`N3b2T^T3uj5+eShz7v)7qy literal 0 HcmV?d00001 diff --git a/opennow-stable/android/app/src/main/res/layout/activity_main.xml b/opennow-stable/android/app/src/main/res/layout/activity_main.xml new file mode 100644 index 00000000..b5ad1387 --- /dev/null +++ b/opennow-stable/android/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,12 @@ + + + + + diff --git a/opennow-stable/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/opennow-stable/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 00000000..036d09bc --- /dev/null +++ b/opennow-stable/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/opennow-stable/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/opennow-stable/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 00000000..036d09bc --- /dev/null +++ b/opennow-stable/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/opennow-stable/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/opennow-stable/android/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..c023e50595074292c7361183a64de08cf9686c9c GIT binary patch literal 2786 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 literal 0 HcmV?d00001 diff --git a/opennow-stable/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png b/opennow-stable/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..2127973b2d318df7085734d236d0ec649a2b0292 GIT binary patch literal 3450 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 literal 0 HcmV?d00001 diff --git a/opennow-stable/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/opennow-stable/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..4d1e077104cd61e6a4c3707e87363b523077245a GIT binary patch literal 3981 zcmV;84|4E{P)?m z2Iqx7pAYgakSjnIq={jqe_xK2+h*EzWwd!kfWi5380F4z@bASS>p|K~(;2oMw*a3< zK?+G?T5chzM-ta%1;eyc>o{H=hukKL25q{GrPnd+0-KniwCBCEX}iOg#o7W)E)HXr zd(Ve|7lL$v@QH~D&KTpmX>rrCz0YZ)8#Xshc|FT^xTaguda8BDHIv&=Useyu_v$*1 zE3FHi#1s6Ccz|>ii^Xel9SMTXLZR>#xWSPCc*}KN2mWk^(?%1*8lH5juXvA@x zr?BV4&1|^Y#I)XED2#-ddR}jaHn0a$dUVOPmILihzZU<-5kl$t(?^2qT^lzN!aYAE zh>2~QChzL%dM+0NgnQN0)N}zfegGLpx|6}Bl2BR?!Pm-9642O<6%FqtvjQaqK`M+H9vOMH38sJ-;5jwj zl##{26!QLoq4Aere)&g;T^YKzue*<_n(J+&NC zv0cwQO6e?!4H7UsJY0P7#TS2!*yTaM+{VVnMM!|SiDA+JOR@=e0KTheJ7f}8J1Q=! z417T*5?s{cN37_asDgli@#mj^{wIiC?gZd4^B+oqgb-l}{&>t#HZqccZAJ}lRub@e zjF^#xB!owT@QQ>Ds5k*rJ%a|AVfYW21b+BMOjDhNv>>Zo67V?;!;+I&CjR0yA<$6 zK#3y+JtGk(%m@K861*4Jr(RqqfJ?Cn<@otY5i>>YL{+LerFJGsm@xvP-a-=iStDkl zfARmz4YHC*pxU&!5h6%{(O4M*8X6iGLC-D9BH^&tkOY1f60(AyM1m~BrKl$)0lXtj z2~}nUz>SMKAri)yK@UOG<@#1vNZ{d%=apU%Bw%}i|DKCsb{vP{vkndpRYnDQAV?x% zG>Yi$P`x7x2@VkXcBjn`4LOs+Tjr=4r2h7FaDgsnvI z(+sn!|NlCI|2E^dzQK4M$bCRU`{``p?;rHRzp;VwUxF;z#Q47tX9K_LZfF=>J0;Lj z3D%-7ycxj1Ya8RYLGQoq%_$OA012O#NkZEIv543R;sGXZOO(#L9qoS@3{)`ZS9?6)O zC$|WREgA{<4&7%=zUBkQ>!J78za3A4P)8kS7|AfB+W8%{vE(&hrjfA8CjklSI$hob zQB?_;n!|O;x?VwfjRFG(cazLoL4r*PV_ zyji-c5fC?lPA4J0UR;p1yB|Cs0tu@VNWi~88HSz@*Dc-bOA-mo0Q}besWz-KNT><{ z03b_Ry+94;qa;lB{FoqX7l5+reYrYXv)wn$Zivu>0RHdcx?eYfY)&Sj9z3F!KK0yD z)d>h(O_ugRY9!cx&)2QgIb0-R<@@xJ-~{0R0gU*~TR<99+ubM0BPMAA9o5kaqB_FBZTY*5{|3~`EnAXFK=4~m<+lP43BVCp zkx00xo6=;QY7q8TH{%cQ2HiVIi*C^{-?v?^j_N?A{I_g zRhG>#UzUG1l#q^A^?Kd}@Ygg0pgS0Uuo=O1N%@=BLE1=2BjIkS+d9CM^Gaz`szN=_ z*nEHr32*f5(#Kd zCSmU&BdeqPi0bH`ZGO*p+ArAt^#*LDIbXF1&PA}l!odw1p-xrXOG7``*?;oZCmKdx>NLce; zJ|s-8?E5UJpfLDCj*T+@gbE1+wXy3IorLxbB-jZ?SPx>PicQL6Af`%ymNJ1}LV`pc zsf>gyxg#m~PO=+nRoV^JG}B8(Pzj(+pd$$+brg`mh&BP!)JVeZk}N8wvX#KsWkXy*0>vhvI-=MFH^`z= zMgp!oYX7h6y^|{VGZKiolbhG_+mD6s@Lr!!0L3sHI4e$W~a}TJ2Jpl!XRkpTR)djZJ3*+|$&4AxruT`v&3>m9%6=eanyVsStv zBH<1I|1TebYuO3}v?i1AD17%=D=lq7oln@?@9@TBPOi(-y_J1^6^MiZ)S{)D3zDpM zI1J!F^D*Op+UFDSP(VPGgeSl#A3PJNDT0eii4*+vg5?Qm&l-UQvr@Sr%!XQu+0e;g zErEo?;O#v73F8m9`2>`Z5E=>Vz$hOY@!OjW*7j!$*6c`-Mct{BMnbS^!rP!RYvu!z zNI;$c41oVgn=eSh!x0it)(h}6M9fijWG8G_%|e1$yyZBvaYigef(Kr~2met3_mTY} z684pjg!N#QKOKqpYTO`!x4w;L6U6kUElDqE#8Y0x&j08H{p_6+4o)#Sde-58J?Mik zq=bY(9j*V!2cMG4CQok;xt_kKZ5*VL;GN9!S(ua;Lw9Gt%^wGFA3G3F0ut~Pe1C9+ z-Y#W&a}~%NU8p8hPI+;pM!Yblm#CvzOMt%v-Cq~<0qEpECy?;e$7hr4}XItd8=p^@_QNO9Afxb$)JiSh%hIK%9LADNo0_;EGp zhJuAxCcsEJdjUs+P)ARLQEoq*J(G$yVO>B1=8~Ga%U?JgM?xIPW2B~#s=U73?}2!GM-fMLwYkcVpd+cth{kB zy%e>zifhG&O$<3gqw8mUMvZwoeI9pMXmCr{1gc);HT{!OWQ3e%WBFt4yuey%8H0M z5@uvl9(T%9R*k869n|>*^vZC#pi2z~DUJc$8x1aHjyX!gjGPsLdRKPdz6$tM5)k~N zW~xWzDI^G0W)RPgn>r2NnVHj4gl=_N@{b;Zn zT^=Q&oFiXkB*dLdl;t?$w8gio=N(n$=;E}qqrI(2c#3W0MA@t&yd&E#Z^c>~39`kv zDo5=gHg<4$cdi6%-MaPr)YH=u98A+{x|v&a>y{jK&vI)Q?bj$gtE^4>Q9Hr$^$>`? z@WKl}&5eLpUww6lJavQOhY}4oA(@Qxhp92pe$XWbeq6&p!Ku zJP5#_-u#50{k$^h}~UKPw4IL6*uXFL7QJU^9W(jE#-) zrlzL9BW3}1bMheI!X-b;x7WtU%Phg%`g)BMn^|I*0JDm$*3RG3a*vG1xqfQ;FN;L|6*^H z6>KwD2_h|G`fx(>2W nm0GElTB(&OnKI&V600000NkvXXu0mjff+~0a literal 0 HcmV?d00001 diff --git a/opennow-stable/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png b/opennow-stable/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..df0f15880bee46332dfc6622583215194f948b0f GIT binary patch literal 5036 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 literal 0 HcmV?d00001 diff --git a/opennow-stable/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/opennow-stable/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..6cdf97c1196d48e9833487ff6de7c4cfc4e1232d GIT binary patch literal 6644 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 literal 0 HcmV?d00001 diff --git a/opennow-stable/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png b/opennow-stable/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..2960cbb6104b915c84760f889deed9bff2b3e17a GIT binary patch literal 9793 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 y3vD~Wi9;mL_v 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 literal 0 HcmV?d00001 diff --git a/opennow-stable/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/opennow-stable/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png new file mode 100644 index 0000000000000000000000000000000000000000..a40d73e9c68ea638c28c7b13e4bcd1e179a3a102 GIT binary patch literal 15916 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 + + #FFFFFF + \ No newline at end of file diff --git a/opennow-stable/android/app/src/main/res/values/strings.xml b/opennow-stable/android/app/src/main/res/values/strings.xml new file mode 100644 index 00000000..60ba7161 --- /dev/null +++ b/opennow-stable/android/app/src/main/res/values/strings.xml @@ -0,0 +1,7 @@ + + + OpenNOW + OpenNOW + com.opencouldgaming.opennow + com.opencouldgaming.opennow + diff --git a/opennow-stable/android/app/src/main/res/values/styles.xml b/opennow-stable/android/app/src/main/res/values/styles.xml new file mode 100644 index 00000000..be874e54 --- /dev/null +++ b/opennow-stable/android/app/src/main/res/values/styles.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/opennow-stable/android/app/src/main/res/xml/file_paths.xml b/opennow-stable/android/app/src/main/res/xml/file_paths.xml new file mode 100644 index 00000000..bd0c4d80 --- /dev/null +++ b/opennow-stable/android/app/src/main/res/xml/file_paths.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/opennow-stable/android/build.gradle b/opennow-stable/android/build.gradle new file mode 100644 index 00000000..f8f0e43b --- /dev/null +++ b/opennow-stable/android/build.gradle @@ -0,0 +1,29 @@ +// Top-level build file where you can add configuration options common to all sub-projects/modules. + +buildscript { + + repositories { + google() + mavenCentral() + } + dependencies { + classpath 'com.android.tools.build:gradle:8.13.0' + classpath 'com.google.gms:google-services:4.4.4' + + // NOTE: Do not place your application dependencies here; they belong + // in the individual module build.gradle files + } +} + +apply from: "variables.gradle" + +allprojects { + repositories { + google() + mavenCentral() + } +} + +task clean(type: Delete) { + delete rootProject.buildDir +} diff --git a/opennow-stable/android/capacitor.settings.gradle b/opennow-stable/android/capacitor.settings.gradle new file mode 100644 index 00000000..90dd5869 --- /dev/null +++ b/opennow-stable/android/capacitor.settings.gradle @@ -0,0 +1,24 @@ +// DO NOT EDIT THIS FILE! IT IS GENERATED EACH TIME "capacitor update" IS RUN +include ':capacitor-android' +project(':capacitor-android').projectDir = new File('../node_modules/@capacitor/android/capacitor') + +include ':capacitor-app' +project(':capacitor-app').projectDir = new File('../node_modules/@capacitor/app/android') + +include ':capacitor-browser' +project(':capacitor-browser').projectDir = new File('../node_modules/@capacitor/browser/android') + +include ':capacitor-device' +project(':capacitor-device').projectDir = new File('../node_modules/@capacitor/device/android') + +include ':capacitor-filesystem' +project(':capacitor-filesystem').projectDir = new File('../node_modules/@capacitor/filesystem/android') + +include ':capacitor-http' +project(':capacitor-http').projectDir = new File('../node_modules/@capacitor/http/android') + +include ':capacitor-preferences' +project(':capacitor-preferences').projectDir = new File('../node_modules/@capacitor/preferences/android') + +include ':capacitor-status-bar' +project(':capacitor-status-bar').projectDir = new File('../node_modules/@capacitor/status-bar/android') diff --git a/opennow-stable/android/gradle.properties b/opennow-stable/android/gradle.properties new file mode 100644 index 00000000..2e87c52f --- /dev/null +++ b/opennow-stable/android/gradle.properties @@ -0,0 +1,22 @@ +# Project-wide Gradle settings. + +# IDE (e.g. Android Studio) users: +# Gradle settings configured through the IDE *will override* +# any settings specified in this file. + +# For more details on how to configure your build environment visit +# http://www.gradle.org/docs/current/userguide/build_environment.html + +# Specifies the JVM arguments used for the daemon process. +# The setting is particularly useful for tweaking memory settings. +org.gradle.jvmargs=-Xmx1536m + +# When configured, Gradle will run in incubating parallel mode. +# This option should only be used with decoupled projects. More details, visit +# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects +# org.gradle.parallel=true + +# AndroidX package structure to make it clearer which packages are bundled with the +# Android operating system, and which are packaged with your app's APK +# https://developer.android.com/topic/libraries/support-library/androidx-rn +android.useAndroidX=true diff --git a/opennow-stable/android/gradle/wrapper/gradle-wrapper.jar b/opennow-stable/android/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..1b33c55baabb587c669f562ae36f953de2481846 GIT binary patch literal 43764 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 '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + +CLASSPATH="\\\"\\\"" + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/opennow-stable/android/gradlew.bat b/opennow-stable/android/gradlew.bat new file mode 100644 index 00000000..5eed7ee8 --- /dev/null +++ b/opennow-stable/android/gradlew.bat @@ -0,0 +1,94 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem +@rem SPDX-License-Identifier: Apache-2.0 +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH= + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/opennow-stable/android/settings.gradle b/opennow-stable/android/settings.gradle new file mode 100644 index 00000000..3b4431d7 --- /dev/null +++ b/opennow-stable/android/settings.gradle @@ -0,0 +1,5 @@ +include ':app' +include ':capacitor-cordova-android-plugins' +project(':capacitor-cordova-android-plugins').projectDir = new File('./capacitor-cordova-android-plugins/') + +apply from: 'capacitor.settings.gradle' \ No newline at end of file diff --git a/opennow-stable/android/variables.gradle b/opennow-stable/android/variables.gradle new file mode 100644 index 00000000..ee4ba41c --- /dev/null +++ b/opennow-stable/android/variables.gradle @@ -0,0 +1,16 @@ +ext { + minSdkVersion = 24 + compileSdkVersion = 36 + targetSdkVersion = 36 + androidxActivityVersion = '1.11.0' + androidxAppCompatVersion = '1.7.1' + androidxCoordinatorLayoutVersion = '1.3.0' + androidxCoreVersion = '1.17.0' + androidxFragmentVersion = '1.8.9' + coreSplashScreenVersion = '1.2.0' + androidxWebkitVersion = '1.14.0' + junitVersion = '4.13.2' + androidxJunitVersion = '1.3.0' + androidxEspressoCoreVersion = '3.7.0' + cordovaAndroidVersion = '14.0.1' +} \ No newline at end of file diff --git a/opennow-stable/capacitor.config.ts b/opennow-stable/capacitor.config.ts new file mode 100644 index 00000000..1dad04da --- /dev/null +++ b/opennow-stable/capacitor.config.ts @@ -0,0 +1,13 @@ +import type { CapacitorConfig } from "@capacitor/cli"; + +const config: CapacitorConfig = { + appId: "com.opencloudgaming.opennow", + appName: "OpenNOW", + webDir: "dist", + bundledWebRuntime: false, + server: { + androidScheme: "https", + }, +}; + +export default config; diff --git a/opennow-stable/package-lock.json b/opennow-stable/package-lock.json index 4e46427c..6fa1c7dd 100644 --- a/opennow-stable/package-lock.json +++ b/opennow-stable/package-lock.json @@ -8,12 +8,22 @@ "name": "opennow-stable", "version": "0.3.2", "dependencies": { + "@capacitor/android": "^8.3.0", + "@capacitor/app": "^8.1.0", + "@capacitor/browser": "^8.0.3", + "@capacitor/core": "^8.3.0", + "@capacitor/device": "^8.0.2", + "@capacitor/filesystem": "^8.1.2", + "@capacitor/http": "^0.0.2", + "@capacitor/preferences": "^8.0.1", + "@capacitor/status-bar": "^8.0.2", "lucide-react": "^1.7.0", "react": "^19.2.4", "react-dom": "^19.2.4", "ws": "^8.20.0" }, "devDependencies": { + "@capacitor/cli": "^8.3.0", "@types/node": "^22.19.17", "@types/react": "^19.2.14", "@types/react-dom": "^19.2.3", @@ -327,6 +337,267 @@ "node": ">=6.9.0" } }, + "node_modules/@capacitor/android": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/@capacitor/android/-/android-8.3.0.tgz", + "integrity": "sha512-EQy6ByUuKayQBJmMm/e0byJiHavqsQHrvW23BuT2GNVQvenAvipqwaePiJHzrv2PZr7A0T0+se4kgDCeROj0mQ==", + "license": "MIT", + "peerDependencies": { + "@capacitor/core": "^8.3.0" + } + }, + "node_modules/@capacitor/app": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@capacitor/app/-/app-8.1.0.tgz", + "integrity": "sha512-MlmttTOWHDedr/G4SrhNRxsXMqY+R75S4MM4eIgzsgCzOYhb/MpCkA5Q3nuOCfL1oHm26xjUzqZ5aupbOwdfYg==", + "license": "MIT", + "peerDependencies": { + "@capacitor/core": ">=8.0.0" + } + }, + "node_modules/@capacitor/browser": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/@capacitor/browser/-/browser-8.0.3.tgz", + "integrity": "sha512-WJWPHEPbweiFoHYmVlCbZf5yrqJ2Rchx2Xvbmd+3Lf+Zkpq3nXBThThY2CF69lYEg1NINGF9BcHThIOEU1gZlQ==", + "license": "MIT", + "peerDependencies": { + "@capacitor/core": ">=8.0.0" + } + }, + "node_modules/@capacitor/cli": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/@capacitor/cli/-/cli-8.3.0.tgz", + "integrity": "sha512-n3QDUimtFNbagoo8kLdjvTz3i3Y4jX1fOjvo6ptUKLzErmuqeamL8kECASoyQvg/OzJisZToGZrgLphBsptJcw==", + "dev": true, + "license": "MIT", + "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.0", + "env-paths": "^2.2.0", + "fs-extra": "^11.2.0", + "kleur": "^4.1.5", + "native-run": "^2.0.3", + "open": "^8.4.0", + "plist": "^3.1.0", + "prompts": "^2.4.2", + "rimraf": "^6.0.1", + "semver": "^7.6.3", + "tar": "^7.5.3", + "tslib": "^2.8.1", + "xml2js": "^0.6.2" + }, + "bin": { + "cap": "bin/capacitor", + "capacitor": "bin/capacitor" + }, + "engines": { + "node": ">=22.0.0" + } + }, + "node_modules/@capacitor/cli/node_modules/commander": { + "version": "12.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", + "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@capacitor/cli/node_modules/fs-extra": { + "version": "11.3.4", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.4.tgz", + "integrity": "sha512-CTXd6rk/M3/ULNQj8FBqBWHYBVYybQ3VPBw0xGKFe3tuH7ytT6ACnvzpIQ3UZtB8yvUKC2cXn1a+x+5EVQLovA==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" + } + }, + "node_modules/@capacitor/cli/node_modules/glob": { + "version": "13.0.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-13.0.6.tgz", + "integrity": "sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "minimatch": "^10.2.2", + "minipass": "^7.1.3", + "path-scurry": "^2.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@capacitor/cli/node_modules/jsonfile": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", + "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", + "dev": true, + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/@capacitor/cli/node_modules/kleur": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz", + "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/@capacitor/cli/node_modules/lru-cache": { + "version": "11.3.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.3.3.tgz", + "integrity": "sha512-JvNw9Y81y33E+BEYPr0U7omo+U9AySnsMsEiXgwT6yqd31VQWTLNQqmT4ou5eqPFUrTfIDFta2wKhB1hyohtAQ==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/@capacitor/cli/node_modules/path-scurry": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.2.tgz", + "integrity": "sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^11.0.0", + "minipass": "^7.1.2" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@capacitor/cli/node_modules/rimraf": { + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-6.1.3.tgz", + "integrity": "sha512-LKg+Cr2ZF61fkcaK1UdkH2yEBBKnYjTyWzTJT6KNPcSPaiT7HSdhtMXQuN5wkTX0Xu72KQ1l8S42rlmexS2hSA==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "glob": "^13.0.3", + "package-json-from-dist": "^1.0.1" + }, + "bin": { + "rimraf": "dist/esm/bin.mjs" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@capacitor/cli/node_modules/semver": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@capacitor/cli/node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/@capacitor/core": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/@capacitor/core/-/core-8.3.0.tgz", + "integrity": "sha512-S4ajn4G/fS3VJj8salxqH/3LO5PPWv1VxGKQ27OCajnDcLJjEg9VXwgMPnlypgkIOqCJ2fmQLtk8GT+BlI9/rw==", + "license": "MIT", + "peer": true, + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/@capacitor/device": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@capacitor/device/-/device-8.0.2.tgz", + "integrity": "sha512-fIqSXnG0s6bz5A/0xFgSXDkbU+Xl65ti80LhucNvLI4kGhJzcNn6SwWVwpXN9SJTOFWXblXknHNppheP8X1frQ==", + "license": "MIT", + "peerDependencies": { + "@capacitor/core": ">=8.0.0" + } + }, + "node_modules/@capacitor/filesystem": { + "version": "8.1.2", + "resolved": "https://registry.npmjs.org/@capacitor/filesystem/-/filesystem-8.1.2.tgz", + "integrity": "sha512-doaaMfGoFR2hWU6aV6u83I+5ZsGyJVq+Gz4r9lMpJzUKMm1eMu0hLnFdV1aXZlU9FlK/RndFrVD8oRZfNOqWgQ==", + "license": "MIT", + "dependencies": { + "@capacitor/synapse": "^1.0.4" + }, + "peerDependencies": { + "@capacitor/core": ">=8.0.0" + } + }, + "node_modules/@capacitor/http": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/@capacitor/http/-/http-0.0.2.tgz", + "integrity": "sha512-3UPqYOmVkAQjCWWowSDGPnBkXY7znbPE7lNs8nhwTmE2E5fXTvjHM8PV15zOyn+nenY7zEu9Air49fGjrX+Tjg==", + "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", + "license": "MIT", + "dependencies": { + "@capacitor/core": "latest" + } + }, + "node_modules/@capacitor/preferences": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@capacitor/preferences/-/preferences-8.0.1.tgz", + "integrity": "sha512-T6no3ebi79XJCk91U3Jp/liJUwgBdvHR+s6vhvPkPxSuch7z3zx5Rv1bdWM6sWruNx+pViuEGqZvbfCdyBvcHQ==", + "license": "MIT", + "peerDependencies": { + "@capacitor/core": ">=8.0.0" + } + }, + "node_modules/@capacitor/status-bar": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@capacitor/status-bar/-/status-bar-8.0.2.tgz", + "integrity": "sha512-WXs8YB8B9eEaPZz+bcdY6t2nForF1FLoj/JU0Dl9RRgQnddnS98FEEyDooQhaY7wivr000j4+SC1FyeJkrFO7A==", + "license": "MIT", + "peerDependencies": { + "@capacitor/core": ">=8.0.0" + } + }, + "node_modules/@capacitor/synapse": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@capacitor/synapse/-/synapse-1.0.4.tgz", + "integrity": "sha512-/C1FUo8/OkKuAT4nCIu/34ny9siNHr9qtFezu4kxm6GY1wNFxrCFWjfYx5C1tUhVGz3fxBABegupkpjXvjCHrw==", + "license": "ISC" + }, "node_modules/@develar/schema-utils": { "version": "2.6.5", "resolved": "https://registry.npmjs.org/@develar/schema-utils/-/schema-utils-2.6.5.tgz", @@ -735,7 +1006,6 @@ "dev": true, "license": "BSD-2-Clause", "optional": true, - "peer": true, "dependencies": { "cross-dirname": "^0.1.0", "debug": "^4.3.4", @@ -757,7 +1027,6 @@ "dev": true, "license": "MIT", "optional": true, - "peer": true, "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", @@ -774,7 +1043,6 @@ "dev": true, "license": "MIT", "optional": true, - "peer": true, "dependencies": { "universalify": "^2.0.0" }, @@ -789,7 +1057,6 @@ "dev": true, "license": "MIT", "optional": true, - "peer": true, "engines": { "node": ">= 10.0.0" } @@ -1243,6 +1510,205 @@ "node": ">=18" } }, + "node_modules/@ionic/cli-framework-output": { + "version": "2.2.8", + "resolved": "https://registry.npmjs.org/@ionic/cli-framework-output/-/cli-framework-output-2.2.8.tgz", + "integrity": "sha512-TshtaFQsovB4NWRBydbNFawql6yul7d5bMiW1WYYf17hd99V6xdDdk3vtF51bw6sLkxON3bDQpWsnUc9/hVo3g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@ionic/utils-terminal": "2.3.5", + "debug": "^4.0.0", + "tslib": "^2.0.1" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@ionic/utils-array": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/@ionic/utils-array/-/utils-array-2.1.6.tgz", + "integrity": "sha512-0JZ1Zkp3wURnv8oq6Qt7fMPo5MpjbLoUoa9Bu2Q4PJuSDWM8H8gwF3dQO7VTeUj3/0o1IB1wGkFWZZYgUXZMUg==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.0.0", + "tslib": "^2.0.1" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@ionic/utils-fs": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/@ionic/utils-fs/-/utils-fs-3.1.7.tgz", + "integrity": "sha512-2EknRvMVfhnyhL1VhFkSLa5gOcycK91VnjfrTB0kbqkTFCOXyXgVLI5whzq7SLrgD9t1aqos3lMMQyVzaQ5gVA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/fs-extra": "^8.0.0", + "debug": "^4.0.0", + "fs-extra": "^9.0.0", + "tslib": "^2.0.1" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@ionic/utils-fs/node_modules/@types/fs-extra": { + "version": "8.1.5", + "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-8.1.5.tgz", + "integrity": "sha512-0dzKcwO+S8s2kuF5Z9oUWatQJj5Uq/iqphEtE3GQJVRRYm/tD1LglU2UnXi2A8jLq5umkGouOXOR9y0n613ZwQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@ionic/utils-fs/node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@ionic/utils-fs/node_modules/jsonfile": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", + "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", + "dev": true, + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/@ionic/utils-fs/node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/@ionic/utils-object": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/@ionic/utils-object/-/utils-object-2.1.6.tgz", + "integrity": "sha512-vCl7sl6JjBHFw99CuAqHljYJpcE88YaH2ZW4ELiC/Zwxl5tiwn4kbdP/gxi2OT3MQb1vOtgAmSNRtusvgxI8ww==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.0.0", + "tslib": "^2.0.1" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@ionic/utils-process": { + "version": "2.1.12", + "resolved": "https://registry.npmjs.org/@ionic/utils-process/-/utils-process-2.1.12.tgz", + "integrity": "sha512-Jqkgyq7zBs/v/J3YvKtQQiIcxfJyplPgECMWgdO0E1fKrrH8EF0QGHNJ9mJCn6PYe2UtHNS8JJf5G21e09DfYg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@ionic/utils-object": "2.1.6", + "@ionic/utils-terminal": "2.3.5", + "debug": "^4.0.0", + "signal-exit": "^3.0.3", + "tree-kill": "^1.2.2", + "tslib": "^2.0.1" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@ionic/utils-stream": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/@ionic/utils-stream/-/utils-stream-3.1.7.tgz", + "integrity": "sha512-eSELBE7NWNFIHTbTC2jiMvh1ABKGIpGdUIvARsNPMNQhxJB3wpwdiVnoBoTYp+5a6UUIww4Kpg7v6S7iTctH1w==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.0.0", + "tslib": "^2.0.1" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@ionic/utils-subprocess": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@ionic/utils-subprocess/-/utils-subprocess-3.0.1.tgz", + "integrity": "sha512-cT4te3AQQPeIM9WCwIg8ohroJ8TjsYaMb2G4ZEgv9YzeDqHZ4JpeIKqG2SoaA3GmVQ3sOfhPM6Ox9sxphV/d1A==", + "dev": true, + "license": "MIT", + "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.3", + "debug": "^4.0.0", + "tslib": "^2.0.1" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@ionic/utils-terminal": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@ionic/utils-terminal/-/utils-terminal-2.3.5.tgz", + "integrity": "sha512-3cKScz9Jx2/Pr9ijj1OzGlBDfcmx7OMVBt4+P1uRR0SSW4cm1/y3Mo4OY3lfkuaYifMNBW8Wz6lQHbs1bihr7A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/slice-ansi": "^4.0.0", + "debug": "^4.0.0", + "signal-exit": "^3.0.3", + "slice-ansi": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0", + "tslib": "^2.0.1", + "untildify": "^4.0.0", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@ionic/utils-terminal/node_modules/slice-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, "node_modules/@isaacs/cliui": { "version": "8.0.2", "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", @@ -2151,6 +2617,13 @@ "@types/node": "*" } }, + "node_modules/@types/slice-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@types/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-+OpjSaq85gvlZAYINyzKpLeiFkSC4EsC6IIiT6v6TLSU5k5U83fHGj9Lel8oKEXM0HqgrMVCjXPDPVICtxF7EQ==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/verror": { "version": "1.10.11", "resolved": "https://registry.npmjs.org/@types/verror/-/verror-1.10.11.tgz", @@ -2529,7 +3002,6 @@ "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", "dev": true, "license": "MIT", - "optional": true, "engines": { "node": ">=8" } @@ -2612,6 +3084,16 @@ "node": ">=6.0.0" } }, + "node_modules/big-integer": { + "version": "1.6.52", + "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.52.tgz", + "integrity": "sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg==", + "dev": true, + "license": "Unlicense", + "engines": { + "node": ">=0.6" + } + }, "node_modules/bippy": { "version": "0.5.39", "resolved": "https://registry.npmjs.org/bippy/-/bippy-0.5.39.tgz", @@ -2643,6 +3125,19 @@ "license": "MIT", "optional": true }, + "node_modules/bplist-parser": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.3.2.tgz", + "integrity": "sha512-apC2+fspHGI3mMKj+dGevkGo/tCqVB8jMb6i+OX+E29p0Iposz07fABkRIfVUPNd5A5VbuOz1bZbnmkKLYF+wQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "big-integer": "1.6.x" + }, + "engines": { + "node": ">= 5.10.0" + } + }, "node_modules/brace-expansion": { "version": "5.0.5", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.5.tgz", @@ -3194,8 +3689,7 @@ "integrity": "sha512-+R08/oI0nl3vfPcqftZRpytksBXDzOUveBq/NBVx0sUp1axwzPQrKinNx5yd5sxPu8j1wIy8AfnVQ+5eFdha6Q==", "dev": true, "license": "MIT", - "optional": true, - "peer": true + "optional": true }, "node_modules/cross-env": { "version": "10.1.0", @@ -3326,6 +3820,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/define-lazy-prop": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", + "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/define-properties": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", @@ -3760,7 +4264,6 @@ "dev": true, "hasInstallScript": true, "license": "MIT", - "peer": true, "dependencies": { "@electron/asar": "^3.2.1", "debug": "^4.1.1", @@ -3781,7 +4284,6 @@ "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "graceful-fs": "^4.1.2", "jsonfile": "^4.0.0", @@ -3808,6 +4310,26 @@ "dev": true, "license": "MIT" }, + "node_modules/elementtree": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/elementtree/-/elementtree-0.1.7.tgz", + "integrity": "sha512-wkgGT6kugeQk/P6VZ/f4T+4HB41BVgNBq5CDIZVbQ02nvTVqAiVTbskxxu3eA/X96lMlfYOwnLQpN2v5E1zDEg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "sax": "1.1.4" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/elementtree/node_modules/sax": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.1.4.tgz", + "integrity": "sha512-5f3k2PbGGp+YtKJjOItpg3P99IMD84E4HOvcfleTb5joCHNXYLsR9yWFPOYGgaeMPDubQILTCMdsFb2OMeOjtg==", + "dev": true, + "license": "ISC" + }, "node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", @@ -4668,6 +5190,16 @@ "dev": true, "license": "ISC" }, + "node_modules/ini": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/ini/-/ini-4.1.3.tgz", + "integrity": "sha512-X7rqawQBvfdjS10YU1y1YVreA3SsLrW9dX2CewP2EbBJM4ypVNLDkO5y04gejPwKIY9lR+7r9gn3rFPt/kmWFg==", + "dev": true, + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, "node_modules/ip-address": { "version": "10.1.0", "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.1.0.tgz", @@ -4678,6 +5210,22 @@ "node": ">= 12" } }, + "node_modules/is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "dev": true, + "license": "MIT", + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", @@ -4711,6 +5259,19 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-docker": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/isbinaryfile": { "version": "5.0.7", "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-5.0.7.tgz", @@ -5225,20 +5786,6 @@ "node": ">= 18" } }, - "node_modules/mkdirp": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", - "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "minimist": "^1.2.6" - }, - "bin": { - "mkdirp": "bin/cmd.js" - } - }, "node_modules/mkdirp": { "version": "0.5.6", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", @@ -5278,6 +5825,32 @@ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, + "node_modules/native-run": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/native-run/-/native-run-2.0.3.tgz", + "integrity": "sha512-U1PllBuzW5d1gfan+88L+Hky2eZx+9gv3Pf6rNBxKbORxi7boHzqiA6QFGSnqMem4j0A9tZ08NMIs5+0m/VS1Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@ionic/utils-fs": "^3.1.7", + "@ionic/utils-terminal": "^2.3.4", + "bplist-parser": "^0.3.2", + "debug": "^4.3.4", + "elementtree": "^0.1.7", + "ini": "^4.1.1", + "plist": "^3.1.0", + "split2": "^4.2.0", + "through2": "^4.0.2", + "tslib": "^2.6.2", + "yauzl": "^2.10.0" + }, + "bin": { + "native-run": "bin/native-run" + }, + "engines": { + "node": ">=16.0.0" + } + }, "node_modules/negotiator": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz", @@ -5482,6 +6055,24 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/open": { + "version": "8.4.2", + "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz", + "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-lazy-prop": "^2.0.0", + "is-docker": "^2.1.1", + "is-wsl": "^2.2.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/ora": { "version": "5.4.1", "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", @@ -5689,7 +6280,6 @@ "dev": true, "license": "MIT", "optional": true, - "peer": true, "dependencies": { "commander": "^9.4.0" }, @@ -5707,7 +6297,6 @@ "dev": true, "license": "MIT", "optional": true, - "peer": true, "engines": { "node": "^12.20.0 || >=14" } @@ -5718,6 +6307,7 @@ "integrity": "sha512-gQCLc/vWroE8lIpleXtdJhTFDogTdZG9AjMUpVkDf2iTCNwYNWA+u16dL41TqUDJO4gm2IgrcMv3uTpjd4Pwmg==", "dev": true, "license": "MIT", + "peer": true, "funding": { "type": "opencollective", "url": "https://opencollective.com/preact" @@ -6009,7 +6599,6 @@ "deprecated": "Rimraf versions prior to v4 are no longer supported", "dev": true, "license": "ISC", - "peer": true, "dependencies": { "glob": "^7.1.3" }, @@ -6322,6 +6911,16 @@ "source-map": "^0.6.0" } }, + "node_modules/split2": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", + "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">= 10.x" + } + }, "node_modules/sprintf-js": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", @@ -6480,7 +7079,6 @@ "integrity": "sha512-yYrrsWnrXMcdsnu/7YMYAofM1ktpL5By7vZhf15CrXijWWrEYZks5AXBudalfSWJLlnen/QUJUB5aoB0kqZUGA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "mkdirp": "^0.5.1", "rimraf": "~2.6.2" @@ -6538,6 +7136,16 @@ "node": ">= 10.0.0" } }, + "node_modules/through2": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/through2/-/through2-4.0.2.tgz", + "integrity": "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "readable-stream": "3" + } + }, "node_modules/tiny-async-pool": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/tiny-async-pool/-/tiny-async-pool-1.3.0.tgz", @@ -6595,6 +7203,16 @@ "tmp": "^0.2.0" } }, + "node_modules/tree-kill": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", + "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", + "dev": true, + "license": "MIT", + "bin": { + "tree-kill": "cli.js" + } + }, "node_modules/truncate-utf8-bytes": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/truncate-utf8-bytes/-/truncate-utf8-bytes-1.0.2.tgz", @@ -6605,6 +7223,12 @@ "utf8-byte-length": "^1.0.1" } }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, "node_modules/type-fest": { "version": "0.13.1", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz", @@ -6691,6 +7315,16 @@ "node": ">=18.12.0" } }, + "node_modules/untildify": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz", + "integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/update-browserslist-db": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", @@ -7421,6 +8055,30 @@ } } }, + "node_modules/xml2js": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.6.2.tgz", + "integrity": "sha512-T4rieHaC1EXcES0Kxxj4JWgaUQHDk+qwHcYOCFHfiwKz7tOVPLq7Hjq9dM1WCMhylqMEfP7hMcOIChvotiZegA==", + "dev": true, + "license": "MIT", + "dependencies": { + "sax": ">=0.6.0", + "xmlbuilder": "~11.0.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/xml2js/node_modules/xmlbuilder": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", + "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4.0" + } + }, "node_modules/xmlbuilder": { "version": "15.1.1", "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-15.1.1.tgz", diff --git a/opennow-stable/package.json b/opennow-stable/package.json index 621d1283..795636f9 100644 --- a/opennow-stable/package.json +++ b/opennow-stable/package.json @@ -18,17 +18,30 @@ "dev": "electron-vite dev", "build": "electron-vite build", "preview": "electron-vite preview", + "build:web": "electron-vite build", + "cap:sync:android": "npm run build:web && npx cap sync android", + "cap:open:android": "npx cap open android", "dist": "npm run build && cross-env CSC_IDENTITY_AUTO_DISCOVERY=false electron-builder", "dist:signed": "npm run build && electron-builder", "typecheck": "tsc --noEmit -p tsconfig.node.json && tsc --noEmit -p tsconfig.json" }, "dependencies": { + "@capacitor/android": "^8.3.0", + "@capacitor/app": "^8.1.0", + "@capacitor/browser": "^8.0.3", + "@capacitor/core": "^8.3.0", + "@capacitor/device": "^8.0.2", + "@capacitor/filesystem": "^8.1.2", + "@capacitor/http": "^0.0.2", + "@capacitor/preferences": "^8.0.1", + "@capacitor/status-bar": "^8.0.2", "lucide-react": "^1.7.0", "react": "^19.2.4", "react-dom": "^19.2.4", "ws": "^8.20.0" }, "devDependencies": { + "@capacitor/cli": "^8.3.0", "@types/node": "^22.19.17", "@types/react": "^19.2.14", "@types/react-dom": "^19.2.3", diff --git a/opennow-stable/src/main/settings.ts b/opennow-stable/src/main/settings.ts index db226b1e..1f250024 100644 --- a/opennow-stable/src/main/settings.ts +++ b/opennow-stable/src/main/settings.ts @@ -3,6 +3,7 @@ import { join } from "node:path"; import { readFileSync, writeFileSync, existsSync, mkdirSync } from "node:fs"; import type { VideoCodec, ColorQuality, VideoAccelerationPreference, MicrophoneMode, GameLanguage, AspectRatio, KeyboardLayout } from "@shared/gfn"; import { DEFAULT_KEYBOARD_LAYOUT } from "@shared/gfn"; +import { DEFAULT_SETTINGS as SHARED_DEFAULT_SETTINGS } from "@shared/settings"; export interface Settings { /** Video resolution (e.g., "1920x1080") */ @@ -82,43 +83,7 @@ const defaultMicShortcut = "Ctrl+Shift+M"; const LEGACY_STOP_SHORTCUTS = new Set(["META+SHIFT+Q", "CMD+SHIFT+Q"]); const LEGACY_ANTI_AFK_SHORTCUTS = new Set(["META+SHIFT+F10", "CMD+SHIFT+F10", "CTRL+SHIFT+F10"]); -const DEFAULT_SETTINGS: Settings = { - resolution: "1920x1080", - aspectRatio: "16:9", - fps: 60, - maxBitrateMbps: 75, - codec: "H264", - colorQuality: "8bit_420", - region: "", - clipboardPaste: false, - mouseSensitivity: 1, - mouseAcceleration: 1, - shortcutToggleStats: "F3", - shortcutTogglePointerLock: "F8", - shortcutStopStream: defaultStopShortcut, - shortcutToggleAntiAfk: defaultAntiAfkShortcut, - shortcutToggleMicrophone: defaultMicShortcut, - shortcutScreenshot: "F11", - shortcutToggleRecording: "F12", - microphoneMode: "disabled", - microphoneDeviceId: "", - hideStreamButtons: false, - showStatsOnLaunch: false, - controllerMode: false, - controllerUiSounds: false, - controllerBackgroundAnimations: false, - autoLoadControllerLibrary: false, - autoFullScreen: false, - favoriteGameIds: [], - sessionCounterEnabled: false, - sessionClockShowEveryMinutes: 60, - sessionClockShowDurationSeconds: 30, - windowWidth: 1400, - windowHeight: 900, - keyboardLayout: DEFAULT_KEYBOARD_LAYOUT, - gameLanguage: "en_US", - enableL4S: false, -}; +const DEFAULT_SETTINGS: Settings = { ...SHARED_DEFAULT_SETTINGS }; export class SettingsManager { private settings: Settings; diff --git a/opennow-stable/src/renderer/src/App.tsx b/opennow-stable/src/renderer/src/App.tsx index c71b4c1b..4473bce4 100644 --- a/opennow-stable/src/renderer/src/App.tsx +++ b/opennow-stable/src/renderer/src/App.tsx @@ -38,6 +38,7 @@ import { useControllerNavigation } from "./controllerNavigation"; import { useElapsedSeconds } from "./utils/useElapsedSeconds"; import { usePlaytime } from "./utils/usePlaytime"; import { createStreamDiagnosticsStore } from "./utils/streamDiagnosticsStore"; +import { openNow, platformCapabilities, platform } from "./platform"; // UI Components import { LoginScreen } from "./components/LoginScreen"; @@ -1227,7 +1228,7 @@ export function App(): JSX.Element { `watchedTimeInMs=${request.watchedTimeInMs ?? "n/a"}, pausedTimeInMs=${request.pausedTimeInMs ?? 0}, ` + `cancelReason=${request.cancelReason ?? "n/a"}, errorInfo=${request.errorInfo ?? "n/a"}`, ); - const updated = await window.openNow.reportSessionAd(request); + const updated = await openNow.reportSessionAd(request); if (sessionRef.current?.sessionId !== updated.sessionId) { return; } @@ -1391,7 +1392,7 @@ export function App(): JSX.Element { const loadSubscriptionInfo = useCallback( async (session: AuthSession): Promise => { const token = session.tokens.idToken ?? session.tokens.accessToken; - const subscription = await window.openNow.fetchSubscription({ + const subscription = await openNow.fetchSubscription({ token, providerStreamingBaseUrl: session.provider.streamingServiceUrl, userId: session.user.userId, @@ -1412,7 +1413,7 @@ export function App(): JSX.Element { return; } try { - const activeSessions = await window.openNow.getActiveSessions(token, effectiveStreamingBaseUrl); + const activeSessions = await openNow.getActiveSessions(token, effectiveStreamingBaseUrl); const candidate = activeSessions.find((entry) => entry.status === 3 || entry.status === 2) ?? null; setNavbarActiveSession(candidate); } catch (error) { @@ -1476,7 +1477,7 @@ export function App(): JSX.Element { const initialize = async () => { try { // Load settings first - const loadedSettings = await window.openNow.getSettings(); + const loadedSettings = await openNow.getSettings(); setSettings(loadedSettings); setShowStatsOverlay(loadedSettings.showStatsOnLaunch); setSettingsLoaded(true); @@ -1484,8 +1485,8 @@ export function App(): JSX.Element { // Load providers and session (refresh only if token is near expiry) setStartupStatusMessage("Restoring saved session..."); const [providerList, sessionResult] = await Promise.all([ - window.openNow.getLoginProviders(), - window.openNow.getAuthSession(), + openNow.getLoginProviders(), + openNow.getAuthSession(), ]); const persistedSession = sessionResult.session; @@ -1533,7 +1534,7 @@ export function App(): JSX.Element { if (persistedSession) { // Load regions const token = persistedSession.tokens.idToken ?? persistedSession.tokens.accessToken; - const discovered = await window.openNow.getRegions({ token }); + const discovered = await openNow.getRegions({ token }); setRegions(discovered); try { @@ -1545,7 +1546,7 @@ export function App(): JSX.Element { // Load games try { - const mainGames = await window.openNow.fetchMainGames({ + const mainGames = await openNow.fetchMainGames({ token, providerStreamingBaseUrl: persistedSession.provider.streamingServiceUrl, }); @@ -1555,7 +1556,7 @@ export function App(): JSX.Element { applyVariantSelections(mainGames); // Also load library - const libGames = await window.openNow.fetchLibraryGames({ + const libGames = await openNow.fetchLibraryGames({ token, providerStreamingBaseUrl: persistedSession.provider.streamingServiceUrl, }); @@ -1563,14 +1564,14 @@ export function App(): JSX.Element { applyVariantSelections(libGames); } catch { // Fallback to public games - const publicGames = await window.openNow.fetchPublicGames(); + const publicGames = await openNow.fetchPublicGames(); setGames(publicGames); setSource("public"); applyVariantSelections(publicGames); } } else { // Load public games for non-logged in users - const publicGames = await window.openNow.fetchPublicGames(); + const publicGames = await openNow.fetchPublicGames(); setGames(publicGames); setSource("public"); applyVariantSelections(publicGames); @@ -1697,7 +1698,7 @@ export function App(): JSX.Element { // Listen for F11 fullscreen toggle from main process (uses W3C Fullscreen API // so navigator.keyboard.lock() can capture Escape in fullscreen) useEffect(() => { - const unsubscribe = window.openNow.onToggleFullscreen(() => { + const unsubscribe = openNow.onToggleFullscreen(() => { if (document.fullscreenElement) { document.exitFullscreen().catch(() => {}); } else { @@ -1792,7 +1793,7 @@ export function App(): JSX.Element { // Signaling events useEffect(() => { - const unsubscribe = window.openNow.onSignalingEvent(async (event: MainToRendererSignalingEvent) => { + const unsubscribe = openNow.onSignalingEvent(async (event: MainToRendererSignalingEvent) => { console.log(`[App] Signaling event: ${event.type}`, event.type === "offer" ? `(SDP ${event.sdp.length} chars)` : "", event.type === "remote-ice" ? event.candidate : ""); try { if (event.type === "offer") { @@ -1882,7 +1883,7 @@ export function App(): JSX.Element { const updateSetting = useCallback(async (key: K, value: Settings[K]) => { setSettings((prev) => ({ ...prev, [key]: value })); if (settingsLoaded) { - await window.openNow.setSetting(key, value); + await openNow.setSetting(key, value); } // If a running client exists, push certain settings live if (key === "mouseSensitivity") { @@ -1932,8 +1933,8 @@ export function App(): JSX.Element { if (settingsLoaded) { void Promise.all([ - window.openNow.setSetting("controllerMode", false), - window.openNow.setSetting("autoLoadControllerLibrary", false), + openNow.setSetting("controllerMode", false), + openNow.setSetting("autoLoadControllerLibrary", false), ]).catch((error) => { console.warn("Failed to persist controller mode exit settings:", error); }); @@ -1941,7 +1942,8 @@ export function App(): JSX.Element { }, [settingsLoaded]); const handleExitApp = useCallback(() => { - void window.openNow.quitApp().catch((error) => { + if (!platformCapabilities.supportsQuitApp) return; + void openNow.quitApp().catch((error) => { console.warn("Failed to quit application:", error); }); }, []); @@ -1958,13 +1960,13 @@ export function App(): JSX.Element { setIsLoggingIn(true); setLoginError(null); try { - const session = await window.openNow.login({ providerIdpId: providerIdpId || undefined }); + const session = await openNow.login({ providerIdpId: providerIdpId || undefined }); setAuthSession(session); setProviderIdpId(session.provider.idpId); // Load regions const token = session.tokens.idToken ?? session.tokens.accessToken; - const discovered = await window.openNow.getRegions({ token }); + const discovered = await openNow.getRegions({ token }); setRegions(discovered); try { @@ -1975,7 +1977,7 @@ export function App(): JSX.Element { } // Load games - const mainGames = await window.openNow.fetchMainGames({ + const mainGames = await openNow.fetchMainGames({ token, providerStreamingBaseUrl: session.provider.streamingServiceUrl, }); @@ -1985,7 +1987,7 @@ export function App(): JSX.Element { applyVariantSelections(mainGames); // Load library - const libGames = await window.openNow.fetchLibraryGames({ + const libGames = await openNow.fetchLibraryGames({ token, providerStreamingBaseUrl: session.provider.streamingServiceUrl, }); @@ -2000,7 +2002,7 @@ export function App(): JSX.Element { // Logout handler const handleLogout = useCallback(async () => { - await window.openNow.logout(); + await openNow.logout(); setAuthSession(null); setGames([]); setLibraryGames([]); @@ -2010,7 +2012,7 @@ export function App(): JSX.Element { setIsResumingNavbarSession(false); setSubscriptionInfo(null); setCurrentPage("home"); - const publicGames = await window.openNow.fetchPublicGames(); + const publicGames = await openNow.fetchPublicGames(); setGames(publicGames); setSource("public"); applyVariantSelections(publicGames); @@ -2025,13 +2027,13 @@ export function App(): JSX.Element { let result: GameInfo[] = []; if (targetSource === "main" && token) { - result = await window.openNow.fetchMainGames({ token, providerStreamingBaseUrl: baseUrl }); + result = await openNow.fetchMainGames({ token, providerStreamingBaseUrl: baseUrl }); } else if (targetSource === "library" && token) { - result = await window.openNow.fetchLibraryGames({ token, providerStreamingBaseUrl: baseUrl }); + result = await openNow.fetchLibraryGames({ token, providerStreamingBaseUrl: baseUrl }); setLibraryGames(result); applyVariantSelections(result); } else if (targetSource === "public") { - result = await window.openNow.fetchPublicGames(); + result = await openNow.fetchPublicGames(); } if (targetSource !== "library") { @@ -2079,7 +2081,7 @@ export function App(): JSX.Element { setStreamingStore(null); } - const claimed = await window.openNow.claimSession({ + const claimed = await openNow.claimSession({ token, streamingBaseUrl: effectiveStreamingBaseUrl, serverIp: existingSession.serverIp, @@ -2110,7 +2112,7 @@ export function App(): JSX.Element { sessionRef.current = claimed; setQueuePosition(undefined); setStreamStatus("connecting"); - await window.openNow.connectSignaling({ + await openNow.connectSignaling({ sessionId: claimed.sessionId, signalingServer: claimed.signalingServer, signalingUrl: claimed.signalingUrl, @@ -2167,7 +2169,7 @@ export function App(): JSX.Element { if (!appId && token) { try { - const resolved = await window.openNow.resolveLaunchAppId({ + const resolved = await openNow.resolveLaunchAppId({ token, providerStreamingBaseUrl: effectiveStreamingBaseUrl, appIdOrUuid: game.uuid ?? selectedVariantId, @@ -2195,7 +2197,7 @@ export function App(): JSX.Element { // Check for active sessions first if (token) { try { - const activeSessions = await window.openNow.getActiveSessions(token, effectiveStreamingBaseUrl); + const activeSessions = await openNow.getActiveSessions(token, effectiveStreamingBaseUrl); if (activeSessions.length > 0) { // Only claim sessions that are already paused/ready (status 2 or 3). // Status=1 sessions are still in queue/setup; sending a RESUME claim @@ -2211,7 +2213,7 @@ export function App(): JSX.Element { } if (otherSession) { - const choice = await window.openNow.showSessionConflictDialog(); + const choice = await openNow.showSessionConflictDialog(); if (choice === "cancel") { resetLaunchRuntime(); return; @@ -2230,7 +2232,7 @@ export function App(): JSX.Element { } // Create new session - const newSession = await window.openNow.createSession({ + const newSession = await openNow.createSession({ token: token || undefined, streamingBaseUrl: effectiveStreamingBaseUrl, appId, @@ -2312,7 +2314,7 @@ export function App(): JSX.Element { return; } - const polled = await window.openNow.pollSession({ + const polled = await openNow.pollSession({ token: token || undefined, streamingBaseUrl: newSession.streamingBaseUrl ?? effectiveStreamingBaseUrl, serverIp: newSession.serverIp, @@ -2380,7 +2382,7 @@ export function App(): JSX.Element { status: sessionToConnect.status, }); - await window.openNow.connectSignaling({ + await openNow.connectSignaling({ sessionId: sessionToConnect.sessionId, signalingServer: sessionToConnect.signalingServer, signalingUrl: sessionToConnect.signalingUrl, @@ -2391,7 +2393,7 @@ export function App(): JSX.Element { } console.error("Launch failed:", error); setLaunchError(toLaunchErrorState(error, loadingStep)); - await window.openNow.disconnectSignaling().catch(() => {}); + await openNow.disconnectSignaling().catch(() => {}); clientRef.current?.dispose(); clientRef.current = null; resetLaunchRuntime({ keepLaunchError: true, keepStreamingContext: true }); @@ -2449,7 +2451,7 @@ export function App(): JSX.Element { } catch (error) { console.error("Navbar resume failed:", error); setLaunchError(toLaunchErrorState(error, loadingStep)); - await window.openNow.disconnectSignaling().catch(() => {}); + await openNow.disconnectSignaling().catch(() => {}); clientRef.current?.dispose(); clientRef.current = null; resetLaunchRuntime({ keepLaunchError: true }); @@ -2478,12 +2480,12 @@ export function App(): JSX.Element { if (status !== "idle" && status !== "streaming") { launchAbortRef.current = true; } - await window.openNow.disconnectSignaling(); + await openNow.disconnectSignaling(); const current = sessionRef.current; if (current) { const token = authSession?.tokens.idToken ?? authSession?.tokens.accessToken; - await window.openNow.stopSession({ + await openNow.stopSession({ token: token || undefined, streamingBaseUrl: current.streamingBaseUrl, serverIp: current.serverIp, @@ -2554,7 +2556,7 @@ export function App(): JSX.Element { }, [handleStopStream, handlePlayGame]); const handleDismissLaunchError = useCallback(async () => { - await window.openNow.disconnectSignaling().catch(() => {}); + await openNow.disconnectSignaling().catch(() => {}); clientRef.current?.dispose(); clientRef.current = null; resetLaunchRuntime(); @@ -2663,7 +2665,7 @@ export function App(): JSX.Element { return; } - if (isShortcutMatch(e, shortcuts.togglePointerLock)) { + if (platformCapabilities.supportsPointerLockToggle && isShortcutMatch(e, shortcuts.togglePointerLock)) { e.preventDefault(); e.stopPropagation(); e.stopImmediatePropagation(); diff --git a/opennow-stable/src/renderer/src/components/ControllerLibraryPage.tsx b/opennow-stable/src/renderer/src/components/ControllerLibraryPage.tsx index f1af77c6..16a82ef6 100644 --- a/opennow-stable/src/renderer/src/components/ControllerLibraryPage.tsx +++ b/opennow-stable/src/renderer/src/components/ControllerLibraryPage.tsx @@ -6,6 +6,7 @@ import { ButtonA, ButtonB, ButtonX, ButtonY, ButtonPSCross, ButtonPSCircle, Butt import { getStoreDisplayName } from "./GameCard"; import { SessionElapsedIndicator, RemainingPlaytimeIndicator, CurrentClock } from "./ElapsedSessionIndicators"; import { type PlaytimeStore, formatPlaytime, formatLastPlayed } from "../utils/usePlaytime"; +import { openNow, platformCapabilities } from "../platform"; interface ControllerLibraryPageProps { games: GameInfo[]; @@ -395,7 +396,7 @@ export function ControllerLibraryPage({ useEffect(() => { if (topCategory !== "media" || mediaSubcategory === "root") return; - if (typeof window.openNow?.listMediaByGame !== "function") { + if (typeof openNow?.listMediaByGame !== "function") { setMediaVideos([]); setMediaScreenshots([]); setMediaThumbById({}); @@ -409,7 +410,7 @@ export function ControllerLibraryPage({ try { setMediaLoading(true); setMediaError(null); - const listing = await window.openNow.listMediaByGame({}); + const listing = await openNow.listMediaByGame({}); if (cancelled) return; const videos = [...(listing.videos ?? [])].sort((a, b) => b.createdAtMs - a.createdAtMs); @@ -423,8 +424,8 @@ export function ControllerLibraryPage({ allItems.map(async (item): Promise<[string, string | null]> => { if (item.thumbnailDataUrl) return [item.id, item.thumbnailDataUrl]; if (item.dataUrl) return [item.id, item.dataUrl]; - if (typeof window.openNow?.getMediaThumbnail === "function") { - const generated = await window.openNow.getMediaThumbnail({ filePath: item.filePath }); + if (typeof openNow?.getMediaThumbnail === "function") { + const generated = await openNow.getMediaThumbnail({ filePath: item.filePath }); return [item.id, generated]; } return [item.id, null]; @@ -493,7 +494,7 @@ export function ControllerLibraryPage({ }, [currentStreamingGame, selectedGame]); useEffect(() => { - if (!showGameHub || !selectedGame?.title || typeof window.openNow?.listMediaByGame !== "function") { + if (!showGameHub || !selectedGame?.title || typeof openNow?.listMediaByGame !== "function") { setGameHubMedia([]); setGameHubMediaLoading(false); return; @@ -506,7 +507,7 @@ export function ControllerLibraryPage({ const timeoutId = window.setTimeout(() => { void (async () => { try { - const listing = await window.openNow.listMediaByGame({ gameTitle: selectedGame.title }); + const listing = await openNow.listMediaByGame({ gameTitle: selectedGame.title }); if (cancelled) return; const recentItems: GameHubMediaItem[] = [ @@ -522,8 +523,8 @@ export function ControllerLibraryPage({ recentItems.map(async (item): Promise<[string, string | null]> => { if (item.thumbnailDataUrl) return [item.id, item.thumbnailDataUrl]; if (item.dataUrl) return [item.id, item.dataUrl]; - if (typeof window.openNow?.getMediaThumbnail === "function") { - const generated = await window.openNow.getMediaThumbnail({ filePath: item.filePath }); + if (typeof openNow?.getMediaThumbnail === "function") { + const generated = await openNow.getMediaThumbnail({ filePath: item.filePath }); return [item.id, generated]; } return [item.id, null]; @@ -717,8 +718,8 @@ export function ControllerLibraryPage({ if (settingsSubcategory === "root" && setting?.id === "exitApp") { if (onExitApp) { onExitApp(); - } else if (window.openNow?.quitApp) { - void window.openNow.quitApp(); + } else if (platformCapabilities.supportsQuitApp) { + void openNow.quitApp(); } playUiSound("confirm"); return; @@ -753,8 +754,8 @@ export function ControllerLibraryPage({ if (mediaSubcategory !== "root") { const selectedMedia = mediaAssetItems[selectedMediaIndex]; - if (selectedMedia && typeof window.openNow?.showMediaInFolder === "function") { - void window.openNow.showMediaInFolder({ filePath: selectedMedia.filePath }); + if (selectedMedia && platformCapabilities.supportsMediaFolderAccess) { + void openNow.showMediaInFolder({ filePath: selectedMedia.filePath }); playUiSound("confirm"); return; } diff --git a/opennow-stable/src/renderer/src/components/SettingsPage.tsx b/opennow-stable/src/renderer/src/components/SettingsPage.tsx index e3b96fe4..95acf1b6 100644 --- a/opennow-stable/src/renderer/src/components/SettingsPage.tsx +++ b/opennow-stable/src/renderer/src/components/SettingsPage.tsx @@ -18,6 +18,7 @@ import type { } from "@shared/gfn"; import { colorQualityRequiresHevc, keyboardLayoutOptions } from "@shared/gfn"; import { formatShortcutForDisplay, normalizeShortcut } from "../shortcuts"; +import { openNow, platformCapabilities } from "../platform"; interface SettingsPageProps { settings: Settings; @@ -571,7 +572,7 @@ export function SettingsPage({ settings, regions, onSettingChange }: SettingsPag if (regions.length === 0) return; setIsPinging(true); try { - const results = await window.openNow.pingRegions(regions); + const results = await openNow.pingRegions(regions); const pingMap = new Map(); let bestUrl: string | null = null; let bestPing = Infinity; @@ -698,7 +699,7 @@ export function SettingsPage({ settings, regions, onSettingChange }: SettingsPag async function load(): Promise { try { - const sessionResult = await window.openNow.getAuthSession(); + const sessionResult = await openNow.getAuthSession(); const session = sessionResult.session; if (!session || cancelled) { setEntitledResolutions([]); @@ -714,7 +715,7 @@ export function SettingsPage({ settings, regions, onSettingChange }: SettingsPag return; } - const sub = await window.openNow.fetchSubscription({ + const sub = await openNow.fetchSubscription({ userId, }); @@ -824,8 +825,8 @@ export function SettingsPage({ settings, regions, onSettingChange }: SettingsPag }; try { - if (typeof window.openNow?.getMicrophonePermission === "function") { - const permission = await window.openNow.getMicrophonePermission(); + if (typeof openNow?.getMicrophonePermission === "function") { + const permission = await openNow.getMicrophonePermission(); if (cancelled) { return; } @@ -1055,7 +1056,7 @@ export function SettingsPage({ settings, regions, onSettingChange }: SettingsPag let requestPromise: Promise; try { - const getThanksData = window.openNow?.getThanksData; + const getThanksData = openNow?.getThanksData; if (typeof getThanksData !== "function") { throw new Error("openNow.getThanksData is unavailable"); } @@ -2302,63 +2303,73 @@ export function SettingsPage({ settings, regions, onSettingChange }: SettingsPag

Miscellaneous

- {/* Export Logs */} -
- - -
+ {platformCapabilities.supportsLogExport && ( +
+ + +
+ )} -
- - -
+ {platformCapabilities.supportsCacheDeletion && ( +
+ + +
+ )} + + {!platformCapabilities.supportsLogExport && !platformCapabilities.supportsCacheDeletion && ( +
+ + Local log export and Electron cache management are not available on Android in this pass. +
+ )}
diff --git a/opennow-stable/src/renderer/src/components/StreamView.tsx b/opennow-stable/src/renderer/src/components/StreamView.tsx index ea79028c..55f849c7 100644 --- a/opennow-stable/src/renderer/src/components/StreamView.tsx +++ b/opennow-stable/src/renderer/src/components/StreamView.tsx @@ -11,6 +11,7 @@ import { getStoreDisplayName, getStoreIconComponent } from "./GameCard"; import { RemainingPlaytimeIndicator, SessionElapsedIndicator } from "./ElapsedSessionIndicators"; import type { MicrophoneMode, ScreenshotEntry, RecordingEntry, SubscriptionInfo } from "@shared/gfn"; import { isShortcutMatch, normalizeShortcut } from "../shortcuts"; +import { openNow, platformCapabilities } from "../platform"; interface StreamViewProps { videoRef: React.Ref; @@ -679,10 +680,10 @@ export function StreamView({ const [screenshotShortcutError, setScreenshotShortcutError] = useState(null); const [activeSidebarTab, setActiveSidebarTab] = useState<"preferences" | "shortcuts">("preferences"); const screenshotApiAvailable = - typeof window.openNow?.saveScreenshot === "function" && - typeof window.openNow?.listScreenshots === "function" && - typeof window.openNow?.deleteScreenshot === "function" && - typeof window.openNow?.saveScreenshotAs === "function"; + typeof openNow?.saveScreenshot === "function" && + typeof openNow?.listScreenshots === "function" && + typeof openNow?.deleteScreenshot === "function" && + typeof openNow?.saveScreenshotAs === "function"; // Recording state const [isRecording, setIsRecording] = useState(false); @@ -699,12 +700,12 @@ export function StreamView({ const thumbnailDataUrlRef = useRef(null); const recCarouselRef = useRef(null); const recordingApiAvailable = - typeof window.openNow?.beginRecording === "function" && - typeof window.openNow?.sendRecordingChunk === "function" && - typeof window.openNow?.finishRecording === "function" && - typeof window.openNow?.abortRecording === "function" && - typeof window.openNow?.listRecordings === "function" && - typeof window.openNow?.deleteRecording === "function"; + typeof openNow?.beginRecording === "function" && + typeof openNow?.sendRecordingChunk === "function" && + typeof openNow?.finishRecording === "function" && + typeof openNow?.abortRecording === "function" && + typeof openNow?.listRecordings === "function" && + typeof openNow?.deleteRecording === "function"; const microphoneModes = useMemo( () => [ @@ -899,7 +900,7 @@ export function StreamView({ return; } try { - const items = await window.openNow.listScreenshots(); + const items = await openNow.listScreenshots(); setScreenshots(items); } catch (error) { console.error("[StreamView] Failed to load screenshots:", error); @@ -935,7 +936,7 @@ export function StreamView({ context.drawImage(video, 0, 0, canvas.width, canvas.height); const dataUrl = canvas.toDataURL("image/png"); - const saved = await window.openNow.saveScreenshot({ dataUrl, gameTitle }); + const saved = await openNow.saveScreenshot({ dataUrl, gameTitle }); setScreenshots((prev) => [saved, ...prev.filter((item) => item.id !== saved.id)].slice(0, 60)); } catch (error) { console.error("[StreamView] Failed to capture screenshot:", error); @@ -961,7 +962,7 @@ export function StreamView({ if (!selectedScreenshot) return; try { - await window.openNow.deleteScreenshot({ id: selectedScreenshot.id }); + await openNow.deleteScreenshot({ id: selectedScreenshot.id }); setScreenshots((prev) => prev.filter((item) => item.id !== selectedScreenshot.id)); setSelectedScreenshotId(null); } catch (error) { @@ -979,7 +980,7 @@ export function StreamView({ if (!selectedScreenshot) return; try { - await window.openNow.saveScreenshotAs({ id: selectedScreenshot.id }); + await openNow.saveScreenshotAs({ id: selectedScreenshot.id }); } catch (error) { console.error("[StreamView] Failed to save screenshot as:", error); setGalleryError("Unable to save screenshot."); @@ -990,7 +991,7 @@ export function StreamView({ setRecordingError(null); if (!recordingApiAvailable) return; try { - const items = await window.openNow.listRecordings(); + const items = await openNow.listRecordings(); setRecordings(items); } catch (error) { console.error("[StreamView] Failed to load recordings:", error); @@ -1002,7 +1003,7 @@ export function StreamView({ setRecordingError(null); if (!recordingApiAvailable) return; try { - await window.openNow.deleteRecording({ id }); + await openNow.deleteRecording({ id }); setRecordings((prev) => prev.filter((r) => r.id !== id)); } catch (error) { console.error("[StreamView] Failed to delete recording:", error); @@ -1073,7 +1074,7 @@ export function StreamView({ let recordingId: string; try { - const result = await window.openNow.beginRecording({ mimeType }); + const result = await openNow.beginRecording({ mimeType }); recordingId = result.recordingId; } catch (error) { console.error("[StreamView] Failed to begin recording:", error); @@ -1136,7 +1137,7 @@ export function StreamView({ void e.data.arrayBuffer().then((buf) => { const id = recordingIdRef.current; if (!id) return; - window.openNow.sendRecordingChunk({ recordingId: id, chunk: buf }).catch((err: unknown) => { + openNow.sendRecordingChunk({ recordingId: id, chunk: buf }).catch((err: unknown) => { console.error("[StreamView] Failed to send recording chunk:", err); }); }); @@ -1154,7 +1155,7 @@ export function StreamView({ if (!id) return; const durationMs = Date.now() - recordingStartTimeRef.current; - void window.openNow + void openNow .finishRecording({ recordingId: id, durationMs, @@ -1181,7 +1182,7 @@ export function StreamView({ setIsRecording(false); thumbnailDataUrlRef.current = null; if (id) { - window.openNow.abortRecording({ recordingId: id }).catch(() => undefined); + openNow.abortRecording({ recordingId: id }).catch(() => undefined); } setRecordingError("Recording encountered an error."); }; @@ -1200,7 +1201,7 @@ export function StreamView({ recorder.stop(); } if (id) { - window.openNow.abortRecording({ recordingId: id }).catch(() => undefined); + openNow.abortRecording({ recordingId: id }).catch(() => undefined); recordingIdRef.current = null; } audioCtxRef.current?.close().catch(() => undefined); @@ -1598,10 +1599,10 @@ export function StreamView({ className="sidebar-rec-card-action" aria-label="Show in folder" title="Show in folder" - onClick={() => { void window.openNow.showRecordingInFolder(rec.id); }} - disabled={typeof window.openNow?.showRecordingInFolder !== "function"} + onClick={() => { void openNow.showRecordingInFolder(rec.id); }} + disabled={!platformCapabilities.supportsMediaFolderAccess} > - + {platformCapabilities.supportsMediaFolderAccess ? : } + )} - + {platformCapabilities.supportsLogExport && ( +
+ + +
+ )} -
- - -
+ {platformCapabilities.supportsCacheDeletion && ( +
+ + +
+ )} )} diff --git a/opennow-stable/src/renderer/src/gfn/webrtcClient.ts b/opennow-stable/src/renderer/src/gfn/webrtcClient.ts index db67c9cc..fddd4275 100644 --- a/opennow-stable/src/renderer/src/gfn/webrtcClient.ts +++ b/opennow-stable/src/renderer/src/gfn/webrtcClient.ts @@ -2005,6 +2005,23 @@ export class GfnWebRtcClient { }; } + private bindControlChannel(channel: RTCDataChannel, connectionLabel = "Peer connection"): void { + this.controlChannel = channel; + this.controlChannel.binaryType = "arraybuffer"; + this.controlChannel.onmessage = (msgEvent) => { + void this.onControlChannelMessage(msgEvent.data as string | Blob | ArrayBuffer); + }; + this.controlChannel.onclose = () => { + this.log(`${connectionLabel} control channel closed`); + if (this.controlChannel === channel) { + this.controlChannel = null; + } + }; + this.controlChannel.onerror = () => { + this.log(`${connectionLabel} control channel error`); + }; + } + private mapTimerNotificationCode(rawCode: number): StreamTimeWarning["code"] | null { // Mirrors official client behavior from timerNotification -> StreamWarningType. if (rawCode === 1 || rawCode === 2) { @@ -3430,21 +3447,7 @@ export class GfnWebRtcClient { if (channel.label !== "control_channel") { return; } - - this.controlChannel = channel; - this.controlChannel.binaryType = "arraybuffer"; - this.controlChannel.onmessage = (msgEvent) => { - void this.onControlChannelMessage(msgEvent.data as string | Blob | ArrayBuffer); - }; - this.controlChannel.onclose = () => { - this.log("Control channel closed"); - if (this.controlChannel === channel) { - this.controlChannel = null; - } - }; - this.controlChannel.onerror = () => { - this.log("Control channel error"); - }; + this.bindControlChannel(channel); }; pc.onicecandidateerror = (event: Event) => { @@ -3749,6 +3752,15 @@ export class GfnWebRtcClient { this.configureReceiverForLowLatency(evt.receiver, evt.track.kind); }; + relayPc.ondatachannel = (event) => { + const channel = event.channel; + this.log(`Relay PC remote data channel received: label=${channel.label}, ordered=${channel.ordered}`); + if (channel.label !== "control_channel") { + return; + } + this.bindControlChannel(channel, "Relay PC"); + }; + relayPc.onconnectionstatechange = () => { this.diagnostics.connectionState = relayPc.connectionState; this.emitStats(); @@ -3811,7 +3823,7 @@ export class GfnWebRtcClient { const proto = cand.includes("udp") ? "udp" : "tcp"; for (const mid of mids) { try { - await relayPc.addIceCandidate({ candidate: cand, sdpMid: mid, sdpMLineIndex: parseInt(mid, 10), usernameFragment: relayCredentials.ufrag || undefined }); + await relayPc.addIceCandidate({ candidate: cand, sdpMid: mid, sdpMLineIndex: parseInt(mid, 10), usernameFragment: serverIceUfrag || undefined }); this.log(`Relay PC manual ICE candidate injected (sdpMid=${mid}, proto=${proto})`); injectedRelay = true; break; diff --git a/opennow-stable/src/renderer/src/platform/android/api.ts b/opennow-stable/src/renderer/src/platform/android/api.ts index 8f23436a..8af92fc8 100644 --- a/opennow-stable/src/renderer/src/platform/android/api.ts +++ b/opennow-stable/src/renderer/src/platform/android/api.ts @@ -76,7 +76,6 @@ import { TOKEN_REFRESH_WINDOW_MS, USERINFO_ENDPOINT, defaultProvider, - gravatarUrl, isExpired, isNearExpiry, normalizeProvider, @@ -156,7 +155,7 @@ async function refreshAuthTokens(refreshToken: string): Promise { co async function requestClientToken(accessToken: string): Promise<{ token: string; expiresAt: number; lifetimeMs: number }> { const payload = await httpRequest(CLIENT_TOKEN_ENDPOINT, { headers: { Authorization: `Bearer ${accessToken}`, Origin: "https://nvfile", Accept: "application/json, text/plain, */*", "User-Agent": GFN_USER_AGENT } }); const expiresAt = toExpiresAt(payload.expires_in); return { token: payload.client_token, expiresAt, lifetimeMs: Math.max(0, expiresAt - Date.now()) }; } async function refreshWithClientToken(clientToken: string, userId: string): Promise { const body = new URLSearchParams({ grant_type: "urn:ietf:params:oauth:grant-type:client_token", client_token: clientToken, client_id: CLIENT_ID, sub: userId }); return httpRequest(TOKEN_ENDPOINT, { method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8", Origin: "https://nvfile", Accept: "application/json, text/plain, */*", "User-Agent": GFN_USER_AGENT }, data: body.toString() }); } function mergeTokenSnapshot(base: AuthTokens, refreshed: TokenResponse): AuthTokens { return { accessToken: refreshed.access_token, refreshToken: refreshed.refresh_token ?? base.refreshToken, idToken: refreshed.id_token, expiresAt: toExpiresAt(refreshed.expires_in), clientToken: refreshed.client_token ?? base.clientToken, clientTokenExpiresAt: base.clientTokenExpiresAt, clientTokenLifetimeMs: base.clientTokenLifetimeMs }; } -async function fetchUserInfo(tokens: AuthTokens): Promise { const jwtUser = userFromJwt(tokens); if (jwtUser?.email || jwtUser?.avatarUrl) return jwtUser; const payload = await httpRequest<{ sub: string; preferred_username?: string; email?: string; picture?: string }>(USERINFO_ENDPOINT, { headers: { Authorization: `Bearer ${tokens.accessToken}`, Origin: "https://nvfile", Accept: "application/json", "User-Agent": GFN_USER_AGENT } }); return { userId: payload.sub, displayName: payload.preferred_username ?? payload.email?.split("@")[0] ?? "User", email: payload.email, avatarUrl: payload.picture ?? (payload.email ? gravatarUrl(payload.email) : undefined), membershipTier: jwtUser?.membershipTier ?? "FREE" }; } +async function fetchUserInfo(tokens: AuthTokens): Promise { const jwtUser = userFromJwt(tokens); if (jwtUser?.email || jwtUser?.avatarUrl) return jwtUser; const payload = await httpRequest<{ sub: string; preferred_username?: string; email?: string; picture?: string }>(USERINFO_ENDPOINT, { headers: { Authorization: `Bearer ${tokens.accessToken}`, Origin: "https://nvfile", Accept: "application/json", "User-Agent": GFN_USER_AGENT } }); return { userId: payload.sub, displayName: payload.preferred_username ?? payload.email?.split("@")[0] ?? "User", email: payload.email, avatarUrl: payload.picture, membershipTier: jwtUser?.membershipTier ?? "FREE" }; } const AUTH_REDIRECT_PORTS = [2259, 6460, 7119, 8870, 9096] as const; @@ -580,26 +579,29 @@ async function pollSessionRequest(input: SessionPollRequest): Promise { const token = await authStore.resolveJwtToken(input.token); const clientId = input.clientId ?? crypto.randomUUID(); const deviceId = input.deviceId ?? (await Device.getId()).identifier ?? crypto.randomUUID(); const base = input.serverIp ? `https://${input.serverIp}` : resolveStreamingBaseUrl(input.zone, input.streamingBaseUrl); await httpRequest(`${base}/v2/session/${input.sessionId}`, { method: "DELETE", headers: requestHeaders({ token, clientId, deviceId }), responseType: "text" }); } async function reportSessionAdRequest(input: SessionAdReportRequest): Promise { const token = await authStore.resolveJwtToken(input.token); const clientId = input.clientId ?? crypto.randomUUID(); const deviceId = input.deviceId ?? (await Device.getId()).identifier ?? crypto.randomUUID(); const base = input.serverIp ? `https://${input.serverIp}` : resolveStreamingBaseUrl(input.zone, input.streamingBaseUrl); const response = await httpRequest(`${base}/v2/session/${input.sessionId}/ad`, { method: "PUT", headers: requestHeaders({ token, clientId, deviceId }), data: { adId: input.adId, action: ({ start: 1, pause: 2, resume: 3, finish: 4, cancel: 5 } as const)[input.action], clientTimestamp: input.clientTimestamp, watchedTimeInMs: input.watchedTimeInMs, pausedTimeInMs: input.pausedTimeInMs, cancelReason: input.cancelReason, errorInfo: input.errorInfo } }); return toSessionInfo(input.zone, base, response, clientId, deviceId); } async function getActiveSessionsRequest(token: string, streamingBaseUrl?: string): Promise { const base = resolveStreamingBaseUrl("", streamingBaseUrl || authStore.getSelectedProvider().streamingServiceUrl); const response = await httpRequest(`${base}/v2/sessions`, { headers: { Authorization: `GFNJWT ${token}`, Accept: "application/json, text/plain, */*", "User-Agent": GFN_USER_AGENT, "nv-client-id": LCARS_CLIENT_ID, "nv-client-streamer": "NVIDIA-CLASSIC", "nv-client-type": "NATIVE", "nv-client-version": GFN_CLIENT_VERSION, "nv-device-os": "ANDROID", "nv-device-type": "PHONE" } }); return (response.sessions ?? []).filter((session) => session.status === 2 || session.status === 3).map((session) => ({ sessionId: session.sessionId, appId: session.appId, gpuType: session.gpuType, status: session.status, serverIp: Array.isArray(session.sessionControlInfo?.ip) ? session.sessionControlInfo?.ip[0] : session.sessionControlInfo?.ip, signalingUrl: session.connectionInfo?.find((entry) => entry.usage === 14)?.resourcePath, resolution: session.resolution, fps: session.fps })); } -async function claimSessionRequest(input: SessionClaimRequest): Promise { const token = await authStore.resolveJwtToken(input.token); const clientId = crypto.randomUUID(); const deviceId = (await Device.getId()).identifier || crypto.randomUUID(); const base = `https://${input.serverIp}`; const claimUrl = `${base}/v2/session/${input.sessionId}?${new URLSearchParams({ keyboardLayout: resolveGfnKeyboardLayout(input.settings?.keyboardLayout ?? DEFAULT_KEYBOARD_LAYOUT, "linux"), languageCode: input.settings?.gameLanguage ?? "en_US" }).toString()}`; await httpRequest(claimUrl, { method: "PUT", headers: requestHeaders({ token, clientId, deviceId }), data: { sessionRequestData: { appId: input.appId ?? "0", requestedStreamingFeatures: { reflex: (input.settings?.fps ?? 60) >= 120, bitDepth: colorQualityBitDepth(input.settings?.colorQuality ?? "8bit_420"), enabledL4S: input.settings?.enableL4S ?? false, chromaFormat: colorQualityChromaFormat(input.settings?.colorQuality ?? "8bit_420") } } } }).catch(() => undefined); for (let attempt = 0; attempt < 60; attempt += 1) { if (attempt > 0) await new Promise((resolve) => window.setTimeout(resolve, 1000)); try { const polled = await httpRequest(`${base}/v2/session/${input.sessionId}`, { headers: requestHeaders({ token, clientId, deviceId, includeOrigin: false }) }); if (polled.session.status === 2 || polled.session.status === 3) return toSessionInfo("", base, polled, clientId, deviceId); } catch {} } throw new Error("Session did not become ready after claiming"); } +async function claimSessionRequest(input: SessionClaimRequest): Promise { const token = await authStore.resolveJwtToken(input.token); const clientId = crypto.randomUUID(); const deviceId = (await Device.getId()).identifier || crypto.randomUUID(); const base = `https://${input.serverIp}`; const claimUrl = `${base}/v2/session/${input.sessionId}?${new URLSearchParams({ keyboardLayout: resolveGfnKeyboardLayout(input.settings?.keyboardLayout ?? DEFAULT_KEYBOARD_LAYOUT, "linux"), languageCode: input.settings?.gameLanguage ?? "en_US" }).toString()}`; await httpRequest(claimUrl, { method: "PUT", headers: requestHeaders({ token, clientId, deviceId }), data: { sessionRequestData: { appId: input.appId ?? "0", requestedStreamingFeatures: { reflex: (input.settings?.fps ?? 60) >= 120, bitDepth: colorQualityBitDepth(input.settings?.colorQuality ?? "8bit_420"), enabledL4S: input.settings?.enableL4S ?? false, chromaFormat: colorQualityChromaFormat(input.settings?.colorQuality ?? "8bit_420") } } } }); for (let attempt = 0; attempt < 60; attempt += 1) { if (attempt > 0) await new Promise((resolve) => window.setTimeout(resolve, 1000)); try { const polled = await httpRequest(`${base}/v2/session/${input.sessionId}`, { headers: requestHeaders({ token, clientId, deviceId, includeOrigin: false }) }); if (polled.session.status === 2 || polled.session.status === 3) return toSessionInfo("", base, polled, clientId, deviceId); } catch {} } throw new Error("Session did not become ready after claiming"); } async function fetchSubscriptionInfo(input: SubscriptionFetchRequest): Promise { const token = await authStore.resolveJwtToken(input.token); const vpcId = await getVpcId(token, input.providerStreamingBaseUrl); const userId = input.userId || authStore.getSession()?.user.userId; if (!userId) throw new Error("No authenticated user available for subscription lookup"); const url = new URL(MES_URL); url.searchParams.append("serviceName", "gfn_pc"); url.searchParams.append("languageCode", "en_US"); url.searchParams.append("vpcId", vpcId); url.searchParams.append("userId", userId); const data = await httpRequest(url.toString(), { headers: { Authorization: `GFNJWT ${token}`, Accept: "application/json", "nv-client-id": LCARS_CLIENT_ID, "nv-client-type": "NATIVE", "nv-client-version": GFN_CLIENT_VERSION, "nv-client-streamer": "NVIDIA-CLASSIC", "nv-device-os": "ANDROID", "nv-device-type": "PHONE" } }); const allottedMinutes = data.allottedTimeInMinutes ?? 0; const purchasedMinutes = data.purchasedTimeInMinutes ?? 0; const rolledOverMinutes = data.rolledOverTimeInMinutes ?? 0; const totalMinutes = data.totalTimeInMinutes ?? allottedMinutes + purchasedMinutes + rolledOverMinutes; const remainingMinutes = data.remainingTimeInMinutes ?? 0; const usedMinutes = Math.max(totalMinutes - remainingMinutes, 0); const storageAddon = data.addons?.find((addon) => addon.type === "STORAGE" && addon.subType === "PERMANENT_STORAGE" && addon.status === "OK"); const attr = (key: string) => storageAddon?.attributes?.find((entry) => entry.key === key)?.textValue; return { membershipTier: data.membershipTier ?? "FREE", subscriptionType: data.type, subscriptionSubType: data.subType, allottedHours: allottedMinutes / 60, purchasedHours: purchasedMinutes / 60, rolledOverHours: rolledOverMinutes / 60, usedHours: usedMinutes / 60, remainingHours: remainingMinutes / 60, totalHours: totalMinutes / 60, firstEntitlementStartDateTime: data.firstEntitlementStartDateTime, serverRegionId: vpcId, currentSpanStartDateTime: data.currentSpanStartDateTime, currentSpanEndDateTime: data.currentSpanEndDateTime, notifyUserWhenTimeRemainingInMinutes: data.notifications?.notifyUserWhenTimeRemainingInMinutes, notifyUserOnSessionWhenRemainingTimeInMinutes: data.notifications?.notifyUserOnSessionWhenRemainingTimeInMinutes, state: data.currentSubscriptionState?.state, isGamePlayAllowed: data.currentSubscriptionState?.isGamePlayAllowed, isUnlimited: data.subType === "UNLIMITED", storageAddon: storageAddon ? { type: "PERMANENT_STORAGE", sizeGb: attr("TOTAL_STORAGE_SIZE_IN_GB") ? Number(attr("TOTAL_STORAGE_SIZE_IN_GB")) : undefined, usedGb: attr("USED_STORAGE_SIZE_IN_GB") ? Number(attr("USED_STORAGE_SIZE_IN_GB")) : undefined, regionName: attr("STORAGE_METRO_REGION_NAME"), regionCode: attr("STORAGE_METRO_REGION") } : undefined, entitledResolutions: (data.features?.resolutions ?? []).map((res) => ({ width: res.widthInPixels, height: res.heightInPixels, fps: res.framesPerSecond })) }; } function unsupported(message: string): Promise { return Promise.reject(new Error(message)); } function dataUrlExtension(dataUrl: string): string { if (dataUrl.startsWith("data:image/jpeg")) return "jpg"; if (dataUrl.startsWith("data:image/webp")) return "webp"; return "png"; } function decodeDataUrl(dataUrl: string): string { const match = /^data:[^;]+;base64,(.+)$/i.exec(dataUrl); if (!match || !match[1]) throw new Error("Invalid data URL"); return match[1]; } function encodeBase64(bytes: Uint8Array): string { let binary = ""; const chunkSize = 0x8000; for (let index = 0; index < bytes.length; index += chunkSize) { binary += String.fromCharCode(...bytes.subarray(index, index + chunkSize)); } return btoa(binary); } -function concatBytes(chunks: Uint8Array[]): Uint8Array { const totalLength = chunks.reduce((sum, chunk) => sum + chunk.byteLength, 0); const merged = new Uint8Array(totalLength); let offset = 0; for (const chunk of chunks) { merged.set(chunk, offset); offset += chunk.byteLength; } return merged; } async function ensureDirectory(path: string): Promise { await Filesystem.mkdir({ path, directory: Directory.Data, recursive: true }).catch(() => undefined); } async function listDirectory(path: string): Promise> { try { const result = await Filesystem.readdir({ path, directory: Directory.Data }); return result.files.map((file) => ({ name: file.name })); } catch { return []; } } type RecordingMeta = RecordingEntry; +interface RecordingDraft { id: string; fileName: string; filePath: string; pendingWrite: Promise; } const RECORDING_META_KEY = RECORDINGS_KEY; const THANKS_CACHE_KEY = "opennow.android.thanks.v1"; async function readRecordingMeta(): Promise { return readPreferenceJson(RECORDING_META_KEY, []); } async function writeRecordingMeta(entries: RecordingMeta[]): Promise { await writePreferenceJson(RECORDING_META_KEY, entries); } async function readDataUrl(path: string, mimeType: string): Promise { const file = await Filesystem.readFile({ path, directory: Directory.Data }); return `data:${mimeType};base64,${typeof file.data === "string" ? file.data : ""}`; } +function recordingExtension(mimeType: string): "mp4" | "webm" { return mimeType.includes("mp4") ? "mp4" : "webm"; } +async function createRecordingDraft(recordingId: string, mimeType: string): Promise { await ensureDirectory(RECORDING_DIR); const fileName = `${Date.now()}-${recordingId}.${recordingExtension(mimeType)}`; const filePath = `${RECORDING_DIR}/${fileName}`; await Filesystem.writeFile({ path: filePath, directory: Directory.Data, data: "", recursive: true }); return { id: recordingId, fileName, filePath, pendingWrite: Promise.resolve() }; } +function enqueueRecordingWrite(state: RecordingDraft, chunk: ArrayBuffer): Promise { state.pendingWrite = state.pendingWrite.then(async () => { await Filesystem.appendFile({ path: state.filePath, directory: Directory.Data, data: encodeBase64(new Uint8Array(chunk.slice(0))) }); }); return state.pendingWrite; } +async function cleanupRecordingDraft(state: RecordingDraft): Promise { await state.pendingWrite.catch(() => undefined); await Filesystem.deleteFile({ path: state.filePath, directory: Directory.Data }).catch(() => undefined); } const signalingListeners = new Set<(event: MainToRendererSignalingEvent) => void>(); let signalingClient: BrowserSignalingClient | null = null; -const recordingBuffers = new Map(); -const recordingMime = new Map(); +const recordingStates = new Map(); const api: OpenNowApi = { getAuthSession: async (input: AuthSessionRequest = {}) => { await ensureInitialized(); return authStore.ensureValidSessionWithStatus(Boolean(input.forceRefresh)); }, @@ -647,10 +649,10 @@ const api: OpenNowApi = { deleteScreenshot: async (input: ScreenshotDeleteRequest) => { await Filesystem.deleteFile({ path: `${SCREENSHOT_DIR}/${input.id}`, directory: Directory.Data }).catch(() => undefined); }, saveScreenshotAs: async (_input: ScreenshotSaveAsRequest): Promise => unsupported("Screenshot export is not supported on Android.") as Promise, onTriggerScreenshot: () => () => undefined, - beginRecording: async (input: RecordingBeginRequest): Promise => { const recordingId = crypto.randomUUID(); recordingBuffers.set(recordingId, []); recordingMime.set(recordingId, input.mimeType); return { recordingId }; }, - sendRecordingChunk: async (input: RecordingChunkRequest) => { const list = recordingBuffers.get(input.recordingId); if (!list) return; list.push(new Uint8Array(input.chunk.slice(0))); }, - finishRecording: async (input: RecordingFinishRequest): Promise => { await ensureDirectory(RECORDING_DIR); const ext = (recordingMime.get(input.recordingId) ?? "video/webm").includes("mp4") ? "mp4" : "webm"; const fileName = `${Date.now()}-${input.recordingId}.${ext}`; const filePath = `${RECORDING_DIR}/${fileName}`; const mergedBytes = concatBytes(recordingBuffers.get(input.recordingId) ?? []); await Filesystem.writeFile({ path: filePath, directory: Directory.Data, data: encodeBase64(mergedBytes), recursive: true }); const stat = await Filesystem.stat({ path: filePath, directory: Directory.Data }); const entry: RecordingMeta = { id: input.recordingId, fileName, filePath, createdAtMs: Number(stat.ctime ?? Date.now()), sizeBytes: stat.size, durationMs: input.durationMs, gameTitle: input.gameTitle, thumbnailDataUrl: input.thumbnailDataUrl }; const entries = await readRecordingMeta(); await writeRecordingMeta([entry, ...entries.filter((item) => item.id !== entry.id)]); recordingBuffers.delete(input.recordingId); recordingMime.delete(input.recordingId); return entry; }, - abortRecording: async (input: RecordingAbortRequest) => { recordingBuffers.delete(input.recordingId); recordingMime.delete(input.recordingId); }, + beginRecording: async (input: RecordingBeginRequest): Promise => { const recordingId = crypto.randomUUID(); recordingStates.set(recordingId, await createRecordingDraft(recordingId, input.mimeType)); return { recordingId }; }, + sendRecordingChunk: async (input: RecordingChunkRequest) => { const state = recordingStates.get(input.recordingId); if (!state) return; await enqueueRecordingWrite(state, input.chunk); }, + finishRecording: async (input: RecordingFinishRequest): Promise => { const state = recordingStates.get(input.recordingId); if (!state) throw new Error("Recording session not found."); try { await state.pendingWrite; const stat = await Filesystem.stat({ path: state.filePath, directory: Directory.Data }); const entry: RecordingMeta = { id: input.recordingId, fileName: state.fileName, filePath: state.filePath, createdAtMs: Number(stat.ctime ?? Date.now()), sizeBytes: stat.size, durationMs: input.durationMs, gameTitle: input.gameTitle, thumbnailDataUrl: input.thumbnailDataUrl }; const entries = await readRecordingMeta(); await writeRecordingMeta([entry, ...entries.filter((item) => item.id !== entry.id)]); return entry; } catch (error) { await cleanupRecordingDraft(state); throw error; } finally { recordingStates.delete(input.recordingId); } }, + abortRecording: async (input: RecordingAbortRequest) => { const state = recordingStates.get(input.recordingId); recordingStates.delete(input.recordingId); if (!state) return; await cleanupRecordingDraft(state); }, listRecordings: async (): Promise => { const entries = await readRecordingMeta(); return entries.sort((a, b) => b.createdAtMs - a.createdAtMs); }, deleteRecording: async (input: RecordingDeleteRequest) => { const entries = await readRecordingMeta(); const match = entries.find((entry) => entry.id === input.id); if (match) await Filesystem.deleteFile({ path: match.filePath, directory: Directory.Data }).catch(() => undefined); await writeRecordingMeta(entries.filter((entry) => entry.id !== input.id)); }, showRecordingInFolder: async () => unsupported("Folder access is not supported on Android."), diff --git a/opennow-stable/src/renderer/src/platform/android/storage.ts b/opennow-stable/src/renderer/src/platform/android/storage.ts index 3c8d8b4e..b2a388b7 100644 --- a/opennow-stable/src/renderer/src/platform/android/storage.ts +++ b/opennow-stable/src/renderer/src/platform/android/storage.ts @@ -3,6 +3,10 @@ import { Preferences } from "@capacitor/preferences"; const BASE_DIR = "opennow"; +function normalizePath(path: string): string { + return path.startsWith(`${BASE_DIR}/`) ? path : `${BASE_DIR}/${path}`; +} + export async function getPreferenceJson(key: string, fallback: T): Promise { const { value } = await Preferences.get({ key }); if (!value) return fallback; @@ -30,33 +34,33 @@ export async function ensureDir(path: string): Promise { } export async function writeFile(path: string, data: string): Promise { - const normalized = path.startsWith(`${BASE_DIR}/`) ? path : `${BASE_DIR}/${path}`; + const normalized = normalizePath(path); const parent = normalized.split("/").slice(0, -1).join("/"); if (parent) await ensureDir(parent); - await Filesystem.writeFile({ path: normalized, data, directory: Directory.Data }); + await Filesystem.writeFile({ path: normalized, data, directory: Directory.Data, encoding: Encoding.UTF8 }); } export async function appendFile(path: string, data: string): Promise { - const normalized = path.startsWith(`${BASE_DIR}/`) ? path : `${BASE_DIR}/${path}`; + const normalized = normalizePath(path); const parent = normalized.split("/").slice(0, -1).join("/"); if (parent) await ensureDir(parent); - await Filesystem.appendFile({ path: normalized, data, directory: Directory.Data }); + await Filesystem.appendFile({ path: normalized, data, directory: Directory.Data, encoding: Encoding.UTF8 }); } export async function readFile(path: string): Promise { - const normalized = path.startsWith(`${BASE_DIR}/`) ? path : `${BASE_DIR}/${path}`; + const normalized = normalizePath(path); const result = await Filesystem.readFile({ path: normalized, directory: Directory.Data, encoding: Encoding.UTF8 }); return typeof result.data === "string" ? result.data : ""; } export async function readFileBase64(path: string): Promise { - const normalized = path.startsWith(`${BASE_DIR}/`) ? path : `${BASE_DIR}/${path}`; + const normalized = normalizePath(path); const result = await Filesystem.readFile({ path: normalized, directory: Directory.Data }); return typeof result.data === "string" ? result.data : ""; } export async function deleteFile(path: string): Promise { - const normalized = path.startsWith(`${BASE_DIR}/`) ? path : `${BASE_DIR}/${path}`; + const normalized = normalizePath(path); try { await Filesystem.deleteFile({ path: normalized, directory: Directory.Data }); } catch { @@ -65,7 +69,7 @@ export async function deleteFile(path: string): Promise { } export async function readDir(path: string): Promise { - const normalized = path.startsWith(`${BASE_DIR}/`) ? path : `${BASE_DIR}/${path}`; + const normalized = normalizePath(path); try { const result = await Filesystem.readdir({ path: normalized, directory: Directory.Data }); return result.files.map((file) => file.name); @@ -76,7 +80,16 @@ export async function readDir(path: string): Promise { export async function clearDirectory(path: string): Promise { const names = await readDir(path); - await Promise.all(names.map((name) => deleteFile(`${path}/${name}`))); + await Promise.all(names.map(async (name) => { + const childPath = `${path}/${name}`; + try { + await Filesystem.deleteFile({ path: normalizePath(childPath), directory: Directory.Data }); + return; + } catch { + await clearDirectory(childPath); + await Filesystem.rmdir({ path: normalizePath(childPath), directory: Directory.Data }).catch(() => undefined); + } + })); } export function toBase64DataUrl(mimeType: string, data: string): string { diff --git a/opennow-stable/src/shared/gfnRuntime.ts b/opennow-stable/src/shared/gfnRuntime.ts index 5a8a697f..89c5965f 100644 --- a/opennow-stable/src/shared/gfnRuntime.ts +++ b/opennow-stable/src/shared/gfnRuntime.ts @@ -74,10 +74,6 @@ export function generatePkce(): { verifier: string; challenge: string } { throw new Error("Use a runtime-specific PKCE helper"); } -export function gravatarUrl(email: string, size = 80): string { - return `https://ui-avatars.com/api/?name=${encodeURIComponent(email.trim())}&size=${size}&background=1f2937&color=ffffff`; -} - export function userFromJwt(tokens: AuthTokens): AuthUser | null { const jwtToken = tokens.idToken ?? tokens.accessToken; const parsed = parseJwtPayload<{ @@ -88,12 +84,11 @@ export function userFromJwt(tokens: AuthTokens): AuthUser | null { picture?: string; }>(jwtToken); if (!parsed?.sub) return null; - const avatar = parsed.picture ?? (parsed.email ? gravatarUrl(parsed.email) : undefined); return { userId: parsed.sub, displayName: parsed.preferred_username ?? parsed.email?.split("@")[0] ?? "User", email: parsed.email, - avatarUrl: avatar, + avatarUrl: parsed.picture, membershipTier: parsed.gfn_tier ?? "FREE", }; } From e6946d376e0c8dfe82d01d449109ed4f200b54e9 Mon Sep 17 00:00:00 2001 From: zortos293 <65777760+zortos293@users.noreply.github.com> Date: Fri, 17 Apr 2026 21:12:50 +0000 Subject: [PATCH 18/66] Fix Android session parity follow-ups --- opennow-stable/src/renderer/src/App.tsx | 4 + .../src/renderer/src/platform/android/api.ts | 12 ++- .../src/renderer/src/platform/android/http.ts | 3 + .../renderer/src/platform/android/storage.ts | 87 ++++++++++++++++--- 4 files changed, 88 insertions(+), 18 deletions(-) diff --git a/opennow-stable/src/renderer/src/App.tsx b/opennow-stable/src/renderer/src/App.tsx index 3df8d4f9..85cde9cd 100644 --- a/opennow-stable/src/renderer/src/App.tsx +++ b/opennow-stable/src/renderer/src/App.tsx @@ -3269,6 +3269,10 @@ export function App(): JSX.Element { return; } + if (!platformCapabilities.supportsKeyboardShortcuts) { + return; + } + if (isShortcutMatch(e, shortcuts.toggleStats)) { e.preventDefault(); e.stopPropagation(); diff --git a/opennow-stable/src/renderer/src/platform/android/api.ts b/opennow-stable/src/renderer/src/platform/android/api.ts index 8af92fc8..762f27fe 100644 --- a/opennow-stable/src/renderer/src/platform/android/api.ts +++ b/opennow-stable/src/renderer/src/platform/android/api.ts @@ -51,6 +51,7 @@ import type { SessionStopRequest, Settings, SignalingConnectRequest, + StreamSettings, StreamRegion, SubscriptionFetchRequest, SubscriptionInfo, @@ -129,7 +130,7 @@ interface GraphQlResponse { data?: { panels?: Array<{ sections?: Array<{ items?: interface AppData { id: string; title: string; description?: string; longDescription?: string; features?: unknown[]; gameFeatures?: unknown[]; appFeatures?: unknown[]; genres?: unknown[]; tags?: unknown[]; images?: { GAME_BOX_ART?: string; TV_BANNER?: string; HERO_IMAGE?: string }; variants?: Array<{ id: string; appStore: string; supportedControls?: string[]; gfn?: { library?: { selected?: boolean } } }>; gfn?: { playType?: string; minimumMembershipTierLabel?: string }; } interface SubscriptionResponse { firstEntitlementStartDateTime?: string; type?: string; membershipTier?: string; allottedTimeInMinutes?: number; purchasedTimeInMinutes?: number; rolledOverTimeInMinutes?: number; remainingTimeInMinutes?: number; totalTimeInMinutes?: number; notifications?: { notifyUserWhenTimeRemainingInMinutes?: number; notifyUserOnSessionWhenRemainingTimeInMinutes?: number }; currentSpanStartDateTime?: string; currentSpanEndDateTime?: string; currentSubscriptionState?: { state?: string; isGamePlayAllowed?: boolean }; subType?: string; addons?: Array<{ type?: string; subType?: string; status?: string; attributes?: Array<{ key?: string; textValue?: string }> }>; features?: { resolutions?: Array<{ heightInPixels: number; widthInPixels: number; framesPerSecond: number }> }; } interface RawPublicGame { id?: string | number; title?: string; steamUrl?: string; status?: string; } -interface CloudMatchResponse { requestStatus: { statusCode: number; statusName?: string; statusDescription?: string }; session: { sessionId: string; status: number; queuePosition?: number; seatSetupInfo?: { queuePosition?: number; seatSetupStep?: number }; sessionProgress?: { queuePosition?: number; isAdsRequired?: boolean }; progressInfo?: { queuePosition?: number; isAdsRequired?: boolean }; sessionAdsRequired?: boolean; isAdsRequired?: boolean; connectionInfo?: Array<{ usage?: number; ip?: string | string[]; port?: number; resourcePath?: string }>; sessionControlInfo?: { ip?: string | string[] }; gpuType?: string; iceServerConfiguration?: { iceServers?: Array<{ urls: string[] | string; username?: string; credential?: string }> }; sessionRequestData?: { clientRequestMonitorSettings?: Array<{ widthInPixels: number; heightInPixels: number; framesPerSecond: number }>; requestedStreamingFeatures?: { bitDepth?: number; chromaFormat?: number; enabledL4S?: boolean } }; finalizedStreamingFeatures?: { bitDepth?: number; chromaFormat?: number; enabledL4S?: boolean } }; sessions?: Array<{ sessionId: string; appId: number; gpuType?: string; status: number; sessionControlInfo?: { ip?: string | string[] }; connectionInfo?: Array<{ usage?: number; ip?: string | string[]; resourcePath?: string }>; resolution?: string; fps?: number }>; } +interface CloudMatchResponse { requestStatus: { statusCode: number; statusName?: string; statusDescription?: string }; session: { sessionId: string; status: number; queuePosition?: number; seatSetupInfo?: { queuePosition?: number; seatSetupStep?: number }; sessionProgress?: { queuePosition?: number; isAdsRequired?: boolean }; progressInfo?: { queuePosition?: number; isAdsRequired?: boolean }; sessionAdsRequired?: boolean; isAdsRequired?: boolean; connectionInfo?: Array<{ usage?: number; ip?: string | string[]; port?: number; resourcePath?: string }>; sessionControlInfo?: { ip?: string | string[] }; gpuType?: string; errorCode?: number; iceServerConfiguration?: { iceServers?: Array<{ urls: string[] | string; username?: string; credential?: string }> }; sessionRequestData?: { clientRequestMonitorSettings?: Array<{ widthInPixels: number; heightInPixels: number; framesPerSecond: number }>; requestedStreamingFeatures?: { bitDepth?: number; chromaFormat?: number; enabledL4S?: boolean } }; finalizedStreamingFeatures?: { bitDepth?: number; chromaFormat?: number; enabledL4S?: boolean } }; sessions?: Array<{ sessionId: string; appId?: number; gpuType?: string; status: number; sessionControlInfo?: { ip?: string | string[] }; connectionInfo?: Array<{ usage?: number; ip?: string | string[]; resourcePath?: string }>; resolution?: string; fps?: number; monitorSettings?: Array<{ widthInPixels?: number; heightInPixels?: number; framesPerSecond?: number }>; sessionRequestData?: { appId?: number | string } }>; } function ensureTrailingSlash(value: string): string { return value.endsWith("/") ? value : `${value}/`; } function normalizeBaseUrl(value: string): string { return ensureTrailingSlash(value.trim()); } @@ -146,7 +147,7 @@ function appToGame(app: AppData): GameInfo { const variants = app.variants?.map( function mergeAppMetaIntoGame(game: GameInfo, app: AppData): GameInfo { const variants = app.variants?.map((variant) => ({ id: variant.id, store: variant.appStore, supportedControls: variant.supportedControls ?? [] })) ?? game.variants; const selectedVariantId = game.id.split(":")[1]; const selectedVariantIndex = Math.max(0, variants.findIndex((variant) => variant.id === selectedVariantId)); const imageUrl = app.images?.GAME_BOX_ART ?? app.images?.TV_BANNER ?? app.images?.HERO_IMAGE ?? undefined; return { ...game, title: app.title || game.title, description: app.description ?? game.description, longDescription: app.longDescription ?? game.longDescription, featureLabels: extractFeatureLabels(app), genres: extractGenres(app), imageUrl: imageUrl ? optimizeImage(imageUrl) : game.imageUrl, playType: app.gfn?.playType ?? game.playType, membershipTierLabel: app.gfn?.minimumMembershipTierLabel ?? game.membershipTierLabel, selectedVariantIndex, variants }; } async function readPreferenceJson(key: string, fallback: T): Promise { const { value } = await Preferences.get({ key }); if (!value) return fallback; try { return JSON.parse(value) as T; } catch { return fallback; } } async function writePreferenceJson(key: string, value: T): Promise { await Preferences.set({ key, value: JSON.stringify(value) }); } -async function httpRequest(url: string, options: { method?: string; headers?: Record; data?: unknown; responseType?: "json" | "text" } = {}): Promise { const response = await CapacitorHttp.request({ url, method: options.method ?? "GET", headers: options.headers, data: options.data, responseType: options.responseType ?? "json", readTimeout: 120000, connectTimeout: 30000 }); if (response.status < 200 || response.status >= 300) { const body = typeof response.data === "string" ? response.data : JSON.stringify(response.data); throw new Error(`HTTP ${response.status}: ${body.slice(0, 500)}`); } return response.data as T; } +async function httpRequest(url: string, options: { method?: string; headers?: Record; data?: unknown; responseType?: "json" | "text" } = {}): Promise { const responseType = options.responseType ?? "json"; const response = await CapacitorHttp.request({ url, method: options.method ?? "GET", headers: options.headers, data: options.data, responseType, readTimeout: 120000, connectTimeout: 30000 }); if (response.status < 200 || response.status >= 300) { const body = typeof response.data === "string" ? response.data : JSON.stringify(response.data); throw new Error(`HTTP ${response.status}: ${body.slice(0, 500)}`); } if (responseType === "text") return (typeof response.data === "string" ? response.data : JSON.stringify(response.data)) as T; if (typeof response.data === "string") { if (response.data.trim().length === 0) return undefined as T; return JSON.parse(response.data) as T; } return response.data as T; } function authRedirectUri(port: number): string { return `http://localhost:${port}`; } async function createPkce(): Promise<{ verifier: string; challenge: string }> { const bytes = new Uint8Array(64); crypto.getRandomValues(bytes); let binary = ""; for (const value of bytes) binary += String.fromCharCode(value); const verifier = btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/g, "").slice(0, 86); const challengeBuffer = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(verifier)); let challengeBinary = ""; for (const value of new Uint8Array(challengeBuffer)) challengeBinary += String.fromCharCode(value); const challenge = btoa(challengeBinary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/g, ""); return { verifier, challenge }; } function buildAuthUrl(provider: LoginProvider, challenge: string, deviceId: string, port: number): string { const nonce = `${Math.random().toString(16).slice(2)}${Math.random().toString(16).slice(2)}`; const params = new URLSearchParams({ response_type: "code", device_id: deviceId, scope: SCOPES, client_id: CLIENT_ID, redirect_uri: authRedirectUri(port), ui_locales: "en_US", nonce, prompt: "select_account", code_challenge: challenge, code_challenge_method: "S256", idp_id: provider.idpId }); return `${AUTH_ENDPOINT}?${params.toString()}`; } @@ -549,6 +550,8 @@ function resolveStreamingBaseUrl(zone: string, provided?: string): string { if ( function parseResolution(input: string): { width: number; height: number } { const [rawWidth, rawHeight] = input.split("x"); const width = Number.parseInt(rawWidth ?? "", 10); const height = Number.parseInt(rawHeight ?? "", 10); if (!Number.isFinite(width) || !Number.isFinite(height) || width <= 0 || height <= 0) return { width: 1920, height: 1080 }; return { width, height }; } function timezoneOffsetMs(): number { return -new Date().getTimezoneOffset() * 60 * 1000; } function extractHostFromUrl(url: string): string | null { for (const prefix of ["rtsps://", "rtsp://", "wss://", "https://"]) { if (url.startsWith(prefix)) { const host = url.slice(prefix.length).split(":")[0]?.split("/")[0]; return host || null; } } return null; } +function isZoneHostname(ip: string): boolean { return ip.includes("cloudmatchbeta.nvidiagrid.net") || ip.includes("cloudmatch.nvidiagrid.net"); } +function resolveActiveSessionSignalingUrl(connection: { ip?: string | string[]; resourcePath?: string } | undefined, serverIp?: string): string | undefined { const resourcePath = connection?.resourcePath; if (typeof resourcePath === "string") { if (resourcePath.startsWith("wss://")) return resourcePath; if (resourcePath.startsWith("rtsps://") || resourcePath.startsWith("rtsp://")) { const host = extractHostFromUrl(resourcePath) ?? serverIp; return host ? `wss://${host}/nvst/` : undefined; } if (resourcePath.startsWith("/") && serverIp) return `wss://${serverIp}${resourcePath}`; } return serverIp ? `wss://${serverIp}:443/nvst/` : undefined; } function streamingServerIp(response: CloudMatchResponse): string | null { const connection = response.session.connectionInfo?.find((conn) => conn.usage === 14); const directIp = Array.isArray(connection?.ip) ? connection?.ip[0] : connection?.ip; if (directIp) return directIp; if (connection?.resourcePath) { const host = extractHostFromUrl(connection.resourcePath); if (host) return host; } const controlIp = response.session.sessionControlInfo?.ip; return Array.isArray(controlIp) ? controlIp[0] ?? null : controlIp ?? null; } function resolveSignaling(response: CloudMatchResponse): { serverIp: string; signalingServer: string; signalingUrl: string; mediaConnectionInfo?: { ip: string; port: number } } { const connection = response.session.connectionInfo?.find((conn) => conn.usage === 14 && conn.ip) ?? response.session.connectionInfo?.find((conn) => conn.ip); const serverIp = streamingServerIp(response); if (!serverIp) throw new Error("CloudMatch response did not include a signaling host"); const resourcePath = connection?.resourcePath ?? "/nvst/"; let signalingUrl = `wss://${serverIp}/nvst/`; if (resourcePath.startsWith("wss://")) signalingUrl = resourcePath; else if (resourcePath.startsWith("rtsps://") || resourcePath.startsWith("rtsp://")) signalingUrl = `wss://${extractHostFromUrl(resourcePath) ?? serverIp}/nvst/`; else if (resourcePath.startsWith("/")) signalingUrl = `wss://${serverIp}${resourcePath}`; const connectionIp = Array.isArray(connection?.ip) ? connection?.ip[0] : connection?.ip; return { serverIp, signalingServer: connectionIp ?? extractHostFromUrl(signalingUrl) ?? serverIp, signalingUrl, mediaConnectionInfo: connection?.port && connectionIp ? { ip: connectionIp, port: connection.port } : undefined }; } function extractQueuePosition(payload: CloudMatchResponse): number | undefined { return toPositiveInt(payload.session.queuePosition) ?? toPositiveInt(payload.session.seatSetupInfo?.queuePosition) ?? toPositiveInt(payload.session.sessionProgress?.queuePosition) ?? toPositiveInt(payload.session.progressInfo?.queuePosition); } @@ -573,13 +576,14 @@ function extractNegotiatedStreamProfile(payload: CloudMatchResponse): SessionInf async function toSessionInfo(zone: string, streamingBaseUrl: string, payload: CloudMatchResponse, clientId?: string, deviceId?: string): Promise { if (payload.requestStatus.statusCode !== 1) throw new Error(payload.requestStatus.statusDescription ?? payload.requestStatus.statusName ?? "Session request failed"); const signaling = resolveSignaling(payload); return { sessionId: payload.session.sessionId, status: payload.session.status, queuePosition: extractQueuePosition(payload), seatSetupStep: payload.session.seatSetupInfo?.seatSetupStep, adState: extractAdState(payload), zone, streamingBaseUrl, serverIp: signaling.serverIp, signalingServer: signaling.signalingServer, signalingUrl: signaling.signalingUrl, gpuType: payload.session.gpuType, iceServers: normalizeIceServers(payload), mediaConnectionInfo: signaling.mediaConnectionInfo, negotiatedStreamProfile: extractNegotiatedStreamProfile(payload), clientId, deviceId }; } async function buildDeviceIdentifiers(): Promise<{ clientId: string; deviceId: string; deviceMake: string; deviceModel: string }> { const [{ identifier }, info] = await Promise.all([Device.getId(), Device.getInfo()]); return { clientId: crypto.randomUUID(), deviceId: identifier || crypto.randomUUID(), deviceMake: info.manufacturer || "UNKNOWN", deviceModel: info.model || "UNKNOWN" }; } function buildSessionRequestBody(input: SessionCreateRequest) { const { width, height } = parseResolution(input.settings.resolution); const hdrEnabled = false; const accountLinked = input.accountLinked ?? true; return { sessionRequestData: { appId: input.appId, internalTitle: input.internalTitle || null, availableSupportedControllers: [], networkTestSessionId: null, parentSessionId: null, clientIdentification: "GFN-PC", deviceHashId: crypto.randomUUID(), clientVersion: "30.0", sdkVersion: "1.0", streamerVersion: 1, clientPlatformName: "windows", clientRequestMonitorSettings: [{ widthInPixels: width, heightInPixels: height, framesPerSecond: input.settings.fps, sdrHdrMode: hdrEnabled ? 1 : 0, displayData: { desiredContentMaxLuminance: hdrEnabled ? 1000 : 0, desiredContentMinLuminance: 0, desiredContentMaxFrameAverageLuminance: hdrEnabled ? 500 : 0 }, dpi: 100 }], useOps: true, audioMode: 2, metaData: [{ key: "SubSessionId", value: crypto.randomUUID() }, { key: "wssignaling", value: "1" }, { key: "GSStreamerType", value: "WebRTC" }, { key: "networkType", value: "Unknown" }, { key: "ClientImeSupport", value: "0" }, { key: "clientPhysicalResolution", value: JSON.stringify({ horizontalPixels: width, verticalPixels: height }) }, { key: "surroundAudioInfo", value: "2" }], sdrHdrMode: hdrEnabled ? 1 : 0, clientDisplayHdrCapabilities: hdrEnabled ? { version: 1, hdrEdrSupportedFlagsInUint32: 1, staticMetadataDescriptorId: 0 } : null, surroundAudioInfo: 0, remoteControllersBitmap: 0, clientTimezoneOffset: timezoneOffsetMs(), enhancedStreamMode: 1, appLaunchMode: 1, secureRTSPSupported: false, partnerCustomData: "", accountLinked, enablePersistingInGameSettings: true, userAge: 26, requestedStreamingFeatures: { reflex: input.settings.fps >= 120, bitDepth: colorQualityBitDepth(input.settings.colorQuality), cloudGsync: false, enabledL4S: input.settings.enableL4S, mouseMovementFlags: 0, trueHdr: hdrEnabled, supportedHidDevices: 0, profile: 0, fallbackToLogicalResolution: false, hidDevices: null, chromaFormat: colorQualityChromaFormat(input.settings.colorQuality), prefilterMode: 0, prefilterSharpness: 0, prefilterNoiseReduction: 0, hudStreamingMode: 0, sdrColorSpace: 2, hdrColorSpace: hdrEnabled ? 4 : 0 } } }; } +function buildClaimRequestBody(sessionId: string, appId: string, settings: StreamSettings): unknown { const deviceId = crypto.randomUUID(); const subSessionId = crypto.randomUUID(); return { action: 2, data: "RESUME", sessionRequestData: { audioMode: 2, remoteControllersBitmap: 0, sdrHdrMode: 0, networkTestSessionId: null, availableSupportedControllers: [], clientVersion: "30.0", deviceHashId: deviceId, internalTitle: null, clientPlatformName: "windows", metaData: [{ key: "SubSessionId", value: subSessionId }, { key: "wssignaling", value: "1" }, { key: "GSStreamerType", value: "WebRTC" }, { key: "networkType", value: "Unknown" }, { key: "ClientImeSupport", value: "0" }], surroundAudioInfo: 0, clientTimezoneOffset: timezoneOffsetMs(), clientIdentification: "GFN-PC", parentSessionId: null, appId: Number.parseInt(appId, 10), streamerVersion: 1, appLaunchMode: 1, sdkVersion: "1.0", enhancedStreamMode: 1, useOps: true, clientDisplayHdrCapabilities: null, accountLinked: true, partnerCustomData: "", enablePersistingInGameSettings: true, secureRTSPSupported: false, userAge: 26, requestedStreamingFeatures: { reflex: false, bitDepth: 0, cloudGsync: false, profile: 0, fallbackToLogicalResolution: false, chromaFormat: 0, prefilterMode: 0, hudStreamingMode: 0, enabledL4S: settings.enableL4S } }, metaData: [] }; } async function createSessionRequest(input: SessionCreateRequest): Promise { const token = await authStore.resolveJwtToken(input.token); const { clientId, deviceId, deviceMake, deviceModel } = await buildDeviceIdentifiers(); const streamingBaseUrl = resolveStreamingBaseUrl(input.zone, input.streamingBaseUrl); const keyboardLayout = resolveGfnKeyboardLayout(input.settings.keyboardLayout ?? DEFAULT_KEYBOARD_LAYOUT, "linux"); const languageCode = input.settings.gameLanguage ?? "en_US"; const response = await httpRequest(`${streamingBaseUrl}/v2/session?${new URLSearchParams({ keyboardLayout, languageCode }).toString()}`, { method: "POST", headers: requestHeaders({ token, clientId, deviceId, deviceMake, deviceModel }), data: buildSessionRequestBody(input) }); return toSessionInfo(input.zone, streamingBaseUrl, response, clientId, deviceId); } async function pollSessionRequest(input: SessionPollRequest): Promise { const token = await authStore.resolveJwtToken(input.token); const clientId = input.clientId ?? crypto.randomUUID(); const deviceId = input.deviceId ?? (await Device.getId()).identifier ?? crypto.randomUUID(); const base = input.serverIp ? `https://${input.serverIp}` : resolveStreamingBaseUrl(input.zone, input.streamingBaseUrl); const response = await httpRequest(`${base}/v2/session/${input.sessionId}`, { headers: requestHeaders({ token, clientId, deviceId, includeOrigin: false }) }); return toSessionInfo(input.zone, base, response, clientId, deviceId); } async function stopSessionRequest(input: SessionStopRequest): Promise { const token = await authStore.resolveJwtToken(input.token); const clientId = input.clientId ?? crypto.randomUUID(); const deviceId = input.deviceId ?? (await Device.getId()).identifier ?? crypto.randomUUID(); const base = input.serverIp ? `https://${input.serverIp}` : resolveStreamingBaseUrl(input.zone, input.streamingBaseUrl); await httpRequest(`${base}/v2/session/${input.sessionId}`, { method: "DELETE", headers: requestHeaders({ token, clientId, deviceId }), responseType: "text" }); } async function reportSessionAdRequest(input: SessionAdReportRequest): Promise { const token = await authStore.resolveJwtToken(input.token); const clientId = input.clientId ?? crypto.randomUUID(); const deviceId = input.deviceId ?? (await Device.getId()).identifier ?? crypto.randomUUID(); const base = input.serverIp ? `https://${input.serverIp}` : resolveStreamingBaseUrl(input.zone, input.streamingBaseUrl); const response = await httpRequest(`${base}/v2/session/${input.sessionId}/ad`, { method: "PUT", headers: requestHeaders({ token, clientId, deviceId }), data: { adId: input.adId, action: ({ start: 1, pause: 2, resume: 3, finish: 4, cancel: 5 } as const)[input.action], clientTimestamp: input.clientTimestamp, watchedTimeInMs: input.watchedTimeInMs, pausedTimeInMs: input.pausedTimeInMs, cancelReason: input.cancelReason, errorInfo: input.errorInfo } }); return toSessionInfo(input.zone, base, response, clientId, deviceId); } -async function getActiveSessionsRequest(token: string, streamingBaseUrl?: string): Promise { const base = resolveStreamingBaseUrl("", streamingBaseUrl || authStore.getSelectedProvider().streamingServiceUrl); const response = await httpRequest(`${base}/v2/sessions`, { headers: { Authorization: `GFNJWT ${token}`, Accept: "application/json, text/plain, */*", "User-Agent": GFN_USER_AGENT, "nv-client-id": LCARS_CLIENT_ID, "nv-client-streamer": "NVIDIA-CLASSIC", "nv-client-type": "NATIVE", "nv-client-version": GFN_CLIENT_VERSION, "nv-device-os": "ANDROID", "nv-device-type": "PHONE" } }); return (response.sessions ?? []).filter((session) => session.status === 2 || session.status === 3).map((session) => ({ sessionId: session.sessionId, appId: session.appId, gpuType: session.gpuType, status: session.status, serverIp: Array.isArray(session.sessionControlInfo?.ip) ? session.sessionControlInfo?.ip[0] : session.sessionControlInfo?.ip, signalingUrl: session.connectionInfo?.find((entry) => entry.usage === 14)?.resourcePath, resolution: session.resolution, fps: session.fps })); } -async function claimSessionRequest(input: SessionClaimRequest): Promise { const token = await authStore.resolveJwtToken(input.token); const clientId = crypto.randomUUID(); const deviceId = (await Device.getId()).identifier || crypto.randomUUID(); const base = `https://${input.serverIp}`; const claimUrl = `${base}/v2/session/${input.sessionId}?${new URLSearchParams({ keyboardLayout: resolveGfnKeyboardLayout(input.settings?.keyboardLayout ?? DEFAULT_KEYBOARD_LAYOUT, "linux"), languageCode: input.settings?.gameLanguage ?? "en_US" }).toString()}`; await httpRequest(claimUrl, { method: "PUT", headers: requestHeaders({ token, clientId, deviceId }), data: { sessionRequestData: { appId: input.appId ?? "0", requestedStreamingFeatures: { reflex: (input.settings?.fps ?? 60) >= 120, bitDepth: colorQualityBitDepth(input.settings?.colorQuality ?? "8bit_420"), enabledL4S: input.settings?.enableL4S ?? false, chromaFormat: colorQualityChromaFormat(input.settings?.colorQuality ?? "8bit_420") } } } }); for (let attempt = 0; attempt < 60; attempt += 1) { if (attempt > 0) await new Promise((resolve) => window.setTimeout(resolve, 1000)); try { const polled = await httpRequest(`${base}/v2/session/${input.sessionId}`, { headers: requestHeaders({ token, clientId, deviceId, includeOrigin: false }) }); if (polled.session.status === 2 || polled.session.status === 3) return toSessionInfo("", base, polled, clientId, deviceId); } catch {} } throw new Error("Session did not become ready after claiming"); } +async function getActiveSessionsRequest(token: string, streamingBaseUrl?: string): Promise { const base = resolveStreamingBaseUrl("", streamingBaseUrl || authStore.getSelectedProvider().streamingServiceUrl); try { const response = await httpRequest(`${base}/v2/session`, { headers: requestHeaders({ token, clientId: LCARS_CLIENT_ID, deviceId: crypto.randomUUID(), includeOrigin: false }) }); if (response.requestStatus.statusCode !== 1) return []; return (response.sessions ?? []).filter((session) => session.status === 1 || session.status === 2 || session.status === 3).map((session) => { const connection = session.connectionInfo?.find((entry) => entry.usage === 14) ?? session.connectionInfo?.find((entry) => entry.ip || entry.resourcePath); const connIpRaw = connection?.ip; const connIp = Array.isArray(connIpRaw) ? connIpRaw[0] : connIpRaw; const controlIpRaw = session.sessionControlInfo?.ip; const controlIp = Array.isArray(controlIpRaw) ? controlIpRaw[0] : controlIpRaw; const serverIp = connIp ?? controlIp; const monitor = session.monitorSettings?.[0]; const rawAppId = session.sessionRequestData?.appId ?? session.appId; const appId = typeof rawAppId === "string" || typeof rawAppId === "number" ? Number(rawAppId) : 0; return { sessionId: session.sessionId, appId: Number.isFinite(appId) ? appId : 0, gpuType: session.gpuType, status: session.status, streamingBaseUrl: base, serverIp, signalingUrl: resolveActiveSessionSignalingUrl(connection, serverIp), resolution: session.resolution ?? (monitor?.widthInPixels && monitor?.heightInPixels ? `${monitor.widthInPixels}x${monitor.heightInPixels}` : undefined), fps: session.fps ?? monitor?.framesPerSecond }; }); } catch { return []; } } +async function claimSessionRequest(input: SessionClaimRequest): Promise { const token = await authStore.resolveJwtToken(input.token); const clientId = crypto.randomUUID(); const deviceId = (await Device.getId()).identifier || crypto.randomUUID(); const settings = input.settings ?? { resolution: "1920x1080", fps: 60, maxBitrateMbps: 75, codec: "H264", colorQuality: "8bit_420", keyboardLayout: DEFAULT_KEYBOARD_LAYOUT, gameLanguage: "en_US", enableL4S: false, enableCloudGsync: false }; const appId = input.appId ?? "0"; const keyboardLayout = resolveGfnKeyboardLayout(settings.keyboardLayout ?? DEFAULT_KEYBOARD_LAYOUT, "linux"); const languageCode = settings.gameLanguage ?? "en_US"; let effectiveServerIp = input.serverIp; if (isZoneHostname(effectiveServerIp)) { try { const zoneBase = `https://${effectiveServerIp}`; const prefetchPayload = await httpRequest(`${zoneBase}/v2/session/${input.sessionId}`, { headers: requestHeaders({ token, clientId, deviceId, includeOrigin: false }) }); const realIp = streamingServerIp(prefetchPayload); if (realIp) effectiveServerIp = realIp; } catch {} } const effectiveBase = `https://${effectiveServerIp}`; const sessionUrl = `${effectiveBase}/v2/session/${input.sessionId}`; let preClaimStatus: number | null = null; try { const preClaimPayload = await httpRequest(sessionUrl, { headers: requestHeaders({ token, clientId, deviceId, includeOrigin: false }) }); preClaimStatus = preClaimPayload.session?.status ?? null; } catch {} if (preClaimStatus !== 1) { const claimUrl = `${sessionUrl}?${new URLSearchParams({ keyboardLayout, languageCode }).toString()}`; await httpRequest(claimUrl, { method: "PUT", headers: requestHeaders({ token, clientId, deviceId }), data: buildClaimRequestBody(input.sessionId, appId, settings) }); } for (let attempt = 0; attempt < 60; attempt += 1) { if (attempt > 0) await new Promise((resolve) => window.setTimeout(resolve, 1000)); try { const polled = await httpRequest(sessionUrl, { headers: requestHeaders({ token, clientId, deviceId, includeOrigin: false }) }); if (polled.session.status === 2 || polled.session.status === 3) return toSessionInfo("", effectiveBase, polled, clientId, deviceId); if (polled.session.status > 3 && polled.session.status !== 6) break; } catch {} } throw new Error("Session did not become ready after claiming"); } async function fetchSubscriptionInfo(input: SubscriptionFetchRequest): Promise { const token = await authStore.resolveJwtToken(input.token); const vpcId = await getVpcId(token, input.providerStreamingBaseUrl); const userId = input.userId || authStore.getSession()?.user.userId; if (!userId) throw new Error("No authenticated user available for subscription lookup"); const url = new URL(MES_URL); url.searchParams.append("serviceName", "gfn_pc"); url.searchParams.append("languageCode", "en_US"); url.searchParams.append("vpcId", vpcId); url.searchParams.append("userId", userId); const data = await httpRequest(url.toString(), { headers: { Authorization: `GFNJWT ${token}`, Accept: "application/json", "nv-client-id": LCARS_CLIENT_ID, "nv-client-type": "NATIVE", "nv-client-version": GFN_CLIENT_VERSION, "nv-client-streamer": "NVIDIA-CLASSIC", "nv-device-os": "ANDROID", "nv-device-type": "PHONE" } }); const allottedMinutes = data.allottedTimeInMinutes ?? 0; const purchasedMinutes = data.purchasedTimeInMinutes ?? 0; const rolledOverMinutes = data.rolledOverTimeInMinutes ?? 0; const totalMinutes = data.totalTimeInMinutes ?? allottedMinutes + purchasedMinutes + rolledOverMinutes; const remainingMinutes = data.remainingTimeInMinutes ?? 0; const usedMinutes = Math.max(totalMinutes - remainingMinutes, 0); const storageAddon = data.addons?.find((addon) => addon.type === "STORAGE" && addon.subType === "PERMANENT_STORAGE" && addon.status === "OK"); const attr = (key: string) => storageAddon?.attributes?.find((entry) => entry.key === key)?.textValue; return { membershipTier: data.membershipTier ?? "FREE", subscriptionType: data.type, subscriptionSubType: data.subType, allottedHours: allottedMinutes / 60, purchasedHours: purchasedMinutes / 60, rolledOverHours: rolledOverMinutes / 60, usedHours: usedMinutes / 60, remainingHours: remainingMinutes / 60, totalHours: totalMinutes / 60, firstEntitlementStartDateTime: data.firstEntitlementStartDateTime, serverRegionId: vpcId, currentSpanStartDateTime: data.currentSpanStartDateTime, currentSpanEndDateTime: data.currentSpanEndDateTime, notifyUserWhenTimeRemainingInMinutes: data.notifications?.notifyUserWhenTimeRemainingInMinutes, notifyUserOnSessionWhenRemainingTimeInMinutes: data.notifications?.notifyUserOnSessionWhenRemainingTimeInMinutes, state: data.currentSubscriptionState?.state, isGamePlayAllowed: data.currentSubscriptionState?.isGamePlayAllowed, isUnlimited: data.subType === "UNLIMITED", storageAddon: storageAddon ? { type: "PERMANENT_STORAGE", sizeGb: attr("TOTAL_STORAGE_SIZE_IN_GB") ? Number(attr("TOTAL_STORAGE_SIZE_IN_GB")) : undefined, usedGb: attr("USED_STORAGE_SIZE_IN_GB") ? Number(attr("USED_STORAGE_SIZE_IN_GB")) : undefined, regionName: attr("STORAGE_METRO_REGION_NAME"), regionCode: attr("STORAGE_METRO_REGION") } : undefined, entitledResolutions: (data.features?.resolutions ?? []).map((res) => ({ width: res.widthInPixels, height: res.heightInPixels, fps: res.framesPerSecond })) }; } function unsupported(message: string): Promise { return Promise.reject(new Error(message)); } function dataUrlExtension(dataUrl: string): string { if (dataUrl.startsWith("data:image/jpeg")) return "jpg"; if (dataUrl.startsWith("data:image/webp")) return "webp"; return "png"; } diff --git a/opennow-stable/src/renderer/src/platform/android/http.ts b/opennow-stable/src/renderer/src/platform/android/http.ts index f5bb2f65..bda00c93 100644 --- a/opennow-stable/src/renderer/src/platform/android/http.ts +++ b/opennow-stable/src/renderer/src/platform/android/http.ts @@ -18,6 +18,9 @@ async function parseResponse(response: HttpResponse, responseType: "json" | " } if (typeof response.data === "string") { + if (response.data.trim().length === 0) { + return undefined as T; + } return JSON.parse(response.data) as T; } return response.data as T; diff --git a/opennow-stable/src/renderer/src/platform/android/storage.ts b/opennow-stable/src/renderer/src/platform/android/storage.ts index b2a388b7..5878d1aa 100644 --- a/opennow-stable/src/renderer/src/platform/android/storage.ts +++ b/opennow-stable/src/renderer/src/platform/android/storage.ts @@ -7,6 +7,28 @@ function normalizePath(path: string): string { return path.startsWith(`${BASE_DIR}/`) ? path : `${BASE_DIR}/${path}`; } +function filesystemErrorMessage(error: unknown): string { + if (error instanceof Error) { + return error.message; + } + return String(error); +} + +function isMissingFilesystemError(error: unknown): boolean { + const message = filesystemErrorMessage(error).toLowerCase(); + return message.includes("does not exist") + || message.includes("not found") + || message.includes("no such file") + || message.includes("no such directory") + || message.includes("file_notfound") + || message.includes("file does not exist"); +} + +function isAlreadyExistsFilesystemError(error: unknown): boolean { + const message = filesystemErrorMessage(error).toLowerCase(); + return message.includes("already exists") || message.includes("file exists"); +} + export async function getPreferenceJson(key: string, fallback: T): Promise { const { value } = await Preferences.get({ key }); if (!value) return fallback; @@ -28,8 +50,11 @@ export async function removePreference(key: string): Promise { export async function ensureDir(path: string): Promise { try { await Filesystem.mkdir({ path, directory: Directory.Data, recursive: true }); - } catch { - return; + } catch (error) { + if (isAlreadyExistsFilesystemError(error)) { + return; + } + throw error; } } @@ -63,8 +88,11 @@ export async function deleteFile(path: string): Promise { const normalized = normalizePath(path); try { await Filesystem.deleteFile({ path: normalized, directory: Directory.Data }); - } catch { - return; + } catch (error) { + if (isMissingFilesystemError(error)) { + return; + } + throw error; } } @@ -73,25 +101,56 @@ export async function readDir(path: string): Promise { try { const result = await Filesystem.readdir({ path: normalized, directory: Directory.Data }); return result.files.map((file) => file.name); - } catch { - return []; + } catch (error) { + if (isMissingFilesystemError(error)) { + return []; + } + throw error; } } -export async function clearDirectory(path: string): Promise { - const names = await readDir(path); - await Promise.all(names.map(async (name) => { - const childPath = `${path}/${name}`; +async function clearDirectoryNormalized(path: string): Promise { + const entries = await Filesystem.readdir({ path, directory: Directory.Data }).catch((error) => { + if (isMissingFilesystemError(error)) { + return null; + } + throw error; + }); + if (!entries) { + return; + } + + await Promise.all(entries.files.map(async (entry) => { + const childPath = `${path}/${entry.name}`; + if (entry.type === "directory") { + await clearDirectoryNormalized(childPath); + try { + await Filesystem.rmdir({ path: childPath, directory: Directory.Data }); + } catch (error) { + if (isMissingFilesystemError(error)) { + return; + } + throw error; + } + return; + } + try { - await Filesystem.deleteFile({ path: normalizePath(childPath), directory: Directory.Data }); + await Filesystem.deleteFile({ path: childPath, directory: Directory.Data }); return; - } catch { - await clearDirectory(childPath); - await Filesystem.rmdir({ path: normalizePath(childPath), directory: Directory.Data }).catch(() => undefined); + } catch (error) { + if (isMissingFilesystemError(error)) { + return; + } + throw error; } })); } +export async function clearDirectory(path: string): Promise { + await clearDirectoryNormalized(normalizePath(path)); +} + export function toBase64DataUrl(mimeType: string, data: string): string { return `data:${mimeType};base64,${data}`; } From 915c4ff01bd8ea013e3e4e1084b38ab13e8f2c0d Mon Sep 17 00:00:00 2001 From: zortos293 <65777760+zortos293@users.noreply.github.com> Date: Fri, 17 Apr 2026 21:30:11 +0000 Subject: [PATCH 19/66] Fix Android follow-up parity issues --- opennow-stable/android/app/build.gradle | 17 ++++- .../src/components/ControllerLibraryPage.tsx | 19 +++-- .../src/renderer/src/platform/android/api.ts | 27 +++---- .../src/platform/android/browserSignaling.ts | 76 +++++++++++++++---- .../src/renderer/src/platform/android/http.ts | 8 -- .../renderer/src/platform/android/storage.ts | 45 ++++++----- 6 files changed, 128 insertions(+), 64 deletions(-) diff --git a/opennow-stable/android/app/build.gradle b/opennow-stable/android/app/build.gradle index 4babcb64..3d24617a 100644 --- a/opennow-stable/android/app/build.gradle +++ b/opennow-stable/android/app/build.gradle @@ -1,5 +1,18 @@ apply plugin: 'com.android.application' +import groovy.json.JsonSlurper + +def packageJson = new JsonSlurper().parse(rootProject.file('../package.json')) +def packageVersionName = ((packageJson.version ?: '1.0.0') as String).trim() +def versionParts = packageVersionName.tokenize('.').collect { token -> + def numeric = (token =~ /(\d+)/) + numeric.find() ? Integer.parseInt(numeric.group(1)) : 0 +} +while (versionParts.size() < 3) { + versionParts << 0 +} +def packageVersionCode = (versionParts[0] * 10000) + (versionParts[1] * 100) + versionParts[2] + android { namespace = "com.opencloudgaming.opennow" compileSdk = rootProject.ext.compileSdkVersion @@ -7,8 +20,8 @@ android { applicationId "com.opencloudgaming.opennow" minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 1 - versionName "1.0" + versionCode packageVersionCode + versionName packageVersionName testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" aaptOptions { // Files and dirs to omit from the packaged assets dir, modified to accommodate modern web apps. diff --git a/opennow-stable/src/renderer/src/components/ControllerLibraryPage.tsx b/opennow-stable/src/renderer/src/components/ControllerLibraryPage.tsx index e14a6051..81870c20 100644 --- a/opennow-stable/src/renderer/src/components/ControllerLibraryPage.tsx +++ b/opennow-stable/src/renderer/src/components/ControllerLibraryPage.tsx @@ -763,6 +763,7 @@ export function ControllerLibraryPage({ playUiSound("confirm"); return; } + return; } playUiSound("confirm"); @@ -1386,14 +1387,16 @@ export function ControllerLibraryPage({ ) : ( <> -
- {controllerType === "ps" ? ( - - ) : ( - - )} - Open Folder -
+ {platformCapabilities.supportsMediaFolderAccess && ( +
+ {controllerType === "ps" ? ( + + ) : ( + + )} + Open Folder +
+ )}
{controllerType === "ps" ? ( diff --git a/opennow-stable/src/renderer/src/platform/android/api.ts b/opennow-stable/src/renderer/src/platform/android/api.ts index 762f27fe..e3748531 100644 --- a/opennow-stable/src/renderer/src/platform/android/api.ts +++ b/opennow-stable/src/renderer/src/platform/android/api.ts @@ -1,8 +1,7 @@ import { App as CapacitorApp } from "@capacitor/app"; -import { CapacitorHttp, registerPlugin } from "@capacitor/core"; +import { registerPlugin } from "@capacitor/core"; import { Device } from "@capacitor/device"; import { Directory, Filesystem } from "@capacitor/filesystem"; -import { Preferences } from "@capacitor/preferences"; import { StatusBar, Style } from "@capacitor/status-bar"; import type { @@ -86,6 +85,8 @@ import { import { DEFAULT_SETTINGS } from "@shared/settings"; import type { OpenNowPlatform } from "../types"; import { BrowserSignalingClient } from "./browserSignaling"; +import { nativeRequest } from "./http"; +import { clearDirectory, deleteFile, ensureDir, getPreferenceJson, readDir, readFileBase64, removePreference, setPreferenceJson } from "./storage"; const AUTH_STATE_KEY = "opennow.android.auth-state.v1"; const SETTINGS_KEY = "opennow.android.settings.v1"; @@ -145,9 +146,9 @@ function extractGenres(app: AppData): string[] { if (!Array.isArray(app.genres)) function optimizeImage(url: string): string { return url.includes("img.nvidiagrid.net") ? `${url};f=webp;w=272` : url; } function appToGame(app: AppData): GameInfo { const variants = app.variants?.map((variant) => ({ id: variant.id, store: variant.appStore, supportedControls: variant.supportedControls ?? [] })) ?? []; const selectedVariantIndex = app.variants?.findIndex((variant) => variant.gfn?.library?.selected === true) ?? 0; const safeIndex = Math.max(0, selectedVariantIndex); const selectedVariantId = variants[safeIndex]?.id; const fallbackNumericVariantId = variants.find((variant) => isNumericId(variant.id))?.id; const launchAppId = isNumericId(selectedVariantId) ? selectedVariantId : fallbackNumericVariantId ?? (isNumericId(app.id) ? app.id : undefined); const imageUrl = app.images?.GAME_BOX_ART ?? app.images?.TV_BANNER ?? app.images?.HERO_IMAGE ?? undefined; return { id: `${app.id}:${selectedVariantId ?? "default"}`, uuid: app.id, launchAppId, title: app.title, description: app.description, longDescription: app.longDescription, featureLabels: extractFeatureLabels(app), genres: extractGenres(app), imageUrl: imageUrl ? optimizeImage(imageUrl) : undefined, playType: app.gfn?.playType, membershipTierLabel: app.gfn?.minimumMembershipTierLabel, selectedVariantIndex: Math.max(0, selectedVariantIndex), variants }; } function mergeAppMetaIntoGame(game: GameInfo, app: AppData): GameInfo { const variants = app.variants?.map((variant) => ({ id: variant.id, store: variant.appStore, supportedControls: variant.supportedControls ?? [] })) ?? game.variants; const selectedVariantId = game.id.split(":")[1]; const selectedVariantIndex = Math.max(0, variants.findIndex((variant) => variant.id === selectedVariantId)); const imageUrl = app.images?.GAME_BOX_ART ?? app.images?.TV_BANNER ?? app.images?.HERO_IMAGE ?? undefined; return { ...game, title: app.title || game.title, description: app.description ?? game.description, longDescription: app.longDescription ?? game.longDescription, featureLabels: extractFeatureLabels(app), genres: extractGenres(app), imageUrl: imageUrl ? optimizeImage(imageUrl) : game.imageUrl, playType: app.gfn?.playType ?? game.playType, membershipTierLabel: app.gfn?.minimumMembershipTierLabel ?? game.membershipTierLabel, selectedVariantIndex, variants }; } -async function readPreferenceJson(key: string, fallback: T): Promise { const { value } = await Preferences.get({ key }); if (!value) return fallback; try { return JSON.parse(value) as T; } catch { return fallback; } } -async function writePreferenceJson(key: string, value: T): Promise { await Preferences.set({ key, value: JSON.stringify(value) }); } -async function httpRequest(url: string, options: { method?: string; headers?: Record; data?: unknown; responseType?: "json" | "text" } = {}): Promise { const responseType = options.responseType ?? "json"; const response = await CapacitorHttp.request({ url, method: options.method ?? "GET", headers: options.headers, data: options.data, responseType, readTimeout: 120000, connectTimeout: 30000 }); if (response.status < 200 || response.status >= 300) { const body = typeof response.data === "string" ? response.data : JSON.stringify(response.data); throw new Error(`HTTP ${response.status}: ${body.slice(0, 500)}`); } if (responseType === "text") return (typeof response.data === "string" ? response.data : JSON.stringify(response.data)) as T; if (typeof response.data === "string") { if (response.data.trim().length === 0) return undefined as T; return JSON.parse(response.data) as T; } return response.data as T; } +async function readPreferenceJson(key: string, fallback: T): Promise { return getPreferenceJson(key, fallback); } +async function writePreferenceJson(key: string, value: T): Promise { await setPreferenceJson(key, value); } +async function httpRequest(url: string, options: { method?: string; headers?: Record; data?: unknown; responseType?: "json" | "text" } = {}): Promise { return nativeRequest({ url, method: options.method ?? "GET", headers: options.headers, data: options.data, readTimeout: 120000, connectTimeout: 30000 }, options.responseType ?? "json"); } function authRedirectUri(port: number): string { return `http://localhost:${port}`; } async function createPkce(): Promise<{ verifier: string; challenge: string }> { const bytes = new Uint8Array(64); crypto.getRandomValues(bytes); let binary = ""; for (const value of bytes) binary += String.fromCharCode(value); const verifier = btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/g, "").slice(0, 86); const challengeBuffer = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(verifier)); let challengeBinary = ""; for (const value of new Uint8Array(challengeBuffer)) challengeBinary += String.fromCharCode(value); const challenge = btoa(challengeBinary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/g, ""); return { verifier, challenge }; } function buildAuthUrl(provider: LoginProvider, challenge: string, deviceId: string, port: number): string { const nonce = `${Math.random().toString(16).slice(2)}${Math.random().toString(16).slice(2)}`; const params = new URLSearchParams({ response_type: "code", device_id: deviceId, scope: SCOPES, client_id: CLIENT_ID, redirect_uri: authRedirectUri(port), ui_locales: "en_US", nonce, prompt: "select_account", code_challenge: challenge, code_challenge_method: "S256", idp_id: provider.idpId }); return `${AUTH_ENDPOINT}?${params.toString()}`; } @@ -576,7 +577,7 @@ function extractNegotiatedStreamProfile(payload: CloudMatchResponse): SessionInf async function toSessionInfo(zone: string, streamingBaseUrl: string, payload: CloudMatchResponse, clientId?: string, deviceId?: string): Promise { if (payload.requestStatus.statusCode !== 1) throw new Error(payload.requestStatus.statusDescription ?? payload.requestStatus.statusName ?? "Session request failed"); const signaling = resolveSignaling(payload); return { sessionId: payload.session.sessionId, status: payload.session.status, queuePosition: extractQueuePosition(payload), seatSetupStep: payload.session.seatSetupInfo?.seatSetupStep, adState: extractAdState(payload), zone, streamingBaseUrl, serverIp: signaling.serverIp, signalingServer: signaling.signalingServer, signalingUrl: signaling.signalingUrl, gpuType: payload.session.gpuType, iceServers: normalizeIceServers(payload), mediaConnectionInfo: signaling.mediaConnectionInfo, negotiatedStreamProfile: extractNegotiatedStreamProfile(payload), clientId, deviceId }; } async function buildDeviceIdentifiers(): Promise<{ clientId: string; deviceId: string; deviceMake: string; deviceModel: string }> { const [{ identifier }, info] = await Promise.all([Device.getId(), Device.getInfo()]); return { clientId: crypto.randomUUID(), deviceId: identifier || crypto.randomUUID(), deviceMake: info.manufacturer || "UNKNOWN", deviceModel: info.model || "UNKNOWN" }; } function buildSessionRequestBody(input: SessionCreateRequest) { const { width, height } = parseResolution(input.settings.resolution); const hdrEnabled = false; const accountLinked = input.accountLinked ?? true; return { sessionRequestData: { appId: input.appId, internalTitle: input.internalTitle || null, availableSupportedControllers: [], networkTestSessionId: null, parentSessionId: null, clientIdentification: "GFN-PC", deviceHashId: crypto.randomUUID(), clientVersion: "30.0", sdkVersion: "1.0", streamerVersion: 1, clientPlatformName: "windows", clientRequestMonitorSettings: [{ widthInPixels: width, heightInPixels: height, framesPerSecond: input.settings.fps, sdrHdrMode: hdrEnabled ? 1 : 0, displayData: { desiredContentMaxLuminance: hdrEnabled ? 1000 : 0, desiredContentMinLuminance: 0, desiredContentMaxFrameAverageLuminance: hdrEnabled ? 500 : 0 }, dpi: 100 }], useOps: true, audioMode: 2, metaData: [{ key: "SubSessionId", value: crypto.randomUUID() }, { key: "wssignaling", value: "1" }, { key: "GSStreamerType", value: "WebRTC" }, { key: "networkType", value: "Unknown" }, { key: "ClientImeSupport", value: "0" }, { key: "clientPhysicalResolution", value: JSON.stringify({ horizontalPixels: width, verticalPixels: height }) }, { key: "surroundAudioInfo", value: "2" }], sdrHdrMode: hdrEnabled ? 1 : 0, clientDisplayHdrCapabilities: hdrEnabled ? { version: 1, hdrEdrSupportedFlagsInUint32: 1, staticMetadataDescriptorId: 0 } : null, surroundAudioInfo: 0, remoteControllersBitmap: 0, clientTimezoneOffset: timezoneOffsetMs(), enhancedStreamMode: 1, appLaunchMode: 1, secureRTSPSupported: false, partnerCustomData: "", accountLinked, enablePersistingInGameSettings: true, userAge: 26, requestedStreamingFeatures: { reflex: input.settings.fps >= 120, bitDepth: colorQualityBitDepth(input.settings.colorQuality), cloudGsync: false, enabledL4S: input.settings.enableL4S, mouseMovementFlags: 0, trueHdr: hdrEnabled, supportedHidDevices: 0, profile: 0, fallbackToLogicalResolution: false, hidDevices: null, chromaFormat: colorQualityChromaFormat(input.settings.colorQuality), prefilterMode: 0, prefilterSharpness: 0, prefilterNoiseReduction: 0, hudStreamingMode: 0, sdrColorSpace: 2, hdrColorSpace: hdrEnabled ? 4 : 0 } } }; } -function buildClaimRequestBody(sessionId: string, appId: string, settings: StreamSettings): unknown { const deviceId = crypto.randomUUID(); const subSessionId = crypto.randomUUID(); return { action: 2, data: "RESUME", sessionRequestData: { audioMode: 2, remoteControllersBitmap: 0, sdrHdrMode: 0, networkTestSessionId: null, availableSupportedControllers: [], clientVersion: "30.0", deviceHashId: deviceId, internalTitle: null, clientPlatformName: "windows", metaData: [{ key: "SubSessionId", value: subSessionId }, { key: "wssignaling", value: "1" }, { key: "GSStreamerType", value: "WebRTC" }, { key: "networkType", value: "Unknown" }, { key: "ClientImeSupport", value: "0" }], surroundAudioInfo: 0, clientTimezoneOffset: timezoneOffsetMs(), clientIdentification: "GFN-PC", parentSessionId: null, appId: Number.parseInt(appId, 10), streamerVersion: 1, appLaunchMode: 1, sdkVersion: "1.0", enhancedStreamMode: 1, useOps: true, clientDisplayHdrCapabilities: null, accountLinked: true, partnerCustomData: "", enablePersistingInGameSettings: true, secureRTSPSupported: false, userAge: 26, requestedStreamingFeatures: { reflex: false, bitDepth: 0, cloudGsync: false, profile: 0, fallbackToLogicalResolution: false, chromaFormat: 0, prefilterMode: 0, hudStreamingMode: 0, enabledL4S: settings.enableL4S } }, metaData: [] }; } +function buildClaimRequestBody(sessionId: string, appId: string, _settings: StreamSettings): unknown { const deviceId = crypto.randomUUID(); const subSessionId = crypto.randomUUID(); return { action: 2, data: "RESUME", sessionRequestData: { audioMode: 2, remoteControllersBitmap: 0, sdrHdrMode: 0, networkTestSessionId: null, availableSupportedControllers: [], clientVersion: "30.0", deviceHashId: deviceId, internalTitle: null, clientPlatformName: "windows", metaData: [{ key: "SubSessionId", value: subSessionId }, { key: "wssignaling", value: "1" }, { key: "GSStreamerType", value: "WebRTC" }, { key: "networkType", value: "Unknown" }, { key: "ClientImeSupport", value: "0" }], surroundAudioInfo: 0, clientTimezoneOffset: timezoneOffsetMs(), clientIdentification: "GFN-PC", parentSessionId: null, appId: Number.parseInt(appId, 10), streamerVersion: 1, appLaunchMode: 1, sdkVersion: "1.0", enhancedStreamMode: 1, useOps: true, clientDisplayHdrCapabilities: null, accountLinked: true, partnerCustomData: "", enablePersistingInGameSettings: true, secureRTSPSupported: false, userAge: 26, requestedStreamingFeatures: { reflex: false, bitDepth: 0, cloudGsync: false, profile: 0, fallbackToLogicalResolution: false, chromaFormat: 0, prefilterMode: 0, hudStreamingMode: 0 } }, metaData: [] }; } async function createSessionRequest(input: SessionCreateRequest): Promise { const token = await authStore.resolveJwtToken(input.token); const { clientId, deviceId, deviceMake, deviceModel } = await buildDeviceIdentifiers(); const streamingBaseUrl = resolveStreamingBaseUrl(input.zone, input.streamingBaseUrl); const keyboardLayout = resolveGfnKeyboardLayout(input.settings.keyboardLayout ?? DEFAULT_KEYBOARD_LAYOUT, "linux"); const languageCode = input.settings.gameLanguage ?? "en_US"; const response = await httpRequest(`${streamingBaseUrl}/v2/session?${new URLSearchParams({ keyboardLayout, languageCode }).toString()}`, { method: "POST", headers: requestHeaders({ token, clientId, deviceId, deviceMake, deviceModel }), data: buildSessionRequestBody(input) }); return toSessionInfo(input.zone, streamingBaseUrl, response, clientId, deviceId); } async function pollSessionRequest(input: SessionPollRequest): Promise { const token = await authStore.resolveJwtToken(input.token); const clientId = input.clientId ?? crypto.randomUUID(); const deviceId = input.deviceId ?? (await Device.getId()).identifier ?? crypto.randomUUID(); const base = input.serverIp ? `https://${input.serverIp}` : resolveStreamingBaseUrl(input.zone, input.streamingBaseUrl); const response = await httpRequest(`${base}/v2/session/${input.sessionId}`, { headers: requestHeaders({ token, clientId, deviceId, includeOrigin: false }) }); return toSessionInfo(input.zone, base, response, clientId, deviceId); } @@ -589,19 +590,19 @@ function unsupported(message: string): Promise { return Promise.reject(ne function dataUrlExtension(dataUrl: string): string { if (dataUrl.startsWith("data:image/jpeg")) return "jpg"; if (dataUrl.startsWith("data:image/webp")) return "webp"; return "png"; } function decodeDataUrl(dataUrl: string): string { const match = /^data:[^;]+;base64,(.+)$/i.exec(dataUrl); if (!match || !match[1]) throw new Error("Invalid data URL"); return match[1]; } function encodeBase64(bytes: Uint8Array): string { let binary = ""; const chunkSize = 0x8000; for (let index = 0; index < bytes.length; index += chunkSize) { binary += String.fromCharCode(...bytes.subarray(index, index + chunkSize)); } return btoa(binary); } -async function ensureDirectory(path: string): Promise { await Filesystem.mkdir({ path, directory: Directory.Data, recursive: true }).catch(() => undefined); } -async function listDirectory(path: string): Promise> { try { const result = await Filesystem.readdir({ path, directory: Directory.Data }); return result.files.map((file) => ({ name: file.name })); } catch { return []; } } +async function ensureDirectory(path: string): Promise { await ensureDir(path, { relativeToBaseDir: false }); } +async function listDirectory(path: string): Promise> { return (await readDir(path, { relativeToBaseDir: false })).map((name) => ({ name })); } type RecordingMeta = RecordingEntry; interface RecordingDraft { id: string; fileName: string; filePath: string; pendingWrite: Promise; } const RECORDING_META_KEY = RECORDINGS_KEY; const THANKS_CACHE_KEY = "opennow.android.thanks.v1"; async function readRecordingMeta(): Promise { return readPreferenceJson(RECORDING_META_KEY, []); } async function writeRecordingMeta(entries: RecordingMeta[]): Promise { await writePreferenceJson(RECORDING_META_KEY, entries); } -async function readDataUrl(path: string, mimeType: string): Promise { const file = await Filesystem.readFile({ path, directory: Directory.Data }); return `data:${mimeType};base64,${typeof file.data === "string" ? file.data : ""}`; } +async function readDataUrl(path: string, mimeType: string): Promise { return `data:${mimeType};base64,${await readFileBase64(path, { relativeToBaseDir: false })}`; } function recordingExtension(mimeType: string): "mp4" | "webm" { return mimeType.includes("mp4") ? "mp4" : "webm"; } async function createRecordingDraft(recordingId: string, mimeType: string): Promise { await ensureDirectory(RECORDING_DIR); const fileName = `${Date.now()}-${recordingId}.${recordingExtension(mimeType)}`; const filePath = `${RECORDING_DIR}/${fileName}`; await Filesystem.writeFile({ path: filePath, directory: Directory.Data, data: "", recursive: true }); return { id: recordingId, fileName, filePath, pendingWrite: Promise.resolve() }; } function enqueueRecordingWrite(state: RecordingDraft, chunk: ArrayBuffer): Promise { state.pendingWrite = state.pendingWrite.then(async () => { await Filesystem.appendFile({ path: state.filePath, directory: Directory.Data, data: encodeBase64(new Uint8Array(chunk.slice(0))) }); }); return state.pendingWrite; } -async function cleanupRecordingDraft(state: RecordingDraft): Promise { await state.pendingWrite.catch(() => undefined); await Filesystem.deleteFile({ path: state.filePath, directory: Directory.Data }).catch(() => undefined); } +async function cleanupRecordingDraft(state: RecordingDraft): Promise { await state.pendingWrite.catch(() => undefined); await deleteFile(state.filePath, { relativeToBaseDir: false }); } const signalingListeners = new Set<(event: MainToRendererSignalingEvent) => void>(); let signalingClient: BrowserSignalingClient | null = null; @@ -650,7 +651,7 @@ const api: OpenNowApi = { pingRegions: async (regions: StreamRegion[]): Promise => Promise.all(regions.map(async (region) => { const startedAt = performance.now(); try { await httpRequest(region.url, { responseType: "text" }); return { url: region.url, pingMs: Math.round(performance.now() - startedAt) }; } catch (error) { return { url: region.url, pingMs: null, error: error instanceof Error ? error.message : String(error) }; } })), saveScreenshot: async (input: ScreenshotSaveRequest): Promise => { await ensureDirectory(SCREENSHOT_DIR); const fileName = `${Date.now()}-${Math.random().toString(16).slice(2)}.${dataUrlExtension(input.dataUrl)}`; const filePath = `${SCREENSHOT_DIR}/${fileName}`; await Filesystem.writeFile({ path: filePath, directory: Directory.Data, data: decodeDataUrl(input.dataUrl), recursive: true }); const stat = await Filesystem.stat({ path: filePath, directory: Directory.Data }); return { id: fileName, fileName, filePath, createdAtMs: Number(stat.ctime ?? Date.now()), sizeBytes: stat.size, dataUrl: input.dataUrl }; }, listScreenshots: async (): Promise => { const files = await listDirectory(SCREENSHOT_DIR); const entries = await Promise.all(files.map(async (file) => { const filePath = `${SCREENSHOT_DIR}/${file.name}`; const stat = await Filesystem.stat({ path: filePath, directory: Directory.Data }); const mime = file.name.endsWith(".jpg") ? "image/jpeg" : file.name.endsWith(".webp") ? "image/webp" : "image/png"; return { id: file.name, fileName: file.name, filePath, createdAtMs: Number(stat.ctime ?? Date.now()), sizeBytes: stat.size, dataUrl: await readDataUrl(filePath, mime) } satisfies ScreenshotEntry; })); return entries.sort((a, b) => b.createdAtMs - a.createdAtMs); }, - deleteScreenshot: async (input: ScreenshotDeleteRequest) => { await Filesystem.deleteFile({ path: `${SCREENSHOT_DIR}/${input.id}`, directory: Directory.Data }).catch(() => undefined); }, + deleteScreenshot: async (input: ScreenshotDeleteRequest) => { await deleteFile(`${SCREENSHOT_DIR}/${input.id}`, { relativeToBaseDir: false }); }, saveScreenshotAs: async (_input: ScreenshotSaveAsRequest): Promise => unsupported("Screenshot export is not supported on Android.") as Promise, onTriggerScreenshot: () => () => undefined, beginRecording: async (input: RecordingBeginRequest): Promise => { const recordingId = crypto.randomUUID(); recordingStates.set(recordingId, await createRecordingDraft(recordingId, input.mimeType)); return { recordingId }; }, @@ -658,12 +659,12 @@ const api: OpenNowApi = { finishRecording: async (input: RecordingFinishRequest): Promise => { const state = recordingStates.get(input.recordingId); if (!state) throw new Error("Recording session not found."); try { await state.pendingWrite; const stat = await Filesystem.stat({ path: state.filePath, directory: Directory.Data }); const entry: RecordingMeta = { id: input.recordingId, fileName: state.fileName, filePath: state.filePath, createdAtMs: Number(stat.ctime ?? Date.now()), sizeBytes: stat.size, durationMs: input.durationMs, gameTitle: input.gameTitle, thumbnailDataUrl: input.thumbnailDataUrl }; const entries = await readRecordingMeta(); await writeRecordingMeta([entry, ...entries.filter((item) => item.id !== entry.id)]); return entry; } catch (error) { await cleanupRecordingDraft(state); throw error; } finally { recordingStates.delete(input.recordingId); } }, abortRecording: async (input: RecordingAbortRequest) => { const state = recordingStates.get(input.recordingId); recordingStates.delete(input.recordingId); if (!state) return; await cleanupRecordingDraft(state); }, listRecordings: async (): Promise => { const entries = await readRecordingMeta(); return entries.sort((a, b) => b.createdAtMs - a.createdAtMs); }, - deleteRecording: async (input: RecordingDeleteRequest) => { const entries = await readRecordingMeta(); const match = entries.find((entry) => entry.id === input.id); if (match) await Filesystem.deleteFile({ path: match.filePath, directory: Directory.Data }).catch(() => undefined); await writeRecordingMeta(entries.filter((entry) => entry.id !== input.id)); }, + deleteRecording: async (input: RecordingDeleteRequest) => { const entries = await readRecordingMeta(); const match = entries.find((entry) => entry.id === input.id); if (match) await deleteFile(match.filePath, { relativeToBaseDir: false }); await writeRecordingMeta(entries.filter((entry) => entry.id !== input.id)); }, showRecordingInFolder: async () => unsupported("Folder access is not supported on Android."), listMediaByGame: async (input = {}): Promise => { const screenshots = await api.listScreenshots(); const recordings = await api.listRecordings(); const title = input.gameTitle?.trim().toLowerCase(); return { screenshots: title ? [] : screenshots.map((entry) => ({ ...entry })), videos: recordings.filter((entry) => !title || entry.gameTitle?.trim().toLowerCase() === title).map((entry) => ({ ...entry })) }; }, getMediaThumbnail: async (input: { filePath: string }) => { if (input.filePath.startsWith(SCREENSHOT_DIR)) return readDataUrl(input.filePath, "image/png"); const recordings = await readRecordingMeta(); return recordings.find((entry) => entry.filePath === input.filePath)?.thumbnailDataUrl ?? null; }, showMediaInFolder: async () => unsupported("Folder access is not supported on Android."), - deleteCache: async () => unsupported("Cache deletion is not supported on Android in this pass."), + deleteCache: async () => { await Promise.all([clearDirectory(SCREENSHOT_DIR, { relativeToBaseDir: false }), clearDirectory(RECORDING_DIR, { relativeToBaseDir: false }), writeRecordingMeta([]), removePreference(THANKS_CACHE_KEY)]); }, fetchPrintedWasteQueue: async (): Promise => fetchPrintedWasteQueueRequest(), fetchPrintedWasteServerMapping: async (): Promise => fetchPrintedWasteServerMappingRequest(), getThanksData: async (): Promise => { const cached = await readPreferenceJson(THANKS_CACHE_KEY, null); if (cached) return cached; const placeholder: ThankYouDataResult = { contributors: [], supporters: [], contributorsError: "Community data is unavailable on Android in this pass." }; await writePreferenceJson(THANKS_CACHE_KEY, placeholder); return placeholder; }, diff --git a/opennow-stable/src/renderer/src/platform/android/browserSignaling.ts b/opennow-stable/src/renderer/src/platform/android/browserSignaling.ts index 8f39aafd..5c6275cf 100644 --- a/opennow-stable/src/renderer/src/platform/android/browserSignaling.ts +++ b/opennow-stable/src/renderer/src/platform/android/browserSignaling.ts @@ -38,6 +38,13 @@ export class BrowserSignalingClient { private heartbeatTimer: number | null = null; private listeners = new Set<(event: MainToRendererSignalingEvent) => void>(); private generation = 0; + private pendingConnect: { + ws: WebSocket; + generation: number; + settled: boolean; + resolve: () => void; + reject: (error: Error) => void; + } | null = null; onEvent(listener: (event: MainToRendererSignalingEvent) => void): () => void { this.listeners.add(listener); @@ -53,6 +60,27 @@ export class BrowserSignalingClient { return this.ackCounter; } + private clearHeartbeat(): void { + if (this.heartbeatTimer !== null) { + window.clearInterval(this.heartbeatTimer); + this.heartbeatTimer = null; + } + } + + private settlePendingConnect(ws: WebSocket, generation: number, error?: Error): void { + const pending = this.pendingConnect; + if (!pending || pending.ws !== ws || pending.generation !== generation || pending.settled) { + return; + } + pending.settled = true; + this.pendingConnect = null; + if (error) { + pending.reject(error); + return; + } + pending.resolve(); + } + private buildSignInUrl(input: SignalingConnectRequest): string { const fallbackHost = input.signalingServer.includes(":") ? input.signalingServer @@ -69,6 +97,9 @@ export class BrowserSignalingClient { async connect(input: SignalingConnectRequest): Promise { if (this.ws?.readyState === WebSocket.OPEN) return; + if (this.ws || this.pendingConnect) { + this.disconnect("Signaling connect replaced"); + } const url = this.buildSignInUrl(input); const protocol = `x-nv-sessionid.${input.sessionId}`; const generation = ++this.generation; @@ -76,13 +107,14 @@ export class BrowserSignalingClient { await new Promise((resolve, reject) => { const ws = new WebSocket(url, protocol); this.ws = ws; + this.pendingConnect = { ws, generation, settled: false, resolve, reject }; const isCurrent = (): boolean => this.ws === ws && this.generation === generation; ws.onerror = () => { if (!isCurrent()) return; this.emit({ type: "error", message: "Signaling connect failed" }); - reject(new Error("Signaling connect failed")); + this.settlePendingConnect(ws, generation, new Error("Signaling connect failed")); }; ws.onopen = () => { @@ -102,9 +134,14 @@ export class BrowserSignalingClient { secWebSocketKey: randomKey(), }, }); - this.heartbeatTimer = window.setInterval(() => this.sendJson({ hb: 1 }), 5000); + this.clearHeartbeat(); + this.heartbeatTimer = window.setInterval(() => { + if (this.ws === ws && this.generation === generation) { + this.sendJson({ hb: 1 }); + } + }, 5000); this.emit({ type: "connected" }); - resolve(); + this.settlePendingConnect(ws, generation); }; ws.onmessage = (event) => { @@ -113,13 +150,17 @@ export class BrowserSignalingClient { }; ws.onclose = (event) => { - if (this.heartbeatTimer !== null) { - window.clearInterval(this.heartbeatTimer); - this.heartbeatTimer = null; + if (this.ws === ws) { + this.clearHeartbeat(); + this.ws = null; } - if (!isCurrent()) return; - this.ws = null; - this.emit({ type: "disconnected", reason: event.reason || "socket closed" }); + const reason = event.reason || "socket closed"; + if (isCurrent()) { + this.settlePendingConnect(ws, generation, new Error(reason)); + this.emit({ type: "disconnected", reason }); + return; + } + this.settlePendingConnect(ws, generation, new Error(reason)); }; }); } @@ -226,13 +267,20 @@ export class BrowserSignalingClient { }); } - disconnect(): void { + disconnect(reason = "Signaling disconnected"): void { + const ws = this.ws; this.generation += 1; - if (this.heartbeatTimer !== null) { - window.clearInterval(this.heartbeatTimer); - this.heartbeatTimer = null; + this.clearHeartbeat(); + if (this.pendingConnect && !this.pendingConnect.settled) { + const pending = this.pendingConnect; + pending.settled = true; + this.pendingConnect = null; + pending.reject(new Error(reason)); } - this.ws?.close(); this.ws = null; + if (ws) { + ws.close(); + this.emit({ type: "disconnected", reason }); + } } } diff --git a/opennow-stable/src/renderer/src/platform/android/http.ts b/opennow-stable/src/renderer/src/platform/android/http.ts index bda00c93..55b8e47b 100644 --- a/opennow-stable/src/renderer/src/platform/android/http.ts +++ b/opennow-stable/src/renderer/src/platform/android/http.ts @@ -34,11 +34,3 @@ export async function nativeRequest(options: HttpOptions, responseType: "json }); return parseResponse(response, responseType); } - -export async function nativeRequestRaw(options: HttpOptions): Promise { - return CapacitorHttp.request({ - ...options, - headers: normalizeHeaders(options.headers), - responseType: "text", - }); -} diff --git a/opennow-stable/src/renderer/src/platform/android/storage.ts b/opennow-stable/src/renderer/src/platform/android/storage.ts index 5878d1aa..9abb6c69 100644 --- a/opennow-stable/src/renderer/src/platform/android/storage.ts +++ b/opennow-stable/src/renderer/src/platform/android/storage.ts @@ -3,7 +3,14 @@ import { Preferences } from "@capacitor/preferences"; const BASE_DIR = "opennow"; -function normalizePath(path: string): string { +interface StoragePathOptions { + relativeToBaseDir?: boolean; +} + +function normalizePath(path: string, options: StoragePathOptions = {}): string { + if (options.relativeToBaseDir === false) { + return path; + } return path.startsWith(`${BASE_DIR}/`) ? path : `${BASE_DIR}/${path}`; } @@ -47,9 +54,9 @@ export async function removePreference(key: string): Promise { await Preferences.remove({ key }); } -export async function ensureDir(path: string): Promise { +export async function ensureDir(path: string, options: StoragePathOptions = {}): Promise { try { - await Filesystem.mkdir({ path, directory: Directory.Data, recursive: true }); + await Filesystem.mkdir({ path: normalizePath(path, options), directory: Directory.Data, recursive: true }); } catch (error) { if (isAlreadyExistsFilesystemError(error)) { return; @@ -58,34 +65,34 @@ export async function ensureDir(path: string): Promise { } } -export async function writeFile(path: string, data: string): Promise { - const normalized = normalizePath(path); +export async function writeFile(path: string, data: string, options: StoragePathOptions = {}): Promise { + const normalized = normalizePath(path, options); const parent = normalized.split("/").slice(0, -1).join("/"); - if (parent) await ensureDir(parent); + if (parent) await ensureDir(parent, { relativeToBaseDir: false }); await Filesystem.writeFile({ path: normalized, data, directory: Directory.Data, encoding: Encoding.UTF8 }); } -export async function appendFile(path: string, data: string): Promise { - const normalized = normalizePath(path); +export async function appendFile(path: string, data: string, options: StoragePathOptions = {}): Promise { + const normalized = normalizePath(path, options); const parent = normalized.split("/").slice(0, -1).join("/"); - if (parent) await ensureDir(parent); + if (parent) await ensureDir(parent, { relativeToBaseDir: false }); await Filesystem.appendFile({ path: normalized, data, directory: Directory.Data, encoding: Encoding.UTF8 }); } -export async function readFile(path: string): Promise { - const normalized = normalizePath(path); +export async function readFile(path: string, options: StoragePathOptions = {}): Promise { + const normalized = normalizePath(path, options); const result = await Filesystem.readFile({ path: normalized, directory: Directory.Data, encoding: Encoding.UTF8 }); return typeof result.data === "string" ? result.data : ""; } -export async function readFileBase64(path: string): Promise { - const normalized = normalizePath(path); +export async function readFileBase64(path: string, options: StoragePathOptions = {}): Promise { + const normalized = normalizePath(path, options); const result = await Filesystem.readFile({ path: normalized, directory: Directory.Data }); return typeof result.data === "string" ? result.data : ""; } -export async function deleteFile(path: string): Promise { - const normalized = normalizePath(path); +export async function deleteFile(path: string, options: StoragePathOptions = {}): Promise { + const normalized = normalizePath(path, options); try { await Filesystem.deleteFile({ path: normalized, directory: Directory.Data }); } catch (error) { @@ -96,8 +103,8 @@ export async function deleteFile(path: string): Promise { } } -export async function readDir(path: string): Promise { - const normalized = normalizePath(path); +export async function readDir(path: string, options: StoragePathOptions = {}): Promise { + const normalized = normalizePath(path, options); try { const result = await Filesystem.readdir({ path: normalized, directory: Directory.Data }); return result.files.map((file) => file.name); @@ -147,8 +154,8 @@ async function clearDirectoryNormalized(path: string): Promise { })); } -export async function clearDirectory(path: string): Promise { - await clearDirectoryNormalized(normalizePath(path)); +export async function clearDirectory(path: string, options: StoragePathOptions = {}): Promise { + await clearDirectoryNormalized(normalizePath(path, options)); } export function toBase64DataUrl(mimeType: string, data: string): string { From 0b834610715df9780ba99c115f6fe0f54346bbe4 Mon Sep 17 00:00:00 2001 From: zortos293 <65777760+zortos293@users.noreply.github.com> Date: Fri, 17 Apr 2026 22:02:04 +0000 Subject: [PATCH 20/66] Fix Android runtime follow-up regressions --- opennow-stable/android/app/build.gradle | 2 +- .../app/src/main/res/values/colors.xml | 6 + .../src/components/ControllerLibraryPage.tsx | 10 +- .../renderer/src/components/SettingsPage.tsx | 383 +++++++++--------- .../renderer/src/components/StreamView.tsx | 41 +- .../src/renderer/src/gfn/webrtcClient.ts | 17 +- .../src/renderer/src/platform/android/api.ts | 21 +- .../src/platform/android/browserSignaling.ts | 41 +- .../src/renderer/src/platform/android/http.ts | 18 +- opennow-stable/src/shared/gfn.ts | 1 + 10 files changed, 309 insertions(+), 231 deletions(-) create mode 100644 opennow-stable/android/app/src/main/res/values/colors.xml diff --git a/opennow-stable/android/app/build.gradle b/opennow-stable/android/app/build.gradle index 3d24617a..ce5eb256 100644 --- a/opennow-stable/android/app/build.gradle +++ b/opennow-stable/android/app/build.gradle @@ -11,7 +11,7 @@ def versionParts = packageVersionName.tokenize('.').collect { token -> while (versionParts.size() < 3) { versionParts << 0 } -def packageVersionCode = (versionParts[0] * 10000) + (versionParts[1] * 100) + versionParts[2] +def packageVersionCode = (versionParts[0] * 100000000) + (versionParts[1] * 10000) + versionParts[2] android { namespace = "com.opencloudgaming.opennow" diff --git a/opennow-stable/android/app/src/main/res/values/colors.xml b/opennow-stable/android/app/src/main/res/values/colors.xml new file mode 100644 index 00000000..c6d8f1d5 --- /dev/null +++ b/opennow-stable/android/app/src/main/res/values/colors.xml @@ -0,0 +1,6 @@ + + + #0F172A + #020617 + #38BDF8 + diff --git a/opennow-stable/src/renderer/src/components/ControllerLibraryPage.tsx b/opennow-stable/src/renderer/src/components/ControllerLibraryPage.tsx index 81870c20..31738a01 100644 --- a/opennow-stable/src/renderer/src/components/ControllerLibraryPage.tsx +++ b/opennow-stable/src/renderer/src/components/ControllerLibraryPage.tsx @@ -410,11 +410,11 @@ export function ControllerLibraryPage({ } let cancelled = false; - const loadMedia = async () => { - try { - setMediaLoading(true); - setMediaError(null); - const listing = await openNow.listMediaByGame({}); + const loadMedia = async () => { + try { + setMediaLoading(true); + setMediaError(null); + const listing = await openNow.listMediaByGame({}); if (cancelled) return; const videos = [...(listing.videos ?? [])].sort((a, b) => b.createdAtMs - a.createdAtMs); diff --git a/opennow-stable/src/renderer/src/components/SettingsPage.tsx b/opennow-stable/src/renderer/src/components/SettingsPage.tsx index 9972b1de..dcd02cd6 100644 --- a/opennow-stable/src/renderer/src/components/SettingsPage.tsx +++ b/opennow-stable/src/renderer/src/components/SettingsPage.tsx @@ -2132,209 +2132,210 @@ export function SettingsPage({ settings, regions, onSettingChange, codecResults, Dynamic turn boost strength (1% = off-like, 150% = strongest).
- {/* Shortcuts */} -
-
- -
- Editable - + {platformCapabilities.supportsKeyboardShortcuts && ( +
+
+ +
+ Editable + +
-
-
-
- Toggle Stats - e.target.select()} - onBlur={() => handleShortcutBlur("shortcutToggleStats", toggleStatsInput)} - onPaste={(e) => handleShortcutPaste("shortcutToggleStats", e)} - onKeyDown={(e) => handleShortcutCaptureKeyDown("shortcutToggleStats", e)} - placeholder="Click here, then press a key" - title="Focus and press the key combination to bind" - spellCheck={false} - /> -
+
+
+ Toggle Stats + e.target.select()} + onBlur={() => handleShortcutBlur("shortcutToggleStats", toggleStatsInput)} + onPaste={(e) => handleShortcutPaste("shortcutToggleStats", e)} + onKeyDown={(e) => handleShortcutCaptureKeyDown("shortcutToggleStats", e)} + placeholder="Click here, then press a key" + title="Focus and press the key combination to bind" + spellCheck={false} + /> +
-
- Mouse Lock - e.target.select()} - onBlur={() => handleShortcutBlur("shortcutTogglePointerLock", togglePointerLockInput)} - onPaste={(e) => handleShortcutPaste("shortcutTogglePointerLock", e)} - onKeyDown={(e) => handleShortcutCaptureKeyDown("shortcutTogglePointerLock", e)} - placeholder="Click here, then press a key" - title="Focus and press the key combination to bind" - spellCheck={false} - /> -
+
+ Mouse Lock + e.target.select()} + onBlur={() => handleShortcutBlur("shortcutTogglePointerLock", togglePointerLockInput)} + onPaste={(e) => handleShortcutPaste("shortcutTogglePointerLock", e)} + onKeyDown={(e) => handleShortcutCaptureKeyDown("shortcutTogglePointerLock", e)} + placeholder="Click here, then press a key" + title="Focus and press the key combination to bind" + spellCheck={false} + /> +
-
- Toggle Full Screen - e.target.select()} - onBlur={() => handleShortcutBlur("shortcutToggleFullscreen", toggleFullscreenInput)} - onPaste={(e) => handleShortcutPaste("shortcutToggleFullscreen", e)} - onKeyDown={(e) => handleShortcutCaptureKeyDown("shortcutToggleFullscreen", e)} - placeholder="Click here, then press a key" - title="Focus and press the key combination to bind" - spellCheck={false} - /> -
+
+ Toggle Full Screen + e.target.select()} + onBlur={() => handleShortcutBlur("shortcutToggleFullscreen", toggleFullscreenInput)} + onPaste={(e) => handleShortcutPaste("shortcutToggleFullscreen", e)} + onKeyDown={(e) => handleShortcutCaptureKeyDown("shortcutToggleFullscreen", e)} + placeholder="Click here, then press a key" + title="Focus and press the key combination to bind" + spellCheck={false} + /> +
-
- Stop Stream - e.target.select()} - onBlur={() => handleShortcutBlur("shortcutStopStream", stopStreamInput)} - onPaste={(e) => handleShortcutPaste("shortcutStopStream", e)} - onKeyDown={(e) => handleShortcutCaptureKeyDown("shortcutStopStream", e)} - placeholder="Click here, then press a key" - title="Focus and press the key combination to bind" - spellCheck={false} - /> -
+
+ Stop Stream + e.target.select()} + onBlur={() => handleShortcutBlur("shortcutStopStream", stopStreamInput)} + onPaste={(e) => handleShortcutPaste("shortcutStopStream", e)} + onKeyDown={(e) => handleShortcutCaptureKeyDown("shortcutStopStream", e)} + placeholder="Click here, then press a key" + title="Focus and press the key combination to bind" + spellCheck={false} + /> +
-
- Toggle Anti-AFK - e.target.select()} - onBlur={() => handleShortcutBlur("shortcutToggleAntiAfk", toggleAntiAfkInput)} - onPaste={(e) => handleShortcutPaste("shortcutToggleAntiAfk", e)} - onKeyDown={(e) => handleShortcutCaptureKeyDown("shortcutToggleAntiAfk", e)} - placeholder="Click here, then press a key" - title="Focus and press the key combination to bind" - spellCheck={false} - /> -
+
+ Toggle Anti-AFK + e.target.select()} + onBlur={() => handleShortcutBlur("shortcutToggleAntiAfk", toggleAntiAfkInput)} + onPaste={(e) => handleShortcutPaste("shortcutToggleAntiAfk", e)} + onKeyDown={(e) => handleShortcutCaptureKeyDown("shortcutToggleAntiAfk", e)} + placeholder="Click here, then press a key" + title="Focus and press the key combination to bind" + spellCheck={false} + /> +
-
- Toggle Microphone - e.target.select()} - onBlur={() => handleShortcutBlur("shortcutToggleMicrophone", toggleMicrophoneInput)} - onPaste={(e) => handleShortcutPaste("shortcutToggleMicrophone", e)} - onKeyDown={(e) => handleShortcutCaptureKeyDown("shortcutToggleMicrophone", e)} - placeholder="Click here, then press a key" - title="Focus and press the key combination to bind" - spellCheck={false} - /> -
+
+ Toggle Microphone + e.target.select()} + onBlur={() => handleShortcutBlur("shortcutToggleMicrophone", toggleMicrophoneInput)} + onPaste={(e) => handleShortcutPaste("shortcutToggleMicrophone", e)} + onKeyDown={(e) => handleShortcutCaptureKeyDown("shortcutToggleMicrophone", e)} + placeholder="Click here, then press a key" + title="Focus and press the key combination to bind" + spellCheck={false} + /> +
-
- Screenshot - e.target.select()} - onBlur={() => handleShortcutBlur("shortcutScreenshot", screenshotInput)} - onPaste={(e) => handleShortcutPaste("shortcutScreenshot", e)} - onKeyDown={(e) => handleShortcutCaptureKeyDown("shortcutScreenshot", e)} - placeholder="Click here, then press a key" - title="Focus and press the key combination to bind" - spellCheck={false} - /> -
+
+ Screenshot + e.target.select()} + onBlur={() => handleShortcutBlur("shortcutScreenshot", screenshotInput)} + onPaste={(e) => handleShortcutPaste("shortcutScreenshot", e)} + onKeyDown={(e) => handleShortcutCaptureKeyDown("shortcutScreenshot", e)} + placeholder="Click here, then press a key" + title="Focus and press the key combination to bind" + spellCheck={false} + /> +
-
- Recording - e.target.select()} - onBlur={() => handleShortcutBlur("shortcutToggleRecording", recordingInput)} - onPaste={(e) => handleShortcutPaste("shortcutToggleRecording", e)} - onKeyDown={(e) => handleShortcutCaptureKeyDown("shortcutToggleRecording", e)} - placeholder="Click here, then press a key" - title="Focus and press the key combination to bind" - spellCheck={false} - /> -
+
+ Recording + e.target.select()} + onBlur={() => handleShortcutBlur("shortcutToggleRecording", recordingInput)} + onPaste={(e) => handleShortcutPaste("shortcutToggleRecording", e)} + onKeyDown={(e) => handleShortcutCaptureKeyDown("shortcutToggleRecording", e)} + placeholder="Click here, then press a key" + title="Focus and press the key combination to bind" + spellCheck={false} + /> +
-
- Toggle stream sidebar - -
-
+
+ Toggle stream sidebar + +
+
- {(toggleStatsError || togglePointerLockError || toggleFullscreenError || stopStreamError || toggleAntiAfkError || toggleMicrophoneError || screenshotError || recordingError) && ( - - {toggleStatsError - || togglePointerLockError - || toggleFullscreenError - || stopStreamError - || toggleAntiAfkError - || toggleMicrophoneError - || screenshotError - || recordingError} - - )} + {(toggleStatsError || togglePointerLockError || toggleFullscreenError || stopStreamError || toggleAntiAfkError || toggleMicrophoneError || screenshotError || recordingError) && ( + + {toggleStatsError + || togglePointerLockError + || toggleFullscreenError + || stopStreamError + || toggleAntiAfkError + || toggleMicrophoneError + || screenshotError + || recordingError} + + )} - {!toggleStatsError && !togglePointerLockError && !toggleFullscreenError && !stopStreamError && !toggleAntiAfkError && !toggleMicrophoneError && !screenshotError && !recordingError && ( - - Click a field and press the keys to bind, or paste a shortcut ({shortcutExamples}). Escape cancels focus. Full screen: {formatShortcutForDisplay(settings.shortcutToggleFullscreen, isMac)}. Stop: {formatShortcutForDisplay(settings.shortcutStopStream, isMac)}. Mic: {formatShortcutForDisplay(settings.shortcutToggleMicrophone, isMac)}. Screenshot: {formatShortcutForDisplay(settings.shortcutScreenshot, isMac)}. Recording: {formatShortcutForDisplay(settings.shortcutToggleRecording, isMac)}. - - )} -
+ {!toggleStatsError && !togglePointerLockError && !toggleFullscreenError && !stopStreamError && !toggleAntiAfkError && !toggleMicrophoneError && !screenshotError && !recordingError && ( + + Click a field and press the keys to bind, or paste a shortcut ({shortcutExamples}). Escape cancels focus. Full screen: {formatShortcutForDisplay(settings.shortcutToggleFullscreen, isMac)}. Stop: {formatShortcutForDisplay(settings.shortcutStopStream, isMac)}. Mic: {formatShortcutForDisplay(settings.shortcutToggleMicrophone, isMac)}. Screenshot: {formatShortcutForDisplay(settings.shortcutScreenshot, isMac)}. Recording: {formatShortcutForDisplay(settings.shortcutToggleRecording, isMac)}. + + )} +
+ )}
)} diff --git a/opennow-stable/src/renderer/src/components/StreamView.tsx b/opennow-stable/src/renderer/src/components/StreamView.tsx index 12bb04fe..f4aa112e 100644 --- a/opennow-stable/src/renderer/src/components/StreamView.tsx +++ b/opennow-stable/src/renderer/src/components/StreamView.tsx @@ -1406,6 +1406,15 @@ export function StreamView({ }, [onReleasePointerLock]); useEffect(() => { + if (!platformCapabilities.supportsKeyboardShortcuts && activeSidebarTab === "shortcuts") { + setActiveSidebarTab("preferences"); + } + }, [activeSidebarTab]); + + useEffect(() => { + if (!platformCapabilities.supportsKeyboardShortcuts) { + return; + } const screenshotShortcut = normalizeShortcut(shortcuts.screenshot); const recordingShortcut = normalizeShortcut(shortcuts.recording); const onKeyDown = (event: KeyboardEvent) => { @@ -1493,15 +1502,17 @@ export function StreamView({ > Preferences - + {platformCapabilities.supportsKeyboardShortcuts && ( + + )} {activeSidebarTab === "preferences" && ( @@ -1603,7 +1614,7 @@ export function StreamView({
Gallery - ScreensShot key: {shortcuts.screenshot} + {platformCapabilities.supportsKeyboardShortcuts ? `ScreensShot key: ${shortcuts.screenshot}` : "Capture screenshots from the sidebar"}
ScreensShot @@ -1651,7 +1662,7 @@ export function StreamView({
{screenshots.length === 0 && ( - No screenshots yet. Press {shortcuts.screenshot} to capture one. + {platformCapabilities.supportsKeyboardShortcuts ? `No screenshots yet. Press ${shortcuts.screenshot} to capture one.` : "No screenshots yet. Use Capture to save one."} )} {galleryError && {galleryError}}
@@ -1659,7 +1670,7 @@ export function StreamView({
Recordings - Record key: {shortcuts.recording} + {platformCapabilities.supportsKeyboardShortcuts ? `Record key: ${shortcuts.recording}` : "Start or stop recording from the sidebar"}
{usedMimeType && ( Codec: {usedMimeType} @@ -1682,7 +1693,7 @@ export function StreamView({ {recordingError} )} {recordings.length === 0 ? ( - No recordings yet. Press {shortcuts.recording} to record. + {platformCapabilities.supportsKeyboardShortcuts ? `No recordings yet. Press ${shortcuts.recording} to record.` : "No recordings yet. Use Start to record."} ) : (
+ ); +} diff --git a/opennow-stable/src/renderer/src/components/StreamLoading.tsx b/opennow-stable/src/renderer/src/components/StreamLoading.tsx index fec2a28c..fb242db8 100644 --- a/opennow-stable/src/renderer/src/components/StreamLoading.tsx +++ b/opennow-stable/src/renderer/src/components/StreamLoading.tsx @@ -11,6 +11,7 @@ import { } from "@shared/gfn"; import type { SessionAdInfo, SessionAdState } from "@shared/gfn"; import { getStoreDisplayName, getStoreIconComponent } from "./GameCard"; +import { CopyErrorButton } from "./CopyErrorButton"; import { QueueAdPreview, type QueueAdPlaybackEvent, type QueueAdPreviewHandle } from "./QueueAdPreview"; export interface StreamLoadingProps { @@ -28,6 +29,7 @@ export interface StreamLoadingProps { description: string; code?: string; }; + copyErrorText?: string; onAdPlaybackEvent?: (event: QueueAdPlaybackEvent, adId: string) => void; adPreviewRef?: Ref; onCancel: () => void; @@ -107,6 +109,7 @@ export function StreamLoading({ activeAd, activeAdMediaUrl, error, + copyErrorText, onAdPlaybackEvent, adPreviewRef, onCancel, @@ -213,6 +216,7 @@ export function StreamLoading({

{error.title}

{error.description}

{error.code &&

{error.code}

} + {copyErrorText && } )} {status === "queue" && estimatedWait && ( diff --git a/opennow-stable/src/renderer/src/components/StreamView.tsx b/opennow-stable/src/renderer/src/components/StreamView.tsx index bb3c96eb..a3b4539f 100644 --- a/opennow-stable/src/renderer/src/components/StreamView.tsx +++ b/opennow-stable/src/renderer/src/components/StreamView.tsx @@ -7,6 +7,21 @@ import type { StreamDiagnosticsStore } from "../utils/streamDiagnosticsStore"; import { useStreamDiagnosticsSelector, useStreamDiagnosticsStore } from "../utils/streamDiagnosticsStore"; import type { StreamLagReason } from "../gfn/webrtcClient"; import type { MicState } from "../gfn/microphoneManager"; +import type { VirtualGamepadState } from "../gfn/webrtcClient"; +import { + GAMEPAD_A, + GAMEPAD_B, + GAMEPAD_BACK, + GAMEPAD_DPAD_DOWN, + GAMEPAD_DPAD_LEFT, + GAMEPAD_DPAD_RIGHT, + GAMEPAD_DPAD_UP, + GAMEPAD_LB, + GAMEPAD_RB, + GAMEPAD_START, + GAMEPAD_X, + GAMEPAD_Y, +} from "../gfn/inputProtocol"; import { getStoreDisplayName, getStoreIconComponent } from "./GameCard"; import { RemainingPlaytimeIndicator, SessionElapsedIndicator } from "./ElapsedSessionIndicators"; import type { MicrophoneMode, ScreenshotEntry, RecordingEntry, SubscriptionInfo } from "@shared/gfn"; @@ -65,6 +80,7 @@ interface StreamViewProps { onMouseAccelerationChange: (value: number) => void; onRequestPointerLock?: () => void; onReleasePointerLock?: () => void; + onVirtualGamepadState?: (state: VirtualGamepadState) => void; microphoneMode: MicrophoneMode; onMicrophoneModeChange: (value: MicrophoneMode) => void; onScreenshotShortcutChange: (value: string) => void; @@ -168,6 +184,17 @@ type MicBadgeState = { micEnabled: boolean; }; +const EMPTY_VIRTUAL_GAMEPAD_STATE: VirtualGamepadState = { + connected: true, + buttons: 0, + leftTrigger: 0, + rightTrigger: 0, + leftStickX: 0, + leftStickY: 0, + rightStickX: 0, + rightStickY: 0, +}; + function isMicBadgeStateEqual(prev: MicBadgeState, next: MicBadgeState): boolean { return ( prev.connectedGamepads === next.connectedGamepads && @@ -524,6 +551,204 @@ function VideoFocusOnReady({ return null; } +type StickValue = { x: number; y: number }; + +function TouchStick({ + label, + value, + onChange, +}: { + label: string; + value: StickValue; + onChange: (value: StickValue) => void; +}): JSX.Element { + const baseRef = useRef(null); + + const updateFromPointer = useCallback((event: React.PointerEvent) => { + const rect = baseRef.current?.getBoundingClientRect(); + if (!rect) return; + const radius = Math.max(1, Math.min(rect.width, rect.height) / 2); + const centerX = rect.left + rect.width / 2; + const centerY = rect.top + rect.height / 2; + const rawX = (event.clientX - centerX) / radius; + const rawY = (event.clientY - centerY) / radius; + const magnitude = Math.hypot(rawX, rawY); + const scale = magnitude > 1 ? 1 / magnitude : 1; + onChange({ x: rawX * scale, y: rawY * scale }); + }, [onChange]); + + return ( +
{ + event.preventDefault(); + event.currentTarget.setPointerCapture(event.pointerId); + updateFromPointer(event); + }} + onPointerMove={(event) => { + if (event.currentTarget.hasPointerCapture(event.pointerId)) { + event.preventDefault(); + updateFromPointer(event); + } + }} + onPointerUp={(event) => { + event.preventDefault(); + event.currentTarget.releasePointerCapture(event.pointerId); + onChange({ x: 0, y: 0 }); + }} + onPointerCancel={(event) => { + if (event.currentTarget.hasPointerCapture(event.pointerId)) { + event.currentTarget.releasePointerCapture(event.pointerId); + } + onChange({ x: 0, y: 0 }); + }} + aria-label={label} + role="application" + > + +
+ ); +} + +function TouchControllerOverlay({ + onVirtualGamepadState, +}: { + onVirtualGamepadState: (state: VirtualGamepadState) => void; +}): JSX.Element { + const [leftStick, setLeftStick] = useState({ x: 0, y: 0 }); + const [rightStick, setRightStick] = useState({ x: 0, y: 0 }); + const buttonsRef = useRef(0); + const triggersRef = useRef({ left: 0, right: 0 }); + const leftStickRef = useRef(leftStick); + const rightStickRef = useRef(rightStick); + + const emit = useCallback((connected = true) => { + onVirtualGamepadState({ + connected, + buttons: connected ? buttonsRef.current : 0, + leftTrigger: connected ? triggersRef.current.left : 0, + rightTrigger: connected ? triggersRef.current.right : 0, + leftStickX: connected ? leftStickRef.current.x : 0, + leftStickY: connected ? -leftStickRef.current.y : 0, + rightStickX: connected ? rightStickRef.current.x : 0, + rightStickY: connected ? -rightStickRef.current.y : 0, + }); + }, [onVirtualGamepadState]); + + const updateLeftStick = useCallback((value: StickValue) => { + leftStickRef.current = value; + setLeftStick(value); + emit(); + }, [emit]); + + const updateRightStick = useCallback((value: StickValue) => { + rightStickRef.current = value; + setRightStick(value); + emit(); + }, [emit]); + + const setButton = useCallback((mask: number, pressed: boolean) => { + buttonsRef.current = pressed + ? buttonsRef.current | mask + : buttonsRef.current & ~mask; + emit(); + }, [emit]); + + const setTrigger = useCallback((side: "left" | "right", pressed: boolean) => { + triggersRef.current = { + ...triggersRef.current, + [side]: pressed ? 1 : 0, + }; + emit(); + }, [emit]); + + const bindButton = (mask: number) => ({ + onPointerDown: (event: React.PointerEvent) => { + event.preventDefault(); + event.currentTarget.setPointerCapture(event.pointerId); + setButton(mask, true); + }, + onPointerUp: (event: React.PointerEvent) => { + event.preventDefault(); + event.currentTarget.releasePointerCapture(event.pointerId); + setButton(mask, false); + }, + onPointerCancel: (event: React.PointerEvent) => { + if (event.currentTarget.hasPointerCapture(event.pointerId)) { + event.currentTarget.releasePointerCapture(event.pointerId); + } + setButton(mask, false); + }, + }); + + const bindTrigger = (side: "left" | "right") => ({ + onPointerDown: (event: React.PointerEvent) => { + event.preventDefault(); + event.currentTarget.setPointerCapture(event.pointerId); + setTrigger(side, true); + }, + onPointerUp: (event: React.PointerEvent) => { + event.preventDefault(); + event.currentTarget.releasePointerCapture(event.pointerId); + setTrigger(side, false); + }, + onPointerCancel: (event: React.PointerEvent) => { + if (event.currentTarget.hasPointerCapture(event.pointerId)) { + event.currentTarget.releasePointerCapture(event.pointerId); + } + setTrigger(side, false); + }, + }); + + useEffect(() => { + emit(); + const keepalive = window.setInterval(() => emit(), 80); + return () => { + window.clearInterval(keepalive); + onVirtualGamepadState({ ...EMPTY_VIRTUAL_GAMEPAD_STATE, connected: false }); + }; + }, [emit, onVirtualGamepadState]); + + return ( +
+
+ + + + +
+
+ +
+ + + + +
+
+
+ + +
+
+ +
+ + + + +
+
+
+ ); +} + function useMicMeter( canvasRef: React.RefObject, track: MediaStreamTrack | null, @@ -670,6 +895,7 @@ export function StreamView({ onMouseAccelerationChange, onRequestPointerLock, onReleasePointerLock, + onVirtualGamepadState, microphoneMode, onMicrophoneModeChange, onScreenshotShortcutChange, @@ -1931,6 +2157,10 @@ export function StreamView({ {/* Gradient background when no video */} + {platformCapabilities.isAndroid && !isConnecting && onVirtualGamepadState && ( + + )} + {/* Connecting overlay */} {isConnecting && (
diff --git a/opennow-stable/src/renderer/src/gfn/webrtcClient.ts b/opennow-stable/src/renderer/src/gfn/webrtcClient.ts index fa9260d4..59b63c16 100644 --- a/opennow-stable/src/renderer/src/gfn/webrtcClient.ts +++ b/opennow-stable/src/renderer/src/gfn/webrtcClient.ts @@ -118,6 +118,17 @@ export interface StreamDiagnostics { micEnabled: boolean; } +export interface VirtualGamepadState { + connected: boolean; + buttons: number; + leftTrigger: number; + rightTrigger: number; + leftStickX: number; + leftStickY: number; + rightStickX: number; + rightStickY: number; +} + export type StreamLagReason = | "unknown" | "stable" @@ -483,6 +494,8 @@ export class GfnWebRtcClient { private renderFpsCounter = { frames: 0, lastUpdate: 0, fps: 0 }; private connectedGamepads: Set = new Set(); private previousGamepadStates: Map = new Map(); + private virtualGamepadConnected = false; + private previousVirtualGamepadState: GamepadInput | null = null; // Track currently pressed keys (VK codes) for synthetic Escape detection private pressedKeys: Set = new Set(); @@ -1618,6 +1631,8 @@ export class GfnWebRtcClient { this.resetDiagnostics(); this.connectedGamepads.clear(); this.previousGamepadStates.clear(); + this.virtualGamepadConnected = false; + this.previousVirtualGamepadState = null; this.gamepadSendCount = 0; this.lastGamepadSendMs = 0; this.reliableDropLogged = false; @@ -1906,7 +1921,64 @@ export class GfnWebRtcClient { } } - this.diagnostics.connectedGamepads = connectedCount; + this.diagnostics.connectedGamepads = connectedCount + (this.virtualGamepadConnected ? 1 : 0); + } + + public setVirtualGamepadState(state: VirtualGamepadState): void { + if (!this.inputReady || this.inputPaused) { + return; + } + + const controllerId = 0; + const wasConnected = this.virtualGamepadConnected; + this.virtualGamepadConnected = state.connected; + if (state.connected) { + this.gamepadBitmap |= (1 << controllerId); + } else { + this.gamepadBitmap &= ~(1 << controllerId); + } + + const gamepadInput: GamepadInput = { + controllerId, + buttons: state.buttons & 0xffff, + leftTrigger: normalizeToUint8(state.leftTrigger), + rightTrigger: normalizeToUint8(state.rightTrigger), + leftStickX: normalizeToInt16(state.leftStickX), + leftStickY: normalizeToInt16(state.leftStickY), + rightStickX: normalizeToInt16(state.rightStickX), + rightStickY: normalizeToInt16(state.rightStickY), + connected: state.connected, + timestampUs: timestampUs(), + }; + + const stateChanged = + !this.previousVirtualGamepadState || + this.previousVirtualGamepadState.connected !== gamepadInput.connected || + this.previousVirtualGamepadState.buttons !== gamepadInput.buttons || + this.previousVirtualGamepadState.leftTrigger !== gamepadInput.leftTrigger || + this.previousVirtualGamepadState.rightTrigger !== gamepadInput.rightTrigger || + this.previousVirtualGamepadState.leftStickX !== gamepadInput.leftStickX || + this.previousVirtualGamepadState.leftStickY !== gamepadInput.leftStickY || + this.previousVirtualGamepadState.rightStickX !== gamepadInput.rightStickX || + this.previousVirtualGamepadState.rightStickY !== gamepadInput.rightStickY; + const nowMs = performance.now(); + const needsKeepalive = nowMs - this.lastGamepadSendMs >= GfnWebRtcClient.GAMEPAD_KEEPALIVE_MS; + + if (!stateChanged && !needsKeepalive && wasConnected === state.connected) { + return; + } + + const usePR = this.canSendGamepadPartiallyReliable(controllerId); + const bytes = this.inputEncoder.encodeGamepadState(gamepadInput, this.gamepadBitmap, usePR); + if (usePR) { + this.sendGamepad(bytes); + } else { + this.sendReliable(bytes); + } + this.lastGamepadSendMs = nowMs; + this.previousVirtualGamepadState = { ...gamepadInput }; + this.diagnostics.connectedGamepads = this.connectedGamepads.size + (this.virtualGamepadConnected ? 1 : 0); + this.emitStats(); } private readGamepadState(gamepad: Gamepad, controllerId: number): GamepadInput { diff --git a/opennow-stable/src/renderer/src/styles.css b/opennow-stable/src/renderer/src/styles.css index 391be61d..e0fc6fec 100644 --- a/opennow-stable/src/renderer/src/styles.css +++ b/opennow-stable/src/renderer/src/styles.css @@ -5633,6 +5633,161 @@ button.game-card-store-chip.active:hover { color: var(--accent); } +.sv-touch { + position: fixed; + inset: 0; + z-index: 1001; + pointer-events: none; + touch-action: none; +} + +.sv-touch-left, +.sv-touch-right { + position: fixed; + bottom: max(18px, env(safe-area-inset-bottom)); + display: grid; + align-items: end; + gap: 14px; + pointer-events: none; +} + +.sv-touch-left { + left: max(16px, env(safe-area-inset-left)); + grid-template-columns: auto auto; +} + +.sv-touch-right { + right: max(16px, env(safe-area-inset-right)); + grid-template-columns: auto auto; +} + +.sv-touch-shoulders { + position: fixed; + top: max(12px, env(safe-area-inset-top)); + left: 50%; + transform: translateX(-50%); + display: grid; + grid-template-columns: repeat(4, minmax(52px, 68px)); + gap: 8px; + pointer-events: none; +} + +.sv-touch-center { + position: fixed; + left: 50%; + bottom: max(18px, env(safe-area-inset-bottom)); + transform: translateX(-50%); + display: flex; + gap: 10px; + pointer-events: none; +} + +.sv-touch-stick { + width: 112px; + aspect-ratio: 1; + border-radius: 999px; + border: 1px solid rgba(255, 255, 255, 0.18); + background: rgba(8, 10, 12, 0.34); + box-shadow: + 0 10px 26px rgba(0, 0, 0, 0.34), + inset 0 1px 0 rgba(255, 255, 255, 0.08); + backdrop-filter: blur(10px) saturate(135%); + display: grid; + place-items: center; + pointer-events: auto; + touch-action: none; +} + +.sv-touch-stick-thumb { + width: 48px; + aspect-ratio: 1; + border-radius: 999px; + background: rgba(255, 255, 255, 0.22); + border: 1px solid rgba(255, 255, 255, 0.22); + box-shadow: 0 8px 18px rgba(0, 0, 0, 0.34); + transition: transform 34ms linear; +} + +.sv-touch-dpad, +.sv-touch-face { + position: relative; + width: 124px; + aspect-ratio: 1; + pointer-events: none; +} + +.sv-touch-btn { + pointer-events: auto; + touch-action: none; + -webkit-tap-highlight-color: transparent; + border: 1px solid rgba(255, 255, 255, 0.18); + background: rgba(8, 10, 12, 0.42); + color: rgba(255, 255, 255, 0.76); + box-shadow: + 0 10px 24px rgba(0, 0, 0, 0.34), + inset 0 1px 0 rgba(255, 255, 255, 0.08); + backdrop-filter: blur(10px) saturate(135%); + font: inherit; + font-size: 0.72rem; + font-weight: 800; + letter-spacing: 0; + display: inline-flex; + align-items: center; + justify-content: center; + user-select: none; +} + +.sv-touch-btn:active { + background: color-mix(in srgb, var(--accent) 26%, rgba(8, 10, 12, 0.52)); + border-color: color-mix(in srgb, var(--accent) 55%, rgba(255, 255, 255, 0.18)); + color: #fff; + transform: scale(0.96); +} + +.sv-touch-btn--shoulder, +.sv-touch-btn--trigger, +.sv-touch-btn--menu { + height: 36px; + border-radius: 8px; +} + +.sv-touch-btn--menu { + min-width: 54px; + padding: 0 12px; +} + +.sv-touch-btn--dpad, +.sv-touch-btn--face { + position: absolute; + width: 44px; + height: 44px; + border-radius: 999px; +} + +.sv-touch-dpad-up, +.sv-touch-face-y { + top: 0; + left: 40px; +} + +.sv-touch-dpad-left, +.sv-touch-face-x { + top: 40px; + left: 0; +} + +.sv-touch-dpad-right, +.sv-touch-face-b { + top: 40px; + right: 0; +} + +.sv-touch-dpad-down, +.sv-touch-face-a { + bottom: 0; + left: 40px; +} + @media (max-width: 640px) { .sv-session-clock { top: 10px; @@ -5680,6 +5835,76 @@ button.game-card-store-chip.active:hover { .sv-exit-actions { flex-direction: column; } + + .sv-touch-left, + .sv-touch-right { + gap: 10px; + } + + .sv-touch-left { + left: max(10px, env(safe-area-inset-left)); + } + + .sv-touch-right { + right: max(10px, env(safe-area-inset-right)); + } + + .sv-touch-stick { + width: 94px; + } + + .sv-touch-stick-thumb { + width: 40px; + } + + .sv-touch-dpad, + .sv-touch-face { + width: 104px; + } + + .sv-touch-btn--dpad, + .sv-touch-btn--face { + width: 38px; + height: 38px; + } + + .sv-touch-dpad-up, + .sv-touch-face-y { + left: 33px; + } + + .sv-touch-dpad-left, + .sv-touch-face-x { + top: 33px; + } + + .sv-touch-dpad-right, + .sv-touch-face-b { + top: 33px; + } + + .sv-touch-dpad-down, + .sv-touch-face-a { + left: 33px; + } + + .sv-touch-shoulders { + top: max(8px, env(safe-area-inset-top)); + grid-template-columns: repeat(4, 48px); + gap: 6px; + } + + .sv-touch-btn--shoulder, + .sv-touch-btn--trigger, + .sv-touch-btn--menu { + height: 32px; + border-radius: 8px; + font-size: 0.66rem; + } + + .sv-touch-center { + bottom: max(124px, calc(env(safe-area-inset-bottom) + 112px)); + } } @@ -6341,6 +6566,137 @@ button.game-card-store-chip.active:hover { letter-spacing: 0.01em; } +.sload-copy-error, +.csl-copy-error { + align-self: center; + display: inline-flex; + align-items: center; + justify-content: center; + gap: 7px; + min-height: 34px; + padding: 0 12px; + border-radius: 8px; + border: 1px solid rgba(255, 119, 119, 0.28); + background: rgba(255, 255, 255, 0.06); + color: #ffd0d0; + font: inherit; + font-size: 0.76rem; + font-weight: 700; + letter-spacing: 0; + cursor: pointer; + transition: transform var(--t-fast), background var(--t-fast), border-color var(--t-fast); +} + +.sload-copy-error:hover, +.csl-copy-error:hover { + background: rgba(255, 119, 119, 0.12); + border-color: rgba(255, 119, 119, 0.42); +} + +.sload-copy-error:active, +.csl-copy-error:active { + transform: scale(0.97); +} + +.android-shell .sload { + align-items: flex-start; + justify-content: center; + padding: + max(12px, env(safe-area-inset-top)) + max(12px, env(safe-area-inset-right)) + max(12px, env(safe-area-inset-bottom)) + max(12px, env(safe-area-inset-left)); + overflow-y: auto; +} + +.android-shell .sload-content { + width: min(100%, 420px); + max-width: calc(100vw - 24px); + min-height: min-content; + gap: 18px; + padding: 12px 0; +} + +.android-shell .sload-game { + width: 100%; + min-width: 0; +} + +.android-shell .sload-game-meta { + min-width: 0; +} + +.android-shell .sload-title { + max-width: 100%; +} + +.android-shell .sload-status, +.android-shell .sload-status-text { + width: 100%; + min-width: 0; +} + +.android-shell .sload-error-title, +.android-shell .sload-error-desc, +.android-shell .sload-error-code { + max-width: 100%; + overflow-wrap: anywhere; + word-break: break-word; +} + +.android-shell .sload-error-code { + white-space: normal; +} + +.android-shell .sload-copy-error { + max-width: 100%; + flex-shrink: 0; +} + +.android-shell .controller-stream-loading { + align-items: flex-start; + overflow-y: auto; +} + +.android-shell .csl-content-wrapper { + height: auto; + min-height: 100%; + padding: + max(16px, env(safe-area-inset-top)) + max(12px, env(safe-area-inset-right)) + max(16px, env(safe-area-inset-bottom)) + max(12px, env(safe-area-inset-left)); +} + +.android-shell .csl-content { + grid-template-columns: minmax(0, 1fr); + gap: 18px; + max-width: calc(100vw - 24px); + min-width: 0; +} + +.android-shell .csl-poster-section { + display: none; +} + +.android-shell .csl-info-section, +.android-shell .csl-status-container, +.android-shell .csl-error-panel { + width: 100%; + min-width: 0; +} + +.android-shell .csl-error-title, +.android-shell .csl-error-description, +.android-shell .csl-error-code { + overflow-wrap: anywhere; + word-break: break-word; +} + +.android-shell .csl-error-code { + white-space: normal; +} + .sload.sload--error .sload-queue, .sload.sload--error .sload-queue-num, .sload.sload--error .sload-wait { From e10bc1f632d331d587924a480ba685b2467edcb3 Mon Sep 17 00:00:00 2001 From: Kiefer Date: Sat, 25 Apr 2026 16:59:53 -0700 Subject: [PATCH 41/66] Implement Android touch controls and mousepad functionality with UI adjustments --- .../src/main/res/mipmap-hdpi/ic_launcher.png | Bin 2786 -> 5984 bytes .../mipmap-hdpi/ic_launcher_foreground.png | Bin 3450 -> 17623 bytes .../res/mipmap-hdpi/ic_launcher_round.png | Bin 4341 -> 5984 bytes .../src/main/res/mipmap-mdpi/ic_launcher.png | Bin 1869 -> 3972 bytes .../mipmap-mdpi/ic_launcher_foreground.png | Bin 2110 -> 9693 bytes .../res/mipmap-mdpi/ic_launcher_round.png | Bin 2725 -> 3972 bytes .../src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 3981 -> 8328 bytes .../mipmap-xhdpi/ic_launcher_foreground.png | Bin 5036 -> 27323 bytes .../res/mipmap-xhdpi/ic_launcher_round.png | Bin 6593 -> 8328 bytes .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin 6644 -> 14583 bytes .../mipmap-xxhdpi/ic_launcher_foreground.png | Bin 9793 -> 53914 bytes .../res/mipmap-xxhdpi/ic_launcher_round.png | Bin 10455 -> 14583 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin 9441 -> 22489 bytes .../mipmap-xxxhdpi/ic_launcher_foreground.png | Bin 15529 -> 89153 bytes .../res/mipmap-xxxhdpi/ic_launcher_round.png | Bin 15916 -> 22489 bytes .../res/values/ic_launcher_background.xml | 4 +- opennow-stable/src/renderer/src/App.tsx | 3 + .../renderer/src/components/StreamView.tsx | 364 +++++++++++++++++- .../src/renderer/src/gfn/webrtcClient.ts | 51 +++ opennow-stable/src/renderer/src/styles.css | 190 ++++++++- 20 files changed, 603 insertions(+), 9 deletions(-) diff --git a/opennow-stable/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/opennow-stable/android/app/src/main/res/mipmap-hdpi/ic_launcher.png index c023e50595074292c7361183a64de08cf9686c9c..5f72501498e47ca0e0876ac37765ffdf94db3d22 100644 GIT binary patch literal 5984 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 diff --git a/opennow-stable/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png b/opennow-stable/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png index 2127973b2d318df7085734d236d0ec649a2b0292..bf9ca94a0f81246f894612255f4af22bb1ed62d4 100644 GIT binary patch literal 17623 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 delta 1855 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 diff --git a/opennow-stable/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/opennow-stable/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png index 9502e47a2c575c50c925b987f397bc5244c57b90..bc2ad4f20142f621d867a942e2852151865d4fee 100644 GIT binary patch literal 3972 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 delta 2718 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¥I^?%$)-0Yc%l0)<5DAk$557wkZv1hZ8R((z zLs7aRU7ooeb6QtB9|op}U0kMlf`X$4UhP(+UN|k7~~@!PIrR#p>1+c zO4tom5G71EWYsIV`ISu<6+zcww4*+0Hy(*kAyd5X^_LFNQTFaF4C4`qe!Mx;{lad? zMFG3w2g!U>HXVER1WAg)8@r=#C^Vrz_D$9q+;b_uS!#=v$brz;-0oPl78Ct@#bW%b`Ihl=Sw%S=Z!GrFqw3oo67I($@>*)qz9AH{#; zaF}Mh`^C1YQ04}X!>yvH*JJ#}@yrabXilf2DwF>Zv zi(YW>X}N+P=)gy2r3Np(D)J^#qYw8%zpKH9VY-rBpnajh`l%!5O(M&j%bU<$~t3q%J-a}y?*1K zjcLp8L#J=N=c}mFoV?#AzFu6M8)%#iY?SEfc;pqiw5zlQt*H>jKEl9Tn;@kukks(I zZ&KoDBGj#0t#eOA`Ps+tFsiD^f{wY|_-C)|NpV4u!CLLMcbQ?ETPnlOZQ{dYbbj}8 zZW}+bn?9s`emcx<%_Zwi@oIy>0XK=5C}*aOgeHkqqXzCVeEvN^$Vt-PH~Z8la%gru z$E49}jODoQ7FUIH{bCpe$bWzLA(d;3Mcu@w3XP&x@sxnpA3v16n*-{kSX5J6nt3#6 z)`D=$?XqyGxtwS}jTZ(b9D+@R**1MOqJ>P)r8lt%6QqF$M$eGqgj#apkB2>jXv~AH ziO7WYM)OR8yPTXa4jRnIoJQ&zjq=C^AnZqE-iP6A7$;cU7msU@qn#P>({i%?*G+NC z?C!1Gs$UK3T265#OU2!VB^voBB-U1z4(1vu0{Y-ol#i)|sX!SdWXhl+Ul4CUJN(p_0p!1PO%v}BD|iETPtyG+9n)Y8 zMX@V$LR{YSJlXfvBz%vTm}c~j9ceWrE$Ew$@2+rO#tft{ePmoQIG;AJlSD1Be;P_y z*m0ZdT(T5<0KEXm&WZ6SHE*t8z!@5?43kY_EqJfD~{vr8o*R|v`8g6V# zLfY=&C`L#au~VE^jq3yDxn@rU zmR7QtT!^Lj8tb{M7w3in3%d!JrFgv(0Bw5rI{uU}{5!NB^3}1v9C-Na6vHtbmD)Qc zzWFyoNp1UTOI17<^GE{nbv;EYB=D8r%V(5hZx0^6_<qgjs~pUu;r#DOT&f8!T(Pvk%oRD$EC?kj$R<4B&B>(kf(p~ODHnuC zG}V-nRHFtLF3AZtAabOPP| zVs`G3Fr$t$JuoH3BMdr`_3JAGQ;JNB_|s5lQSpOY8^5p|umxpPtbs6yGE>V}No~Q+ zBQERh2{s$Z69P{ik!E?X|M|!$&uabV;v|Hf{;h}WIDQ94w8kSa% z(-`k}hie`@U)Q36=j}3MCa)Si1J3QeP}d=`p0Yx?jK24ur5oZxL${&&-yeV@#H@p* zPjVUgaW3Cnv-DjAF?j>Z5$|IYzaa<-2&f43G*%T{3!}61wLuf@Ay+N~4f%fz05bXj literal 3981 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 nm0GElTB(&OnKI&V600000NkvXXu0mjff+~0a diff --git a/opennow-stable/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png b/opennow-stable/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png index df0f15880bee46332dfc6622583215194f948b0f..1fe8ed0e8a105aee1519cadc9f3153e746f70eb0 100644 GIT binary patch literal 27323 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

Gog$kHF!N)HarchyA74K4 zA5cxU%XqrnZ3jekmi59HVdfCOn#cO~jh6c$x*Ne8NiG6{H!?Rc6(GXD_xBg#quXZQ zC6y8aGqnWaXF1s`qQ7$$iFG-%w>}k31FR3_{iUzD=yLFCC=#pv$8&wt*L*lt2G#_m zR$tK3znSYz0fBFg zZ6wTOOTnft3+Bt8ON$nzBCsqJgGPx|N&UXDCnn5ICUynh8z{BL%_E*KXt&298 z_#hJz!HEP;M4UDQP6o!MF{nXNcDg zOLah&+0{{XLude20@fNz?gI+AV49w+F$b;;NnLNL<+PU@1$|d=^h+*odK?a+z)z0y znEtv24p9~wgXcH?{lLR>m*0C{+Pk2~iv<-a0qs}&b^Qw8@nxT0(b}ddYY=F^+QiZb zL_C)o3_W^0dd{i*E!N&Z)`%uJEa-cg&UG$m$#j)Si~U8u@Ah4?z}~jL4$`Hi`5^7H zhA67fs1Ce$J;DsD5b?JUkaEyI7*}*QtlRPdN5wV`W!X7?r34wsjP9r>ZQ&cJUqO0z z6+${xW^4juv|u_Q+|D@47jQUPJVoq)jAm2}{)ZYHS>x%gu&-58tV$%GqL^pHjq^XG z{U(PqCt$G*o627|Oo!rh9GJ>wX-5TP6MhV{wCtx@_6&B7kMvS%xa95?u$iP5PU0ZH z`P8Py6Z{`9_##@?@L5q;s>iy4fxv?@k5_)Mb?Dva?97otblNpm6)1EG2}5mNpJ`jH z77${uY5<6xCdbTd*FEheE~6078o4*YrBc6%nzSL!J2qd;GIJOG0{pyv%FGi=s0<|K z3-c6CL~|B@MJ#5ERz1{c>Fj>XMhq{z2Y;!-JH>fje}lHd$#xx?k)7b&vB>O-MXXLeSo zyuPR|)C@3#YdvWVlsL&UT0Z(PusWV(WJiVRqlB1TzvXmm%yF zVZx5q5-aZZ^G}y|Ln_aQuU$4OhlGJlDl1y{*OmO;uIt;0dlut^k+R>KaU7r$2_aFU zM}Mqzf(4x>vQ`(>Q%!|c)~3~+Ix}LJ*+O@eMPjEf;@ApZ4~Syr%WbhJNE>Etnabmk z<+s!|xOolBcQZMcWbwwfGvpYt@Vp9J7C@7!my(LIE*q`X86AfsE5|>KTZJ_rt%n53 zJc+H+1iwmjyUJ$@o74D*Ru|RVWKgHwpe?x=pOwz9$r_-qPA4s0`DcE|8ITq zc%?l(h(-d*lyDC&(Hr0W*xhkuv<(s}s`;MYJV$>aZlK9bZ7o!kzvvbYZ@Aw406o{Z zw0nl_&A+FpYWnXJgz>XA|A4LM4-4Bb4&BftrvL6mZT^Zsfph-xU$yTiIHd)14?90Q z*PL%VJ59e;@Zm@WTls3@%_~I8tC=u1Ekt zF)%izUgNF~^NCK)rPiUqiCSzc66+HY0hjFep*@JVLjruU^Ozz50lrbQ;zY84F=1?! z(wSN;i_$NB`au0reO-Vt`tWrA|1zZoCnmf*35)>cecX;Y{rE1Wy#f!#bm&8&;WwfL z$~>uHmm=?8lsL*}SfLzRlP2qhJPq9%@eC^zQ9hby5tUwRn?H#bG=H~dw%k&!=J?y)U;R&T6ZT8@=dJrp&UK$o7W zeD@5+PYBH4LEzEl?|*W)z4%L$+sY^9DhO$#0`5$w8(sC(MMZ9A2E8{>jSMGXq;wie zrob%tBA6#^%2sp?_@nrW0Vgp5`5#l~I}3E@UF#Z}G70D_*kv6y?N54=-acGHJdG1> z;)19yS6&Upc*j?MB1WiCA⁼!BF@8%c(ByQj^k61X=e%|A%^w>cDv&Xt{!g-%lWMdJ_^Nx1ca1jJ6Cem^TZN%RlTeA?Ic0x+(yT!*vQ zt0YXRLMI*NIpskq=aXHj-LoBmkAlpa#P|4d4|wW@3+qu7dN&+wEx^2+d~%B`I=On9 z0%@AM3|%`b=CxBUCAjJEDiX}$#J@0jAln=S-)b&HCH`f|aHSLYx;)b7;Fe^0)enOo z(}u|khzbVsuBd>FFJ>aD>zH+DeKDw6ty%f$v9q8elk-0J2*NoBgk<`=j-B`bQ|G&# zY%yLuWQzwytGk5~#_eRsEt0e20o6{7cuX7Ug=ydx3~-9Bu6UPCKn?E05mt+fF<6Z$ z&J}j01Er;b3~~t}f?2 z6XEv1T0(Tr`&syc2}i;BADVE4VChz}@@L;ln2IN)!u!vH>4gVu?cl&?1ZP*i8`S=C;0qX8JvD<>`E)L}S#edYF9f3j%NH;YH46CPpD!v3Gr`Fy^hSzFn@++NSiu~7B{_X9OM}M^RDx=hkae@1XIpbBCm9QQ)iV(WXGcH z*QG&Dn?Kg6)~l-}9)EVJGLTj-R)OCe(<-FzC?<;H*v(p-aeoMQ>l}Etz0v8vnas z1<@MdCG961%sG*3zw*Iwqrt1GNOK@HUN@l^78a$vE-&_jVQ#H)Z{9{^Y044kJy?v4 z*o#) j$HXC^5%_;NSTf?B(N%_@bW>#hZ?&3|mSWXg%h3M=K8Ft& literal 5036 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¥I^?%$)-0Yc%l0)<5DAk$557wkZv1hZ8R((z zLs7aRU7ooeb6QtB9|op}U0kMlf`X$4UhP(+UN|k7~~@!PIrR#p>1+c zO4tom5G71EWYsIV`ISu<6+zcww4*+0Hy(*kAyd5X^_LFNQTFaF4C4`qe!Mx;{lad? zMFG3w2g!U>HXVER1WAg)8@r=#C^Vrz_D$9q+;b_uS!#=v$brz;-0oPl78Ct@#bW%b`Ihl=Sw%S=Z!GrFqw3oo67I($@>*)qz9AH{#; zaF}Mh`^C1YQ04}X!>yvH*JJ#}@yrabXilf2DwF>Zv zi(YW>X}N+P=)gy2r3Np(D)J^#qYw8%zpKH9VY-rBpnajh`l%!5O(M&j%bU<$~t3q%J-a}y?*1K zjcLp8L#J=N=c}mFoV?#AzFu6M8)%#iY?SEfc;pqiw5zlQt*H>jKEl9Tn;@kukks(I zZ&KoDBGj#0t#eOA`Ps+tFsiD^f{wY|_-C)|NpV4u!CLLMcbQ?ETPnlOZQ{dYbbj}8 zZW}+bn?9s`emcx<%_Zwi@oIy>0XK=5C}*aOgeHkqqXzCVeEvN^$Vt-PH~Z8la%gru z$E49}jODoQ7FUIH{bCpe$bWzLA(d;3Mcu@w3XP&x@sxnpA3v16n*-{kSX5J6nt3#6 z)`D=$?XqyGxtwS}jTZ(b9D+@R**1MOqJ>P)r8lt%6QqF$M$eGqgj#apkB2>jXv~AH ziO7WYM)OR8yPTXa4jRnIoJQ&zjq=C^AnZqE-iP6A7$;cU7msU@qn#P>({i%?*G+NC z?C!1Gs$UK3T265#OU2!VB^voBB-U1z4(1vu0{Y-ol#i)|sX!SdWXhl+Ul4CUJN(p_0p!1PO%v}BD|iETPtyG+9n)Y8 zMX@V$LR{YSJlXfvBz%vTm}c~j9ceWrE$Ew$@2+rO#tft{ePmoQIG;AJlSD1Be;P_y z*m0ZdT(T5<0KEXm&WZ6SHE*t8z!@5?43kY_EqJfD~{vr8o*R|v`8g6V# zLfY=&C`L#au~VE^jq3yDxn@rU zmR7QtT!^Lj8tb{M7w3in3%d!JrFgv(0Bw5rI{uU}{5!NB^3}1v9C-Na6vHtbmD)Qc zzWFyoNp1UTOI17<^GE{nbv;EYB=D8r%V(5hZx0^6_<qgjs~pUu;r#DOT&f8!T(Pvk%oRD$EC?kj$R<4B&B>(kf(p~ODHnuC zG}V-nRHFtLF3AZtAabOPP| zVs`G3Fr$t$JuoH3BMdr`_3JAGQ;JNB_|s5lQSpOY8^5p|umxpPtbs6yGE>V}No~Q+ zBQERh2{s$Z69P{ik!E?X|M|!$&uabV;v|Hf{;h}WIDQ94w8kSa% z(-`k}hie`@U)Q36=j}3MCa)Si1J3QeP}d=`p0Yx?jK24ur5oZxL${&&-yeV@#H@p* zPjVUgaW3Cnv-DjAF?j>Z5$|IYzaa<-2&f43G*%T{3!}61wLuf@Ay+N~4f%fz05bXj literal 6593 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 diff --git a/opennow-stable/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/opennow-stable/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png index 6cdf97c1196d48e9833487ff6de7c4cfc4e1232d..434bb7093a6255401441086041dad9c4d378be0c 100644 GIT binary patch literal 14583 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 literal 6644 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 diff --git a/opennow-stable/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png b/opennow-stable/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png index 2960cbb6104b915c84760f889deed9bff2b3e17a..431271dd2f42b77a68401197f2a1222187fc6af0 100644 GIT binary patch literal 53914 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 literal 10455 zcmV;|C@9y7P)+A7-qze9UP%f&tx zt#U=BWl)qMU`S*X5(p#=2@paULlOdnOlO|G% z8E87|0fzj4AZZgwn?~A8q{xHtz`#49{Id@S5tm8Kgswla{GcOLt#M; z7(oFP1`yF`^AamWKqL|n8F_z90j>!7i~uV}C{YQhlcX&o?LOrV&|#IF2TzO6rGoYa z(hdVCZf{Tocw+Lw0AmU)T1^0m{H8!8e~!Et;2{8vF+kCCQ-bL*y@p}xo1|mJodeE9 z(*8-BS5mh`qqsZ)0-i{O-uug-s_b#RIAsb6iiC0^U`aY*a0NIz)@1wzmv8} zdHa&VjJQ00AwVd?Dd3m|kz{!Q9)HltcQVVQyewSfclG+A<1nUk;@ZINkK98#I9nx# ziM|kGO>V!KD)7YVED4A_gi6s&es@d*NVw*ERa&n@A0+{gQdDNbtV7p8-zc<=7>NiX zz!MCm4m?IIk=vt7TV`5BC6qvInOc3+acEc_JSUy_2lD7*Js1o{1n3+92hEjY%cBV* ze<%(jg|CutqlNJHx=p5II3H*u2@g!Sd8M`oxANpGX8yn*)e}sGgipU4xgW<GR>F?NC`Am1iSsoY`U;aZ`N zD?SCmo)cg^O8#zASe=+AcvQ3n5CKpr7%<%i%JL`#vr-c|{M#{wHEIflLXT+g z{K3%tL{>-XZE0y9{13oNwIu>T+&Xa{uPrwV1Emihr6qEC{3+8!O4hLWJ4pkR_6I80|CF zYYap+RaI5vE^81m6G|@TR`UE370Y40PJz|ARPQxJTL~?Zi!X>0WYtYrB7Pv!usoU| zA{M{y^y$;LUzT*Hpe@YVIhPDP5o&o5Bs4=4dLZHvC*ql&;6-O~%cBpT79jHZd^Lv; zAHKZkjJc6bO-1pJGKT8H4bc#!|JR$wNjR&34EWXjZ+{-_!Zp#u`usp3m6p2K{ z%F1(DWNbRA#;V;>SDMEc_zSEDO-+bagM^Z>PBEQH=?QPp@pw|RB{CZI4%z&@aHPJ$ zEml`oFTfbJJ1S!;p8(?_$pZ*Q5Fw6fnQAlhdE^cZ+NP6Wk~mR3&f^QFEG5!xiG;-9 zv3X8%C?OzaJv<(dc>MVBDecNLV`wHki$GyL70p8PN(P~|U=D`FV>cl8Ogj|)&ds z77j;)pXN1&*>cdO~91S-;re;YwSY^NBE4_4V~)QBl#iF^1c>Z|~Ap)YXZY z#XWj+dX#Y<3_8SfDzoBxZR4q^`1F>jxa5!^2EuI*9zQvUkB>&hAFqpwD~=Elgq-#6 z7?lyPY(E*p^psN>qb_n1v-PMe5|8sJW)fNqq$Q#=Gk0q+5*4?djfzigii%TnqT)|; zqvEnsLL0%h0}lYajDY4R>!ae2)h~YMv9t%LPEsu(m zvt;nF221o=nf$tg5pJoP$b}0R8aHg%a3cj#r&MX5PUK|Y*P^aO(@>R`h}YB$w*fCI zLco!8Ix7Brb5wkS0A^aQ0z@0-|9x=SI(1m3t>wh>JVLm^$v(GvR#xeBFd#NQkP1b38p^AkO3CNN0)C9wBlUZ?7blXDb29 z7cy8{fr!%C3Zg?iq10F&famcIGI&^10tgMX1`z34B0Jzw3hLV0+9(my&I@X4;yMwx zeJx@YfnX$}we-deZ@WBvGTwS|qOF9se!VR!PX9t~i9j@iytb4Ktdn#GZL^Nh){nDf zEA!CW#2~_ZKxb-A#Onrx6$%D}VtILa4q`)&(HOHnjg5`>QR<4ZnS}B5M8M)qLXUkq z6Ifvb3ZgK%Yd2L8Z;OEEr<>$v1VqzwWe|Bo4$)RA5z54}JiJZ@M=KDmk(*i*L0B`2 zo3NhK!SG$7r)WVr?1qjJ79&%%E~r7 zVuhIXsjI7-pbQ!+XA;^05Cc&YED?teDLLmC=j;%~CpXIgY5}4znn5%@i6(-ujtG3f zvzpM>qr~z&k|hJkD2UXSsIbD3#RHNSI)DDWn46n>A9pLnJg;y#yjW>{Sb9Q=`GC#> zd=j2k?=ChCwTV#K7Zrl|D`J5(L1d85@V{jc)|CxDPq`s5-aBJTSYJGrWH5Ad0V1r=HG+Q?dq9f@p>Yh^8kI z*2@Wqf?;dmSwk$()a+*P!~tXiM30i!mK~NgloJ|A85cTx_H5Jp@4r6^W4>zDs?NNk z&Yiqo@9!k=5bKjD&V$!{9Oz7n6PaDBu8IfY^BYe`ZCfHnXJ(?q80=4v5$!@;^~vky z_T%*`Ag$8?(Ylr(!fR`eIp>8b4FHChI7wnbLBUHH^L_jFrSr&np>-jy`#zLzM@_;+ zS#>sl*B@|Z{*K->RFBRyRCGM^#;ky7ngT@24boYFSihCzz0)_!x@YowZ4hZ%A%!JE zoCxtE2jf7kXbjU|j~zR9h>Ur68l6tFt$k{1YbQxF{3T$7V@A*{$As)!q9CQSB(#+z zmV~%Y7NN6W8lba8AOf916D5ihVX)VqkZJ4D4Ya92l%)+KC6FMP0Um$YSS*bbh$Jz6 z;lc$mJ3IS+jJ+)}O-)#5LSG9II7F#AbHP17$2rY{tvSq~GgzWua}d^gX%7tcC&X2s zk}Xr$V;hWtNDU;!iI5{RlM8ckqBGDKroI*x6}^kGw@hP5NUdQq0ZzytTc$BaUnfsi+!qW<72qw4GqdxclXZ~CMn)f&DC?9lO_b0( z%WY13NFLt_IWhZ_Y#BgG5It%TM0o9!qseK@X%MlPP*zsf|FTSD^g~_h8k+tui~ZP9 z_&n&$LptbCjbCiCxz-$mzUi!e?+j^=j|hnVRVqIRb)mHakpVh`#r^va77+~eFim4D?{)Ct!5fh?rSui!adB4T zMBA#P;@xzFVg;XT#EHxX8$n%UCMIUrc|)A;I2RRvN5J!&opJ++W)l$QRtS*a~GklKNLj8-{#3p2_jgctyT8t?*K%wL{Hn)L{l{Yqy&-DGXrg{ zDCKW?tO{#3&zwz%fewN@ziZd7{|_t})dP;*f!e?m(H+WI{K z&&>R00BM0JyCP~ki;vGk6B&vVzIMJ>P z#M{~%6`$Efn+Aw}qXN-f^1f|V_AQZ=_Bg2uHg2+Mi70^ZzmJbPPg`a{q_;g4w$lRp zR99C=KKS5+ZvhkUz4uZ&FadEgX54j7r6T$ok0-jk!G|$?V7({AI zG>g)iT}{L*?V$wG^c*=ymTJqBh|Ut#8=%?w7=-ld)vKQZCJYH_3ZSlab#>3Pxj(76 zFwC+$dNCmWv4~L8ZVDg^Ac7{^#(~cC(jHb^e8h?Vc_i8{R>88O7g%ndC=~<%!FDt? zHHn)yZ+;D!Fa#j_rfx2m>uo0mv{qIfYt=tJMO^khGKgkd1QF3v#=fNGt6zV^jNC?O}SK4_YqIfOjT@LLsrRun?2&ds1v9KED0!Z{tlp1A)L^ z2xuoMOm9nVFV;>GmwK*A5dB7n&O#2QJFD3`UL?4Qcv_#ei zZd#X7qek@&hr?w~1IRoL1)ieu|#6->cB9SVmVnE5Jp(-b6t>;8%n=9=LYgn?)RMsx+DWo`kQaQGlG0kol^kPqAlGE!^#G7=l`z2 zrm&`TX7|nyB};pJVSKd*=*&sa%*ggsNkAk4==AB+4bMFD%x%Di5dd}l@WT&pCST@p zB8X_ECL!nyAo~4Y1&DUF1kp@`nrI`(w1=*+{=!(WaXO{5VAwg@GFvWBNoOpWSW!{o z{nMZRbf;kek;k!aZ!kbtU&Of5mc`v`e3Z_fY?%s;sOGzVgZ|_W&CS0YpR9@b|})FAB+JQ$jIbaUQ#sIHa{!r?ly8R$HY#c&zrI zD_|o6FDq| zGaF?Wp9$+(7G3;VdCsOiOvj0G_!PO~Q4U$5Rb$XkXV0Du8v+nDPu-R-T{?~c$WPt) znAOUtGHr#VyMgCgZZD-XyAf-r(;ij|I;dBBSgISzZ*Q_#AQ%zL%1;L7&6@`b>-LLZ z{31OmfZl!g-CM~QxS1Dbb+;H^^$_(mh%!#3Wr=1Q^v*W(N_(8-6Ku3nn_6pdiB*;ZzLbSq;%uWfGD1xaCqZcX%%QiVmfO9qI_*SGnbn4Wp`f1bt&+SP8#AYHs`Q($=heDxNlgZc=fJ7h?*sjH%)NFmt z(jLESM`@3ZXY5Z(n~|G5?ZIr zObn#hNI0!EjhHCB>6(UyhINUibEqwm)BB_w4K_+?j|6l!(?p!esns4>AXLT-TX-hRDQCixwapOjmy}O!XBjL)7v^jI;U@2?A^78T*l1*u4 zBJNVX$0;ws+V%lVR2SHzvss+tL`l;g28A^?h`}yH*s3Z;0E%K)pHDvdJ0*))sqc-lh;L{D#(H;Rc{v=H6WJR&#=pcst-1)qEFx$grLGiJ=_o)kdT z&+m2bz4s0y0_u#~69Z7Bc_Ut}8EkC>B3Pb{1U&PKWa^qr+Z+uLS&dkyEbXBZ*4Q9s zyGD>x+S1(Z9Eg|;UtC;VJ#O4M#DIF;dFP$!$pD0-b4Er+FY=ht*x0z40!T0#=Sel4 zNqc~ui;BN5B;eUgn;wXETUaub=TO?iz-kX{5QANYlJ5a4IO&05Y4g_x4<6i;?X#Nf z=rnoqX&PqseK7A6LfQA=buB zEKp1s0#Mom4?F-N-EZ#Pxpzb&k$S3mqE=4C?Er`vZ9PZ9qilvjRA4_k(^V99f{ zC4%MITw!NRbAek9thBVWY1*`D-vkzD5YbSTvNVXL{{8#+CC`VPKVQ28)D@Ao25Y;W zmX+YiC3pWH_Y-%$NNz0vlmtY~JH!9%P6gqa_Q*XgNE^g_SrygIeI@-KLT60`L}B}u zC<^_vdGj`uxVr&ZFe;$qLVDuFiG9f9pndy_=VNA~o%Lb7=uEOaH3U2dWb4BKWEMn- z6Cs1YI#Jpq-{5>A4rvcT+V(pr7FYYFLZbHSYKLvbiC6&f!i8FK$%ji9!Up1Yk+49p{;rQW$>_;5JZKoL4?0SfA~JO+Jj5l z!^Ub4mQ@#`e4LLUrL%|y5F!2(3Jc=FlB2?lFTOYx7$EdzSU|^VY}BYx&_P#|mPyoj z36E8(RzZZp{(=bR|2#-Mu6=TggQ%z_h?GE5TcQ_=WUnnG=&$y$S{1}f+CytTPlW9? z!U0507KAnVT(rK?L)`bB$H>@YH|MJ<7EBczmo`|LG-=W`&_PFz99hU~nX{E5o7*XE zJ-?qe4G=w-gwF6hr!uNpl#{LYn7haR;zcuQ551+`yo$3!ST~sv)-vb<(c0Qe;<9DS zmSF7fx#u2KtM6hKKuR5S-J5T|`2Z2oAzlj&jSA}kwLC8#kg03l{+1wmE`cTby#h#x z6G1zLgv43=tTTL;Q5#w9k!;alv$eLDqz)lYWFYM!d2vlX)Dy!}<}mTVAH&#N(LZq= zgc)dk`t-RLGYN9%iSdqGmKY{>$@Z@QLPm;egx{ zfk+J`1|U4&Ty0L5s8@TKO2Dep9-B1cM2RYr=y_<#s@d9!6S2fBridVBjNsur@4Pb~ zV?JTR1OO=A3Vp?CY|NN3P~g`QB|g5Xsp&lLf(vR(6c^0J&EQE2qW!Hc5iAe$wyb!3 zSrz6NFKW?QPKB)F1RHah}$Fgb|kY0w!2cdpIMd3?18hluso zN$Wbb_>!jLp&LWXN1IhkKnTcA)l63@J^UAq>O=SR@7?qQd{ zT8L?)g&?MfzWVB`KXSX>5uPr+GPnrWJ(p^r79dJOXFO=j&T0=W5MhHDWttA zR;|j#*wQg(lgGFKh>7X0Lx&E96}sWKzy0k4b#-+IWZQA{-chtMw|$*2U56wK(e$4zysP!Hj@xk=H{@LF1~e^ z-i@deiDsS`w)kGUbSXS9;wz29rYgO7iDylho+9*yyU0;lS$U4u(u+DZwF8z2bf(rs z_#45-P#dg-g{E11T4)s~!Ui$eWyp9HupqZR-!-;tiVJ0(th}^rIX^%D!uavyQ9SB~ z!Gi}6;NiL_bm@Umiqw%SSFU^k>RtBgoz2GQD(DQ4UsSj4#w92MwT^&@3F|-Xk-=kz zN`)xDdICy1lPdmWa+zCuav7bn8a;XPq_|+gg1=xaowhzLv=CDKJ$m%Go;==MQc|*$ zQdz{w`9J|W9|)EQkAXJc^@ag^)k#5ou}Iz=&xwNTRyOgImYeG&P$_jqaO1CEzrK)+ z;VpD5uXaNF=z3(CnVEwSGx+(>fBqj;RaJhf?xRl5NJK0J!A6%i)aKw}t-%u%OE1_@ zGjP~xS=MO5P<$sIz3HlWEG#SxOp%522&X)+L{5pfdyo8(lt0I3rG^-W{7wS3Q3GxcK+K z|NU6mu9Dg_6#LQ)-}e*OBP1pckNckkYUN)Ae|jMu6R1|Al}h<|Szf=Fv= zH)tck0Yp~fL~>T$*FrD@M6BqAGT*g&_3Au~86CU+bSzV1eOd|X0RslW{EZwtcI-W6 zWo6ZvPa@alR--(GXe zEw}s|#*B>J;8Y0bWP-XMqq3J@e)&n_+D9qPM4bXpD+`xG5HZ@)8(ds_D(Ot7Er2JI zDD4pq5LzoPE{@KbGw0VBE24W~efp(BI47erB;BqZI&|nLn8oGGm;d$Tsk2yK60?&l zlfYwOc?$1!XJ%;2%tpf2EKy=QGqU=EX4+#1iVukk7yj+<7$Z7X*D4aGX;-z;5vMXt zKXtgO#hUA%bFa;_|y<77K6_yCsU`G=rN_((rsCt%1se39a zD#VXI`e;4IhK|v7ZAo2vRMw|w&z^(nQjoEPYq!_c)kzm%#qyY4)8wQj@>-13;2L-c zYjvEcnYM(a;6Z_?RjXFzlQBV^=No(U=z&yJpSGkfEi2TChQO~T$1rd#Y2$b8+O;16 zD+I2LSQDePm8|GCPfKLClrC>N3mBs)ij!p&DDx@McP&E z^VEnDBPL-i=$Q0x54tCr9zsNO02OMtOq@9JJ_4fC%o6Eq9)5+AWDo^ySt6e4h4^AY z8*~<=S#^kby#ilK@Z{#^p1td?yZ#+xK*j>HVgMbRF6|LKEoLuLfi{qNW&lxsetx-@ zCgKgAmUJeANU-8&THKCvMrYWk2ShP!PqO0#B=o?j|e|BDWr|a|P2`oXDsp(u?y*`;ka-B6({{ z^eNVKtzNylWccvm-=yHVk$POcQ<IuQGi zMH9K9JS~wC5b>t1MCSxh&@Dwxr6<&r(hwv>oaglE)8fjND|eDU{vYUT+UFT`4AR@1 zXg2DZb)^?DXuyC0xS(6f1&&{_@{>;w9X=|C!(qu9IbZXbf+&Ho<|UZTxcG@C#_Odg z)RYAf?mti>E?KfCDS%j(-77ytFBj(J`NtgA1g_P`Sag+3w?^drG1=nxr0XwMBw3p-Me=m-oJnU zG35EU*|TT=EH5vw5>ac+ki%31C#{jz=4?*v^k*kdlqfyH=3Jq#pd~kL+Eo4Y(@*~j z;6a~~z8ygYbMN*PDCDV$dQo@shCzb{0YqaFr&zOQ%~s4&!BQbTSD(Kn3byI?R9bN& z09h|R!CZ7amX(!Z3G$bjnVH{0A6|d`^|zrPlMGMEz;a`C090XhVhDre=jVIhc;k(Q z=ri;ky%DdcecJO%1dmp*5z$aoKO5YqPoJBvx#pU&FvAZ$^w9s#%F4_1FJv=gyr~aQA6VA}MafBh8_tEr&O(HN4zdqAeEDr{O+RfU32=U#sK`TV=z{q92=R%a0Hs~%Un-Z5*9 zy3yDLJc*&*x^=thy6dhR2X`NxICbjO$5*agxseEMAIv&*0feOydh_~|msUxoC6XqC zx%{z6L|Wk|tq?tT?i^w|zGcgn_<~WQd17XYZS&evn*oN=6V3@~iQ2j*v9hXKJb3V+ z59j{pKmYkJ0|ySA#4HZ35!XtAGl=#MT_3c$;l}xE-nthd%Jk4UIGF!PH{ldRhiIEF{Ymc&4{ltOQie``khfFU?`X+ zOLMleO59aY7|71vSb}qX_~C~i$GOvZjzm?|;$+fm?N6`0o5DTs01pQsNfrsZfC$U6 z#4`c4N%V$H^y7~|{=|ZXe|!7mRiEzKy?ggX#FQ{E7*q$Xp*Yw;3kp#lWgs9{D~e3F z#}|nIPx(6CKSZG7H_E;gU;tfXuU?b?*S{`&o9MWol5@O^o-4en+i?w4 z<1mZEfYZGLIQ)Usop$aube;=@&;KN$I~N8Pln0Loz`}w%TK7>2Fv)sBfFtAG{J)s=UM!%*XR$3d1n{X-r?BqI zh2Ow$;Wy{ZnKNt5m@(g{mImiE9_NU2#W~~L=`~zOuc^c0qzFh|Y1qCm^-R7-b3r2+ zm=u;N4k*&T@tyB{=SQ<=&z?Dd{`}XMELpO2#flZ#>({R@*t&IV>CT-y&lD6CR1-J4 zmVlxD(4j+(hYlTX+_QII{qBOI+P!=CR_EpAo!+)>Tj_=k8wx)D_~UGR$Lp`ZJ|EwS z@9xs2%RThB?x4RdSsDdsM$&Wr8a?-Z^jf-h04KFT>P$TnW|jIWz=Yh;a6%2Ei734d zgGU~jZc>Bl>(oNrg~1;(WXOHQYTQ3z!h|1Anl$M_G&~SeU1yfHNc)Oa4(}7f|4xtud7#(bA zk&zgDSPTGxwp(etg@R)=1;|MHnc?(1uBYEQi2g=@`kQ^|Idp*LG6hp-I%w%soc5qG zmEKf8F<@OwsbwG)v>6l(%9cT28%W=KtpX^0>38;`ztN5UW)~Gbb%5qF2b2<23|L+1 zfOn^Z--B8Wt;SyOPCwIC0Td-zIso$(0hJnDom4rX>LdOm6_IwC)J z2sYx%;s8KhJlee(;`2F`g`9>m0N}>}06@Y3fZJylWCsB7I-aL}5t}>0%))B`zmntEQ`Bu5Ll) z>0#wAtSv6BCeGn4r|qClW$td~Y$+`9hr{V8$Ia&e02sKqgIzqH^&lkx0Dnc#!Ntju z2>crjgo6j<{TH8;gCh_4&v^3S{^3(s9{fM)XI%h>H_@!m-3wPa{b${neSaD-g$0xJ z*$$VTmL6D7SxL~s#fja_(#710-N(uG4+@My$AWi`R0T2flh>MHuS%S^O*BNZ)!{+Qk`!^;3rANxj!@}Lp6>R6?O!Y^v znYoK6SeS<9kD-5TfAiDI$L^n&oIU;?)^mWMKO-Pcb`H>g2YU|oAO8It%E!$0e*}T; ztp5jFe@6aCn5D%(Ou2fxJN}gjOAC;dqm`4DGuY!9#|ipJ{LkSD{qbB-(#6rmUDMUf z!b*fw=&xY@mG#d|{7qWT&d178Ps;9DqsMdBL^ydlIR1|M&!PW>N z4*OU3e?nv&%{*+M_5K6)T%do4{pZksLjUqc|9^J$Uxxk@D(T|n>f-z-Ws)w=)^;|Y z?q+`~Y+oU|F`7g-7^8Qm^@1JHw1YZ9g@UP7O1nB>FfPZEF3&7Gs z5Nro_wEFi#_-l^E9l`(3{bzanxqS&bnmOAD)A+DiT3MTUI)Z6Lw4MJ_Wl3de3>rHvUh_>;G@+Z|Hxy%l_rV-?-2B za1qq!3i+?+fe300lbaI&AO?_^64&wp9=5+|w${}@Zt1wW8&xa$rNx}0!0eF-`B1jeL=m2dxH}!@5sF{TH@d6C&H#RwI0p-Hd9Jk72q-TQhQ;W( z<;%IWn0a%{xq~d8f}gyPHSre~?4NmcGXg8i4mFn@#|C#sPu|M@hfSJ8><(1_Z~s5e zz$(#X7gHQ_VNL8_Vduj_#8|6HMEz6Nu)WT*N41+87kg{Ko6hEBe~6{xUBe2#h* zhAL$oGbzE>(55nDBZ2a`)MA5TV+ZYs!+G0$5t5M^nd#kr@%aqq5#;at!^f1A?EbbM z`xj1>cP;TFLdY(s0!hV=fU(4aJnP`WrfnzZ$}%I7g~JYe=&ZlE_xM6WW~g<0wnp)5 zg-~aD&#%2aWJNsX#ah!fuu7W(RE?mnQR&q_mac!wTjmFF@6Y=_ z-Q(-_Hxz*%7LPm_Nap}KTLnIcktScA_t!&3xg6Qr>gI^sET2S6cqiY&ot28d z%)G4dsNOL!J7ai=fG3}VFMn-GrJZk*25+P*rAw}jD^4VzvTy99>!8P5t6Tk!%WbK%XDh|#{7>XI+1%V6*RW78zwSGKGICp1*(KNv4jQGBCxi zhZ`gt;;=8{E)VXUc6dnpl~bo0crLjzcgtF~Dv;>-8e-E-H2Rd{F{;W!urfh@8EkIG zpT4JAcvWu4q*}3T6$S6y@V!;lUF+4f1Nm9lM{28v}sg74%t$-KjchSn6pz>?03PjvB z@Zc{OX@+Qz*jMHAg{WYR8o#rH=1#X-S#32?0OomXuV- zMZaa-_t>d3Xsn9vGIX^bC=^$G-)iEw6yr2}<&N%G{mkZ;es|11O$d zQQo?Z!D?T>m%UqfVp1OMEQN~rn=}Qr>noOIwFqT+(Y10SrLjtJm@ zzrF#cE~EDZi@FJyn3{;V(%r`o8V;&Ai@#5mH^F|(M(&cX1o4myjbGyJ6(FHp-rRms zA*l>JADIoh6L)tN5>zI&^ycAp{SC@>8!_~_Rh{0_S0^q_)x9#`_;m_?+#1%f(ZFgz zFl}Y~@oW6}^?-O=cA|5x!$TC?IzZIeXTt_JzaP+_YUP1rL`@iUN=Bk8_AAT^WKVgI zwxL(-JO|a(frfgtH+rnJp)18+u0>=VEo$2sb=*L|JNr2jmQlK}lXj`IP7nree*E%7 zSt&SRipVSMLJJ04*lu^!7Ch`H$KVMUzEa=$OqBL69by3Ke7WQ04B_POCmzD2LiYpI zaC>CpR5;*Un31IxG6^GTCfMQ|_hMhTy!1(CV2j`4rzVCPlv%SB!(LY>FZ%ffl<270 z#(dUQbRdjaniYQ9d+$8=dn@vDQpv`k6+FK}@lDK1a6hT{tam_w)~=@?$-&I0Lhzcl z!({X}58@1jS+5t#+!ie%qzJ-fo9fBW#LEER@F83xO}ygh!&9ua7HT()#xh7A#mLfI)Lkdn0DVHh}ACrH* z4&4C7-pO!kp8n)TG<6jQ3Ka{&-77sbc=1{?sYn6UI0+^~ySeRZyl$)8q7jqepNbBu zMKAui-CMXK8vh{Ogs@1_5RExKHZ>>)gOoF3nFu> zXi0&>fmQZq^WnOc$}B3?cE4nK%byem5!ZoCM(Hn0QGc_>bz`Ynm>QA{P#>XyitxY# ziL)VQB9KgHon3TSqc;PIkQ^R)y(jzpgRMLOy2BJ@kq5hNu_DN%ilDM4l-FTv``r|+1E`62A9HFd$;J! zyNhVwr8QMoZbnsVzLSCpYHsbXJdV?TTOHOm<&8J=v`hu>jYB&Gz)(@1b0{79cu z3z`$?1qvq2k%?`n#Tau)K*acA1>Z5WVKAe~pGNmmOc-08+N6qKmg`xT0*_UM)vHUb z9ME-s^W9Ie9d~SvjrgEbqE?ahdb@_{i{1qb`PX|7^;AS=uaU}DUAVKw>6_>O&^hWOtB$6P#Zxrn#}@D4qr32N zi?a*(Hz*yeE5@~6)A5zpH~pR-oqSn4kA_wOKE_QVS(Wxn!tHQkD=?Ccj!|P9S}7fE zquEknD-7Cj$*2&e>dIoYYQtjfPk|hawf$I9J}MNUt|pP0Y5c2kA$Z?b`J-t^@5!*v zdpC(BEJ&vD;F#IM3!`T{yA3s1-X+_&;ZX&T<0lr`Nltj0VW(4nQ~W(ZdqKqUdt&^j z^~ezZZU^#Je^&=*db&uhOYfVG+v=x%C>WRSdr<>L{9u-7zmiMy#pGzr?BV@xP{~t{ zb9=D8Dkw|q!Zg*_U)!S$%FCIZ62~J_ymBT(0&6Mey=EnXSAygqIxXo}?F;ZLopUdN zCo?SU`u#?dnJ~lQ$go3l=gDOs6w)cp@y!|$ICE9!agM8Bgt?pIIg81gP>5<7pT4-( z#tk)t|D3QZHGo`|#I??zkV8i4{*vTLIw4k1M6^(iq>+7ZU4R|xLaPi%(q!FwUOjga z_m)zbch|{Hy@u$(x!rF6*zuu}_(Qj3@+fEeX|QjqY|42}`|4Kj=`PmH_gm0md9;aE z8nh&{4Vv>XCCDZ%(v*@~RZ;T0K9j<{?02%)qA-vH(N<0GVr*JhN3@hZ0pl{00P7=q zGozK#(hC6d@{Tv|E44kWD18E(LOrQ)+P1bH(~FLp>Wnd6gDi3asXFx11Um-xJ#>sz z6j{v*aoTbon$wT3B*<|fk%^pQMxyViqs4g$?~@|ES|8uX7dyQz(Nv|rockqASk-ni zIrjKQQySrk5vLzFLOuE=yIz>g;I6fcE~-u6?Dltvs0R$mP)9mxwl=O+{4Hf^SL|-Xbcgb&E$_H zV)_;hRE#5MgUfq|3FQ|c>tr^rwYJ@lRSF%Gqa|YyfbB>%U+;|bvyT(&CNSqzu3!4V z#S`@a0@nD4C#5}DxPnUkF{%@KAw;x$N?Ma0jDB`smKjUSFQ+`-HL$mz+&pb{ zy!}Gq0fLduBDo$dj2V5Y4Z12p#zm_kFMEBwFMWP1rSQqPyy-f#y7CKgUwITFT`F=Y zi1tSwrkdJYcnu{u(`N31>%>?Tzn+_th;J>!mL@=!sEc^<)r761Xt?Me;_sis;M!w6 zW@T&y8Go@x4QdNiyM9L`PBj^*>!MM*>1($C0f*x(eTYyUe(hG?hdQV@+-6_^d~?e_wph^Sugqe{$Sm*8AaCVX%Jofw7MI zrOHUt`lhwuU5u5Tdpp6aP-c6dP@3B=U^t_ZB&#kiCpN~Nv^<~i%3FYm|@;drN;AU**#M=vw2P1T&A~1xdlKkgHD#J#|wJbW`I#X;PO-fSrr4sjtvdZwm5;!>R<2 z+qBD;5`{cjWG~lR3X^PVzy{yP*P6K@4%IEt-z#4CU*boaY>YWyUi%`tT?$z2PNgZ? zYFmswc=k#+HL!dsu!Sc8?l7iMZm}cOuQ&6+&DL%q+6pg5r?M-DfU*&}Ob`+|nQF#F z5+GSBn-yRKzl}PCjRg8ouyIcj8GDeoavxq>w)BB9Df*efDPrXC71y|O^YV~RBIk4@GQ9y@xcWN%B3Ym|l zvZ`gIpJ|i3CSz4+Q5Ac9f9)IqIR1^sGLR23Bi>D--qr3_U3R&Nr3q1eR>}X5#=lZ+HR)U5p?fGHVYADQjS-r*X@q4Hd>f0^3(_}>|&#hOg zty1e|u0$uEFL1wVrPm3m%)%)SjO&Y$?8JmSM9N9$1wZ}3KzM;IPprZxE85VKiZ7ZG zD$|)BBpn7}&f(H!Se?I-0yGNBW8c&w+$7%7A&+Q?ZALh(ByHio64{ORe^ufgsdSoI z2Z>>CMqCtAK9FZ@ob+ihgC~l;Wfbx{S!SX6{ga=959wrCH0apJv-~R2-hyA=O0;_G zg-xe9GcRxd?kFa2$50WHLHdvuT1X+s`_^eORCH85wXdu25b^iwC_?7$POnBwUqtt( z2(4jk8AMsVHI{!z_6UyXp~9Vf$P%C3WU)8iq8v{N7=JmauVqHI7+)P=5+<9QbBLq3 zmLB17kFr|cjQoPxK0IN2kqLfaL&Sn4#n4^3I_nMnkKgQvob6nnKPTOiU|$j3?shF+ zOh>w-Ja{aSKgQm-WW$1Ky!nLA_*^ox4FmMG9nOILWn;Mt8x@U);x0VuuIyqm06??@ zIny4K9{HT)I6G6XgB)v0i8v}Y>X2AfIGPlVCjTOo>D|&*gz=AGjNCMh=tO;y)LmBF z{NH;lTQzdh*xx#XS6F2wgtz0-fy-1)r5Z>!8W8o5WRX%2ub5(chACj_?qzwVSpD?;Smw`ceDr}6U`vF0`0eUt9Y8~isvYWOD7&PyM`YOQH>CejGMF2 zeugNWh)0`}BjwoIp)|5Hh-m`4>VVcrq2g@D*BIy zs~Y*o&`QZsE^x~fm#Of_;VGNVw`rfbmR!WQQ|({5M4m}~(;pxV^urm>Na5zA-`1QW zz=0Iwkl_42=LxvH^(wbZv;SCj}}&&ihGQdCiPWvC(fx4Po*#;dH~(E0fr(fzB870O~*uq|`dV(Eix<4X#7 zv9WgGoBFz?JbORt*y#_(*V;llT+Ij)E-aAj|Xl4(fm-Mz#3QHE*m`7*!sUpx;#BH9}6knL24 zhy0gHeMk(nhb84O2q$ejxOUJ5O>9SJo;I>6JC0v#_(GQ^*@R&)D61|;gBSX@4~!Z% zj%7ANRYDDn5EZ;5;eO%wx7vH4ewe*uBKy5ivTi|52;QQKe|X)F#yykA*rw?~Vt3A> zTQV=D%1g!~3?D{@L4e2 z;$!tjC}GeH#H(F4-IW9fFz1&W46UhxCx*a%ddK4g#5wxDA0zsP(LioI+O>w9Mve}L z4eJG=5xeBd=?+{)vYEV%rzr7k@p>u0&=Y=H`Yq};{N{l0%tf2j z73`O-ea?BKA;7M!c^MX-EuRh&<; zI;hI|OS#?jkhNgoMogm}%sucpFUJ~62s;3_3p3^@1WxVnBBvde9s4io*USYx{RWBN z<{^mEvV*T<=`Jtm+^1_yntY)m!Q!1W6{AYW1W|}L`4pjc8zVD)X9kM%F4OzH(JFz> zHcv+rKkgk#>`UUq!D)B znS9#1U&FkMA?qhFD75Ba^d}rD9Z9-4^6Fwc5ae$BI;4LcmBQZHQlJq~lppz2tMP91 z0n7z74gU&w-2?Z%<8@bPN)-+pQo<0YtFR#yUO?`38-)d)FQ$as@OlH|LIEGIhbLWH(T_hPn9btU}yPnfP{~_r1&26D8sT z%#Zo}cO!#4U61+~F1u;+=&WG&V|^Fl%dB~UhvRaN3+6*A;V0SIqTi@)6^jE1d3;{l zQB(76*top*WeQZ->^VYG0b!Gj!R~QJ39S`C>$&QL;! zT?UV116|G&9#KwGgK|tPLx_VLqX{$^{iwE8O^_tDS)fg0cVA>^UrQHw5N7`uBHM6#ndoKb(`NFW96Q`#& zwqwOz12@sY>gMSZP)M-CnS;n#Iht3A(Nk}Cs0XPvuYvtk6RMHmK1ip$Dpdqnaugk- z{Am)qH>u}RtNCAqZQ^nP~v>mXj4 z3MXN->XEWH+?Do#J^7p>Xlwb{kFr{s`Qv=iN>*0PyK~UQOax(lRCVDjt;xwo1uv1c zJ_i-mS~KmK`v6w0Va>bBNg&)h8Ppu)L!|Xi*~|O&09K(*KeJc?h}PQGD8 zL1v7a8j@~+>@H5?HAFN!HGnOplD{P(x)}|jM8dP6k!L@{a*>j$Vq;5>``mT)gSVav zMu`Ln9HdlV6qNydN#X$^iM8g$X$&lRj}^Uj3GCtaWW#sWR83=nWyc5juRUG~WiK?| zQM82E^ctOnaIa{aOx$^5L^EvvlCcY!#hpf$9scnOrdlGY0q% zEfja~zPjSZ+V2%pXTdfQ-5r)kv>w$`T$MF{i-4n0k{20s%oeMmtIR1Kn$P>4PIrbc zp)%*pzr=e-m=Z=Hg+2)QSN>OG1M(bF2dy`z~*i0o|0k;F-@iRej)%tyMe zmnps{ZCd^YFU8REV`3V?&b5m0z@aphsfQ0hVb;`2e+$>+yO+VR-Dphr3-b(|;2mbj zUfMdX{4f`6QrLCd7ScD!3)!YL+2k>XVqtWnT~n7d#V9F$FQ6=2lqj)`B(HgEU|=L~ z(!2|Fnp;*@#<-AW-aHNW>~!1z@g;a`m+PI46ZU-%meF<0(RH^dxppgg$8>Mwsv4-W zwuuUsQK?mGSKXT5YUml#;a+-%RC{|V-HW`c_350#|9-r|+NY66{dpBOrp8{dnqiBJ zyKib$Z6VDzIF|>Kn@uidV!=__=))P*g}j|Up~h#~d!AYxM;LF%F~Ydt(_-C=jS9d$ z>S+Ji(3ywk1CJlh;D&>PzQZYbM^quRDbYba?d#h(m?6BJ~ zbR%_c(qO|=Riqw!PvYRH9-Qxo`mY~4-hG&XGwvcG>o1N9RL)tuqy(cz1&8lwAWJ1Q zI@RV`2%O`oVeL8@ZPLvUpDVvx6#>@>G%P?$#7?a6g_^Sv<|isyM9T zSk%APwqs@1ce>r9L9M_}{i}}1NM7fK^`?w+H65ND*}WH0Iu6tycL<$wDbyW@&$=sI z$mhOI0ZzyT^t=-G5Q09LCh9B^Bvw)3-oUB>Z+mds8_Kb*YZhW7oesbha&MJg!P2Z; zj5^0X<@AivpqJkKan@y>Ef%9GnDe}d>BfhuA-&;GXTrhX+g;&c{5#&c;Mz)WM?#ap zt|aGG!0l5D=x~nrgvZMxzqRIE>Rj79FknHQ4{l824k@P_zTfxPy1+hR5$>+A6Tg+d z;8ytXWLA#Wr6o3AWkIE5+(MBTq@a+-CmlAMQP!Rc=}p5idY|W$g7cMoC!^*jQKG6( zve2L|dG^6Ijiye$6uzBFD6dJ4InGaW*EUmYcgn%uKN;9cluV9@_h3l;sXG12D~B%f zUVEC%P1JZYufYYveX~l3jNS6#s|4=vJ+-X&4nLb+AVxZUa<2yC7>^3`dI^15VNnj? zU7o1OYgb*Ax2S0)*kyNuTCg{aDrzFxY34ES+^bpp_*j-!i{6^J6Bg?xOK1AzES?FZ z@RT4*4PTIlS5zCOi97|1LPyYw=1wPKT2db3jqX3cH)+~xWs|*Z->~TifcFbw)?+@E z1?s`NsDUTPC9sPe-{~n0{C(eRi{Xy~Y}OVx@5;qWXxb*$><}i8^|p#AFLbJ^J2wpEP?y z7QL%2@xR@7J|?ab=-8Y|xHcycs+Jae!)d3kNp|p0mnUx&br@`EUS#|nHg=O}J^gmb z?4m7~)SHIRfOPzF7kR`r8BCA z0}XE%y1&;z8eyU;tMGNUPl$!PLvs{k3BOA$ZAFZ6aA=#K>g8C$yC?Z^Rz~T0T9_v% zd!{|Op!N|R(2M<1$lBB-_*cQ5^V+n1Y3GC^%3=(Zr3a=McoH7yYP5>pcX_WAQJ@${ z?`JE^)Q8hQ;(E1J|7i9mL@yNP(p#5U}Qic z%~e}u&JmfeW%s0J*|fK!g7uiF-& z_?p_onGP$M2r`ehOZ|;ofs}*`H1v~J+j!EOLd)&dWN<4Xb6My8ui0<><#Vtc$~3E~?~j8h zg?i$r1dCW?TI%ByS$pYBR2p(i|8)TK4bJ=br%FV$mN5)GMG3*vOq(_3Lryn)I;~F~ z#KfgT4cugJ$$nr^Jbn7!nLK%CCTOl}xf``5WChd>UfnzQ!uZ|hSgV$CpiOw!bSh#Y zl;5bI;ix*ZkM<={vbM6di3~(>7f`#NMYh_oZSsdl_bw ztoya}f;nmU(+F<`yTe0tMU8<$C0&~d$n4lOXgREB!|8bL%!DQh-F1Xj8bc*hva5v9hFJ&a=0v52XYO5jcvbGxp2$J z@h-xZyJ8nG^PvkTuOjWtw1(-J8w&{pkwR-6j`IU86kFF2MGVK*mB`T=ZMnFl1QCO% z#|@MCOg&}Y5&=;Js~^W0%7!$_m8&oJRgTi@{sWu6!|Z&wREI5^;eM|JbvJ2KK=<3l z*xt<&x9DqIw}F<1!V~vEjXox^DjjXKy(w!u-MzYtHty8-23na@dZnywH=}QkHxqYp zzCJI5SN2H4eQt|GB!zFsEKRH*s)cS7<;6-Mx5+SXo~@g}@l!mZ>KhU)cjbwp#4A*w zZ*v6+vQG@xuqQ1LhCjbH$}Ji8;Yj922R{v%7=8-vTfEdr-_lQTRNxg@J7I}wP&ItR zdN!z?Vb&_jaE4;Eo6JVCJ4jy8U&8UQVPXG?nD0m*w7{s7sKYaAFm;~Se%>(lR9w?> zMROfLMSf{FJ{DlDwZM7mf7wpC{6>zicrAN(bf~(qqW)JV?{vkodkXARb}l)2^M2PV z)WJo9eAiS^PoA*k;)8cv$LHe%s}%hAEHVontxkI1(s)E~-iYe2oP5Nv8(GhsxL+BI z7r84N!|bfvA|JB2{Y<^IQ;U}*h)`0)NY z%P-lHrIEF&FU*gvlBc>I=R-rjy1BahJlgT9Un0GiJZD$WXM>jO^ICsp!kBBG_(1lJ z)0iMIqwL-B(#q4+Sg?IFy%Vu+9EteHkU=RuScjW(ii z3v@gV&!5HO`ZG$a$;~@b2=UxuctT{@49bFr#`AcO3LN;Hf6Se4P4ZXTmr0Y_oe%42hewAGeDhxS0qyrN3Qv~zw_0i@ zxS${Nc9TU0F5t$;cyC1>|GApji<)T>u)8)Xm=`upX=hu$m7o!}Tr$3l87gi9%iLSv z!++^1^~vHgmBC(0z3{8x6gxsW*}bV_U-FKtmP7218d-g<*P%i2a|k)ih5Pn}#<2Qr z2Di!joD2+qqxQinZCnNQvYj%6!fK(9=Gp>8mzRbrd$XILXE0yM2NKDzU=^oTZ1JOq zeeDe~{%lC**%WIbVG^+-G_F-$pFHDi4^<5EiF*kJ4a3(rtJ?E`lwDJ^*c_Jm30~Y3 zPYSh}5}|mY6-!E1j}-G^*?AsjPDg?GcXbJaF+`PFYWNj_G=-$0EE378gRtwKw<1H7 zAJ>(xdckm|Z_%!k?QDrcufqdu!SF(B#c2Fg#t4r{a6yApo#srCX2!Fct>}+HwhRqs zJxEVs%FFOJ<&o>aHI@a~%2LM|#Gb4)a5sM?U^7yRh>vyx>CV#**Rm2lPoblqE|qT-XqzsIX;)nKo$;pVZ7U=)j49k*O!3e* z10r7C75X5PaE6!w=Em$*jC*S+7%SO_)ETEj2SByHh?@y8{1`54h8aQhDw3>1&+SCK zhg$AO9-0AyGkcIdKDmqmHQ&+9kd|H@+NZh6$+rQHQ}W@Mo9XC( zSJ<4A22`H)rQ7NxzSSk+83sfNomK&69}5ua9rIOyXVFx#FAmSoQ0(dv;3d0IIgCkB zgTlWyO}>m7w2GU`&;Sk%%te2YIKS(R`Y06rBK}Nj?z?JGxa^mAhLWgen}e}FgOQIk z%lYE(4A05dr>r2$@6hHGh-4=t<=Hjd;aX$-F%A=HvgsxYo`28Y58X^bdLgV-Tf-V} z*aeR!NJGAD5EJ)mtQonKRSe-sA{vu{w5m!b%}}<=VlVoIa!fh8?>u|#bj5~UVY4|l z8%7N*6eltffD`ahIfu=FY(S&AB{830 z!=~Gm-`p%DK6tb5LDHOZ%d9*B(MF(f^K&=QjEbQF*hQT&W7VyS-6)vsN3)PDt;JEq z7CrijfD~0V={9KL{vA4`)Y?K|QFi^qPXH2H6Y1X4JbdBk&c#{)z4A&GiJD8=k8;px zByPZ%1ZJS;?@hBNDzO5!o!16Qw{^I5q7{~L$$Q4U$ic7i!}tnuu-xwE7MPjow#!N z^bS}qy>qnl9ttP&iBlfQ0(<0V0&?;}Pd^~VL@G}UX}$fS5Ii<}RTS5dv>Uel#qeuO zw2pgq27hm1KmviceE#?BBznSZA)Ek zu18louD%g=9`~?pN1)ZrR^B3IKwb69;yf>y8a1ly>gH`bRt~WUE}@|5CIfh3uBz#` znQ~gl2AU7OP{H+H-%FSK5h_pA#x9S_W#Z_H)}QZl{9N+in2^F+)d#D8gxX-lU6u%n zd)&Y4m8hv8S7TCr+ils-OEMcJ0e@zo3xCuv(2ls6wmW^vH>G%WC{x7=WrXjNs2KvW zU(Abh_O*nR?D?N+D?q z4s4cbK{SJ%=xGmnZwq}(bM-)^bpq$~~q>wMzhbxd7{)z+T|# z85f(&b%|Jqqfoz`tmmyWx}U^-zd5`bIdFxNww|Rs*?`1a zR>I!fmeX(|A^g^8bcF4|>z%A?p0f{0HmUZKLg~4k(oSjg|%I09R+gOxh&f!yiKqiwWBKPfy$R4p@v$jfvz8Xs2xp$SmlVN57Y zJ~e4OFSGWbBfWF;ov4&FiR;gv9rg&x*L20K@kRkvY6IjIfT(0!p*SycmmGe;*md-f z9W~?G*h9MZjVzSzb`E$kfVX_v;FH6y`N=h;@1vNIa{yfukc-axUb zL^-8`Q~oeGW@`p^ZS-!gGW8!Ssh98>g8RTHvsd=Z@?lylT}v8+!lmL@56ZR23w47S zk9?f45~e{$Afb-jWiMeAO?a5lMGwz**sR1kI!-J3@*WLF_lj{l^jPi&TgtP2s*~}<-9}&T{iv!N-6CCh zZ0V77$;CZHqetj`0}i_;+7pXJ=;$ZkHgX2Ma*)>TNTkWm2^m$-1=1in+CWRnD^_Ym@x=17G9J z#8NWNEUziG$m!>A?0@_udRK4)kK}WSX4qA#h~HQU=NQG@c>>4V)rgVFW{IZ(#~s5s z^{uD@GyoCe?6oyBxD=c44( zvt*@ccx5L;XrgG-R8Ba!V%e_2VXCvvW}CbbzBuQZjpCcnc%KCGQHQcKSM9-hPRtTJ1py zQ?W|71QcM+A89ab;fl5$U|Bd-9kPP$_BZvJwYB{7bcKb1rn4(Ew~e^Ku$duiSj*7K-W zphgOlWOnkIBAJCpZ=c;IF}QQV1bUWS4U68dv8c*U4hQc_fBHRgbVKjrO5eMCT3J|F zj4{k?H+N>AnKea7#dz7Ja3)iEKNZUP`G=`p!%WvMHL(p_%J^#*3}IHYnu$boxs(X; zoW?aLD?>9bCbsgEG1a6?j_Tr-uuYe?+MJxL-VHm)4EuR=LLP|x%>q6}%y?6YVp)_1 zwPwT?C?@%4=5vsK$?HcG8x$;<_6iDrsB$mHK33y_?3+d zX|)6$R8NtS_nP$)ttJW-C57||Slw(WX@vib(iNLJP}p>}Dab2|;Ywl`);UQJyNjOB zoyu#hs|y4Y(}joZ-6#cqez?KvIQ5SAK}|joF=7+5%KvgL5eUaP z(f;$|V;T7DywOqeyxH%2|Io4h+XMg3Hq8a{a!=b>sC9)0NIi(+CuhS(+fZva*Bak6 z;tY3RXruP7ja#L)M+ zvMAsP9Y!j=I*5`8xuFBQdbuvv_>kN=LD;yM%bK+o3g*p(1imij+aCTh5(op!88(!l z;w+Pq}%lJ2Y)F7^uq!~@x_Sq))+FhcSa8bWOJ9mXUaGS_trr%ttJ=9m{eCtoIhhGsmb+u7 z-b!TY@sW#qtCjD2W|{?mh~xXZwf3nc%ha_gd}{OUrr^`zZ;TL{%|OC;RKRruj|IfP zEaW!aia*NX))}IKqgb32cwSy&g?Sg6TFG*y2-1PWnIs?BmOiBqG4|r<)8$=^Ywnt- zGD+OWhNC2vD-$qqC{ESru(TL3q-2 zYZ>%rotIy7J%4r)vFVQs8%$YKI=|=fu#~+#o(!YZ4-Ee2`GVXya3jAc2v3}43j)d+ z1eyu!AbI$7S99}QgP3Ml4K_Xp<~qjF{3-6UzA$MihI5!0+Uj1zK`=(#1pP25=JB?c zltO((;+Nz>ace|QvKk>qexxtciPIxI3WYRPOKquKWB7g%4;ofIjyVBI4pVl zvV!y#!x`(-=h3x^Wy1nj1p_qIa#Kx|tH5uyV?;r9me#J6cP~`bgnl$z*QbSH*wXWzT)Id@c6V zuUpf3HgA-enqapb(kIT@Ye~o7HchB${yP9befhsFfIt6Q>NcV;@tP0v^t_>5x0oXV z(p>?9cfJ8GbQGzX^iXNU>dYJHy52GT!)D2qTP!9)L0bkr+?OjWlVd=~v3PSmWbs*^ zFx~atZ?BHSi&4W*`4C!8+Vj1|wJ1~+R+;zSwSap1Xa;u41$5~;O@Enj z9v6g~JmK#=EhAggSmfU}0YPd`SC6P3t6TBkBG^`OR)328jmkVU=5UF~7FSGcmb7d2c`@0y8lcOid zZu7^Lu~}@};1|J+!vai~``l|=w0QvY4RFm^Lqpn`<{FTm#ep}N6UnHw`|ZIAlU-|Y z7JSht%_FB{T36cmPz`p%!;Pzo}2S_fVY^Pwpj0fGz<7WKh zU%sTo+TF#XX;8}uKSO;Uqx_Al%iCdkGi){}ua(K|Ag`ddu-*ClN$X;dXLD$a^bL=f zUMICg5+rz(Au&jxx6I^6<7LY7-Y}a(jB&*)U6&r;oIp3PeIllRA=azAd4Q*B^$o@c z#Qz;2bcs;nM~ZC-G7(?#I@hbaXiCDH(r+;+g$GaTVXnWQ2@lxGuGnd&EyKlM4=6HI zFCA!(rCgVrGnp_dsse*apRc@YI7==Ro`o5$)}KF8XUE_9+D@?>z~a3@#IgwAb2R(H z?bD-ykK-~o^K!FpVX)&dtV)zjul@Bc4k#tS0vM0GwGY`-|F-f6?3-dtfh9ahi=NTW> zOgvSVHVqA^yDW;u_*9G)fW5JEzv(2ruzqZt}Em{2hw<$tK6i8{7V-%@Iy zS7UVEO8CuZAX5r>n|WC)7k`@ z{rVW{GnPOS2)54u8Oy1UM-@jbk1m5pfrO*KSzWTM|M}44gPez1c`YrrjW0i%0INFr;_5`Z22njs70?TE}JGU zcS^;7Z#+F5tdNjZY_V5l``EUD0*fSZv~z1z$PRAbwgW9B_$fG}wZVOQ+61vy*F`3w zOUrYNM>(I^NX1Yz%||<);A{99&*G^PwDi}~^T+JjVT6Iv!OGf<_Pmv(bG)z5N#S?xpncjRG|3RvKoEZwdeAjJ~6{Zv+!xTdueUI<3k^*Sz5nNS_Pv^NP^reZ_k0 zo~u`^a_FXhv~R@iK_q>KP*1?(b+zj*{?XcPC8u44YU8jn&&Q`Z+VIDg*43Gu;3iOq?`yQJ4@7)#|0-NA$KsOzoVmSHZk%6&q2QI1AMM0Rirdb z&1yoVDc_FOD57U-nj?fo_$XMDwV~^orcatBpq$`H^RYAmIWC{N;!%=g6oa7gl@9JB zi98DEyHCb4+&jp)ew^-ei#$b*d}7n0_L8dt&0LM8Shjf~*T$zV^kk1asaGD8DMXC^ zr*Y}eqpdEyWKd_6kX=cQ9crsMP(U4~+AVRnq}3DX4wDtF5bjCGcv9vX0>C+xM&5j% z8>=r6pmF_SlZ!A1R_?xy*o;j}Eb`-4`;A`YQC1d48*Uh6HF>D!e!wJ3`qc!934moNhTIn-UYEeuw)B=O-f zm20sfZ<{Z5CCD>+?ij8cMzKb*K|`#I?`NiBy6QTUh- zTOI{O^KqyfG}Dae)>!Nr9|HjGI;>00LmhjWy=!h#<<^-B6KV&4E>xmC7N@ zyAT0NwHc;#MIs`N^k8{9m(Up+jk^N16E)@+QrRT4a3ZE86cD<;xBSCfboHce6=f>7 zvEE~IV=C3n(egg-LKiuREZ*B;fMiPVI*q6hz)U5Z-T+ ziRVF_wFqy7`hvtjo^L9qmet)ohIuJAtouI3G$R(;`Zi-sx(Z@#|`a_KPy@c^1*Yo&pPfeUlRzBovmbwOv`=lvj86d1_{+vxOEFX1J zB8=T;L?0>qb%}Vdj+Y*C^>kW$a0-P?LjzHR6MHnw7gN%8AJsD&etl%)1Nk)aejEjC z`q-k-^u&F3vE8O2Sx)MZiIDKcH=zgL2~eVwQU8dhfxOzsD9z1M#s z*=R9Ts#V0Z?C`)@>GQe|ZHwJ@)A!-uq%YTg&um&8fQ+5Wgcgdc&dvnoBmNnCOt#F0 z>UL(n9BnpM5mdEd8=>ekw2n<>BAD;rGXmf%_((((%7WTLdyO_I(((A^mlo#~r`fjR z*arU=65z-R@yp2sD=Q0+&RQ+!dhmHrGx!{FL9hE69LO{I&zAli@xoHIABB8h)gD2S@KM%a_5XH`6A%8d^NZILHCet%>lc-l==F94!C>= z`ujOs=SByUNSezEu8&c%`gdFSp5RyX%6(z+vX~_9S%mP>>uyq`OBIoGijU!ThuSto zKeIuKrAPGoy=3})vh*dnUSSBK8ZCQncO|kmpSL3=XULhjMbuY_em|^vDaYGo<4lM- z8RHv7Mh^(!_)U;ubY;L#qj%%a(M+t`_bAyh{0$Yc-73hCHP~SCT%uIeUDbyzE8fGe z6d*>7EFY_7_KY?Ab>g=CjdQ1v`yj0&rpO~01a#1RqVY0-`T#pgt{sTlM=Zmm3|Qks zymf#M1TogY&qvcjQCQ2_eshf%H7~nUXS&Mfi?MTBs9L@IYnglN)1v93?EFZP)$I=u z+oPWFn}jCXIJQqL0@l^S#zl3PiKDV6?*8O}&aWq%DD{}|1}aa zwXD<77m4(rQp5C3mv3E7w*$^9q^_>}mTnDDrqXD;N5LJ^Ve^-GfSpZO(&EYQB*F&cl*ZlUN ztJI$8FL{3RPV41DeeQ<}(xL}u9-%xxzAW_AI4wPqdeCxfJribdS~3}VzJMtixbv+O zou3G`fUqyzzACH9-J5S_^9~qdg|eI52DF9VfMevFErC>zUy3xCwU~mKHZt5E%r2x} zeb!%ZIJ?z;Ys){DG?+L7`?Zmrt=%QP=RQ4e-&7IkQGU7hp6ZWA4cV;A`}4%O#**Av z?})D)v+A(|tj3V8%3rQp$!m9`vLrS=eouYt7OHlQCT@;1I;55}P4eFNUv!2VG|b9K zRjMU5J>h#fA2}0bz`9#*@(I^(UMB5cqrjztSPKUo-b!kd{G*p?@O~}yC89J}Olr&p$@u=x{R{0O3S;Zlz= zE39%U-h#OSx0Fz_yoL-zkg(^tdp*|NE9x2S#Hr>ow%MXz;a$@G`q{mGqGoE%;c%if5ljUmKs>KUfC}8e*jnT@PhyV literal 9441 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 y3vD~Wi9;mL_v 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 diff --git a/opennow-stable/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/opennow-stable/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png index a40d73e9c68ea638c28c7b13e4bcd1e179a3a102..cc29914b856e4cb4ae1c1d9eb6f88c6aa4e3affe 100644 GIT binary patch literal 22489 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 literal 15916 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 - #FFFFFF - \ No newline at end of file + #020617 + diff --git a/opennow-stable/src/renderer/src/App.tsx b/opennow-stable/src/renderer/src/App.tsx index 14c04480..a8dd1ec1 100644 --- a/opennow-stable/src/renderer/src/App.tsx +++ b/opennow-stable/src/renderer/src/App.tsx @@ -3548,6 +3548,9 @@ export function App(): JSX.Element { onVirtualGamepadState={(state) => { clientRef.current?.setVirtualGamepadState(state); }} + onTouchMouseMove={(input) => { + clientRef.current?.sendTouchMouseMove(input); + }} /> )} {isSwitchingGame && settings.controllerMode && streamStatus !== "connecting" && ( diff --git a/opennow-stable/src/renderer/src/components/StreamView.tsx b/opennow-stable/src/renderer/src/components/StreamView.tsx index a3b4539f..583935f9 100644 --- a/opennow-stable/src/renderer/src/components/StreamView.tsx +++ b/opennow-stable/src/renderer/src/components/StreamView.tsx @@ -1,7 +1,7 @@ import { useState, useEffect, useCallback, useRef, useMemo } from "react"; import { createPortal } from "react-dom"; -import type { JSX } from "react"; -import { Maximize, Minimize, Gamepad2, Loader2, LogOut, Clock3, AlertTriangle, Mic, MicOff, Camera, ChevronLeft, ChevronRight, Save, Trash2, X, Circle, Square, Video, FolderOpen } from "lucide-react"; +import type { CSSProperties, JSX } from "react"; +import { Maximize, Minimize, Gamepad2, Loader2, LogOut, Clock3, AlertTriangle, Mic, MicOff, Camera, ChevronLeft, ChevronRight, Save, Trash2, X, Circle, Square, Video, FolderOpen, Menu, Battery, Wifi, MousePointer2 } from "lucide-react"; import SideBar from "./SideBar"; import type { StreamDiagnosticsStore } from "../utils/streamDiagnosticsStore"; import { useStreamDiagnosticsSelector, useStreamDiagnosticsStore } from "../utils/streamDiagnosticsStore"; @@ -27,6 +27,7 @@ import { RemainingPlaytimeIndicator, SessionElapsedIndicator } from "./ElapsedSe import type { MicrophoneMode, ScreenshotEntry, RecordingEntry, SubscriptionInfo } from "@shared/gfn"; import { formatShortcutForDisplay, isShortcutMatch, normalizeShortcut, shortcutFromKeyboardEvent } from "../shortcuts"; import { openNow, platformCapabilities } from "../platform"; +import { useElapsedSeconds } from "../utils/useElapsedSeconds"; interface StreamViewProps { videoRef: React.Ref; @@ -81,6 +82,7 @@ interface StreamViewProps { onRequestPointerLock?: () => void; onReleasePointerLock?: () => void; onVirtualGamepadState?: (state: VirtualGamepadState) => void; + onTouchMouseMove?: (input: { dx: number; dy: number; timestampMs?: number }) => void; microphoneMode: MicrophoneMode; onMicrophoneModeChange: (value: MicrophoneMode) => void; onScreenshotShortcutChange: (value: string) => void; @@ -552,6 +554,64 @@ function VideoFocusOnReady({ } type StickValue = { x: number; y: number }; +type TouchPlacement = "default" | "compact" | "lower" | "split"; +type AndroidTouchSettings = { + enabled: boolean; + size: number; + opacity: number; + placement: TouchPlacement; + mousePad: boolean; +}; + +const ANDROID_TOUCH_SETTINGS_KEY = "opennow.android.touchControls.v1"; +const DEFAULT_ANDROID_TOUCH_SETTINGS: AndroidTouchSettings = { + enabled: true, + size: 1, + opacity: 0.74, + placement: "default", + mousePad: true, +}; + +function clampNumber(value: number, min: number, max: number): number { + if (!Number.isFinite(value)) { + return min; + } + return Math.max(min, Math.min(max, value)); +} + +function readAndroidTouchSettings(): AndroidTouchSettings { + if (typeof window === "undefined") { + return DEFAULT_ANDROID_TOUCH_SETTINGS; + } + + try { + const raw = window.localStorage.getItem(ANDROID_TOUCH_SETTINGS_KEY); + if (!raw) { + return DEFAULT_ANDROID_TOUCH_SETTINGS; + } + const parsed = JSON.parse(raw) as Partial; + const placements: TouchPlacement[] = ["default", "compact", "lower", "split"]; + return { + enabled: parsed.enabled ?? DEFAULT_ANDROID_TOUCH_SETTINGS.enabled, + size: clampNumber(Number(parsed.size ?? DEFAULT_ANDROID_TOUCH_SETTINGS.size), 0.72, 1.35), + opacity: clampNumber(Number(parsed.opacity ?? DEFAULT_ANDROID_TOUCH_SETTINGS.opacity), 0.25, 1), + placement: placements.includes(parsed.placement as TouchPlacement) + ? parsed.placement as TouchPlacement + : DEFAULT_ANDROID_TOUCH_SETTINGS.placement, + mousePad: parsed.mousePad ?? DEFAULT_ANDROID_TOUCH_SETTINGS.mousePad, + }; + } catch { + return DEFAULT_ANDROID_TOUCH_SETTINGS; + } +} + +function writeAndroidTouchSettings(settings: AndroidTouchSettings): void { + try { + window.localStorage.setItem(ANDROID_TOUCH_SETTINGS_KEY, JSON.stringify(settings)); + } catch { + // Non-fatal; controls remain usable for the current session. + } +} function TouchStick({ label, @@ -618,8 +678,10 @@ function TouchStick({ function TouchControllerOverlay({ onVirtualGamepadState, + settings, }: { onVirtualGamepadState: (state: VirtualGamepadState) => void; + settings: AndroidTouchSettings; }): JSX.Element { const [leftStick, setLeftStick] = useState({ x: 0, y: 0 }); const [rightStick, setRightStick] = useState({ x: 0, y: 0 }); @@ -716,7 +778,15 @@ function TouchControllerOverlay({ }, [emit, onVirtualGamepadState]); return ( -

+
@@ -749,6 +819,257 @@ function TouchControllerOverlay({ ); } +function AndroidMousePad({ + enabled, + onTouchMouseMove, +}: { + enabled: boolean; + onTouchMouseMove?: (input: { dx: number; dy: number; timestampMs?: number }) => void; +}): JSX.Element | null { + const lastPointRef = useRef<{ x: number; y: number; id: number } | null>(null); + + if (!enabled || !onTouchMouseMove) { + return null; + } + + return ( +
{ + if (event.pointerType === "mouse") { + return; + } + event.preventDefault(); + event.currentTarget.setPointerCapture(event.pointerId); + lastPointRef.current = { x: event.clientX, y: event.clientY, id: event.pointerId }; + }} + onPointerMove={(event) => { + const last = lastPointRef.current; + if (!last || last.id !== event.pointerId || event.pointerType === "mouse") { + return; + } + event.preventDefault(); + const dx = event.clientX - last.x; + const dy = event.clientY - last.y; + lastPointRef.current = { x: event.clientX, y: event.clientY, id: event.pointerId }; + onTouchMouseMove({ dx, dy, timestampMs: event.timeStamp }); + }} + onPointerUp={(event) => { + if (lastPointRef.current?.id === event.pointerId) { + lastPointRef.current = null; + } + }} + onPointerCancel={(event) => { + if (lastPointRef.current?.id === event.pointerId) { + lastPointRef.current = null; + } + }} + /> + ); +} + +type BatterySnapshot = { + level: number | null; + charging: boolean | null; +}; + +type BatteryManagerLike = EventTarget & { + level: number; + charging: boolean; +}; + +type NavigatorWithBattery = Navigator & { + getBattery?: () => Promise; +}; + +function useBatterySnapshot(): BatterySnapshot { + const [battery, setBattery] = useState({ level: null, charging: null }); + + useEffect(() => { + const getBattery = (navigator as NavigatorWithBattery).getBattery; + if (!getBattery) { + return; + } + + let dead = false; + let manager: BatteryManagerLike | null = null; + const sync = () => { + if (!manager || dead) { + return; + } + setBattery({ + level: Math.round(manager.level * 100), + charging: manager.charging, + }); + }; + + void getBattery.call(navigator).then((value) => { + if (dead) { + return; + } + manager = value; + sync(); + manager.addEventListener("levelchange", sync); + manager.addEventListener("chargingchange", sync); + }).catch(() => undefined); + + return () => { + dead = true; + manager?.removeEventListener("levelchange", sync); + manager?.removeEventListener("chargingchange", sync); + }; + }, []); + + return battery; +} + +function AndroidStreamMenu({ + diagnosticsStore, + sessionStartedAtMs, + isStreaming, + touchSettings, + onTouchSettingsChange, + onEndSession, +}: { + diagnosticsStore: StreamDiagnosticsStore; + sessionStartedAtMs: number | null; + isStreaming: boolean; + touchSettings: AndroidTouchSettings; + onTouchSettingsChange: (settings: AndroidTouchSettings) => void; + onEndSession: () => void; +}): JSX.Element { + const [open, setOpen] = useState(false); + const battery = useBatterySnapshot(); + const elapsedSeconds = useElapsedSeconds(sessionStartedAtMs, isStreaming); + const stats = useStreamDiagnosticsSelector( + diagnosticsStore, + (value) => ({ + rttMs: value.rttMs, + packetLossPercent: value.packetLossPercent, + bitrateKbps: value.bitrateKbps, + decodeFps: value.decodeFps, + connectionState: value.connectionState, + inputReady: value.inputReady, + lagReason: value.lagReason, + }), + (prev, next) => + prev.rttMs === next.rttMs && + prev.packetLossPercent === next.packetLossPercent && + prev.bitrateKbps === next.bitrateKbps && + prev.decodeFps === next.decodeFps && + prev.connectionState === next.connectionState && + prev.inputReady === next.inputReady && + prev.lagReason === next.lagReason, + ); + const updateTouchSettings = useCallback((patch: Partial) => { + onTouchSettingsChange({ ...touchSettings, ...patch }); + }, [onTouchSettingsChange, touchSettings]); + const batteryText = battery.level === null ? "Battery --" : `Battery ${battery.level}%${battery.charging ? " charging" : ""}`; + + return ( +
+ + {open && ( +
+
+ {formatElapsed(elapsedSeconds)} + {batteryText} + {stats.connectionState} · {stats.inputReady ? "input live" : "input sync"} +
+ +
+ RTT + {stats.rttMs > 0 ? `${stats.rttMs.toFixed(0)}ms` : "--"} + Loss + {stats.packetLossPercent.toFixed(2)}% + Bitrate + {(stats.bitrateKbps / 1000).toFixed(1)} Mbps + FPS + {stats.decodeFps || "--"} +
+ + + + + + + + + +
+ {(["default", "compact", "lower", "split"] as TouchPlacement[]).map((placement) => ( + + ))} +
+ + +
+ )} +
+ ); +} + function useMicMeter( canvasRef: React.RefObject, track: MediaStreamTrack | null, @@ -896,6 +1217,7 @@ export function StreamView({ onRequestPointerLock, onReleasePointerLock, onVirtualGamepadState, + onTouchMouseMove, microphoneMode, onMicrophoneModeChange, onScreenshotShortcutChange, @@ -933,6 +1255,7 @@ export function StreamView({ const [usedMimeType, setUsedMimeType] = useState(null); const [recordingShortcutInput, setRecordingShortcutInput] = useState(shortcuts.recording); const [recordingShortcutError, setRecordingShortcutError] = useState(null); + const [androidTouchSettings, setAndroidTouchSettings] = useState(() => readAndroidTouchSettings()); const mediaRecorderRef = useRef(null); const recordingIdRef = useRef(null); const recordingStartTimeRef = useRef(0); @@ -947,6 +1270,18 @@ export function StreamView({ typeof openNow?.listRecordings === "function" && typeof openNow?.deleteRecording === "function"; + const handleAndroidTouchSettingsChange = useCallback((next: AndroidTouchSettings) => { + const normalized: AndroidTouchSettings = { + enabled: next.enabled, + size: clampNumber(next.size, 0.72, 1.35), + opacity: clampNumber(next.opacity, 0.25, 1), + placement: next.placement, + mousePad: next.mousePad, + }; + setAndroidTouchSettings(normalized); + writeAndroidTouchSettings(normalized); + }, []); + const microphoneModes = useMemo( () => [ { value: "disabled" as MicrophoneMode, label: "Disabled", description: "No microphone input" }, @@ -2157,8 +2492,27 @@ export function StreamView({ {/* Gradient background when no video */} - {platformCapabilities.isAndroid && !isConnecting && onVirtualGamepadState && ( - + {platformCapabilities.isAndroid && !isConnecting && ( + <> + {onVirtualGamepadState && androidTouchSettings.enabled && ( + + )} + + + )} {/* Connecting overlay */} diff --git a/opennow-stable/src/renderer/src/gfn/webrtcClient.ts b/opennow-stable/src/renderer/src/gfn/webrtcClient.ts index 59b63c16..66f9030f 100644 --- a/opennow-stable/src/renderer/src/gfn/webrtcClient.ts +++ b/opennow-stable/src/renderer/src/gfn/webrtcClient.ts @@ -129,6 +129,12 @@ export interface VirtualGamepadState { rightStickY: number; } +export interface TouchMouseMoveInput { + dx: number; + dy: number; + timestampMs?: number; +} + export type StreamLagReason = | "unknown" | "stable" @@ -1981,6 +1987,51 @@ export class GfnWebRtcClient { this.emitStats(); } + public sendTouchMouseMove(input: TouchMouseMoveInput): void { + if (!this.inputReady || this.inputPaused) { + return; + } + + const dx = Number.isFinite(input.dx) ? input.dx : 0; + const dy = Number.isFinite(input.dy) ? input.dy : 0; + if (dx === 0 && dy === 0) { + return; + } + + let scaleX = 1; + let scaleY = 1; + const target = this.pointerLockTarget ?? this.options.videoElement; + const rect = target.getBoundingClientRect(); + const resMatch = /^([0-9]+)x([0-9]+)$/.exec(this.currentResolution ?? ""); + if (rect.width > 0 && rect.height > 0 && resMatch) { + const serverWidth = parseInt(resMatch[1], 10); + const serverHeight = parseInt(resMatch[2], 10); + if (Number.isFinite(serverWidth) && Number.isFinite(serverHeight) && serverWidth > 0 && serverHeight > 0) { + scaleX = serverWidth / rect.width; + scaleY = serverHeight / rect.height; + } + } + + const sensitivity = this.mouseSensitivity; + const speed = Math.hypot(dx, dy); + const strength = Math.max(0, this.mouseAccelerationPercent - 1) / 149; + const accelFactor = this.mouseAccelerationPercent > 1 + ? 1 + Math.min(0.6 * strength, (speed / 50) * strength) + : 1; + const dxServer = Math.max(-32768, Math.min(32767, Math.round(dx * sensitivity * accelFactor * scaleX))); + const dyServer = Math.max(-32768, Math.min(32767, Math.round(dy * sensitivity * accelFactor * scaleY))); + if (dxServer === 0 && dyServer === 0) { + return; + } + + const payload = this.inputEncoder.encodeMouseMove({ + dx: dxServer, + dy: dyServer, + timestampUs: timestampUs(input.timestampMs), + }); + this.sendInputPacket(payload, INPUT_MOUSE_REL); + } + private readGamepadState(gamepad: Gamepad, controllerId: number): GamepadInput { const buttons = mapGamepadButtons(gamepad); const axes = readGamepadAxes(gamepad); diff --git a/opennow-stable/src/renderer/src/styles.css b/opennow-stable/src/renderer/src/styles.css index e0fc6fec..7fe9f13c 100644 --- a/opennow-stable/src/renderer/src/styles.css +++ b/opennow-stable/src/renderer/src/styles.css @@ -5639,6 +5639,8 @@ button.game-card-store-chip.active:hover { z-index: 1001; pointer-events: none; touch-action: none; + --sv-touch-scale: 1; + --sv-touch-opacity: 0.74; } .sv-touch-left, @@ -5649,6 +5651,8 @@ button.game-card-store-chip.active:hover { align-items: end; gap: 14px; pointer-events: none; + transform: scale(var(--sv-touch-scale)); + transform-origin: bottom left; } .sv-touch-left { @@ -5659,27 +5663,30 @@ button.game-card-store-chip.active:hover { .sv-touch-right { right: max(16px, env(safe-area-inset-right)); grid-template-columns: auto auto; + transform-origin: bottom right; } .sv-touch-shoulders { position: fixed; top: max(12px, env(safe-area-inset-top)); left: 50%; - transform: translateX(-50%); display: grid; grid-template-columns: repeat(4, minmax(52px, 68px)); gap: 8px; pointer-events: none; + transform: translateX(-50%) scale(var(--sv-touch-scale)); + transform-origin: top center; } .sv-touch-center { position: fixed; left: 50%; bottom: max(18px, env(safe-area-inset-bottom)); - transform: translateX(-50%); display: flex; gap: 10px; pointer-events: none; + transform: translateX(-50%) scale(var(--sv-touch-scale)); + transform-origin: bottom center; } .sv-touch-stick { @@ -5696,6 +5703,7 @@ button.game-card-store-chip.active:hover { place-items: center; pointer-events: auto; touch-action: none; + opacity: var(--sv-touch-opacity); } .sv-touch-stick-thumb { @@ -5735,6 +5743,7 @@ button.game-card-store-chip.active:hover { align-items: center; justify-content: center; user-select: none; + opacity: var(--sv-touch-opacity); } .sv-touch-btn:active { @@ -5788,6 +5797,183 @@ button.game-card-store-chip.active:hover { left: 40px; } +.sv-touch[data-placement="compact"] .sv-touch-dpad, +.sv-touch[data-placement="compact"] .sv-touch-shoulders { + display: none; +} + +.sv-touch[data-placement="compact"] .sv-touch-left { + grid-template-columns: auto; +} + +.sv-touch[data-placement="compact"] .sv-touch-right { + grid-template-columns: auto auto; +} + +.sv-touch[data-placement="lower"] .sv-touch-left, +.sv-touch[data-placement="lower"] .sv-touch-right, +.sv-touch[data-placement="lower"] .sv-touch-center { + bottom: max(8px, env(safe-area-inset-bottom)); +} + +.sv-touch[data-placement="lower"] .sv-touch-shoulders { + top: max(6px, env(safe-area-inset-top)); +} + +.sv-touch[data-placement="split"] .sv-touch-left { + bottom: max(82px, calc(env(safe-area-inset-bottom) + 70px)); +} + +.sv-touch[data-placement="split"] .sv-touch-right { + bottom: max(10px, env(safe-area-inset-bottom)); +} + +.sv-android-mousepad { + position: fixed; + z-index: 1000; + left: 18%; + right: 18%; + top: 18%; + bottom: 18%; + pointer-events: auto; + touch-action: none; + background: transparent; +} + +.sv-android-menu { + position: fixed; + z-index: 1004; + right: max(10px, env(safe-area-inset-right)); + top: max(10px, env(safe-area-inset-top)); + display: flex; + align-items: flex-start; + justify-content: flex-end; + pointer-events: none; +} + +.sv-android-menu-toggle { + width: 42px; + height: 42px; + display: inline-flex; + align-items: center; + justify-content: center; + border-radius: 999px; + border: 1px solid rgba(255, 255, 255, 0.18); + background: rgba(8, 10, 12, 0.72); + color: rgba(255, 255, 255, 0.86); + backdrop-filter: blur(12px) saturate(140%); + box-shadow: 0 10px 26px rgba(0, 0, 0, 0.36); + pointer-events: auto; +} + +.sv-android-menu-panel { + position: absolute; + top: 50px; + right: 0; + width: min(330px, calc(100vw - 20px)); + max-height: min(78dvh, 560px); + overflow: auto; + display: flex; + flex-direction: column; + gap: 10px; + padding: 12px; + border-radius: 12px; + border: 1px solid rgba(255, 255, 255, 0.14); + background: rgba(10, 10, 12, 0.92); + color: var(--ink); + backdrop-filter: blur(16px) saturate(150%); + box-shadow: 0 18px 48px rgba(0, 0, 0, 0.46); + pointer-events: auto; +} + +.sv-android-menu-status { + display: flex; + flex-direction: column; + gap: 6px; + color: var(--ink-soft); + font-size: 0.75rem; + font-variant-numeric: tabular-nums; +} + +.sv-android-menu-status span, +.sv-android-switch span, +.sv-android-quit { + display: inline-flex; + align-items: center; + gap: 7px; +} + +.sv-android-menu-grid { + display: grid; + grid-template-columns: auto 1fr auto 1fr; + gap: 6px 10px; + padding: 9px; + border-radius: 8px; + background: rgba(255, 255, 255, 0.04); + color: var(--ink-muted); + font-size: 0.72rem; +} + +.sv-android-menu-grid strong { + color: var(--ink); + font-weight: 700; +} + +.sv-android-switch, +.sv-android-slider { + display: flex; + justify-content: space-between; + gap: 12px; + color: var(--ink-soft); + font-size: 0.78rem; +} + +.sv-android-switch input { + width: 18px; + height: 18px; + accent-color: var(--accent); +} + +.sv-android-slider { + flex-direction: column; + gap: 6px; +} + +.sv-android-slider input { + width: 100%; + accent-color: var(--accent); +} + +.sv-android-placement { + display: grid; + grid-template-columns: repeat(4, minmax(0, 1fr)); + gap: 6px; +} + +.sv-android-placement button, +.sv-android-quit { + min-height: 34px; + border-radius: 8px; + border: 1px solid rgba(255, 255, 255, 0.13); + background: rgba(255, 255, 255, 0.045); + color: var(--ink-soft); + font: inherit; + font-size: 0.72rem; + font-weight: 700; +} + +.sv-android-placement button.active { + border-color: color-mix(in srgb, var(--accent) 55%, rgba(255, 255, 255, 0.13)); + background: color-mix(in srgb, var(--accent) 18%, transparent); + color: var(--accent); +} + +.sv-android-quit { + justify-content: center; + color: #ffd0d0; + border-color: color-mix(in srgb, var(--error) 45%, rgba(255, 255, 255, 0.13)); +} + @media (max-width: 640px) { .sv-session-clock { top: 10px; From 7569fc0f09d004b19ac6eb2cbe2cf36c74e63f01 Mon Sep 17 00:00:00 2001 From: Kiefer Date: Sat, 25 Apr 2026 17:02:29 -0700 Subject: [PATCH 42/66] Add touch mouse tap support to AndroidMousePad and WebRTC client --- opennow-stable/src/renderer/src/App.tsx | 3 ++ .../renderer/src/components/StreamView.tsx | 32 +++++++++++++++++-- .../src/renderer/src/gfn/webrtcClient.ts | 20 ++++++++++++ 3 files changed, 52 insertions(+), 3 deletions(-) diff --git a/opennow-stable/src/renderer/src/App.tsx b/opennow-stable/src/renderer/src/App.tsx index a8dd1ec1..73be8564 100644 --- a/opennow-stable/src/renderer/src/App.tsx +++ b/opennow-stable/src/renderer/src/App.tsx @@ -3551,6 +3551,9 @@ export function App(): JSX.Element { onTouchMouseMove={(input) => { clientRef.current?.sendTouchMouseMove(input); }} + onTouchMouseTap={(input) => { + clientRef.current?.sendTouchMouseTap(input); + }} /> )} {isSwitchingGame && settings.controllerMode && streamStatus !== "connecting" && ( diff --git a/opennow-stable/src/renderer/src/components/StreamView.tsx b/opennow-stable/src/renderer/src/components/StreamView.tsx index 583935f9..b30d0fc5 100644 --- a/opennow-stable/src/renderer/src/components/StreamView.tsx +++ b/opennow-stable/src/renderer/src/components/StreamView.tsx @@ -83,6 +83,7 @@ interface StreamViewProps { onReleasePointerLock?: () => void; onVirtualGamepadState?: (state: VirtualGamepadState) => void; onTouchMouseMove?: (input: { dx: number; dy: number; timestampMs?: number }) => void; + onTouchMouseTap?: (input: { timestampMs?: number }) => void; microphoneMode: MicrophoneMode; onMicrophoneModeChange: (value: MicrophoneMode) => void; onScreenshotShortcutChange: (value: string) => void; @@ -822,11 +823,20 @@ function TouchControllerOverlay({ function AndroidMousePad({ enabled, onTouchMouseMove, + onTouchMouseTap, }: { enabled: boolean; onTouchMouseMove?: (input: { dx: number; dy: number; timestampMs?: number }) => void; + onTouchMouseTap?: (input: { timestampMs?: number }) => void; }): JSX.Element | null { - const lastPointRef = useRef<{ x: number; y: number; id: number } | null>(null); + const lastPointRef = useRef<{ + x: number; + y: number; + startX: number; + startY: number; + startMs: number; + id: number; + } | null>(null); if (!enabled || !onTouchMouseMove) { return null; @@ -842,7 +852,14 @@ function AndroidMousePad({ } event.preventDefault(); event.currentTarget.setPointerCapture(event.pointerId); - lastPointRef.current = { x: event.clientX, y: event.clientY, id: event.pointerId }; + lastPointRef.current = { + x: event.clientX, + y: event.clientY, + startX: event.clientX, + startY: event.clientY, + startMs: event.timeStamp, + id: event.pointerId, + }; }} onPointerMove={(event) => { const last = lastPointRef.current; @@ -856,8 +873,15 @@ function AndroidMousePad({ onTouchMouseMove({ dx, dy, timestampMs: event.timeStamp }); }} onPointerUp={(event) => { - if (lastPointRef.current?.id === event.pointerId) { + const last = lastPointRef.current; + if (last?.id === event.pointerId) { + const movedPx = Math.hypot(event.clientX - last.startX, event.clientY - last.startY); + const elapsedMs = event.timeStamp - last.startMs; lastPointRef.current = null; + if (movedPx <= 10 && elapsedMs <= 280) { + event.preventDefault(); + onTouchMouseTap?.({ timestampMs: event.timeStamp }); + } } }} onPointerCancel={(event) => { @@ -1218,6 +1242,7 @@ export function StreamView({ onReleasePointerLock, onVirtualGamepadState, onTouchMouseMove, + onTouchMouseTap, microphoneMode, onMicrophoneModeChange, onScreenshotShortcutChange, @@ -2503,6 +2528,7 @@ export function StreamView({ Date: Mon, 27 Apr 2026 16:15:38 -0700 Subject: [PATCH 43/66] Implement text input and key press handling for Android controls; enhance mousepad cursor visibility --- opennow-stable/src/renderer/src/App.tsx | 4 + .../renderer/src/components/StreamView.tsx | 173 +++++++++++++++++- .../src/renderer/src/gfn/webrtcClient.ts | 36 ++++ .../src/renderer/src/platform/android/api.ts | 43 ++++- .../src/renderer/src/platform/android/http.ts | 17 +- opennow-stable/src/renderer/src/styles.css | 84 ++++++++- 6 files changed, 340 insertions(+), 17 deletions(-) diff --git a/opennow-stable/src/renderer/src/App.tsx b/opennow-stable/src/renderer/src/App.tsx index 73be8564..3dc30164 100644 --- a/opennow-stable/src/renderer/src/App.tsx +++ b/opennow-stable/src/renderer/src/App.tsx @@ -3554,6 +3554,10 @@ export function App(): JSX.Element { onTouchMouseTap={(input) => { clientRef.current?.sendTouchMouseTap(input); }} + onSendText={(text) => clientRef.current?.sendText(text) ?? 0} + onSendKeyPress={(key) => { + clientRef.current?.sendKeyPress(key); + }} /> )} {isSwitchingGame && settings.controllerMode && streamStatus !== "connecting" && ( diff --git a/opennow-stable/src/renderer/src/components/StreamView.tsx b/opennow-stable/src/renderer/src/components/StreamView.tsx index b30d0fc5..11719dae 100644 --- a/opennow-stable/src/renderer/src/components/StreamView.tsx +++ b/opennow-stable/src/renderer/src/components/StreamView.tsx @@ -1,7 +1,7 @@ import { useState, useEffect, useCallback, useRef, useMemo } from "react"; import { createPortal } from "react-dom"; import type { CSSProperties, JSX } from "react"; -import { Maximize, Minimize, Gamepad2, Loader2, LogOut, Clock3, AlertTriangle, Mic, MicOff, Camera, ChevronLeft, ChevronRight, Save, Trash2, X, Circle, Square, Video, FolderOpen, Menu, Battery, Wifi, MousePointer2 } from "lucide-react"; +import { Maximize, Minimize, Gamepad2, Loader2, LogOut, Clock3, AlertTriangle, Mic, MicOff, Camera, ChevronLeft, ChevronRight, Save, Trash2, X, Circle, Square, Video, FolderOpen, Menu, Battery, Wifi, MousePointer2, Keyboard, CornerDownLeft, Delete } from "lucide-react"; import SideBar from "./SideBar"; import type { StreamDiagnosticsStore } from "../utils/streamDiagnosticsStore"; import { useStreamDiagnosticsSelector, useStreamDiagnosticsStore } from "../utils/streamDiagnosticsStore"; @@ -84,6 +84,8 @@ interface StreamViewProps { onVirtualGamepadState?: (state: VirtualGamepadState) => void; onTouchMouseMove?: (input: { dx: number; dy: number; timestampMs?: number }) => void; onTouchMouseTap?: (input: { timestampMs?: number }) => void; + onSendText?: (text: string) => number; + onSendKeyPress?: (key: "Backspace" | "Enter") => void; microphoneMode: MicrophoneMode; onMicrophoneModeChange: (value: MicrophoneMode) => void; onScreenshotShortcutChange: (value: string) => void; @@ -829,6 +831,7 @@ function AndroidMousePad({ onTouchMouseMove?: (input: { dx: number; dy: number; timestampMs?: number }) => void; onTouchMouseTap?: (input: { timestampMs?: number }) => void; }): JSX.Element | null { + const padRef = useRef(null); const lastPointRef = useRef<{ x: number; y: number; @@ -837,6 +840,39 @@ function AndroidMousePad({ startMs: number; id: number; } | null>(null); + const hoverPointRef = useRef<{ x: number; y: number } | null>(null); + const [cursor, setCursor] = useState({ x: 0, y: 0, visible: false }); + + const clampCursor = useCallback((x: number, y: number) => { + const rect = padRef.current?.getBoundingClientRect(); + if (!rect) { + return { x, y }; + } + return { + x: clampNumber(x, 0, rect.width), + y: clampNumber(y, 0, rect.height), + }; + }, []); + + const setCursorFromClientPoint = useCallback((clientX: number, clientY: number) => { + const rect = padRef.current?.getBoundingClientRect(); + if (!rect) return; + const next = clampCursor(clientX - rect.left, clientY - rect.top); + setCursor({ ...next, visible: true }); + }, [clampCursor]); + + const moveCursorBy = useCallback((dx: number, dy: number, clientX: number, clientY: number) => { + setCursor((previous) => { + if (!previous.visible) { + const rect = padRef.current?.getBoundingClientRect(); + if (!rect) return previous; + const next = clampCursor(clientX - rect.left, clientY - rect.top); + return { ...next, visible: true }; + } + const next = clampCursor(previous.x + dx, previous.y + dy); + return { ...next, visible: true }; + }); + }, [clampCursor]); if (!enabled || !onTouchMouseMove) { return null; @@ -844,14 +880,18 @@ function AndroidMousePad({ return (
{ - if (event.pointerType === "mouse") { - return; - } event.preventDefault(); event.currentTarget.setPointerCapture(event.pointerId); + hoverPointRef.current = { x: event.clientX, y: event.clientY }; + if (event.pointerType === "mouse") { + setCursorFromClientPoint(event.clientX, event.clientY); + } else { + moveCursorBy(0, 0, event.clientX, event.clientY); + } lastPointRef.current = { x: event.clientX, y: event.clientY, @@ -863,33 +903,71 @@ function AndroidMousePad({ }} onPointerMove={(event) => { const last = lastPointRef.current; - if (!last || last.id !== event.pointerId || event.pointerType === "mouse") { + if (!last || last.id !== event.pointerId) { + if (event.pointerType === "mouse") { + const previous = hoverPointRef.current; + hoverPointRef.current = { x: event.clientX, y: event.clientY }; + setCursorFromClientPoint(event.clientX, event.clientY); + if (previous) { + const dx = event.clientX - previous.x; + const dy = event.clientY - previous.y; + if (dx !== 0 || dy !== 0) { + onTouchMouseMove({ dx, dy, timestampMs: event.timeStamp }); + } + } + } return; } event.preventDefault(); const dx = event.clientX - last.x; const dy = event.clientY - last.y; - lastPointRef.current = { x: event.clientX, y: event.clientY, id: event.pointerId }; - onTouchMouseMove({ dx, dy, timestampMs: event.timeStamp }); + lastPointRef.current = { + ...last, + x: event.clientX, + y: event.clientY, + }; + hoverPointRef.current = { x: event.clientX, y: event.clientY }; + if (dx !== 0 || dy !== 0) { + moveCursorBy(dx, dy, event.clientX, event.clientY); + onTouchMouseMove({ dx, dy, timestampMs: event.timeStamp }); + } }} onPointerUp={(event) => { const last = lastPointRef.current; if (last?.id === event.pointerId) { + event.preventDefault(); const movedPx = Math.hypot(event.clientX - last.startX, event.clientY - last.startY); const elapsedMs = event.timeStamp - last.startMs; + if (event.currentTarget.hasPointerCapture(event.pointerId)) { + event.currentTarget.releasePointerCapture(event.pointerId); + } lastPointRef.current = null; - if (movedPx <= 10 && elapsedMs <= 280) { - event.preventDefault(); + hoverPointRef.current = { x: event.clientX, y: event.clientY }; + setCursorFromClientPoint(event.clientX, event.clientY); + if (movedPx <= 10 && elapsedMs <= 360) { onTouchMouseTap?.({ timestampMs: event.timeStamp }); } } }} onPointerCancel={(event) => { if (lastPointRef.current?.id === event.pointerId) { + if (event.currentTarget.hasPointerCapture(event.pointerId)) { + event.currentTarget.releasePointerCapture(event.pointerId); + } lastPointRef.current = null; } }} - /> + onPointerLeave={(event) => { + if (event.pointerType === "mouse" && !lastPointRef.current) { + hoverPointRef.current = null; + } + }} + > + +
); } @@ -955,6 +1033,8 @@ function AndroidStreamMenu({ touchSettings, onTouchSettingsChange, onEndSession, + onSendText, + onSendKeyPress, }: { diagnosticsStore: StreamDiagnosticsStore; sessionStartedAtMs: number | null; @@ -962,10 +1042,13 @@ function AndroidStreamMenu({ touchSettings: AndroidTouchSettings; onTouchSettingsChange: (settings: AndroidTouchSettings) => void; onEndSession: () => void; + onSendText?: (text: string) => number; + onSendKeyPress?: (key: "Backspace" | "Enter") => void; }): JSX.Element { const [open, setOpen] = useState(false); const battery = useBatterySnapshot(); const elapsedSeconds = useElapsedSeconds(sessionStartedAtMs, isStreaming); + const textInputRef = useRef(null); const stats = useStreamDiagnosticsSelector( diagnosticsStore, (value) => ({ @@ -990,6 +1073,13 @@ function AndroidStreamMenu({ onTouchSettingsChange({ ...touchSettings, ...patch }); }, [onTouchSettingsChange, touchSettings]); const batteryText = battery.level === null ? "Battery --" : `Battery ${battery.level}%${battery.charging ? " charging" : ""}`; + const sendInputText = useCallback((input: HTMLInputElement) => { + const text = input.value; + input.value = ""; + if (text.length > 0) { + onSendText?.(text); + } + }, [onSendText]); return (
@@ -1040,6 +1130,65 @@ function AndroidStreamMenu({ Finger mouse +
+ +
+ + +
+
+ + +
+ +
{(["default", "compact", "lower", "split"] as AndroidTouchPlacement[]).map((placement) => ( +
- +
@@ -1000,7 +1017,7 @@ function TouchControllerOverlay({
- +
@@ -1704,6 +1721,7 @@ export function StreamView({ onRecordingShortcutChange, subscriptionInfo, micTrack, + lowPowerTouchControls = false, hideStreamButtons = false, className, }: StreamViewProps): JSX.Element { @@ -3082,6 +3100,7 @@ export function StreamView({ onVirtualGamepadState={onVirtualGamepadState} settings={androidTouchSettings} revealSignal={androidTouchRevealSignal} + lowPowerMode={lowPowerTouchControls} /> )} { const target = event.target as HTMLElement | null; - const isTyping = !!target && ( - target.tagName === "INPUT" || - target.tagName === "TEXTAREA" || - target.isContentEditable - ); - if (isTyping && !(target instanceof HTMLInputElement && target.type === "range")) { + if (target && shouldKeepTextInputKeyEvent(target, event)) { return; } diff --git a/opennow-stable/src/renderer/src/platform/android/api.ts b/opennow-stable/src/renderer/src/platform/android/api.ts index 0d572fcd..317baaeb 100644 --- a/opennow-stable/src/renderer/src/platform/android/api.ts +++ b/opennow-stable/src/renderer/src/platform/android/api.ts @@ -62,6 +62,7 @@ import type { ThankYouDataResult, PrintedWasteQueueData, PrintedWasteServerMapping, + AndroidPerformanceInfo, } from "@shared/gfn"; import { DEFAULT_KEYBOARD_LAYOUT, colorQualityBitDepth, colorQualityChromaFormat, resolveGfnKeyboardLayout } from "@shared/gfn"; import { @@ -139,6 +140,7 @@ const LocalhostAuth = registerPlugin("LocalhostAuth"); interface OpenNowAndroidPlugin { setImmersiveFullscreen(options: { enabled: boolean }): Promise<{ enabled: boolean }>; setPointerCapture(options: { enabled: boolean }): Promise<{ supported: boolean; enabled: boolean }>; + getPerformanceInfo(): Promise; consumeLaunchIntent(): Promise<{ intent?: AndroidLaunchIntent | null }>; addListener( eventName: "nativeMouseMove" | "nativeMouseButton" | "nativeMouseWheel" | "launchIntent", @@ -153,7 +155,22 @@ interface TokenResponse { access_token: string; refresh_token?: string; id_token interface ClientTokenResponse { client_token: string; expires_in?: number; } interface ServiceUrlsResponse { gfnServiceInfo?: { gfnServiceEndpoints?: Array<{ idpId: string; loginProviderCode: string; loginProviderDisplayName: string; streamingServiceUrl: string; loginProviderPriority?: number; }>; }; } interface ServerInfoResponse { requestStatus?: { serverId?: string }; metaData?: Array<{ key: string; value: string }>; } -interface GraphQlResponse { data?: { panels?: Array<{ sections?: Array<{ items?: Array<{ __typename: string; app?: AppData }> }> }>; apps?: { items: AppData[] } }; errors?: Array<{ message: string }>; } +interface GraphQlResponse { + data?: { + panels?: Array<{ sections?: Array<{ items?: Array<{ __typename: string; app?: AppData }> }> }>; + apps?: { + items: AppData[]; + numberReturned?: number; + numberSupported?: number; + pageInfo?: { + totalCount?: number; + hasNextPage?: boolean; + endCursor?: string; + }; + }; + }; + errors?: Array<{ message: string }>; +} interface AppData { id: string; title: string; description?: string; longDescription?: string; features?: unknown[]; gameFeatures?: unknown[]; appFeatures?: unknown[]; genres?: unknown[]; tags?: unknown[]; images?: { KEY_ART?: string; GAME_BOX_ART?: string; TV_BANNER?: string; HERO_IMAGE?: string }; publisherName?: string; contentRatings?: unknown[]; variants?: Array<{ id: string; appStore: string; supportedControls?: string[]; gfn?: { status?: string; library?: { selected?: boolean; status?: string; lastPlayedDate?: string } } }>; gfn?: { playType?: string; playabilityState?: string; minimumMembershipTierLabel?: string; catalogSkuStrings?: { SKU_BASED_TAG?: string[] } }; } interface SubscriptionResponse { firstEntitlementStartDateTime?: string; type?: string; membershipTier?: string; allottedTimeInMinutes?: number; purchasedTimeInMinutes?: number; rolledOverTimeInMinutes?: number; remainingTimeInMinutes?: number; totalTimeInMinutes?: number; notifications?: { notifyUserWhenTimeRemainingInMinutes?: number; notifyUserOnSessionWhenRemainingTimeInMinutes?: number }; currentSpanStartDateTime?: string; currentSpanEndDateTime?: string; currentSubscriptionState?: { state?: string; isGamePlayAllowed?: boolean }; subType?: string; addons?: Array<{ type?: string; subType?: string; status?: string; attributes?: Array<{ key?: string; textValue?: string }> }>; features?: { resolutions?: Array<{ heightInPixels: number; widthInPixels: number; framesPerSecond: number }> }; } interface RawPublicGame { id?: string | number; title?: string; steamUrl?: string; status?: string; } @@ -458,6 +475,84 @@ async function fetchCatalog(kind: "MAIN" | "LIBRARY", token: string, providerStr const payload = await fetchPanels(token, [kind], vpcId); return flattenPanels(payload); } +async function searchCatalog( + token: string, + providerStreamingBaseUrl: string | undefined, + searchQuery: string, +): Promise<{ games: GameInfo[]; numberReturned: number; numberSupported: number; totalCount: number }> { + const vpcId = await getVpcId(token, providerStreamingBaseUrl); + const query = `query GetSearchFilterResults( + $vpcId: String!, + $locale: String!, + $sortString: String!, + $fetchCount: Int!, + $cursor: String!, + $searchString: String!, + $filters: AppFilterFields! + ) { + apps( + vpcId: $vpcId, + language: $locale, + orderBy: $sortString, + first: $fetchCount, + after: $cursor, + searchQuery: $searchString, + filters: $filters + ) { + numberReturned + numberSupported + pageInfo { totalCount hasNextPage endCursor } + items { + id + title + images { KEY_ART GAME_BOX_ART TV_BANNER HERO_IMAGE } + variants { + id + appStore + supportedControls + gfn { + status + library { status selected lastPlayedDate } + } + } + gfn { + playType + playabilityState + minimumMembershipTierLabel + catalogSkuStrings { SKU_BASED_TAG } + } + } + } + }`; + + const payload = await httpRequest(GFN_GRAPHQL_URL, { + method: "POST", + headers: buildCatalogHeaders(token), + data: { + query, + variables: { + vpcId, + locale: DEFAULT_LOCALE, + sortString: "itemMetadata.relevance:DESC,sortName:ASC", + fetchCount: 100, + cursor: "", + searchString: searchQuery, + filters: {}, + }, + }, + }); + if (payload.errors?.length) { + throw new Error(payload.errors.map((error) => error.message).join(", ")); + } + const apps = payload.data?.apps; + const games = dedupeGames((apps?.items ?? []).map(appToGame)); + return { + games, + numberReturned: apps?.numberReturned ?? games.length, + numberSupported: Math.max(apps?.numberSupported ?? 0, games.length), + totalCount: Math.max(apps?.pageInfo?.totalCount ?? 0, games.length), + }; +} const androidCatalogCache = new Map(); const androidCatalogInflight = new Map>(); function androidCatalogCacheKey(kind: "MAIN" | "LIBRARY", token: string, providerStreamingBaseUrl?: string): string { @@ -584,18 +679,28 @@ async function browseCatalogRequest(input: CatalogBrowseRequest): Promise catalogSearchText(game).includes(normalizedQuery)) - : allGames; + let searchResult: Awaited> | null = null; + if (normalizedQuery) { + try { + searchResult = await searchCatalog(token, input.providerStreamingBaseUrl, normalizedQuery); + } catch (error) { + console.warn("[Android catalog] Full catalog search failed; falling back to cached Main panel search.", error); + } + } + const searchedGames = searchResult + ? searchResult.games + : normalizedQuery + ? allGames.filter((game) => catalogSearchText(game).includes(normalizedQuery)) + : allGames; const filteredGames = selectedFilterIds.length > 0 ? searchedGames.filter((game) => selectedFilterIds.every((filterId) => gameMatchesCatalogFilter(game, filterId))) : searchedGames; const sortedGames = sortAndroidCatalogGames(filteredGames, selectedSortId); return { games: sortedGames, - numberReturned: sortedGames.length, - numberSupported: sortedGames.length, - totalCount: filteredGames.length, + numberReturned: searchResult?.numberReturned ?? sortedGames.length, + numberSupported: searchResult?.numberSupported ?? sortedGames.length, + totalCount: searchResult?.totalCount ?? filteredGames.length, hasNextPage: false, searchQuery: input.searchQuery ?? "", selectedSortId, @@ -1319,6 +1424,7 @@ const api: OpenNowApi = { onNativeMouseMove, onNativeMouseButton, onNativeMouseWheel, + getAndroidPerformanceInfo: async (): Promise => OpenNowAndroid.getPerformanceInfo(), consumeLaunchIntent: async (): Promise => { const result = await OpenNowAndroid.consumeLaunchIntent().catch(() => ({ intent: null })); return result.intent ?? null; diff --git a/opennow-stable/src/renderer/src/styles.css b/opennow-stable/src/renderer/src/styles.css index e9e53239..c6254176 100644 --- a/opennow-stable/src/renderer/src/styles.css +++ b/opennow-stable/src/renderer/src/styles.css @@ -5831,6 +5831,35 @@ button.game-card-store-chip.active:hover { will-change: transform; } +.android-shell .sv-touch[data-render-mode="lite"] .sv-touch-left, +.android-shell .sv-touch[data-render-mode="lite"] .sv-touch-right, +.android-shell .sv-touch[data-render-mode="lite"] .sv-touch-shoulders, +.android-shell .sv-touch[data-render-mode="lite"] .sv-touch-center, +.android-shell .sv-touch[data-render-mode="lite"] .sv-touch-stick, +.android-shell .sv-touch[data-render-mode="lite"] .sv-touch-btn, +.android-shell .sv-touch[data-render-mode="lite"] .sv-touch-stick-thumb { + will-change: auto; +} + +.android-shell .sv-touch[data-render-mode="lite"] .sv-touch-stick, +.android-shell .sv-touch[data-render-mode="lite"] .sv-touch-btn { + opacity: 0.94; + background: rgb(13, 17, 21); + border-color: rgba(255, 255, 255, 0.28); + color: rgba(255, 255, 255, 0.88); +} + +.android-shell .sv-touch[data-render-mode="lite"] .sv-touch-stick-thumb { + background: rgb(214, 222, 230); + border-color: rgba(255, 255, 255, 0.36); +} + +.android-shell .sv-touch[data-render-mode="lite"] .sv-touch-btn:active { + transform: none; + background: rgb(30, 42, 54); + border-color: rgba(255, 255, 255, 0.42); +} + .sv-touch-btn--shoulder, .sv-touch-btn--trigger, .sv-touch-btn--menu { diff --git a/opennow-stable/src/shared/gfn.ts b/opennow-stable/src/shared/gfn.ts index 6db3cc7a..7ddd57dd 100644 --- a/opennow-stable/src/shared/gfn.ts +++ b/opennow-stable/src/shared/gfn.ts @@ -738,6 +738,14 @@ export interface AppUpdaterState { isPackaged: boolean; } +export interface AndroidPerformanceInfo { + totalMemBytes?: number; + availMemBytes?: number; + thresholdBytes?: number; + lowMemory?: boolean; + liteTouchRecommended?: boolean; +} + export interface OpenNowApi { getAuthSession(input?: AuthSessionRequest): Promise; getLoginProviders(): Promise; @@ -781,6 +789,7 @@ export interface OpenNowApi { onNativeMouseMove(listener: (event: NativeMouseMoveEvent) => void): () => void; onNativeMouseButton(listener: (event: NativeMouseButtonEvent) => void): () => void; onNativeMouseWheel(listener: (event: NativeMouseWheelEvent) => void): () => void; + getAndroidPerformanceInfo?(): Promise; consumeLaunchIntent(): Promise; onLaunchIntent(listener: (event: AndroidLaunchIntent) => void): () => void; getSettings(): Promise; From 661e485454992aaaf9914fb69e370531e052be5e Mon Sep 17 00:00:00 2001 From: Kiefer Date: Sat, 9 May 2026 12:26:37 -0700 Subject: [PATCH 62/66] feat(android): update version code and enhance mouse input support - Incremented androidVersionCode from 30017 to 30018 in gradle.properties. - Added functionality to prefer mouse input for specific games on Android. - Updated App component to include logic for determining mouse input preference. - Modified StreamView and AndroidStreamMenu components to handle mouse input settings. - Introduced new types for native touch controls and gamepad events in the API. - Added baseline profiles for performance optimization in release builds. --- .../opennow/OpenNowAndroidPlugin.java | 465 ++++++++++++++++++ opennow-stable/android/gradle.properties | 2 +- opennow-stable/src/renderer/src/App.tsx | 31 ++ .../renderer/src/components/StreamView.tsx | 70 ++- .../src/renderer/src/platform/android/api.ts | 19 +- opennow-stable/src/shared/gfn.ts | 21 + 6 files changed, 598 insertions(+), 10 deletions(-) diff --git a/opennow-stable/android/app/src/main/java/com/opencloudgaming/opennow/OpenNowAndroidPlugin.java b/opennow-stable/android/app/src/main/java/com/opencloudgaming/opennow/OpenNowAndroidPlugin.java index e6076e63..b5e81083 100644 --- a/opennow-stable/android/app/src/main/java/com/opencloudgaming/opennow/OpenNowAndroidPlugin.java +++ b/opennow-stable/android/app/src/main/java/com/opencloudgaming/opennow/OpenNowAndroidPlugin.java @@ -5,7 +5,11 @@ import android.content.Context; import android.content.Intent; import android.content.pm.ActivityInfo; +import android.graphics.Canvas; import android.graphics.Color; +import android.graphics.Paint; +import android.graphics.RectF; +import android.graphics.Typeface; import android.net.Uri; import android.os.Build; import android.os.Bundle; @@ -14,9 +18,12 @@ import android.view.InputDevice; import android.view.MotionEvent; import android.view.View; +import android.view.ViewGroup; import android.view.Window; import android.view.WindowManager; +import android.widget.FrameLayout; +import java.util.ArrayList; import java.util.List; import androidx.core.view.WindowCompat; @@ -80,6 +87,7 @@ public class OpenNowAndroidPlugin extends Plugin { }; private View pointerCaptureView; + private NativeTouchControllerView nativeTouchControllerView; private JSObject pendingLaunchIntent; private int launchIntentSequence = 0; private boolean pointerCaptureRequested = false; @@ -177,6 +185,28 @@ public void getPerformanceInfo(PluginCall call) { call.resolve(payload); } + @PluginMethod + public void setNativeTouchControls(PluginCall call) { + boolean enabled = call.getBoolean("enabled", false); + Double sizeValue = call.getDouble("size", 1.0); + Double opacityValue = call.getDouble("opacity", 1.0); + String placement = call.getString("placement", "default"); + float size = clampFloat(sizeValue != null ? sizeValue.floatValue() : 1f, 0.72f, 1.35f); + float opacity = clampFloat(opacityValue != null ? opacityValue.floatValue() : 1f, 0.25f, 1f); + + getBridge().executeOnMainThread(() -> { + if (enabled) { + installNativeTouchController(size, opacity, placement); + } else { + removeNativeTouchController(); + } + + JSObject payload = new JSObject(); + payload.put("enabled", nativeTouchControllerView != null && nativeTouchControllerView.isAttachedToWindow()); + call.resolve(payload); + }); + } + @Override protected void handleOnNewIntent(Intent intent) { super.handleOnNewIntent(intent); @@ -189,6 +219,67 @@ protected void handleOnNewIntent(Intent intent) { notifyListeners("launchIntent", payload, true); } + private void installNativeTouchController(float size, float opacity, String placement) { + Activity activity = getActivity(); + if (activity == null) { + return; + } + + ViewGroup root = activity.findViewById(android.R.id.content); + if (root == null) { + return; + } + + if (nativeTouchControllerView == null) { + nativeTouchControllerView = new NativeTouchControllerView(activity, this::emitNativeTouchGamepadState); + FrameLayout.LayoutParams params = new FrameLayout.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.MATCH_PARENT + ); + root.addView(nativeTouchControllerView, params); + } + nativeTouchControllerView.configure(size, opacity, placement); + nativeTouchControllerView.bringToFront(); + } + + private void removeNativeTouchController() { + NativeTouchControllerView view = nativeTouchControllerView; + if (view == null) { + return; + } + + view.disconnect(); + ViewGroup parent = view.getParent() instanceof ViewGroup ? (ViewGroup) view.getParent() : null; + if (parent != null) { + parent.removeView(view); + } + nativeTouchControllerView = null; + } + + private void emitNativeTouchGamepadState( + boolean connected, + int buttons, + float leftTrigger, + float rightTrigger, + float leftStickX, + float leftStickY, + float rightStickX, + float rightStickY, + long timestampMs + ) { + JSObject payload = new JSObject(); + payload.put("connected", connected); + payload.put("buttons", buttons); + payload.put("leftTrigger", leftTrigger); + payload.put("rightTrigger", rightTrigger); + payload.put("leftStickX", leftStickX); + payload.put("leftStickY", leftStickY); + payload.put("rightStickX", rightStickX); + payload.put("rightStickY", rightStickY); + payload.put("timestampMs", timestampMs); + notifyListeners("nativeTouchGamepad", payload); + } + private void installPointerCaptureListener(View view) { if (view == null || Build.VERSION.SDK_INT < Build.VERSION_CODES.O) { return; @@ -279,6 +370,13 @@ private ActivityManager.MemoryInfo readMemoryInfo(Activity activity) { return memoryInfo; } + private static float clampFloat(float value, float min, float max) { + if (Float.isNaN(value) || Float.isInfinite(value)) { + return min; + } + return Math.max(min, Math.min(max, value)); + } + private boolean isSupportedPointerSource(int source) { if ((source & InputDevice.SOURCE_MOUSE) == InputDevice.SOURCE_MOUSE) { return true; @@ -456,6 +554,373 @@ private void applyImmersiveFullscreen(boolean enabled) { applyImmersiveFullscreen(activity, enabled); } + private interface NativeTouchStateListener { + void onState( + boolean connected, + int buttons, + float leftTrigger, + float rightTrigger, + float leftStickX, + float leftStickY, + float rightStickX, + float rightStickY, + long timestampMs + ); + } + + private static final class NativeTouchControllerView extends View { + private static final int GAMEPAD_DPAD_UP = 0x0001; + private static final int GAMEPAD_DPAD_DOWN = 0x0002; + private static final int GAMEPAD_DPAD_LEFT = 0x0004; + private static final int GAMEPAD_DPAD_RIGHT = 0x0008; + private static final int GAMEPAD_START = 0x0010; + private static final int GAMEPAD_BACK = 0x0020; + private static final int GAMEPAD_LB = 0x0100; + private static final int GAMEPAD_RB = 0x0200; + private static final int GAMEPAD_A = 0x1000; + private static final int GAMEPAD_B = 0x2000; + private static final int GAMEPAD_X = 0x4000; + private static final int GAMEPAD_Y = 0x8000; + private static final int KIND_BUTTON = 1; + private static final int KIND_LEFT_TRIGGER = 2; + private static final int KIND_RIGHT_TRIGGER = 3; + private static final int KIND_LEFT_STICK = 4; + private static final int KIND_RIGHT_STICK = 5; + private static final long MIN_EMIT_INTERVAL_MS = 33L; + + private final NativeTouchStateListener listener; + private final Paint fillPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + private final Paint strokePaint = new Paint(Paint.ANTI_ALIAS_FLAG); + private final Paint textPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + private final Paint thumbPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + private final List regions = new ArrayList<>(); + private final RectF leftStickRect = new RectF(); + private final RectF rightStickRect = new RectF(); + private float size = 1f; + private float opacity = 1f; + private String placement = "default"; + private int buttons = 0; + private float leftTrigger = 0f; + private float rightTrigger = 0f; + private float leftStickX = 0f; + private float leftStickY = 0f; + private float rightStickX = 0f; + private float rightStickY = 0f; + private int lastButtons = -1; + private float lastLeftTrigger = -1f; + private float lastRightTrigger = -1f; + private float lastLeftStickX = -2f; + private float lastLeftStickY = -2f; + private float lastRightStickX = -2f; + private float lastRightStickY = -2f; + private boolean connected = false; + private long lastEmitTimestampMs = 0L; + + NativeTouchControllerView(Context context, NativeTouchStateListener listener) { + super(context); + this.listener = listener; + setWillNotDraw(false); + setBackgroundColor(Color.TRANSPARENT); + setFocusable(false); + setClickable(false); + setLayerType(View.LAYER_TYPE_SOFTWARE, null); + + fillPaint.setStyle(Paint.Style.FILL); + strokePaint.setStyle(Paint.Style.STROKE); + strokePaint.setStrokeWidth(dp(1.5f)); + textPaint.setColor(Color.WHITE); + textPaint.setTextAlign(Paint.Align.CENTER); + textPaint.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.BOLD)); + thumbPaint.setStyle(Paint.Style.FILL); + } + + void configure(float size, float opacity, String placement) { + this.size = clampFloat(size, 0.72f, 1.35f); + this.opacity = clampFloat(opacity, 0.25f, 1f); + this.placement = placement != null ? placement : "default"; + layoutControls(getWidth(), getHeight()); + invalidate(); + } + + void disconnect() { + resetState(); + emitState(true, System.currentTimeMillis(), false); + } + + @Override + protected void onSizeChanged(int width, int height, int oldWidth, int oldHeight) { + super.onSizeChanged(width, height, oldWidth, oldHeight); + layoutControls(width, height); + } + + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + int alpha = Math.round(255f * Math.max(0.92f, opacity)); + fillPaint.setColor(Color.argb(alpha, 13, 17, 21)); + strokePaint.setColor(Color.argb(128, 255, 255, 255)); + thumbPaint.setColor(Color.argb(235, 214, 222, 230)); + textPaint.setTextSize(dp(13f) * size); + + for (TouchRegion region : regions) { + float radius = region.kind == KIND_LEFT_STICK || region.kind == KIND_RIGHT_STICK + ? region.rect.width() / 2f + : dp(10f) * size; + canvas.drawRoundRect(region.rect, radius, radius, fillPaint); + canvas.drawRoundRect(region.rect, radius, radius, strokePaint); + if (region.label != null) { + Paint.FontMetrics metrics = textPaint.getFontMetrics(); + float baseline = region.rect.centerY() - (metrics.ascent + metrics.descent) / 2f; + canvas.drawText(region.label, region.rect.centerX(), baseline, textPaint); + } + } + + drawStickThumb(canvas, leftStickRect, leftStickX, leftStickY); + drawStickThumb(canvas, rightStickRect, rightStickX, rightStickY); + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + if (event == null || regions.isEmpty()) { + return false; + } + + int action = event.getActionMasked(); + if (action == MotionEvent.ACTION_DOWN && hitTest(event.getX(), event.getY()) == null) { + return false; + } + + long timestampMs = event.getEventTime(); + if (action == MotionEvent.ACTION_CANCEL) { + resetState(); + emitState(true, timestampMs, false); + invalidate(); + return true; + } + + resetState(); + int actionIndex = event.getActionIndex(); + for (int i = 0; i < event.getPointerCount(); i++) { + if ((action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_POINTER_UP) && i == actionIndex) { + continue; + } + applyPointer(event.getX(i), event.getY(i)); + } + + boolean active = isActive(); + boolean wasConnected = connected; + connected = active || wasConnected; + boolean force = action == MotionEvent.ACTION_DOWN + || action == MotionEvent.ACTION_POINTER_DOWN + || action == MotionEvent.ACTION_UP + || action == MotionEvent.ACTION_POINTER_UP; + emitState(force, timestampMs, connected); + if (!active && (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_POINTER_UP)) { + connected = false; + } + invalidate(); + return true; + } + + private void layoutControls(int width, int height) { + regions.clear(); + if (width <= 0 || height <= 0) { + return; + } + + float margin = dp(24f) * size; + float bottom = height - dp("lower".equals(placement) ? 24f : 34f) * size; + float stick = dp("compact".equals(placement) ? 92f : 108f) * size; + float button = dp("compact".equals(placement) ? 48f : 56f) * size; + float gap = dp(10f) * size; + float shoulderWidth = dp(72f) * size; + float shoulderHeight = dp(42f) * size; + + leftStickRect.set(margin, bottom - stick, margin + stick, bottom); + rightStickRect.set(width - margin - stick, bottom - stick, width - margin, bottom); + regions.add(new TouchRegion(leftStickRect, KIND_LEFT_STICK, 0, null)); + regions.add(new TouchRegion(rightStickRect, KIND_RIGHT_STICK, 0, null)); + + float dpadLeft = leftStickRect.right + gap; + float dpadTop = leftStickRect.top + (stick - button * 2f - gap) / 2f; + addButton(dpadLeft + button + gap, dpadTop, button, button, GAMEPAD_DPAD_UP, "U"); + addButton(dpadLeft, dpadTop + button + gap, button, button, GAMEPAD_DPAD_LEFT, "L"); + addButton(dpadLeft + (button + gap) * 2f, dpadTop + button + gap, button, button, GAMEPAD_DPAD_RIGHT, "R"); + addButton(dpadLeft + button + gap, dpadTop + (button + gap) * 2f, button, button, GAMEPAD_DPAD_DOWN, "D"); + + float faceLeft = rightStickRect.left - gap - button * 3f - gap * 2f; + float faceTop = rightStickRect.top + (stick - button * 2f - gap) / 2f; + addButton(faceLeft + button + gap, faceTop, button, button, GAMEPAD_Y, "Y"); + addButton(faceLeft, faceTop + button + gap, button, button, GAMEPAD_X, "X"); + addButton(faceLeft + (button + gap) * 2f, faceTop + button + gap, button, button, GAMEPAD_B, "B"); + addButton(faceLeft + button + gap, faceTop + (button + gap) * 2f, button, button, GAMEPAD_A, "A"); + + float centerY = bottom - stick - dp(58f) * size; + float centerButtonWidth = dp(74f) * size; + float centerLeft = width / 2f - centerButtonWidth - gap / 2f; + addButton(centerLeft, centerY, centerButtonWidth, shoulderHeight, GAMEPAD_BACK, "View"); + addButton(centerLeft + centerButtonWidth + gap, centerY, centerButtonWidth, shoulderHeight, GAMEPAD_START, "Menu"); + + float shoulderTop = dp(18f) * size; + addButton(margin, shoulderTop, shoulderWidth, shoulderHeight, GAMEPAD_LB, "LB"); + addTrigger(margin + shoulderWidth + gap, shoulderTop, shoulderWidth, shoulderHeight, true, "LT"); + addTrigger(width - margin - shoulderWidth * 2f - gap, shoulderTop, shoulderWidth, shoulderHeight, false, "RT"); + addButton(width - margin - shoulderWidth, shoulderTop, shoulderWidth, shoulderHeight, GAMEPAD_RB, "RB"); + } + + private void addButton(float left, float top, float width, float height, int buttonMask, String label) { + regions.add(new TouchRegion(new RectF(left, top, left + width, top + height), KIND_BUTTON, buttonMask, label)); + } + + private void addTrigger(float left, float top, float width, float height, boolean leftTrigger, String label) { + regions.add(new TouchRegion( + new RectF(left, top, left + width, top + height), + leftTrigger ? KIND_LEFT_TRIGGER : KIND_RIGHT_TRIGGER, + 0, + label + )); + } + + private void drawStickThumb(Canvas canvas, RectF stickRect, float x, float y) { + if (stickRect.isEmpty()) { + return; + } + float radius = stickRect.width() * 0.16f; + float travel = stickRect.width() * 0.28f; + canvas.drawCircle(stickRect.centerX() + x * travel, stickRect.centerY() + y * travel, radius, thumbPaint); + } + + private void applyPointer(float x, float y) { + TouchRegion region = hitTest(x, y); + if (region == null) { + return; + } + + switch (region.kind) { + case KIND_BUTTON: + buttons |= region.buttonMask; + break; + case KIND_LEFT_TRIGGER: + leftTrigger = 1f; + break; + case KIND_RIGHT_TRIGGER: + rightTrigger = 1f; + break; + case KIND_LEFT_STICK: + float[] left = stickValue(region.rect, x, y); + leftStickX = left[0]; + leftStickY = left[1]; + break; + case KIND_RIGHT_STICK: + float[] right = stickValue(region.rect, x, y); + rightStickX = right[0]; + rightStickY = right[1]; + break; + default: + break; + } + } + + private TouchRegion hitTest(float x, float y) { + for (TouchRegion region : regions) { + if (region.rect.contains(x, y)) { + return region; + } + } + return null; + } + + private float[] stickValue(RectF rect, float x, float y) { + float rawX = (x - rect.centerX()) / Math.max(1f, rect.width() / 2f); + float rawY = (y - rect.centerY()) / Math.max(1f, rect.height() / 2f); + float magnitude = (float) Math.sqrt(rawX * rawX + rawY * rawY); + float scale = magnitude > 1f ? 1f / magnitude : 1f; + return new float[] { + quantize(rawX * scale), + quantize(rawY * scale) + }; + } + + private float quantize(float value) { + return Math.round(clampFloat(value, -1f, 1f) * 100f) / 100f; + } + + private void resetState() { + buttons = 0; + leftTrigger = 0f; + rightTrigger = 0f; + leftStickX = 0f; + leftStickY = 0f; + rightStickX = 0f; + rightStickY = 0f; + } + + private boolean isActive() { + return buttons != 0 + || leftTrigger > 0f + || rightTrigger > 0f + || leftStickX != 0f + || leftStickY != 0f + || rightStickX != 0f + || rightStickY != 0f; + } + + private void emitState(boolean force, long timestampMs, boolean connectedValue) { + boolean changed = force + || buttons != lastButtons + || leftTrigger != lastLeftTrigger + || rightTrigger != lastRightTrigger + || leftStickX != lastLeftStickX + || leftStickY != lastLeftStickY + || rightStickX != lastRightStickX + || rightStickY != lastRightStickY; + if (!changed) { + return; + } + if (!force && timestampMs - lastEmitTimestampMs < MIN_EMIT_INTERVAL_MS) { + return; + } + + lastEmitTimestampMs = timestampMs; + lastButtons = buttons; + lastLeftTrigger = leftTrigger; + lastRightTrigger = rightTrigger; + lastLeftStickX = leftStickX; + lastLeftStickY = leftStickY; + lastRightStickX = rightStickX; + lastRightStickY = rightStickY; + listener.onState( + connectedValue, + buttons, + leftTrigger, + rightTrigger, + leftStickX, + leftStickY, + rightStickX, + rightStickY, + timestampMs + ); + } + + private float dp(float value) { + return value * getResources().getDisplayMetrics().density; + } + + private static final class TouchRegion { + final RectF rect; + final int kind; + final int buttonMask; + final String label; + + TouchRegion(RectF rect, int kind, int buttonMask, String label) { + this.rect = new RectF(rect); + this.kind = kind; + this.buttonMask = buttonMask; + this.label = label; + } + } + } + public static boolean isImmersiveFullscreenRequested() { return immersiveFullscreenRequested; } diff --git a/opennow-stable/android/gradle.properties b/opennow-stable/android/gradle.properties index cc74bbe8..c415f2f3 100644 --- a/opennow-stable/android/gradle.properties +++ b/opennow-stable/android/gradle.properties @@ -20,4 +20,4 @@ org.gradle.jvmargs=-Xmx1536m # Android operating system, and which are packaged with your app's APK # https://developer.android.com/topic/libraries/support-library/androidx-rn android.useAndroidX=true -androidVersionCode=30017 \ No newline at end of file +androidVersionCode=30018 \ No newline at end of file diff --git a/opennow-stable/src/renderer/src/App.tsx b/opennow-stable/src/renderer/src/App.tsx index 4d375b0d..cd7e345d 100644 --- a/opennow-stable/src/renderer/src/App.tsx +++ b/opennow-stable/src/renderer/src/App.tsx @@ -133,6 +133,32 @@ function shouldUseLowPowerAndroidTouchControls( return typeof totalMemBytes === "number" && totalMemBytes > 0 && totalMemBytes < 3 * 1024 * 1024 * 1024; } +function androidGamePrefersMouseInput(game: GameInfo | null): boolean { + if (!platformCapabilities.isAndroid || !game) { + return false; + } + + if (/runescape|old school rune/i.test(game.title)) { + return true; + } + + const controls = game.variants.flatMap((variant) => variant.supportedControls ?? []); + if (controls.length === 0) { + return false; + } + const normalizedControls = controls.map((control) => control.toLowerCase()); + const hasMouseKeyboard = normalizedControls.some((control) => ( + control.includes("mouse") || + control.includes("keyboard") || + control.includes("kbm") + )); + const hasController = normalizedControls.some((control) => ( + control.includes("gamepad") || + control.includes("controller") + )); + return hasMouseKeyboard && !hasController; +} + function capAndroidCompatibilityResolution(resolution: string): string { const normalizedResolution = normalizeAndroidStreamResolution(resolution); const match = /^(\d+)x(\d+)$/.exec(normalizedResolution); @@ -1208,6 +1234,10 @@ export function App(): JSX.Element { () => shouldUseLowPowerAndroidTouchControls(androidStreamCompatibilityReason, androidPerformanceInfo), [androidPerformanceInfo, androidStreamCompatibilityReason], ); + const preferAndroidMouseInput = useMemo( + () => androidGamePrefersMouseInput(streamingGame), + [streamingGame], + ); const effectiveStreamPreferences = useMemo( () => getEffectiveStreamPreferences(settings, androidStreamCompatibilityReason), [androidStreamCompatibilityReason, settings], @@ -4015,6 +4045,7 @@ export function App(): JSX.Element { void updateSetting("androidTouchControls", value); }} lowPowerTouchControls={lowPowerAndroidTouchControls} + preferAndroidMouseInput={preferAndroidMouseInput} onSendText={(text) => clientRef.current?.sendText(text) ?? 0} onSendKeyPress={(key) => { clientRef.current?.sendKeyPress(key); diff --git a/opennow-stable/src/renderer/src/components/StreamView.tsx b/opennow-stable/src/renderer/src/components/StreamView.tsx index 9736676e..fc9e81e8 100644 --- a/opennow-stable/src/renderer/src/components/StreamView.tsx +++ b/opennow-stable/src/renderer/src/components/StreamView.tsx @@ -98,6 +98,7 @@ interface StreamViewProps { subscriptionInfo: SubscriptionInfo | null; micTrack?: MediaStreamTrack | null; lowPowerTouchControls?: boolean; + preferAndroidMouseInput?: boolean; className?: string; } @@ -1240,6 +1241,7 @@ function AndroidStreamMenu({ onSendText, onSendKeyPress, physicalGamepads, + preferMouseInput, revealSignal, onTouchControlsReveal, streamZoom, @@ -1257,6 +1259,7 @@ function AndroidStreamMenu({ onSendText?: (text: string) => number; onSendKeyPress?: (key: "Backspace" | "Enter" | "Escape") => void; physicalGamepads: number; + preferMouseInput: boolean; revealSignal?: number; onTouchControlsReveal?: () => void; streamZoom: number; @@ -1398,11 +1401,11 @@ function AndroidStreamMenu({
+
, + document.body, + ); +} diff --git a/opennow-stable/src/renderer/src/components/StreamView.tsx b/opennow-stable/src/renderer/src/components/StreamView.tsx index aa6f0767..8c5629b3 100644 --- a/opennow-stable/src/renderer/src/components/StreamView.tsx +++ b/opennow-stable/src/renderer/src/components/StreamView.tsx @@ -1806,12 +1806,12 @@ export function StreamView({ const [androidNativeTouchAvailable, setAndroidNativeTouchAvailable] = useState(true); const hasVirtualGamepadHandler = Boolean(onVirtualGamepadState); const androidTouchSurfaceAvailable = !isAndroidTvLikeSurface() && androidPhysicalGamepads === 0; + const androidMousePadEnabled = androidTouchSettings.mousePad || preferAndroidMouseInput; const shouldAttemptAndroidNativeTouchControls = platformCapabilities.isAndroid && lowPowerTouchControls && androidNativeTouchAvailable && androidTouchSurfaceAvailable && - !preferAndroidMouseInput && androidTouchSettings.enabled && hasVirtualGamepadHandler; const shouldRenderReactAndroidTouchControls = @@ -1819,7 +1819,6 @@ export function StreamView({ hasVirtualGamepadHandler && androidTouchSurfaceAvailable && androidTouchSettings.enabled && - !preferAndroidMouseInput && (!lowPowerTouchControls || !androidNativeTouchAvailable); const virtualGamepadStateRef = useRef(onVirtualGamepadState); virtualGamepadStateRef.current = onVirtualGamepadState; @@ -1840,6 +1839,7 @@ export function StreamView({ hasNativeTouchListener: Boolean(openNow.onAndroidNativeTouchGamepad), reactOverlayWillRender: shouldRenderReactAndroidTouchControls, nativeOverlayWillAttempt: shouldAttemptAndroidNativeTouchControls, + mousePadWillRender: androidMousePadEnabled, viewport: `${window.innerWidth}x${window.innerHeight}`, devicePixelRatio: window.devicePixelRatio, }); @@ -1848,6 +1848,7 @@ export function StreamView({ androidPhysicalGamepads, androidTouchSettings.enabled, androidTouchSurfaceAvailable, + androidMousePadEnabled, hasVirtualGamepadHandler, lowPowerTouchControls, preferAndroidMouseInput, @@ -1858,7 +1859,6 @@ export function StreamView({ if ( !platformCapabilities.isAndroid || !lowPowerTouchControls || - preferAndroidMouseInput || !androidTouchSurfaceAvailable || !androidTouchSettings.enabled || !virtualGamepadStateRef.current @@ -1936,10 +1936,8 @@ export function StreamView({ androidNativeTouchAvailable, androidTouchSurfaceAvailable, lowPowerTouchControls, - preferAndroidMouseInput, ]); const androidNativeMouseCapture = androidTouchSettings.mouseCapture && androidPhysicalGamepads === 0; - const androidMousePadEnabled = androidTouchSettings.mousePad || preferAndroidMouseInput; const [androidMenuRevealSignal, setAndroidMenuRevealSignal] = useState(0); const [androidTouchRevealSignal, setAndroidTouchRevealSignal] = useState(0); const mediaRecorderRef = useRef(null); diff --git a/opennow-stable/src/renderer/src/styles.css b/opennow-stable/src/renderer/src/styles.css index c6254176..f4409e4f 100644 --- a/opennow-stable/src/renderer/src/styles.css +++ b/opennow-stable/src/renderer/src/styles.css @@ -962,6 +962,229 @@ body[data-android-fullscreen="true"] .app-container { text-align: right; } +.launch-store-picker { + position: fixed; + inset: 0; + z-index: 3600; + display: flex; + align-items: center; + justify-content: center; + padding: 18px; +} + +.launch-store-picker-backdrop { + position: absolute; + inset: 0; + border: 0; + background: rgba(5, 7, 9, 0.72); + backdrop-filter: blur(8px); + cursor: pointer; +} + +.launch-store-picker-panel { + position: relative; + width: min(460px, calc(100vw - 36px)); + max-height: calc(100vh - 42px); + display: flex; + flex-direction: column; + overflow: hidden; + border: 1px solid rgba(255, 255, 255, 0.12); + border-radius: 12px; + background: + linear-gradient(180deg, rgba(27, 31, 34, 0.98), rgba(13, 16, 18, 0.98)); + box-shadow: 0 28px 80px rgba(0, 0, 0, 0.48); + animation: fade-in 130ms var(--ease); +} + +.launch-store-picker-head { + display: flex; + align-items: flex-start; + justify-content: space-between; + gap: 14px; + padding: 18px 18px 14px; + border-bottom: 1px solid rgba(255, 255, 255, 0.08); +} + +.launch-store-picker-title { + min-width: 0; +} + +.launch-store-picker-title span { + display: block; + margin-bottom: 4px; + font-size: 0.72rem; + font-weight: 800; + letter-spacing: 0.12em; + text-transform: uppercase; + color: var(--accent); +} + +.launch-store-picker-title h3 { + margin: 0; + color: #fff; + font-size: 1.04rem; + line-height: 1.22; + letter-spacing: 0; + overflow-wrap: anywhere; +} + +.launch-store-picker-close { + width: 32px; + height: 32px; + flex: 0 0 auto; + border: 1px solid transparent; + border-radius: 8px; + background: rgba(255, 255, 255, 0.04); + color: var(--ink-muted); + display: inline-flex; + align-items: center; + justify-content: center; + cursor: pointer; + transition: background var(--t-fast), color var(--t-fast), border-color var(--t-fast); +} + +.launch-store-picker-close:hover, +.launch-store-picker-close:focus-visible { + background: rgba(255, 255, 255, 0.08); + border-color: rgba(255, 255, 255, 0.12); + color: var(--ink); +} + +.launch-store-picker-options { + display: grid; + gap: 8px; + padding: 14px; + overflow: auto; +} + +.launch-store-option { + min-height: 60px; + display: grid; + grid-template-columns: 38px minmax(0, 1fr) 28px; + align-items: center; + gap: 12px; + padding: 10px 12px; + border: 1px solid rgba(255, 255, 255, 0.08); + border-radius: 10px; + background: rgba(255, 255, 255, 0.035); + color: var(--ink); + text-align: left; + cursor: pointer; + transition: background var(--t-fast), border-color var(--t-fast), transform var(--t-fast); +} + +.launch-store-option:hover, +.launch-store-option:focus-visible { + background: rgba(255, 255, 255, 0.07); + border-color: rgba(255, 255, 255, 0.16); + transform: translateY(-1px); +} + +.launch-store-option.is-selected { + background: color-mix(in srgb, var(--accent) 18%, rgba(255, 255, 255, 0.05)); + border-color: color-mix(in srgb, var(--accent) 70%, rgba(255, 255, 255, 0.16)); +} + +.launch-store-option-icon { + width: 38px; + height: 38px; + display: inline-flex; + align-items: center; + justify-content: center; + border-radius: 9px; + background: rgba(0, 0, 0, 0.22); + color: var(--ink-soft); +} + +.launch-store-option-icon .store-svg { + width: 18px; + height: 18px; +} + +.launch-store-option-copy { + min-width: 0; + display: flex; + flex-direction: column; + gap: 2px; +} + +.launch-store-option-copy strong { + color: #fff; + font-size: 0.92rem; + font-weight: 800; + letter-spacing: 0; +} + +.launch-store-option-copy span { + color: var(--ink-muted); + font-size: 0.75rem; + font-weight: 650; +} + +.launch-store-option-check { + width: 24px; + height: 24px; + display: inline-flex; + align-items: center; + justify-content: center; + border-radius: 999px; + color: var(--accent-on); + background: transparent; +} + +.launch-store-option.is-selected .launch-store-option-check { + background: var(--accent); +} + +.launch-store-picker-actions { + display: flex; + justify-content: flex-end; + gap: 10px; + padding: 14px; + border-top: 1px solid rgba(255, 255, 255, 0.08); +} + +.launch-store-picker-cancel, +.launch-store-picker-confirm { + height: 38px; + border-radius: 8px; + padding: 0 14px; + font: inherit; + font-size: 0.86rem; + font-weight: 800; + letter-spacing: 0; + cursor: pointer; + transition: background var(--t-fast), border-color var(--t-fast), transform var(--t-fast); +} + +.launch-store-picker-cancel { + border: 1px solid rgba(255, 255, 255, 0.1); + background: rgba(255, 255, 255, 0.04); + color: var(--ink-soft); +} + +.launch-store-picker-confirm { + border: 1px solid color-mix(in srgb, var(--accent) 76%, transparent); + background: var(--accent); + color: var(--accent-on); + display: inline-flex; + align-items: center; + justify-content: center; + gap: 8px; +} + +.launch-store-picker-cancel:hover, +.launch-store-picker-cancel:focus-visible { + background: rgba(255, 255, 255, 0.08); + border-color: rgba(255, 255, 255, 0.16); +} + +.launch-store-picker-confirm:hover, +.launch-store-picker-confirm:focus-visible { + background: var(--accent-press); + transform: translateY(-1px); +} + .navbar-meter { border: 1px solid var(--panel-border); border-radius: 9px; @@ -1148,6 +1371,45 @@ body[data-android-fullscreen="true"] .app-container { max-height: calc(100dvh - 96px); } +.android-shell .launch-store-picker { + padding: max(10px, env(safe-area-inset-top)) max(10px, env(safe-area-inset-right)) max(10px, env(safe-area-inset-bottom)) max(10px, env(safe-area-inset-left)); +} + +.android-shell .launch-store-picker-panel { + width: min(520px, calc(100vw - 20px)); + max-height: calc(100dvh - 20px); + border-radius: 10px; +} + +.android-shell .launch-store-picker-head { + padding: 14px 14px 10px; +} + +.android-shell .launch-store-picker-title h3 { + font-size: 0.96rem; +} + +.android-shell .launch-store-picker-options { + grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); + padding: 10px; +} + +.android-shell .launch-store-option { + min-height: 56px; + grid-template-columns: 34px minmax(0, 1fr) 24px; + gap: 10px; + border-radius: 9px; +} + +.android-shell .launch-store-option-icon { + width: 34px; + height: 34px; +} + +.android-shell .launch-store-picker-actions { + padding: 10px; +} + /* ====================================================== MAIN CONTENT — offset for fixed navbar